diff --git a/.gitignore b/.gitignore
index 68c48822e9d1a05e148af8643e88a13976dd0c30..ac58f3e6a637f100ab1bcde3663bb15e5630f79d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,6 +2,8 @@
 data
 owncloud
 config/config.php
+config/mount.php
+apps/inc.php
 
 # just sane ignores
 .*.sw[po]
diff --git a/.htaccess b/.htaccess
index 11520d743dc1b6842db59ab9d986f50cbef25b15..adc6667d5bf64ce0e4f282dc9c53da2a7b187255 100644
--- a/.htaccess
+++ b/.htaccess
@@ -1,5 +1,9 @@
 ErrorDocument 403 /core/templates/403.php
 ErrorDocument 404 /core/templates/404.php
+Redirect 301 /apps/calendar/caldav.php /remote/caldav.php
+Redirect 301 /apps/contacts/carddav.php /remote/carddav.php
+Redirect 301 /apps/files/webdav.php /remote/webdav.php
+Redirect 301 /files/webdav.php /remote/webdav.php
 <IfModule mod_php5.c>
 php_value upload_max_filesize 512M
 php_value post_max_size 512M
@@ -10,6 +14,10 @@ php_value memory_limit 512M
 </IfModule>
 <IfModule mod_rewrite.c>
 RewriteEngine on
-RewriteRule .* - [env=HTTP_AUTHORIZATION:%{HTTP:Authorization},last]
+RewriteRule .* - [env=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
+RewriteRule ^.well-known/carddav /remote/carddav.php [R]
+RewriteRule ^.well-known/caldav /remote/caldav.php [R]
+
+RewriteRule ^apps/([^/]*)/(.*\.(css|php))$ index.php?app=$1&getfile=$2 [QSA,L]
 </IfModule>
 Options -Indexes
diff --git a/3rdparty/Sabre.includes.php b/3rdparty/Sabre.includes.php
index d41b287b77db5ea8f1ad7b4be78ab68046a803d5..c1334373663c646b05bba88d38d322fac8910039 100644
--- a/3rdparty/Sabre.includes.php
+++ b/3rdparty/Sabre.includes.php
@@ -3,125 +3,24 @@
 /**
  * Library include file
  *
+ * This file is deprecated, don't use it!
+ * Instead, use the specific includes files that are in the sub-packages.
+ *
+ *   Sabre/DAV/includes.php
+ *   Sabre/HTTP/includes.php
+ *
+ *   etc..
+ *
  * This file contains all includes to the rest of the SabreDAV library
- * Make sure the lib/ directory is in PHP's include_path
+ * Make sure the lib/ directory is in PHP's include_path.
  *
  * @package Sabre
- * @subpackage DAV
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
+ * @deprecated Don't use this file, it will be remove in a future version
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
  * @author Evert Pot (http://www.rooftopsolutions.nl/) 
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
  */
 
-/* Utilities */
-include 'Sabre/HTTP/Util.php';
-include 'Sabre/HTTP/Response.php';
-include 'Sabre/HTTP/Request.php';
-include 'Sabre/HTTP/AbstractAuth.php';
-include 'Sabre/HTTP/BasicAuth.php';
-include 'Sabre/HTTP/DigestAuth.php';
-include 'Sabre/HTTP/AWSAuth.php';
-
-/* Version */
-include 'Sabre/DAV/Version.php';
-include 'Sabre/HTTP/Version.php';
-
-/* Exceptions */
-include 'Sabre/DAV/Exception.php';
-include 'Sabre/DAV/Exception/BadRequest.php';
-include 'Sabre/DAV/Exception/Conflict.php';
-include 'Sabre/DAV/Exception/FileNotFound.php';
-include 'Sabre/DAV/Exception/InsufficientStorage.php';
-include 'Sabre/DAV/Exception/Locked.php';
-include 'Sabre/DAV/Exception/LockTokenMatchesRequestUri.php';
-include 'Sabre/DAV/Exception/MethodNotAllowed.php';
-include 'Sabre/DAV/Exception/NotImplemented.php';
-include 'Sabre/DAV/Exception/Forbidden.php';
-include 'Sabre/DAV/Exception/PreconditionFailed.php';
-include 'Sabre/DAV/Exception/RequestedRangeNotSatisfiable.php';
-include 'Sabre/DAV/Exception/UnsupportedMediaType.php';
-include 'Sabre/DAV/Exception/NotAuthenticated.php';
-
-include 'Sabre/DAV/Exception/ConflictingLock.php';
-include 'Sabre/DAV/Exception/ReportNotImplemented.php';
-include 'Sabre/DAV/Exception/InvalidResourceType.php';
-
-/* Properties */
-include 'Sabre/DAV/Property.php';
-include 'Sabre/DAV/Property/GetLastModified.php';
-include 'Sabre/DAV/Property/ResourceType.php';
-include 'Sabre/DAV/Property/SupportedLock.php';
-include 'Sabre/DAV/Property/LockDiscovery.php';
-include 'Sabre/DAV/Property/IHref.php';
-include 'Sabre/DAV/Property/Href.php';
-include 'Sabre/DAV/Property/HrefList.php';
-include 'Sabre/DAV/Property/SupportedReportSet.php';
-include 'Sabre/DAV/Property/Response.php';
-include 'Sabre/DAV/Property/ResponseList.php';
-
-/* Node interfaces */
-include 'Sabre/DAV/INode.php';
-include 'Sabre/DAV/IFile.php';
-include 'Sabre/DAV/ICollection.php';
-include 'Sabre/DAV/IProperties.php';
-include 'Sabre/DAV/ILockable.php';
-include 'Sabre/DAV/IQuota.php';
-include 'Sabre/DAV/IExtendedCollection.php';
-
-/* Node abstract implementations */
-include 'Sabre/DAV/Node.php';
-include 'Sabre/DAV/File.php';
-include 'Sabre/DAV/Collection.php';
-include 'Sabre/DAV/Directory.php';
-
-/* Utilities */
-include 'Sabre/DAV/SimpleCollection.php';
-include 'Sabre/DAV/SimpleDirectory.php';
-include 'Sabre/DAV/XMLUtil.php';
-include 'Sabre/DAV/URLUtil.php';
-
-/* Filesystem implementation */
-include 'Sabre/DAV/FS/Node.php';
-include 'Sabre/DAV/FS/File.php';
-include 'Sabre/DAV/FS/Directory.php';
-
-/* Advanced filesystem implementation */
-include 'Sabre/DAV/FSExt/Node.php';
-include 'Sabre/DAV/FSExt/File.php';
-include 'Sabre/DAV/FSExt/Directory.php';
-
-/* Trees */
-include 'Sabre/DAV/Tree.php';
-include 'Sabre/DAV/ObjectTree.php';
-include 'Sabre/DAV/Tree/Filesystem.php';
-
-/* Server */
-include 'Sabre/DAV/Server.php';
-include 'Sabre/DAV/ServerPlugin.php';
-
-/* Browser */
-include 'Sabre/DAV/Browser/Plugin.php';
-include 'Sabre/DAV/Browser/MapGetToPropFind.php';
-include 'Sabre/DAV/Browser/GuessContentType.php';
-
-/* Locks */
-include 'Sabre/DAV/Locks/LockInfo.php';
-include 'Sabre/DAV/Locks/Plugin.php';
-include 'Sabre/DAV/Locks/Backend/Abstract.php';
-include 'Sabre/DAV/Locks/Backend/FS.php';
-include 'Sabre/DAV/Locks/Backend/PDO.php';
-
-/* Temporary File Filter plugin */
-include 'Sabre/DAV/TemporaryFileFilterPlugin.php';
-
-/* Authentication plugin */
-include 'Sabre/DAV/Auth/Plugin.php';
-include 'Sabre/DAV/Auth/IBackend.php';
-include 'Sabre/DAV/Auth/Backend/AbstractDigest.php';
-include 'Sabre/DAV/Auth/Backend/AbstractBasic.php';
-include 'Sabre/DAV/Auth/Backend/File.php';
-include 'Sabre/DAV/Auth/Backend/PDO.php';
-
-/* DavMount plugin */
-include 'Sabre/DAV/Mount/Plugin.php';
+include 'Sabre/HTTP/includes.php';
+include 'Sabre/DAV/includes.php';
 
diff --git a/3rdparty/Sabre/CalDAV/Backend/Abstract.php b/3rdparty/Sabre/CalDAV/Backend/Abstract.php
index b694eef49e4696aa470cf56bc126c2bd1b273378..7aba1d69ffe3052f344110c70c2f2139ddebadbf 100644
--- a/3rdparty/Sabre/CalDAV/Backend/Abstract.php
+++ b/3rdparty/Sabre/CalDAV/Backend/Abstract.php
@@ -2,10 +2,10 @@
 
 /**
  * Abstract Calendaring backend. Extend this class to create your own backends.
- * 
+ *
  * @package Sabre
  * @subpackage CalDAV
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
  * @author Evert Pot (http://www.rooftopsolutions.nl/) 
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
  */
@@ -17,16 +17,16 @@ abstract class Sabre_CalDAV_Backend_Abstract {
      * Every project is an array with the following keys:
      *  * id, a unique id that will be used by other functions to modify the
      *    calendar. This can be the same as the uri or a database key.
-     *  * uri, which the basename of the uri with which the calendar is 
+     *  * uri, which the basename of the uri with which the calendar is
      *    accessed.
-     *  * principalUri. The owner of the calendar. Almost always the same as
+     *  * principaluri. The owner of the calendar. Almost always the same as
      *    principalUri passed to this method.
      *
      * Furthermore it can contain webdav properties in clark notation. A very
-     * common one is '{DAV:}displayname'. 
+     * common one is '{DAV:}displayname'.
      *
-     * @param string $principalUri 
-     * @return array 
+     * @param string $principalUri
+     * @return array
      */
     abstract function getCalendarsForUser($principalUri);
 
@@ -39,9 +39,9 @@ abstract class Sabre_CalDAV_Backend_Abstract {
      * @param string $principalUri
      * @param string $calendarUri
      * @param array $properties
-     * @return void 
+     * @return void
      */
-    abstract function createCalendar($principalUri,$calendarUri,array $properties); 
+    abstract function createCalendar($principalUri,$calendarUri,array $properties);
 
     /**
      * Updates properties for a calendar.
@@ -56,7 +56,7 @@ abstract class Sabre_CalDAV_Backend_Abstract {
      * If the operation was successful, true can be returned.
      * If the operation failed, false can be returned.
      *
-     * Deletion of a non-existant property is always succesful.
+     * Deletion of a non-existent property is always successful.
      *
      * Lastly, it is optional to return detailed information about any
      * failures. In this case an array should be returned with the following
@@ -71,24 +71,24 @@ abstract class Sabre_CalDAV_Backend_Abstract {
      *   )
      * )
      *
-     * In this example it was forbidden to update {DAV:}displayname. 
+     * In this example it was forbidden to update {DAV:}displayname.
      * (403 Forbidden), which in turn also caused {DAV:}owner to fail
      * (424 Failed Dependency) because the request needs to be atomic.
      *
      * @param string $calendarId
      * @param array $mutations
-     * @return bool|array 
+     * @return bool|array
      */
     public function updateCalendar($calendarId, array $mutations) {
-        
-        return false; 
+
+        return false;
 
     }
 
     /**
-     * Delete a calendar and all it's objects 
-     * 
-     * @param string $calendarId 
+     * Delete a calendar and all it's objects
+     *
+     * @param string $calendarId
      * @return void
      */
     abstract function deleteCalendar($calendarId);
@@ -98,22 +98,27 @@ abstract class Sabre_CalDAV_Backend_Abstract {
      *
      * Every item contains an array with the following keys:
      *   * id - unique identifier which will be used for subsequent updates
-     *   * calendardata - The iCalendar-compatible calnedar data
+     *   * calendardata - The iCalendar-compatible calendar data
      *   * uri - a unique key which will be used to construct the uri. This can be any arbitrary string.
      *   * lastmodified - a timestamp of the last modification time
-     *   * etag - An arbitrary string, surrounded by double-quotes. (e.g.: 
+     *   * etag - An arbitrary string, surrounded by double-quotes. (e.g.:
      *   '  "abcdef"')
      *   * calendarid - The calendarid as it was passed to this function.
+     *   * size - The size of the calendar objects, in bytes.
      *
-     * Note that the etag is optional, but it's highly encouraged to return for 
+     * Note that the etag is optional, but it's highly encouraged to return for
      * speed reasons.
      *
-     * The calendardata is also optional. If it's not returned 
-     * 'getCalendarObject' will be called later, which *is* expected to return 
+     * The calendardata is also optional. If it's not returned
+     * 'getCalendarObject' will be called later, which *is* expected to return
      * calendardata.
-     * 
-     * @param string $calendarId 
-     * @return array 
+     *
+     * If neither etag or size are specified, the calendardata will be
+     * used/fetched to determine these numbers. If both are specified the
+     * amount of times this is needed is reduced by a great degree.
+     *
+     * @param string $calendarId
+     * @return array
      */
     abstract function getCalendarObjects($calendarId);
 
@@ -121,41 +126,41 @@ abstract class Sabre_CalDAV_Backend_Abstract {
      * Returns information from a single calendar object, based on it's object
      * uri.
      *
-     * The returned array must have the same keys as getCalendarObjects. The 
-     * 'calendardata' object is required here though, while it's not required 
+     * The returned array must have the same keys as getCalendarObjects. The
+     * 'calendardata' object is required here though, while it's not required
      * for getCalendarObjects.
-     * 
-     * @param string $calendarId 
-     * @param string $objectUri 
-     * @return array 
+     *
+     * @param string $calendarId
+     * @param string $objectUri
+     * @return array
      */
     abstract function getCalendarObject($calendarId,$objectUri);
 
     /**
-     * Creates a new calendar object. 
-     * 
-     * @param string $calendarId 
-     * @param string $objectUri 
-     * @param string $calendarData 
+     * Creates a new calendar object.
+     *
+     * @param string $calendarId
+     * @param string $objectUri
+     * @param string $calendarData
      * @return void
      */
     abstract function createCalendarObject($calendarId,$objectUri,$calendarData);
 
     /**
-     * Updates an existing calendarobject, based on it's uri. 
-     * 
-     * @param string $calendarId 
-     * @param string $objectUri 
-     * @param string $calendarData 
+     * Updates an existing calendarobject, based on it's uri.
+     *
+     * @param string $calendarId
+     * @param string $objectUri
+     * @param string $calendarData
      * @return void
      */
     abstract function updateCalendarObject($calendarId,$objectUri,$calendarData);
 
     /**
-     * Deletes an existing calendar object. 
-     * 
-     * @param string $calendarId 
-     * @param string $objectUri 
+     * Deletes an existing calendar object.
+     *
+     * @param string $calendarId
+     * @param string $objectUri
      * @return void
      */
     abstract function deleteCalendarObject($calendarId,$objectUri);
diff --git a/3rdparty/Sabre/CalDAV/Backend/PDO.php b/3rdparty/Sabre/CalDAV/Backend/PDO.php
index 7b1b33b912ee53a4fd4a94febccbcb6b4c871141..ddacf940c74fa12e21ff389e06604325c55bf3ba 100644
--- a/3rdparty/Sabre/CalDAV/Backend/PDO.php
+++ b/3rdparty/Sabre/CalDAV/Backend/PDO.php
@@ -3,35 +3,35 @@
 /**
  * PDO CalDAV backend
  *
- * This backend is used to store calendar-data in a PDO database, such as 
+ * This backend is used to store calendar-data in a PDO database, such as
  * sqlite or MySQL
- * 
+ *
  * @package Sabre
  * @subpackage CalDAV
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
  * @author Evert Pot (http://www.rooftopsolutions.nl/) 
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
  */
 class Sabre_CalDAV_Backend_PDO extends Sabre_CalDAV_Backend_Abstract {
 
     /**
-     * pdo 
-     * 
+     * pdo
+     *
      * @var PDO
      */
     protected $pdo;
 
     /**
-     * The table name that will be used for calendars 
-     * 
-     * @var string 
+     * The table name that will be used for calendars
+     *
+     * @var string
      */
     protected $calendarTableName;
 
     /**
-     * The table name that will be used for calendar objects  
-     * 
-     * @var string 
+     * The table name that will be used for calendar objects
+     *
+     * @var string
      */
     protected $calendarObjectTableName;
 
@@ -39,7 +39,7 @@ class Sabre_CalDAV_Backend_PDO extends Sabre_CalDAV_Backend_Abstract {
      * List of CalDAV properties, and how they map to database fieldnames
      *
      * Add your own properties by simply adding on to this array
-     * 
+     *
      * @var array
      */
     public $propertyMap = array(
@@ -51,9 +51,11 @@ class Sabre_CalDAV_Backend_PDO extends Sabre_CalDAV_Backend_Abstract {
     );
 
     /**
-     * Creates the backend 
-     * 
-     * @param PDO $pdo 
+     * Creates the backend
+     *
+     * @param PDO $pdo
+     * @param string $calendarTableName
+     * @param string $calendarObjectTableName
      */
     public function __construct(PDO $pdo, $calendarTableName = 'calendars', $calendarObjectTableName = 'calendarobjects') {
 
@@ -69,16 +71,16 @@ class Sabre_CalDAV_Backend_PDO extends Sabre_CalDAV_Backend_Abstract {
      * Every project is an array with the following keys:
      *  * id, a unique id that will be used by other functions to modify the
      *    calendar. This can be the same as the uri or a database key.
-     *  * uri, which the basename of the uri with which the calendar is 
+     *  * uri, which the basename of the uri with which the calendar is
      *    accessed.
-     *  * principalUri. The owner of the calendar. Almost always the same as
+     *  * principaluri. The owner of the calendar. Almost always the same as
      *    principalUri passed to this method.
      *
      * Furthermore it can contain webdav properties in clark notation. A very
-     * common one is '{DAV:}displayname'. 
+     * common one is '{DAV:}displayname'.
      *
-     * @param string $principalUri 
-     * @return array 
+     * @param string $principalUri
+     * @return array
      */
     public function getCalendarsForUser($principalUri) {
 
@@ -89,15 +91,18 @@ class Sabre_CalDAV_Backend_PDO extends Sabre_CalDAV_Backend_Abstract {
         $fields[] = 'components';
         $fields[] = 'principaluri';
 
-        // Making fields a comma-delimited list 
+        // Making fields a comma-delimited list
         $fields = implode(', ', $fields);
-        $stmt = $this->pdo->prepare("SELECT " . $fields . " FROM `".$this->calendarTableName."` WHERE principaluri = ?"); 
+        $stmt = $this->pdo->prepare("SELECT " . $fields . " FROM ".$this->calendarTableName." WHERE principaluri = ? ORDER BY calendarorder ASC");
         $stmt->execute(array($principalUri));
 
         $calendars = array();
         while($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
 
-            $components = explode(',',$row['components']);
+            $components = array();
+            if ($row['components']) {
+                $components = explode(',',$row['components']);
+            }
 
             $calendar = array(
                 'id' => $row['id'],
@@ -106,7 +111,7 @@ class Sabre_CalDAV_Backend_PDO extends Sabre_CalDAV_Backend_Abstract {
                 '{' . Sabre_CalDAV_Plugin::NS_CALENDARSERVER . '}getctag' => $row['ctag']?$row['ctag']:'0',
                 '{' . Sabre_CalDAV_Plugin::NS_CALDAV . '}supported-calendar-component-set' => new Sabre_CalDAV_Property_SupportedCalendarComponentSet($components),
             );
-        
+
 
             foreach($this->propertyMap as $xmlName=>$dbName) {
                 $calendar[$xmlName] = $row[$dbName];
@@ -129,8 +134,9 @@ class Sabre_CalDAV_Backend_PDO extends Sabre_CalDAV_Backend_Abstract {
      * @param string $principalUri
      * @param string $calendarUri
      * @param array $properties
+     * @return string
      */
-    public function createCalendar($principalUri,$calendarUri, array $properties) {
+    public function createCalendar($principalUri, $calendarUri, array $properties) {
 
         $fieldNames = array(
             'principaluri',
@@ -158,13 +164,12 @@ class Sabre_CalDAV_Backend_PDO extends Sabre_CalDAV_Backend_Abstract {
         foreach($this->propertyMap as $xmlName=>$dbName) {
             if (isset($properties[$xmlName])) {
 
-                $myValue = $properties[$xmlName];
                 $values[':' . $dbName] = $properties[$xmlName];
                 $fieldNames[] = $dbName;
             }
         }
 
-        $stmt = $this->pdo->prepare("INSERT INTO `".$this->calendarTableName."` (".implode(', ', $fieldNames).") VALUES (".implode(', ',array_keys($values)).")");
+        $stmt = $this->pdo->prepare("INSERT INTO ".$this->calendarTableName." (".implode(', ', $fieldNames).") VALUES (".implode(', ',array_keys($values)).")");
         $stmt->execute($values);
 
         return $this->pdo->lastInsertId();
@@ -184,7 +189,7 @@ class Sabre_CalDAV_Backend_PDO extends Sabre_CalDAV_Backend_Abstract {
      * If the operation was successful, true can be returned.
      * If the operation failed, false can be returned.
      *
-     * Deletion of a non-existant property is always succesful.
+     * Deletion of a non-existent property is always successful.
      *
      * Lastly, it is optional to return detailed information about any
      * failures. In this case an array should be returned with the following
@@ -199,13 +204,13 @@ class Sabre_CalDAV_Backend_PDO extends Sabre_CalDAV_Backend_Abstract {
      *   )
      * )
      *
-     * In this example it was forbidden to update {DAV:}displayname. 
+     * In this example it was forbidden to update {DAV:}displayname.
      * (403 Forbidden), which in turn also caused {DAV:}owner to fail
      * (424 Failed Dependency) because the request needs to be atomic.
      *
      * @param string $calendarId
-     * @param array $mutations 
-     * @return bool|array 
+     * @param array $mutations
+     * @return bool|array
      */
     public function updateCalendar($calendarId, array $mutations) {
 
@@ -220,7 +225,7 @@ class Sabre_CalDAV_Backend_PDO extends Sabre_CalDAV_Backend_Abstract {
 
         foreach($mutations as $propertyName=>$propertyValue) {
 
-            // We don't know about this property. 
+            // We don't know about this property.
             if (!isset($this->propertyMap[$propertyName])) {
                 $hasError = true;
                 $result[403][$propertyName] = null;
@@ -230,7 +235,7 @@ class Sabre_CalDAV_Backend_PDO extends Sabre_CalDAV_Backend_Abstract {
 
             $fieldName = $this->propertyMap[$propertyName];
             $newValues[$fieldName] = $propertyValue;
-                
+
         }
 
         // If there were any errors we need to fail the request
@@ -258,55 +263,60 @@ class Sabre_CalDAV_Backend_PDO extends Sabre_CalDAV_Backend_Abstract {
         }
         $valuesSql[] = 'ctag = ctag + 1';
 
-        $stmt = $this->pdo->prepare("UPDATE `" . $this->calendarTableName . "` SET " . implode(', ',$valuesSql) . " WHERE id = ?");
-        $newValues['id'] = $calendarId; 
+        $stmt = $this->pdo->prepare("UPDATE " . $this->calendarTableName . " SET " . implode(', ',$valuesSql) . " WHERE id = ?");
+        $newValues['id'] = $calendarId;
         $stmt->execute(array_values($newValues));
 
-        return true; 
+        return true;
 
     }
 
     /**
-     * Delete a calendar and all it's objects 
-     * 
-     * @param string $calendarId 
+     * Delete a calendar and all it's objects
+     *
+     * @param string $calendarId
      * @return void
      */
     public function deleteCalendar($calendarId) {
 
-        $stmt = $this->pdo->prepare('DELETE FROM `'.$this->calendarObjectTableName.'` WHERE calendarid = ?');
+        $stmt = $this->pdo->prepare('DELETE FROM '.$this->calendarObjectTableName.' WHERE calendarid = ?');
         $stmt->execute(array($calendarId));
 
-        $stmt = $this->pdo->prepare('DELETE FROM `'.$this->calendarTableName.'` WHERE id = ?');
+        $stmt = $this->pdo->prepare('DELETE FROM '.$this->calendarTableName.' WHERE id = ?');
         $stmt->execute(array($calendarId));
 
     }
 
     /**
-     * Returns all calendar objects within a calendar. 
+     * Returns all calendar objects within a calendar.
      *
      * Every item contains an array with the following keys:
      *   * id - unique identifier which will be used for subsequent updates
-     *   * calendardata - The iCalendar-compatible calnedar data
+     *   * calendardata - The iCalendar-compatible calendar data
      *   * uri - a unique key which will be used to construct the uri. This can be any arbitrary string.
      *   * lastmodified - a timestamp of the last modification time
-     *   * etag - An arbitrary string, surrounded by double-quotes. (e.g.: 
+     *   * etag - An arbitrary string, surrounded by double-quotes. (e.g.:
      *   '  "abcdef"')
      *   * calendarid - The calendarid as it was passed to this function.
+     *   * size - The size of the calendar objects, in bytes.
      *
-     * Note that the etag is optional, but it's highly encouraged to return for 
+     * Note that the etag is optional, but it's highly encouraged to return for
      * speed reasons.
      *
-     * The calendardata is also optional. If it's not returned 
-     * 'getCalendarObject' will be called later, which *is* expected to return 
+     * The calendardata is also optional. If it's not returned
+     * 'getCalendarObject' will be called later, which *is* expected to return
      * calendardata.
-     * 
-     * @param string $calendarId 
-     * @return array 
+     *
+     * If neither etag or size are specified, the calendardata will be
+     * used/fetched to determine these numbers. If both are specified the
+     * amount of times this is needed is reduced by a great degree.
+     *
+     * @param string $calendarId
+     * @return array
      */
     public function getCalendarObjects($calendarId) {
 
-        $stmt = $this->pdo->prepare('SELECT * FROM `'.$this->calendarObjectTableName.'` WHERE calendarid = ?');
+        $stmt = $this->pdo->prepare('SELECT * FROM '.$this->calendarObjectTableName.' WHERE calendarid = ?');
         $stmt->execute(array($calendarId));
         return $stmt->fetchAll();
 
@@ -316,68 +326,68 @@ class Sabre_CalDAV_Backend_PDO extends Sabre_CalDAV_Backend_Abstract {
      * Returns information from a single calendar object, based on it's object
      * uri.
      *
-     * The returned array must have the same keys as getCalendarObjects. The 
-     * 'calendardata' object is required here though, while it's not required 
+     * The returned array must have the same keys as getCalendarObjects. The
+     * 'calendardata' object is required here though, while it's not required
      * for getCalendarObjects.
-     * 
-     * @param string $calendarId 
-     * @param string $objectUri 
-     * @return array 
+     *
+     * @param string $calendarId
+     * @param string $objectUri
+     * @return array
      */
     public function getCalendarObject($calendarId,$objectUri) {
 
-        $stmt = $this->pdo->prepare('SELECT * FROM `'.$this->calendarObjectTableName.'` WHERE calendarid = ? AND uri = ?');
+        $stmt = $this->pdo->prepare('SELECT * FROM '.$this->calendarObjectTableName.' WHERE calendarid = ? AND uri = ?');
         $stmt->execute(array($calendarId, $objectUri));
         return $stmt->fetch();
 
     }
 
     /**
-     * Creates a new calendar object. 
-     * 
-     * @param string $calendarId 
-     * @param string $objectUri 
-     * @param string $calendarData 
+     * Creates a new calendar object.
+     *
+     * @param string $calendarId
+     * @param string $objectUri
+     * @param string $calendarData
      * @return void
      */
     public function createCalendarObject($calendarId,$objectUri,$calendarData) {
 
-        $stmt = $this->pdo->prepare('INSERT INTO `'.$this->calendarObjectTableName.'` (calendarid, uri, calendardata, lastmodified) VALUES (?,?,?,?)');
+        $stmt = $this->pdo->prepare('INSERT INTO '.$this->calendarObjectTableName.' (calendarid, uri, calendardata, lastmodified) VALUES (?,?,?,?)');
         $stmt->execute(array($calendarId,$objectUri,$calendarData,time()));
-        $stmt = $this->pdo->prepare('UPDATE `'.$this->calendarTableName.'` SET ctag = ctag + 1 WHERE id = ?');
+        $stmt = $this->pdo->prepare('UPDATE '.$this->calendarTableName.' SET ctag = ctag + 1 WHERE id = ?');
         $stmt->execute(array($calendarId));
 
     }
 
     /**
-     * Updates an existing calendarobject, based on it's uri. 
-     * 
-     * @param string $calendarId 
-     * @param string $objectUri 
-     * @param string $calendarData 
+     * Updates an existing calendarobject, based on it's uri.
+     *
+     * @param string $calendarId
+     * @param string $objectUri
+     * @param string $calendarData
      * @return void
      */
     public function updateCalendarObject($calendarId,$objectUri,$calendarData) {
 
-        $stmt = $this->pdo->prepare('UPDATE `'.$this->calendarObjectTableName.'` SET calendardata = ?, lastmodified = ? WHERE calendarid = ? AND uri = ?');
+        $stmt = $this->pdo->prepare('UPDATE '.$this->calendarObjectTableName.' SET calendardata = ?, lastmodified = ? WHERE calendarid = ? AND uri = ?');
         $stmt->execute(array($calendarData,time(),$calendarId,$objectUri));
-        $stmt = $this->pdo->prepare('UPDATE `'.$this->calendarTableName.'` SET ctag = ctag + 1 WHERE id = ?');
+        $stmt = $this->pdo->prepare('UPDATE '.$this->calendarTableName.' SET ctag = ctag + 1 WHERE id = ?');
         $stmt->execute(array($calendarId));
 
     }
 
     /**
-     * Deletes an existing calendar object. 
-     * 
-     * @param string $calendarId 
-     * @param string $objectUri 
+     * Deletes an existing calendar object.
+     *
+     * @param string $calendarId
+     * @param string $objectUri
      * @return void
      */
     public function deleteCalendarObject($calendarId,$objectUri) {
 
-        $stmt = $this->pdo->prepare('DELETE FROM `'.$this->calendarObjectTableName.'` WHERE calendarid = ? AND uri = ?');
+        $stmt = $this->pdo->prepare('DELETE FROM '.$this->calendarObjectTableName.' WHERE calendarid = ? AND uri = ?');
         $stmt->execute(array($calendarId,$objectUri));
-        $stmt = $this->pdo->prepare('UPDATE `'. $this->calendarTableName .'` SET ctag = ctag + 1 WHERE id = ?');
+        $stmt = $this->pdo->prepare('UPDATE '. $this->calendarTableName .' SET ctag = ctag + 1 WHERE id = ?');
         $stmt->execute(array($calendarId));
 
     }
diff --git a/3rdparty/Sabre/CalDAV/Calendar.php b/3rdparty/Sabre/CalDAV/Calendar.php
index 0d2b3875771729f323e8f19cc86a2376eb77b6d6..623df2dd1b8951cb9d6730f9b6849265dcf1f159 100644
--- a/3rdparty/Sabre/CalDAV/Calendar.php
+++ b/3rdparty/Sabre/CalDAV/Calendar.php
@@ -5,42 +5,42 @@
  *
  * A calendar can contain multiple TODO and or Events. These are represented
  * as Sabre_CalDAV_CalendarObject objects.
- * 
+ *
  * @package Sabre
  * @subpackage CalDAV
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
  * @author Evert Pot (http://www.rooftopsolutions.nl/) 
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
  */
 class Sabre_CalDAV_Calendar implements Sabre_CalDAV_ICalendar, Sabre_DAV_IProperties, Sabre_DAVACL_IACL {
 
     /**
-     * This is an array with calendar information 
-     * 
-     * @var array 
+     * This is an array with calendar information
+     *
+     * @var array
      */
     protected $calendarInfo;
 
     /**
-     * CalDAV backend 
-     * 
-     * @var Sabre_CalDAV_Backend_Abstract 
+     * CalDAV backend
+     *
+     * @var Sabre_CalDAV_Backend_Abstract
      */
     protected $caldavBackend;
 
     /**
      * Principal backend
-     * 
+     *
      * @var Sabre_DAVACL_IPrincipalBackend
      */
     protected $principalBackend;
 
     /**
-     * Constructor 
-     * 
-     * @param Sabre_CalDAV_Backend_Abstract $caldavBackend 
-     * @param array $calendarInfo 
-     * @return void
+     * Constructor
+     *
+     * @param Sabre_DAVACL_IPrincipalBackend $principalBackend
+     * @param Sabre_CalDAV_Backend_Abstract $caldavBackend
+     * @param array $calendarInfo
      */
     public function __construct(Sabre_DAVACL_IPrincipalBackend $principalBackend, Sabre_CalDAV_Backend_Abstract $caldavBackend, $calendarInfo) {
 
@@ -52,9 +52,9 @@ class Sabre_CalDAV_Calendar implements Sabre_CalDAV_ICalendar, Sabre_DAV_IProper
     }
 
     /**
-     * Returns the name of the calendar 
-     * 
-     * @return string 
+     * Returns the name of the calendar
+     *
+     * @return string
      */
     public function getName() {
 
@@ -63,10 +63,10 @@ class Sabre_CalDAV_Calendar implements Sabre_CalDAV_ICalendar, Sabre_DAV_IProper
     }
 
     /**
-     * Updates properties such as the display name and description 
-     * 
-     * @param array $mutations 
-     * @return array 
+     * Updates properties such as the display name and description
+     *
+     * @param array $mutations
+     * @return array
      */
     public function updateProperties($mutations) {
 
@@ -75,10 +75,10 @@ class Sabre_CalDAV_Calendar implements Sabre_CalDAV_ICalendar, Sabre_DAV_IProper
     }
 
     /**
-     * Returns the list of properties 
-     * 
-     * @param array $properties 
-     * @return array 
+     * Returns the list of properties
+     *
+     * @param array $requestedProperties
+     * @return array
      */
     public function getProperties($requestedProperties) {
 
@@ -86,16 +86,16 @@ class Sabre_CalDAV_Calendar implements Sabre_CalDAV_ICalendar, Sabre_DAV_IProper
 
         foreach($requestedProperties as $prop) switch($prop) {
 
-            case '{urn:ietf:params:xml:ns:caldav}supported-calendar-data' : 
-                $response[$prop] = new Sabre_CalDAV_Property_SupportedCalendarData(); 
+            case '{urn:ietf:params:xml:ns:caldav}supported-calendar-data' :
+                $response[$prop] = new Sabre_CalDAV_Property_SupportedCalendarData();
                 break;
-            case '{urn:ietf:params:xml:ns:caldav}supported-collation-set' : 
-                $response[$prop] =  new Sabre_CalDAV_Property_SupportedCollationSet(); 
+            case '{urn:ietf:params:xml:ns:caldav}supported-collation-set' :
+                $response[$prop] =  new Sabre_CalDAV_Property_SupportedCollationSet();
                 break;
             case '{DAV:}owner' :
                 $response[$prop] = new Sabre_DAVACL_Property_Principal(Sabre_DAVACL_Property_Principal::HREF,$this->calendarInfo['principaluri']);
                 break;
-            default : 
+            default :
                 if (isset($this->calendarInfo[$prop])) $response[$prop] = $this->calendarInfo[$prop];
                 break;
 
@@ -108,22 +108,22 @@ class Sabre_CalDAV_Calendar implements Sabre_CalDAV_ICalendar, Sabre_DAV_IProper
      * Returns a calendar object
      *
      * The contained calendar objects are for example Events or Todo's.
-     * 
-     * @param string $name 
-     * @return Sabre_DAV_ICalendarObject 
+     *
+     * @param string $name
+     * @return Sabre_DAV_ICalendarObject
      */
     public function getChild($name) {
 
         $obj = $this->caldavBackend->getCalendarObject($this->calendarInfo['id'],$name);
-        if (!$obj) throw new Sabre_DAV_Exception_FileNotFound('Calendar object not found');
+        if (!$obj) throw new Sabre_DAV_Exception_NotFound('Calendar object not found');
         return new Sabre_CalDAV_CalendarObject($this->caldavBackend,$this->calendarInfo,$obj);
 
     }
 
     /**
-     * Returns the full list of calendar objects  
-     * 
-     * @return array 
+     * Returns the full list of calendar objects
+     *
+     * @return array
      */
     public function getChildren() {
 
@@ -137,17 +137,17 @@ class Sabre_CalDAV_Calendar implements Sabre_CalDAV_ICalendar, Sabre_DAV_IProper
     }
 
     /**
-     * Checks if a child-node exists. 
-     * 
-     * @param string $name 
-     * @return bool 
+     * Checks if a child-node exists.
+     *
+     * @param string $name
+     * @return bool
      */
     public function childExists($name) {
 
         $obj = $this->caldavBackend->getCalendarObject($this->calendarInfo['id'],$name);
-        if (!$obj) 
+        if (!$obj)
             return false;
-        else 
+        else
             return true;
 
     }
@@ -156,8 +156,8 @@ class Sabre_CalDAV_Calendar implements Sabre_CalDAV_ICalendar, Sabre_DAV_IProper
      * Creates a new directory
      *
      * We actually block this, as subdirectories are not allowed in calendars.
-     * 
-     * @param string $name 
+     *
+     * @param string $name
      * @return void
      */
     public function createDirectory($name) {
@@ -170,32 +170,23 @@ class Sabre_CalDAV_Calendar implements Sabre_CalDAV_ICalendar, Sabre_DAV_IProper
      * Creates a new file
      *
      * The contents of the new file must be a valid ICalendar string.
-     * 
-     * @param string $name 
-     * @param resource $calendarData 
-     * @return void
+     *
+     * @param string $name
+     * @param resource $calendarData
+     * @return string|null
      */
     public function createFile($name,$calendarData = null) {
 
-        $calendarData = stream_get_contents($calendarData);
-        // Converting to UTF-8, if needed
-        $calendarData = Sabre_DAV_StringUtil::ensureUTF8($calendarData);
-
-        $supportedComponents = $this->calendarInfo['{' . Sabre_CalDAV_Plugin::NS_CALDAV . '}supported-calendar-component-set'];
-        if ($supportedComponents) {
-            $supportedComponents = $supportedComponents->getValue();
-        } else {
-            $supportedComponents = null;
+        if (is_resource($calendarData)) {
+            $calendarData = stream_get_contents($calendarData);
         }
-        Sabre_CalDAV_ICalendarUtil::validateICalendarObject($calendarData, $supportedComponents);
-
-        $this->caldavBackend->createCalendarObject($this->calendarInfo['id'],$name,$calendarData);
+        return $this->caldavBackend->createCalendarObject($this->calendarInfo['id'],$name,$calendarData);
 
     }
 
     /**
-     * Deletes the calendar. 
-     * 
+     * Deletes the calendar.
+     *
      * @return void
      */
     public function delete() {
@@ -205,10 +196,10 @@ class Sabre_CalDAV_Calendar implements Sabre_CalDAV_ICalendar, Sabre_DAV_IProper
     }
 
     /**
-     * Renames the calendar. Note that most calendars use the 
-     * {DAV:}displayname to display a name to display a name. 
-     * 
-     * @param string $newName 
+     * Renames the calendar. Note that most calendars use the
+     * {DAV:}displayname to display a name to display a name.
+     *
+     * @param string $newName
      * @return void
      */
     public function setName($newName) {
@@ -219,7 +210,7 @@ class Sabre_CalDAV_Calendar implements Sabre_CalDAV_ICalendar, Sabre_DAV_IProper
 
     /**
      * Returns the last modification date as a unix timestamp.
-     * 
+     *
      * @return void
      */
     public function getLastModified() {
@@ -231,8 +222,8 @@ class Sabre_CalDAV_Calendar implements Sabre_CalDAV_ICalendar, Sabre_DAV_IProper
     /**
      * Returns the owner principal
      *
-     * This must be a url to a principal, or null if there's no owner 
-     * 
+     * This must be a url to a principal, or null if there's no owner
+     *
      * @return string|null
      */
     public function getOwner() {
@@ -245,8 +236,8 @@ class Sabre_CalDAV_Calendar implements Sabre_CalDAV_ICalendar, Sabre_DAV_IProper
      * Returns a group principal
      *
      * This must be a url to a principal, or null if there's no owner
-     * 
-     * @return string|null 
+     *
+     * @return string|null
      */
     public function getGroup() {
 
@@ -258,13 +249,13 @@ class Sabre_CalDAV_Calendar implements Sabre_CalDAV_ICalendar, Sabre_DAV_IProper
      * Returns a list of ACE's for this node.
      *
      * Each ACE has the following properties:
-     *   * 'privilege', a string such as {DAV:}read or {DAV:}write. These are 
+     *   * 'privilege', a string such as {DAV:}read or {DAV:}write. These are
      *     currently the only supported privileges
      *   * 'principal', a url to the principal who owns the node
-     *   * 'protected' (optional), indicating that this ACE is not allowed to 
-     *      be updated. 
-     * 
-     * @return array 
+     *   * 'protected' (optional), indicating that this ACE is not allowed to
+     *      be updated.
+     *
+     * @return array
      */
     public function getACL() {
 
@@ -294,6 +285,11 @@ class Sabre_CalDAV_Calendar implements Sabre_CalDAV_ICalendar, Sabre_DAV_IProper
                 'principal' => $this->calendarInfo['principaluri'] . '/calendar-proxy-read',
                 'protected' => true,
             ),
+            array(
+                'privilege' => '{' . Sabre_CalDAV_Plugin::NS_CALDAV . '}read-free-busy',
+                'principal' => '{DAV:}authenticated',
+                'protected' => true,
+            ),
 
         );
 
@@ -302,9 +298,9 @@ class Sabre_CalDAV_Calendar implements Sabre_CalDAV_ICalendar, Sabre_DAV_IProper
     /**
      * Updates the ACL
      *
-     * This method will receive a list of new ACE's. 
-     * 
-     * @param array $acl 
+     * This method will receive a list of new ACE's.
+     *
+     * @param array $acl
      * @return void
      */
     public function setACL(array $acl) {
@@ -313,6 +309,35 @@ class Sabre_CalDAV_Calendar implements Sabre_CalDAV_ICalendar, Sabre_DAV_IProper
 
     }
 
+    /**
+     * Returns the list of supported privileges for this node.
+     *
+     * The returned data structure is a list of nested privileges.
+     * See Sabre_DAVACL_Plugin::getDefaultSupportedPrivilegeSet for a simple
+     * standard structure.
+     *
+     * If null is returned from this method, the default privilege set is used,
+     * which is fine for most common usecases.
+     *
+     * @return array|null
+     */
+    public function getSupportedPrivilegeSet() {
+
+        $default = Sabre_DAVACL_Plugin::getDefaultSupportedPrivilegeSet();
+
+        // We need to inject 'read-free-busy' in the tree, aggregated under
+        // {DAV:}read.
+        foreach($default['aggregates'] as &$agg) {
 
+            if ($agg['privilege'] !== '{DAV:}read') continue;
+
+            $agg['aggregates'][] = array(
+                'privilege' => '{' . Sabre_CalDAV_Plugin::NS_CALDAV . '}read-free-busy',
+            );
+
+        }
+        return $default;
+
+    }
 
 }
diff --git a/3rdparty/Sabre/CalDAV/CalendarObject.php b/3rdparty/Sabre/CalDAV/CalendarObject.php
index 0c99f18deb72cca5233bd50ffdce28bd3037fc86..72f0a578d16a554b847354867c608ca732b8f72e 100644
--- a/3rdparty/Sabre/CalDAV/CalendarObject.php
+++ b/3rdparty/Sabre/CalDAV/CalendarObject.php
@@ -1,43 +1,43 @@
 <?php
 
 /**
- * The CalendarObject represents a single VEVENT or VTODO within a Calendar. 
- * 
+ * The CalendarObject represents a single VEVENT or VTODO within a Calendar.
+ *
  * @package Sabre
  * @subpackage CalDAV
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
  * @author Evert Pot (http://www.rooftopsolutions.nl/) 
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
  */
 class Sabre_CalDAV_CalendarObject extends Sabre_DAV_File implements Sabre_CalDAV_ICalendarObject, Sabre_DAVACL_IACL {
 
     /**
-     * Sabre_CalDAV_Backend_Abstract 
-     * 
-     * @var array 
+     * Sabre_CalDAV_Backend_Abstract
+     *
+     * @var array
      */
     protected $caldavBackend;
 
     /**
-     * Array with information about this CalendarObject 
-     * 
-     * @var array 
+     * Array with information about this CalendarObject
+     *
+     * @var array
      */
     protected $objectData;
 
     /**
      * Array with information about the containing calendar
-     * 
-     * @var array 
+     *
+     * @var array
      */
     protected $calendarInfo;
 
     /**
-     * Constructor 
-     * 
+     * Constructor
+     *
      * @param Sabre_CalDAV_Backend_Abstract $caldavBackend
      * @param array $calendarInfo
-     * @param array $objectData 
+     * @param array $objectData
      */
     public function __construct(Sabre_CalDAV_Backend_Abstract $caldavBackend,array $calendarInfo,array $objectData) {
 
@@ -56,9 +56,9 @@ class Sabre_CalDAV_CalendarObject extends Sabre_DAV_File implements Sabre_CalDAV
     }
 
     /**
-     * Returns the uri for this object 
-     * 
-     * @return string 
+     * Returns the uri for this object
+     *
+     * @return string
      */
     public function getName() {
 
@@ -67,9 +67,9 @@ class Sabre_CalDAV_CalendarObject extends Sabre_DAV_File implements Sabre_CalDAV
     }
 
     /**
-     * Returns the ICalendar-formatted object 
-     * 
-     * @return string 
+     * Returns the ICalendar-formatted object
+     *
+     * @return string
      */
     public function get() {
 
@@ -83,35 +83,27 @@ class Sabre_CalDAV_CalendarObject extends Sabre_DAV_File implements Sabre_CalDAV
     }
 
     /**
-     * Updates the ICalendar-formatted object 
-     * 
-     * @param string $calendarData 
-     * @return void 
+     * Updates the ICalendar-formatted object
+     *
+     * @param string $calendarData
+     * @return void
      */
     public function put($calendarData) {
 
-        if (is_resource($calendarData))
+        if (is_resource($calendarData)) {
             $calendarData = stream_get_contents($calendarData);
-
-        // Converting to UTF-8, if needed
-        $calendarData = Sabre_DAV_StringUtil::ensureUTF8($calendarData);
-
-        $supportedComponents = $this->calendarInfo['{' . Sabre_CalDAV_Plugin::NS_CALDAV . '}supported-calendar-component-set'];
-        if ($supportedComponents) {
-            $supportedComponents = $supportedComponents->getValue();
-        } else {
-            $supportedComponents = null;
         }
-        Sabre_CalDAV_ICalendarUtil::validateICalendarObject($calendarData, $supportedComponents);
-
-        $this->caldavBackend->updateCalendarObject($this->calendarInfo['id'],$this->objectData['uri'],$calendarData);
+        $etag = $this->caldavBackend->updateCalendarObject($this->calendarInfo['id'],$this->objectData['uri'],$calendarData);
         $this->objectData['calendardata'] = $calendarData;
+        $this->objectData['etag'] = $etag;
+
+        return $etag;
 
     }
 
     /**
-     * Deletes the calendar object 
-     * 
+     * Deletes the calendar object
+     *
      * @return void
      */
     public function delete() {
@@ -121,9 +113,9 @@ class Sabre_CalDAV_CalendarObject extends Sabre_DAV_File implements Sabre_CalDAV
     }
 
     /**
-     * Returns the mime content-type 
-     * 
-     * @return string 
+     * Returns the mime content-type
+     *
+     * @return string
      */
     public function getContentType() {
 
@@ -134,9 +126,9 @@ class Sabre_CalDAV_CalendarObject extends Sabre_DAV_File implements Sabre_CalDAV
     /**
      * Returns an ETag for this object.
      *
-     * The ETag is an arbritrary string, but MUST be surrounded by double-quotes.
-     * 
-     * @return string 
+     * The ETag is an arbitrary string, but MUST be surrounded by double-quotes.
+     *
+     * @return string
      */
     public function getETag() {
 
@@ -150,8 +142,8 @@ class Sabre_CalDAV_CalendarObject extends Sabre_DAV_File implements Sabre_CalDAV
 
     /**
      * Returns the last modification date as a unix timestamp
-     * 
-     * @return time 
+     *
+     * @return time
      */
     public function getLastModified() {
 
@@ -160,21 +152,25 @@ class Sabre_CalDAV_CalendarObject extends Sabre_DAV_File implements Sabre_CalDAV
     }
 
     /**
-     * Returns the size of this object in bytes 
-     * 
+     * Returns the size of this object in bytes
+     *
      * @return int
      */
     public function getSize() {
 
-        return strlen($this->objectData['calendardata']);
+        if (array_key_exists('size',$this->objectData)) {
+            return $this->objectData['size'];
+        } else {
+            return strlen($this->get());
+        }
 
     }
 
     /**
      * Returns the owner principal
      *
-     * This must be a url to a principal, or null if there's no owner 
-     * 
+     * This must be a url to a principal, or null if there's no owner
+     *
      * @return string|null
      */
     public function getOwner() {
@@ -187,8 +183,8 @@ class Sabre_CalDAV_CalendarObject extends Sabre_DAV_File implements Sabre_CalDAV
      * Returns a group principal
      *
      * This must be a url to a principal, or null if there's no owner
-     * 
-     * @return string|null 
+     *
+     * @return string|null
      */
     public function getGroup() {
 
@@ -200,13 +196,13 @@ class Sabre_CalDAV_CalendarObject extends Sabre_DAV_File implements Sabre_CalDAV
      * Returns a list of ACE's for this node.
      *
      * Each ACE has the following properties:
-     *   * 'privilege', a string such as {DAV:}read or {DAV:}write. These are 
+     *   * 'privilege', a string such as {DAV:}read or {DAV:}write. These are
      *     currently the only supported privileges
      *   * 'principal', a url to the principal who owns the node
-     *   * 'protected' (optional), indicating that this ACE is not allowed to 
-     *      be updated. 
-     * 
-     * @return array 
+     *   * 'protected' (optional), indicating that this ACE is not allowed to
+     *      be updated.
+     *
+     * @return array
      */
     public function getACL() {
 
@@ -244,9 +240,9 @@ class Sabre_CalDAV_CalendarObject extends Sabre_DAV_File implements Sabre_CalDAV
     /**
      * Updates the ACL
      *
-     * This method will receive a list of new ACE's. 
-     * 
-     * @param array $acl 
+     * This method will receive a list of new ACE's.
+     *
+     * @param array $acl
      * @return void
      */
     public function setACL(array $acl) {
@@ -255,6 +251,23 @@ class Sabre_CalDAV_CalendarObject extends Sabre_DAV_File implements Sabre_CalDAV
 
     }
 
+    /**
+     * Returns the list of supported privileges for this node.
+     *
+     * The returned data structure is a list of nested privileges.
+     * See Sabre_DAVACL_Plugin::getDefaultSupportedPrivilegeSet for a simple
+     * standard structure.
+     *
+     * If null is returned from this method, the default privilege set is used,
+     * which is fine for most common usecases.
+     *
+     * @return array|null
+     */
+    public function getSupportedPrivilegeSet() {
+
+        return null;
+
+    }
 
 }
 
diff --git a/3rdparty/Sabre/CalDAV/CalendarQueryParser.php b/3rdparty/Sabre/CalDAV/CalendarQueryParser.php
new file mode 100644
index 0000000000000000000000000000000000000000..bd0d343382f8b684b396e6addcc445e1dbbbaae1
--- /dev/null
+++ b/3rdparty/Sabre/CalDAV/CalendarQueryParser.php
@@ -0,0 +1,296 @@
+<?php
+
+/**
+ * Parses the calendar-query report request body.
+ *
+ * Whoever designed this format, and the CalDAV equivalent even more so,
+ * has no feel for design.
+ *
+ * @package Sabre
+ * @subpackage CalDAV
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
+ * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
+ */
+class Sabre_CalDAV_CalendarQueryParser {
+
+    /**
+     * List of requested properties the client wanted
+     *
+     * @var array
+     */
+    public $requestedProperties;
+
+    /**
+     * List of property/component filters.
+     *
+     * @var array
+     */
+    public $filters;
+
+    /**
+     * This property will contain null if CALDAV:expand was not specified, 
+     * otherwise it will contain an array with 2 elements (start, end). Each 
+     * contain a DateTime object.
+     *
+     * If expand is specified, recurring calendar objects are to be expanded 
+     * into their individual components, and only the components that fall 
+     * within the specified time-range are to be returned.
+     *
+     * For more details, see rfc4791, section 9.6.5.
+     * 
+     * @var null|array 
+     */
+    public $expand;
+
+    /**
+     * DOM Document
+     *
+     * @var DOMDocument
+     */
+    protected $dom;
+
+    /**
+     * DOM XPath object
+     *
+     * @var DOMXPath
+     */
+    protected $xpath;
+
+    /**
+     * Creates the parser
+     *
+     * @param DOMDocument $dom
+     */
+    public function __construct(DOMDocument $dom) {
+
+        $this->dom = $dom;
+
+        $this->xpath = new DOMXPath($dom);
+        $this->xpath->registerNameSpace('cal',Sabre_CalDAV_Plugin::NS_CALDAV);
+        $this->xpath->registerNameSpace('dav','urn:DAV');
+
+    }
+
+    /**
+     * Parses the request.
+     *
+     * @return void
+     */
+    public function parse() {
+
+        $filterNode = null;
+
+        $filter = $this->xpath->query('/cal:calendar-query/cal:filter');
+        if ($filter->length !== 1) {
+            throw new Sabre_DAV_Exception_BadRequest('Only one filter element is allowed');
+        }
+
+        $compFilters = $this->parseCompFilters($filter->item(0));
+        if (count($compFilters)!==1) {
+            throw new Sabre_DAV_Exception_BadRequest('There must be exactly 1 top-level comp-filter.');
+        }
+
+        $this->filters = $compFilters[0];
+        $this->requestedProperties = array_keys(Sabre_DAV_XMLUtil::parseProperties($this->dom->firstChild));
+
+        $expand = $this->xpath->query('/cal:calendar-query/dav:prop/cal:calendar-data/cal:expand');
+        if ($expand->length>0) {
+            $this->expand = $this->parseExpand($expand->item(0));
+        }
+             
+
+    }
+
+    /**
+     * Parses all the 'comp-filter' elements from a node
+     *
+     * @param DOMElement $parentNode
+     * @return array
+     */
+    protected function parseCompFilters(DOMElement $parentNode) {
+
+        $compFilterNodes = $this->xpath->query('cal:comp-filter', $parentNode);
+        $result = array();
+
+        for($ii=0; $ii < $compFilterNodes->length; $ii++) {
+
+            $compFilterNode = $compFilterNodes->item($ii);
+
+            $compFilter = array();
+            $compFilter['name'] = $compFilterNode->getAttribute('name');
+            $compFilter['is-not-defined'] = $this->xpath->query('cal:is-not-defined', $compFilterNode)->length>0;
+            $compFilter['comp-filters'] = $this->parseCompFilters($compFilterNode);
+            $compFilter['prop-filters'] = $this->parsePropFilters($compFilterNode);
+            $compFilter['time-range'] = $this->parseTimeRange($compFilterNode);
+
+            if ($compFilter['time-range'] && !in_array($compFilter['name'],array(
+                'VEVENT',
+                'VTODO',
+                'VJOURNAL',
+                'VFREEBUSY',
+                'VALARM',
+            ))) {
+                throw new Sabre_DAV_Exception_BadRequest('The time-range filter is not defined for the ' . $compFilter['name'] . ' component');
+            };
+
+            $result[] = $compFilter;
+
+        }
+
+        return $result;
+
+    }
+
+    /**
+     * Parses all the prop-filter elements from a node
+     *
+     * @param DOMElement $parentNode
+     * @return array
+     */
+    protected function parsePropFilters(DOMElement $parentNode) {
+
+        $propFilterNodes = $this->xpath->query('cal:prop-filter', $parentNode);
+        $result = array();
+
+        for ($ii=0; $ii < $propFilterNodes->length; $ii++) {
+
+            $propFilterNode = $propFilterNodes->item($ii);
+            $propFilter = array();
+            $propFilter['name'] = $propFilterNode->getAttribute('name');
+            $propFilter['is-not-defined'] = $this->xpath->query('cal:is-not-defined', $propFilterNode)->length>0;
+            $propFilter['param-filters'] = $this->parseParamFilters($propFilterNode);
+            $propFilter['text-match'] = $this->parseTextMatch($propFilterNode);
+            $propFilter['time-range'] = $this->parseTimeRange($propFilterNode);
+
+            $result[] = $propFilter;
+
+        }
+
+        return $result;
+
+    }
+
+    /**
+     * Parses the param-filter element
+     *
+     * @param DOMElement $parentNode
+     * @return array
+     */
+    protected function parseParamFilters(DOMElement $parentNode) {
+
+        $paramFilterNodes = $this->xpath->query('cal:param-filter', $parentNode);
+        $result = array();
+
+        for($ii=0;$ii<$paramFilterNodes->length;$ii++) {
+
+            $paramFilterNode = $paramFilterNodes->item($ii);
+            $paramFilter = array();
+            $paramFilter['name'] = $paramFilterNode->getAttribute('name');
+            $paramFilter['is-not-defined'] = $this->xpath->query('cal:is-not-defined', $paramFilterNode)->length>0;
+            $paramFilter['text-match'] = $this->parseTextMatch($paramFilterNode);
+
+            $result[] = $paramFilter;
+
+        }
+
+        return $result;
+
+    }
+
+    /**
+     * Parses the text-match element
+     *
+     * @param DOMElement $parentNode
+     * @return array|null
+     */
+    protected function parseTextMatch(DOMElement $parentNode) {
+
+        $textMatchNodes = $this->xpath->query('cal:text-match', $parentNode);
+
+        if ($textMatchNodes->length === 0)
+            return null;
+
+        $textMatchNode = $textMatchNodes->item(0);
+        $negateCondition = $textMatchNode->getAttribute('negate-condition');
+        $negateCondition = $negateCondition==='yes';
+        $collation = $textMatchNode->getAttribute('collation');
+        if (!$collation) $collation = 'i;ascii-casemap';
+
+        return array(
+            'negate-condition' => $negateCondition,
+            'collation' => $collation,
+            'value' => $textMatchNode->nodeValue
+        );
+
+    }
+
+    /**
+     * Parses the time-range element
+     *
+     * @param DOMElement $parentNode
+     * @return array|null
+     */
+    protected function parseTimeRange(DOMElement $parentNode) {
+
+        $timeRangeNodes = $this->xpath->query('cal:time-range', $parentNode);
+        if ($timeRangeNodes->length === 0) {
+            return null;
+        }
+
+        $timeRangeNode = $timeRangeNodes->item(0);
+
+        if ($start = $timeRangeNode->getAttribute('start')) {
+            $start = Sabre_VObject_DateTimeParser::parseDateTime($start);
+        } else {
+            $start = null;
+        }
+        if ($end = $timeRangeNode->getAttribute('end')) {
+            $end = Sabre_VObject_DateTimeParser::parseDateTime($end);
+        } else {
+            $end = null;
+        }
+
+        if (!is_null($start) && !is_null($end) && $end <= $start) {
+            throw new Sabre_DAV_Exception_BadRequest('The end-date must be larger than the start-date in the time-range filter');
+        }
+
+        return array(
+            'start' => $start,
+            'end' => $end,
+        );
+
+    }
+
+    /**
+     * Parses the CALDAV:expand element
+     * 
+     * @param DOMElement $parentNode 
+     * @return void
+     */
+    protected function parseExpand(DOMElement $parentNode) {
+
+        $start = $parentNode->getAttribute('start');
+        if(!$start) {
+            throw new Sabre_DAV_Exception_BadRequest('The "start" attribute is required for the CALDAV:expand element');
+        } 
+        $start = Sabre_VObject_DateTimeParser::parseDateTime($start);
+
+        $end = $parentNode->getAttribute('end');
+        if(!$end) {
+            throw new Sabre_DAV_Exception_BadRequest('The "end" attribute is required for the CALDAV:expand element');
+        } 
+        $end = Sabre_VObject_DateTimeParser::parseDateTime($end);
+        
+        if ($end <= $start) {
+            throw new Sabre_DAV_Exception_BadRequest('The end-date must be larger than the start-date in the expand element.');
+        }
+
+        return array(
+            'start' => $start,
+            'end' => $end,
+        );
+
+    }
+
+}
diff --git a/3rdparty/Sabre/CalDAV/CalendarQueryValidator.php b/3rdparty/Sabre/CalDAV/CalendarQueryValidator.php
new file mode 100644
index 0000000000000000000000000000000000000000..1bb6b5d53faf4f6848d2675c701554558d525269
--- /dev/null
+++ b/3rdparty/Sabre/CalDAV/CalendarQueryValidator.php
@@ -0,0 +1,347 @@
+<?php
+
+/**
+ * CalendarQuery Validator
+ *
+ * This class is responsible for checking if an iCalendar object matches a set
+ * of filters. The main function to do this is 'validate'.
+ *
+ * This is used to determine which icalendar objects should be returned for a
+ * calendar-query REPORT request.
+ *
+ * @package Sabre
+ * @subpackage CalDAV
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
+ * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
+ */
+class Sabre_CalDAV_CalendarQueryValidator {
+
+    /**
+     * Verify if a list of filters applies to the calendar data object
+     *
+     * The list of filters must be formatted as parsed by Sabre_CalDAV_CalendarQueryParser
+     *
+     * @param Sabre_VObject_Component $vObject
+     * @param array $filters
+     * @return bool
+     */
+    public function validate(Sabre_VObject_Component $vObject,array $filters) {
+
+        // The top level object is always a component filter.
+        // We'll parse it manually, as it's pretty simple.
+        if ($vObject->name !== $filters['name']) {
+            return false;
+        }
+
+        return
+            $this->validateCompFilters($vObject, $filters['comp-filters']) &&
+            $this->validatePropFilters($vObject, $filters['prop-filters']);
+
+
+    }
+
+    /**
+     * This method checks the validity of comp-filters.
+     *
+     * A list of comp-filters needs to be specified. Also the parent of the
+     * component we're checking should be specified, not the component to check
+     * itself.
+     *
+     * @param Sabre_VObject_Component $parent
+     * @param array $filters
+     * @return bool
+     */
+    protected function validateCompFilters(Sabre_VObject_Component $parent, array $filters) {
+
+        foreach($filters as $filter) {
+
+            $isDefined = isset($parent->$filter['name']);
+
+            if ($filter['is-not-defined']) {
+
+                if ($isDefined) {
+                    return false;
+                } else {
+                    continue;
+                }
+
+            }
+            if (!$isDefined) {
+                return false;
+            }
+
+            if ($filter['time-range']) {
+                foreach($parent->$filter['name'] as $subComponent) {
+                    if ($this->validateTimeRange($subComponent, $filter['time-range']['start'], $filter['time-range']['end'])) {
+                        continue 2;
+                    }
+                }
+                return false;
+            }
+
+            if (!$filter['comp-filters'] && !$filter['prop-filters']) {
+                continue;
+            }
+
+            // If there are sub-filters, we need to find at least one component
+            // for which the subfilters hold true.
+            foreach($parent->$filter['name'] as $subComponent) {
+
+                if (
+                    $this->validateCompFilters($subComponent, $filter['comp-filters']) &&
+                    $this->validatePropFilters($subComponent, $filter['prop-filters'])) {
+                        // We had a match, so this comp-filter succeeds
+                        continue 2;
+                }
+
+            }
+
+            // If we got here it means there were sub-comp-filters or
+            // sub-prop-filters and there was no match. This means this filter
+            // needs to return false.
+            return false;
+
+        }
+
+        // If we got here it means we got through all comp-filters alive so the
+        // filters were all true.
+        return true;
+
+    }
+
+    /**
+     * This method checks the validity of prop-filters.
+     *
+     * A list of prop-filters needs to be specified. Also the parent of the
+     * property we're checking should be specified, not the property to check
+     * itself.
+     *
+     * @param Sabre_VObject_Component $parent
+     * @param array $filters
+     * @return bool
+     */
+    protected function validatePropFilters(Sabre_VObject_Component $parent, array $filters) {
+
+        foreach($filters as $filter) {
+
+            $isDefined = isset($parent->$filter['name']);
+
+            if ($filter['is-not-defined']) {
+
+                if ($isDefined) {
+                    return false;
+                } else {
+                    continue;
+                }
+
+            }
+            if (!$isDefined) {
+                return false;
+            }
+
+            if ($filter['time-range']) {
+                foreach($parent->$filter['name'] as $subComponent) {
+                    if ($this->validateTimeRange($subComponent, $filter['time-range']['start'], $filter['time-range']['end'])) {
+                        continue 2;
+                    }
+                }
+                return false;
+            }
+
+            if (!$filter['param-filters'] && !$filter['text-match']) {
+                continue;
+            }
+
+            // If there are sub-filters, we need to find at least one property
+            // for which the subfilters hold true.
+            foreach($parent->$filter['name'] as $subComponent) {
+
+                if(
+                    $this->validateParamFilters($subComponent, $filter['param-filters']) &&
+                    (!$filter['text-match'] || $this->validateTextMatch($subComponent, $filter['text-match']))
+                ) {
+                    // We had a match, so this prop-filter succeeds
+                    continue 2;
+                }
+
+            }
+
+            // If we got here it means there were sub-param-filters or
+            // text-match filters and there was no match. This means the
+            // filter needs to return false.
+            return false;
+
+        }
+
+        // If we got here it means we got through all prop-filters alive so the
+        // filters were all true.
+        return true;
+
+    }
+
+    /**
+     * This method checks the validity of param-filters.
+     *
+     * A list of param-filters needs to be specified. Also the parent of the
+     * parameter we're checking should be specified, not the parameter to check
+     * itself.
+     *
+     * @param Sabre_VObject_Property $parent
+     * @param array $filters
+     * @return bool
+     */
+    protected function validateParamFilters(Sabre_VObject_Property $parent, array $filters) {
+
+        foreach($filters as $filter) {
+
+            $isDefined = isset($parent[$filter['name']]);
+
+            if ($filter['is-not-defined']) {
+
+                if ($isDefined) {
+                    return false;
+                } else {
+                    continue;
+                }
+
+            }
+            if (!$isDefined) {
+                return false;
+            }
+
+            if (!$filter['text-match']) {
+                continue;
+            }
+
+            // If there are sub-filters, we need to find at least one parameter
+            // for which the subfilters hold true.
+            foreach($parent[$filter['name']] as $subParam) {
+
+                if($this->validateTextMatch($subParam,$filter['text-match'])) {
+                    // We had a match, so this param-filter succeeds
+                    continue 2;
+                }
+
+            }
+
+            // If we got here it means there was a text-match filter and there
+            // were no matches. This means the filter needs to return false.
+            return false;
+
+        }
+
+        // If we got here it means we got through all param-filters alive so the
+        // filters were all true.
+        return true;
+
+    }
+
+    /**
+     * This method checks the validity of a text-match.
+     *
+     * A single text-match should be specified as well as the specific property
+     * or parameter we need to validate.
+     *
+     * @param Sabre_VObject_Node $parent
+     * @param array $textMatch
+     * @return bool
+     */
+    protected function validateTextMatch(Sabre_VObject_Node $parent, array $textMatch) {
+
+        $value = (string)$parent;
+
+        $isMatching = Sabre_DAV_StringUtil::textMatch($value, $textMatch['value'], $textMatch['collation']);
+
+        return ($textMatch['negate-condition'] xor $isMatching);
+
+    }
+
+    /**
+     * Validates if a component matches the given time range.
+     *
+     * This is all based on the rules specified in rfc4791, which are quite
+     * complex.
+     *
+     * @param Sabre_VObject_Node $component
+     * @param DateTime $start
+     * @param DateTime $end
+     * @return bool
+     */
+    protected function validateTimeRange(Sabre_VObject_Node $component, $start, $end) {
+
+        if (is_null($start)) {
+            $start = new DateTime('1900-01-01');
+        }
+        if (is_null($end)) {
+            $end = new DateTime('3000-01-01');
+        }
+
+        switch($component->name) {
+
+            case 'VEVENT' :
+            case 'VTODO' :
+            case 'VJOURNAL' :
+
+                return $component->isInTimeRange($start, $end);
+
+            case 'VALARM' :
+
+                // If the valarm is wrapped in a recurring event, we need to
+                // expand the recursions, and validate each.
+                //
+                // Our datamodel doesn't easily allow us to do this straight
+                // in the VALARM component code, so this is a hack, and an
+                // expensive one too.
+                if ($component->parent->name === 'VEVENT' && $component->parent->RRULE) {
+                    // Fire up the iterator!
+                    $it = new Sabre_VObject_RecurrenceIterator($component->parent->parent, (string)$component->parent->UID);
+                    while($it->valid()) {
+                        $expandedEvent = $it->getEventObject();
+
+                        // We need to check from these expanded alarms, which
+                        // one is the first to trigger. Based on this, we can
+                        // determine if we can 'give up' expanding events.
+                        $firstAlarm = null;
+                        foreach($expandedEvent->VALARM as $expandedAlarm) {
+                            $effectiveTrigger = $expandedAlarm->getEffectiveTriggerTime();
+                            if (!$firstAlarm || $effectiveTrigger < $firstAlarm) {
+                                $firstAlarm = $effectiveTrigger;
+                            }
+                            if ($expandedAlarm->isInTimeRange($start, $end)) {
+                                return true;
+                            }
+
+                        }
+                        if ($firstAlarm > $end) {
+                            return false;
+                        }
+                        $it->next();
+                    }
+                    return false;
+                } else {
+                    return $component->isInTimeRange($start, $end);
+                }
+
+            case 'VFREEBUSY' :
+                throw new Sabre_DAV_Exception_NotImplemented('time-range filters are currently not supported on ' . $component->name . ' components');
+
+            case 'COMPLETED' :
+            case 'CREATED' :
+            case 'DTEND' :
+            case 'DTSTAMP' :
+            case 'DTSTART' :
+            case 'DUE' :
+            case 'LAST-MODIFIED' :
+                return ($start <= $component->getDateTime() && $end >= $component->getDateTime());
+
+
+
+            default :
+                throw new Sabre_DAV_Exception_BadRequest('You cannot create a time-range filter on a ' . $component->name . ' component');
+
+        }
+
+    }
+
+}
diff --git a/3rdparty/Sabre/CalDAV/CalendarRootNode.php b/3rdparty/Sabre/CalDAV/CalendarRootNode.php
index 69669a9d7fd96a5612661cf463621f242c8fcd3e..3907913cc78600afc38698ddb42ba3d30cffeed7 100644
--- a/3rdparty/Sabre/CalDAV/CalendarRootNode.php
+++ b/3rdparty/Sabre/CalDAV/CalendarRootNode.php
@@ -1,38 +1,38 @@
 <?php
 
 /**
- * Users collection 
+ * Users collection
  *
  * This object is responsible for generating a collection of users.
  *
  * @package Sabre
  * @subpackage CalDAV
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
  * @author Evert Pot (http://www.rooftopsolutions.nl/) 
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
  */
 class Sabre_CalDAV_CalendarRootNode extends Sabre_DAVACL_AbstractPrincipalCollection {
 
     /**
-     * CalDAV backend 
-     * 
-     * @var Sabre_CalDAV_Backend_Abstract 
+     * CalDAV backend
+     *
+     * @var Sabre_CalDAV_Backend_Abstract
      */
     protected $caldavBackend;
 
     /**
-     * Constructor 
+     * Constructor
      *
      * This constructor needs both an authentication and a caldav backend.
      *
-     * By default this class will show a list of calendar collections for 
-     * principals in the 'principals' collection. If your main principals are 
-     * actually located in a different path, use the $principalPrefix argument 
+     * By default this class will show a list of calendar collections for
+     * principals in the 'principals' collection. If your main principals are
+     * actually located in a different path, use the $principalPrefix argument
      * to override this.
      *
      *
-     * @param Sabre_DAVACL_IPrincipalBackend $principalBackend 
-     * @param Sabre_CalDAV_Backend_Abstract $caldavBackend 
+     * @param Sabre_DAVACL_IPrincipalBackend $principalBackend
+     * @param Sabre_CalDAV_Backend_Abstract $caldavBackend
      * @param string $principalPrefix
      */
     public function __construct(Sabre_DAVACL_IPrincipalBackend $principalBackend,Sabre_CalDAV_Backend_Abstract $caldavBackend, $principalPrefix = 'principals') {
@@ -46,9 +46,9 @@ class Sabre_CalDAV_CalendarRootNode extends Sabre_DAVACL_AbstractPrincipalCollec
      * Returns the nodename
      *
      * We're overriding this, because the default will be the 'principalPrefix',
-     * and we want it to be Sabre_CalDAV_Plugin::CALENDAR_ROOT 
-     * 
-     * @return void
+     * and we want it to be Sabre_CalDAV_Plugin::CALENDAR_ROOT
+     *
+     * @return string
      */
     public function getName() {
 
@@ -62,9 +62,9 @@ class Sabre_CalDAV_CalendarRootNode extends Sabre_DAVACL_AbstractPrincipalCollec
      * The passed array contains principal information, and is guaranteed to
      * at least contain a uri item. Other properties may or may not be
      * supplied by the authentication backend.
-     * 
-     * @param array $principal 
-     * @return Sabre_DAV_INode 
+     *
+     * @param array $principal
+     * @return Sabre_DAV_INode
      */
     public function getChildForPrincipal(array $principal) {
 
diff --git a/3rdparty/Sabre/CalDAV/Exception/InvalidICalendarObject.php b/3rdparty/Sabre/CalDAV/Exception/InvalidICalendarObject.php
deleted file mode 100644
index 656b7286a66538dbeb487983a226384705e7c6b9..0000000000000000000000000000000000000000
--- a/3rdparty/Sabre/CalDAV/Exception/InvalidICalendarObject.php
+++ /dev/null
@@ -1,18 +0,0 @@
-<?php
-
-/**
- * InvalidICalendarObject
- *
- * This exception is thrown when an attempt is made to create or update
- * an invalid ICalendar object
- * 
- * @package Sabre
- * @subpackage CalDAV
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
- * @author Evert Pot (http://www.rooftopsolutions.nl/) 
- * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
- */
-class Sabre_CalDAV_Exception_InvalidICalendarObject extends Sabre_DAV_Exception_PreconditionFailed {
-
-
-}
diff --git a/3rdparty/Sabre/CalDAV/ICSExportPlugin.php b/3rdparty/Sabre/CalDAV/ICSExportPlugin.php
index 4e2c6eb93d286da842e1ecb9035d031b0cb885c2..ec42b406b2f172c7289a00ba7975fc35f59fa877 100644
--- a/3rdparty/Sabre/CalDAV/ICSExportPlugin.php
+++ b/3rdparty/Sabre/CalDAV/ICSExportPlugin.php
@@ -4,28 +4,28 @@
  * ICS Exporter
  *
  * This plugin adds the ability to export entire calendars as .ics files.
- * This is useful for clients that don't support CalDAV yet. They often do 
+ * This is useful for clients that don't support CalDAV yet. They often do
  * support ics files.
- * 
+ *
  * @package Sabre
  * @subpackage CalDAV
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
- * @author Evert Pot (http://www.rooftopsolutions.nl/) 
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
  */
 class Sabre_CalDAV_ICSExportPlugin extends Sabre_DAV_ServerPlugin {
 
     /**
-     * Reference to Server class 
-     * 
-     * @var Sabre_DAV_Server 
+     * Reference to Server class
+     *
+     * @var Sabre_DAV_Server
      */
     private $server;
 
     /**
-     * Initializes the plugin and registers event handlers 
-     * 
-     * @param Sabre_DAV_Server $server 
+     * Initializes the plugin and registers event handlers
+     *
+     * @param Sabre_DAV_Server $server
      * @return void
      */
     public function initialize(Sabre_DAV_Server $server) {
@@ -38,10 +38,10 @@ class Sabre_CalDAV_ICSExportPlugin extends Sabre_DAV_ServerPlugin {
     /**
      * 'beforeMethod' event handles. This event handles intercepts GET requests ending
      * with ?export
-     * 
+     *
      * @param string $method
      * @param string $uri
-     * @return void
+     * @return bool
      */
     public function beforeMethod($method, $uri) {
 
@@ -55,9 +55,19 @@ class Sabre_CalDAV_ICSExportPlugin extends Sabre_DAV_ServerPlugin {
 
         if (!($node instanceof Sabre_CalDAV_Calendar)) return;
 
+        // Checking ACL, if available.
+        if ($aclPlugin = $this->server->getPlugin('acl')) {
+            $aclPlugin->checkPrivileges($uri, '{DAV:}read');
+        }
+
         $this->server->httpResponse->setHeader('Content-Type','text/calendar');
         $this->server->httpResponse->sendStatus(200);
-        $this->server->httpResponse->sendBody($this->generateICS($this->server->tree->getChildren($uri)));
+
+        $nodes = $this->server->getPropertiesForPath($uri, array(
+            '{' . Sabre_CalDAV_Plugin::NS_CALDAV . '}calendar-data',
+        ),1);
+
+        $this->server->httpResponse->sendBody($this->generateICS($nodes));
 
         // Returning false to break the event chain
         return false;
@@ -65,16 +75,20 @@ class Sabre_CalDAV_ICSExportPlugin extends Sabre_DAV_ServerPlugin {
     }
 
     /**
-     * Merges all calendar objects, and builds one big ics export 
-     * 
-     * @param array $nodes 
-     * @return void
+     * Merges all calendar objects, and builds one big ics export
+     *
+     * @param array $nodes
+     * @return string
      */
     public function generateICS(array $nodes) {
 
         $calendar = new Sabre_VObject_Component('vcalendar');
         $calendar->version = '2.0';
-        $calendar->prodid = '-//SabreDAV//SabreDAV ' . Sabre_DAV_Version::VERSION . '//EN';
+        if (Sabre_DAV_Server::$exposeVersion) {
+            $calendar->prodid = '-//SabreDAV//SabreDAV ' . Sabre_DAV_Version::VERSION . '//EN';
+        } else {
+            $calendar->prodid = '-//SabreDAV//SabreDAV//EN';
+        }
         $calendar->calscale = 'GREGORIAN';
 
         $collectedTimezones = array();
@@ -84,7 +98,11 @@ class Sabre_CalDAV_ICSExportPlugin extends Sabre_DAV_ServerPlugin {
 
         foreach($nodes as $node) {
 
-            $nodeData = $node->get();
+            if (!isset($node[200]['{' . Sabre_CalDAV_Plugin::NS_CALDAV . '}calendar-data'])) {
+                continue;
+            }
+            $nodeData = $node[200]['{' . Sabre_CalDAV_Plugin::NS_CALDAV . '}calendar-data'];
+
             $nodeComp = Sabre_VObject_Reader::read($nodeData);
 
             foreach($nodeComp->children() as $child) {
@@ -105,13 +123,10 @@ class Sabre_CalDAV_ICSExportPlugin extends Sabre_DAV_ServerPlugin {
                         $collectedTimezones[] = $child->TZID;
                         break;
 
-
                 }
 
-
             }
 
-
         }
 
         foreach($timezones as $tz) $calendar->add($tz);
@@ -119,6 +134,6 @@ class Sabre_CalDAV_ICSExportPlugin extends Sabre_DAV_ServerPlugin {
 
         return $calendar->serialize();
 
-    } 
+    }
 
 }
diff --git a/3rdparty/Sabre/CalDAV/ICalendar.php b/3rdparty/Sabre/CalDAV/ICalendar.php
index 8193dff3a8393debda39bb09cf1df42a1f642763..15d51ebcf79a2b7552257ac4b7c1d5e42596461a 100644
--- a/3rdparty/Sabre/CalDAV/ICalendar.php
+++ b/3rdparty/Sabre/CalDAV/ICalendar.php
@@ -4,15 +4,15 @@
  * Calendar interface
  *
  * Implement this interface to allow a node to be recognized as an calendar.
- * 
+ *
  * @package Sabre
  * @subpackage CalDAV
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
  * @author Evert Pot (http://www.rooftopsolutions.nl/) 
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
  */
 interface Sabre_CalDAV_ICalendar extends Sabre_DAV_ICollection {
 
- 
+
 
 }
diff --git a/3rdparty/Sabre/CalDAV/ICalendarObject.php b/3rdparty/Sabre/CalDAV/ICalendarObject.php
index 708300ad7bd83f731c6e0933ebaeaf31789aa876..280f982a310e225929c22dc0685caf3852c3f20a 100644
--- a/3rdparty/Sabre/CalDAV/ICalendarObject.php
+++ b/3rdparty/Sabre/CalDAV/ICalendarObject.php
@@ -1,20 +1,20 @@
 <?php
 
 /**
- * CalendarObject interface 
+ * CalendarObject interface
 /**
- * Extend the ICalendarObject interface to allow your custom nodes to be picked up as 
+ * Extend the ICalendarObject interface to allow your custom nodes to be picked up as
  * CalendarObjects.
  *
  * Calendar objects are resources such as Events, Todo's or Journals.
- * 
+ *
  * @package Sabre
  * @subpackage CalDAV
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
  * @author Evert Pot (http://www.rooftopsolutions.nl/) 
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
  */
-interface Sabre_CalDAV_ICalendarObject extends Sabre_DAV_IFile { 
+interface Sabre_CalDAV_ICalendarObject extends Sabre_DAV_IFile {
 
 }
 
diff --git a/3rdparty/Sabre/CalDAV/ICalendarUtil.php b/3rdparty/Sabre/CalDAV/ICalendarUtil.php
deleted file mode 100644
index 699abfdd6f5e0726701664a849405df4b422fe32..0000000000000000000000000000000000000000
--- a/3rdparty/Sabre/CalDAV/ICalendarUtil.php
+++ /dev/null
@@ -1,157 +0,0 @@
-<?php
-
-/**
- * This class contains several utilities related to the ICalendar (rfc2445) format
- *
- * This class is now deprecated, and won't be further maintained. Please use 
- * the Sabre_VObject package for your ics parsing needs.
- *
- * @package Sabre
- * @subpackage CalDAV
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
- * @author Evert Pot (http://www.rooftopsolutions.nl/) 
- * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
- * @deprecated Use Sabre_VObject instead.
- */
-class Sabre_CalDAV_ICalendarUtil {
-
-    /**
-     * Validates an ICalendar object
-     *
-     * This method makes sure this ICalendar object is properly formatted.
-     * If we can't parse it, we'll throw exceptions.
-     *
-     * @param string $icalData 
-     * @param array $allowedComponents 
-     * @return bool 
-     */
-    static function validateICalendarObject($icalData, array $allowedComponents = null) {
-
-        $xcal = simplexml_load_string(self::toXCal($icalData));
-        if (!$xcal) throw new Sabre_CalDAV_Exception_InvalidICalendarObject('Invalid calendarobject format');
-
-        $xcal->registerXPathNameSpace('cal','urn:ietf:params:xml:ns:xcal');
-        
-        // Check if there's only 1 component
-        $components = array('vevent','vtodo','vjournal','vfreebusy');
-        $componentsFound = array();
-
-        foreach($components as $component) {
-            $test = $xcal->xpath('/cal:iCalendar/cal:vcalendar/cal:' . $component);
-            if (is_array($test)) $componentsFound = array_merge($componentsFound, $test);
-        }
-        if (count($componentsFound)<1) {
-            throw new Sabre_CalDAV_Exception_InvalidICalendarObject('One VEVENT, VTODO, VJOURNAL or VFREEBUSY must be specified. 0 found.');
-        }
-        $component = $componentsFound[0];
-
-        if (is_null($allowedComponents)) return true;
-
-        // Check if the component is allowed
-        $name = $component->getName();
-        if (!in_array(strtoupper($name),$allowedComponents)) {
-            throw new Sabre_CalDAV_Exception_InvalidICalendarObject(strtoupper($name) . ' is not allowed in this calendar.');
-        }
-
-        if (count($xcal->xpath('/cal:iCalendar/cal:vcalendar/cal:method'))>0) {
-            throw new Sabre_CalDAV_Exception_InvalidICalendarObject('The METHOD property is not allowed in calendar objects');
-        }
-
-        return true;
-
-    }
-
-    /**
-     * Converts ICalendar data to XML.
-     *
-     * Properties are converted to lowercase xml elements. Parameters are;
-     * converted to attributes. BEGIN:VEVENT is converted to <vevent> and
-     * END:VEVENT </vevent> as well as other components.
-     *
-     * It's a very loose parser. If any line does not conform to the spec, it
-     * will simply be ignored. It will try to detect if \r\n or \n line endings
-     * are used.
-     *
-     * @todo Currently quoted attributes are not parsed correctly.
-     * @see http://tools.ietf.org/html/draft-royer-calsch-xcal-03
-     * @param string $icalData 
-     * @return string. 
-     */
-    static function toXCAL($icalData) {
-
-        // Detecting line endings
-        $lb="\r\n";
-        if (strpos($icalData,"\r\n")!==false) $lb = "\r\n";
-        elseif (strpos($icalData,"\n")!==false) $lb = "\n";
-
-        // Splitting up items per line
-        $lines = explode($lb,$icalData);
-
-        // Properties can be folded over 2 lines. In this case the second
-        // line will be preceeded by a space or tab.
-        $lines2 = array();
-        foreach($lines as $line) {
-
-            if (!$line) continue;
-            if ($line[0]===" " || $line[0]==="\t") {
-                $lines2[count($lines2)-1].=substr($line,1);
-                continue;
-            }
-
-            $lines2[]=$line;
-
-        }
-
-        $xml = '<?xml version="1.0"?>' . "\n";
-        $xml.= "<iCalendar xmlns=\"urn:ietf:params:xml:ns:xcal\">\n";
-
-        $spaces = 2;
-        foreach($lines2 as $line) {
-
-            $matches = array();
-            // This matches PROPERTYNAME;ATTRIBUTES:VALUE
-            if (!preg_match('/^([^:^;]*)(?:;([^:]*))?:(.*)$/',$line,$matches))
-                continue;
-
-            $propertyName = strtolower($matches[1]);
-            $attributes = $matches[2];
-            $value = $matches[3];
-
-            // If the line was in the format BEGIN:COMPONENT or END:COMPONENT, we need to special case it.
-            if ($propertyName === 'begin') {
-                $xml.=str_repeat(" ",$spaces);
-                $xml.='<' . strtolower($value) . ">\n";
-                $spaces+=2;
-                continue;
-            } elseif ($propertyName === 'end') {
-                $spaces-=2;
-                $xml.=str_repeat(" ",$spaces);
-                $xml.='</' . strtolower($value) . ">\n";
-                continue;
-            }
-
-            $xml.=str_repeat(" ",$spaces);
-            $xml.='<' . $propertyName;
-            if ($attributes) {
-                // There can be multiple attributes
-                $attributes = explode(';',$attributes);
-                foreach($attributes as $att) {
-  
-                    list($attName,$attValue) = explode('=',$att,2);
-                    $attName = strtolower($attName);
-                    if ($attName === 'language') $attName='xml:lang';
-                    $xml.=' ' . $attName . '="' . htmlspecialchars($attValue) . '"';
-
-                }
-            }
-
-            $xml.='>'. htmlspecialchars(trim($value)) . '</' . $propertyName . ">\n";
-          
-        }
-        $xml.="</iCalendar>";
-        return $xml;
-
-    }
-
-}
-
diff --git a/3rdparty/Sabre/CalDAV/Plugin.php b/3rdparty/Sabre/CalDAV/Plugin.php
index 02747c8395e3a2b6d0f32183074d598d707ffff6..d7d1d970518a8f32e1cdcfe9feed27a930804b6e 100644
--- a/3rdparty/Sabre/CalDAV/Plugin.php
+++ b/3rdparty/Sabre/CalDAV/Plugin.php
@@ -8,8 +8,8 @@
  *
  * @package Sabre
  * @subpackage CalDAV
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
- * @author Evert Pot (http://www.rooftopsolutions.nl/) 
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
  */
 class Sabre_CalDAV_Plugin extends Sabre_DAV_ServerPlugin {
@@ -18,7 +18,7 @@ class Sabre_CalDAV_Plugin extends Sabre_DAV_ServerPlugin {
      * This is the official CalDAV namespace
      */
     const NS_CALDAV = 'urn:ietf:params:xml:ns:caldav';
-    
+
     /**
      * This is the namespace for the proprietary calendarserver extensions
      */
@@ -41,21 +41,48 @@ class Sabre_CalDAV_Plugin extends Sabre_DAV_ServerPlugin {
     const CALENDAR_ROOT = 'calendars';
 
     /**
-     * Reference to server object 
-     * 
-     * @var Sabre_DAV_Server 
+     * Reference to server object
+     *
+     * @var Sabre_DAV_Server
      */
     private $server;
 
+    /**
+     * The email handler for invites and other scheduling messages.
+     * 
+     * @var Sabre_CalDAV_Schedule_IMip 
+     */
+    protected $imipHandler;
+
+    /**
+     * Sets the iMIP handler.
+     *
+     * iMIP = The email transport of iCalendar scheduling messages. Setting 
+     * this is optional, but if you want the server to allow invites to be sent 
+     * out, you must set a handler.
+     *
+     * Specifically iCal will plain assume that the server supports this. If 
+     * the server doesn't, iCal will display errors when inviting people to 
+     * events.
+     *
+     * @param Sabre_CalDAV_Schedule_IMip $imipHandler 
+     * @return void
+     */
+    public function setIMipHandler(Sabre_CalDAV_Schedule_IMip $imipHandler) {
+
+        $this->imipHandler = $imipHandler;
+
+    }
+
     /**
      * Use this method to tell the server this plugin defines additional
      * HTTP methods.
      *
-     * This method is passed a uri. It should only return HTTP methods that are 
+     * This method is passed a uri. It should only return HTTP methods that are
      * available for the specified uri.
      *
      * @param string $uri
-     * @return array 
+     * @return array
      */
     public function getHTTPMethods($uri) {
 
@@ -68,7 +95,7 @@ class Sabre_CalDAV_Plugin extends Sabre_DAV_ServerPlugin {
         if ($node instanceof Sabre_DAV_IExtendedCollection) {
             try {
                 $node->getChild($name);
-            } catch (Sabre_DAV_Exception_FileNotFound $e) {
+            } catch (Sabre_DAV_Exception_NotFound $e) {
                 return array('MKCALENDAR');
             }
         }
@@ -77,9 +104,9 @@ class Sabre_CalDAV_Plugin extends Sabre_DAV_ServerPlugin {
     }
 
     /**
-     * Returns a list of features for the DAV: HTTP header. 
-     * 
-     * @return array 
+     * Returns a list of features for the DAV: HTTP header.
+     *
+     * @return array
      */
     public function getFeatures() {
 
@@ -89,11 +116,11 @@ class Sabre_CalDAV_Plugin extends Sabre_DAV_ServerPlugin {
 
     /**
      * Returns a plugin name.
-     * 
+     *
      * Using this name other plugins will be able to access other plugins
-     * using Sabre_DAV_Server::getPlugin 
-     * 
-     * @return string 
+     * using Sabre_DAV_Server::getPlugin
+     *
+     * @return string
      */
     public function getPluginName() {
 
@@ -105,38 +132,46 @@ class Sabre_CalDAV_Plugin extends Sabre_DAV_ServerPlugin {
      * Returns a list of reports this plugin supports.
      *
      * This will be used in the {DAV:}supported-report-set property.
-     * Note that you still need to subscribe to the 'report' event to actually 
-     * implement them 
-     * 
+     * Note that you still need to subscribe to the 'report' event to actually
+     * implement them
+     *
      * @param string $uri
-     * @return array 
+     * @return array
      */
     public function getSupportedReportSet($uri) {
 
         $node = $this->server->tree->getNodeForPath($uri);
+
+        $reports = array();
         if ($node instanceof Sabre_CalDAV_ICalendar || $node instanceof Sabre_CalDAV_ICalendarObject) {
-            return array(
-                 '{' . self::NS_CALDAV . '}calendar-multiget',
-                 '{' . self::NS_CALDAV . '}calendar-query',
-            );
+            $reports[] = '{' . self::NS_CALDAV . '}calendar-multiget';
+            $reports[] = '{' . self::NS_CALDAV . '}calendar-query';
         }
-        return array();
+        if ($node instanceof Sabre_CalDAV_ICalendar) {
+            $reports[] = '{' . self::NS_CALDAV . '}free-busy-query';
+        }
+        return $reports;
 
     }
 
     /**
-     * Initializes the plugin 
-     * 
-     * @param Sabre_DAV_Server $server 
+     * Initializes the plugin
+     *
+     * @param Sabre_DAV_Server $server
      * @return void
      */
     public function initialize(Sabre_DAV_Server $server) {
 
         $this->server = $server;
+
         $server->subscribeEvent('unknownMethod',array($this,'unknownMethod'));
         //$server->subscribeEvent('unknownMethod',array($this,'unknownMethod2'),1000);
         $server->subscribeEvent('report',array($this,'report'));
         $server->subscribeEvent('beforeGetProperties',array($this,'beforeGetProperties'));
+        $server->subscribeEvent('onHTMLActionsPanel', array($this,'htmlActionsPanel'));
+        $server->subscribeEvent('onBrowserPostAction', array($this,'browserPostAction'));
+        $server->subscribeEvent('beforeWriteContent', array($this, 'beforeWriteContent'));
+        $server->subscribeEvent('beforeCreateFile', array($this, 'beforeCreateFile'));
 
         $server->xmlNamespaces[self::NS_CALDAV] = 'cal';
         $server->xmlNamespaces[self::NS_CALENDARSERVER] = 'cs';
@@ -144,6 +179,7 @@ class Sabre_CalDAV_Plugin extends Sabre_DAV_ServerPlugin {
         $server->propertyMap['{' . self::NS_CALDAV . '}supported-calendar-component-set'] = 'Sabre_CalDAV_Property_SupportedCalendarComponentSet';
 
         $server->resourceTypeMapping['Sabre_CalDAV_ICalendar'] = '{urn:ietf:params:xml:ns:caldav}calendar';
+        $server->resourceTypeMapping['Sabre_CalDAV_Schedule_IOutbox'] = '{urn:ietf:params:xml:ns:caldav}schedule-outbox';
         $server->resourceTypeMapping['Sabre_CalDAV_Principal_ProxyRead'] = '{http://calendarserver.org/ns/}calendar-proxy-read';
         $server->resourceTypeMapping['Sabre_CalDAV_Principal_ProxyWrite'] = '{http://calendarserver.org/ns/}calendar-proxy-write';
 
@@ -161,7 +197,10 @@ class Sabre_CalDAV_Plugin extends Sabre_DAV_ServerPlugin {
             '{' . self::NS_CALDAV . '}calendar-data',
 
             // scheduling extension
+            '{' . self::NS_CALDAV . '}schedule-inbox-URL',
+            '{' . self::NS_CALDAV . '}schedule-outbox-URL',
             '{' . self::NS_CALDAV . '}calendar-user-address-set',
+            '{' . self::NS_CALDAV . '}calendar-user-type',
 
             // CalendarServer extensions
             '{' . self::NS_CALENDARSERVER . '}getctag',
@@ -173,36 +212,55 @@ class Sabre_CalDAV_Plugin extends Sabre_DAV_ServerPlugin {
 
     /**
      * This function handles support for the MKCALENDAR method
-     * 
-     * @param string $method 
-     * @return bool 
+     *
+     * @param string $method
+     * @param string $uri
+     * @return bool
      */
     public function unknownMethod($method, $uri) {
 
-        if ($method!=='MKCALENDAR') return;
+        switch ($method) {
+            case 'MKCALENDAR' :
+                $this->httpMkCalendar($uri);
+                // false is returned to stop the propagation of the
+                // unknownMethod event.
+                return false;
+            case 'POST' :
+                // Checking if we're talking to an outbox
+                try {
+                    $node = $this->server->tree->getNodeForPath($uri);
+                } catch (Sabre_DAV_Exception_NotFound $e) {
+                    return;
+                }
+                if (!$node instanceof Sabre_CalDAV_Schedule_IOutbox)
+                    return;
 
-        $this->httpMkCalendar($uri);
-        // false is returned to stop the unknownMethod event
-        return false;
+                $this->outboxRequest($node);
+                return false;
+
+        }
 
     }
 
     /**
-     * This functions handles REPORT requests specific to CalDAV 
-     * 
-     * @param string $reportName 
-     * @param DOMNode $dom 
-     * @return bool 
+     * This functions handles REPORT requests specific to CalDAV
+     *
+     * @param string $reportName
+     * @param DOMNode $dom
+     * @return bool
      */
     public function report($reportName,$dom) {
 
-        switch($reportName) { 
+        switch($reportName) {
             case '{'.self::NS_CALDAV.'}calendar-multiget' :
                 $this->calendarMultiGetReport($dom);
                 return false;
             case '{'.self::NS_CALDAV.'}calendar-query' :
                 $this->calendarQueryReport($dom);
                 return false;
+            case '{'.self::NS_CALDAV.'}free-busy-query' :
+                $this->freeBusyQueryReport($dom);
+                return false;
 
         }
 
@@ -212,9 +270,9 @@ class Sabre_CalDAV_Plugin extends Sabre_DAV_ServerPlugin {
     /**
      * This function handles the MKCALENDAR HTTP method, which creates
      * a new calendar.
-     * 
+     *
      * @param string $uri
-     * @return void 
+     * @return void
      */
     public function httpMkCalendar($uri) {
 
@@ -238,7 +296,7 @@ class Sabre_CalDAV_Plugin extends Sabre_DAV_ServerPlugin {
                 foreach(Sabre_DAV_XMLUtil::parseProperties($child,$this->server->propertyMap) as $k=>$prop) {
                     $properties[$k] = $prop;
                 }
-            
+
             }
         }
 
@@ -254,9 +312,9 @@ class Sabre_CalDAV_Plugin extends Sabre_DAV_ServerPlugin {
      * beforeGetProperties
      *
      * This method handler is invoked before any after properties for a
-     * resource are fetched. This allows us to add in any CalDAV specific 
-     * properties. 
-     * 
+     * resource are fetched. This allows us to add in any CalDAV specific
+     * properties.
+     *
      * @param string $path
      * @param Sabre_DAV_INode $node
      * @param array $requestedProperties
@@ -270,12 +328,21 @@ class Sabre_CalDAV_Plugin extends Sabre_DAV_ServerPlugin {
             // calendar-home-set property
             $calHome = '{' . self::NS_CALDAV . '}calendar-home-set';
             if (in_array($calHome,$requestedProperties)) {
-                $principalId = $node->getName(); 
+                $principalId = $node->getName();
                 $calendarHomePath = self::CALENDAR_ROOT . '/' . $principalId . '/';
                 unset($requestedProperties[$calHome]);
                 $returnedProperties[200][$calHome] = new Sabre_DAV_Property_Href($calendarHomePath);
             }
 
+            // schedule-outbox-URL property
+            $scheduleProp = '{' . self::NS_CALDAV . '}schedule-outbox-URL';
+            if (in_array($scheduleProp,$requestedProperties)) {
+                $principalId = $node->getName();
+                $outboxPath = self::CALENDAR_ROOT . '/' . $principalId . '/outbox';
+                unset($requestedProperties[$scheduleProp]);
+                $returnedProperties[200][$scheduleProp] = new Sabre_DAV_Property_Href($outboxPath);
+            }
+
             // calendar-user-address-set property
             $calProp = '{' . self::NS_CALDAV . '}calendar-user-address-set';
             if (in_array($calProp,$requestedProperties)) {
@@ -287,7 +354,7 @@ class Sabre_CalDAV_Plugin extends Sabre_DAV_ServerPlugin {
 
             }
 
-            // These two properties are shortcuts for ical to easily find 
+            // These two properties are shortcuts for ical to easily find
             // other principals this principal has access to.
             $propRead = '{' . self::NS_CALENDARSERVER . '}calendar-proxy-read-for';
             $propWrite = '{' . self::NS_CALENDARSERVER . '}calendar-proxy-write-for';
@@ -301,8 +368,8 @@ class Sabre_CalDAV_Plugin extends Sabre_DAV_ServerPlugin {
 
                     $groupNode = $this->server->tree->getNodeForPath($group);
 
-                    // If the node is either ap proxy-read or proxy-write 
-                    // group, we grab the parent principal and add it to the 
+                    // If the node is either ap proxy-read or proxy-write
+                    // group, we grab the parent principal and add it to the
                     // list.
                     if ($groupNode instanceof Sabre_CalDAV_Principal_ProxyRead) {
                         list($readList[]) = Sabre_DAV_URLUtil::splitPath($group);
@@ -327,8 +394,8 @@ class Sabre_CalDAV_Plugin extends Sabre_DAV_ServerPlugin {
 
 
         if ($node instanceof Sabre_CalDAV_ICalendarObject) {
-            // The calendar-data property is not supposed to be a 'real' 
-            // property, but in large chunks of the spec it does act as such. 
+            // The calendar-data property is not supposed to be a 'real'
+            // property, but in large chunks of the spec it does act as such.
             // Therefore we simply expose it as a property.
             $calDataProp = '{' . Sabre_CalDAV_Plugin::NS_CALDAV . '}calendar-data';
             if (in_array($calDataProp, $requestedProperties)) {
@@ -350,18 +417,52 @@ class Sabre_CalDAV_Plugin extends Sabre_DAV_ServerPlugin {
      *
      * This report is used by the client to fetch the content of a series
      * of urls. Effectively avoiding a lot of redundant requests.
-     * 
-     * @param DOMNode $dom 
+     *
+     * @param DOMNode $dom
      * @return void
      */
     public function calendarMultiGetReport($dom) {
 
         $properties = array_keys(Sabre_DAV_XMLUtil::parseProperties($dom->firstChild));
-
         $hrefElems = $dom->getElementsByTagNameNS('urn:DAV','href');
+
+        $xpath = new DOMXPath($dom);
+        $xpath->registerNameSpace('cal',Sabre_CalDAV_Plugin::NS_CALDAV);
+        $xpath->registerNameSpace('dav','urn:DAV');
+
+        $expand = $xpath->query('/cal:calendar-multiget/dav:prop/cal:calendar-data/cal:expand');
+        if ($expand->length>0) {
+            $expandElem = $expand->item(0);
+            $start = $expandElem->getAttribute('start');
+            $end = $expandElem->getAttribute('end');
+            if(!$start || !$end) {
+                throw new Sabre_DAV_Exception_BadRequest('The "start" and "end" attributes are required for the CALDAV:expand element');
+            }
+            $start = Sabre_VObject_DateTimeParser::parseDateTime($start);
+            $end = Sabre_VObject_DateTimeParser::parseDateTime($end);
+
+            if ($end <= $start) {
+                throw new Sabre_DAV_Exception_BadRequest('The end-date must be larger than the start-date in the expand element.');
+            }
+
+            $expand = true;
+
+        } else {
+
+            $expand = false;
+
+        }
+
         foreach($hrefElems as $elem) {
             $uri = $this->server->calculateUri($elem->nodeValue);
             list($objProps) = $this->server->getPropertiesForPath($uri,$properties);
+
+            if ($expand && isset($objProps[200]['{' . self::NS_CALDAV . '}calendar-data'])) {
+                $vObject = Sabre_VObject_Reader::read($objProps[200]['{' . self::NS_CALDAV . '}calendar-data']);
+                $vObject->expand($start, $end);
+                $objProps[200]['{' . self::NS_CALDAV . '}calendar-data'] = $vObject->serialize();
+            }
+
             $propertyList[]=$objProps;
 
         }
@@ -377,48 +478,57 @@ class Sabre_CalDAV_Plugin extends Sabre_DAV_ServerPlugin {
      *
      * This report is used by clients to request calendar objects based on
      * complex conditions.
-     * 
-     * @param DOMNode $dom 
+     *
+     * @param DOMNode $dom
      * @return void
      */
     public function calendarQueryReport($dom) {
 
-        $requestedProperties = array_keys(Sabre_DAV_XMLUtil::parseProperties($dom->firstChild));
-
-        $filterNode = $dom->getElementsByTagNameNS('urn:ietf:params:xml:ns:caldav','filter');
-        if ($filterNode->length!==1) {
-            throw new Sabre_DAV_Exception_BadRequest('The calendar-query report must have a filter element');
-        }
-        $filters = Sabre_CalDAV_XMLUtil::parseCalendarQueryFilters($filterNode->item(0));
+        $parser = new Sabre_CalDAV_CalendarQueryParser($dom);
+        $parser->parse();
 
         $requestedCalendarData = true;
+        $requestedProperties = $parser->requestedProperties;
 
         if (!in_array('{urn:ietf:params:xml:ns:caldav}calendar-data', $requestedProperties)) {
+
             // We always retrieve calendar-data, as we need it for filtering.
             $requestedProperties[] = '{urn:ietf:params:xml:ns:caldav}calendar-data';
 
-            // If calendar-data wasn't explicitly requested, we need to remove 
+            // If calendar-data wasn't explicitly requested, we need to remove
             // it after processing.
             $requestedCalendarData = false;
         }
 
         // These are the list of nodes that potentially match the requirement
-        $candidateNodes = $this->server->getPropertiesForPath($this->server->getRequestUri(),$requestedProperties,$this->server->getHTTPDepth(0));
+        $candidateNodes = $this->server->getPropertiesForPath(
+            $this->server->getRequestUri(),
+            $requestedProperties,
+            $this->server->getHTTPDepth(0)
+        );
 
         $verifiedNodes = array();
 
+        $validator = new Sabre_CalDAV_CalendarQueryValidator();
+
         foreach($candidateNodes as $node) {
 
             // If the node didn't have a calendar-data property, it must not be a calendar object
-            if (!isset($node[200]['{urn:ietf:params:xml:ns:caldav}calendar-data'])) continue;
+            if (!isset($node[200]['{urn:ietf:params:xml:ns:caldav}calendar-data']))
+                continue;
+
+            $vObject = Sabre_VObject_Reader::read($node[200]['{urn:ietf:params:xml:ns:caldav}calendar-data']);
+            if ($validator->validate($vObject,$parser->filters)) {
 
-            if ($this->validateFilters($node[200]['{urn:ietf:params:xml:ns:caldav}calendar-data'],$filters)) {
-                
                 if (!$requestedCalendarData) {
                     unset($node[200]['{urn:ietf:params:xml:ns:caldav}calendar-data']);
                 }
+                if ($parser->expand) {
+                    $vObject->expand($parser->expand['start'], $parser->expand['end']);
+                    $node[200]['{' . self::NS_CALDAV . '}calendar-data'] = $vObject->serialize();
+                }
                 $verifiedNodes[] = $node;
-            } 
+            }
 
         }
 
@@ -428,360 +538,291 @@ class Sabre_CalDAV_Plugin extends Sabre_DAV_ServerPlugin {
 
     }
 
-
     /**
-     * Verify if a list of filters applies to the calendar data object 
+     * This method is responsible for parsing the request and generating the
+     * response for the CALDAV:free-busy-query REPORT.
      *
-     * The calendarData object must be a valid iCalendar blob. The list of 
-     * filters must be formatted as parsed by Sabre_CalDAV_Plugin::parseCalendarQueryFilters
-     *
-     * @param string $calendarData 
-     * @param array $filters 
-     * @return bool 
+     * @param DOMNode $dom
+     * @return void
      */
-    public function validateFilters($calendarData,$filters) {
-
-        // We are converting the calendar object to an XML structure
-        // This makes it far easier to parse
-        $xCalendarData = Sabre_CalDAV_ICalendarUtil::toXCal($calendarData);
-        $xml = simplexml_load_string($xCalendarData);
-        $xml->registerXPathNamespace('c','urn:ietf:params:xml:ns:xcal');
-
-        foreach($filters as $xpath=>$filter) {
-
-            // if-not-defined comes first
-            if (isset($filter['is-not-defined'])) {
-                if (!$xml->xpath($xpath))
-                    continue;
-                else
-                    return false;
-                
-            }
-
-            $elem = $xml->xpath($xpath);
-            
-            if (!$elem) return false;
-            $elem = $elem[0];
-
-            if (isset($filter['time-range'])) {
-
-                switch($elem->getName()) {
-                    case 'vevent' :
-                        $result = $this->validateTimeRangeFilterForEvent($xml,$xpath,$filter);
-                        if ($result===false) return false;
-                        break;
-                    case 'vtodo' :
-                        $result = $this->validateTimeRangeFilterForTodo($xml,$xpath,$filter);
-                        if ($result===false) return false;
-                        break;
-                    case 'vjournal' :
-                    case 'vfreebusy' :
-                    case 'valarm' :
-                        // TODO: not implemented
-                        break;
-
-                    /*
-
-                    case 'vjournal' :
-                        $result = $this->validateTimeRangeFilterForJournal($xml,$xpath,$filter);
-                        if ($result===false) return false;
-                        break;
-                    case 'vfreebusy' :
-                        $result = $this->validateTimeRangeFilterForFreeBusy($xml,$xpath,$filter);
-                        if ($result===false) return false;
-                        break;
-                    case 'valarm' :
-                        $result = $this->validateTimeRangeFilterForAlarm($xml,$xpath,$filter);
-                        if ($result===false) return false;
-                        break;
-
-                        */
-
-                }
+    protected function freeBusyQueryReport(DOMNode $dom) {
 
-            } 
+        $start = null;
+        $end = null;
 
-            if (isset($filter['text-match'])) {
-                $currentString = (string)$elem;
+        foreach($dom->firstChild->childNodes as $childNode) {
 
-                $isMatching = Sabre_DAV_StringUtil::textMatch($currentString, $filter['text-match']['value'], $filter['text-match']['collation']);
-                if ($filter['text-match']['negate-condition'] && $isMatching) return false;
-                if (!$filter['text-match']['negate-condition'] && !$isMatching) return false;
-                
+            $clark = Sabre_DAV_XMLUtil::toClarkNotation($childNode);
+            if ($clark == '{' . self::NS_CALDAV . '}time-range') {
+                $start = $childNode->getAttribute('start');
+                $end = $childNode->getAttribute('end');
+                break;
             }
 
         }
-        return true;
-        
-    }
-
-    /**
-     * Checks whether a time-range filter matches an event.
-     * 
-     * @param SimpleXMLElement $xml Event as xml object 
-     * @param string $currentXPath XPath to check 
-     * @param array $currentFilter Filter information 
-     * @return void
-     */
-    private function validateTimeRangeFilterForEvent(SimpleXMLElement $xml,$currentXPath,array $currentFilter) {
-
-        // Grabbing the DTSTART property
-        $xdtstart = $xml->xpath($currentXPath.'/c:dtstart');
-        if (!count($xdtstart)) {
-            throw new Sabre_DAV_Exception_BadRequest('DTSTART property missing from calendar object');
+        if ($start) {
+            $start = Sabre_VObject_DateTimeParser::parseDateTime($start);
+        }
+        if ($end) {
+            $end = Sabre_VObject_DateTimeParser::parseDateTime($end);
         }
 
-        // The dtstart can be both a date, or datetime property
-        if ((string)$xdtstart[0]['value']==='DATE' || strlen((string)$xdtstart[0])===8) {
-            $isDateTime = false;
-        } else {
-            $isDateTime = true;
+        if (!$start && !$end) {
+            throw new Sabre_DAV_Exception_BadRequest('The freebusy report must have a time-range filter');
         }
+        $acl = $this->server->getPlugin('acl');
 
-        // Determining the timezone
-        if ($tzid = (string)$xdtstart[0]['tzid']) {
-            $tz = new DateTimeZone($tzid);
-        } else {
-            $tz = null;
+        if (!$acl) {
+            throw new Sabre_DAV_Exception('The ACL plugin must be loaded for free-busy queries to work');
         }
-        if ($isDateTime) {
-            $dtstart = Sabre_CalDAV_XMLUtil::parseICalendarDateTime((string)$xdtstart[0],$tz);
-        } else {
-            $dtstart = Sabre_CalDAV_XMLUtil::parseICalendarDate((string)$xdtstart[0]);
+        $uri = $this->server->getRequestUri();
+        $acl->checkPrivileges($uri,'{' . self::NS_CALDAV . '}read-free-busy');
+
+        $calendar = $this->server->tree->getNodeForPath($uri);
+        if (!$calendar instanceof Sabre_CalDAV_ICalendar) {
+            throw new Sabre_DAV_Exception_NotImplemented('The free-busy-query REPORT is only implemented on calendars');
         }
 
+        $objects = array_map(function($child) {
+            $obj = $child->get();
+            if (is_resource($obj)) {
+                $obj = stream_get_contents($obj);
+            }
+            return $obj;
+        }, $calendar->getChildren());
 
-        // Grabbing the DTEND property
-        $xdtend = $xml->xpath($currentXPath.'/c:dtend');
-        $dtend = null;
+        $generator = new Sabre_VObject_FreeBusyGenerator();
+        $generator->setObjects($objects);
+        $generator->setTimeRange($start, $end);
+        $result = $generator->getResult();
+        $result = $result->serialize();
 
-        if (count($xdtend)) {
-            // Determining the timezone
-            if ($tzid = (string)$xdtend[0]['tzid']) {
-                $tz = new DateTimeZone($tzid);
-            } else {
-                $tz = null;
-            }
+        $this->server->httpResponse->sendStatus(200);
+        $this->server->httpResponse->setHeader('Content-Type', 'text/calendar');
+        $this->server->httpResponse->setHeader('Content-Length', strlen($result));
+        $this->server->httpResponse->sendBody($result);
 
-            // Since the VALUE prameter of both DTSTART and DTEND must be the same
-            // we can assume we don't need to check the VALUE paramter of DTEND.
-            if ($isDateTime) {
-                $dtend = Sabre_CalDAV_XMLUtil::parseICalendarDateTime((string)$xdtend[0],$tz);
-            } else {
-                $dtend = Sabre_CalDAV_XMLUtil::parseICalendarDate((string)$xdtend[0],$tz);
-            }
+    }
 
-        } 
-        
-        if (is_null($dtend)) {
-            // The DTEND property was not found. We will first see if the event has a duration
-            // property
-
-            $xduration = $xml->xpath($currentXPath.'/c:duration');
-            if (count($xduration)) {
-                $duration = Sabre_CalDAV_XMLUtil::parseICalendarDuration((string)$xduration[0]);
-
-                // Making sure that the duration is bigger than 0 seconds.
-                $tempDT = clone $dtstart;
-                $tempDT->modify($duration);
-                if ($tempDT > $dtstart) {
-
-                    // use DTEND = DTSTART + DURATION 
-                    $dtend = $tempDT;
-                } else {
-                    // use DTEND = DTSTART
-                    $dtend = $dtstart;
-                }
+    /**
+     * This method is triggered before a file gets updated with new content.
+     *
+     * This plugin uses this method to ensure that CalDAV objects receive
+     * valid calendar data.
+     *
+     * @param string $path
+     * @param Sabre_DAV_IFile $node
+     * @param resource $data
+     * @return void
+     */
+    public function beforeWriteContent($path, Sabre_DAV_IFile $node, &$data) {
 
-            }
-        }
+        if (!$node instanceof Sabre_CalDAV_ICalendarObject)
+            return;
+
+        $this->validateICalendar($data);
 
-        if (is_null($dtend)) {
-            if ($isDateTime) {
-                // DTEND = DTSTART
-                $dtend = $dtstart;
-            } else {
-                // DTEND = DTSTART + 1 DAY
-                $dtend = clone $dtstart;
-                $dtend->modify('+1 day');
-            }
-        }
-        // TODO: we need to properly parse RRULE's, but it's very difficult.
-        // For now, we're always returning events if they have an RRULE at all.
-        $rrule = $xml->xpath($currentXPath.'/c:rrule');
-        $hasRrule = (count($rrule))>0; 
-       
-        if (!is_null($currentFilter['time-range']['start']) && $currentFilter['time-range']['start'] >= $dtend)  return false;
-        if (!is_null($currentFilter['time-range']['end'])   && $currentFilter['time-range']['end']   <= $dtstart && !$hasRrule) return false;
-        return true;
-    
     }
 
-    private function validateTimeRangeFilterForTodo(SimpleXMLElement $xml,$currentXPath,array $filter) {
+    /**
+     * This method is triggered before a new file is created.
+     *
+     * This plugin uses this method to ensure that newly created calendar
+     * objects contain valid calendar data.
+     *
+     * @param string $path
+     * @param resource $data
+     * @param Sabre_DAV_ICollection $parentNode
+     * @return void
+     */
+    public function beforeCreateFile($path, &$data, Sabre_DAV_ICollection $parentNode) {
 
-        // Gathering all relevant elements
+        if (!$parentNode instanceof Sabre_CalDAV_Calendar)
+            return;
 
-        $dtStart = null;
-        $duration = null;
-        $due = null;
-        $completed = null;
-        $created = null;
+        $this->validateICalendar($data);
 
-        $xdt = $xml->xpath($currentXPath.'/c:dtstart');
-        if (count($xdt)) {
-            // The dtstart can be both a date, or datetime property
-            if ((string)$xdt[0]['value']==='DATE') {
-                $isDateTime = false;
-            } else {
-                $isDateTime = true;
-            }
+    }
 
-            // Determining the timezone
-            if ($tzid = (string)$xdt[0]['tzid']) {
-                $tz = new DateTimeZone($tzid);
-            } else {
-                $tz = null;
-            }
-            if ($isDateTime) {
-                $dtStart = Sabre_CalDAV_XMLUtil::parseICalendarDateTime((string)$xdt[0],$tz);
-            } else {
-                $dtStart = Sabre_CalDAV_XMLUtil::parseICalendarDate((string)$xdt[0]);
-            }
+    /**
+     * Checks if the submitted iCalendar data is in fact, valid.
+     *
+     * An exception is thrown if it's not.
+     *
+     * @param resource|string $data
+     * @return void
+     */
+    protected function validateICalendar(&$data) {
+
+        // If it's a stream, we convert it to a string first.
+        if (is_resource($data)) {
+            $data = stream_get_contents($data);
         }
 
-        // Only need to grab duration if dtStart is set
-        if (!is_null($dtStart)) {
+        // Converting the data to unicode, if needed.
+        $data = Sabre_DAV_StringUtil::ensureUTF8($data);
 
-            $xduration = $xml->xpath($currentXPath.'/c:duration');
-            if (count($xduration)) {
-                $duration = Sabre_CalDAV_XMLUtil::parseICalendarDuration((string)$xduration[0]);
-            }
+        try {
+
+            $vobj = Sabre_VObject_Reader::read($data);
+
+        } catch (Sabre_VObject_ParseException $e) {
+
+            throw new Sabre_DAV_Exception_UnsupportedMediaType('This resource only supports valid iCalendar 2.0 data. Parse error: ' . $e->getMessage());
 
         }
 
-        if (!is_null($dtStart) && !is_null($duration)) {
+    }
 
-            // Comparision from RFC 4791:
-            // (start <= DTSTART+DURATION) AND ((end > DTSTART) OR (end >= DTSTART+DURATION))
+    /**
+     * This method handles POST requests to the schedule-outbox
+     *
+     * @param Sabre_CalDAV_Schedule_IOutbox $outboxNode
+     * @return void
+     */
+    public function outboxRequest(Sabre_CalDAV_Schedule_IOutbox $outboxNode) {
 
-            $end = clone $dtStart;
-            $end->modify($duration);
+        $originator = $this->server->httpRequest->getHeader('Originator');
+        $recipients = $this->server->httpRequest->getHeader('Recipient');
 
-            if( (is_null($filter['time-range']['start']) || $filter['time-range']['start'] <= $end) &&
-                (is_null($filter['time-range']['end']) || $filter['time-range']['end'] > $dtStart || $filter['time-range']['end'] >= $end) ) {
-                return true;
-            } else {
-                return false;
-            }
+        if (!$originator) {
+            throw new Sabre_DAV_Exception_BadRequest('The Originator: header must be specified when making POST requests');
+        } 
+        if (!$recipients) {
+            throw new Sabre_DAV_Exception_BadRequest('The Recipient: header must be specified when making POST requests');
+        } 
 
+        if (!preg_match('/^mailto:(.*)@(.*)$/', $originator)) {
+            throw new Sabre_DAV_Exception_BadRequest('Originator must start with mailto: and must be valid email address');
         }
+        $originator = substr($originator,7);
 
-        // Need to grab the DUE property
-        $xdt = $xml->xpath($currentXPath.'/c:due');
-        if (count($xdt)) {
-            // The due property can be both a date, or datetime property
-            if ((string)$xdt[0]['value']==='DATE') {
-                $isDateTime = false;
-            } else {
-                $isDateTime = true;
-            }
-            // Determining the timezone
-            if ($tzid = (string)$xdt[0]['tzid']) {
-                $tz = new DateTimeZone($tzid);
-            } else {
-                $tz = null;
-            }
-            if ($isDateTime) {
-                $due = Sabre_CalDAV_XMLUtil::parseICalendarDateTime((string)$xdt[0],$tz);
-            } else {
-                $due = Sabre_CalDAV_XMLUtil::parseICalendarDate((string)$xdt[0]);
+        $recipients = explode(',',$recipients);
+        foreach($recipients as $k=>$recipient) {
+
+            $recipient = trim($recipient);
+            if (!preg_match('/^mailto:(.*)@(.*)$/', $recipient)) { 
+                throw new Sabre_DAV_Exception_BadRequest('Recipients must start with mailto: and must be valid email address');
             }
+            $recipient = substr($recipient, 7);
+            $recipients[$k] = $recipient;
         }
 
-        if (!is_null($dtStart) && !is_null($due)) {
-
-            // Comparision from RFC 4791:
-            // ((start < DUE) OR (start <= DTSTART)) AND ((end > DTSTART) OR (end >= DUE))
-            
-            if( (is_null($filter['time-range']['start']) || $filter['time-range']['start'] < $due || $filter['time-range']['start'] < $dtstart) &&
-                (is_null($filter['time-range']['end'])   || $filter['time-range']['end'] >= $due) ) {
-                return true;
-            } else {
-                return false;
-            }
+        // We need to make sure that 'originator' matches one of the email 
+        // addresses of the selected principal.
+        $principal = $outboxNode->getOwner();
+        $props = $this->server->getProperties($principal,array(
+            '{' . self::NS_CALDAV . '}calendar-user-address-set',
+        ));
 
+        $addresses = array();
+        if (isset($props['{' . self::NS_CALDAV . '}calendar-user-address-set'])) {
+            $addresses = $props['{' . self::NS_CALDAV . '}calendar-user-address-set']->getHrefs();
         }
 
-        if (!is_null($dtStart)) {
-            
-            // Comparision from RFC 4791
-            // (start <= DTSTART)  AND (end > DTSTART)
-            if ( (is_null($filter['time-range']['start']) || $filter['time-range']['start'] <= $dtStart) &&
-                 (is_null($filter['time-range']['end'])   || $filter['time-range']['end'] > $dtStart) ) {
-                 return true;
-            } else {
-                return false;
-            }
+        if (!in_array('mailto:' . $originator, $addresses)) {
+            throw new Sabre_DAV_Exception_Forbidden('The addresses specified in the Originator header did not match any addresses in the owners calendar-user-address-set header');
+        }
 
+        try { 
+            $vObject = Sabre_VObject_Reader::read($this->server->httpRequest->getBody(true));
+        } catch (Sabre_VObject_ParseException $e) {
+            throw new Sabre_DAV_Exception_BadRequest('The request body must be a valid iCalendar object. Parse error: ' . $e->getMessage());
         }
 
-        if (!is_null($due)) {
-            
-            // Comparison from RFC 4791
-            // (start < DUE) AND (end >= DUE)
-            if ( (is_null($filter['time-range']['start']) || $filter['time-range']['start'] < $due) &&
-                 (is_null($filter['time-range']['end'])   || $filter['time-range']['end'] >= $due) ) {
-                 return true;
-            } else {
-                return false;
+        // Checking for the object type
+        $componentType = null;
+        foreach($vObject->getComponents() as $component) {
+            if ($component->name !== 'VTIMEZONE') {
+                $componentType = $component->name;
+                break;
             }
-
-        }
-        // Need to grab the COMPLETED property
-        $xdt = $xml->xpath($currentXPath.'/c:completed');
-        if (count($xdt)) {
-            $completed = Sabre_CalDAV_XMLUtil::parseICalendarDateTime((string)$xdt[0]);
         }
-        // Need to grab the CREATED property
-        $xdt = $xml->xpath($currentXPath.'/c:created');
-        if (count($xdt)) {
-            $created = Sabre_CalDAV_XMLUtil::parseICalendarDateTime((string)$xdt[0]);
+        if (is_null($componentType)) {
+            throw new Sabre_DAV_Exception_BadRequest('We expected at least one VTODO, VJOURNAL, VFREEBUSY or VEVENT component');
         }
 
-        if (!is_null($completed) && !is_null($created)) {
-            // Comparison from RFC 4791
-            // ((start <= CREATED) OR (start <= COMPLETED)) AND ((end >= CREATED) OR (end >= COMPLETED))
-            if( (is_null($filter['time-range']['start']) || $filter['time-range']['start'] <= $created || $filter['time-range']['start'] <= $completed) &&
-                (is_null($filter['time-range']['end'])   || $filter['time-range']['end'] >= $created   || $filter['time-range']['end'] >= $completed)) {
-                return true;
-            } else {
-                return false;
-            }
+        // Validating the METHOD
+        $method = strtoupper((string)$vObject->METHOD);
+        if (!$method) {
+            throw new Sabre_DAV_Exception_BadRequest('A METHOD property must be specified in iTIP messages');
         }
 
-        if (!is_null($completed)) {
-            // Comparison from RFC 4791
-            // (start <= COMPLETED) AND (end  >= COMPLETED)
-            if( (is_null($filter['time-range']['start']) || $filter['time-range']['start'] <= $completed) &&
-                (is_null($filter['time-range']['end'])   || $filter['time-range']['end'] >= $completed)) {
-                return true;
-            } else {
-                return false;
-            }
+        if (in_array($method, array('REQUEST','REPLY','ADD','CANCEL')) && $componentType==='VEVENT') {
+            $this->iMIPMessage($originator, $recipients, $vObject);
+            $this->server->httpResponse->sendStatus(200);
+            $this->server->httpResponse->sendBody('Messages sent');
+        } else {
+            throw new Sabre_DAV_Exception_NotImplemented('This iTIP method is currently not implemented');
         }
 
-        if (!is_null($created)) {
-            // Comparison from RFC 4791
-            // (end > CREATED)
-            if( (is_null($filter['time-range']['end']) || $filter['time-range']['end'] > $created) ) {
-                return true;
-            } else {
-                return false;
-            }
+    }
+
+    /**
+     * Sends an iMIP message by email.
+     * 
+     * @param string $originator 
+     * @param array $recipients 
+     * @param Sabre_VObject_Component $vObject 
+     * @return void
+     */
+    protected function iMIPMessage($originator, array $recipients, Sabre_VObject_Component $vObject) {
+
+        if (!$this->imipHandler) {
+            throw new Sabre_DAV_Exception_NotImplemented('No iMIP handler is setup on this server.');
         }
+        $this->imipHandler->sendMessage($originator, $recipients, $vObject); 
+
+    }
+
+    /**
+     * This method is used to generate HTML output for the
+     * Sabre_DAV_Browser_Plugin. This allows us to generate an interface users
+     * can use to create new calendars.
+     *
+     * @param Sabre_DAV_INode $node
+     * @param string $output
+     * @return bool
+     */
+    public function htmlActionsPanel(Sabre_DAV_INode $node, &$output) {
+
+        if (!$node instanceof Sabre_CalDAV_UserCalendars)
+            return;
+
+        $output.= '<tr><td colspan="2"><form method="post" action="">
+            <h3>Create new calendar</h3>
+            <input type="hidden" name="sabreAction" value="mkcalendar" />
+            <label>Name (uri):</label> <input type="text" name="name" /><br />
+            <label>Display name:</label> <input type="text" name="{DAV:}displayname" /><br />
+            <input type="submit" value="create" />
+            </form>
+            </td></tr>';
+
+        return false;
 
-        // Everything else is TRUE
-        return true;
+    }
+
+    /**
+     * This method allows us to intercept the 'mkcalendar' sabreAction. This
+     * action enables the user to create new calendars from the browser plugin.
+     *
+     * @param string $uri
+     * @param string $action
+     * @param array $postVars
+     * @return bool
+     */
+    public function browserPostAction($uri, $action, array $postVars) {
+
+        if ($action!=='mkcalendar')
+            return;
+
+        $resourceType = array('{DAV:}collection','{urn:ietf:params:xml:ns:caldav}calendar');
+        $properties = array();
+        if (isset($postVars['{DAV:}displayname'])) {
+            $properties['{DAV:}displayname'] = $postVars['{DAV:}displayname'];
+        }
+        $this->server->createCollection($uri . '/' . $postVars['name'],$resourceType,$properties);
+        return false;
 
     }
 
diff --git a/3rdparty/Sabre/CalDAV/Principal/Collection.php b/3rdparty/Sabre/CalDAV/Principal/Collection.php
index 13435b2448efc55a0f7b8439e6a8727174d2cfd7..abbefa5567a4c9f939fe7a9ce5faba22c749695b 100644
--- a/3rdparty/Sabre/CalDAV/Principal/Collection.php
+++ b/3rdparty/Sabre/CalDAV/Principal/Collection.php
@@ -4,23 +4,23 @@
  * Principal collection
  *
  * This is an alternative collection to the standard ACL principal collection.
- * This collection adds support for the calendar-proxy-read and 
- * calendar-proxy-write sub-principals, as defined by the caldav-proxy 
+ * This collection adds support for the calendar-proxy-read and
+ * calendar-proxy-write sub-principals, as defined by the caldav-proxy
  * specification.
  *
  * @package Sabre
  * @subpackage CalDAV
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
  * @author Evert Pot (http://www.rooftopsolutions.nl/) 
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
  */
 class Sabre_CalDAV_Principal_Collection extends Sabre_DAVACL_AbstractPrincipalCollection {
 
     /**
-     * Returns a child object based on principal information 
-     * 
-     * @param array $principalInfo 
-     * @return Sabre_CalDAV_Principal_User 
+     * Returns a child object based on principal information
+     *
+     * @param array $principalInfo
+     * @return Sabre_CalDAV_Principal_User
      */
     public function getChildForPrincipal(array $principalInfo) {
 
diff --git a/3rdparty/Sabre/CalDAV/Principal/ProxyRead.php b/3rdparty/Sabre/CalDAV/Principal/ProxyRead.php
index f531d85d1ffffacb2bf00101c942e0bb2b0953f3..4b3f035634a795f82ac33460ba9ccbf570b1a415 100644
--- a/3rdparty/Sabre/CalDAV/Principal/ProxyRead.php
+++ b/3rdparty/Sabre/CalDAV/Principal/ProxyRead.php
@@ -4,38 +4,38 @@
  * ProxyRead principal
  *
  * This class represents a principal group, hosted under the main principal.
- * This is needed to implement 'Calendar delegation' support. This class is 
+ * This is needed to implement 'Calendar delegation' support. This class is
  * instantiated by Sabre_CalDAV_Principal_User.
- * 
+ *
  * @package Sabre
  * @subpackage CalDAV
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
  * @author Evert Pot (http://www.rooftopsolutions.nl/) 
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
  */
 class Sabre_CalDAV_Principal_ProxyRead implements Sabre_DAVACL_IPrincipal {
 
     /**
-     * Principal information from the parent principal. 
-     * 
-     * @var array 
+     * Principal information from the parent principal.
+     *
+     * @var array
      */
     protected $principalInfo;
 
     /**
-     * Principal backend 
-     * 
-     * @var Sabre_DAVACL_IPrincipalBackend 
+     * Principal backend
+     *
+     * @var Sabre_DAVACL_IPrincipalBackend
      */
     protected $principalBackend;
 
     /**
      * Creates the object.
      *
-     * Note that you MUST supply the parent principal information. 
-     * 
-     * @param Sabre_DAVACL_IPrincipalBackend $principalBackend 
-     * @param array $principalInfo 
+     * Note that you MUST supply the parent principal information.
+     *
+     * @param Sabre_DAVACL_IPrincipalBackend $principalBackend
+     * @param array $principalInfo
      */
     public function __construct(Sabre_DAVACL_IPrincipalBackend $principalBackend, array $principalInfo) {
 
@@ -46,8 +46,8 @@ class Sabre_CalDAV_Principal_ProxyRead implements Sabre_DAVACL_IPrincipal {
 
     /**
      * Returns this principals name.
-     * 
-     * @return string 
+     *
+     * @return string
      */
     public function getName() {
 
@@ -56,13 +56,13 @@ class Sabre_CalDAV_Principal_ProxyRead implements Sabre_DAVACL_IPrincipal {
     }
 
     /**
-     * Returns the last modification time 
+     * Returns the last modification time
      *
-     * @return null 
+     * @return null
      */
     public function getLastModified() {
 
-        return null; 
+        return null;
 
     }
 
@@ -70,7 +70,7 @@ class Sabre_CalDAV_Principal_ProxyRead implements Sabre_DAVACL_IPrincipal {
      * Deletes the current node
      *
      * @throws Sabre_DAV_Exception_Forbidden
-     * @return void 
+     * @return void
      */
     public function delete() {
 
@@ -80,7 +80,7 @@ class Sabre_CalDAV_Principal_ProxyRead implements Sabre_DAVACL_IPrincipal {
 
     /**
      * Renames the node
-     * 
+     *
      * @throws Sabre_DAV_Exception_Forbidden
      * @param string $name The new name
      * @return void
@@ -93,11 +93,11 @@ class Sabre_CalDAV_Principal_ProxyRead implements Sabre_DAVACL_IPrincipal {
 
 
     /**
-     * Returns a list of altenative urls for a principal
-     * 
+     * Returns a list of alternative urls for a principal
+     *
      * This can for example be an email address, or ldap url.
-     * 
-     * @return array 
+     *
+     * @return array
      */
     public function getAlternateUriSet() {
 
@@ -106,41 +106,41 @@ class Sabre_CalDAV_Principal_ProxyRead implements Sabre_DAVACL_IPrincipal {
     }
 
     /**
-     * Returns the full principal url 
-     * 
-     * @return string 
+     * Returns the full principal url
+     *
+     * @return string
      */
     public function getPrincipalUrl() {
 
-        return $this->principalInfo['uri'] . '/' . $this->getName(); 
+        return $this->principalInfo['uri'] . '/' . $this->getName();
 
     }
 
     /**
      * Returns the list of group members
-     * 
+     *
      * If this principal is a group, this function should return
-     * all member principal uri's for the group. 
-     * 
+     * all member principal uri's for the group.
+     *
      * @return array
      */
     public function getGroupMemberSet() {
 
-        return $this->principalBackend->getGroupMemberSet($this->getPrincipalUrl()); 
+        return $this->principalBackend->getGroupMemberSet($this->getPrincipalUrl());
 
     }
 
     /**
      * Returns the list of groups this principal is member of
-     * 
+     *
      * If this principal is a member of a (list of) groups, this function
-     * should return a list of principal uri's for it's members. 
-     * 
-     * @return array 
+     * should return a list of principal uri's for it's members.
+     *
+     * @return array
      */
     public function getGroupMembership() {
 
-        return $this->principalBackend->getGroupMembership($this->getPrincipalUrl()); 
+        return $this->principalBackend->getGroupMembership($this->getPrincipalUrl());
 
     }
 
@@ -149,11 +149,11 @@ class Sabre_CalDAV_Principal_ProxyRead implements Sabre_DAVACL_IPrincipal {
      *
      * If this principal is a group, this method sets all the group members.
      * The list of members is always overwritten, never appended to.
-     * 
-     * This method should throw an exception if the members could not be set. 
-     * 
-     * @param array $principals 
-     * @return void 
+     *
+     * This method should throw an exception if the members could not be set.
+     *
+     * @param array $principals
+     * @return void
      */
     public function setGroupMemberSet(array $principals) {
 
@@ -165,9 +165,9 @@ class Sabre_CalDAV_Principal_ProxyRead implements Sabre_DAVACL_IPrincipal {
      * Returns the displayname
      *
      * This should be a human readable name for the principal.
-     * If none is available, return the nodename. 
-     * 
-     * @return string 
+     * If none is available, return the nodename.
+     *
+     * @return string
      */
     public function getDisplayName() {
 
diff --git a/3rdparty/Sabre/CalDAV/Principal/ProxyWrite.php b/3rdparty/Sabre/CalDAV/Principal/ProxyWrite.php
index 4d8face20607f51a3f81e449143bdace2708aff7..dd0c2e86edd70e5b8e7ef43bb3d0374482021d04 100644
--- a/3rdparty/Sabre/CalDAV/Principal/ProxyWrite.php
+++ b/3rdparty/Sabre/CalDAV/Principal/ProxyWrite.php
@@ -4,38 +4,38 @@
  * ProxyWrite principal
  *
  * This class represents a principal group, hosted under the main principal.
- * This is needed to implement 'Calendar delegation' support. This class is 
+ * This is needed to implement 'Calendar delegation' support. This class is
  * instantiated by Sabre_CalDAV_Principal_User.
- * 
+ *
  * @package Sabre
  * @subpackage CalDAV
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
  * @author Evert Pot (http://www.rooftopsolutions.nl/) 
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
  */
 class Sabre_CalDAV_Principal_ProxyWrite implements Sabre_DAVACL_IPrincipal {
 
     /**
-     * Parent principal information 
-     * 
-     * @var array 
+     * Parent principal information
+     *
+     * @var array
      */
     protected $principalInfo;
 
     /**
-     * Principal Backend 
-     * 
-     * @var Sabre_DAVACL_IPrincipalBackend 
+     * Principal Backend
+     *
+     * @var Sabre_DAVACL_IPrincipalBackend
      */
     protected $principalBackend;
 
     /**
      * Creates the object
      *
-     * Note that you MUST supply the parent principal information. 
-     * 
-     * @param Sabre_DAVACL_IPrincipalBackend $principalBackend 
-     * @param array $principalInfo 
+     * Note that you MUST supply the parent principal information.
+     *
+     * @param Sabre_DAVACL_IPrincipalBackend $principalBackend
+     * @param array $principalInfo
      */
     public function __construct(Sabre_DAVACL_IPrincipalBackend $principalBackend, array $principalInfo) {
 
@@ -46,8 +46,8 @@ class Sabre_CalDAV_Principal_ProxyWrite implements Sabre_DAVACL_IPrincipal {
 
     /**
      * Returns this principals name.
-     * 
-     * @return string 
+     *
+     * @return string
      */
     public function getName() {
 
@@ -56,13 +56,13 @@ class Sabre_CalDAV_Principal_ProxyWrite implements Sabre_DAVACL_IPrincipal {
     }
 
     /**
-     * Returns the last modification time 
+     * Returns the last modification time
      *
-     * @return null 
+     * @return null
      */
     public function getLastModified() {
 
-        return null; 
+        return null;
 
     }
 
@@ -70,7 +70,7 @@ class Sabre_CalDAV_Principal_ProxyWrite implements Sabre_DAVACL_IPrincipal {
      * Deletes the current node
      *
      * @throws Sabre_DAV_Exception_Forbidden
-     * @return void 
+     * @return void
      */
     public function delete() {
 
@@ -80,7 +80,7 @@ class Sabre_CalDAV_Principal_ProxyWrite implements Sabre_DAVACL_IPrincipal {
 
     /**
      * Renames the node
-     * 
+     *
      * @throws Sabre_DAV_Exception_Forbidden
      * @param string $name The new name
      * @return void
@@ -93,11 +93,11 @@ class Sabre_CalDAV_Principal_ProxyWrite implements Sabre_DAVACL_IPrincipal {
 
 
     /**
-     * Returns a list of altenative urls for a principal
-     * 
+     * Returns a list of alternative urls for a principal
+     *
      * This can for example be an email address, or ldap url.
-     * 
-     * @return array 
+     *
+     * @return array
      */
     public function getAlternateUriSet() {
 
@@ -106,41 +106,41 @@ class Sabre_CalDAV_Principal_ProxyWrite implements Sabre_DAVACL_IPrincipal {
     }
 
     /**
-     * Returns the full principal url 
-     * 
-     * @return string 
+     * Returns the full principal url
+     *
+     * @return string
      */
     public function getPrincipalUrl() {
 
-        return $this->principalInfo['uri'] . '/' . $this->getName(); 
+        return $this->principalInfo['uri'] . '/' . $this->getName();
 
     }
 
     /**
      * Returns the list of group members
-     * 
+     *
      * If this principal is a group, this function should return
-     * all member principal uri's for the group. 
-     * 
+     * all member principal uri's for the group.
+     *
      * @return array
      */
     public function getGroupMemberSet() {
 
-        return $this->principalBackend->getGroupMemberSet($this->getPrincipalUrl()); 
+        return $this->principalBackend->getGroupMemberSet($this->getPrincipalUrl());
 
     }
 
     /**
      * Returns the list of groups this principal is member of
-     * 
+     *
      * If this principal is a member of a (list of) groups, this function
-     * should return a list of principal uri's for it's members. 
-     * 
-     * @return array 
+     * should return a list of principal uri's for it's members.
+     *
+     * @return array
      */
     public function getGroupMembership() {
 
-        return $this->principalBackend->getGroupMembership($this->getPrincipalUrl()); 
+        return $this->principalBackend->getGroupMembership($this->getPrincipalUrl());
 
     }
 
@@ -149,11 +149,11 @@ class Sabre_CalDAV_Principal_ProxyWrite implements Sabre_DAVACL_IPrincipal {
      *
      * If this principal is a group, this method sets all the group members.
      * The list of members is always overwritten, never appended to.
-     * 
-     * This method should throw an exception if the members could not be set. 
-     * 
-     * @param array $principals 
-     * @return void 
+     *
+     * This method should throw an exception if the members could not be set.
+     *
+     * @param array $principals
+     * @return void
      */
     public function setGroupMemberSet(array $principals) {
 
@@ -165,9 +165,9 @@ class Sabre_CalDAV_Principal_ProxyWrite implements Sabre_DAVACL_IPrincipal {
      * Returns the displayname
      *
      * This should be a human readable name for the principal.
-     * If none is available, return the nodename. 
-     * 
-     * @return string 
+     * If none is available, return the nodename.
+     *
+     * @return string
      */
     public function getDisplayName() {
 
diff --git a/3rdparty/Sabre/CalDAV/Principal/User.php b/3rdparty/Sabre/CalDAV/Principal/User.php
index 034629b89b3154006e4756d3ffe614df8ca850b6..8453b877a73da3762382110378cf38aa91aeb65b 100644
--- a/3rdparty/Sabre/CalDAV/Principal/User.php
+++ b/3rdparty/Sabre/CalDAV/Principal/User.php
@@ -1,25 +1,25 @@
 <?php
 
 /**
- * CalDAV principal 
+ * CalDAV principal
  *
- * This is a standard user-principal for CalDAV. This principal is also a 
- * collection and returns the caldav-proxy-read and caldav-proxy-write child 
+ * This is a standard user-principal for CalDAV. This principal is also a
+ * collection and returns the caldav-proxy-read and caldav-proxy-write child
  * principals.
- * 
+ *
  * @package Sabre
  * @subpackage CalDAV
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
  * @author Evert Pot (http://www.rooftopsolutions.nl/) 
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
  */
 class Sabre_CalDAV_Principal_User extends Sabre_DAVACL_Principal implements Sabre_DAV_ICollection {
 
     /**
-     * Creates a new file in the directory 
-     * 
-     * @param string $name Name of the file 
-     * @param resource $data Initial payload, passed as a readable stream resource. 
+     * Creates a new file in the directory
+     *
+     * @param string $name Name of the file
+     * @param resource $data Initial payload, passed as a readable stream resource.
      * @throws Sabre_DAV_Exception_Forbidden
      * @return void
      */
@@ -30,9 +30,9 @@ class Sabre_CalDAV_Principal_User extends Sabre_DAVACL_Principal implements Sabr
     }
 
     /**
-     * Creates a new subdirectory 
-     * 
-     * @param string $name 
+     * Creates a new subdirectory
+     *
+     * @param string $name
      * @throws Sabre_DAV_Exception_Forbidden
      * @return void
      */
@@ -43,45 +43,60 @@ class Sabre_CalDAV_Principal_User extends Sabre_DAVACL_Principal implements Sabr
     }
 
     /**
-     * Returns a specific child node, referenced by its name 
-     * 
-     * @param string $name 
-     * @return Sabre_DAV_INode 
+     * Returns a specific child node, referenced by its name
+     *
+     * @param string $name
+     * @return Sabre_DAV_INode
      */
     public function getChild($name) {
 
+        $principal = $this->principalBackend->getPrincipalByPath($this->getPrincipalURL() . '/' . $name);
+        if (!$principal) {
+            throw new Sabre_DAV_Exception_NotFound('Node with name ' . $name . ' was not found');
+        }
         if ($name === 'calendar-proxy-read')
             return new Sabre_CalDAV_Principal_ProxyRead($this->principalBackend, $this->principalProperties);
 
         if ($name === 'calendar-proxy-write')
             return new Sabre_CalDAV_Principal_ProxyWrite($this->principalBackend, $this->principalProperties);
 
-        throw new Sabre_DAV_Exception_FileNotFound('Node with name ' . $name . ' was not found');
+        throw new Sabre_DAV_Exception_NotFound('Node with name ' . $name . ' was not found');
 
     }
 
     /**
-     * Returns an array with all the child nodes 
-     * 
-     * @return Sabre_DAV_INode[] 
+     * Returns an array with all the child nodes
+     *
+     * @return Sabre_DAV_INode[]
      */
     public function getChildren() {
 
-        return array(
-            new Sabre_CalDAV_Principal_ProxyRead($this->principalBackend, $this->principalProperties),
-            new Sabre_CalDAV_Principal_ProxyWrite($this->principalBackend, $this->principalProperties),
-        );
+        $r = array();
+        if ($this->principalBackend->getPrincipalByPath($this->getPrincipalURL() . '/calendar-proxy-read')) {
+            $r[] = new Sabre_CalDAV_Principal_ProxyRead($this->principalBackend, $this->principalProperties);
+        }
+        if ($this->principalBackend->getPrincipalByPath($this->getPrincipalURL() . '/calendar-proxy-write')) {
+            $r[] = new Sabre_CalDAV_Principal_ProxyWrite($this->principalBackend, $this->principalProperties);
+        }
+
+        return $r;
 
     }
 
     /**
-     * Checks if a child-node with the specified name exists 
-     * 
-     * @return bool 
+     * Returns whether or not the child node exists
+     *
+     * @param string $name
+     * @return bool
      */
     public function childExists($name) {
 
-        return $name === 'calendar-proxy-read' ||  $name === 'calendar-proxy-write';
+        try {
+            $this->getChild($name);
+            return true;
+        } catch (Sabre_DAV_Exception_NotFound $e) {
+            return false;
+        }
 
     }
 
@@ -89,33 +104,28 @@ class Sabre_CalDAV_Principal_User extends Sabre_DAVACL_Principal implements Sabr
      * Returns a list of ACE's for this node.
      *
      * Each ACE has the following properties:
-     *   * 'privilege', a string such as {DAV:}read or {DAV:}write. These are 
+     *   * 'privilege', a string such as {DAV:}read or {DAV:}write. These are
      *     currently the only supported privileges
      *   * 'principal', a url to the principal who owns the node
-     *   * 'protected' (optional), indicating that this ACE is not allowed to 
-     *      be updated. 
-     * 
-     * @return array 
+     *   * 'protected' (optional), indicating that this ACE is not allowed to
+     *      be updated.
+     *
+     * @return array
      */
     public function getACL() {
 
-        return array(
-            array(
-                'privilege' => '{DAV:}read',
-                'principal' => $this->principalProperties['uri'],
-                'protected' => true,
-            ),
-            array(
-                'privilege' => '{DAV:}read',
-                'principal' => $this->principalProperties['uri'] . '/calendar-proxy-read',
-                'protected' => true,
-            ),
-            array(
-                'privilege' => '{DAV:}read',
-                'principal' => $this->principalProperties['uri'] . '/calendar-proxy-write',
-                'protected' => true,
-            ),
+        $acl = parent::getACL();
+        $acl[] = array(
+            'privilege' => '{DAV:}read',
+            'principal' => $this->principalProperties['uri'] . '/calendar-proxy-read',
+            'protected' => true,
+        );
+        $acl[] = array(
+            'privilege' => '{DAV:}read',
+            'principal' => $this->principalProperties['uri'] . '/calendar-proxy-write',
+            'protected' => true,
         );
+        return $acl;
 
     }
 
diff --git a/3rdparty/Sabre/CalDAV/Property/SupportedCalendarComponentSet.php b/3rdparty/Sabre/CalDAV/Property/SupportedCalendarComponentSet.php
index 1bbaca6b8a75b2c57aafbc6ddf1f461af95b4f9e..2ea078d7dac03cbe8e241690739ad7c02bb17676 100644
--- a/3rdparty/Sabre/CalDAV/Property/SupportedCalendarComponentSet.php
+++ b/3rdparty/Sabre/CalDAV/Property/SupportedCalendarComponentSet.php
@@ -3,40 +3,40 @@
 /**
  * Supported component set property
  *
- * This property is a representation of the supported-calendar_component-set 
+ * This property is a representation of the supported-calendar_component-set
  * property in the CalDAV namespace. It simply requires an array of components,
  * such as VEVENT, VTODO
  *
  * @package Sabre
  * @subpackage CalDAV
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
  * @author Evert Pot (http://www.rooftopsolutions.nl/) 
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
  */
 class Sabre_CalDAV_Property_SupportedCalendarComponentSet extends Sabre_DAV_Property {
 
     /**
-     * List of supported components, such as "VEVENT, VTODO" 
-     * 
-     * @var array 
+     * List of supported components, such as "VEVENT, VTODO"
+     *
+     * @var array
      */
     private $components;
 
     /**
-     * Creates the property 
-     * 
-     * @param array $components 
+     * Creates the property
+     *
+     * @param array $components
      */
     public function __construct(array $components) {
 
-       $this->components = $components; 
+       $this->components = $components;
 
     }
 
     /**
-     * Returns the list of supported components 
-     * 
-     * @return array 
+     * Returns the list of supported components
+     *
+     * @return array
      */
     public function getValue() {
 
@@ -45,10 +45,10 @@ class Sabre_CalDAV_Property_SupportedCalendarComponentSet extends Sabre_DAV_Prop
     }
 
     /**
-     * Serializes the property in a DOMDocument 
-     * 
-     * @param Sabre_DAV_Server $server 
-     * @param DOMElement $node 
+     * Serializes the property in a DOMDocument
+     *
+     * @param Sabre_DAV_Server $server
+     * @param DOMElement $node
      * @return void
      */
     public function serialize(Sabre_DAV_Server $server,DOMElement $node) {
@@ -58,7 +58,7 @@ class Sabre_CalDAV_Property_SupportedCalendarComponentSet extends Sabre_DAV_Prop
 
             $xcomp = $doc->createElement('cal:comp');
             $xcomp->setAttribute('name',$component);
-            $node->appendChild($xcomp); 
+            $node->appendChild($xcomp);
 
        }
 
@@ -66,9 +66,9 @@ class Sabre_CalDAV_Property_SupportedCalendarComponentSet extends Sabre_DAV_Prop
 
     /**
      * Unserializes the DOMElement back into a Property class.
-     * 
-     * @param DOMElement $node 
-     * @return void
+     *
+     * @param DOMElement $node
+     * @return Sabre_CalDAV_Property_SupportedCalendarComponentSet
      */
     static function unserialize(DOMElement $node) {
 
diff --git a/3rdparty/Sabre/CalDAV/Property/SupportedCalendarData.php b/3rdparty/Sabre/CalDAV/Property/SupportedCalendarData.php
index 5010ee6d5257ad3085b646e95157d3870506279a..1d848dd5cf68acaa05977a0292297a559dff316a 100644
--- a/3rdparty/Sabre/CalDAV/Property/SupportedCalendarData.php
+++ b/3rdparty/Sabre/CalDAV/Property/SupportedCalendarData.php
@@ -9,17 +9,17 @@
  *
  * @package Sabre
  * @subpackage CalDAV
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
  * @author Evert Pot (http://www.rooftopsolutions.nl/) 
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
  */
 class Sabre_CalDAV_Property_SupportedCalendarData extends Sabre_DAV_Property {
 
     /**
-     * Serializes the property in a DOMDocument 
-     * 
-     * @param Sabre_DAV_Server $server 
-     * @param DOMElement $node 
+     * Serializes the property in a DOMDocument
+     *
+     * @param Sabre_DAV_Server $server
+     * @param DOMElement $node
      * @return void
      */
     public function serialize(Sabre_DAV_Server $server,DOMElement $node) {
@@ -32,7 +32,7 @@ class Sabre_CalDAV_Property_SupportedCalendarData extends Sabre_DAV_Property {
         $caldata->setAttribute('content-type','text/calendar');
         $caldata->setAttribute('version','2.0');
 
-        $node->appendChild($caldata); 
+        $node->appendChild($caldata);
     }
 
 }
diff --git a/3rdparty/Sabre/CalDAV/Property/SupportedCollationSet.php b/3rdparty/Sabre/CalDAV/Property/SupportedCollationSet.php
index e585e9db3d877b5dc8e1d67ff7961791ac98800d..24e84d4c17d99815fba07ec9d540787f74f68e71 100644
--- a/3rdparty/Sabre/CalDAV/Property/SupportedCollationSet.php
+++ b/3rdparty/Sabre/CalDAV/Property/SupportedCollationSet.php
@@ -4,27 +4,27 @@
  * supported-collation-set property
  *
  * This property is a representation of the supported-collation-set property
- * in the CalDAV namespace. 
+ * in the CalDAV namespace.
  *
  * @package Sabre
  * @subpackage CalDAV
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
  * @author Evert Pot (http://www.rooftopsolutions.nl/) 
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
  */
 class Sabre_CalDAV_Property_SupportedCollationSet extends Sabre_DAV_Property {
 
     /**
-     * Serializes the property in a DOM document 
-     * 
-     * @param Sabre_DAV_Server $server 
-     * @param DOMElement $node 
+     * Serializes the property in a DOM document
+     *
+     * @param Sabre_DAV_Server $server
+     * @param DOMElement $node
      * @return void
      */
     public function serialize(Sabre_DAV_Server $server,DOMElement $node) {
 
         $doc = $node->ownerDocument;
-        
+
         $prefix = $node->lookupPrefix('urn:ietf:params:xml:ns:caldav');
         if (!$prefix) $prefix = 'cal';
 
diff --git a/3rdparty/Sabre/CalDAV/Schedule/IMip.php b/3rdparty/Sabre/CalDAV/Schedule/IMip.php
new file mode 100644
index 0000000000000000000000000000000000000000..37e75fcc4a71c2626922319fef90a971ce6a4460
--- /dev/null
+++ b/3rdparty/Sabre/CalDAV/Schedule/IMip.php
@@ -0,0 +1,104 @@
+<?php
+
+/**
+ * iMIP handler.
+ *
+ * This class is responsible for sending out iMIP messages. iMIP is the
+ * email-based transport for iTIP. iTIP deals with scheduling operations for
+ * iCalendar objects.
+ *
+ * If you want to customize the email that gets sent out, you can do so by
+ * extending this class and overriding the sendMessage method.
+ *
+ * @package Sabre
+ * @subpackage CalDAV
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
+ * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
+ */
+class Sabre_CalDAV_Schedule_IMip {
+
+    /**
+     * Email address used in From: header.
+     *
+     * @var string
+     */
+    protected $senderEmail;
+
+    /**
+     * Creates the email handler.
+     *
+     * @param string $senderEmail. The 'senderEmail' is the email that shows up
+     *                             in the 'From:' address. This should
+     *                             generally be some kind of no-reply email
+     *                             address you own.
+     */
+    public function __construct($senderEmail) {
+
+        $this->senderEmail = $senderEmail;
+
+    }
+
+    /**
+     * Sends one or more iTip messages through email.
+     *
+     * @param string $originator
+     * @param array $recipients
+     * @param Sabre_VObject_Component $vObject
+     * @return void
+     */
+    public function sendMessage($originator, array $recipients, Sabre_VObject_Component $vObject) {
+
+        foreach($recipients as $recipient) {
+
+            $to = $recipient;
+            $replyTo = $originator;
+            $subject = 'SabreDAV iTIP message';
+
+            switch(strtoupper($vObject->METHOD)) {
+                case 'REPLY' :
+                    $subject = 'Response for: ' . $vObject->VEVENT->SUMMARY;
+                    break;
+                case 'REQUEST' :
+                    $subject = 'Invitation for: ' .$vObject->VEVENT->SUMMARY;
+                    break;
+                case 'CANCEL' :
+                    $subject = 'Cancelled event: ' . $vObject->VEVENT->SUMMARY;
+                    break;
+            }
+
+            $headers = array();
+            $headers[] = 'Reply-To: ' . $replyTo;
+            $headers[] = 'From: ' . $this->senderEmail;
+            $headers[] = 'Content-Type: text/calendar; method=' . (string)$vObject->method . '; charset=utf-8';
+            if (Sabre_DAV_Server::$exposeVersion) {
+                $headers[] = 'X-Sabre-Version: ' . Sabre_DAV_Version::VERSION . '-' . Sabre_DAV_Version::STABILITY;
+            }
+
+            $vcalBody = $vObject->serialize();
+
+            $this->mail($to, $subject, $vcalBody, $headers);
+
+        }
+
+    }
+
+    /**
+     * This function is reponsible for sending the actual email.
+     *
+     * @param string $to Recipient email address
+     * @param string $subject Subject of the email
+     * @param string $body iCalendar body
+     * @param array $headers List of headers
+     * @return void
+     */
+    protected function mail($to, $subject, $body, array $headers) {
+
+        mail($to, $subject, $body, implode("\r\n", $headers));
+
+    }
+
+
+}
+
+?>
diff --git a/3rdparty/Sabre/CalDAV/Schedule/IOutbox.php b/3rdparty/Sabre/CalDAV/Schedule/IOutbox.php
new file mode 100644
index 0000000000000000000000000000000000000000..46d77514bc048ba965fa091a84bd19233c5404f4
--- /dev/null
+++ b/3rdparty/Sabre/CalDAV/Schedule/IOutbox.php
@@ -0,0 +1,16 @@
+<?php
+
+/**
+ * Implement this interface to have a node be recognized as a CalDAV scheduling
+ * outbox.
+ *
+ * @package Sabre
+ * @subpackage CalDAV
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
+ * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
+ */
+interface Sabre_CalDAV_Schedule_IOutbox extends Sabre_DAV_ICollection, Sabre_DAVACL_IACL {
+
+
+}
diff --git a/3rdparty/Sabre/CalDAV/Schedule/Outbox.php b/3rdparty/Sabre/CalDAV/Schedule/Outbox.php
new file mode 100644
index 0000000000000000000000000000000000000000..014c37230d194a8bc2fb9efa5b4bb7b913b2a127
--- /dev/null
+++ b/3rdparty/Sabre/CalDAV/Schedule/Outbox.php
@@ -0,0 +1,152 @@
+<?php
+
+/**
+ * The CalDAV scheduling outbox
+ *
+ * The outbox is mainly used as an endpoint in the tree for a client to do
+ * free-busy requests. This functionality is completely handled by the
+ * Scheduling plugin, so this object is actually mostly static.
+ *
+ * @package Sabre
+ * @subpackage CalDAV
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
+ * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
+ */
+class Sabre_CalDAV_Schedule_Outbox extends Sabre_DAV_Directory implements Sabre_CalDAV_Schedule_IOutbox {
+
+    /**
+     * The principal Uri
+     *
+     * @var string
+     */
+    protected $principalUri;
+
+    /**
+     * Constructor
+     *
+     * @param string $principalUri
+     */
+    public function __construct($principalUri) {
+
+        $this->principalUri = $principalUri;
+
+    }
+
+    /**
+     * Returns the name of the node.
+     *
+     * This is used to generate the url.
+     *
+     * @return string
+     */
+    public function getName() {
+
+        return 'outbox';
+
+    }
+
+    /**
+     * Returns an array with all the child nodes
+     *
+     * @return Sabre_DAV_INode[]
+     */
+    public function getChildren() {
+
+        return array();
+
+    }
+
+    /**
+     * Returns the owner principal
+     *
+     * This must be a url to a principal, or null if there's no owner
+     *
+     * @return string|null
+     */
+    public function getOwner() {
+
+        return $this->principalUri;
+
+    }
+
+    /**
+     * Returns a group principal
+     *
+     * This must be a url to a principal, or null if there's no owner
+     *
+     * @return string|null
+     */
+    public function getGroup() {
+
+        return null;
+
+    }
+
+    /**
+     * Returns a list of ACE's for this node.
+     *
+     * Each ACE has the following properties:
+     *   * 'privilege', a string such as {DAV:}read or {DAV:}write. These are
+     *     currently the only supported privileges
+     *   * 'principal', a url to the principal who owns the node
+     *   * 'protected' (optional), indicating that this ACE is not allowed to
+     *      be updated.
+     *
+     * @return array
+     */
+    public function getACL() {
+
+        return array(
+            array(
+                'privilege' => '{' . Sabre_CalDAV_Plugin::NS_CALDAV . '}schedule-query-freebusy',
+                'principal' => $this->getOwner(),
+                'protected' => true,
+            ),
+            array(
+                'privilege' => '{DAV:}read',
+                'principal' => $this->getOwner(),
+                'protected' => true,
+            ),
+        );
+
+    }
+
+    /**
+     * Updates the ACL
+     *
+     * This method will receive a list of new ACE's.
+     *
+     * @param array $acl
+     * @return void
+     */
+    public function setACL(array $acl) {
+
+        throw new Sabre_DAV_Exception_MethodNotAllowed('You\'re not allowed to update the ACL');
+
+    }
+
+    /**
+     * Returns the list of supported privileges for this node.
+     *
+     * The returned data structure is a list of nested privileges.
+     * See Sabre_DAVACL_Plugin::getDefaultSupportedPrivilegeSet for a simple
+     * standard structure.
+     *
+     * If null is returned from this method, the default privilege set is used,
+     * which is fine for most common usecases.
+     *
+     * @return array|null
+     */
+    public function getSupportedPrivilegeSet() {
+
+        $default = Sabre_DAVACL_Plugin::getDefaultSupportedPrivilegeSet();
+        $default['aggregates'][] = array(
+            'privilege' => '{' . Sabre_CalDAV_Plugin::NS_CALDAV . '}schedule-query-freebusy',
+        );
+
+        return $default;
+
+    }
+
+}
diff --git a/3rdparty/Sabre/CalDAV/Server.php b/3rdparty/Sabre/CalDAV/Server.php
index 969d69c6279a262286d1453d960a8da8aefbb29d..325e3d80a7fd081065ab216dd528c0b3927c966e 100644
--- a/3rdparty/Sabre/CalDAV/Server.php
+++ b/3rdparty/Sabre/CalDAV/Server.php
@@ -3,17 +3,20 @@
 /**
  * CalDAV server
  *
+ * Deprecated! Warning: This class is now officially deprecated
+ *
  * This script is a convenience script. It quickly sets up a WebDAV server
  * with caldav and ACL support, and it creates the root 'principals' and
  * 'calendars' collections.
  *
- * Note that if you plan to do anything moderately complex, you are advised to 
- * not subclass this server, but use Sabre_DAV_Server directly instead. This 
+ * Note that if you plan to do anything moderately complex, you are advised to
+ * not subclass this server, but use Sabre_DAV_Server directly instead. This
  * class is nothing more than an 'easy setup'.
- * 
+ *
  * @package Sabre
  * @subpackage CalDAV
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
+ * @deprecated Don't use this class anymore, it will be removed in version 1.7.
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
  * @author Evert Pot (http://www.rooftopsolutions.nl/) 
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
  */
@@ -22,17 +25,17 @@ class Sabre_CalDAV_Server extends Sabre_DAV_Server {
     /**
      * The authentication realm
      *
-     * Note that if this changes, the hashes in the auth backend must also 
-     * be recalculated. 
-     * 
+     * Note that if this changes, the hashes in the auth backend must also
+     * be recalculated.
+     *
      * @var string
      */
     public $authRealm = 'SabreDAV';
 
     /**
      * Sets up the object. A PDO object must be passed to setup all the backends.
-     * 
-     * @param PDO $pdo 
+     *
+     * @param PDO $pdo
      */
     public function __construct(PDO $pdo) {
 
diff --git a/3rdparty/Sabre/CalDAV/UserCalendars.php b/3rdparty/Sabre/CalDAV/UserCalendars.php
index f52d65e9a73f222e325ec7695374ae4a0f93ffcb..b8d3f0573fa4c9c2b43084b1a63937aaf137b33f 100644
--- a/3rdparty/Sabre/CalDAV/UserCalendars.php
+++ b/3rdparty/Sabre/CalDAV/UserCalendars.php
@@ -1,68 +1,68 @@
 <?php
 
 /**
- * The UserCalenders class contains all calendars associated to one user 
- * 
+ * The UserCalenders class contains all calendars associated to one user
+ *
  * @package Sabre
  * @subpackage CalDAV
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
  * @author Evert Pot (http://www.rooftopsolutions.nl/) 
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
  */
 class Sabre_CalDAV_UserCalendars implements Sabre_DAV_IExtendedCollection, Sabre_DAVACL_IACL {
 
     /**
-     * Principal backend 
-     * 
+     * Principal backend
+     *
      * @var Sabre_DAVACL_IPrincipalBackend
      */
     protected $principalBackend;
 
     /**
      * CalDAV backend
-     * 
+     *
      * @var Sabre_CalDAV_Backend_Abstract
      */
     protected $caldavBackend;
 
     /**
-     * Principal information 
-     * 
-     * @var array 
+     * Principal information
+     *
+     * @var array
      */
     protected $principalInfo;
-    
+
     /**
-     * Constructor 
-     * 
+     * Constructor
+     *
      * @param Sabre_DAVACL_IPrincipalBackend $principalBackend
-     * @param Sabre_CalDAV_Backend_Abstract $caldavBackend 
-     * @param mixed $userUri 
+     * @param Sabre_CalDAV_Backend_Abstract $caldavBackend
+     * @param mixed $userUri
      */
     public function __construct(Sabre_DAVACL_IPrincipalBackend $principalBackend, Sabre_CalDAV_Backend_Abstract $caldavBackend, $userUri) {
 
         $this->principalBackend = $principalBackend;
         $this->caldavBackend = $caldavBackend;
         $this->principalInfo = $principalBackend->getPrincipalByPath($userUri);
-       
+
     }
 
     /**
-     * Returns the name of this object 
-     * 
+     * Returns the name of this object
+     *
      * @return string
      */
     public function getName() {
-      
+
         list(,$name) = Sabre_DAV_URLUtil::splitPath($this->principalInfo['uri']);
-        return $name; 
+        return $name;
 
     }
 
     /**
-     * Updates the name of this object 
-     * 
-     * @param string $name 
+     * Updates the name of this object
+     *
+     * @param string $name
      * @return void
      */
     public function setName($name) {
@@ -72,8 +72,8 @@ class Sabre_CalDAV_UserCalendars implements Sabre_DAV_IExtendedCollection, Sabre
     }
 
     /**
-     * Deletes this object 
-     * 
+     * Deletes this object
+     *
      * @return void
      */
     public function delete() {
@@ -83,13 +83,13 @@ class Sabre_CalDAV_UserCalendars implements Sabre_DAV_IExtendedCollection, Sabre
     }
 
     /**
-     * Returns the last modification date 
-     * 
-     * @return int 
+     * Returns the last modification date
+     *
+     * @return int
      */
     public function getLastModified() {
 
-        return null; 
+        return null;
 
     }
 
@@ -97,9 +97,9 @@ class Sabre_CalDAV_UserCalendars implements Sabre_DAV_IExtendedCollection, Sabre
      * Creates a new file under this object.
      *
      * This is currently not allowed
-     * 
-     * @param string $filename 
-     * @param resource $data 
+     *
+     * @param string $filename
+     * @param resource $data
      * @return void
      */
     public function createFile($filename, $data=null) {
@@ -112,8 +112,8 @@ class Sabre_CalDAV_UserCalendars implements Sabre_DAV_IExtendedCollection, Sabre
      * Creates a new directory under this object.
      *
      * This is currently not allowed.
-     * 
-     * @param string $filename 
+     *
+     * @param string $filename
      * @return void
      */
     public function createDirectory($filename) {
@@ -123,11 +123,11 @@ class Sabre_CalDAV_UserCalendars implements Sabre_DAV_IExtendedCollection, Sabre
     }
 
     /**
-     * Returns a single calendar, by name 
-     * 
+     * Returns a single calendar, by name
+     *
      * @param string $name
      * @todo needs optimizing
-     * @return Sabre_CalDAV_Calendar 
+     * @return Sabre_CalDAV_Calendar
      */
     public function getChild($name) {
 
@@ -136,22 +136,22 @@ class Sabre_CalDAV_UserCalendars implements Sabre_DAV_IExtendedCollection, Sabre
                 return $child;
 
         }
-        throw new Sabre_DAV_Exception_FileNotFound('Calendar with name \'' . $name . '\' could not be found');
+        throw new Sabre_DAV_Exception_NotFound('Calendar with name \'' . $name . '\' could not be found');
 
     }
 
     /**
      * Checks if a calendar exists.
-     * 
+     *
      * @param string $name
      * @todo needs optimizing
-     * @return bool 
+     * @return bool
      */
     public function childExists($name) {
 
         foreach($this->getChildren() as $child) {
             if ($name==$child->getName())
-                return true; 
+                return true;
 
         }
         return false;
@@ -160,8 +160,8 @@ class Sabre_CalDAV_UserCalendars implements Sabre_DAV_IExtendedCollection, Sabre
 
     /**
      * Returns a list of calendars
-     * 
-     * @return array 
+     *
+     * @return array
      */
     public function getChildren() {
 
@@ -170,15 +170,17 @@ class Sabre_CalDAV_UserCalendars implements Sabre_DAV_IExtendedCollection, Sabre
         foreach($calendars as $calendar) {
             $objs[] = new Sabre_CalDAV_Calendar($this->principalBackend, $this->caldavBackend, $calendar);
         }
+        $objs[] = new Sabre_CalDAV_Schedule_Outbox($this->principalInfo['uri']);
         return $objs;
 
     }
 
     /**
      * Creates a new calendar
-     * 
-     * @param string $name 
-     * @param string $properties 
+     *
+     * @param string $name
+     * @param array $resourceType
+     * @param array $properties
      * @return void
      */
     public function createExtendedCollection($name, array $resourceType, array $properties) {
@@ -193,8 +195,8 @@ class Sabre_CalDAV_UserCalendars implements Sabre_DAV_IExtendedCollection, Sabre
     /**
      * Returns the owner principal
      *
-     * This must be a url to a principal, or null if there's no owner 
-     * 
+     * This must be a url to a principal, or null if there's no owner
+     *
      * @return string|null
      */
     public function getOwner() {
@@ -207,8 +209,8 @@ class Sabre_CalDAV_UserCalendars implements Sabre_DAV_IExtendedCollection, Sabre
      * Returns a group principal
      *
      * This must be a url to a principal, or null if there's no owner
-     * 
-     * @return string|null 
+     *
+     * @return string|null
      */
     public function getGroup() {
 
@@ -220,13 +222,13 @@ class Sabre_CalDAV_UserCalendars implements Sabre_DAV_IExtendedCollection, Sabre
      * Returns a list of ACE's for this node.
      *
      * Each ACE has the following properties:
-     *   * 'privilege', a string such as {DAV:}read or {DAV:}write. These are 
+     *   * 'privilege', a string such as {DAV:}read or {DAV:}write. These are
      *     currently the only supported privileges
      *   * 'principal', a url to the principal who owns the node
-     *   * 'protected' (optional), indicating that this ACE is not allowed to 
-     *      be updated. 
-     * 
-     * @return array 
+     *   * 'protected' (optional), indicating that this ACE is not allowed to
+     *      be updated.
+     *
+     * @return array
      */
     public function getACL() {
 
@@ -264,9 +266,9 @@ class Sabre_CalDAV_UserCalendars implements Sabre_DAV_IExtendedCollection, Sabre
     /**
      * Updates the ACL
      *
-     * This method will receive a list of new ACE's. 
-     * 
-     * @param array $acl 
+     * This method will receive a list of new ACE's.
+     *
+     * @param array $acl
      * @return void
      */
     public function setACL(array $acl) {
@@ -275,6 +277,22 @@ class Sabre_CalDAV_UserCalendars implements Sabre_DAV_IExtendedCollection, Sabre
 
     }
 
+    /**
+     * Returns the list of supported privileges for this node.
+     *
+     * The returned data structure is a list of nested privileges.
+     * See Sabre_DAVACL_Plugin::getDefaultSupportedPrivilegeSet for a simple
+     * standard structure.
+     *
+     * If null is returned from this method, the default privilege set is used,
+     * which is fine for most common usecases.
+     *
+     * @return array|null
+     */
+    public function getSupportedPrivilegeSet() {
+
+        return null;
 
+    }
 
 }
diff --git a/3rdparty/Sabre/CalDAV/Version.php b/3rdparty/Sabre/CalDAV/Version.php
index df8fe1f6bd6fba8d724939a0ed3d9fe18014fac4..939e903c89f87830b572678b5619f413127c0f78 100644
--- a/3rdparty/Sabre/CalDAV/Version.php
+++ b/3rdparty/Sabre/CalDAV/Version.php
@@ -2,10 +2,10 @@
 
 /**
  * This class contains the Sabre_CalDAV version constants.
- * 
+ *
  * @package Sabre
  * @subpackage CalDAV 
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
  * @author Evert Pot (http://www.rooftopsolutions.nl/)
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
  */
@@ -14,7 +14,7 @@ class Sabre_CalDAV_Version {
     /**
      * Full version number
      */
-    const VERSION = '1.5.3';
+    const VERSION = '1.6.2';
 
     /**
      * Stability : alpha, beta, stable
diff --git a/3rdparty/Sabre/CalDAV/XMLUtil.php b/3rdparty/Sabre/CalDAV/XMLUtil.php
deleted file mode 100644
index bf349a36aae6f13418dd7f25fd1710bcc3975750..0000000000000000000000000000000000000000
--- a/3rdparty/Sabre/CalDAV/XMLUtil.php
+++ /dev/null
@@ -1,208 +0,0 @@
-<?php
-
-/**
- * XML utilities for CalDAV 
- *
- * This class contains a few static methods used for parsing certain CalDAV 
- * requests.
- *
- * @package Sabre
- * @subpackage CalDAV
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
- * @author Evert Pot (http://www.rooftopsolutions.nl/) 
- * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
- */
-class Sabre_CalDAV_XMLUtil {
-
-    /**
-     * This function parses the calendar-query report request body
-     *
-     * The body is quite complicated, so we're turning it into a PHP
-     * array.
-     *
-     * The resulting associative array has xpath expressions as keys.
-     * By default the xpath expressions should simply be checked for existance
-     * The xpath expressions can point to elements or attributes.
-     * 
-     * The array values can contain a number of items, which alters the query
-     * filter. 
-     *
-     * * time-range. Must also check if the todo or event falls within the
-     *               specified timerange. How this is interpreted depends on
-     *               the type of object (VTODO, VEVENT, VJOURNAL, etc)
-     * * is-not-defined
-     *               Instead of checking if the attribute or element exist,
-     *               we must check if it doesn't.
-     * * text-match
-     *               Checks if the value of the attribute or element matches
-     *               the specified value. This is actually another array with
-     *               the 'collation', 'value' and 'negate-condition' items.
-     *
-     * Refer to the CalDAV spec for more information.
-     * 
-     * @param DOMNode $domNode 
-     * @param string $basePath used for recursive calls.
-     * @param array $filters used for recursive calls.
-     * @return array 
-     */
-    static public function parseCalendarQueryFilters($domNode,$basePath = '/c:iCalendar', &$filters = array()) {
-
-        foreach($domNode->childNodes as $child) {
-
-            switch(Sabre_DAV_XMLUtil::toClarkNotation($child)) {
-
-                case '{urn:ietf:params:xml:ns:caldav}comp-filter' :
-                case '{urn:ietf:params:xml:ns:caldav}prop-filter' :
-                   
-                    $filterName = $basePath . '/' . 'c:' . strtolower($child->getAttribute('name'));
-                    $filters[$filterName] = array(); 
-
-                    self::parseCalendarQueryFilters($child, $filterName,$filters);
-                    break;
-
-                case '{urn:ietf:params:xml:ns:caldav}time-range' :
-               
-                    if ($start = $child->getAttribute('start')) {
-                        $start = self::parseICalendarDateTime($start);
-                    } else {
-                        $start = null;
-                    }
-                    if ($end = $child->getAttribute('end')) {
-                        $end = self::parseICalendarDateTime($end);
-                    } else {
-                        $end = null;
-                    }
-
-                    if (!is_null($start) && !is_null($end) && $end <= $start) {
-                        throw new Sabre_DAV_Exception_BadRequest('The end-date must be larger than the start-date in the time-range filter');
-                    }
-
-                    $filters[$basePath]['time-range'] = array(
-                        'start' => $start,
-                        'end'   => $end
-                    );
-                    break;
-
-                case '{urn:ietf:params:xml:ns:caldav}is-not-defined' :
-                    $filters[$basePath]['is-not-defined'] = true;
-                    break;
-
-                case '{urn:ietf:params:xml:ns:caldav}param-filter' :
-               
-                    $filterName = $basePath . '/@' . strtolower($child->getAttribute('name'));
-                    $filters[$filterName] = array();
-                    self::parseCalendarQueryFilters($child, $filterName, $filters);
-                    break;
-
-                case '{urn:ietf:params:xml:ns:caldav}text-match' :
-               
-                    $collation = $child->getAttribute('collation');
-                    if (!$collation) $collation = 'i;ascii-casemap';
-
-                    $filters[$basePath]['text-match'] = array(
-                        'collation' => ($collation == 'default'?'i;ascii-casemap':$collation),
-                        'negate-condition' => $child->getAttribute('negate-condition')==='yes',
-                        'value' => $child->nodeValue,
-                    );
-                    break;
-
-            }
-
-        }
-
-        return $filters;
-
-    }
-
-    /**
-     * Parses an iCalendar (rfc5545) formatted datetime and returns a DateTime object
-     *
-     * Specifying a reference timezone is optional. It will only be used
-     * if the non-UTC format is used. The argument is used as a reference, the 
-     * returned DateTime object will still be in the UTC timezone.
-     *
-     * @param string $dt 
-     * @param DateTimeZone $tz 
-     * @return DateTime 
-     */
-    static public function parseICalendarDateTime($dt,DateTimeZone $tz = null) {
-
-        // Format is YYYYMMDD + "T" + hhmmss 
-        $result = preg_match('/^([1-3][0-9]{3})([0-1][0-9])([0-3][0-9])T([0-2][0-9])([0-5][0-9])([0-5][0-9])([Z]?)$/',$dt,$matches);
-
-        if (!$result) {
-            throw new Sabre_DAV_Exception_BadRequest('The supplied iCalendar datetime value is incorrect: ' . $dt);
-        }
-
-        if ($matches[7]==='Z' || is_null($tz)) {
-            $tz = new DateTimeZone('UTC');
-        } 
-        $date = new DateTime($matches[1] . '-' . $matches[2] . '-' . $matches[3] . ' ' . $matches[4] . ':' . $matches[5] .':' . $matches[6], $tz);
-
-        // Still resetting the timezone, to normalize everything to UTC
-        $date->setTimeZone(new DateTimeZone('UTC'));
-        return $date;
-
-    }
-
-    /**
-     * Parses an iCalendar (rfc5545) formatted datetime and returns a DateTime object
-     *
-     * @param string $date 
-     * @param DateTimeZone $tz 
-     * @return DateTime 
-     */
-    static public function parseICalendarDate($date) {
-
-        // Format is YYYYMMDD
-        $result = preg_match('/^([1-3][0-9]{3})([0-1][0-9])([0-3][0-9])$/',$date,$matches);
-
-        if (!$result) {
-            throw new Sabre_DAV_Exception_BadRequest('The supplied iCalendar date value is incorrect: ' . $date);
-        }
-
-        $date = new DateTime($matches[1] . '-' . $matches[2] . '-' . $matches[3], new DateTimeZone('UTC'));
-        return $date;
-
-    }
-   
-    /**
-     * Parses an iCalendar (RFC5545) formatted duration and returns a string suitable
-     * for strtotime or DateTime::modify.
-     *
-     * NOTE: When we require PHP 5.3 this can be replaced by the DateTimeInterval object, which
-     * supports ISO 8601 Intervals, which is a superset of ICalendar durations.
-     *
-     * For now though, we're just gonna live with this messy system
-     *
-     * @param string $duration
-     * @return string
-     */
-    static public function parseICalendarDuration($duration) {
-
-        $result = preg_match('/^(?P<plusminus>\+|-)?P((?P<week>\d+)W)?((?P<day>\d+)D)?(T((?P<hour>\d+)H)?((?P<minute>\d+)M)?((?P<second>\d+)S)?)?$/', $duration, $matches);
-        if (!$result) {
-            throw new Sabre_DAV_Exception_BadRequest('The supplied iCalendar duration value is incorrect: ' . $duration);
-        }
-       
-        $parts = array(
-            'week',
-            'day',
-            'hour',
-            'minute',
-            'second',
-        );
-
-        $newDur = '';
-        foreach($parts as $part) {
-            if (isset($matches[$part]) && $matches[$part]) {
-                $newDur.=' '.$matches[$part] . ' ' . $part . 's';
-            }
-        }
-
-        $newDur = ($matches['plusminus']==='-'?'-':'+') . trim($newDur);
-        return $newDur;
-
-    }
-
-}
diff --git a/3rdparty/Sabre/CalDAV/includes.php b/3rdparty/Sabre/CalDAV/includes.php
new file mode 100644
index 0000000000000000000000000000000000000000..1ecb870a0e134c76bf318e7b7bf68f6176d8a923
--- /dev/null
+++ b/3rdparty/Sabre/CalDAV/includes.php
@@ -0,0 +1,43 @@
+<?php
+
+/**
+ * Sabre_CalDAV includes file
+ *
+ * Including this file will automatically include all files from the
+ * Sabre_CalDAV package.
+ *
+ * This often allows faster loadtimes, as autoload-speed is often quite slow.
+ *
+ * @package Sabre
+ * @subpackage CalDAV
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
+ * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
+ */
+
+// Begin includes
+include __DIR__ . '/Backend/Abstract.php';
+include __DIR__ . '/Backend/PDO.php';
+include __DIR__ . '/CalendarQueryParser.php';
+include __DIR__ . '/CalendarQueryValidator.php';
+include __DIR__ . '/CalendarRootNode.php';
+include __DIR__ . '/ICalendar.php';
+include __DIR__ . '/ICalendarObject.php';
+include __DIR__ . '/ICSExportPlugin.php';
+include __DIR__ . '/Plugin.php';
+include __DIR__ . '/Principal/Collection.php';
+include __DIR__ . '/Principal/ProxyRead.php';
+include __DIR__ . '/Principal/ProxyWrite.php';
+include __DIR__ . '/Principal/User.php';
+include __DIR__ . '/Property/SupportedCalendarComponentSet.php';
+include __DIR__ . '/Property/SupportedCalendarData.php';
+include __DIR__ . '/Property/SupportedCollationSet.php';
+include __DIR__ . '/Schedule/IMip.php';
+include __DIR__ . '/Schedule/IOutbox.php';
+include __DIR__ . '/Schedule/Outbox.php';
+include __DIR__ . '/Server.php';
+include __DIR__ . '/UserCalendars.php';
+include __DIR__ . '/Version.php';
+include __DIR__ . '/Calendar.php';
+include __DIR__ . '/CalendarObject.php';
+// End includes
diff --git a/3rdparty/Sabre/CardDAV/AddressBook.php b/3rdparty/Sabre/CardDAV/AddressBook.php
index 471ca7b338a7734e392ddfd92fcb0c4db8bcf729..3b381e1eea3a27073fe0b28e60ca777ef16e3039 100644
--- a/3rdparty/Sabre/CardDAV/AddressBook.php
+++ b/3rdparty/Sabre/CardDAV/AddressBook.php
@@ -7,34 +7,33 @@
  *
  * @package Sabre
  * @subpackage CardDAV
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
- * @author Evert Pot (http://www.rooftopsolutions.nl/) 
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
  */
 class Sabre_CardDAV_AddressBook extends Sabre_DAV_Collection implements Sabre_CardDAV_IAddressBook, Sabre_DAV_IProperties, Sabre_DAVACL_IACL {
 
     /**
-     * This is an array with addressbook information 
-     * 
-     * @var array 
+     * This is an array with addressbook information
+     *
+     * @var array
      */
     private $addressBookInfo;
 
     /**
-     * CardDAV backend 
-     * 
-     * @var Sabre_CardDAV_Backend_Abstract 
+     * CardDAV backend
+     *
+     * @var Sabre_CardDAV_Backend_Abstract
      */
     private $carddavBackend;
 
     /**
-     * Constructor 
-     * 
-     * @param Sabre_CardDAV_Backend_Abstract $carddavBackend 
-     * @param array $addressBookInfo 
-     * @return void
+     * Constructor
+     *
+     * @param Sabre_CardDAV_Backend_Abstract $carddavBackend
+     * @param array $addressBookInfo
      */
-    public function __construct(Sabre_CardDAV_Backend_Abstract $carddavBackend,array $addressBookInfo) {
+    public function __construct(Sabre_CardDAV_Backend_Abstract $carddavBackend, array $addressBookInfo) {
 
         $this->carddavBackend = $carddavBackend;
         $this->addressBookInfo = $addressBookInfo;
@@ -42,9 +41,9 @@ class Sabre_CardDAV_AddressBook extends Sabre_DAV_Collection implements Sabre_Ca
     }
 
     /**
-     * Returns the name of the addressbook 
-     * 
-     * @return string 
+     * Returns the name of the addressbook
+     *
+     * @return string
      */
     public function getName() {
 
@@ -55,21 +54,21 @@ class Sabre_CardDAV_AddressBook extends Sabre_DAV_Collection implements Sabre_Ca
     /**
      * Returns a card
      *
-     * @param string $name 
+     * @param string $name
      * @return Sabre_DAV_Card
      */
     public function getChild($name) {
 
         $obj = $this->carddavBackend->getCard($this->addressBookInfo['id'],$name);
-        if (!$obj) throw new Sabre_DAV_Exception_FileNotFound('Card not found');
+        if (!$obj) throw new Sabre_DAV_Exception_NotFound('Card not found');
         return new Sabre_CardDAV_Card($this->carddavBackend,$this->addressBookInfo,$obj);
 
     }
 
     /**
      * Returns the full list of cards
-     * 
-     * @return array 
+     *
+     * @return array
      */
     public function getChildren() {
 
@@ -85,9 +84,9 @@ class Sabre_CardDAV_AddressBook extends Sabre_DAV_Collection implements Sabre_Ca
     /**
      * Creates a new directory
      *
-     * We actually block this, as subdirectories are not allowed in addressbooks. 
-     * 
-     * @param string $name 
+     * We actually block this, as subdirectories are not allowed in addressbooks.
+     *
+     * @param string $name
      * @return void
      */
     public function createDirectory($name) {
@@ -99,11 +98,13 @@ class Sabre_CardDAV_AddressBook extends Sabre_DAV_Collection implements Sabre_Ca
     /**
      * Creates a new file
      *
-     * The contents of the new file must be a valid VCARD
-     * 
-     * @param string $name 
-     * @param resource $vcardData 
-     * @return void
+     * The contents of the new file must be a valid VCARD.
+     *
+     * This method may return an ETag.
+     *
+     * @param string $name
+     * @param resource $vcardData
+     * @return void|null
      */
     public function createFile($name,$vcardData = null) {
 
@@ -111,13 +112,13 @@ class Sabre_CardDAV_AddressBook extends Sabre_DAV_Collection implements Sabre_Ca
         // Converting to UTF-8, if needed
         $vcardData = Sabre_DAV_StringUtil::ensureUTF8($vcardData);
 
-        $this->carddavBackend->createCard($this->addressBookInfo['id'],$name,$vcardData);
+        return $this->carddavBackend->createCard($this->addressBookInfo['id'],$name,$vcardData);
 
     }
 
     /**
-     * Deletes the entire addressbook. 
-     * 
+     * Deletes the entire addressbook.
+     *
      * @return void
      */
     public function delete() {
@@ -128,8 +129,8 @@ class Sabre_CardDAV_AddressBook extends Sabre_DAV_Collection implements Sabre_Ca
 
     /**
      * Renames the addressbook
-     * 
-     * @param string $newName 
+     *
+     * @param string $newName
      * @return void
      */
     public function setName($newName) {
@@ -140,7 +141,7 @@ class Sabre_CardDAV_AddressBook extends Sabre_DAV_Collection implements Sabre_Ca
 
     /**
      * Returns the last modification date as a unix timestamp.
-     * 
+     *
      * @return void
      */
     public function getLastModified() {
@@ -162,7 +163,7 @@ class Sabre_CardDAV_AddressBook extends Sabre_DAV_Collection implements Sabre_Ca
      * If the operation was successful, true can be returned.
      * If the operation failed, false can be returned.
      *
-     * Deletion of a non-existant property is always succesful.
+     * Deletion of a non-existent property is always successful.
      *
      * Lastly, it is optional to return detailed information about any
      * failures. In this case an array should be returned with the following
@@ -177,16 +178,16 @@ class Sabre_CardDAV_AddressBook extends Sabre_DAV_Collection implements Sabre_Ca
      *   )
      * )
      *
-     * In this example it was forbidden to update {DAV:}displayname. 
+     * In this example it was forbidden to update {DAV:}displayname.
      * (403 Forbidden), which in turn also caused {DAV:}owner to fail
      * (424 Failed Dependency) because the request needs to be atomic.
      *
-     * @param array $mutations 
-     * @return bool|array 
+     * @param array $mutations
+     * @return bool|array
      */
     public function updateProperties($mutations) {
 
-        return $this->carddavBackend->updateAddressBook($this->addressBookInfo['id'], $mutations); 
+        return $this->carddavBackend->updateAddressBook($this->addressBookInfo['id'], $mutations);
 
     }
 
@@ -198,8 +199,8 @@ class Sabre_CardDAV_AddressBook extends Sabre_DAV_Collection implements Sabre_Ca
      *
      * If the array is empty, it means 'all properties' were requested.
      *
-     * @param array $properties 
-     * @return void
+     * @param array $properties
+     * @return array
      */
     public function getProperties($properties) {
 
@@ -221,8 +222,8 @@ class Sabre_CardDAV_AddressBook extends Sabre_DAV_Collection implements Sabre_Ca
     /**
      * Returns the owner principal
      *
-     * This must be a url to a principal, or null if there's no owner 
-     * 
+     * This must be a url to a principal, or null if there's no owner
+     *
      * @return string|null
      */
     public function getOwner() {
@@ -235,8 +236,8 @@ class Sabre_CardDAV_AddressBook extends Sabre_DAV_Collection implements Sabre_Ca
      * Returns a group principal
      *
      * This must be a url to a principal, or null if there's no owner
-     * 
-     * @return string|null 
+     *
+     * @return string|null
      */
     public function getGroup() {
 
@@ -248,13 +249,13 @@ class Sabre_CardDAV_AddressBook extends Sabre_DAV_Collection implements Sabre_Ca
      * Returns a list of ACE's for this node.
      *
      * Each ACE has the following properties:
-     *   * 'privilege', a string such as {DAV:}read or {DAV:}write. These are 
+     *   * 'privilege', a string such as {DAV:}read or {DAV:}write. These are
      *     currently the only supported privileges
      *   * 'principal', a url to the principal who owns the node
-     *   * 'protected' (optional), indicating that this ACE is not allowed to 
-     *      be updated. 
-     * 
-     * @return array 
+     *   * 'protected' (optional), indicating that this ACE is not allowed to
+     *      be updated.
+     *
+     * @return array
      */
     public function getACL() {
 
@@ -277,9 +278,9 @@ class Sabre_CardDAV_AddressBook extends Sabre_DAV_Collection implements Sabre_Ca
     /**
      * Updates the ACL
      *
-     * This method will receive a list of new ACE's. 
-     * 
-     * @param array $acl 
+     * This method will receive a list of new ACE's.
+     *
+     * @param array $acl
      * @return void
      */
     public function setACL(array $acl) {
@@ -288,6 +289,22 @@ class Sabre_CardDAV_AddressBook extends Sabre_DAV_Collection implements Sabre_Ca
 
     }
 
+    /**
+     * Returns the list of supported privileges for this node.
+     *
+     * The returned data structure is a list of nested privileges.
+     * See Sabre_DAVACL_Plugin::getDefaultSupportedPrivilegeSet for a simple
+     * standard structure.
+     *
+     * If null is returned from this method, the default privilege set is used,
+     * which is fine for most common usecases.
+     *
+     * @return array|null
+     */
+    public function getSupportedPrivilegeSet() {
+
+        return null;
 
+    }
 
 }
diff --git a/3rdparty/Sabre/CardDAV/AddressBookQueryParser.php b/3rdparty/Sabre/CardDAV/AddressBookQueryParser.php
index 08adc3b8157ecf72d8bb7508a8e3819384ce9c1b..85a4963127bff4ef3c1e227525ffdcddff7e01e6 100644
--- a/3rdparty/Sabre/CardDAV/AddressBookQueryParser.php
+++ b/3rdparty/Sabre/CardDAV/AddressBookQueryParser.php
@@ -3,12 +3,12 @@
 /**
  * Parses the addressbook-query report request body.
  *
- * Whoever designed this format, and the CalDAV equavalent even more so, 
+ * Whoever designed this format, and the CalDAV equivalent even more so,
  * has no feel for design.
- * 
+ *
  * @package Sabre
  * @subpackage CardDAV
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
  * @author Evert Pot (http://www.rooftopsolutions.nl/) 
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
  */
@@ -19,8 +19,8 @@ class Sabre_CardDAV_AddressBookQueryParser {
 
     /**
      * List of requested properties the client wanted
-     * 
-     * @var array 
+     *
+     * @var array
      */
     public $requestedProperties;
 
@@ -28,44 +28,43 @@ class Sabre_CardDAV_AddressBookQueryParser {
      * The number of results the client wants
      *
      * null means it wasn't specified, which in most cases means 'all results'.
-     * 
-     * @var int|null 
+     *
+     * @var int|null
      */
     public $limit;
 
     /**
      * List of property filters.
      *
-     * @var array 
+     * @var array
      */
     public $filters;
 
     /**
      * Either TEST_ANYOF or TEST_ALLOF
-     * 
-     * @var string 
+     *
+     * @var string
      */
     public $test;
 
     /**
      * DOM Document
-     * 
-     * @var DOMDocument 
+     *
+     * @var DOMDocument
      */
     protected $dom;
 
     /**
-     * DOM XPath object 
-     * 
-     * @var DOMXPath 
+     * DOM XPath object
+     *
+     * @var DOMXPath
      */
     protected $xpath;
 
     /**
      * Creates the parser
-     * 
-     * @param DOMNode $dom 
-     * @return void
+     *
+     * @param DOMDocument $dom
      */
     public function __construct(DOMDocument $dom) {
 
@@ -77,15 +76,14 @@ class Sabre_CardDAV_AddressBookQueryParser {
     }
 
     /**
-     * Parses the request. 
-     * 
-     * @param DOMNode $dom 
+     * Parses the request.
+     *
      * @return void
      */
     public function parse() {
 
         $filterNode = null;
-        
+
         $limit = $this->xpath->evaluate('number(/card:addressbook-query/card:limit/card:nresults)');
         if (is_nan($limit)) $limit = null;
 
@@ -120,9 +118,9 @@ class Sabre_CardDAV_AddressBookQueryParser {
 
     /**
      * Parses the prop-filter xml element
-     * 
-     * @param DOMElement $propFilterNode 
-     * @return array 
+     *
+     * @param DOMElement $propFilterNode
+     * @return array
      */
     protected function parsePropFilterNode(DOMElement $propFilterNode) {
 
@@ -157,13 +155,13 @@ class Sabre_CardDAV_AddressBookQueryParser {
     }
 
     /**
-     * Parses the param-filter element 
-     * 
-     * @param DOMElement $paramFilterNode 
-     * @return array 
+     * Parses the param-filter element
+     *
+     * @param DOMElement $paramFilterNode
+     * @return array
      */
     public function parseParamFilterNode(DOMElement $paramFilterNode) {
-        
+
         $paramFilter = array();
         $paramFilter['name'] = $paramFilterNode->getAttribute('name');
         $paramFilter['is-not-defined'] = $this->xpath->query('card:is-not-defined', $paramFilterNode)->length>0;
@@ -174,15 +172,15 @@ class Sabre_CardDAV_AddressBookQueryParser {
             $paramFilter['text-match'] = $this->parseTextMatchNode($textMatch->item(0));
         }
 
-        return $paramFilter; 
+        return $paramFilter;
 
     }
 
     /**
      * Text match
-     * 
-     * @param DOMElement $textMatchNode 
-     * @return void
+     *
+     * @param DOMElement $textMatchNode
+     * @return array
      */
     public function parseTextMatchNode(DOMElement $textMatchNode) {
 
@@ -204,8 +202,8 @@ class Sabre_CardDAV_AddressBookQueryParser {
             'match-type' => $matchType,
             'value' => $textMatchNode->nodeValue
         );
-          
 
-    } 
+
+    }
 
 }
diff --git a/3rdparty/Sabre/CardDAV/AddressBookRoot.php b/3rdparty/Sabre/CardDAV/AddressBookRoot.php
index 1a80efba35e38e58251f0b13e815843f5e4d8f06..9d37b15f08e2ea04942ed1ffbff4152b50f5b007 100644
--- a/3rdparty/Sabre/CardDAV/AddressBookRoot.php
+++ b/3rdparty/Sabre/CardDAV/AddressBookRoot.php
@@ -1,45 +1,45 @@
 <?php
 
 /**
- * AddressBook rootnode 
+ * AddressBook rootnode
  *
  * This object lists a collection of users, which can contain addressbooks.
  *
  * @package Sabre
  * @subpackage CardDAV
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
  * @author Evert Pot (http://www.rooftopsolutions.nl/) 
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
  */
 class Sabre_CardDAV_AddressBookRoot extends Sabre_DAVACL_AbstractPrincipalCollection {
 
     /**
-     * Principal Backend 
-     * 
+     * Principal Backend
+     *
      * @var Sabre_DAVACL_IPrincipalBackend
      */
     protected $principalBackend;
 
     /**
-     * CardDAV backend 
-     * 
-     * @var Sabre_CardDAV_Backend_Abstract 
+     * CardDAV backend
+     *
+     * @var Sabre_CardDAV_Backend_Abstract
      */
     protected $carddavBackend;
 
     /**
-     * Constructor 
+     * Constructor
      *
      * This constructor needs both a principal and a carddav backend.
      *
-     * By default this class will show a list of addressbook collections for 
-     * principals in the 'principals' collection. If your main principals are 
-     * actually located in a different path, use the $principalPrefix argument 
+     * By default this class will show a list of addressbook collections for
+     * principals in the 'principals' collection. If your main principals are
+     * actually located in a different path, use the $principalPrefix argument
      * to override this.
      *
-     * @param Sabre_DAVACL_IPrincipalBackend $principalBackend 
+     * @param Sabre_DAVACL_IPrincipalBackend $principalBackend
      * @param Sabre_CardDAV_Backend_Abstract $carddavBackend
-     * @param string $principalPrefix 
+     * @param string $principalPrefix
      */
     public function __construct(Sabre_DAVACL_IPrincipalBackend $principalBackend,Sabre_CardDAV_Backend_Abstract $carddavBackend, $principalPrefix = 'principals') {
 
@@ -49,9 +49,9 @@ class Sabre_CardDAV_AddressBookRoot extends Sabre_DAVACL_AbstractPrincipalCollec
     }
 
     /**
-     * Returns the name of the node 
-     * 
-     * @return string 
+     * Returns the name of the node
+     *
+     * @return string
      */
     public function getName() {
 
@@ -65,9 +65,9 @@ class Sabre_CardDAV_AddressBookRoot extends Sabre_DAVACL_AbstractPrincipalCollec
      * The passed array contains principal information, and is guaranteed to
      * at least contain a uri item. Other properties may or may not be
      * supplied by the authentication backend.
-     * 
-     * @param array $principal 
-     * @return Sabre_DAV_INode 
+     *
+     * @param array $principal
+     * @return Sabre_DAV_INode
      */
     public function getChildForPrincipal(array $principal) {
 
diff --git a/3rdparty/Sabre/CardDAV/Backend/Abstract.php b/3rdparty/Sabre/CardDAV/Backend/Abstract.php
index 1f0253ddab802d28fbdbe121311fcb88f28af02c..e4806b7161f10a5a0f77ada0c8f907009866555d 100644
--- a/3rdparty/Sabre/CardDAV/Backend/Abstract.php
+++ b/3rdparty/Sabre/CardDAV/Backend/Abstract.php
@@ -5,14 +5,14 @@
  *
  * This class serves as a base-class for addressbook backends
  *
- * Note that there are references to 'addressBookId' scattered throughout the 
- * class. The value of the addressBookId is completely up to you, it can be any 
+ * Note that there are references to 'addressBookId' scattered throughout the
+ * class. The value of the addressBookId is completely up to you, it can be any
  * arbitrary value you can use as an unique identifier.
- * 
+ *
  * @package Sabre
  * @subpackage CardDAV
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
- * @author Evert Pot (http://www.rooftopsolutions.nl/) 
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
  */
 abstract class Sabre_CardDAV_Backend_Abstract {
@@ -25,97 +25,142 @@ abstract class Sabre_CardDAV_Backend_Abstract {
      *   uri - the 'basename' part of the url
      *   principaluri - Same as the passed parameter
      *
-     * Any additional clark-notation property may be passed besides this. Some 
+     * Any additional clark-notation property may be passed besides this. Some
      * common ones are :
      *   {DAV:}displayname
      *   {urn:ietf:params:xml:ns:carddav}addressbook-description
      *   {http://calendarserver.org/ns/}getctag
-     * 
-     * @param string $principalUri 
-     * @return array 
+     *
+     * @param string $principalUri
+     * @return array
      */
-    public abstract function getAddressBooksForUser($principalUri); 
+    public abstract function getAddressBooksForUser($principalUri);
 
     /**
      * Updates an addressbook's properties
      *
-     * See Sabre_DAV_IProperties for a description of the mutations array, as 
-     * well as the return value. 
+     * See Sabre_DAV_IProperties for a description of the mutations array, as
+     * well as the return value.
      *
      * @param mixed $addressBookId
      * @param array $mutations
      * @see Sabre_DAV_IProperties::updateProperties
      * @return bool|array
      */
-    public abstract function updateAddressBook($addressBookId, array $mutations); 
+    public abstract function updateAddressBook($addressBookId, array $mutations);
 
     /**
-     * Creates a new address book 
+     * Creates a new address book
      *
-     * @param string $principalUri 
-     * @param string $url Just the 'basename' of the url. 
-     * @param array $properties 
+     * @param string $principalUri
+     * @param string $url Just the 'basename' of the url.
+     * @param array $properties
      * @return void
      */
-    abstract public function createAddressBook($principalUri, $url, array $properties); 
+    abstract public function createAddressBook($principalUri, $url, array $properties);
 
     /**
      * Deletes an entire addressbook and all its contents
      *
-     * @param mixed $addressBookId 
+     * @param mixed $addressBookId
      * @return void
      */
-    abstract public function deleteAddressBook($addressBookId); 
+    abstract public function deleteAddressBook($addressBookId);
 
     /**
-     * Returns all cards for a specific addressbook id. 
+     * Returns all cards for a specific addressbook id.
      *
      * This method should return the following properties for each card:
      *   * carddata - raw vcard data
      *   * uri - Some unique url
      *   * lastmodified - A unix timestamp
-
-     * @param mixed $addressbookId 
-     * @return array 
+     *
+     * It's recommended to also return the following properties:
+     *   * etag - A unique etag. This must change every time the card changes.
+     *   * size - The size of the card in bytes.
+     *
+     * If these last two properties are provided, less time will be spent
+     * calculating them. If they are specified, you can also ommit carddata.
+     * This may speed up certain requests, especially with large cards.
+     *
+     * @param mixed $addressbookId
+     * @return array
      */
-    public abstract function getCards($addressbookId); 
+    public abstract function getCards($addressbookId);
 
     /**
-     * Returns a specfic card
-     * 
-     * @param mixed $addressBookId 
-     * @param string $cardUri 
-     * @return void
+     * Returns a specfic card.
+     *
+     * The same set of properties must be returned as with getCards. The only
+     * exception is that 'carddata' is absolutely required.
+     *
+     * @param mixed $addressBookId
+     * @param string $cardUri
+     * @return array
      */
-    public abstract function getCard($addressBookId, $cardUri); 
+    public abstract function getCard($addressBookId, $cardUri);
 
     /**
-     * Creates a new card
-     * 
-     * @param mixed $addressBookId 
-     * @param string $cardUri 
-     * @param string $cardData 
-     * @return bool 
+     * Creates a new card.
+     *
+     * The addressbook id will be passed as the first argument. This is the
+     * same id as it is returned from the getAddressbooksForUser method.
+     *
+     * The cardUri is a base uri, and doesn't include the full path. The
+     * cardData argument is the vcard body, and is passed as a string.
+     *
+     * It is possible to return an ETag from this method. This ETag is for the
+     * newly created resource, and must be enclosed with double quotes (that
+     * is, the string itself must contain the double quotes).
+     *
+     * You should only return the ETag if you store the carddata as-is. If a
+     * subsequent GET request on the same card does not have the same body,
+     * byte-by-byte and you did return an ETag here, clients tend to get
+     * confused.
+     *
+     * If you don't return an ETag, you can just return null.
+     *
+     * @param mixed $addressBookId
+     * @param string $cardUri
+     * @param string $cardData
+     * @return string|null
      */
-    abstract public function createCard($addressBookId, $cardUri, $cardData); 
+    abstract public function createCard($addressBookId, $cardUri, $cardData);
 
     /**
-     * Updates a card
-     * 
-     * @param mixed $addressBookId 
-     * @param string $cardUri 
-     * @param string $cardData 
-     * @return bool 
+     * Updates a card.
+     *
+     * The addressbook id will be passed as the first argument. This is the
+     * same id as it is returned from the getAddressbooksForUser method.
+     *
+     * The cardUri is a base uri, and doesn't include the full path. The
+     * cardData argument is the vcard body, and is passed as a string.
+     *
+     * It is possible to return an ETag from this method. This ETag should
+     * match that of the updated resource, and must be enclosed with double
+     * quotes (that is: the string itself must contain the actual quotes).
+     *
+     * You should only return the ETag if you store the carddata as-is. If a
+     * subsequent GET request on the same card does not have the same body,
+     * byte-by-byte and you did return an ETag here, clients tend to get
+     * confused.
+     *
+     * If you don't return an ETag, you can just return null.
+     *
+     * @param mixed $addressBookId
+     * @param string $cardUri
+     * @param string $cardData
+     * @return string|null
      */
-    abstract public function updateCard($addressBookId, $cardUri, $cardData); 
+    abstract public function updateCard($addressBookId, $cardUri, $cardData);
 
     /**
      * Deletes a card
-     * 
-     * @param mixed $addressBookId 
-     * @param string $cardUri 
-     * @return bool 
+     *
+     * @param mixed $addressBookId
+     * @param string $cardUri
+     * @return bool
      */
-    abstract public function deleteCard($addressBookId, $cardUri); 
+    abstract public function deleteCard($addressBookId, $cardUri);
 
 }
diff --git a/3rdparty/Sabre/CardDAV/Backend/PDO.php b/3rdparty/Sabre/CardDAV/Backend/PDO.php
index f4e44610ccf1146bc3acf3548f23a78d91797977..413a77f3bccfb86695a294fcffcb2bb244beafd6 100644
--- a/3rdparty/Sabre/CardDAV/Backend/PDO.php
+++ b/3rdparty/Sabre/CardDAV/Backend/PDO.php
@@ -4,19 +4,19 @@
  * PDO CardDAV backend
  *
  * This CardDAV backend uses PDO to store addressbooks
- * 
+ *
  * @package Sabre
  * @subpackage CardDAV
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
- * @author Evert Pot (http://www.rooftopsolutions.nl/) 
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
  */
 class Sabre_CardDAV_Backend_PDO extends Sabre_CardDAV_Backend_Abstract {
 
     /**
-     * PDO connection 
-     * 
-     * @var PDO 
+     * PDO connection
+     *
+     * @var PDO
      */
     protected $pdo;
 
@@ -31,28 +31,30 @@ class Sabre_CardDAV_Backend_PDO extends Sabre_CardDAV_Backend_Abstract {
     protected $cardsTableName;
 
     /**
-     * Sets up the object 
-     * 
-     * @param PDO $pdo 
+     * Sets up the object
+     *
+     * @param PDO $pdo
+     * @param string $addressBooksTableName
+     * @param string $cardsTableName
      */
     public function __construct(PDO $pdo, $addressBooksTableName = 'addressbooks', $cardsTableName = 'cards') {
 
         $this->pdo = $pdo;
         $this->addressBooksTableName = $addressBooksTableName;
-        $this->cardsTableName = $cardsTableName; 
+        $this->cardsTableName = $cardsTableName;
 
     }
 
     /**
-     * Returns the list of addressbooks for a specific user. 
-     * 
-     * @param string $principalUri 
-     * @return array 
+     * Returns the list of addressbooks for a specific user.
+     *
+     * @param string $principalUri
+     * @return array
      */
     public function getAddressBooksForUser($principalUri) {
 
-        $stmt = $this->pdo->prepare('SELECT id, uri, displayname, principaluri, description, ctag FROM `'.$this->addressBooksTableName.'` WHERE principaluri = ?');
-        $result = $stmt->execute(array($principalUri));
+        $stmt = $this->pdo->prepare('SELECT id, uri, displayname, principaluri, description, ctag FROM '.$this->addressBooksTableName.' WHERE principaluri = ?');
+        $stmt->execute(array($principalUri));
 
         $addressBooks = array();
 
@@ -65,7 +67,7 @@ class Sabre_CardDAV_Backend_PDO extends Sabre_CardDAV_Backend_Abstract {
                 '{DAV:}displayname' => $row['displayname'],
                 '{' . Sabre_CardDAV_Plugin::NS_CARDDAV . '}addressbook-description' => $row['description'],
                 '{http://calendarserver.org/ns/}getctag' => $row['ctag'],
-                '{' . Sabre_CardDAV_Plugin::NS_CARDDAV . '}supported-address-data' => 
+                '{' . Sabre_CardDAV_Plugin::NS_CARDDAV . '}supported-address-data' =>
                     new Sabre_CardDAV_Property_SupportedAddressData(),
             );
 
@@ -79,8 +81,8 @@ class Sabre_CardDAV_Backend_PDO extends Sabre_CardDAV_Backend_Abstract {
     /**
      * Updates an addressbook's properties
      *
-     * See Sabre_DAV_IProperties for a description of the mutations array, as 
-     * well as the return value. 
+     * See Sabre_DAV_IProperties for a description of the mutations array, as
+     * well as the return value.
      *
      * @param mixed $addressBookId
      * @param array $mutations
@@ -88,7 +90,7 @@ class Sabre_CardDAV_Backend_PDO extends Sabre_CardDAV_Backend_Abstract {
      * @return bool|array
      */
     public function updateAddressBook($addressBookId, array $mutations) {
-        
+
         $updates = array();
 
         foreach($mutations as $property=>$newValue) {
@@ -101,7 +103,7 @@ class Sabre_CardDAV_Backend_PDO extends Sabre_CardDAV_Backend_Abstract {
                     $updates['description'] = $newValue;
                     break;
                 default :
-                    // If any unsupported values were being updated, we must 
+                    // If any unsupported values were being updated, we must
                     // let the entire request fail.
                     return false;
             }
@@ -113,7 +115,7 @@ class Sabre_CardDAV_Backend_PDO extends Sabre_CardDAV_Backend_Abstract {
             return false;
         }
 
-        $query = 'UPDATE `' . $this->addressBooksTableName . '` SET ctag = ctag + 1 ';
+        $query = 'UPDATE ' . $this->addressBooksTableName . ' SET ctag = ctag + 1 ';
         foreach($updates as $key=>$value) {
             $query.=', `' . $key . '` = :' . $key . ' ';
         }
@@ -129,11 +131,11 @@ class Sabre_CardDAV_Backend_PDO extends Sabre_CardDAV_Backend_Abstract {
     }
 
     /**
-     * Creates a new address book 
+     * Creates a new address book
      *
-     * @param string $principalUri 
-     * @param string $url Just the 'basename' of the url. 
-     * @param array $properties 
+     * @param string $principalUri
+     * @param string $url Just the 'basename' of the url.
+     * @param array $properties
      * @return void
      */
     public function createAddressBook($principalUri, $url, array $properties) {
@@ -160,7 +162,7 @@ class Sabre_CardDAV_Backend_PDO extends Sabre_CardDAV_Backend_Abstract {
 
         }
 
-        $query = 'INSERT INTO `' . $this->addressBooksTableName . '` (uri, displayname, description, principaluri, ctag) VALUES (:uri, :displayname, :description, :principaluri, 1)';
+        $query = 'INSERT INTO ' . $this->addressBooksTableName . ' (uri, displayname, description, principaluri, ctag) VALUES (:uri, :displayname, :description, :principaluri, 1)';
         $stmt = $this->pdo->prepare($query);
         $stmt->execute($values);
 
@@ -169,44 +171,61 @@ class Sabre_CardDAV_Backend_PDO extends Sabre_CardDAV_Backend_Abstract {
     /**
      * Deletes an entire addressbook and all its contents
      *
-     * @param int $addressBookId 
+     * @param int $addressBookId
      * @return void
      */
     public function deleteAddressBook($addressBookId) {
 
-        $stmt = $this->pdo->prepare('DELETE FROM `' . $this->cardsTableName . '` WHERE addressbookid = ?');
+        $stmt = $this->pdo->prepare('DELETE FROM ' . $this->cardsTableName . ' WHERE addressbookid = ?');
         $stmt->execute(array($addressBookId));
 
-        $stmt = $this->pdo->prepare('DELETE FROM `' . $this->addressBooksTableName . '` WHERE id = ?');
+        $stmt = $this->pdo->prepare('DELETE FROM ' . $this->addressBooksTableName . ' WHERE id = ?');
         $stmt->execute(array($addressBookId));
 
     }
 
     /**
-     * Returns all cards for a specific addressbook id. 
-     * 
-     * @param mixed $addressbookId 
-     * @return array 
+     * Returns all cards for a specific addressbook id.
+     *
+     * This method should return the following properties for each card:
+     *   * carddata - raw vcard data
+     *   * uri - Some unique url
+     *   * lastmodified - A unix timestamp
+     *
+     * It's recommended to also return the following properties:
+     *   * etag - A unique etag. This must change every time the card changes.
+     *   * size - The size of the card in bytes.
+     *
+     * If these last two properties are provided, less time will be spent
+     * calculating them. If they are specified, you can also ommit carddata.
+     * This may speed up certain requests, especially with large cards.
+     *
+     * @param mixed $addressbookId
+     * @return array
      */
     public function getCards($addressbookId) {
 
-        $stmt = $this->pdo->prepare('SELECT id, carddata, uri, lastmodified FROM `' . $this->cardsTableName . '` WHERE addressbookid = ?');
+        $stmt = $this->pdo->prepare('SELECT id, carddata, uri, lastmodified FROM ' . $this->cardsTableName . ' WHERE addressbookid = ?');
         $stmt->execute(array($addressbookId));
 
         return $stmt->fetchAll(PDO::FETCH_ASSOC);
 
-    
+
     }
+
     /**
-     * Returns a specfic card
-     * 
-     * @param mixed $addressBookId 
-     * @param string $cardUri 
-     * @return array 
+     * Returns a specfic card.
+     *
+     * The same set of properties must be returned as with getCards. The only
+     * exception is that 'carddata' is absolutely required.
+     *
+     * @param mixed $addressBookId
+     * @param string $cardUri
+     * @return array
      */
     public function getCard($addressBookId, $cardUri) {
 
-        $stmt = $this->pdo->prepare('SELECT id, carddata, uri, lastmodified FROM `' . $this->cardsTableName . '` WHERE addressbookid = ? AND uri = ? LIMIT 1');
+        $stmt = $this->pdo->prepare('SELECT id, carddata, uri, lastmodified FROM ' . $this->cardsTableName . ' WHERE addressbookid = ? AND uri = ? LIMIT 1');
         $stmt->execute(array($addressBookId, $cardUri));
 
         $result = $stmt->fetchAll(PDO::FETCH_ASSOC);
@@ -216,59 +235,93 @@ class Sabre_CardDAV_Backend_PDO extends Sabre_CardDAV_Backend_Abstract {
     }
 
     /**
-     * Creates a new card
-     * 
-     * @param mixed $addressBookId 
-     * @param string $cardUri 
-     * @param string $cardData 
-     * @return bool 
+     * Creates a new card.
+     *
+     * The addressbook id will be passed as the first argument. This is the
+     * same id as it is returned from the getAddressbooksForUser method.
+     *
+     * The cardUri is a base uri, and doesn't include the full path. The
+     * cardData argument is the vcard body, and is passed as a string.
+     *
+     * It is possible to return an ETag from this method. This ETag is for the
+     * newly created resource, and must be enclosed with double quotes (that
+     * is, the string itself must contain the double quotes).
+     *
+     * You should only return the ETag if you store the carddata as-is. If a
+     * subsequent GET request on the same card does not have the same body,
+     * byte-by-byte and you did return an ETag here, clients tend to get
+     * confused.
+     *
+     * If you don't return an ETag, you can just return null.
+     *
+     * @param mixed $addressBookId
+     * @param string $cardUri
+     * @param string $cardData
+     * @return string|null
      */
     public function createCard($addressBookId, $cardUri, $cardData) {
 
-        $stmt = $this->pdo->prepare('INSERT INTO `' . $this->cardsTableName . '` (carddata, uri, lastmodified, addressbookid) VALUES (?, ?, ?, ?)');
+        $stmt = $this->pdo->prepare('INSERT INTO ' . $this->cardsTableName . ' (carddata, uri, lastmodified, addressbookid) VALUES (?, ?, ?, ?)');
 
         $result = $stmt->execute(array($cardData, $cardUri, time(), $addressBookId));
 
-        $stmt2 = $this->pdo->prepare('UPDATE `' . $this->addressBooksTableName . '` SET ctag = ctag + 1 WHERE id = ?');
+        $stmt2 = $this->pdo->prepare('UPDATE ' . $this->addressBooksTableName . ' SET ctag = ctag + 1 WHERE id = ?');
         $stmt2->execute(array($addressBookId));
 
-        return $result;
+        return '"' . md5($cardData) . '"';
 
     }
 
     /**
-     * Updates a card
-     * 
-     * @param mixed $addressBookId 
-     * @param string $cardUri 
-     * @param string $cardData 
-     * @return bool 
+     * Updates a card.
+     *
+     * The addressbook id will be passed as the first argument. This is the
+     * same id as it is returned from the getAddressbooksForUser method.
+     *
+     * The cardUri is a base uri, and doesn't include the full path. The
+     * cardData argument is the vcard body, and is passed as a string.
+     *
+     * It is possible to return an ETag from this method. This ETag should
+     * match that of the updated resource, and must be enclosed with double
+     * quotes (that is: the string itself must contain the actual quotes).
+     *
+     * You should only return the ETag if you store the carddata as-is. If a
+     * subsequent GET request on the same card does not have the same body,
+     * byte-by-byte and you did return an ETag here, clients tend to get
+     * confused.
+     *
+     * If you don't return an ETag, you can just return null.
+     *
+     * @param mixed $addressBookId
+     * @param string $cardUri
+     * @param string $cardData
+     * @return string|null
      */
     public function updateCard($addressBookId, $cardUri, $cardData) {
 
-        $stmt = $this->pdo->prepare('UPDATE `' . $this->cardsTableName . '` SET carddata = ?, lastmodified = ? WHERE uri = ? AND addressbookid =?');
-        $result = $stmt->execute(array($cardData, time(), $cardUri, $addressBookId));
+        $stmt = $this->pdo->prepare('UPDATE ' . $this->cardsTableName . ' SET carddata = ?, lastmodified = ? WHERE uri = ? AND addressbookid =?');
+        $stmt->execute(array($cardData, time(), $cardUri, $addressBookId));
 
-        $stmt2 = $this->pdo->prepare('UPDATE `' . $this->addressBooksTableName . '` SET ctag = ctag + 1 WHERE id = ?');
+        $stmt2 = $this->pdo->prepare('UPDATE ' . $this->addressBooksTableName . ' SET ctag = ctag + 1 WHERE id = ?');
         $stmt2->execute(array($addressBookId));
 
-        return $stmt->rowCount()===1;
+        return '"' . md5($cardData) . '"';
 
     }
 
     /**
      * Deletes a card
-     * 
-     * @param mixed $addressBookId 
-     * @param string $cardUri 
-     * @return bool 
+     *
+     * @param mixed $addressBookId
+     * @param string $cardUri
+     * @return bool
      */
     public function deleteCard($addressBookId, $cardUri) {
 
-        $stmt = $this->pdo->prepare('DELETE FROM `' . $this->cardsTableName . '` WHERE addressbookid = ? AND uri = ?');
+        $stmt = $this->pdo->prepare('DELETE FROM ' . $this->cardsTableName . ' WHERE addressbookid = ? AND uri = ?');
         $stmt->execute(array($addressBookId, $cardUri));
 
-        $stmt2 = $this->pdo->prepare('UPDATE `' . $this->addressBooksTableName . '` SET ctag = ctag + 1 WHERE id = ?');
+        $stmt2 = $this->pdo->prepare('UPDATE ' . $this->addressBooksTableName . ' SET ctag = ctag + 1 WHERE id = ?');
         $stmt2->execute(array($addressBookId));
 
         return $stmt->rowCount()===1;
diff --git a/3rdparty/Sabre/CardDAV/Card.php b/3rdparty/Sabre/CardDAV/Card.php
index 2844eaf7ed6b06f06f3a6fbea2c609a544cc16dd..d7c663338375ac8b068851c574d49b45a49a75b7 100644
--- a/3rdparty/Sabre/CardDAV/Card.php
+++ b/3rdparty/Sabre/CardDAV/Card.php
@@ -2,10 +2,10 @@
 
 /**
  * The Card object represents a single Card from an addressbook
- * 
+ *
  * @package Sabre
  * @subpackage CardDAV
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
  * @author Evert Pot (http://www.rooftopsolutions.nl/) 
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
  */
@@ -13,29 +13,29 @@ class Sabre_CardDAV_Card extends Sabre_DAV_File implements Sabre_CardDAV_ICard,
 
     /**
      * CardDAV backend
-     * 
-     * @var Sabre_CardDAV_Backend_Abstract 
+     *
+     * @var Sabre_CardDAV_Backend_Abstract
      */
     private $carddavBackend;
 
     /**
      * Array with information about this Card
-     * 
-     * @var array 
+     *
+     * @var array
      */
     private $cardData;
 
     /**
-     * Array with information about the containing addressbook 
-     * 
-     * @var array 
+     * Array with information about the containing addressbook
+     *
+     * @var array
      */
     private $addressBookInfo;
 
     /**
-     * Constructor 
-     * 
-     * @param Sabre_CardDAV_Backend_Abstract $carddavBackend 
+     * Constructor
+     *
+     * @param Sabre_CardDAV_Backend_Abstract $carddavBackend
      * @param array $addressBookInfo
      * @param array $cardData
      */
@@ -48,9 +48,9 @@ class Sabre_CardDAV_Card extends Sabre_DAV_File implements Sabre_CardDAV_ICard,
     }
 
     /**
-     * Returns the uri for this object 
-     * 
-     * @return string 
+     * Returns the uri for this object
+     *
+     * @return string
      */
     public function getName() {
 
@@ -59,25 +59,26 @@ class Sabre_CardDAV_Card extends Sabre_DAV_File implements Sabre_CardDAV_ICard,
     }
 
     /**
-     * Returns the VCard-formatted object 
-     * 
-     * @return string 
+     * Returns the VCard-formatted object
+     *
+     * @return string
      */
     public function get() {
 
-        $cardData = $this->cardData['carddata'];
-        $s = fopen('php://temp','r+');
-        fwrite($s, $cardData);
-        rewind($s);
-        return $s;
+        // Pre-populating 'carddata' is optional. If we don't yet have it
+        // already, we fetch it from the backend.
+        if (!isset($this->cardData['carddata'])) {
+            $this->cardData = $this->carddavBackend->getCard($this->addressBookInfo['id'], $this->cardData['uri']);
+        }
+        return $this->cardData['carddata'];
 
     }
 
     /**
-     * Updates the VCard-formatted object 
-     * 
-     * @param string $cardData 
-     * @return void 
+     * Updates the VCard-formatted object
+     *
+     * @param string $cardData
+     * @return void
      */
     public function put($cardData) {
 
@@ -87,14 +88,17 @@ class Sabre_CardDAV_Card extends Sabre_DAV_File implements Sabre_CardDAV_ICard,
         // Converting to UTF-8, if needed
         $cardData = Sabre_DAV_StringUtil::ensureUTF8($cardData);
 
-        $this->carddavBackend->updateCard($this->addressBookInfo['id'],$this->cardData['uri'],$cardData);
+        $etag = $this->carddavBackend->updateCard($this->addressBookInfo['id'],$this->cardData['uri'],$cardData);
         $this->cardData['carddata'] = $cardData;
+        $this->cardData['etag'] = $etag;
+
+        return $etag;
 
     }
 
     /**
      * Deletes the card
-     * 
+     *
      * @return void
      */
     public function delete() {
@@ -104,9 +108,9 @@ class Sabre_CardDAV_Card extends Sabre_DAV_File implements Sabre_CardDAV_ICard,
     }
 
     /**
-     * Returns the mime content-type 
-     * 
-     * @return string 
+     * Returns the mime content-type
+     *
+     * @return string
      */
     public function getContentType() {
 
@@ -115,20 +119,24 @@ class Sabre_CardDAV_Card extends Sabre_DAV_File implements Sabre_CardDAV_ICard,
     }
 
     /**
-     * Returns an ETag for this object 
-     * 
-     * @return string 
+     * Returns an ETag for this object
+     *
+     * @return string
      */
     public function getETag() {
 
-        return '"' . md5($this->cardData['carddata']) . '"';
+        if (isset($this->cardData['etag'])) {
+            return $this->cardData['etag'];
+        } else {
+            return '"' . md5($this->get()) . '"';
+        }
 
     }
 
     /**
      * Returns the last modification date as a unix timestamp
-     * 
-     * @return time 
+     *
+     * @return time
      */
     public function getLastModified() {
 
@@ -137,21 +145,25 @@ class Sabre_CardDAV_Card extends Sabre_DAV_File implements Sabre_CardDAV_ICard,
     }
 
     /**
-     * Returns the size of this object in bytes 
-     * 
+     * Returns the size of this object in bytes
+     *
      * @return int
      */
     public function getSize() {
 
-        return strlen($this->cardData['carddata']);
+        if (array_key_exists('size', $this->cardData)) {
+            return $this->cardData['size'];
+        } else {
+            return strlen($this->get());
+        }
 
     }
 
     /**
      * Returns the owner principal
      *
-     * This must be a url to a principal, or null if there's no owner 
-     * 
+     * This must be a url to a principal, or null if there's no owner
+     *
      * @return string|null
      */
     public function getOwner() {
@@ -164,8 +176,8 @@ class Sabre_CardDAV_Card extends Sabre_DAV_File implements Sabre_CardDAV_ICard,
      * Returns a group principal
      *
      * This must be a url to a principal, or null if there's no owner
-     * 
-     * @return string|null 
+     *
+     * @return string|null
      */
     public function getGroup() {
 
@@ -177,13 +189,13 @@ class Sabre_CardDAV_Card extends Sabre_DAV_File implements Sabre_CardDAV_ICard,
      * Returns a list of ACE's for this node.
      *
      * Each ACE has the following properties:
-     *   * 'privilege', a string such as {DAV:}read or {DAV:}write. These are 
+     *   * 'privilege', a string such as {DAV:}read or {DAV:}write. These are
      *     currently the only supported privileges
      *   * 'principal', a url to the principal who owns the node
-     *   * 'protected' (optional), indicating that this ACE is not allowed to 
-     *      be updated. 
-     * 
-     * @return array 
+     *   * 'protected' (optional), indicating that this ACE is not allowed to
+     *      be updated.
+     *
+     * @return array
      */
     public function getACL() {
 
@@ -205,9 +217,9 @@ class Sabre_CardDAV_Card extends Sabre_DAV_File implements Sabre_CardDAV_ICard,
     /**
      * Updates the ACL
      *
-     * This method will receive a list of new ACE's. 
-     * 
-     * @param array $acl 
+     * This method will receive a list of new ACE's.
+     *
+     * @param array $acl
      * @return void
      */
     public function setACL(array $acl) {
@@ -216,5 +228,23 @@ class Sabre_CardDAV_Card extends Sabre_DAV_File implements Sabre_CardDAV_ICard,
 
     }
 
+    /**
+     * Returns the list of supported privileges for this node.
+     *
+     * The returned data structure is a list of nested privileges.
+     * See Sabre_DAVACL_Plugin::getDefaultSupportedPrivilegeSet for a simple
+     * standard structure.
+     *
+     * If null is returned from this method, the default privilege set is used,
+     * which is fine for most common usecases.
+     *
+     * @return array|null
+     */
+    public function getSupportedPrivilegeSet() {
+
+        return null;
+
+    }
+
 }
 
diff --git a/3rdparty/Sabre/CardDAV/IAddressBook.php b/3rdparty/Sabre/CardDAV/IAddressBook.php
index a0dffb30aea5c11cda8c04731c1068cc3c776089..2bc275bcf743b9ca19377527f3cc655ffa461935 100644
--- a/3rdparty/Sabre/CardDAV/IAddressBook.php
+++ b/3rdparty/Sabre/CardDAV/IAddressBook.php
@@ -4,15 +4,15 @@
  * AddressBook interface
  *
  * Implement this interface to allow a node to be recognized as an addressbook.
- * 
+ *
  * @package Sabre
  * @subpackage CardDAV
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
  * @author Evert Pot (http://www.rooftopsolutions.nl/) 
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
  */
 interface Sabre_CardDAV_IAddressBook extends Sabre_DAV_ICollection {
 
- 
+
 
 }
diff --git a/3rdparty/Sabre/CardDAV/ICard.php b/3rdparty/Sabre/CardDAV/ICard.php
index 25bcc551b73d98994a9c5c4d4d13eec939768e15..a17299316c174c45e90418c68026b6188db9d8fd 100644
--- a/3rdparty/Sabre/CardDAV/ICard.php
+++ b/3rdparty/Sabre/CardDAV/ICard.php
@@ -1,18 +1,18 @@
 <?php
 
 /**
- * Card interface 
+ * Card interface
+ *
+ * Extend the ICard interface to allow your custom nodes to be picked up as
+ * 'Cards'.
  *
- * Extend the ICard interface to allow your custom nodes to be picked up as 
- * 'Cards'. 
- * 
  * @package Sabre
  * @subpackage CardDAV
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
  * @author Evert Pot (http://www.rooftopsolutions.nl/) 
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
  */
-interface Sabre_CardDAV_ICard extends Sabre_DAV_IFile { 
+interface Sabre_CardDAV_ICard extends Sabre_DAV_IFile {
 
 }
 
diff --git a/3rdparty/Sabre/CardDAV/IDirectory.php b/3rdparty/Sabre/CardDAV/IDirectory.php
index e0d0797d285bb8e1dae530513c51d6d47e78856e..22d4afeb24a2e838754ec2a19750351bea757649 100644
--- a/3rdparty/Sabre/CardDAV/IDirectory.php
+++ b/3rdparty/Sabre/CardDAV/IDirectory.php
@@ -3,7 +3,7 @@
 /**
  * IDirectory interface
  *
- * Implement this interface to have an addressbook marked as a 'directory'. A 
+ * Implement this interface to have an addressbook marked as a 'directory'. A
  * directory is an (often) global addressbook.
  *
  * A full description can be found in the IETF draft:
@@ -11,7 +11,7 @@
  *
  * @package Sabre
  * @subpackage CardDAV
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
  * @author Evert Pot (http://www.rooftopsolutions.nl/) 
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
  */
diff --git a/3rdparty/Sabre/CardDAV/Plugin.php b/3rdparty/Sabre/CardDAV/Plugin.php
index 14c9c72b0d532e5d009135547b9136396c15ab4e..9ebec243eb0c88ee4f569ccf85e0a5aeedc42e4b 100644
--- a/3rdparty/Sabre/CardDAV/Plugin.php
+++ b/3rdparty/Sabre/CardDAV/Plugin.php
@@ -7,8 +7,8 @@
  *
  * @package Sabre
  * @subpackage CardDAV
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
- * @author Evert Pot (http://www.rooftopsolutions.nl/) 
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
  */
 class Sabre_CardDAV_Plugin extends Sabre_DAV_ServerPlugin {
@@ -24,31 +24,34 @@ class Sabre_CardDAV_Plugin extends Sabre_DAV_ServerPlugin {
     const NS_CARDDAV = 'urn:ietf:params:xml:ns:carddav';
 
     /**
-     * Add urls to this property to have them automatically exposed as 
+     * Add urls to this property to have them automatically exposed as
      * 'directories' to the user.
-     * 
+     *
      * @var array
      */
     public $directories = array();
 
     /**
-     * Server class 
+     * Server class
      *
-     * @var Sabre_DAV_Server 
+     * @var Sabre_DAV_Server
      */
     protected $server;
 
     /**
-     * Initializes the plugin 
+     * Initializes the plugin
      *
-     * @param Sabre_DAV_Server $server 
-     * @return void 
+     * @param Sabre_DAV_Server $server
+     * @return void
      */
     public function initialize(Sabre_DAV_Server $server) {
 
         /* Events */
         $server->subscribeEvent('beforeGetProperties', array($this, 'beforeGetProperties'));
+        $server->subscribeEvent('updateProperties', array($this, 'updateProperties'));
         $server->subscribeEvent('report', array($this,'report'));
+        $server->subscribeEvent('onHTMLActionsPanel', array($this,'htmlActionsPanel'));
+        $server->subscribeEvent('onBrowserPostAction', array($this,'browserPostAction'));
 
         /* Namespaces */
         $server->xmlNamespaces[self::NS_CARDDAV] = 'card';
@@ -56,11 +59,14 @@ class Sabre_CardDAV_Plugin extends Sabre_DAV_ServerPlugin {
         /* Mapping Interfaces to {DAV:}resourcetype values */
         $server->resourceTypeMapping['Sabre_CardDAV_IAddressBook'] = '{' . self::NS_CARDDAV . '}addressbook';
         $server->resourceTypeMapping['Sabre_CardDAV_IDirectory'] = '{' . self::NS_CARDDAV . '}directory';
-        
+
         /* Adding properties that may never be changed */
         $server->protectedProperties[] = '{' . self::NS_CARDDAV . '}supported-address-data';
         $server->protectedProperties[] = '{' . self::NS_CARDDAV . '}max-resource-size';
+        $server->protectedProperties[] = '{' . self::NS_CARDDAV . '}addressbook-home-set';
+        $server->protectedProperties[] = '{' . self::NS_CARDDAV . '}supported-collation-set';
 
+        $server->propertyMap['{http://calendarserver.org/ns/}me-card'] = 'Sabre_DAV_Property_Href';
 
         $this->server = $server;
 
@@ -69,7 +75,7 @@ class Sabre_CardDAV_Plugin extends Sabre_DAV_ServerPlugin {
     /**
      * Returns a list of supported features.
      *
-     * This is used in the DAV: header in the OPTIONS and PROPFIND requests. 
+     * This is used in the DAV: header in the OPTIONS and PROPFIND requests.
      *
      * @return array
      */
@@ -83,11 +89,11 @@ class Sabre_CardDAV_Plugin extends Sabre_DAV_ServerPlugin {
      * Returns a list of reports this plugin supports.
      *
      * This will be used in the {DAV:}supported-report-set property.
-     * Note that you still need to subscribe to the 'report' event to actually 
-     * implement them 
+     * Note that you still need to subscribe to the 'report' event to actually
+     * implement them
      *
      * @param string $uri
-     * @return array 
+     * @return array
      */
     public function getSupportedReportSet($uri) {
 
@@ -104,22 +110,22 @@ class Sabre_CardDAV_Plugin extends Sabre_DAV_ServerPlugin {
 
 
     /**
-     * Adds all CardDAV-specific properties 
+     * Adds all CardDAV-specific properties
      *
      * @param string $path
-     * @param Sabre_DAV_INode $node 
+     * @param Sabre_DAV_INode $node
      * @param array $requestedProperties
-     * @param array $returnedProperties 
+     * @param array $returnedProperties
      * @return void
      */
-    public function beforeGetProperties($path, Sabre_DAV_INode $node, array &$requestedProperties, array &$returnedProperties) { 
+    public function beforeGetProperties($path, Sabre_DAV_INode $node, array &$requestedProperties, array &$returnedProperties) {
 
         if ($node instanceof Sabre_DAVACL_IPrincipal) {
 
             // calendar-home-set property
             $addHome = '{' . self::NS_CARDDAV . '}addressbook-home-set';
             if (in_array($addHome,$requestedProperties)) {
-                $principalId = $node->getName(); 
+                $principalId = $node->getName();
                 $addressbookHomePath = self::ADDRESSBOOK_ROOT . '/' . $principalId . '/';
                 unset($requestedProperties[array_search($addHome, $requestedProperties)]);
                 $returnedProperties[200][$addHome] = new Sabre_DAV_Property_Href($addressbookHomePath);
@@ -135,8 +141,8 @@ class Sabre_CardDAV_Plugin extends Sabre_DAV_ServerPlugin {
 
         if ($node instanceof Sabre_CardDAV_ICard) {
 
-            // The address-data property is not supposed to be a 'real' 
-            // property, but in large chunks of the spec it does act as such. 
+            // The address-data property is not supposed to be a 'real'
+            // property, but in large chunks of the spec it does act as such.
             // Therefore we simply expose it as a property.
             $addressDataProp = '{' . self::NS_CARDDAV . '}address-data';
             if (in_array($addressDataProp, $requestedProperties)) {
@@ -151,24 +157,95 @@ class Sabre_CardDAV_Plugin extends Sabre_DAV_ServerPlugin {
             }
         }
 
+        if ($node instanceof Sabre_CardDAV_UserAddressBooks) {
+
+            $meCardProp = '{http://calendarserver.org/ns/}me-card';
+            if (in_array($meCardProp, $requestedProperties)) {
+
+                $props = $this->server->getProperties($node->getOwner(), array('{http://sabredav.org/ns}vcard-url'));
+                if (isset($props['{http://sabredav.org/ns}vcard-url'])) {
+
+                    $returnedProperties[200][$meCardProp] = new Sabre_DAV_Property_Href(
+                        $props['{http://sabredav.org/ns}vcard-url']
+                    );
+                    $pos = array_search($meCardProp, $requestedProperties);
+                    unset($requestedProperties[$pos]);
+
+                }
+
+            }
+
+        }
+
     }
 
     /**
-     * This functions handles REPORT requests specific to CardDAV 
+     * This event is triggered when a PROPPATCH method is executed
      *
-     * @param string $reportName 
+     * @param array $mutations
+     * @param array $result
+     * @param Sabre_DAV_INode $node
+     * @return void
+     */
+    public function updateProperties(&$mutations, &$result, $node) {
+
+        if (!$node instanceof Sabre_CardDAV_UserAddressBooks) {
+            return true;
+        }
+
+        $meCard = '{http://calendarserver.org/ns/}me-card';
+
+        // The only property we care about
+        if (!isset($mutations[$meCard]))
+            return true;
+
+        $value = $mutations[$meCard];
+        unset($mutations[$meCard]);
+
+        if ($value instanceof Sabre_DAV_Property_IHref) {
+            $value = $value->getHref();
+            $value = $this->server->calculateUri($value);
+        } elseif (!is_null($value)) {
+            $result[400][$meCard] = null;
+            return false;
+        }
+
+        $innerResult = $this->server->updateProperties(
+            $node->getOwner(),
+            array(
+                '{http://sabredav.org/ns}vcard-url' => $value,
+            )
+        );
+
+        $closureResult = false;
+        foreach($innerResult as $status => $props) {
+            if (is_array($props) && array_key_exists('{http://sabredav.org/ns}vcard-url', $props)) {
+                $result[$status][$meCard] = null;
+                $closureResult = ($status>=200 && $status<300);
+            }
+
+        }
+
+        return $result;
+
+    }
+
+    /**
+     * This functions handles REPORT requests specific to CardDAV
+     *
+     * @param string $reportName
      * @param DOMNode $dom
-     * @return bool 
+     * @return bool
      */
     public function report($reportName,$dom) {
 
-        switch($reportName) { 
+        switch($reportName) {
             case '{'.self::NS_CARDDAV.'}addressbook-multiget' :
                 $this->addressbookMultiGetReport($dom);
                 return false;
             case '{'.self::NS_CARDDAV.'}addressbook-query' :
                 $this->addressBookQueryReport($dom);
-                return false; 
+                return false;
             default :
                 return;
 
@@ -256,7 +333,8 @@ class Sabre_CardDAV_Plugin extends Sabre_DAV_ServerPlugin {
 
         $result = array();
         foreach($validNodes as $validNode) {
-            if ($depth==0) { 
+
+            if ($depth==0) {
                 $href = $this->server->getRequestUri();
             } else {
                 $href = $this->server->getRequestUri() . '/' . $validNode->getName();
@@ -265,7 +343,7 @@ class Sabre_CardDAV_Plugin extends Sabre_DAV_ServerPlugin {
             list($result[]) = $this->server->getPropertiesForPath($href, $query->requestedProperties, 0);
 
         }
- 
+
         $this->server->httpResponse->sendStatus(207);
         $this->server->httpResponse->setHeader('Content-Type','application/xml; charset=utf-8');
         $this->server->httpResponse->sendBody($this->server->generateMultiStatus($result));
@@ -274,17 +352,15 @@ class Sabre_CardDAV_Plugin extends Sabre_DAV_ServerPlugin {
 
     /**
      * Validates if a vcard makes it throught a list of filters.
-     * 
-     * @param string $vcardData 
-     * @param array $filters 
-     * @param string $test anyof or allof (which means OR or AND) 
-     * @return bool 
+     *
+     * @param string $vcardData
+     * @param array $filters
+     * @param string $test anyof or allof (which means OR or AND)
+     * @return bool
      */
     public function validateFilters($vcardData, array $filters, $test) {
 
         $vcard = Sabre_VObject_Reader::read($vcardData);
-        
-        $success = true;
 
         foreach($filters as $filter) {
 
@@ -299,10 +375,10 @@ class Sabre_CardDAV_Plugin extends Sabre_DAV_ServerPlugin {
 
                 // We only need to check for existence
                 $success = $isDefined;
-                
+
             } else {
 
-                $vProperties = $vcard->select($filter['name']); 
+                $vProperties = $vcard->select($filter['name']);
 
                 $results = array();
                 if ($filter['param-filters']) {
@@ -328,7 +404,7 @@ class Sabre_CardDAV_Plugin extends Sabre_DAV_ServerPlugin {
 
             } // else
 
-            // There are two conditions where we can already determine wether 
+            // There are two conditions where we can already determine whether
             // or not this filter succeeds.
             if ($test==='anyof' && $success) {
                 return true;
@@ -339,29 +415,28 @@ class Sabre_CardDAV_Plugin extends Sabre_DAV_ServerPlugin {
 
         } // foreach
 
-        // If we got all the way here, it means we haven't been able to 
+        // If we got all the way here, it means we haven't been able to
         // determine early if the test failed or not.
         //
-        // This implies for 'anyof' that the test failed, and for 'allof' that 
+        // This implies for 'anyof' that the test failed, and for 'allof' that
         // we succeeded. Sounds weird, but makes sense.
         return $test==='allof';
 
     }
 
     /**
-     * Validates if a param-filter can be applied to a specific property. 
-     * 
-     * @todo currently we're only validating the first parameter of the passed 
+     * Validates if a param-filter can be applied to a specific property.
+     *
+     * @todo currently we're only validating the first parameter of the passed
      *       property. Any subsequence parameters with the same name are
      *       ignored.
-     * @param Sabre_VObject_Property $vProperty 
-     * @param array $filters 
-     * @param string $test 
-     * @return bool 
+     * @param array $vProperties
+     * @param array $filters
+     * @param string $test
+     * @return bool
      */
     protected function validateParamFilters(array $vProperties, array $filters, $test) {
 
-        $success = false;
         foreach($filters as $filter) {
 
             $isDefined = false;
@@ -377,17 +452,16 @@ class Sabre_CardDAV_Plugin extends Sabre_DAV_ServerPlugin {
                     $success = true;
                 }
 
-            // If there's no text-match, we can just check for existence 
+            // If there's no text-match, we can just check for existence
             } elseif (!$filter['text-match'] || !$isDefined) {
 
                 $success = $isDefined;
-                
+
             } else {
 
-                $texts = array();
                 $success = false;
                 foreach($vProperties as $vProperty) {
-                    // If we got all the way here, we'll need to validate the 
+                    // If we got all the way here, we'll need to validate the
                     // text-match filter.
                     $success = Sabre_DAV_StringUtil::textMatch($vProperty[$filter['name']]->value, $filter['text-match']['value'], $filter['text-match']['collation'], $filter['text-match']['match-type']);
                     if ($success) break;
@@ -398,7 +472,7 @@ class Sabre_CardDAV_Plugin extends Sabre_DAV_ServerPlugin {
 
             } // else
 
-            // There are two conditions where we can already determine wether 
+            // There are two conditions where we can already determine whether
             // or not this filter succeeds.
             if ($test==='anyof' && $success) {
                 return true;
@@ -407,24 +481,24 @@ class Sabre_CardDAV_Plugin extends Sabre_DAV_ServerPlugin {
                 return false;
             }
 
-        } 
+        }
 
-        // If we got all the way here, it means we haven't been able to 
+        // If we got all the way here, it means we haven't been able to
         // determine early if the test failed or not.
         //
-        // This implies for 'anyof' that the test failed, and for 'allof' that 
+        // This implies for 'anyof' that the test failed, and for 'allof' that
         // we succeeded. Sounds weird, but makes sense.
         return $test==='allof';
 
     }
 
     /**
-     * Validates if a text-filter can be applied to a specific property. 
-     * 
+     * Validates if a text-filter can be applied to a specific property.
+     *
      * @param array $texts
-     * @param array $filters 
-     * @param string $test 
-     * @return bool 
+     * @param array $filters
+     * @param string $test
+     * @return bool
      */
     protected function validateTextMatches(array $texts, array $filters, $test) {
 
@@ -440,7 +514,7 @@ class Sabre_CardDAV_Plugin extends Sabre_DAV_ServerPlugin {
             if ($filter['negate-condition']) {
                 $success = !$success;
             }
-            
+
             if ($success && $test==='anyof')
                 return true;
 
@@ -450,14 +524,64 @@ class Sabre_CardDAV_Plugin extends Sabre_DAV_ServerPlugin {
 
         }
 
-        // If we got all the way here, it means we haven't been able to 
+        // If we got all the way here, it means we haven't been able to
         // determine early if the test failed or not.
         //
-        // This implies for 'anyof' that the test failed, and for 'allof' that 
+        // This implies for 'anyof' that the test failed, and for 'allof' that
         // we succeeded. Sounds weird, but makes sense.
         return $test==='allof';
 
     }
 
+    /**
+     * This method is used to generate HTML output for the
+     * Sabre_DAV_Browser_Plugin. This allows us to generate an interface users
+     * can use to create new calendars.
+     *
+     * @param Sabre_DAV_INode $node
+     * @param string $output
+     * @return bool
+     */
+    public function htmlActionsPanel(Sabre_DAV_INode $node, &$output) {
+
+        if (!$node instanceof Sabre_CardDAV_UserAddressBooks)
+            return;
+
+        $output.= '<tr><td colspan="2"><form method="post" action="">
+            <h3>Create new address book</h3>
+            <input type="hidden" name="sabreAction" value="mkaddressbook" />
+            <label>Name (uri):</label> <input type="text" name="name" /><br />
+            <label>Display name:</label> <input type="text" name="{DAV:}displayname" /><br />
+            <input type="submit" value="create" />
+            </form>
+            </td></tr>';
+
+        return false;
+
+    }
+
+    /**
+     * This method allows us to intercept the 'mkcalendar' sabreAction. This
+     * action enables the user to create new calendars from the browser plugin.
+     *
+     * @param string $uri
+     * @param string $action
+     * @param array $postVars
+     * @return bool
+     */
+    public function browserPostAction($uri, $action, array $postVars) {
+
+        if ($action!=='mkaddressbook')
+            return;
+
+        $resourceType = array('{DAV:}collection','{urn:ietf:params:xml:ns:carddav}addressbook');
+        $properties = array();
+        if (isset($postVars['{DAV:}displayname'])) {
+            $properties['{DAV:}displayname'] = $postVars['{DAV:}displayname'];
+        }
+        $this->server->createCollection($uri . '/' . $postVars['name'],$resourceType,$properties);
+        return false;
+
+    }
 
 }
diff --git a/3rdparty/Sabre/CardDAV/Property/SupportedAddressData.php b/3rdparty/Sabre/CardDAV/Property/SupportedAddressData.php
index d57d3a6e7bdfb3494b4f48300029e553e3c4f57c..36d9306e7aabd1ce55525922ce7e574a0acc640d 100644
--- a/3rdparty/Sabre/CardDAV/Property/SupportedAddressData.php
+++ b/3rdparty/Sabre/CardDAV/Property/SupportedAddressData.php
@@ -4,11 +4,11 @@
  * Supported-address-data property
  *
  * This property is a representation of the supported-address-data property
- * in the CardDAV namespace. 
+ * in the CardDAV namespace.
  *
  * @package Sabre
  * @subpackage CardDAV
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
  * @author Evert Pot (http://www.rooftopsolutions.nl/) 
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
  */
@@ -16,15 +16,15 @@ class Sabre_CardDAV_Property_SupportedAddressData extends Sabre_DAV_Property {
 
     /**
      * supported versions
-     * 
-     * @var array 
+     *
+     * @var array
      */
     protected $supportedData = array();
-    
+
     /**
-     * Creates the property 
-     * 
-     * @param array $components 
+     * Creates the property
+     *
+     * @param array|null $supportedData
      */
     public function __construct(array $supportedData = null) {
 
@@ -35,22 +35,22 @@ class Sabre_CardDAV_Property_SupportedAddressData extends Sabre_DAV_Property {
             );
         }
 
-       $this->supportedData = $supportedData; 
+       $this->supportedData = $supportedData;
 
     }
-    
+
     /**
-     * Serializes the property in a DOMDocument 
-     * 
-     * @param Sabre_DAV_Server $server 
-     * @param DOMElement $node 
+     * Serializes the property in a DOMDocument
+     *
+     * @param Sabre_DAV_Server $server
+     * @param DOMElement $node
      * @return void
      */
     public function serialize(Sabre_DAV_Server $server,DOMElement $node) {
 
         $doc = $node->ownerDocument;
 
-        $prefix = 
+        $prefix =
             isset($server->xmlNamespaces[Sabre_CardDAV_Plugin::NS_CARDDAV]) ?
             $server->xmlNamespaces[Sabre_CardDAV_Plugin::NS_CARDDAV] :
             'card';
diff --git a/3rdparty/Sabre/CardDAV/UserAddressBooks.php b/3rdparty/Sabre/CardDAV/UserAddressBooks.php
index e9f2de7f741e0ed553911b3acf61e973390932ed..3f11fb11238ba6274c2dbed7fc19bf9e27c3f290 100644
--- a/3rdparty/Sabre/CardDAV/UserAddressBooks.php
+++ b/3rdparty/Sabre/CardDAV/UserAddressBooks.php
@@ -7,7 +7,7 @@
  *
  * @package Sabre
  * @subpackage CardDAV
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
  * @author Evert Pot (http://www.rooftopsolutions.nl/) 
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
  */
@@ -15,47 +15,47 @@ class Sabre_CardDAV_UserAddressBooks extends Sabre_DAV_Collection implements Sab
 
     /**
      * Principal uri
-     * 
-     * @var array 
+     *
+     * @var array
      */
     protected $principalUri;
 
     /**
-     * carddavBackend 
-     * 
-     * @var Sabre_CardDAV_Backend_Abstract 
+     * carddavBackend
+     *
+     * @var Sabre_CardDAV_Backend_Abstract
      */
     protected $carddavBackend;
 
     /**
-     * Constructor 
-     * 
-     * @param Sabre_CardDAV_Backend_Abstract $carddavBackend 
-     * @param string $principalUri 
+     * Constructor
+     *
+     * @param Sabre_CardDAV_Backend_Abstract $carddavBackend
+     * @param string $principalUri
      */
     public function __construct(Sabre_CardDAV_Backend_Abstract $carddavBackend, $principalUri) {
 
         $this->carddavBackend = $carddavBackend;
         $this->principalUri = $principalUri;
-       
+
     }
 
     /**
-     * Returns the name of this object 
-     * 
+     * Returns the name of this object
+     *
      * @return string
      */
     public function getName() {
-      
+
         list(,$name) = Sabre_DAV_URLUtil::splitPath($this->principalUri);
-        return $name; 
+        return $name;
 
     }
 
     /**
-     * Updates the name of this object 
-     * 
-     * @param string $name 
+     * Updates the name of this object
+     *
+     * @param string $name
      * @return void
      */
     public function setName($name) {
@@ -65,8 +65,8 @@ class Sabre_CardDAV_UserAddressBooks extends Sabre_DAV_Collection implements Sab
     }
 
     /**
-     * Deletes this object 
-     * 
+     * Deletes this object
+     *
      * @return void
      */
     public function delete() {
@@ -76,13 +76,13 @@ class Sabre_CardDAV_UserAddressBooks extends Sabre_DAV_Collection implements Sab
     }
 
     /**
-     * Returns the last modification date 
-     * 
-     * @return int 
+     * Returns the last modification date
+     *
+     * @return int
      */
     public function getLastModified() {
 
-        return null; 
+        return null;
 
     }
 
@@ -90,9 +90,9 @@ class Sabre_CardDAV_UserAddressBooks extends Sabre_DAV_Collection implements Sab
      * Creates a new file under this object.
      *
      * This is currently not allowed
-     * 
-     * @param string $filename 
-     * @param resource $data 
+     *
+     * @param string $filename
+     * @param resource $data
      * @return void
      */
     public function createFile($filename, $data=null) {
@@ -105,8 +105,8 @@ class Sabre_CardDAV_UserAddressBooks extends Sabre_DAV_Collection implements Sab
      * Creates a new directory under this object.
      *
      * This is currently not allowed.
-     * 
-     * @param string $filename 
+     *
+     * @param string $filename
      * @return void
      */
     public function createDirectory($filename) {
@@ -116,8 +116,8 @@ class Sabre_CardDAV_UserAddressBooks extends Sabre_DAV_Collection implements Sab
     }
 
     /**
-     * Returns a single calendar, by name 
-     * 
+     * Returns a single calendar, by name
+     *
      * @param string $name
      * @todo needs optimizing
      * @return Sabre_CardDAV_AddressBook
@@ -129,14 +129,14 @@ class Sabre_CardDAV_UserAddressBooks extends Sabre_DAV_Collection implements Sab
                 return $child;
 
         }
-        throw new Sabre_DAV_Exception_FileNotFound('Addressbook with name \'' . $name . '\' could not be found');
+        throw new Sabre_DAV_Exception_NotFound('Addressbook with name \'' . $name . '\' could not be found');
 
     }
 
     /**
-     * Returns a list of addressbooks 
-     * 
-     * @return array 
+     * Returns a list of addressbooks
+     *
+     * @return array
      */
     public function getChildren() {
 
@@ -150,11 +150,11 @@ class Sabre_CardDAV_UserAddressBooks extends Sabre_DAV_Collection implements Sab
     }
 
     /**
-     * Creates a new addressbook 
-     * 
+     * Creates a new addressbook
+     *
      * @param string $name
-     * @param array $resourceType 
-     * @param array $properties 
+     * @param array $resourceType
+     * @param array $properties
      * @return void
      */
     public function createExtendedCollection($name, array $resourceType, array $properties) {
@@ -169,8 +169,8 @@ class Sabre_CardDAV_UserAddressBooks extends Sabre_DAV_Collection implements Sab
     /**
      * Returns the owner principal
      *
-     * This must be a url to a principal, or null if there's no owner 
-     * 
+     * This must be a url to a principal, or null if there's no owner
+     *
      * @return string|null
      */
     public function getOwner() {
@@ -183,8 +183,8 @@ class Sabre_CardDAV_UserAddressBooks extends Sabre_DAV_Collection implements Sab
      * Returns a group principal
      *
      * This must be a url to a principal, or null if there's no owner
-     * 
-     * @return string|null 
+     *
+     * @return string|null
      */
     public function getGroup() {
 
@@ -196,13 +196,13 @@ class Sabre_CardDAV_UserAddressBooks extends Sabre_DAV_Collection implements Sab
      * Returns a list of ACE's for this node.
      *
      * Each ACE has the following properties:
-     *   * 'privilege', a string such as {DAV:}read or {DAV:}write. These are 
+     *   * 'privilege', a string such as {DAV:}read or {DAV:}write. These are
      *     currently the only supported privileges
      *   * 'principal', a url to the principal who owns the node
-     *   * 'protected' (optional), indicating that this ACE is not allowed to 
-     *      be updated. 
-     * 
-     * @return array 
+     *   * 'protected' (optional), indicating that this ACE is not allowed to
+     *      be updated.
+     *
+     * @return array
      */
     public function getACL() {
 
@@ -225,9 +225,9 @@ class Sabre_CardDAV_UserAddressBooks extends Sabre_DAV_Collection implements Sab
     /**
      * Updates the ACL
      *
-     * This method will receive a list of new ACE's. 
-     * 
-     * @param array $acl 
+     * This method will receive a list of new ACE's.
+     *
+     * @param array $acl
      * @return void
      */
     public function setACL(array $acl) {
@@ -236,5 +236,22 @@ class Sabre_CardDAV_UserAddressBooks extends Sabre_DAV_Collection implements Sab
 
     }
 
+    /**
+     * Returns the list of supported privileges for this node.
+     *
+     * The returned data structure is a list of nested privileges.
+     * See Sabre_DAVACL_Plugin::getDefaultSupportedPrivilegeSet for a simple
+     * standard structure.
+     *
+     * If null is returned from this method, the default privilege set is used,
+     * which is fine for most common usecases.
+     *
+     * @return array|null
+     */
+    public function getSupportedPrivilegeSet() {
+
+        return null;
+
+    }
 
 }
diff --git a/3rdparty/Sabre/CardDAV/Version.php b/3rdparty/Sabre/CardDAV/Version.php
index 900fbf5e75c22861fd27901ea93ae8fe81c211b5..811b929e3978d11661901239b228573a3f0f2ab8 100644
--- a/3rdparty/Sabre/CardDAV/Version.php
+++ b/3rdparty/Sabre/CardDAV/Version.php
@@ -4,10 +4,10 @@
  * Version Class
  *
  * This class contains the Sabre_CardDAV version information
- * 
+ *
  * @package Sabre
  * @subpackage CardDAV 
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
  * @author Evert Pot (http://www.rooftopsolutions.nl/)
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
  */
@@ -16,7 +16,7 @@ class Sabre_CardDAV_Version {
     /**
      * Full version number
      */
-    const VERSION = '1.5.3';
+    const VERSION = '1.6.1';
 
     /**
      * Stability : alpha, beta, stable
diff --git a/3rdparty/Sabre/CardDAV/includes.php b/3rdparty/Sabre/CardDAV/includes.php
new file mode 100644
index 0000000000000000000000000000000000000000..c3b8c04b077584a2a9d168a5e0dc99fcedbf477d
--- /dev/null
+++ b/3rdparty/Sabre/CardDAV/includes.php
@@ -0,0 +1,32 @@
+<?php
+
+/**
+ * Sabre_CardDAV includes file
+ *
+ * Including this file will automatically include all files from the
+ * Sabre_CardDAV package.
+ *
+ * This often allows faster loadtimes, as autoload-speed is often quite slow.
+ *
+ * @package Sabre
+ * @subpackage CardDAV
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
+ * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
+ */
+
+// Begin includes
+include __DIR__ . '/AddressBookQueryParser.php';
+include __DIR__ . '/AddressBookRoot.php';
+include __DIR__ . '/Backend/Abstract.php';
+include __DIR__ . '/Backend/PDO.php';
+include __DIR__ . '/IAddressBook.php';
+include __DIR__ . '/ICard.php';
+include __DIR__ . '/IDirectory.php';
+include __DIR__ . '/Plugin.php';
+include __DIR__ . '/Property/SupportedAddressData.php';
+include __DIR__ . '/UserAddressBooks.php';
+include __DIR__ . '/Version.php';
+include __DIR__ . '/AddressBook.php';
+include __DIR__ . '/Card.php';
+// End includes
diff --git a/3rdparty/Sabre/DAV/Auth/Backend/AbstractBasic.php b/3rdparty/Sabre/DAV/Auth/Backend/AbstractBasic.php
index 11bab8c7af78b024f568a753af54af8c0be93444..1e89b84f9a1811cb1cbba40f9b8c5ef61513b2d7 100644
--- a/3rdparty/Sabre/DAV/Auth/Backend/AbstractBasic.php
+++ b/3rdparty/Sabre/DAV/Auth/Backend/AbstractBasic.php
@@ -8,9 +8,9 @@
  *
  * @package Sabre
  * @subpackage DAV
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
  * @author James David Low (http://jameslow.com/)
- * @author Evert Pot (http://www.rooftopsolutions.nl/) 
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
  */
 abstract class Sabre_DAV_Auth_Backend_AbstractBasic implements Sabre_DAV_Auth_IBackend {
@@ -28,6 +28,8 @@ abstract class Sabre_DAV_Auth_Backend_AbstractBasic implements Sabre_DAV_Auth_IB
      * This method should return true or false depending on if login
      * succeeded.
      *
+     * @param string $username
+     * @param string $password
      * @return bool
      */
     abstract protected function validateUserPass($username, $password);
@@ -47,13 +49,15 @@ abstract class Sabre_DAV_Auth_Backend_AbstractBasic implements Sabre_DAV_Auth_IB
     /**
      * Authenticates the user based on the current request.
      *
-     * If authentication is succesful, true must be returned.
+     * If authentication is successful, true must be returned.
      * If authentication fails, an exception must be thrown.
      *
+     * @param Sabre_DAV_Server $server
+     * @param string $realm
      * @throws Sabre_DAV_Exception_NotAuthenticated
      * @return bool
      */
-    public function authenticate(Sabre_DAV_Server $server,$realm) {
+    public function authenticate(Sabre_DAV_Server $server, $realm) {
 
         $auth = new Sabre_HTTP_BasicAuth();
         $auth->setHTTPRequest($server->httpRequest);
@@ -75,5 +79,5 @@ abstract class Sabre_DAV_Auth_Backend_AbstractBasic implements Sabre_DAV_Auth_IB
     }
 
 
-} 
+}
 
diff --git a/3rdparty/Sabre/DAV/Auth/Backend/AbstractDigest.php b/3rdparty/Sabre/DAV/Auth/Backend/AbstractDigest.php
index 5bdc72753ece623b8bb5c9634c42d7494ba7ccf5..9833928b9769c33257b46cb217f46f837d835e79 100644
--- a/3rdparty/Sabre/DAV/Auth/Backend/AbstractDigest.php
+++ b/3rdparty/Sabre/DAV/Auth/Backend/AbstractDigest.php
@@ -4,12 +4,12 @@
  * HTTP Digest authentication backend class
  *
  * This class can be used by authentication objects wishing to use HTTP Digest
- * Most of the digest logic is handled, implementors just need to worry about 
- * the getDigestHash method 
+ * Most of the digest logic is handled, implementors just need to worry about
+ * the getDigestHash method
  *
  * @package Sabre
  * @subpackage DAV
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
  * @author Evert Pot (http://www.rooftopsolutions.nl/) 
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
  */
@@ -17,7 +17,7 @@ abstract class Sabre_DAV_Auth_Backend_AbstractDigest implements Sabre_DAV_Auth_I
 
     /**
      * This variable holds the currently logged in username.
-     * 
+     *
      * @var array|null
      */
     protected $currentUser;
@@ -25,24 +25,26 @@ abstract class Sabre_DAV_Auth_Backend_AbstractDigest implements Sabre_DAV_Auth_I
     /**
      * Returns a users digest hash based on the username and realm.
      *
-     * If the user was not known, null must be returned. 
-     * 
+     * If the user was not known, null must be returned.
+     *
      * @param string $realm
-     * @param string $username 
-     * @return string|null 
+     * @param string $username
+     * @return string|null
      */
-    abstract public function getDigestHash($realm,$username);
+    abstract public function getDigestHash($realm, $username);
 
     /**
      * Authenticates the user based on the current request.
      *
-     * If authentication is succesful, true must be returned.
+     * If authentication is successful, true must be returned.
      * If authentication fails, an exception must be thrown.
      *
+     * @param Sabre_DAV_Server $server
+     * @param string $realm
      * @throws Sabre_DAV_Exception_NotAuthenticated
-     * @return bool 
+     * @return bool
      */
-    public function authenticate(Sabre_DAV_Server $server,$realm) {
+    public function authenticate(Sabre_DAV_Server $server, $realm) {
 
         $digest = new Sabre_HTTP_DigestAuth();
 
@@ -83,9 +85,9 @@ abstract class Sabre_DAV_Auth_Backend_AbstractDigest implements Sabre_DAV_Auth_I
     }
 
     /**
-     * Returns the currently logged in username. 
-     * 
-     * @return string|null 
+     * Returns the currently logged in username.
+     *
+     * @return string|null
      */
     public function getCurrentUser() {
 
diff --git a/3rdparty/Sabre/DAV/Auth/Backend/Apache.php b/3rdparty/Sabre/DAV/Auth/Backend/Apache.php
index 6bcd76bdcb0ca5c81f2a7d9ad167c03ed1a92054..d4294ea4d86dcaf87247acdbd966ce315f876b6f 100644
--- a/3rdparty/Sabre/DAV/Auth/Backend/Apache.php
+++ b/3rdparty/Sabre/DAV/Auth/Backend/Apache.php
@@ -4,34 +4,36 @@
  * Apache authenticator
  *
  * This authentication backend assumes that authentication has been
- * conifgured in apache, rather than within SabreDAV.
+ * configured in apache, rather than within SabreDAV.
  *
  * Make sure apache is properly configured for this to work.
  *
  * @package Sabre
  * @subpackage DAV
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
  * @author Evert Pot (http://www.rooftopsolutions.nl/) 
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
  */
 class Sabre_DAV_Auth_Backend_Apache implements Sabre_DAV_Auth_IBackend {
 
     /**
-     * Current apache user 
-     * 
-     * @var string 
+     * Current apache user
+     *
+     * @var string
      */
     protected $remoteUser;
-    
+
     /**
      * Authenticates the user based on the current request.
      *
-     * If authentication is succesful, true must be returned.
+     * If authentication is successful, true must be returned.
      * If authentication fails, an exception must be thrown.
      *
-     * @return bool 
+     * @param Sabre_DAV_Server $server
+     * @param string $realm
+     * @return bool
      */
-    public function authenticate(Sabre_DAV_Server $server,$realm) {
+    public function authenticate(Sabre_DAV_Server $server, $realm) {
 
         $remoteUser = $server->httpRequest->getRawServerValue('REMOTE_USER');
         if (is_null($remoteUser)) {
@@ -47,7 +49,7 @@ class Sabre_DAV_Auth_Backend_Apache implements Sabre_DAV_Auth_IBackend {
      * Returns information about the currently logged in user.
      *
      * If nobody is currently logged in, this method should return null.
-     * 
+     *
      * @return array|null
      */
     public function getCurrentUser() {
diff --git a/3rdparty/Sabre/DAV/Auth/Backend/File.php b/3rdparty/Sabre/DAV/Auth/Backend/File.php
index db1f04c477250bec0aab04cb7adbac38af7939e5..de308d64a6728c69be916c6d39362080d004db1f 100644
--- a/3rdparty/Sabre/DAV/Auth/Backend/File.php
+++ b/3rdparty/Sabre/DAV/Auth/Backend/File.php
@@ -4,29 +4,28 @@
  * This is an authentication backend that uses a file to manage passwords.
  *
  * The backend file must conform to Apache's htdigest format
- * 
+ *
  * @package Sabre
  * @subpackage DAV
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
  * @author Evert Pot (http://www.rooftopsolutions.nl/) 
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
  */
 class Sabre_DAV_Auth_Backend_File extends Sabre_DAV_Auth_Backend_AbstractDigest {
 
     /**
-     * List of users 
-     * 
+     * List of users
+     *
      * @var array
      */
     protected $users = array();
 
     /**
-     * Creates the backend object. 
+     * Creates the backend object.
      *
      * If the filename argument is passed in, it will parse out the specified file fist.
-     * 
-     * @param string $filename 
-     * @return void
+     *
+     * @param string|null $filename
      */
     public function __construct($filename=null) {
 
@@ -38,22 +37,22 @@ class Sabre_DAV_Auth_Backend_File extends Sabre_DAV_Auth_Backend_AbstractDigest
     /**
      * Loads an htdigest-formatted file. This method can be called multiple times if
      * more than 1 file is used.
-     * 
-     * @param string $filename 
+     *
+     * @param string $filename
      * @return void
      */
     public function loadFile($filename) {
 
         foreach(file($filename,FILE_IGNORE_NEW_LINES) as $line) {
 
-            if (substr_count($line, ":") !== 2) 
+            if (substr_count($line, ":") !== 2)
                 throw new Sabre_DAV_Exception('Malformed htdigest file. Every line should contain 2 colons');
-            
+
             list($username,$realm,$A1) = explode(':',$line);
 
             if (!preg_match('/^[a-zA-Z0-9]{32}$/', $A1))
                 throw new Sabre_DAV_Exception('Malformed htdigest file. Invalid md5 hash');
-                
+
             $this->users[$realm . ':' . $username] = $A1;
 
         }
@@ -62,10 +61,10 @@ class Sabre_DAV_Auth_Backend_File extends Sabre_DAV_Auth_Backend_AbstractDigest
 
     /**
      * Returns a users' information
-     * 
-     * @param string $realm 
-     * @param string $username 
-     * @return string 
+     *
+     * @param string $realm
+     * @param string $username
+     * @return string
      */
     public function getDigestHash($realm, $username) {
 
diff --git a/3rdparty/Sabre/DAV/Auth/Backend/PDO.php b/3rdparty/Sabre/DAV/Auth/Backend/PDO.php
index 0301503601e2f853c6d40d3c9252b0f08bc6ab35..eac18a23fbbfb3bb46180ec3cb5d0cbd02601dc5 100644
--- a/3rdparty/Sabre/DAV/Auth/Backend/PDO.php
+++ b/3rdparty/Sabre/DAV/Auth/Backend/PDO.php
@@ -4,38 +4,37 @@
  * This is an authentication backend that uses a file to manage passwords.
  *
  * The backend file must conform to Apache's htdigest format
- * 
+ *
  * @package Sabre
  * @subpackage DAV
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
  * @author Evert Pot (http://www.rooftopsolutions.nl/) 
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
  */
 class Sabre_DAV_Auth_Backend_PDO extends Sabre_DAV_Auth_Backend_AbstractDigest {
 
     /**
-     * Reference to PDO connection 
-     * 
-     * @var PDO 
+     * Reference to PDO connection
+     *
+     * @var PDO
      */
     protected $pdo;
 
     /**
-     * PDO table name we'll be using  
-     * 
+     * PDO table name we'll be using
+     *
      * @var string
      */
     protected $tableName;
 
 
     /**
-     * Creates the backend object. 
+     * Creates the backend object.
      *
      * If the filename argument is passed in, it will parse out the specified file fist.
-     * 
-     * @param string $filename
-     * @param string $tableName The PDO table name to use 
-     * @return void
+     *
+     * @param PDO $pdo
+     * @param string $tableName The PDO table name to use
      */
     public function __construct(PDO $pdo, $tableName = 'users') {
 
@@ -45,15 +44,15 @@ class Sabre_DAV_Auth_Backend_PDO extends Sabre_DAV_Auth_Backend_AbstractDigest {
     }
 
     /**
-     * Returns the digest hash for a user. 
-     * 
-     * @param string $realm 
-     * @param string $username 
-     * @return string|null 
+     * Returns the digest hash for a user.
+     *
+     * @param string $realm
+     * @param string $username
+     * @return string|null
      */
     public function getDigestHash($realm,$username) {
 
-        $stmt = $this->pdo->prepare('SELECT username, digesta1 FROM `'.$this->tableName.'` WHERE username = ?');
+        $stmt = $this->pdo->prepare('SELECT username, digesta1 FROM '.$this->tableName.' WHERE username = ?');
         $stmt->execute(array($username));
         $result = $stmt->fetchAll();
 
diff --git a/3rdparty/Sabre/DAV/Auth/IBackend.php b/3rdparty/Sabre/DAV/Auth/IBackend.php
index 1f67af4c2d90eabc8eacfb862b15c17592a28595..5be5d1bc93d7807a9a9eecd8b87100c19be30d5e 100644
--- a/3rdparty/Sabre/DAV/Auth/IBackend.php
+++ b/3rdparty/Sabre/DAV/Auth/IBackend.php
@@ -5,7 +5,7 @@
  *
  * @package Sabre
  * @subpackage DAV
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
  * @author Evert Pot (http://www.rooftopsolutions.nl/) 
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
  */
@@ -14,18 +14,20 @@ interface Sabre_DAV_Auth_IBackend {
     /**
      * Authenticates the user based on the current request.
      *
-     * If authentication is succesful, true must be returned.
+     * If authentication is successful, true must be returned.
      * If authentication fails, an exception must be thrown.
      *
-     * @return bool 
+     * @param Sabre_DAV_Server $server
+     * @param string $realm
+     * @return bool
      */
-    function authenticate(Sabre_DAV_Server $server,$realm); 
+    function authenticate(Sabre_DAV_Server $server,$realm);
 
     /**
      * Returns information about the currently logged in username.
      *
      * If nobody is currently logged in, this method should return null.
-     * 
+     *
      * @return string|null
      */
     function getCurrentUser();
diff --git a/3rdparty/Sabre/DAV/Auth/Plugin.php b/3rdparty/Sabre/DAV/Auth/Plugin.php
index f3718fcf469d53c7039523c98de6f697fd3512bf..55a4e3916741c9a7d728a2c54ae0d5ba4f127eba 100644
--- a/3rdparty/Sabre/DAV/Auth/Plugin.php
+++ b/3rdparty/Sabre/DAV/Auth/Plugin.php
@@ -2,48 +2,47 @@
 
 /**
  * This plugin provides Authentication for a WebDAV server.
- * 
+ *
  * It relies on a Backend object, which provides user information.
  *
  * Additionally, it provides support for:
  *  * {DAV:}current-user-principal property from RFC5397
  *  * {DAV:}principal-collection-set property from RFC3744
- * 
+ *
  * @package Sabre
  * @subpackage DAV
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
- * @author Evert Pot (http://www.rooftopsolutions.nl/) 
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
  */
 class Sabre_DAV_Auth_Plugin extends Sabre_DAV_ServerPlugin {
 
     /**
-     * Reference to main server object 
-     * 
-     * @var Sabre_DAV_Server 
+     * Reference to main server object
+     *
+     * @var Sabre_DAV_Server
      */
     private $server;
 
     /**
      * Authentication backend
-     * 
-     * @var Sabre_DAV_Auth_Backend_Abstract 
+     *
+     * @var Sabre_DAV_Auth_IBackend
      */
     private $authBackend;
 
     /**
-     * The authentication realm. 
-     * 
-     * @var string 
+     * The authentication realm.
+     *
+     * @var string
      */
     private $realm;
 
     /**
-     * __construct 
-     * 
-     * @param Sabre_DAV_Auth_Backend_Abstract $authBackend 
-     * @param string $realm 
-     * @return void
+     * __construct
+     *
+     * @param Sabre_DAV_Auth_IBackend $authBackend
+     * @param string $realm
      */
     public function __construct(Sabre_DAV_Auth_IBackend $authBackend, $realm) {
 
@@ -53,9 +52,9 @@ class Sabre_DAV_Auth_Plugin extends Sabre_DAV_ServerPlugin {
     }
 
     /**
-     * Initializes the plugin. This function is automatically called by the server  
-     * 
-     * @param Sabre_DAV_Server $server 
+     * Initializes the plugin. This function is automatically called by the server
+     *
+     * @param Sabre_DAV_Server $server
      * @return void
      */
     public function initialize(Sabre_DAV_Server $server) {
@@ -67,11 +66,11 @@ class Sabre_DAV_Auth_Plugin extends Sabre_DAV_ServerPlugin {
 
     /**
      * Returns a plugin name.
-     * 
+     *
      * Using this name other plugins will be able to access other plugins
-     * using Sabre_DAV_Server::getPlugin 
-     * 
-     * @return string 
+     * using Sabre_DAV_Server::getPlugin
+     *
+     * @return string
      */
     public function getPluginName() {
 
@@ -81,10 +80,10 @@ class Sabre_DAV_Auth_Plugin extends Sabre_DAV_ServerPlugin {
 
     /**
      * Returns the current users' principal uri.
-     * 
-     * If nobody is logged in, this will return null. 
-     * 
-     * @return string|null 
+     *
+     * If nobody is logged in, this will return null.
+     *
+     * @return string|null
      */
     public function getCurrentUser() {
 
@@ -97,10 +96,11 @@ class Sabre_DAV_Auth_Plugin extends Sabre_DAV_ServerPlugin {
 
     /**
      * This method is called before any HTTP method and forces users to be authenticated
-     * 
+     *
      * @param string $method
+     * @param string $uri
      * @throws Sabre_DAV_Exception_NotAuthenticated
-     * @return bool 
+     * @return bool
      */
     public function beforeMethod($method, $uri) {
 
diff --git a/3rdparty/Sabre/DAV/Browser/GuessContentType.php b/3rdparty/Sabre/DAV/Browser/GuessContentType.php
index ee8c698d782412ef00ba66327a3053ec0c8bd0c6..b6c00d461cb95e3ac778d5810b94a439b26d99c9 100644
--- a/3rdparty/Sabre/DAV/Browser/GuessContentType.php
+++ b/3rdparty/Sabre/DAV/Browser/GuessContentType.php
@@ -10,10 +10,10 @@
  * There's really no accurate, fast and portable way to determine the contenttype
  * so this extension does what the rest of the world does, and guesses it based
  * on the file extension.
- * 
+ *
  * @package Sabre
  * @subpackage DAV
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
  * @author Evert Pot (http://www.rooftopsolutions.nl/) 
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
  */
@@ -43,9 +43,9 @@ class Sabre_DAV_Browser_GuessContentType extends Sabre_DAV_ServerPlugin {
     );
 
     /**
-     * Initializes the plugin 
-     * 
-     * @param Sabre_DAV_Server $server 
+     * Initializes the plugin
+     *
+     * @param Sabre_DAV_Server $server
      * @return void
      */
     public function initialize(Sabre_DAV_Server $server) {
@@ -57,16 +57,16 @@ class Sabre_DAV_Browser_GuessContentType extends Sabre_DAV_ServerPlugin {
     }
 
     /**
-     * Handler for teh afterGetProperties event 
-     * 
-     * @param string $path 
-     * @param array $properties 
+     * Handler for teh afterGetProperties event
+     *
+     * @param string $path
+     * @param array $properties
      * @return void
      */
     public function afterGetProperties($path, &$properties) {
 
         if (array_key_exists('{DAV:}getcontenttype', $properties[404])) {
-           
+
             list(, $fileName) = Sabre_DAV_URLUtil::splitPath($path);
             $contentType = $this->getContentType($fileName);
 
@@ -81,9 +81,9 @@ class Sabre_DAV_Browser_GuessContentType extends Sabre_DAV_ServerPlugin {
 
     /**
      * Simple method to return the contenttype
-     * 
-     * @param string $fileName 
-     * @return string 
+     *
+     * @param string $fileName
+     * @return string
      */
     protected function getContentType($fileName) {
 
diff --git a/3rdparty/Sabre/DAV/Browser/MapGetToPropFind.php b/3rdparty/Sabre/DAV/Browser/MapGetToPropFind.php
index a66b57a3a90ac89ba9038cf0caa085f194c536fd..1588488764133f951cf103fad141763de653154e 100644
--- a/3rdparty/Sabre/DAV/Browser/MapGetToPropFind.php
+++ b/3rdparty/Sabre/DAV/Browser/MapGetToPropFind.php
@@ -1,30 +1,30 @@
 <?php
 
 /**
- * This is a simple plugin that will map any GET request for non-files to 
+ * This is a simple plugin that will map any GET request for non-files to
  * PROPFIND allprops-requests.
  *
  * This should allow easy debugging of PROPFIND
- * 
+ *
  * @package Sabre
  * @subpackage DAV
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
  * @author Evert Pot (http://www.rooftopsolutions.nl/)
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
  */
 class Sabre_DAV_Browser_MapGetToPropFind extends Sabre_DAV_ServerPlugin {
 
     /**
-     * reference to server class 
-     * 
-     * @var Sabre_DAV_Server 
+     * reference to server class
+     *
+     * @var Sabre_DAV_Server
      */
     protected $server;
 
     /**
-     * Initializes the plugin and subscribes to events 
-     * 
-     * @param Sabre_DAV_Server $server 
+     * Initializes the plugin and subscribes to events
+     *
+     * @param Sabre_DAV_Server $server
      * @return void
      */
     public function initialize(Sabre_DAV_Server $server) {
@@ -34,21 +34,22 @@ class Sabre_DAV_Browser_MapGetToPropFind extends Sabre_DAV_ServerPlugin {
     }
 
     /**
-     * This method intercepts GET requests to non-files, and changes it into an HTTP PROPFIND request 
-     * 
-     * @param string $method 
-     * @return bool 
+     * This method intercepts GET requests to non-files, and changes it into an HTTP PROPFIND request
+     *
+     * @param string $method
+     * @param string $uri
+     * @return bool
      */
     public function httpGetInterceptor($method, $uri) {
 
         if ($method!='GET') return true;
-       
+
         $node = $this->server->tree->getNodeForPath($uri);
         if ($node instanceof Sabre_DAV_IFile) return;
 
         $this->server->invokeMethod('PROPFIND',$uri);
         return false;
-        
+
     }
 
 }
diff --git a/3rdparty/Sabre/DAV/Browser/Plugin.php b/3rdparty/Sabre/DAV/Browser/Plugin.php
index cd5617babb160819ad04d72cb4cc48c27c3fad99..09bbdd2ae021e013c83c85bcbbc77f9cfb8a6ace 100644
--- a/3rdparty/Sabre/DAV/Browser/Plugin.php
+++ b/3rdparty/Sabre/DAV/Browser/Plugin.php
@@ -6,77 +6,126 @@
  * This plugin provides a html representation, so that a WebDAV server may be accessed
  * using a browser.
  *
- * The class intercepts GET requests to collection resources and generates a simple 
- * html index. 
- * 
+ * The class intercepts GET requests to collection resources and generates a simple
+ * html index.
+ *
  * @package Sabre
  * @subpackage DAV
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
  * @author Evert Pot (http://www.rooftopsolutions.nl/)
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
  */
 class Sabre_DAV_Browser_Plugin extends Sabre_DAV_ServerPlugin {
 
     /**
-     * reference to server class 
-     * 
-     * @var Sabre_DAV_Server 
+     * List of default icons for nodes.
+     *
+     * This is an array with class / interface names as keys, and asset names
+     * as values.
+     *
+     * The evaluation order is reversed. The last item in the list gets
+     * precendence.
+     *
+     * @var array
+     */
+    public $iconMap = array(
+        'Sabre_DAV_IFile' => 'icons/file',
+        'Sabre_DAV_ICollection' => 'icons/collection',
+        'Sabre_DAVACL_IPrincipal' => 'icons/principal',
+        'Sabre_CalDAV_ICalendar' => 'icons/calendar',
+        'Sabre_CardDAV_IAddressBook' => 'icons/addressbook',
+        'Sabre_CardDAV_ICard' => 'icons/card',
+    );
+
+    /**
+     * The file extension used for all icons
+     *
+     * @var string
+     */
+    public $iconExtension = '.png';
+
+    /**
+     * reference to server class
+     *
+     * @var Sabre_DAV_Server
      */
     protected $server;
 
     /**
-     * enableEditing
-     * 
-     * @var bool 
+     * enablePost turns on the 'actions' panel, which allows people to create
+     * folders and upload files straight from a browser.
+     *
+     * @var bool
      */
     protected $enablePost = true;
 
+    /**
+     * By default the browser plugin will generate a favicon and other images.
+     * To turn this off, set this property to false.
+     *
+     * @var bool
+     */
+    protected $enableAssets = true;
+
     /**
      * Creates the object.
      *
      * By default it will allow file creation and uploads.
      * Specify the first argument as false to disable this
-     * 
-     * @param bool $enablePost 
-     * @return void
+     *
+     * @param bool $enablePost
+     * @param bool $enableAssets
      */
-    public function __construct($enablePost=true) {
+    public function __construct($enablePost=true, $enableAssets = true) {
 
-        $this->enablePost = $enablePost; 
+        $this->enablePost = $enablePost;
+        $this->enableAssets = $enableAssets;
 
     }
 
     /**
-     * Initializes the plugin and subscribes to events 
-     * 
-     * @param Sabre_DAV_Server $server 
+     * Initializes the plugin and subscribes to events
+     *
+     * @param Sabre_DAV_Server $server
      * @return void
      */
     public function initialize(Sabre_DAV_Server $server) {
 
         $this->server = $server;
         $this->server->subscribeEvent('beforeMethod',array($this,'httpGetInterceptor'));
+        $this->server->subscribeEvent('onHTMLActionsPanel', array($this, 'htmlActionsPanel'),200);
         if ($this->enablePost) $this->server->subscribeEvent('unknownMethod',array($this,'httpPOSTHandler'));
     }
 
     /**
-     * This method intercepts GET requests to collections and returns the html 
-     * 
-     * @param string $method 
-     * @return bool 
+     * This method intercepts GET requests to collections and returns the html
+     *
+     * @param string $method
+     * @param string $uri
+     * @return bool
      */
     public function httpGetInterceptor($method, $uri) {
 
-        if ($method!='GET') return true;
+        if ($method !== 'GET') return true;
+
+        // We're not using straight-up $_GET, because we want everything to be
+        // unit testable.
+        $getVars = array();
+        parse_str($this->server->httpRequest->getQueryString(), $getVars);
+
+        if (isset($getVars['sabreAction']) && $getVars['sabreAction'] === 'asset' && isset($getVars['assetName'])) {
+            $this->serveAsset($getVars['assetName']);
+            return false;
+        }
 
-        try { 
+        try {
             $node = $this->server->tree->getNodeForPath($uri);
-        } catch (Sabre_DAV_Exception_FileNotFound $e) {
-            // We're simply stopping when the file isn't found to not interfere 
+        } catch (Sabre_DAV_Exception_NotFound $e) {
+            // We're simply stopping when the file isn't found to not interfere
             // with other plugins.
             return;
         }
-        if ($node instanceof Sabre_DAV_IFile) 
+        if ($node instanceof Sabre_DAV_IFile)
             return;
 
         $this->server->httpResponse->sendStatus(200);
@@ -87,57 +136,71 @@ class Sabre_DAV_Browser_Plugin extends Sabre_DAV_ServerPlugin {
         );
 
         return false;
-        
+
     }
 
     /**
-     * Handles POST requests for tree operations
-     * 
-     * This method is not yet used.
-     * 
-     * @param string $method 
+     * Handles POST requests for tree operations.
+     *
+     * @param string $method
+     * @param string $uri
      * @return bool
      */
     public function httpPOSTHandler($method, $uri) {
 
-        if ($method!='POST') return true;
-        if (isset($_POST['sabreAction'])) switch($_POST['sabreAction']) {
+        if ($method!='POST') return;
+        $contentType = $this->server->httpRequest->getHeader('Content-Type');
+        list($contentType) = explode(';', $contentType);
+        if ($contentType !== 'application/x-www-form-urlencoded' &&
+            $contentType !== 'multipart/form-data') {
+                return;
+        }
+        $postVars = $this->server->httpRequest->getPostVars();
 
-            case 'mkcol' :
-                if (isset($_POST['name']) && trim($_POST['name'])) {
-                    // Using basename() because we won't allow slashes
-                    list(, $folderName) = Sabre_DAV_URLUtil::splitPath(trim($_POST['name']));
-                    $this->server->createDirectory($uri . '/' . $folderName);
-                }
-                break;
-            case 'put' :
-                if ($_FILES) $file = current($_FILES);
-                else break;
-                $newName = trim($file['name']);
-                list(, $newName) = Sabre_DAV_URLUtil::splitPath(trim($file['name']));
-                if (isset($_POST['name']) && trim($_POST['name']))
-                    $newName = trim($_POST['name']);
-
-                // Making sure we only have a 'basename' component
-                list(, $newName) = Sabre_DAV_URLUtil::splitPath($newName);
-                    
-               
-                if (is_uploaded_file($file['tmp_name'])) {
-                    $parent = $this->server->tree->getNodeForPath(trim($uri,'/'));
-                    $parent->createFile($newName,fopen($file['tmp_name'],'r'));
-                }
+        if (!isset($postVars['sabreAction']))
+            return;
+
+        if ($this->server->broadcastEvent('onBrowserPostAction', array($uri, $postVars['sabreAction'], $postVars))) {
+
+            switch($postVars['sabreAction']) {
+
+                case 'mkcol' :
+                    if (isset($postVars['name']) && trim($postVars['name'])) {
+                        // Using basename() because we won't allow slashes
+                        list(, $folderName) = Sabre_DAV_URLUtil::splitPath(trim($postVars['name']));
+                        $this->server->createDirectory($uri . '/' . $folderName);
+                    }
+                    break;
+                case 'put' :
+                    if ($_FILES) $file = current($_FILES);
+                    else break;
+
+                    list(, $newName) = Sabre_DAV_URLUtil::splitPath(trim($file['name']));
+                    if (isset($postVars['name']) && trim($postVars['name']))
+                        $newName = trim($postVars['name']);
+
+                    // Making sure we only have a 'basename' component
+                    list(, $newName) = Sabre_DAV_URLUtil::splitPath($newName);
+
+                    if (is_uploaded_file($file['tmp_name'])) {
+                        $this->server->createFile($uri . '/' . $newName, fopen($file['tmp_name'],'r'));
+                    }
+                    break;
+
+            }
 
         }
         $this->server->httpResponse->setHeader('Location',$this->server->httpRequest->getUri());
+        $this->server->httpResponse->sendStatus(302);
         return false;
 
     }
 
     /**
-     * Escapes a string for html. 
-     * 
-     * @param string $value 
-     * @return void
+     * Escapes a string for html.
+     *
+     * @param string $value
+     * @return string
      */
     public function escapeHTML($value) {
 
@@ -146,118 +209,199 @@ class Sabre_DAV_Browser_Plugin extends Sabre_DAV_ServerPlugin {
     }
 
     /**
-     * Generates the html directory index for a given url 
+     * Generates the html directory index for a given url
      *
-     * @param string $path 
-     * @return string 
+     * @param string $path
+     * @return string
      */
     public function generateDirectoryIndex($path) {
 
+        $version = '';
+        if (Sabre_DAV_Server::$exposeVersion) {
+            $version = Sabre_DAV_Version::VERSION ."-". Sabre_DAV_Version::STABILITY;
+        }
+
         $html = "<html>
 <head>
-  <title>Index for " . $this->escapeHTML($path) . "/ - SabreDAV " . Sabre_DAV_Version::VERSION . "</title>
-  <style type=\"text/css\"> body { Font-family: arial}</style>
-</head>
+  <title>Index for " . $this->escapeHTML($path) . "/ - SabreDAV " . $version . "</title>
+  <style type=\"text/css\">
+  body { Font-family: arial}
+  h1 { font-size: 150% }
+  </style>
+        ";
+
+        if ($this->enableAssets) {
+            $html.='<link rel="shortcut icon" href="'.$this->getAssetUrl('favicon.ico').'" type="image/vnd.microsoft.icon" />';
+        }
+
+        $html .= "</head>
 <body>
   <h1>Index for " . $this->escapeHTML($path) . "/</h1>
   <table>
-    <tr><th>Name</th><th>Type</th><th>Size</th><th>Last modified</th></tr>
-    <tr><td colspan=\"4\"><hr /></td></tr>";
-    
-    $files = $this->server->getPropertiesForPath($path,array(
-        '{DAV:}displayname',
-        '{DAV:}resourcetype',
-        '{DAV:}getcontenttype',
-        '{DAV:}getcontentlength',
-        '{DAV:}getlastmodified',
-    ),1);
+    <tr><th width=\"24\"></th><th>Name</th><th>Type</th><th>Size</th><th>Last modified</th></tr>
+    <tr><td colspan=\"5\"><hr /></td></tr>";
 
-    $parent = $this->server->tree->getNodeForPath($path);
+        $files = $this->server->getPropertiesForPath($path,array(
+            '{DAV:}displayname',
+            '{DAV:}resourcetype',
+            '{DAV:}getcontenttype',
+            '{DAV:}getcontentlength',
+            '{DAV:}getlastmodified',
+        ),1);
 
+        $parent = $this->server->tree->getNodeForPath($path);
 
-    if ($path) {
 
-        list($parentUri) = Sabre_DAV_URLUtil::splitPath($path);
-        $fullPath = Sabre_DAV_URLUtil::encodePath($this->server->getBaseUri() . $parentUri);
+        if ($path) {
 
-        $html.= "<tr>
-<td><a href=\"{$fullPath}\">..</a></td>
-<td>[parent]</td>
-<td></td>
-<td></td>
-</tr>";
+            list($parentUri) = Sabre_DAV_URLUtil::splitPath($path);
+            $fullPath = Sabre_DAV_URLUtil::encodePath($this->server->getBaseUri() . $parentUri);
 
-    }
+            $icon = $this->enableAssets?'<a href="' . $fullPath . '"><img src="' . $this->getAssetUrl('icons/parent' . $this->iconExtension) . '" width="24" alt="Parent" /></a>':'';
+            $html.= "<tr>
+    <td>$icon</td>
+    <td><a href=\"{$fullPath}\">..</a></td>
+    <td>[parent]</td>
+    <td></td>
+    <td></td>
+    </tr>";
 
-    foreach($files as $k=>$file) {
+        }
 
-        // This is the current directory, we can skip it
-        if (rtrim($file['href'],'/')==$path) continue;
+        foreach($files as $file) {
+
+            // This is the current directory, we can skip it
+            if (rtrim($file['href'],'/')==$path) continue;
+
+            list(, $name) = Sabre_DAV_URLUtil::splitPath($file['href']);
+
+            $type = null;
+
+
+            if (isset($file[200]['{DAV:}resourcetype'])) {
+                $type = $file[200]['{DAV:}resourcetype']->getValue();
+
+                // resourcetype can have multiple values
+                if (!is_array($type)) $type = array($type);
+
+                foreach($type as $k=>$v) {
+
+                    // Some name mapping is preferred
+                    switch($v) {
+                        case '{DAV:}collection' :
+                            $type[$k] = 'Collection';
+                            break;
+                        case '{DAV:}principal' :
+                            $type[$k] = 'Principal';
+                            break;
+                        case '{urn:ietf:params:xml:ns:carddav}addressbook' :
+                            $type[$k] = 'Addressbook';
+                            break;
+                        case '{urn:ietf:params:xml:ns:caldav}calendar' :
+                            $type[$k] = 'Calendar';
+                            break;
+                        case '{urn:ietf:params:xml:ns:caldav}schedule-inbox' :
+                            $type[$k] = 'Schedule Inbox';
+                            break;
+                        case '{urn:ietf:params:xml:ns:caldav}schedule-outbox' :
+                            $type[$k] = 'Schedule Outbox';
+                            break;
+                        case '{http://calendarserver.org/ns/}calendar-proxy-read' :
+                            $type[$k] = 'Proxy-Read';
+                            break;
+                        case '{http://calendarserver.org/ns/}calendar-proxy-write' :
+                            $type[$k] = 'Proxy-Write';
+                            break;
+                    }
 
-        list(, $name) = Sabre_DAV_URLUtil::splitPath($file['href']);
+                }
+                $type = implode(', ', $type);
+            }
 
-        $type = null;
+            // If no resourcetype was found, we attempt to use
+            // the contenttype property
+            if (!$type && isset($file[200]['{DAV:}getcontenttype'])) {
+                $type = $file[200]['{DAV:}getcontenttype'];
+            }
+            if (!$type) $type = 'Unknown';
 
+            $size = isset($file[200]['{DAV:}getcontentlength'])?(int)$file[200]['{DAV:}getcontentlength']:'';
+            $lastmodified = isset($file[200]['{DAV:}getlastmodified'])?$file[200]['{DAV:}getlastmodified']->getTime()->format(DateTime::ATOM):'';
 
-        if (isset($file[200]['{DAV:}resourcetype'])) {
-            $type = $file[200]['{DAV:}resourcetype']->getValue();
+            $fullPath = Sabre_DAV_URLUtil::encodePath('/' . trim($this->server->getBaseUri() . ($path?$path . '/':'') . $name,'/'));
 
-            // resourcetype can have multiple values
-            if (!is_array($type)) $type = array($type);
+            $displayName = isset($file[200]['{DAV:}displayname'])?$file[200]['{DAV:}displayname']:$name;
 
-            foreach($type as $k=>$v) { 
+            $displayName = $this->escapeHTML($displayName);
+            $type = $this->escapeHTML($type);
 
-                // Some name mapping is preferred 
-                switch($v) {
-                    case '{DAV:}collection' :
-                        $type[$k] = 'Collection';
-                        break;
-                    case '{DAV:}principal' :
-                        $type[$k] = 'Principal';
-                        break;
-                    case '{urn:ietf:params:xml:ns:carddav}addressbook' :
-                        $type[$k] = 'Addressbook';
-                        break;
-                    case '{urn:ietf:params:xml:ns:caldav}calendar' :
-                        $type[$k] = 'Calendar';
+            $icon = '';
+
+            if ($this->enableAssets) {
+                $node = $parent->getChild($name);
+                foreach(array_reverse($this->iconMap) as $class=>$iconName) {
+
+                    if ($node instanceof $class) {
+                        $icon = '<a href="' . $fullPath . '"><img src="' . $this->getAssetUrl($iconName . $this->iconExtension) . '" alt="" width="24" /></a>';
                         break;
+                    }
+
+
                 }
 
             }
-            $type = implode(', ', $type);
-        }
 
-        // If no resourcetype was found, we attempt to use
-        // the contenttype property
-        if (!$type && isset($file[200]['{DAV:}getcontenttype'])) {
-            $type = $file[200]['{DAV:}getcontenttype'];
+            $html.= "<tr>
+    <td>$icon</td>
+    <td><a href=\"{$fullPath}\">{$displayName}</a></td>
+    <td>{$type}</td>
+    <td>{$size}</td>
+    <td>{$lastmodified}</td>
+    </tr>";
+
         }
-        if (!$type) $type = 'Unknown';
 
-        $size = isset($file[200]['{DAV:}getcontentlength'])?(int)$file[200]['{DAV:}getcontentlength']:'';
-        $lastmodified = isset($file[200]['{DAV:}getlastmodified'])?$file[200]['{DAV:}getlastmodified']->getTime()->format(DateTime::ATOM):'';
+        $html.= "<tr><td colspan=\"5\"><hr /></td></tr>";
+
+        $output = '';
 
-        $fullPath = Sabre_DAV_URLUtil::encodePath('/' . trim($this->server->getBaseUri() . ($path?$path . '/':'') . $name,'/'));
+        if ($this->enablePost) {
+            $this->server->broadcastEvent('onHTMLActionsPanel',array($parent, &$output));
+        }
 
-        $displayName = isset($file[200]['{DAV:}displayname'])?$file[200]['{DAV:}displayname']:$name;
+        $html.=$output;
 
-        $name = $this->escapeHTML($name);
-        $displayName = $this->escapeHTML($displayName);
-        $type = $this->escapeHTML($type);
+        $html.= "</table>
+        <address>Generated by SabreDAV " . $version . " (c)2007-2012 <a href=\"http://code.google.com/p/sabredav/\">http://code.google.com/p/sabredav/</a></address>
+        </body>
+        </html>";
 
-        $html.= "<tr>
-<td><a href=\"{$fullPath}\">{$displayName}</a></td>
-<td>{$type}</td>
-<td>{$size}</td>
-<td>{$lastmodified}</td>
-</tr>";
+        return $html;
 
     }
 
-  $html.= "<tr><td colspan=\"4\"><hr /></td></tr>";
+    /**
+     * This method is used to generate the 'actions panel' output for
+     * collections.
+     *
+     * This specifically generates the interfaces for creating new files, and
+     * creating new directories.
+     *
+     * @param Sabre_DAV_INode $node
+     * @param mixed $output
+     * @return void
+     */
+    public function htmlActionsPanel(Sabre_DAV_INode $node, &$output) {
+
+        if (!$node instanceof Sabre_DAV_ICollection)
+            return;
+
+        // We also know fairly certain that if an object is a non-extended
+        // SimpleCollection, we won't need to show the panel either.
+        if (get_class($node)==='Sabre_DAV_SimpleCollection')
+            return;
 
-  if ($this->enablePost && $parent instanceof Sabre_DAV_ICollection) {
-      $html.= '<tr><td><form method="post" action="">
+        $output.= '<tr><td colspan="2"><form method="post" action="">
             <h3>Create new folder</h3>
             <input type="hidden" name="sabreAction" value="mkcol" />
             Name: <input type="text" name="name" /><br />
@@ -270,15 +414,75 @@ class Sabre_DAV_Browser_Plugin extends Sabre_DAV_ServerPlugin {
             File: <input type="file" name="file" /><br />
             <input type="submit" value="upload" />
             </form>
-       </td></tr>';
-  }
+            </td></tr>';
+
+    }
 
-  $html.= "</table>
-  <address>Generated by SabreDAV " . Sabre_DAV_Version::VERSION ."-". Sabre_DAV_Version::STABILITY . " (c)2007-2011 <a href=\"http://code.google.com/p/sabredav/\">http://code.google.com/p/sabredav/</a></address>
-</body>
-</html>";
+    /**
+     * This method takes a path/name of an asset and turns it into url
+     * suiteable for http access.
+     *
+     * @param string $assetName
+     * @return string
+     */
+    protected function getAssetUrl($assetName) {
 
-        return $html; 
+        return $this->server->getBaseUri() . '?sabreAction=asset&assetName=' . urlencode($assetName);
+
+    }
+
+    /**
+     * This method returns a local pathname to an asset.
+     *
+     * @param string $assetName
+     * @return string
+     */
+    protected function getLocalAssetPath($assetName) {
+
+        // Making sure people aren't trying to escape from the base path.
+        $assetSplit = explode('/', $assetName);
+        if (in_array('..',$assetSplit)) {
+            throw new Sabre_DAV_Exception('Incorrect asset path');
+        }
+        $path = __DIR__ . '/assets/' . $assetName;
+        return $path;
+
+    }
+
+    /**
+     * This method reads an asset from disk and generates a full http response.
+     *
+     * @param string $assetName
+     * @return void
+     */
+    protected function serveAsset($assetName) {
+
+        $assetPath = $this->getLocalAssetPath($assetName);
+        if (!file_exists($assetPath)) {
+            throw new Sabre_DAV_Exception_NotFound('Could not find an asset with this name');
+        }
+        // Rudimentary mime type detection
+        switch(strtolower(substr($assetPath,strpos($assetPath,'.')+1))) {
+
+        case 'ico' :
+            $mime = 'image/vnd.microsoft.icon';
+            break;
+
+        case 'png' :
+            $mime = 'image/png';
+            break;
+
+        default:
+            $mime = 'application/octet-stream';
+            break;
+
+        }
+
+        $this->server->httpResponse->setHeader('Content-Type', $mime);
+        $this->server->httpResponse->setHeader('Content-Length', filesize($assetPath));
+        $this->server->httpResponse->setHeader('Cache-Control', 'public, max-age=1209600');
+        $this->server->httpResponse->sendStatus(200);
+        $this->server->httpResponse->sendBody(fopen($assetPath,'r'));
 
     }
 
diff --git a/3rdparty/Sabre/DAV/Browser/assets/favicon.ico b/3rdparty/Sabre/DAV/Browser/assets/favicon.ico
new file mode 100644
index 0000000000000000000000000000000000000000..2b2c10a22cc7a57c4dc5d7156f184448f2bee92b
Binary files /dev/null and b/3rdparty/Sabre/DAV/Browser/assets/favicon.ico differ
diff --git a/3rdparty/Sabre/DAV/Browser/assets/icons/addressbook.png b/3rdparty/Sabre/DAV/Browser/assets/icons/addressbook.png
new file mode 100644
index 0000000000000000000000000000000000000000..c9acc84172dad59708b6b298b310b8d29eeeb671
Binary files /dev/null and b/3rdparty/Sabre/DAV/Browser/assets/icons/addressbook.png differ
diff --git a/3rdparty/Sabre/DAV/Browser/assets/icons/calendar.png b/3rdparty/Sabre/DAV/Browser/assets/icons/calendar.png
new file mode 100644
index 0000000000000000000000000000000000000000..3ecd6a800a01b77ec8b53fd2ac2c1ad9be035fc0
Binary files /dev/null and b/3rdparty/Sabre/DAV/Browser/assets/icons/calendar.png differ
diff --git a/3rdparty/Sabre/DAV/Browser/assets/icons/card.png b/3rdparty/Sabre/DAV/Browser/assets/icons/card.png
new file mode 100644
index 0000000000000000000000000000000000000000..2ce954866d853edb737a7e281de221f7846846f6
Binary files /dev/null and b/3rdparty/Sabre/DAV/Browser/assets/icons/card.png differ
diff --git a/3rdparty/Sabre/DAV/Browser/assets/icons/collection.png b/3rdparty/Sabre/DAV/Browser/assets/icons/collection.png
new file mode 100644
index 0000000000000000000000000000000000000000..156fa64fd50f15d9e838326d42d68feba2c23c3b
Binary files /dev/null and b/3rdparty/Sabre/DAV/Browser/assets/icons/collection.png differ
diff --git a/3rdparty/Sabre/DAV/Browser/assets/icons/file.png b/3rdparty/Sabre/DAV/Browser/assets/icons/file.png
new file mode 100644
index 0000000000000000000000000000000000000000..3b98551cec3a863ab120a52cf21debad6cab6748
Binary files /dev/null and b/3rdparty/Sabre/DAV/Browser/assets/icons/file.png differ
diff --git a/3rdparty/Sabre/DAV/Browser/assets/icons/parent.png b/3rdparty/Sabre/DAV/Browser/assets/icons/parent.png
new file mode 100644
index 0000000000000000000000000000000000000000..156fa64fd50f15d9e838326d42d68feba2c23c3b
Binary files /dev/null and b/3rdparty/Sabre/DAV/Browser/assets/icons/parent.png differ
diff --git a/3rdparty/Sabre/DAV/Browser/assets/icons/principal.png b/3rdparty/Sabre/DAV/Browser/assets/icons/principal.png
new file mode 100644
index 0000000000000000000000000000000000000000..f8988f828e61bb1894c3ea5b848f95aac84beaa3
Binary files /dev/null and b/3rdparty/Sabre/DAV/Browser/assets/icons/principal.png differ
diff --git a/3rdparty/Sabre/DAV/Client.php b/3rdparty/Sabre/DAV/Client.php
index fc6a6fff083e4ea2747d2fdb3d843c4570757c75..a8320dd978260c46a94944133f2ddae65ea815e2 100644
--- a/3rdparty/Sabre/DAV/Client.php
+++ b/3rdparty/Sabre/DAV/Client.php
@@ -3,14 +3,14 @@
 /**
  * SabreDAV DAV client
  *
- * This client wraps around Curl to provide a convenient API to a WebDAV 
+ * This client wraps around Curl to provide a convenient API to a WebDAV
  * server.
  *
  * NOTE: This class is experimental, it's api will likely change in the future.
- * 
+ *
  * @package Sabre
  * @subpackage DAVClient
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
  * @author Evert Pot (http://www.rooftopsolutions.nl/) 
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
  */
@@ -26,22 +26,22 @@ class Sabre_DAV_Client {
     /**
      * Constructor
      *
-     * Settings are provided through the 'settings' argument. The following 
+     * Settings are provided through the 'settings' argument. The following
      * settings are supported:
      *
      *   * baseUri
      *   * userName (optional)
      *   * password (optional)
      *   * proxy (optional)
-     * 
-     * @param array $settings 
+     *
+     * @param array $settings
      */
     public function __construct(array $settings) {
 
         if (!isset($settings['baseUri'])) {
             throw new InvalidArgumentException('A baseUri must be provided');
         }
-        
+
         $validSettings = array(
             'baseUri',
             'userName',
@@ -62,23 +62,23 @@ class Sabre_DAV_Client {
     /**
      * Does a PROPFIND request
      *
-     * The list of requested properties must be specified as an array, in clark 
-     * notation. 
+     * The list of requested properties must be specified as an array, in clark
+     * notation.
      *
-     * The returned array will contain a list of filenames as keys, and 
+     * The returned array will contain a list of filenames as keys, and
      * properties as values.
      *
-     * The properties array will contain the list of properties. Only properties 
-     * that are actually returned from the server (without error) will be 
+     * The properties array will contain the list of properties. Only properties
+     * that are actually returned from the server (without error) will be
      * returned, anything else is discarded.
      *
-     * Depth should be either 0 or 1. A depth of 1 will cause a request to be 
+     * Depth should be either 0 or 1. A depth of 1 will cause a request to be
      * made to the server to also return all child resources.
      *
-     * @param string $url 
-     * @param array $properties 
-     * @param int $depth 
-     * @return array 
+     * @param string $url
+     * @param array $properties
+     * @param int $depth
+     * @return array
      */
     public function propFind($url, array $properties, $depth = 0) {
 
@@ -132,14 +132,14 @@ class Sabre_DAV_Client {
     /**
      * Updates a list of properties on the server
      *
-     * The list of properties must have clark-notation properties for the keys, 
-     * and the actual (string) value for the value. If the value is null, an 
-     * attempt is made to delete the property. 
+     * The list of properties must have clark-notation properties for the keys,
+     * and the actual (string) value for the value. If the value is null, an
+     * attempt is made to delete the property.
      *
-     * @todo Must be building the request using the DOM, and does not yet 
-     *       support complex properties. 
-     * @param string $url 
-     * @param array $properties 
+     * @todo Must be building the request using the DOM, and does not yet
+     *       support complex properties.
+     * @param string $url
+     * @param array $properties
      * @return void
      */
     public function propPatch($url, array $properties) {
@@ -175,7 +175,7 @@ class Sabre_DAV_Client {
                     $body.="    <x:" . $elementName . " xmlns:x=\"" . $namespace . "\">";
                 }
                 // Shitty.. i know
-                $body.=htmlspecialchars($propValue, ENT_NOQUOTES, 'UTF-8'); 
+                $body.=htmlspecialchars($propValue, ENT_NOQUOTES, 'UTF-8');
                 if ($namespace === 'DAV:') {
                     $body.='</d:' . $elementName . '>' . "\n";
                 } else {
@@ -189,7 +189,7 @@ class Sabre_DAV_Client {
 
         $body.= '</d:propertyupdate>';
 
-        $response = $this->request('PROPPATCH', $url, $body, array(
+        $this->request('PROPPATCH', $url, $body, array(
             'Content-Type' => 'application/xml'
         ));
 
@@ -198,11 +198,11 @@ class Sabre_DAV_Client {
     /**
      * Performs an HTTP options request
      *
-     * This method returns all the features from the 'DAV:' header as an array. 
-     * If there was no DAV header, or no contents this method will return an 
-     * empty array. 
-     * 
-     * @return array 
+     * This method returns all the features from the 'DAV:' header as an array.
+     * If there was no DAV header, or no contents this method will return an
+     * empty array.
+     *
+     * @return array
      */
     public function options() {
 
@@ -222,20 +222,20 @@ class Sabre_DAV_Client {
     /**
      * Performs an actual HTTP request, and returns the result.
      *
-     * If the specified url is relative, it will be expanded based on the base 
+     * If the specified url is relative, it will be expanded based on the base
      * url.
      *
      * The returned array contains 3 keys:
      *   * body - the response body
      *   * httpCode - a HTTP code (200, 404, etc)
-     *   * headers - a list of response http headers. The header names have 
+     *   * headers - a list of response http headers. The header names have
      *     been lowercased.
      *
-     * @param string $method 
-     * @param string $url 
-     * @param string $body 
-     * @param array $headers 
-     * @return array 
+     * @param string $method
+     * @param string $url
+     * @param string $body
+     * @param array $headers
+     * @return array
      */
     public function request($method, $url = '', $body = null, $headers = array()) {
 
@@ -243,14 +243,37 @@ class Sabre_DAV_Client {
 
         $curlSettings = array(
             CURLOPT_RETURNTRANSFER => true,
-            CURLOPT_CUSTOMREQUEST => $method,
-            CURLOPT_POSTFIELDS => $body,
             // Return headers as part of the response
-            CURLOPT_HEADER => true
+            CURLOPT_HEADER => true,
+            CURLOPT_POSTFIELDS => $body,
+            // Automatically follow redirects
+            CURLOPT_FOLLOWLOCATION => true,
+            CURLOPT_MAXREDIRS => 5,
         );
 
+        switch ($method) {
+            case 'PUT':
+                $curlSettings[CURLOPT_PUT] = true;
+                break;
+            case 'HEAD' :
+
+                // do not read body with HEAD requests (this is neccessary because cURL does not ignore the body with HEAD
+                // requests when the Content-Length header is given - which in turn is perfectly valid according to HTTP
+                // specs...) cURL does unfortunately return an error in this case ("transfer closed transfer closed with
+                // ... bytes remaining to read") this can be circumvented by explicitly telling cURL to ignore the
+                // response body
+                $curlSettings[CURLOPT_NOBODY] = true;
+                $curlSettings[CURLOPT_CUSTOMREQUEST] = 'HEAD';
+                break;
+
+            default:
+                $curlSettings[CURLOPT_CUSTOMREQUEST] = $method;
+                break;
+
+        }
+
         // Adding HTTP headers
-        $nHeaders = array(); 
+        $nHeaders = array();
         foreach($headers as $key=>$value) {
 
             $nHeaders[] = $key . ': ' . $value;
@@ -277,17 +300,17 @@ class Sabre_DAV_Client {
         $headerBlob = substr($response, 0, $curlInfo['header_size']);
         $response = substr($response, $curlInfo['header_size']);
 
-        // In the case of 100 Continue, or redirects we'll have multiple lists 
-        // of headers for each separate HTTP response. We can easily split this 
+        // In the case of 100 Continue, or redirects we'll have multiple lists
+        // of headers for each separate HTTP response. We can easily split this
         // because they are separated by \r\n\r\n
         $headerBlob = explode("\r\n\r\n", trim($headerBlob, "\r\n"));
-        
+
         // We only care about the last set of headers
         $headerBlob = $headerBlob[count($headerBlob)-1];
 
         // Splitting headers
         $headerBlob = explode("\r\n", $headerBlob);
-        
+
         $headers = array();
         foreach($headerBlob as $header) {
             $parts = explode(':', $header, 2);
@@ -304,10 +327,17 @@ class Sabre_DAV_Client {
 
         if ($curlErrNo) {
             throw new Sabre_DAV_Exception('[CURL] Error while making request: ' . $curlError . ' (error code: ' . $curlErrNo . ')');
-        } 
+        }
 
         if ($response['statusCode']>=400) {
-            throw new Sabre_DAV_Exception('HTTP error response. (errorcode ' . $response['statusCode'] . ')');
+            switch ($response['statusCode']) {
+                case 404:
+                    throw new Sabre_DAV_Exception_NotFound('Resource ' . $url . ' not found.');
+                    break;
+
+                default:
+                    throw new Sabre_DAV_Exception('HTTP error response. (errorcode ' . $response['statusCode'] . ')');
+            }
         }
 
         return $response;
@@ -317,12 +347,12 @@ class Sabre_DAV_Client {
     /**
      * Wrapper for all curl functions.
      *
-     * The only reason this was split out in a separate method, is so it 
-     * becomes easier to unittest. 
+     * The only reason this was split out in a separate method, is so it
+     * becomes easier to unittest.
      *
      * @param string $url
-     * @param array $settings 
-     * @return  
+     * @param array $settings
+     * @return array
      */
     protected function curlRequest($url, $settings) {
 
@@ -339,20 +369,20 @@ class Sabre_DAV_Client {
     }
 
     /**
-     * Returns the full url based on the given url (which may be relative). All 
-     * urls are expanded based on the base url as given by the server. 
-     * 
-     * @param string $url 
-     * @return string 
+     * Returns the full url based on the given url (which may be relative). All
+     * urls are expanded based on the base url as given by the server.
+     *
+     * @param string $url
+     * @return string
      */
     protected function getAbsoluteUrl($url) {
 
-        // If the url starts with http:// or https://, the url is already absolute. 
+        // If the url starts with http:// or https://, the url is already absolute.
         if (preg_match('/^http(s?):\/\//', $url)) {
             return $url;
         }
 
-        // If the url starts with a slash, we must calculate the url based off 
+        // If the url starts with a slash, we must calculate the url based off
         // the root of the base url.
         if (strpos($url,'/') === 0) {
             $parts = parse_url($this->baseUri);
@@ -366,7 +396,7 @@ class Sabre_DAV_Client {
 
     /**
      * Parses a WebDAV multistatus response body
-     * 
+     *
      * This method returns an array with the following structure
      *
      * array(
@@ -387,7 +417,7 @@ class Sabre_DAV_Client {
      *
      *
      * @param string $body xml body
-     * @return array 
+     * @return array
      */
     public function parseMultiStatus($body) {
 
@@ -397,14 +427,13 @@ class Sabre_DAV_Client {
         if ($responseXML===false) {
             throw new InvalidArgumentException('The passed data is not valid XML');
         }
-         
-        $responseXML->registerXPathNamespace('d','DAV:');
+
+        $responseXML->registerXPathNamespace('d', 'urn:DAV');
 
         $propResult = array();
 
         foreach($responseXML->xpath('d:response') as $response) {
-
-            $response->registerXPathNamespace('d','DAV:');
+            $response->registerXPathNamespace('d', 'urn:DAV');
             $href = $response->xpath('d:href');
             $href = (string)$href[0];
 
@@ -412,11 +441,11 @@ class Sabre_DAV_Client {
 
             foreach($response->xpath('d:propstat') as $propStat) {
 
-                $propStat->registerXPathNamespace('d','DAV:');
+                $propStat->registerXPathNamespace('d', 'urn:DAV');
                 $status = $propStat->xpath('d:status');
                 list($httpVersion, $statusCode, $message) = explode(' ', (string)$status[0],3);
 
-                $properties[$statusCode] = Sabre_DAV_XMLUtil::parseProperties(dom_import_simplexml($propStat), $this->propertyMap); 
+                $properties[$statusCode] = Sabre_DAV_XMLUtil::parseProperties(dom_import_simplexml($propStat), $this->propertyMap);
 
             }
 
diff --git a/3rdparty/Sabre/DAV/Collection.php b/3rdparty/Sabre/DAV/Collection.php
index 9da04c12792fc1324e8b7a502079441a4decc714..776c22531b2485bdcabb5c47a9ae2efec75bdd1a 100644
--- a/3rdparty/Sabre/DAV/Collection.php
+++ b/3rdparty/Sabre/DAV/Collection.php
@@ -4,12 +4,12 @@
  * Collection class
  *
  * This is a helper class, that should aid in getting collections classes setup.
- * Most of its methods are implemented, and throw permission denied exceptions 
- * 
+ * Most of its methods are implemented, and throw permission denied exceptions
+ *
  * @package Sabre
  * @subpackage DAV
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
- * @author Evert Pot (http://www.rooftopsolutions.nl/) 
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
  */
 abstract class Sabre_DAV_Collection extends Sabre_DAV_Node implements Sabre_DAV_ICollection {
@@ -17,12 +17,12 @@ abstract class Sabre_DAV_Collection extends Sabre_DAV_Node implements Sabre_DAV_
     /**
      * Returns a child object, by its name.
      *
-     * This method makes use of the getChildren method to grab all the child nodes, and compares the name. 
+     * This method makes use of the getChildren method to grab all the child nodes, and compares the name.
      * Generally its wise to override this, as this can usually be optimized
-     * 
+     *
      * @param string $name
-     * @throws Sabre_DAV_Exception_FileNotFound
-     * @return Sabre_DAV_INode 
+     * @throws Sabre_DAV_Exception_NotFound
+     * @return Sabre_DAV_INode
      */
     public function getChild($name) {
 
@@ -31,7 +31,7 @@ abstract class Sabre_DAV_Collection extends Sabre_DAV_Node implements Sabre_DAV_
             if ($child->getName()==$name) return $child;
 
         }
-        throw new Sabre_DAV_Exception_FileNotFound('File not found: ' . $name);
+        throw new Sabre_DAV_Exception_NotFound('File not found: ' . $name);
 
     }
 
@@ -39,9 +39,9 @@ abstract class Sabre_DAV_Collection extends Sabre_DAV_Node implements Sabre_DAV_
      * Checks is a child-node exists.
      *
      * It is generally a good idea to try and override this. Usually it can be optimized.
-     * 
-     * @param string $name 
-     * @return bool 
+     *
+     * @param string $name
+     * @return bool
      */
     public function childExists($name) {
 
@@ -50,7 +50,7 @@ abstract class Sabre_DAV_Collection extends Sabre_DAV_Node implements Sabre_DAV_
             $this->getChild($name);
             return true;
 
-        } catch(Sabre_DAV_Exception_FileNotFound $e) {
+        } catch(Sabre_DAV_Exception_NotFound $e) {
 
             return false;
 
@@ -59,12 +59,28 @@ abstract class Sabre_DAV_Collection extends Sabre_DAV_Node implements Sabre_DAV_
     }
 
     /**
-     * Creates a new file in the directory 
-     * 
-     * @param string $name Name of the file 
-     * @param resource $data Initial payload, passed as a readable stream resource. 
-     * @throws Sabre_DAV_Exception_Forbidden
-     * @return void
+     * Creates a new file in the directory
+     *
+     * Data will either be supplied as a stream resource, or in certain cases
+     * as a string. Keep in mind that you may have to support either.
+     *
+     * After succesful creation of the file, you may choose to return the ETag
+     * of the new file here.
+     *
+     * The returned ETag must be surrounded by double-quotes (The quotes should
+     * be part of the actual string).
+     *
+     * If you cannot accurately determine the ETag, you should not return it.
+     * If you don't store the file exactly as-is (you're transforming it
+     * somehow) you should also not return an ETag.
+     *
+     * This means that if a subsequent GET to this new file does not exactly
+     * return the same contents of what was submitted here, you are strongly
+     * recommended to omit the ETag.
+     *
+     * @param string $name Name of the file
+     * @param resource|string $data Initial payload
+     * @return null|string
      */
     public function createFile($name, $data = null) {
 
@@ -73,9 +89,9 @@ abstract class Sabre_DAV_Collection extends Sabre_DAV_Node implements Sabre_DAV_
     }
 
     /**
-     * Creates a new subdirectory 
-     * 
-     * @param string $name 
+     * Creates a new subdirectory
+     *
+     * @param string $name
      * @throws Sabre_DAV_Exception_Forbidden
      * @return void
      */
diff --git a/3rdparty/Sabre/DAV/Directory.php b/3rdparty/Sabre/DAV/Directory.php
index 86af4827b3edf5555142e6e875b28f060fe7f338..6db8febc02e900ceba08c74370bbffa7968fd46b 100644
--- a/3rdparty/Sabre/DAV/Directory.php
+++ b/3rdparty/Sabre/DAV/Directory.php
@@ -8,7 +8,7 @@
  * @package Sabre
  * @subpackage DAV
  * @deprecated Use Sabre_DAV_Collection instead
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
  * @author Evert Pot (http://www.rooftopsolutions.nl/) 
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
  */
diff --git a/3rdparty/Sabre/DAV/Exception.php b/3rdparty/Sabre/DAV/Exception.php
index 61f8b87c0a62f15de6cd09e90383093094f0b799..a2cd6cf5820d935bd5e843d2be95085205faec5d 100644
--- a/3rdparty/Sabre/DAV/Exception.php
+++ b/3rdparty/Sabre/DAV/Exception.php
@@ -7,42 +7,42 @@
  *
  * @package Sabre
  * @subpackage DAV
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
  * @author Evert Pot (http://www.rooftopsolutions.nl/) 
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
  */
 
 /**
- * Main Exception class. 
+ * Main Exception class.
  *
- * This class defines a getHTTPCode method, which should return the appropriate HTTP code for the Exception occured.
+ * This class defines a getHTTPCode method, which should return the appropriate HTTP code for the Exception occurred.
  * The default for this is 500.
  *
  * This class also allows you to generate custom xml data for your exceptions. This will be displayed
  * in the 'error' element in the failing response.
  */
-class Sabre_DAV_Exception extends Exception { 
+class Sabre_DAV_Exception extends Exception {
 
     /**
-     * Returns the HTTP statuscode for this exception 
+     * Returns the HTTP statuscode for this exception
      *
      * @return int
      */
-    public function getHTTPCode() { 
+    public function getHTTPCode() {
 
         return 500;
 
     }
 
     /**
-     * This method allows the exception to include additonal information into the WebDAV error response 
+     * This method allows the exception to include additional information into the WebDAV error response
      *
      * @param Sabre_DAV_Server $server
-     * @param DOMElement $errorNode 
+     * @param DOMElement $errorNode
      * @return void
      */
     public function serialize(Sabre_DAV_Server $server,DOMElement $errorNode) {
-    
+
 
     }
 
@@ -50,14 +50,15 @@ class Sabre_DAV_Exception extends Exception {
      * This method allows the exception to return any extra HTTP response headers.
      *
      * The headers must be returned as an array.
-     * 
-     * @return array 
+     *
+     * @param Sabre_DAV_Server $server
+     * @return array
      */
     public function getHTTPHeaders(Sabre_DAV_Server $server) {
 
         return array();
 
-    } 
+    }
 
 }
 
diff --git a/3rdparty/Sabre/DAV/Exception/BadRequest.php b/3rdparty/Sabre/DAV/Exception/BadRequest.php
index 7025bb1031745b8a94b16afc4e83fa81b11de872..b198648a7545d44972e6e54f3fe81404a8253100 100644
--- a/3rdparty/Sabre/DAV/Exception/BadRequest.php
+++ b/3rdparty/Sabre/DAV/Exception/BadRequest.php
@@ -4,24 +4,24 @@
  * BadRequest
  *
  * The BadRequest is thrown when the user submitted an invalid HTTP request
- * BadRequest 
- * 
+ * BadRequest
+ *
  * @package Sabre
  * @subpackage DAV
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
  * @author Evert Pot (http://www.rooftopsolutions.nl/) 
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
  */
 class Sabre_DAV_Exception_BadRequest extends Sabre_DAV_Exception {
 
     /**
-     * Returns the HTTP statuscode for this exception 
+     * Returns the HTTP statuscode for this exception
      *
      * @return int
      */
     public function getHTTPCode() {
 
-        return 400; 
+        return 400;
 
     }
 
diff --git a/3rdparty/Sabre/DAV/Exception/Conflict.php b/3rdparty/Sabre/DAV/Exception/Conflict.php
index 7eaa08178ae2f16f2417a13ef1dd6833037b871a..6b0bd1fad7302402471aac6d9df3493f64eb156d 100644
--- a/3rdparty/Sabre/DAV/Exception/Conflict.php
+++ b/3rdparty/Sabre/DAV/Exception/Conflict.php
@@ -8,14 +8,14 @@
  *
  * @package Sabre
  * @subpackage DAV
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
  * @author Evert Pot (http://www.rooftopsolutions.nl/) 
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
  */
 class Sabre_DAV_Exception_Conflict extends Sabre_DAV_Exception {
 
     /**
-     * Returns the HTTP statuscode for this exception 
+     * Returns the HTTP statuscode for this exception
      *
      * @return int
      */
diff --git a/3rdparty/Sabre/DAV/Exception/ConflictingLock.php b/3rdparty/Sabre/DAV/Exception/ConflictingLock.php
index 279f63dfde783a5c0fd6955f486f4d8832dfa530..6121868e69e018b073257732d6d9f0d17f4fd26d 100644
--- a/3rdparty/Sabre/DAV/Exception/ConflictingLock.php
+++ b/3rdparty/Sabre/DAV/Exception/ConflictingLock.php
@@ -1,28 +1,28 @@
 <?php
 
 /**
- * ConflictingLock 
+ * ConflictingLock
  *
- * Similar to Exception_Locked, this exception thrown when a LOCK request 
+ * Similar to Exception_Locked, this exception thrown when a LOCK request
  * was made, on a resource which was already locked
  *
  * @package Sabre
  * @subpackage DAV
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
  * @author Evert Pot (http://www.rooftopsolutions.nl/) 
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
  */
 class Sabre_DAV_Exception_ConflictingLock extends Sabre_DAV_Exception_Locked {
 
     /**
-     * This method allows the exception to include additonal information into the WebDAV error response 
+     * This method allows the exception to include additional information into the WebDAV error response
      *
      * @param Sabre_DAV_Server $server
-     * @param DOMElement $errorNode 
+     * @param DOMElement $errorNode
      * @return void
      */
     public function serialize(Sabre_DAV_Server $server,DOMElement $errorNode) {
-        
+
         if ($this->lock) {
             $error = $errorNode->ownerDocument->createElementNS('DAV:','d:no-conflicting-lock');
             $errorNode->appendChild($error);
diff --git a/3rdparty/Sabre/DAV/Exception/FileNotFound.php b/3rdparty/Sabre/DAV/Exception/FileNotFound.php
index b20e4a2fb3ff7b1bed6024700969ad415d5185a5..d76e400c93b111b64fdd15369a8fecdf8fec197a 100644
--- a/3rdparty/Sabre/DAV/Exception/FileNotFound.php
+++ b/3rdparty/Sabre/DAV/Exception/FileNotFound.php
@@ -3,26 +3,17 @@
 /**
  * FileNotFound
  *
- * This Exception is thrown when a Node couldn't be found. It returns HTTP error code 404
+ * Deprecated: Warning, this class is deprecated and will be removed in a 
+ * future version of SabreDAV. Please use Sabre_DAV_Exception_NotFound instead.
  *
  * @package Sabre
  * @subpackage DAV
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
  * @author Evert Pot (http://www.rooftopsolutions.nl/) 
+ * @deprecated Use Sabre_DAV_Exception_NotFound instead
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
  */
-class Sabre_DAV_Exception_FileNotFound extends Sabre_DAV_Exception {
-
-    /**
-     * Returns the HTTP statuscode for this exception 
-     *
-     * @return int
-     */
-    public function getHTTPCode() {
-
-        return 404;
-
-    }
+class Sabre_DAV_Exception_FileNotFound extends Sabre_DAV_Exception_NotFound {
 
 }
 
diff --git a/3rdparty/Sabre/DAV/Exception/Forbidden.php b/3rdparty/Sabre/DAV/Exception/Forbidden.php
index 167f3c2760a8b38704d19fa340fba7327882d383..20b1056e31b5f27ef13e688ff4bf8a2440e5e376 100644
--- a/3rdparty/Sabre/DAV/Exception/Forbidden.php
+++ b/3rdparty/Sabre/DAV/Exception/Forbidden.php
@@ -4,17 +4,17 @@
  * Forbidden
  *
  * This exception is thrown whenever a user tries to do an operation he's not allowed to
- * 
+ *
  * @package Sabre
  * @subpackage DAV
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
  * @author Evert Pot (http://www.rooftopsolutions.nl/) 
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
  */
 class Sabre_DAV_Exception_Forbidden extends Sabre_DAV_Exception {
 
     /**
-     * Returns the HTTP statuscode for this exception 
+     * Returns the HTTP statuscode for this exception
      *
      * @return int
      */
diff --git a/3rdparty/Sabre/DAV/Exception/InsufficientStorage.php b/3rdparty/Sabre/DAV/Exception/InsufficientStorage.php
index 15007cdd352524fd362c754a75bdc7b1ad84ce2e..1a15089b0a34756236781f88152e5e3c91a67781 100644
--- a/3rdparty/Sabre/DAV/Exception/InsufficientStorage.php
+++ b/3rdparty/Sabre/DAV/Exception/InsufficientStorage.php
@@ -1,20 +1,20 @@
 <?php
 
 /**
- * InsufficientStorage 
+ * InsufficientStorage
  *
  * This Exception can be thrown, when for example a harddisk is full or a quota is exceeded
  *
  * @package Sabre
  * @subpackage DAV
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
  * @author Evert Pot (http://www.rooftopsolutions.nl/) 
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
  */
 class Sabre_DAV_Exception_InsufficientStorage extends Sabre_DAV_Exception {
 
     /**
-     * Returns the HTTP statuscode for this exception 
+     * Returns the HTTP statuscode for this exception
      *
      * @return int
      */
diff --git a/3rdparty/Sabre/DAV/Exception/InvalidResourceType.php b/3rdparty/Sabre/DAV/Exception/InvalidResourceType.php
index f06810a25ef58ba2c2b67d71f6accce60d814a7a..2230f1d081166a3cdf27552181e4223a90c22a31 100644
--- a/3rdparty/Sabre/DAV/Exception/InvalidResourceType.php
+++ b/3rdparty/Sabre/DAV/Exception/InvalidResourceType.php
@@ -1,26 +1,26 @@
 <?php
 
 /**
- * InvalidResourceType 
+ * InvalidResourceType
  *
  * This exception is thrown when the user tried to create a new collection, with
  * a special resourcetype value that was not recognized by the server.
  *
  * See RFC5689 section 3.3
- * 
+ *
  * @package Sabre
  * @subpackage DAV
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
  * @author Evert Pot (http://www.rooftopsolutions.nl/) 
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
  */
-class Sabre_DAV_Exception_InvalidResourceType extends Sabre_DAV_Exception_Forbidden { 
+class Sabre_DAV_Exception_InvalidResourceType extends Sabre_DAV_Exception_Forbidden {
 
     /**
-     * This method allows the exception to include additonal information into the WebDAV error response 
+     * This method allows the exception to include additional information into the WebDAV error response
      *
      * @param Sabre_DAV_Server $server
-     * @param DOMElement $errorNode 
+     * @param DOMElement $errorNode
      * @return void
      */
     public function serialize(Sabre_DAV_Server $server,DOMElement $errorNode) {
@@ -29,5 +29,5 @@ class Sabre_DAV_Exception_InvalidResourceType extends Sabre_DAV_Exception_Forbid
         $errorNode->appendChild($error);
 
     }
-    
+
 }
diff --git a/3rdparty/Sabre/DAV/Exception/LockTokenMatchesRequestUri.php b/3rdparty/Sabre/DAV/Exception/LockTokenMatchesRequestUri.php
index 47032cffc75de30033010bfd3a632c5de0ee6b01..80ab7aff65ae80dcdc3afb480ae57e60bc1923b6 100644
--- a/3rdparty/Sabre/DAV/Exception/LockTokenMatchesRequestUri.php
+++ b/3rdparty/Sabre/DAV/Exception/LockTokenMatchesRequestUri.php
@@ -1,13 +1,13 @@
 <?php
 
 /**
- * LockTokenMatchesRequestUri 
+ * LockTokenMatchesRequestUri
+ *
+ * This exception is thrown by UNLOCK if a supplied lock-token is invalid
  *
- * This exception is thrown by UNLOCK if a supplied lock-token is invalid 
- * 
  * @package Sabre
  * @subpackage DAV
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
  * @author Evert Pot (http://www.rooftopsolutions.nl/) 
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
  */
@@ -23,10 +23,10 @@ class Sabre_DAV_Exception_LockTokenMatchesRequestUri extends Sabre_DAV_Exception
     }
 
     /**
-     * This method allows the exception to include additonal information into the WebDAV error response 
+     * This method allows the exception to include additional information into the WebDAV error response
      *
      * @param Sabre_DAV_Server $server
-     * @param DOMElement $errorNode 
+     * @param DOMElement $errorNode
      * @return void
      */
     public function serialize(Sabre_DAV_Server $server,DOMElement $errorNode) {
diff --git a/3rdparty/Sabre/DAV/Exception/Locked.php b/3rdparty/Sabre/DAV/Exception/Locked.php
index b4bb2e0378cc55ed509258da4a5af79b3f853efe..976365ac1f84d6c263d71019edbfa5bfc05e23f7 100644
--- a/3rdparty/Sabre/DAV/Exception/Locked.php
+++ b/3rdparty/Sabre/DAV/Exception/Locked.php
@@ -1,32 +1,32 @@
 <?php
 
 /**
- * Locked 
+ * Locked
  *
  * The 423 is thrown when a client tried to access a resource that was locked, without supplying a valid lock token
- * 
+ *
  * @package Sabre
  * @subpackage DAV
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
  * @author Evert Pot (http://www.rooftopsolutions.nl/) 
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
  */
 class Sabre_DAV_Exception_Locked extends Sabre_DAV_Exception {
 
     /**
-     * Lock information 
-     * 
-     * @var Sabre_DAV_Locks_LockInfo 
+     * Lock information
+     *
+     * @var Sabre_DAV_Locks_LockInfo
      */
     protected $lock;
 
     /**
      * Creates the exception
-     * 
+     *
      * A LockInfo object should be passed if the user should be informed
      * which lock actually has the file locked.
-     * 
-     * @param Sabre_DAV_Locks_LockInfo $lock 
+     *
+     * @param Sabre_DAV_Locks_LockInfo $lock
      */
     public function __construct(Sabre_DAV_Locks_LockInfo $lock = null) {
 
@@ -35,7 +35,7 @@ class Sabre_DAV_Exception_Locked extends Sabre_DAV_Exception {
     }
 
     /**
-     * Returns the HTTP statuscode for this exception 
+     * Returns the HTTP statuscode for this exception
      *
      * @return int
      */
@@ -46,14 +46,14 @@ class Sabre_DAV_Exception_Locked extends Sabre_DAV_Exception {
     }
 
     /**
-     * This method allows the exception to include additonal information into the WebDAV error response 
+     * This method allows the exception to include additional information into the WebDAV error response
      *
      * @param Sabre_DAV_Server $server
-     * @param DOMElement $errorNode 
+     * @param DOMElement $errorNode
      * @return void
      */
     public function serialize(Sabre_DAV_Server $server,DOMElement $errorNode) {
-        
+
         if ($this->lock) {
             $error = $errorNode->ownerDocument->createElementNS('DAV:','d:lock-token-submitted');
             $errorNode->appendChild($error);
diff --git a/3rdparty/Sabre/DAV/Exception/MethodNotAllowed.php b/3rdparty/Sabre/DAV/Exception/MethodNotAllowed.php
index 02c145ffeb635de6320a707ed191963ae8da28e9..318757515054be2edb704216e563b8bb98929857 100644
--- a/3rdparty/Sabre/DAV/Exception/MethodNotAllowed.php
+++ b/3rdparty/Sabre/DAV/Exception/MethodNotAllowed.php
@@ -4,17 +4,17 @@
  * MethodNotAllowed
  *
  * The 405 is thrown when a client tried to create a directory on an already existing directory
- * 
+ *
  * @package Sabre
  * @subpackage DAV
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
  * @author Evert Pot (http://www.rooftopsolutions.nl/) 
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
  */
 class Sabre_DAV_Exception_MethodNotAllowed extends Sabre_DAV_Exception {
 
     /**
-     * Returns the HTTP statuscode for this exception 
+     * Returns the HTTP statuscode for this exception
      *
      * @return int
      */
@@ -28,8 +28,9 @@ class Sabre_DAV_Exception_MethodNotAllowed extends Sabre_DAV_Exception {
      * This method allows the exception to return any extra HTTP response headers.
      *
      * The headers must be returned as an array.
-     * 
-     * @return array 
+     *
+     * @param Sabre_DAV_Server $server
+     * @return array
      */
     public function getHTTPHeaders(Sabre_DAV_Server $server) {
 
diff --git a/3rdparty/Sabre/DAV/Exception/NotAuthenticated.php b/3rdparty/Sabre/DAV/Exception/NotAuthenticated.php
index 1faffddfa00d58f171ed2ac3a6de00145438110b..87ca624429f4240c1ef324a51d210b591f427f18 100644
--- a/3rdparty/Sabre/DAV/Exception/NotAuthenticated.php
+++ b/3rdparty/Sabre/DAV/Exception/NotAuthenticated.php
@@ -5,22 +5,22 @@
  *
  * This exception is thrown when the client did not provide valid
  * authentication credentials.
- * 
+ *
  * @package Sabre
  * @subpackage DAV
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
  * @author Evert Pot (http://www.rooftopsolutions.nl/) 
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
  */
 class Sabre_DAV_Exception_NotAuthenticated extends Sabre_DAV_Exception {
 
     /**
-     * Returns the HTTP statuscode for this exception 
+     * Returns the HTTP statuscode for this exception
      *
      * @return int
      */
     public function getHTTPCode() {
-        
+
         return 401;
 
     }
diff --git a/3rdparty/Sabre/DAV/Exception/NotFound.php b/3rdparty/Sabre/DAV/Exception/NotFound.php
new file mode 100644
index 0000000000000000000000000000000000000000..2b9da560d2352a42d44a335b2d8a2e4db8c4816f
--- /dev/null
+++ b/3rdparty/Sabre/DAV/Exception/NotFound.php
@@ -0,0 +1,28 @@
+<?php
+
+/**
+ * NotFound
+ *
+ * This Exception is thrown when a Node couldn't be found. It returns HTTP error code 404
+ *
+ * @package Sabre
+ * @subpackage DAV
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
+ * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
+ */
+class Sabre_DAV_Exception_NotFound extends Sabre_DAV_Exception {
+
+    /**
+     * Returns the HTTP statuscode for this exception
+     *
+     * @return int
+     */
+    public function getHTTPCode() {
+
+        return 404;
+
+    }
+
+}
+
diff --git a/3rdparty/Sabre/DAV/Exception/NotImplemented.php b/3rdparty/Sabre/DAV/Exception/NotImplemented.php
index cd7f609b09df436604e39bf82528854ad349bbd3..d017a19f5593e439754a12cacfb0723d7e4b54ff 100644
--- a/3rdparty/Sabre/DAV/Exception/NotImplemented.php
+++ b/3rdparty/Sabre/DAV/Exception/NotImplemented.php
@@ -4,22 +4,22 @@
  * NotImplemented
  *
  * This exception is thrown when the client tried to call an unsupported HTTP method or other feature
- * 
+ *
  * @package Sabre
  * @subpackage DAV
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
  * @author Evert Pot (http://www.rooftopsolutions.nl/) 
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
  */
 class Sabre_DAV_Exception_NotImplemented extends Sabre_DAV_Exception {
 
     /**
-     * Returns the HTTP statuscode for this exception 
+     * Returns the HTTP statuscode for this exception
      *
      * @return int
      */
     public function getHTTPCode() {
-        
+
         return 501;
 
     }
diff --git a/3rdparty/Sabre/DAV/Exception/PaymentRequired.php b/3rdparty/Sabre/DAV/Exception/PaymentRequired.php
new file mode 100644
index 0000000000000000000000000000000000000000..4982f45a4b5787030c302e146e7e85e2058fcffb
--- /dev/null
+++ b/3rdparty/Sabre/DAV/Exception/PaymentRequired.php
@@ -0,0 +1,28 @@
+<?php
+
+/**
+ * Payment Required
+ *
+ * The PaymentRequired exception may be thrown in a case where a user must pay
+ * to access a certain resource or operation.
+ *
+ * @package Sabre
+ * @subpackage DAV
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
+ * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
+ */
+class Sabre_DAV_Exception_PaymentRequired extends Sabre_DAV_Exception {
+
+    /**
+     * Returns the HTTP statuscode for this exception
+     *
+     * @return int
+     */
+    public function getHTTPCode() {
+
+        return 402;
+
+    }
+
+}
diff --git a/3rdparty/Sabre/DAV/Exception/PreconditionFailed.php b/3rdparty/Sabre/DAV/Exception/PreconditionFailed.php
index ebcb9f5b9ac858e0a77907bd8785d4e4f0b582f0..213e9c52317e3be1d2f9828098b77dbfffdb9119 100644
--- a/3rdparty/Sabre/DAV/Exception/PreconditionFailed.php
+++ b/3rdparty/Sabre/DAV/Exception/PreconditionFailed.php
@@ -1,15 +1,15 @@
 <?php
 
 /**
- * PreconditionFailed 
+ * PreconditionFailed
  *
- * This exception is normally thrown when a client submitted a conditional request, 
- * like for example an If, If-None-Match or If-Match header, which caused the HTTP 
+ * This exception is normally thrown when a client submitted a conditional request,
+ * like for example an If, If-None-Match or If-Match header, which caused the HTTP
  * request to not execute (the condition of the header failed)
- * 
+ *
  * @package Sabre
  * @subpackage DAV
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
  * @author Evert Pot (http://www.rooftopsolutions.nl/) 
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
  */
@@ -17,47 +17,47 @@ class Sabre_DAV_Exception_PreconditionFailed extends Sabre_DAV_Exception {
 
     /**
      * When this exception is thrown, the header-name might be set.
-     * 
+     *
      * This allows the exception-catching code to determine which HTTP header
      * caused the exception.
-     * 
-     * @var string 
+     *
+     * @var string
      */
     public $header = null;
 
     /**
-     * Create the exception 
-     * 
-     * @param string $message 
-     * @param string $header 
+     * Create the exception
+     *
+     * @param string $message
+     * @param string $header
      */
     public function __construct($message, $header=null) {
 
         parent::__construct($message);
         $this->header = $header;
 
-    } 
+    }
 
     /**
-     * Returns the HTTP statuscode for this exception 
+     * Returns the HTTP statuscode for this exception
      *
      * @return int
      */
     public function getHTTPCode() {
 
-        return 412; 
+        return 412;
 
     }
 
     /**
-     * This method allows the exception to include additonal information into the WebDAV error response 
+     * This method allows the exception to include additional information into the WebDAV error response
      *
      * @param Sabre_DAV_Server $server
-     * @param DOMElement $errorNode 
+     * @param DOMElement $errorNode
      * @return void
      */
     public function serialize(Sabre_DAV_Server $server,DOMElement $errorNode) {
-        
+
         if ($this->header) {
             $prop = $errorNode->ownerDocument->createElement('s:header');
             $prop->nodeValue = $this->header;
diff --git a/3rdparty/Sabre/DAV/Exception/ReportNotImplemented.php b/3rdparty/Sabre/DAV/Exception/ReportNotImplemented.php
index e4ed601b16cd8d37d3663379a17de1a5bd29171a..e86800f30381b9baf877e39d74c0c3a75b561598 100644
--- a/3rdparty/Sabre/DAV/Exception/ReportNotImplemented.php
+++ b/3rdparty/Sabre/DAV/Exception/ReportNotImplemented.php
@@ -7,17 +7,17 @@
  *
  * @package Sabre
  * @subpackage DAV
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
  * @author Evert Pot (http://www.rooftopsolutions.nl/) 
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
  */
 class Sabre_DAV_Exception_ReportNotImplemented extends Sabre_DAV_Exception_NotImplemented {
 
     /**
-     * This method allows the exception to include additonal information into the WebDAV error response 
+     * This method allows the exception to include additional information into the WebDAV error response
      *
      * @param Sabre_DAV_Server $server
-     * @param DOMElement $errorNode 
+     * @param DOMElement $errorNode
      * @return void
      */
     public function serialize(Sabre_DAV_Server $server,DOMElement $errorNode) {
diff --git a/3rdparty/Sabre/DAV/Exception/RequestedRangeNotSatisfiable.php b/3rdparty/Sabre/DAV/Exception/RequestedRangeNotSatisfiable.php
index 37abbd729d11724077faf53b3240cf153d99b0be..29ee3654a7e776b44316769244a308154d7651de 100644
--- a/3rdparty/Sabre/DAV/Exception/RequestedRangeNotSatisfiable.php
+++ b/3rdparty/Sabre/DAV/Exception/RequestedRangeNotSatisfiable.php
@@ -1,21 +1,21 @@
 <?php
 
 /**
- * RequestedRangeNotSatisfiable 
+ * RequestedRangeNotSatisfiable
  *
- * This exception is normally thrown when the user 
+ * This exception is normally thrown when the user
  * request a range that is out of the entity bounds.
  *
  * @package Sabre
  * @subpackage DAV
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
- * @author Evert Pot (http://www.rooftopsolutions.nl/) 
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
  */
 class Sabre_DAV_Exception_RequestedRangeNotSatisfiable extends Sabre_DAV_Exception {
 
     /**
-     * returns the http statuscode for this exception 
+     * returns the http statuscode for this exception
      *
      * @return int
      */
diff --git a/3rdparty/Sabre/DAV/Exception/UnsupportedMediaType.php b/3rdparty/Sabre/DAV/Exception/UnsupportedMediaType.php
index 4c37d8997cf0a63ac09aa20091160b09bd87c092..9a4693b21a8aecfc25b153710c98bc980b4fb9d5 100644
--- a/3rdparty/Sabre/DAV/Exception/UnsupportedMediaType.php
+++ b/3rdparty/Sabre/DAV/Exception/UnsupportedMediaType.php
@@ -3,19 +3,19 @@
 /**
  * UnSupportedMediaType
  *
- * The 415 Unsupported Media Type status code is generally sent back when the client 
+ * The 415 Unsupported Media Type status code is generally sent back when the client
  * tried to call an HTTP method, with a body the server didn't understand
  *
  * @package Sabre
  * @subpackage DAV
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
- * @author Evert Pot (http://www.rooftopsolutions.nl/) 
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
  */
-class Sabre_DAV_Exception_UnsupportedMediaType extends Sabre_DAV_Exception { 
+class Sabre_DAV_Exception_UnsupportedMediaType extends Sabre_DAV_Exception {
 
     /**
-     * returns the http statuscode for this exception 
+     * returns the http statuscode for this exception
      *
      * @return int
      */
diff --git a/3rdparty/Sabre/DAV/FS/Directory.php b/3rdparty/Sabre/DAV/FS/Directory.php
index ebd6a6c505e2bd10140d963bdbb1d6829b65f9f2..3af2d755583747f2c6c3e02c51030ebe9b3cc3df 100644
--- a/3rdparty/Sabre/DAV/FS/Directory.php
+++ b/3rdparty/Sabre/DAV/FS/Directory.php
@@ -1,24 +1,39 @@
 <?php
 
 /**
- * Directory class 
- * 
+ * Directory class
+ *
  * @package Sabre
  * @subpackage DAV
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
- * @author Evert Pot (http://www.rooftopsolutions.nl/) 
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
  */
 class Sabre_DAV_FS_Directory extends Sabre_DAV_FS_Node implements Sabre_DAV_ICollection, Sabre_DAV_IQuota {
 
     /**
-     * Creates a new file in the directory 
-     * 
-     * data is a readable stream resource
+     * Creates a new file in the directory
      *
-     * @param string $name Name of the file 
-     * @param resource $data Initial payload 
-     * @return void
+     * Data will either be supplied as a stream resource, or in certain cases
+     * as a string. Keep in mind that you may have to support either.
+     *
+     * After succesful creation of the file, you may choose to return the ETag
+     * of the new file here.
+     *
+     * The returned ETag must be surrounded by double-quotes (The quotes should
+     * be part of the actual string).
+     *
+     * If you cannot accurately determine the ETag, you should not return it.
+     * If you don't store the file exactly as-is (you're transforming it
+     * somehow) you should also not return an ETag.
+     *
+     * This means that if a subsequent GET to this new file does not exactly
+     * return the same contents of what was submitted here, you are strongly
+     * recommended to omit the ETag.
+     *
+     * @param string $name Name of the file
+     * @param resource|string $data Initial payload
+     * @return null|string
      */
     public function createFile($name, $data = null) {
 
@@ -28,9 +43,9 @@ class Sabre_DAV_FS_Directory extends Sabre_DAV_FS_Node implements Sabre_DAV_ICol
     }
 
     /**
-     * Creates a new subdirectory 
-     * 
-     * @param string $name 
+     * Creates a new subdirectory
+     *
+     * @param string $name
      * @return void
      */
     public function createDirectory($name) {
@@ -41,17 +56,17 @@ class Sabre_DAV_FS_Directory extends Sabre_DAV_FS_Node implements Sabre_DAV_ICol
     }
 
     /**
-     * Returns a specific child node, referenced by its name 
-     * 
-     * @param string $name 
-     * @throws Sabre_DAV_Exception_FileNotFound
-     * @return Sabre_DAV_INode 
+     * Returns a specific child node, referenced by its name
+     *
+     * @param string $name
+     * @throws Sabre_DAV_Exception_NotFound
+     * @return Sabre_DAV_INode
      */
     public function getChild($name) {
 
         $path = $this->path . '/' . $name;
 
-        if (!file_exists($path)) throw new Sabre_DAV_Exception_FileNotFound('File with name ' . $path . ' could not be located');
+        if (!file_exists($path)) throw new Sabre_DAV_Exception_NotFound('File with name ' . $path . ' could not be located');
 
         if (is_dir($path)) {
 
@@ -66,9 +81,9 @@ class Sabre_DAV_FS_Directory extends Sabre_DAV_FS_Node implements Sabre_DAV_ICol
     }
 
     /**
-     * Returns an array with all the child nodes 
-     * 
-     * @return Sabre_DAV_INode[] 
+     * Returns an array with all the child nodes
+     *
+     * @return Sabre_DAV_INode[]
      */
     public function getChildren() {
 
@@ -79,10 +94,10 @@ class Sabre_DAV_FS_Directory extends Sabre_DAV_FS_Node implements Sabre_DAV_ICol
     }
 
     /**
-     * Checks if a child exists. 
-     * 
-     * @param string $name 
-     * @return bool 
+     * Checks if a child exists.
+     *
+     * @param string $name
+     * @return bool
      */
     public function childExists($name) {
 
@@ -92,8 +107,8 @@ class Sabre_DAV_FS_Directory extends Sabre_DAV_FS_Node implements Sabre_DAV_ICol
     }
 
     /**
-     * Deletes all files in this directory, and then itself 
-     * 
+     * Deletes all files in this directory, and then itself
+     *
      * @return void
      */
     public function delete() {
@@ -104,16 +119,16 @@ class Sabre_DAV_FS_Directory extends Sabre_DAV_FS_Node implements Sabre_DAV_ICol
     }
 
     /**
-     * Returns available diskspace information 
-     * 
-     * @return array 
+     * Returns available diskspace information
+     *
+     * @return array
      */
     public function getQuotaInfo() {
 
         return array(
             disk_total_space($this->path)-disk_free_space($this->path),
             disk_free_space($this->path)
-            ); 
+            );
 
     }
 
diff --git a/3rdparty/Sabre/DAV/FS/File.php b/3rdparty/Sabre/DAV/FS/File.php
index 262187d7e8ab8c1abeb60d8b9584920d2b05fe55..6a8039fe303afbbf98364db93df3cf0c8bca987f 100644
--- a/3rdparty/Sabre/DAV/FS/File.php
+++ b/3rdparty/Sabre/DAV/FS/File.php
@@ -1,21 +1,21 @@
 <?php
 
 /**
- * File class 
- * 
+ * File class
+ *
  * @package Sabre
  * @subpackage DAV
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
- * @author Evert Pot (http://www.rooftopsolutions.nl/) 
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
  */
 class Sabre_DAV_FS_File extends Sabre_DAV_FS_Node implements Sabre_DAV_IFile {
 
     /**
-     * Updates the data 
-     * 
-     * @param resource $data 
-     * @return void 
+     * Updates the data
+     *
+     * @param resource $data
+     * @return void
      */
     public function put($data) {
 
@@ -24,9 +24,9 @@ class Sabre_DAV_FS_File extends Sabre_DAV_FS_Node implements Sabre_DAV_IFile {
     }
 
     /**
-     * Returns the data 
-     * 
-     * @return string 
+     * Returns the data
+     *
+     * @return string
      */
     public function get() {
 
@@ -37,7 +37,7 @@ class Sabre_DAV_FS_File extends Sabre_DAV_FS_Node implements Sabre_DAV_IFile {
     /**
      * Delete the current file
      *
-     * @return void 
+     * @return void
      */
     public function delete() {
 
@@ -46,12 +46,12 @@ class Sabre_DAV_FS_File extends Sabre_DAV_FS_Node implements Sabre_DAV_IFile {
     }
 
     /**
-     * Returns the size of the node, in bytes 
-     * 
-     * @return int 
+     * Returns the size of the node, in bytes
+     *
+     * @return int
      */
     public function getSize() {
-        
+
         return filesize($this->path);
 
     }
@@ -60,10 +60,10 @@ class Sabre_DAV_FS_File extends Sabre_DAV_FS_Node implements Sabre_DAV_IFile {
      * Returns the ETag for a file
      *
      * An ETag is a unique identifier representing the current version of the file. If the file changes, the ETag MUST change.
-     * The ETag is an arbritrary string, but MUST be surrounded by double-quotes.
+     * The ETag is an arbitrary string, but MUST be surrounded by double-quotes.
      *
      * Return null if the ETag can not effectively be determined
-     * 
+     *
      * @return mixed
      */
     public function getETag() {
@@ -77,8 +77,8 @@ class Sabre_DAV_FS_File extends Sabre_DAV_FS_Node implements Sabre_DAV_IFile {
      *
      * If null is returned, we'll assume application/octet-stream
      *
-     * @return mixed 
-     */ 
+     * @return mixed
+     */
     public function getContentType() {
 
         return null;
diff --git a/3rdparty/Sabre/DAV/FS/Node.php b/3rdparty/Sabre/DAV/FS/Node.php
index b8d7bcfe8461c11dc4448098889dacf29939aa4a..1283e9d0fdcb70c2bfc91eaaeb1bc024665ff086 100644
--- a/3rdparty/Sabre/DAV/FS/Node.php
+++ b/3rdparty/Sabre/DAV/FS/Node.php
@@ -1,30 +1,29 @@
 <?php
 
 /**
- * Base node-class 
+ * Base node-class
+ *
+ * The node class implements the method used by both the File and the Directory classes
  *
- * The node class implements the method used by both the File and the Directory classes 
- * 
  * @package Sabre
  * @subpackage DAV
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
- * @author Evert Pot (http://www.rooftopsolutions.nl/) 
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
  */
 abstract class Sabre_DAV_FS_Node implements Sabre_DAV_INode {
 
     /**
      * The path to the current node
-     * 
-     * @var string 
+     *
+     * @var string
      */
-    protected $path; 
+    protected $path;
 
     /**
-     * Sets up the node, expects a full path name 
-     * 
-     * @param string $path 
-     * @return void
+     * Sets up the node, expects a full path name
+     *
+     * @param string $path
      */
     public function __construct($path) {
 
@@ -35,9 +34,9 @@ abstract class Sabre_DAV_FS_Node implements Sabre_DAV_INode {
 
 
     /**
-     * Returns the name of the node 
-     * 
-     * @return string 
+     * Returns the name of the node
+     *
+     * @return string
      */
     public function getName() {
 
@@ -59,7 +58,7 @@ abstract class Sabre_DAV_FS_Node implements Sabre_DAV_INode {
 
         $newPath = $parentPath . '/' . $newName;
         rename($this->path,$newPath);
-        
+
         $this->path = $newPath;
 
     }
@@ -67,9 +66,9 @@ abstract class Sabre_DAV_FS_Node implements Sabre_DAV_INode {
 
 
     /**
-     * Returns the last modification time, as a unix timestamp 
-     * 
-     * @return int 
+     * Returns the last modification time, as a unix timestamp
+     *
+     * @return int
      */
     public function getLastModified() {
 
diff --git a/3rdparty/Sabre/DAV/FSExt/Directory.php b/3rdparty/Sabre/DAV/FSExt/Directory.php
index c43d4385ac7b75cb20d19857501cebef51039aa9..540057183b30380c24e8395ab6def0a792a06ff6 100644
--- a/3rdparty/Sabre/DAV/FSExt/Directory.php
+++ b/3rdparty/Sabre/DAV/FSExt/Directory.php
@@ -1,22 +1,39 @@
 <?php
 
 /**
- * Directory class 
- * 
+ * Directory class
+ *
  * @package Sabre
  * @subpackage DAV
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
- * @author Evert Pot (http://www.rooftopsolutions.nl/) 
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
  */
 class Sabre_DAV_FSExt_Directory extends Sabre_DAV_FSExt_Node implements Sabre_DAV_ICollection, Sabre_DAV_IQuota {
 
     /**
-     * Creates a new file in the directory 
-     * 
-     * @param string $name Name of the file 
-     * @param resource $data Initial payload 
-     * @return void
+     * Creates a new file in the directory
+     *
+     * Data will either be supplied as a stream resource, or in certain cases
+     * as a string. Keep in mind that you may have to support either.
+     *
+     * After succesful creation of the file, you may choose to return the ETag
+     * of the new file here.
+     *
+     * The returned ETag must be surrounded by double-quotes (The quotes should
+     * be part of the actual string).
+     *
+     * If you cannot accurately determine the ETag, you should not return it.
+     * If you don't store the file exactly as-is (you're transforming it
+     * somehow) you should also not return an ETag.
+     *
+     * This means that if a subsequent GET to this new file does not exactly
+     * return the same contents of what was submitted here, you are strongly
+     * recommended to omit the ETag.
+     *
+     * @param string $name Name of the file
+     * @param resource|string $data Initial payload
+     * @return null|string
      */
     public function createFile($name, $data = null) {
 
@@ -25,12 +42,14 @@ class Sabre_DAV_FSExt_Directory extends Sabre_DAV_FSExt_Node implements Sabre_DA
         $newPath = $this->path . '/' . $name;
         file_put_contents($newPath,$data);
 
+        return '"' . md5_file($newPath) . '"';
+
     }
 
     /**
-     * Creates a new subdirectory 
-     * 
-     * @param string $name 
+     * Creates a new subdirectory
+     *
+     * @param string $name
      * @return void
      */
     public function createDirectory($name) {
@@ -43,18 +62,18 @@ class Sabre_DAV_FSExt_Directory extends Sabre_DAV_FSExt_Node implements Sabre_DA
     }
 
     /**
-     * Returns a specific child node, referenced by its name 
-     * 
-     * @param string $name 
-     * @throws Sabre_DAV_Exception_FileNotFound
-     * @return Sabre_DAV_INode 
+     * Returns a specific child node, referenced by its name
+     *
+     * @param string $name
+     * @throws Sabre_DAV_Exception_NotFound
+     * @return Sabre_DAV_INode
      */
     public function getChild($name) {
 
         $path = $this->path . '/' . $name;
 
-        if (!file_exists($path)) throw new Sabre_DAV_Exception_FileNotFound('File could not be located');
-        if ($name=='.' || $name=='..') throw new Sabre_DAV_Exception_Forbidden('Permission denied to . and ..'); 
+        if (!file_exists($path)) throw new Sabre_DAV_Exception_NotFound('File could not be located');
+        if ($name=='.' || $name=='..') throw new Sabre_DAV_Exception_Forbidden('Permission denied to . and ..');
 
         if (is_dir($path)) {
 
@@ -69,10 +88,10 @@ class Sabre_DAV_FSExt_Directory extends Sabre_DAV_FSExt_Node implements Sabre_DA
     }
 
     /**
-     * Checks if a child exists. 
-     * 
-     * @param string $name 
-     * @return bool 
+     * Checks if a child exists.
+     *
+     * @param string $name
+     * @return bool
      */
     public function childExists($name) {
 
@@ -85,9 +104,9 @@ class Sabre_DAV_FSExt_Directory extends Sabre_DAV_FSExt_Node implements Sabre_DA
     }
 
     /**
-     * Returns an array with all the child nodes 
-     * 
-     * @return Sabre_DAV_INode[] 
+     * Returns an array with all the child nodes
+     *
+     * @return Sabre_DAV_INode[]
      */
     public function getChildren() {
 
@@ -98,9 +117,9 @@ class Sabre_DAV_FSExt_Directory extends Sabre_DAV_FSExt_Node implements Sabre_DA
     }
 
     /**
-     * Deletes all files in this directory, and then itself 
-     * 
-     * @return void
+     * Deletes all files in this directory, and then itself
+     *
+     * @return bool
      */
     public function delete() {
 
@@ -118,16 +137,16 @@ class Sabre_DAV_FSExt_Directory extends Sabre_DAV_FSExt_Node implements Sabre_DA
     }
 
     /**
-     * Returns available diskspace information 
-     * 
-     * @return array 
+     * Returns available diskspace information
+     *
+     * @return array
      */
     public function getQuotaInfo() {
 
         return array(
             disk_total_space($this->path)-disk_free_space($this->path),
             disk_free_space($this->path)
-            ); 
+            );
 
     }
 
diff --git a/3rdparty/Sabre/DAV/FSExt/File.php b/3rdparty/Sabre/DAV/FSExt/File.php
index 7a8e7a11f21308dd0d285670030cebd925fdd1e2..b93ce5aee2108bfbdb5bebf3a3a6619b7eda458b 100644
--- a/3rdparty/Sabre/DAV/FSExt/File.php
+++ b/3rdparty/Sabre/DAV/FSExt/File.php
@@ -1,34 +1,35 @@
 <?php
 
 /**
- * File class 
- * 
+ * File class
+ *
  * @package Sabre
  * @subpackage DAV
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
- * @author Evert Pot (http://www.rooftopsolutions.nl/) 
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
  */
 class Sabre_DAV_FSExt_File extends Sabre_DAV_FSExt_Node implements Sabre_DAV_IFile {
 
     /**
-     * Updates the data 
+     * Updates the data
      *
      * data is a readable stream resource.
      *
-     * @param resource $data 
-     * @return void 
+     * @param resource $data
+     * @return void
      */
     public function put($data) {
 
         file_put_contents($this->path,$data);
+        return '"' . md5_file($this->path) . '"';
 
     }
 
     /**
      * Returns the data
      *
-     * @return string 
+     * @return string
      */
     public function get() {
 
@@ -39,7 +40,7 @@ class Sabre_DAV_FSExt_File extends Sabre_DAV_FSExt_Node implements Sabre_DAV_IFi
     /**
      * Delete the current file
      *
-     * @return void 
+     * @return bool
      */
     public function delete() {
 
@@ -52,9 +53,11 @@ class Sabre_DAV_FSExt_File extends Sabre_DAV_FSExt_Node implements Sabre_DAV_IFi
      * Returns the ETag for a file
      *
      * An ETag is a unique identifier representing the current version of the file. If the file changes, the ETag MUST change.
-     * The ETag is an arbritrary string, but MUST be surrounded by double-quotes.
+     * The ETag is an arbitrary string, but MUST be surrounded by double-quotes.
      *
      * Return null if the ETag can not effectively be determined
+     *
+     * @return string|null
      */
     public function getETag() {
 
@@ -66,7 +69,9 @@ class Sabre_DAV_FSExt_File extends Sabre_DAV_FSExt_Node implements Sabre_DAV_IFi
      * Returns the mime-type for a file
      *
      * If null is returned, we'll assume application/octet-stream
-     */ 
+     *
+     * @return string|null
+     */
     public function getContentType() {
 
         return null;
@@ -74,9 +79,9 @@ class Sabre_DAV_FSExt_File extends Sabre_DAV_FSExt_Node implements Sabre_DAV_IFi
     }
 
     /**
-     * Returns the size of the file, in bytes 
-     * 
-     * @return int 
+     * Returns the size of the file, in bytes
+     *
+     * @return int
      */
     public function getSize() {
 
diff --git a/3rdparty/Sabre/DAV/FSExt/Node.php b/3rdparty/Sabre/DAV/FSExt/Node.php
index 9e36222bfd325a6bbe164bea5670e120fb83caf1..68ca06beb7e0930c40a20f75907baec4b1b58944 100644
--- a/3rdparty/Sabre/DAV/FSExt/Node.php
+++ b/3rdparty/Sabre/DAV/FSExt/Node.php
@@ -1,95 +1,28 @@
 <?php
 
 /**
- * Base node-class 
+ * Base node-class
+ *
+ * The node class implements the method used by both the File and the Directory classes
  *
- * The node class implements the method used by both the File and the Directory classes 
- * 
  * @package Sabre
  * @subpackage DAV
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
- * @author Evert Pot (http://www.rooftopsolutions.nl/) 
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
  */
-abstract class Sabre_DAV_FSExt_Node extends Sabre_DAV_FS_Node implements Sabre_DAV_ILockable, Sabre_DAV_IProperties {
-
-    /**
-     * Returns all the locks on this node
-     * 
-     * @return array 
-     */
-    function getLocks() {
-
-        $resourceData = $this->getResourceData();
-        $locks = $resourceData['locks'];
-        foreach($locks as $k=>$lock) {
-            if (time() > $lock->timeout + $lock->created) unset($locks[$k]); 
-        }
-        return $locks;
-
-    }
-
-    /**
-     * Locks this node 
-     * 
-     * @param Sabre_DAV_Locks_LockInfo $lockInfo 
-     * @return void
-     */
-    function lock(Sabre_DAV_Locks_LockInfo $lockInfo) {
-
-        // We're making the lock timeout 30 minutes
-        $lockInfo->timeout = 1800;
-        $lockInfo->created = time();
-
-        $resourceData = $this->getResourceData();
-        if (!isset($resourceData['locks'])) $resourceData['locks'] = array();
-        $current = null;
-        foreach($resourceData['locks'] as $k=>$lock) {
-            if ($lock->token === $lockInfo->token) $current = $k;
-        }
-        if (!is_null($current)) $resourceData['locks'][$current] = $lockInfo;
-        else $resourceData['locks'][] = $lockInfo;
-
-        $this->putResourceData($resourceData);
-
-    }
-
-    /**
-     * Removes a lock from this node
-     * 
-     * @param Sabre_DAV_Locks_LockInfo $lockInfo 
-     * @return bool 
-     */
-    function unlock(Sabre_DAV_Locks_LockInfo $lockInfo) {
-
-        //throw new Sabre_DAV_Exception('bla');
-        $resourceData = $this->getResourceData();
-        foreach($resourceData['locks'] as $k=>$lock) {
-
-            if ($lock->token === $lockInfo->token) {
-
-                unset($resourceData['locks'][$k]);
-                $this->putResourceData($resourceData);
-                return true;
-
-            }
-        }
-        return false;
-
-    }
+abstract class Sabre_DAV_FSExt_Node extends Sabre_DAV_FS_Node implements Sabre_DAV_IProperties {
 
     /**
      * Updates properties on this node,
      *
-     * @param array $mutations
+     * @param array $properties
      * @see Sabre_DAV_IProperties::updateProperties
-     * @return bool|array 
+     * @return bool|array
      */
     public function updateProperties($properties) {
 
         $resourceData = $this->getResourceData();
-        
-        $result = array();
 
         foreach($properties as $propertyName=>$propertyValue) {
 
@@ -101,11 +34,11 @@ abstract class Sabre_DAV_FSExt_Node extends Sabre_DAV_FS_Node implements Sabre_D
             } else {
                 $resourceData['properties'][$propertyName] = $propertyValue;
             }
-               
+
         }
 
         $this->putResourceData($resourceData);
-        return true; 
+        return true;
     }
 
     /**
@@ -114,8 +47,8 @@ abstract class Sabre_DAV_FSExt_Node extends Sabre_DAV_FS_Node implements Sabre_D
      * The properties list is a list of propertynames the client requested, encoded as xmlnamespace#tagName, for example: http://www.example.org/namespace#author
      * If the array is empty, all properties should be returned
      *
-     * @param array $properties 
-     * @return void
+     * @param array $properties
+     * @return array
      */
     function getProperties($properties) {
 
@@ -134,9 +67,9 @@ abstract class Sabre_DAV_FSExt_Node extends Sabre_DAV_FS_Node implements Sabre_D
     }
 
     /**
-     * Returns the path to the resource file 
-     * 
-     * @return string 
+     * Returns the path to the resource file
+     *
+     * @return string
      */
     protected function getResourceInfoPath() {
 
@@ -146,14 +79,14 @@ abstract class Sabre_DAV_FSExt_Node extends Sabre_DAV_FS_Node implements Sabre_D
     }
 
     /**
-     * Returns all the stored resource information 
-     * 
-     * @return array 
+     * Returns all the stored resource information
+     *
+     * @return array
      */
     protected function getResourceData() {
 
         $path = $this->getResourceInfoPath();
-        if (!file_exists($path)) return array('locks'=>array(), 'properties' => array());
+        if (!file_exists($path)) return array('properties' => array());
 
         // opening up the file, and creating a shared lock
         $handle = fopen($path,'r');
@@ -171,20 +104,19 @@ abstract class Sabre_DAV_FSExt_Node extends Sabre_DAV_FS_Node implements Sabre_D
         // Unserializing and checking if the resource file contains data for this file
         $data = unserialize($data);
         if (!isset($data[$this->getName()])) {
-            return array('locks'=>array(), 'properties' => array());
+            return array('properties' => array());
         }
 
         $data = $data[$this->getName()];
-        if (!isset($data['locks'])) $data['locks'] = array();
         if (!isset($data['properties'])) $data['properties'] = array();
         return $data;
 
     }
 
     /**
-     * Updates the resource information 
-     * 
-     * @param array $newData 
+     * Updates the resource information
+     *
+     * @param array $newData
      * @return void
      */
     protected function putResourceData(array $newData) {
@@ -238,6 +170,9 @@ abstract class Sabre_DAV_FSExt_Node extends Sabre_DAV_FS_Node implements Sabre_D
 
     }
 
+    /**
+     * @return bool
+     */
     public function deleteResourceData() {
 
         // When we're deleting this node, we also need to delete any resource information
@@ -264,6 +199,7 @@ abstract class Sabre_DAV_FSExt_Node extends Sabre_DAV_FS_Node implements Sabre_D
         fwrite($handle,serialize($data));
         fclose($handle);
 
+        return true;
     }
 
     public function delete() {
diff --git a/3rdparty/Sabre/DAV/File.php b/3rdparty/Sabre/DAV/File.php
index b74bd9525b34cc8452466b260ca8be4c9fc9e16e..3126bd8d364b6c5fdd27ee8fec8fea4b90a48f9c 100644
--- a/3rdparty/Sabre/DAV/File.php
+++ b/3rdparty/Sabre/DAV/File.php
@@ -4,12 +4,12 @@
  * File class
  *
  * This is a helper class, that should aid in getting file classes setup.
- * Most of its methods are implemented, and throw permission denied exceptions 
- * 
+ * Most of its methods are implemented, and throw permission denied exceptions
+ *
  * @package Sabre
  * @subpackage DAV
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
- * @author Evert Pot (http://www.rooftopsolutions.nl/) 
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
  */
 abstract class Sabre_DAV_File extends Sabre_DAV_Node implements Sabre_DAV_IFile {
@@ -18,33 +18,33 @@ abstract class Sabre_DAV_File extends Sabre_DAV_Node implements Sabre_DAV_IFile
      * Updates the data
      *
      * data is a readable stream resource.
-     * 
-     * @param resource $data 
-     * @return void 
+     *
+     * @param resource $data
+     * @return void
      */
-    public function put($data) { 
+    public function put($data) {
 
         throw new Sabre_DAV_Exception_Forbidden('Permission denied to change data');
 
     }
 
     /**
-     * Returns the data 
+     * Returns the data
      *
      * This method may either return a string or a readable stream resource
      *
-     * @return mixed 
+     * @return mixed
      */
-    public function get() { 
+    public function get() {
 
         throw new Sabre_DAV_Exception_Forbidden('Permission denied to read this file');
 
     }
-    
+
     /**
-     * Returns the size of the file, in bytes. 
-     * 
-     * @return int 
+     * Returns the size of the file, in bytes.
+     *
+     * @return int
      */
     public function getSize() {
 
@@ -56,9 +56,11 @@ abstract class Sabre_DAV_File extends Sabre_DAV_Node implements Sabre_DAV_IFile
      * Returns the ETag for a file
      *
      * An ETag is a unique identifier representing the current version of the file. If the file changes, the ETag MUST change.
-     * The ETag is an arbritrary string, but MUST be surrounded by double-quotes.
+     * The ETag is an arbitrary string, but MUST be surrounded by double-quotes.
      *
      * Return null if the ETag can not effectively be determined
+     *
+     * @return string|null
      */
     public function getETag() {
 
@@ -70,7 +72,9 @@ abstract class Sabre_DAV_File extends Sabre_DAV_Node implements Sabre_DAV_IFile
      * Returns the mime-type for a file
      *
      * If null is returned, we'll assume application/octet-stream
-     */ 
+     *
+     * @return string|null
+     */
     public function getContentType() {
 
         return null;
diff --git a/3rdparty/Sabre/DAV/ICollection.php b/3rdparty/Sabre/DAV/ICollection.php
index 0667d88899d2d307c025cc247503506f0d9311e5..4626038a66e3fcb31e211adf577b742e704cf194 100644
--- a/3rdparty/Sabre/DAV/ICollection.php
+++ b/3rdparty/Sabre/DAV/ICollection.php
@@ -3,54 +3,70 @@
 /**
  * The ICollection Interface
  *
- * This interface should be implemented by each class that represents a collection 
- * 
+ * This interface should be implemented by each class that represents a collection
+ *
  * @package Sabre
  * @subpackage DAV
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
- * @author Evert Pot (http://www.rooftopsolutions.nl/) 
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
  */
 interface Sabre_DAV_ICollection extends Sabre_DAV_INode {
 
     /**
-     * Creates a new file in the directory 
-     * 
-     * data is a readable stream resource
+     * Creates a new file in the directory
      *
-     * @param string $name Name of the file 
-     * @param resource $data Initial payload 
-     * @return void
+     * Data will either be supplied as a stream resource, or in certain cases
+     * as a string. Keep in mind that you may have to support either.
+     *
+     * After succesful creation of the file, you may choose to return the ETag
+     * of the new file here.
+     *
+     * The returned ETag must be surrounded by double-quotes (The quotes should
+     * be part of the actual string).
+     *
+     * If you cannot accurately determine the ETag, you should not return it.
+     * If you don't store the file exactly as-is (you're transforming it
+     * somehow) you should also not return an ETag.
+     *
+     * This means that if a subsequent GET to this new file does not exactly
+     * return the same contents of what was submitted here, you are strongly
+     * recommended to omit the ETag.
+     *
+     * @param string $name Name of the file
+     * @param resource|string $data Initial payload
+     * @return null|string
      */
     function createFile($name, $data = null);
 
     /**
-     * Creates a new subdirectory 
-     * 
-     * @param string $name 
+     * Creates a new subdirectory
+     *
+     * @param string $name
      * @return void
      */
     function createDirectory($name);
 
     /**
-     * Returns a specific child node, referenced by its name 
-     * 
-     * @param string $name 
-     * @return Sabre_DAV_INode 
+     * Returns a specific child node, referenced by its name
+     *
+     * @param string $name
+     * @return Sabre_DAV_INode
      */
     function getChild($name);
 
     /**
-     * Returns an array with all the child nodes 
-     * 
-     * @return Sabre_DAV_INode[] 
+     * Returns an array with all the child nodes
+     *
+     * @return Sabre_DAV_INode[]
      */
     function getChildren();
 
     /**
-     * Checks if a child-node with the specified name exists 
-     * 
-     * @return bool 
+     * Checks if a child-node with the specified name exists
+     *
+     * @param string $name
+     * @return bool
      */
     function childExists($name);
 
diff --git a/3rdparty/Sabre/DAV/IExtendedCollection.php b/3rdparty/Sabre/DAV/IExtendedCollection.php
index b8db1ab2f26917a03d5266e22ab157efc3e132bc..6ec345f9a624af16b136ef24570508e017e3e281 100644
--- a/3rdparty/Sabre/DAV/IExtendedCollection.php
+++ b/3rdparty/Sabre/DAV/IExtendedCollection.php
@@ -5,11 +5,11 @@
  *
  * This interface can be used to create special-type of collection-resources
  * as defined by RFC 5689.
- * 
+ *
  * @package Sabre
  * @subpackage DAV
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
- * @author Evert Pot (http://www.rooftopsolutions.nl/) 
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
  */
 interface Sabre_DAV_IExtendedCollection extends Sabre_DAV_ICollection {
@@ -17,7 +17,7 @@ interface Sabre_DAV_IExtendedCollection extends Sabre_DAV_ICollection {
     /**
      * Creates a new collection
      *
-     * @param string $name 
+     * @param string $name
      * @param array $resourceType
      * @param array $properties
      * @return void
diff --git a/3rdparty/Sabre/DAV/IFile.php b/3rdparty/Sabre/DAV/IFile.php
index 446ec86187b3a42f9770683de660b95ff87f3cfb..478f822ae712a8d4b438f61e827de6d2f84c8f9e 100644
--- a/3rdparty/Sabre/DAV/IFile.php
+++ b/3rdparty/Sabre/DAV/IFile.php
@@ -1,34 +1,48 @@
 <?php
 
 /**
- * This interface represents a file or leaf in the tree.
+ * This interface represents a file in the directory tree
+ *
+ * A file is a bit of a broad definition. In general it implies that on
+ * this specific node a PUT or GET method may be performed, to either update,
+ * or retrieve the contents of the file.
  *
- * The nature of a file is, as you might be aware of, that it doesn't contain sub-nodes and has contents
- * 
  * @package Sabre
  * @subpackage DAV
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
- * @author Evert Pot (http://www.rooftopsolutions.nl/) 
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
  */
 interface Sabre_DAV_IFile extends Sabre_DAV_INode {
 
     /**
-     * Updates the data 
-     * 
+     * Updates the data
+     *
      * The data argument is a readable stream resource.
      *
-     * @param resource $data 
-     * @return void 
+     * After a succesful put operation, you may choose to return an ETag. The
+     * etag must always be surrounded by double-quotes. These quotes must
+     * appear in the actual string you're returning.
+     *
+     * Clients may use the ETag from a PUT request to later on make sure that
+     * when they update the file, the contents haven't changed in the mean
+     * time.
+     *
+     * If you don't plan to store the file byte-by-byte, and you return a
+     * different object on a subsequent GET you are strongly recommended to not
+     * return an ETag, and just return null.
+     *
+     * @param resource $data
+     * @return string|null
      */
     function put($data);
 
     /**
-     * Returns the data 
-     * 
+     * Returns the data
+     *
      * This method may either return a string or a readable stream resource
      *
-     * @return mixed 
+     * @return mixed
      */
     function get();
 
@@ -36,7 +50,7 @@ interface Sabre_DAV_IFile extends Sabre_DAV_INode {
      * Returns the mime-type for a file
      *
      * If null is returned, we'll assume application/octet-stream
-     * 
+     *
      * @return void
      */
     function getContentType();
@@ -47,15 +61,15 @@ interface Sabre_DAV_IFile extends Sabre_DAV_INode {
      * An ETag is a unique identifier representing the current version of the file. If the file changes, the ETag MUST change.
      *
      * Return null if the ETag can not effectively be determined
-     * 
+     *
      * @return void
      */
     function getETag();
 
     /**
-     * Returns the size of the node, in bytes 
-     * 
-     * @return int 
+     * Returns the size of the node, in bytes
+     *
+     * @return int
      */
     function getSize();
 
diff --git a/3rdparty/Sabre/DAV/ILockable.php b/3rdparty/Sabre/DAV/ILockable.php
deleted file mode 100644
index f9fb3a702511eccfd4684c22c606237e1255570b..0000000000000000000000000000000000000000
--- a/3rdparty/Sabre/DAV/ILockable.php
+++ /dev/null
@@ -1,38 +0,0 @@
-<?php
-
-/**
- * Implement this class to support locking 
- * 
- * @package Sabre
- * @subpackage DAV
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
- * @author Evert Pot (http://www.rooftopsolutions.nl/) 
- * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
- */
-interface Sabre_DAV_ILockable extends Sabre_DAV_INode {
-
-    /**
-     * Returns an array with locks currently on the node 
-     * 
-     * @return Sabre_DAV_Locks_LockInfo[] 
-     */
-    function getLocks();
-
-    /**
-     * Creates a new lock on the file.  
-     * 
-     * @param Sabre_DAV_Locks_LockInfo $lockInfo The lock information 
-     * @return void
-     */
-    function lock(Sabre_DAV_Locks_LockInfo $lockInfo);
-
-    /**
-     * Unlocks a file 
-     * 
-     * @param Sabre_DAV_Locks_LockInfo $lockInfo The lock information 
-     * @return void 
-     */
-    function unlock(Sabre_DAV_Locks_LockInfo $lockInfo);
-
-}
-
diff --git a/3rdparty/Sabre/DAV/INode.php b/3rdparty/Sabre/DAV/INode.php
index c0b96bf53775370a3374259b51196a0b26e48b1b..c57d3923105d4f0f961afb9a1c4ff28ffffcd971 100644
--- a/3rdparty/Sabre/DAV/INode.php
+++ b/3rdparty/Sabre/DAV/INode.php
@@ -2,11 +2,11 @@
 
 /**
  * The INode interface is the base interface, and the parent class of both ICollection and IFile
- * 
+ *
  * @package Sabre
  * @subpackage DAV
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
- * @author Evert Pot (http://www.rooftopsolutions.nl/) 
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
  */
 interface Sabre_DAV_INode {
@@ -14,14 +14,16 @@ interface Sabre_DAV_INode {
     /**
      * Deleted the current node
      *
-     * @return void 
+     * @return void
      */
     function delete();
 
     /**
-     * Returns the name of the node 
-     * 
-     * @return string 
+     * Returns the name of the node.
+     *
+     * This is used to generate the url.
+     *
+     * @return string
      */
     function getName();
 
@@ -34,9 +36,9 @@ interface Sabre_DAV_INode {
     function setName($name);
 
     /**
-     * Returns the last modification time, as a unix timestamp 
-     * 
-     * @return int 
+     * Returns the last modification time, as a unix timestamp
+     *
+     * @return int
      */
     function getLastModified();
 
diff --git a/3rdparty/Sabre/DAV/IProperties.php b/3rdparty/Sabre/DAV/IProperties.php
index af17cad24affd88f1fe8633b25dae128b6b6460f..38eaab16dadb652e786429bb108785162cf6acc8 100644
--- a/3rdparty/Sabre/DAV/IProperties.php
+++ b/3rdparty/Sabre/DAV/IProperties.php
@@ -4,11 +4,11 @@
  * IProperties interface
  *
  * Implement this interface to support custom WebDAV properties requested and sent from clients.
- * 
+ *
  * @package Sabre
  * @subpackage DAV
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
- * @author Evert Pot (http://www.rooftopsolutions.nl/) 
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
  */
 interface Sabre_DAV_IProperties extends Sabre_DAV_INode {
@@ -26,7 +26,7 @@ interface Sabre_DAV_IProperties extends Sabre_DAV_INode {
      * If the operation was successful, true can be returned.
      * If the operation failed, false can be returned.
      *
-     * Deletion of a non-existant property is always succesful.
+     * Deletion of a non-existent property is always successful.
      *
      * Lastly, it is optional to return detailed information about any
      * failures. In this case an array should be returned with the following
@@ -41,12 +41,12 @@ interface Sabre_DAV_IProperties extends Sabre_DAV_INode {
      *   )
      * )
      *
-     * In this example it was forbidden to update {DAV:}displayname. 
+     * In this example it was forbidden to update {DAV:}displayname.
      * (403 Forbidden), which in turn also caused {DAV:}owner to fail
      * (424 Failed Dependency) because the request needs to be atomic.
      *
-     * @param array $mutations 
-     * @return bool|array 
+     * @param array $mutations
+     * @return bool|array
      */
     function updateProperties($mutations);
 
@@ -58,7 +58,7 @@ interface Sabre_DAV_IProperties extends Sabre_DAV_INode {
      *
      * If the array is empty, it means 'all properties' were requested.
      *
-     * @param array $properties 
+     * @param array $properties
      * @return void
      */
     function getProperties($properties);
diff --git a/3rdparty/Sabre/DAV/IQuota.php b/3rdparty/Sabre/DAV/IQuota.php
index 8ff1a4597f85d43610439216f9c8ecc440429a0c..3fe4c4eced4bd4e58b15408a3192d38c08a33850 100644
--- a/3rdparty/Sabre/DAV/IQuota.php
+++ b/3rdparty/Sabre/DAV/IQuota.php
@@ -4,13 +4,13 @@
  * IQuota interface
  *
  * Implement this interface to add the ability to return quota information. The ObjectTree
- * will check for quota information on any given node. If the information is not available it will 
+ * will check for quota information on any given node. If the information is not available it will
  * attempt to fetch the information from the root node.
- * 
+ *
  * @package Sabre
  * @subpackage DAV
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
- * @author Evert Pot (http://www.rooftopsolutions.nl/) 
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
  */
 interface Sabre_DAV_IQuota extends Sabre_DAV_ICollection {
@@ -21,7 +21,7 @@ interface Sabre_DAV_IQuota extends Sabre_DAV_ICollection {
      * This method MUST return an array with 2 values, the first being the total used space,
      * the second the available space (in bytes)
      */
-    function getQuotaInfo(); 
+    function getQuotaInfo();
 
 }
 
diff --git a/3rdparty/Sabre/DAV/Locks/Backend/Abstract.php b/3rdparty/Sabre/DAV/Locks/Backend/Abstract.php
index b09f93ddac79e41d1aa9497d7739a8a20d5d15d9..127e643a2b9658db3b19cb4024cbfbc228010291 100644
--- a/3rdparty/Sabre/DAV/Locks/Backend/Abstract.php
+++ b/3rdparty/Sabre/DAV/Locks/Backend/Abstract.php
@@ -4,45 +4,45 @@
  * The Lock manager allows you to handle all file-locks centrally.
  *
  * This is an alternative approach to doing this on a per-node basis
- * 
+ *
  * @package Sabre
  * @subpackage DAV
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
- * @author Evert Pot (http://www.rooftopsolutions.nl/) 
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
  */
 abstract class Sabre_DAV_Locks_Backend_Abstract {
 
     /**
-     * Returns a list of Sabre_DAV_Locks_LockInfo objects  
-     * 
+     * Returns a list of Sabre_DAV_Locks_LockInfo objects
+     *
      * This method should return all the locks for a particular uri, including
      * locks that might be set on a parent uri.
      *
      * If returnChildLocks is set to true, this method should also look for
      * any locks in the subtree of the uri for locks.
      *
-     * @param string $uri 
+     * @param string $uri
      * @param bool $returnChildLocks
-     * @return array 
+     * @return array
      */
     abstract function getLocks($uri, $returnChildLocks);
 
     /**
-     * Locks a uri 
-     * 
-     * @param string $uri 
-     * @param Sabre_DAV_Locks_LockInfo $lockInfo 
-     * @return bool 
+     * Locks a uri
+     *
+     * @param string $uri
+     * @param Sabre_DAV_Locks_LockInfo $lockInfo
+     * @return bool
      */
     abstract function lock($uri,Sabre_DAV_Locks_LockInfo $lockInfo);
 
     /**
-     * Removes a lock from a uri 
-     * 
-     * @param string $uri 
-     * @param Sabre_DAV_Locks_LockInfo $lockInfo 
-     * @return bool 
+     * Removes a lock from a uri
+     *
+     * @param string $uri
+     * @param Sabre_DAV_Locks_LockInfo $lockInfo
+     * @return bool
      */
     abstract function unlock($uri,Sabre_DAV_Locks_LockInfo $lockInfo);
 
diff --git a/3rdparty/Sabre/DAV/Locks/Backend/FS.php b/3rdparty/Sabre/DAV/Locks/Backend/FS.php
index 8653f55b1c6f9a116733392332975ff7c5a97e48..02cab87fc829e024aace719ba83c8498a5d97e0e 100644
--- a/3rdparty/Sabre/DAV/Locks/Backend/FS.php
+++ b/3rdparty/Sabre/DAV/Locks/Backend/FS.php
@@ -1,28 +1,30 @@
 <?php
 
 /**
- * The Lock manager allows you to handle all file-locks centrally.
+ * This Lock Backend stores all its data in the filesystem in separate file per
+ * node.
  *
- * This Lock Manager is now deprecated. It has a bug that allows parent 
- * collections to be deletes when children deeper in the tree are locked. 
+ * This Lock Manager is now deprecated. It has a bug that allows parent
+ * collections to be deletes when children deeper in the tree are locked.
+ *
+ * This also means that using this backend means you will not pass the Neon
+ * Litmus test.
  *
  * You are recommended to use either the PDO or the File backend instead.
  *
- * This Lock Manager stores all its data in the filesystem.
- * 
  * @package Sabre
  * @subpackage DAV
  * @deprecated
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
- * @author Evert Pot (http://www.rooftopsolutions.nl/) 
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
  */
 class Sabre_DAV_Locks_Backend_FS extends Sabre_DAV_Locks_Backend_Abstract {
 
     /**
-     * The default data directory 
-     * 
-     * @var string 
+     * The default data directory
+     *
+     * @var string
      */
     private $dataDir;
 
@@ -40,17 +42,17 @@ class Sabre_DAV_Locks_Backend_FS extends Sabre_DAV_Locks_Backend_Abstract {
 
 
     /**
-     * Returns a list of Sabre_DAV_Locks_LockInfo objects  
-     * 
+     * Returns a list of Sabre_DAV_Locks_LockInfo objects
+     *
      * This method should return all the locks for a particular uri, including
      * locks that might be set on a parent uri.
      *
      * If returnChildLocks is set to true, this method should also look for
      * any locks in the subtree of the uri for locks.
      *
-     * @param string $uri 
+     * @param string $uri
      * @param bool $returnChildLocks
-     * @return array 
+     * @return array
      */
     public function getLocks($uri, $returnChildLocks) {
 
@@ -59,15 +61,15 @@ class Sabre_DAV_Locks_Backend_FS extends Sabre_DAV_Locks_Backend_Abstract {
 
         foreach(explode('/',$uri) as $uriPart) {
 
-            // weird algorithm that can probably be improved, but we're traversing the path top down 
-            if ($currentPath) $currentPath.='/'; 
+            // weird algorithm that can probably be improved, but we're traversing the path top down
+            if ($currentPath) $currentPath.='/';
             $currentPath.=$uriPart;
 
             $uriLocks = $this->getData($currentPath);
 
             foreach($uriLocks as $uriLock) {
 
-                // Unless we're on the leaf of the uri-tree we should ingore locks with depth 0
+                // Unless we're on the leaf of the uri-tree we should ignore locks with depth 0
                 if($uri==$currentPath || $uriLock->depth!=0) {
                     $uriLock->uri = $currentPath;
                     $lockList[] = $uriLock;
@@ -79,18 +81,18 @@ class Sabre_DAV_Locks_Backend_FS extends Sabre_DAV_Locks_Backend_Abstract {
 
         // Checking if we can remove any of these locks
         foreach($lockList as $k=>$lock) {
-            if (time() > $lock->timeout + $lock->created) unset($lockList[$k]); 
+            if (time() > $lock->timeout + $lock->created) unset($lockList[$k]);
         }
         return $lockList;
 
     }
 
     /**
-     * Locks a uri 
-     * 
-     * @param string $uri 
-     * @param Sabre_DAV_Locks_LockInfo $lockInfo 
-     * @return bool 
+     * Locks a uri
+     *
+     * @param string $uri
+     * @param Sabre_DAV_Locks_LockInfo $lockInfo
+     * @return bool
      */
     public function lock($uri,Sabre_DAV_Locks_LockInfo $lockInfo) {
 
@@ -109,11 +111,11 @@ class Sabre_DAV_Locks_Backend_FS extends Sabre_DAV_Locks_Backend_Abstract {
     }
 
     /**
-     * Removes a lock from a uri 
-     * 
-     * @param string $uri 
-     * @param Sabre_DAV_Locks_LockInfo $lockInfo 
-     * @return bool 
+     * Removes a lock from a uri
+     *
+     * @param string $uri
+     * @param Sabre_DAV_Locks_LockInfo $lockInfo
+     * @return bool
      */
     public function unlock($uri,Sabre_DAV_Locks_LockInfo $lockInfo) {
 
@@ -136,7 +138,7 @@ class Sabre_DAV_Locks_Backend_FS extends Sabre_DAV_Locks_Backend_Abstract {
      * Returns the stored data for a uri
      *
      * @param string $uri
-     * @return array 
+     * @return array
      */
     protected function getData($uri) {
 
@@ -167,7 +169,7 @@ class Sabre_DAV_Locks_Backend_FS extends Sabre_DAV_Locks_Backend_Abstract {
      * Updates the lock information
      *
      * @param string $uri
-     * @param array $newData 
+     * @param array $newData
      * @return void
      */
     protected function putData($uri,array $newData) {
diff --git a/3rdparty/Sabre/DAV/Locks/Backend/File.php b/3rdparty/Sabre/DAV/Locks/Backend/File.php
index f65b20c4306728f93cd9c00968db46d6008f816c..c33f963514bef4e4ca66546479d03d9a72240e77 100644
--- a/3rdparty/Sabre/DAV/Locks/Backend/File.php
+++ b/3rdparty/Sabre/DAV/Locks/Backend/File.php
@@ -3,30 +3,30 @@
 /**
  * The Lock manager allows you to handle all file-locks centrally.
  *
- * This Lock Manager stores all its data in a single file. 
+ * This Lock Manager stores all its data in a single file.
  *
  * Note that this is not nearly as robust as a database, you are encouraged
  * to use the PDO backend instead.
  *
  * @package Sabre
  * @subpackage DAV
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
- * @author Evert Pot (http://www.rooftopsolutions.nl/) 
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
  */
 class Sabre_DAV_Locks_Backend_File extends Sabre_DAV_Locks_Backend_Abstract {
 
     /**
      * The storage file
-     * 
-     * @var string 
+     *
+     * @var string
      */
     private $locksFile;
 
     /**
      * Constructor
      *
-     * @param string $locksFile path to file 
+     * @param string $locksFile path to file
      */
     public function __construct($locksFile) {
 
@@ -35,24 +35,24 @@ class Sabre_DAV_Locks_Backend_File extends Sabre_DAV_Locks_Backend_Abstract {
     }
 
     /**
-     * Returns a list of Sabre_DAV_Locks_LockInfo objects  
-     * 
+     * Returns a list of Sabre_DAV_Locks_LockInfo objects
+     *
      * This method should return all the locks for a particular uri, including
      * locks that might be set on a parent uri.
      *
      * If returnChildLocks is set to true, this method should also look for
      * any locks in the subtree of the uri for locks.
      *
-     * @param string $uri 
+     * @param string $uri
      * @param bool $returnChildLocks
-     * @return array 
+     * @return array
      */
     public function getLocks($uri, $returnChildLocks) {
 
         $newLocks = array();
-        $currentPath = '';
 
         $locks = $this->getData();
+
         foreach($locks as $lock) {
 
             if ($lock->uri === $uri ||
@@ -70,29 +70,35 @@ class Sabre_DAV_Locks_Backend_File extends Sabre_DAV_Locks_Backend_Abstract {
 
         // Checking if we can remove any of these locks
         foreach($newLocks as $k=>$lock) {
-            if (time() > $lock->timeout + $lock->created) unset($newLocks[$k]); 
+            if (time() > $lock->timeout + $lock->created) unset($newLocks[$k]);
         }
         return $newLocks;
 
     }
 
     /**
-     * Locks a uri 
-     * 
-     * @param string $uri 
-     * @param Sabre_DAV_Locks_LockInfo $lockInfo 
-     * @return bool 
+     * Locks a uri
+     *
+     * @param string $uri
+     * @param Sabre_DAV_Locks_LockInfo $lockInfo
+     * @return bool
      */
-    public function lock($uri,Sabre_DAV_Locks_LockInfo $lockInfo) {
+    public function lock($uri, Sabre_DAV_Locks_LockInfo $lockInfo) {
 
         // We're making the lock timeout 30 minutes
         $lockInfo->timeout = 1800;
         $lockInfo->created = time();
         $lockInfo->uri = $uri;
 
-        $locks = $this->getLocks($uri,false);
+        $locks = $this->getData();
+
         foreach($locks as $k=>$lock) {
-            if ($lock->token == $lockInfo->token) unset($locks[$k]);
+            if (
+                ($lock->token == $lockInfo->token) ||
+                (time() > $lock->timeout + $lock->created)
+            ) {
+                unset($locks[$k]);
+            }
         }
         $locks[] = $lockInfo;
         $this->putData($locks);
@@ -101,15 +107,15 @@ class Sabre_DAV_Locks_Backend_File extends Sabre_DAV_Locks_Backend_Abstract {
     }
 
     /**
-     * Removes a lock from a uri 
-     * 
-     * @param string $uri 
-     * @param Sabre_DAV_Locks_LockInfo $lockInfo 
-     * @return bool 
+     * Removes a lock from a uri
+     *
+     * @param string $uri
+     * @param Sabre_DAV_Locks_LockInfo $lockInfo
+     * @return bool
      */
-    public function unlock($uri,Sabre_DAV_Locks_LockInfo $lockInfo) {
+    public function unlock($uri, Sabre_DAV_Locks_LockInfo $lockInfo) {
 
-        $locks = $this->getLocks($uri,false);
+        $locks = $this->getData();
         foreach($locks as $k=>$lock) {
 
             if ($lock->token == $lockInfo->token) {
@@ -127,7 +133,7 @@ class Sabre_DAV_Locks_Backend_File extends Sabre_DAV_Locks_Backend_Abstract {
     /**
      * Loads the lockdata from the filesystem.
      *
-     * @return array 
+     * @return array
      */
     protected function getData() {
 
@@ -153,7 +159,7 @@ class Sabre_DAV_Locks_Backend_File extends Sabre_DAV_Locks_Backend_Abstract {
     /**
      * Saves the lockdata
      *
-     * @param array $newData 
+     * @param array $newData
      * @return void
      */
     protected function putData(array $newData) {
diff --git a/3rdparty/Sabre/DAV/Locks/Backend/PDO.php b/3rdparty/Sabre/DAV/Locks/Backend/PDO.php
index c3923af19d3ea6d5eae4235711b175ef24672d71..acce80638ecb63c508c096a8e95d7b34d124a96d 100644
--- a/3rdparty/Sabre/DAV/Locks/Backend/PDO.php
+++ b/3rdparty/Sabre/DAV/Locks/Backend/PDO.php
@@ -5,34 +5,34 @@
  *
  * This Lock Manager stores all its data in a database. You must pass a PDO
  * connection object in the constructor.
- * 
+ *
  * @package Sabre
  * @subpackage DAV
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
- * @author Evert Pot (http://www.rooftopsolutions.nl/) 
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
  */
 class Sabre_DAV_Locks_Backend_PDO extends Sabre_DAV_Locks_Backend_Abstract {
 
     /**
-     * The PDO connection object 
-     * 
-     * @var pdo 
+     * The PDO connection object
+     *
+     * @var pdo
      */
     private $pdo;
 
     /**
-     * The PDO tablename this backend uses. 
-     * 
+     * The PDO tablename this backend uses.
+     *
      * @var string
      */
     protected $tableName;
 
     /**
-     * Constructor 
-     * 
+     * Constructor
+     *
      * @param PDO $pdo
-     * @param string $tableName 
+     * @param string $tableName
      */
     public function __construct(PDO $pdo, $tableName = 'locks') {
 
@@ -42,24 +42,24 @@ class Sabre_DAV_Locks_Backend_PDO extends Sabre_DAV_Locks_Backend_Abstract {
     }
 
     /**
-     * Returns a list of Sabre_DAV_Locks_LockInfo objects  
-     * 
+     * Returns a list of Sabre_DAV_Locks_LockInfo objects
+     *
      * This method should return all the locks for a particular uri, including
      * locks that might be set on a parent uri.
      *
      * If returnChildLocks is set to true, this method should also look for
      * any locks in the subtree of the uri for locks.
      *
-     * @param string $uri 
+     * @param string $uri
      * @param bool $returnChildLocks
-     * @return array 
+     * @return array
      */
     public function getLocks($uri, $returnChildLocks) {
 
-        // NOTE: the following 10 lines or so could be easily replaced by 
-        // pure sql. MySQL's non-standard string concatination prevents us
+        // NOTE: the following 10 lines or so could be easily replaced by
+        // pure sql. MySQL's non-standard string concatenation prevents us
         // from doing this though.
-        $query = 'SELECT owner, token, timeout, created, scope, depth, uri FROM `'.$this->tableName.'` WHERE ((created + timeout) > CAST(? AS UNSIGNED INTEGER)) AND ((uri = ?)';
+        $query = 'SELECT owner, token, timeout, created, scope, depth, uri FROM '.$this->tableName.' WHERE ((created + timeout) > CAST(? AS UNSIGNED INTEGER)) AND ((uri = ?)';
         $params = array(time(),$uri);
 
         // We need to check locks for every part in the uri.
@@ -112,11 +112,11 @@ class Sabre_DAV_Locks_Backend_PDO extends Sabre_DAV_Locks_Backend_Abstract {
     }
 
     /**
-     * Locks a uri 
-     * 
-     * @param string $uri 
-     * @param Sabre_DAV_Locks_LockInfo $lockInfo 
-     * @return bool 
+     * Locks a uri
+     *
+     * @param string $uri
+     * @param Sabre_DAV_Locks_LockInfo $lockInfo
+     * @return bool
      */
     public function lock($uri,Sabre_DAV_Locks_LockInfo $lockInfo) {
 
@@ -127,15 +127,15 @@ class Sabre_DAV_Locks_Backend_PDO extends Sabre_DAV_Locks_Backend_Abstract {
 
         $locks = $this->getLocks($uri,false);
         $exists = false;
-        foreach($locks as $k=>$lock) {
+        foreach($locks as $lock) {
             if ($lock->token == $lockInfo->token) $exists = true;
         }
-        
+
         if ($exists) {
-            $stmt = $this->pdo->prepare('UPDATE `'.$this->tableName.'` SET owner = ?, timeout = ?, scope = ?, depth = ?, uri = ?, created = ? WHERE token = ?');
+            $stmt = $this->pdo->prepare('UPDATE '.$this->tableName.' SET owner = ?, timeout = ?, scope = ?, depth = ?, uri = ?, created = ? WHERE token = ?');
             $stmt->execute(array($lockInfo->owner,$lockInfo->timeout,$lockInfo->scope,$lockInfo->depth,$uri,$lockInfo->created,$lockInfo->token));
         } else {
-            $stmt = $this->pdo->prepare('INSERT INTO `'.$this->tableName.'` (owner,timeout,scope,depth,uri,created,token) VALUES (?,?,?,?,?,?,?)');
+            $stmt = $this->pdo->prepare('INSERT INTO '.$this->tableName.' (owner,timeout,scope,depth,uri,created,token) VALUES (?,?,?,?,?,?,?)');
             $stmt->execute(array($lockInfo->owner,$lockInfo->timeout,$lockInfo->scope,$lockInfo->depth,$uri,$lockInfo->created,$lockInfo->token));
         }
 
@@ -146,15 +146,15 @@ class Sabre_DAV_Locks_Backend_PDO extends Sabre_DAV_Locks_Backend_Abstract {
 
 
     /**
-     * Removes a lock from a uri 
-     * 
-     * @param string $uri 
-     * @param Sabre_DAV_Locks_LockInfo $lockInfo 
-     * @return bool 
+     * Removes a lock from a uri
+     *
+     * @param string $uri
+     * @param Sabre_DAV_Locks_LockInfo $lockInfo
+     * @return bool
      */
     public function unlock($uri,Sabre_DAV_Locks_LockInfo $lockInfo) {
 
-        $stmt = $this->pdo->prepare('DELETE FROM `'.$this->tableName.'` WHERE uri = ? AND token = ?');
+        $stmt = $this->pdo->prepare('DELETE FROM '.$this->tableName.' WHERE uri = ? AND token = ?');
         $stmt->execute(array($uri,$lockInfo->token));
 
         return $stmt->rowCount()===1;
diff --git a/3rdparty/Sabre/DAV/Locks/LockInfo.php b/3rdparty/Sabre/DAV/Locks/LockInfo.php
index 6a064466f4015303ca802b44b05d2617e33ce0ad..9df014a4281a8b192f59f85c1d50d27793fb6e3a 100644
--- a/3rdparty/Sabre/DAV/Locks/LockInfo.php
+++ b/3rdparty/Sabre/DAV/Locks/LockInfo.php
@@ -5,11 +5,11 @@
  *
  * An object of the LockInfo class holds all the information relevant to a
  * single lock.
- * 
+ *
  * @package Sabre
  * @subpackage DAV
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
- * @author Evert Pot (http://www.rooftopsolutions.nl/) 
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
  */
 class Sabre_DAV_Locks_LockInfo {
@@ -30,37 +30,37 @@ class Sabre_DAV_Locks_LockInfo {
     const TIMEOUT_INFINITE = -1;
 
     /**
-     * The owner of the lock 
-     * 
-     * @var string 
+     * The owner of the lock
+     *
+     * @var string
      */
     public $owner;
 
     /**
-     * The locktoken 
-     * 
-     * @var string 
+     * The locktoken
+     *
+     * @var string
      */
     public $token;
 
     /**
-     * How long till the lock is expiring 
-     * 
-     * @var int 
+     * How long till the lock is expiring
+     *
+     * @var int
      */
     public $timeout;
 
     /**
-     * UNIX Timestamp of when this lock was created 
-     * 
-     * @var int 
+     * UNIX Timestamp of when this lock was created
+     *
+     * @var int
      */
     public $created;
 
     /**
-     * Exclusive or shared lock 
-     * 
-     * @var int 
+     * Exclusive or shared lock
+     *
+     * @var int
      */
     public $scope = self::EXCLUSIVE;
 
@@ -72,7 +72,7 @@ class Sabre_DAV_Locks_LockInfo {
     /**
      * The uri this lock locks
      *
-     * TODO: This value is not always set 
+     * TODO: This value is not always set
      * @var mixed
      */
     public $uri;
diff --git a/3rdparty/Sabre/DAV/Locks/Plugin.php b/3rdparty/Sabre/DAV/Locks/Plugin.php
index 461e2847e0ae8e562827294eb4d550b19b3b4530..fd956950b8af22d4260c08e5c5130717a9988f5e 100644
--- a/3rdparty/Sabre/DAV/Locks/Plugin.php
+++ b/3rdparty/Sabre/DAV/Locks/Plugin.php
@@ -9,38 +9,37 @@
  * $lockBackend = new Sabre_DAV_Locks_Backend_File('./mylockdb');
  * $lockPlugin = new Sabre_DAV_Locks_Plugin($lockBackend);
  * $server->addPlugin($lockPlugin);
- * 
+ *
  * @package Sabre
  * @subpackage DAV
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
- * @author Evert Pot (http://www.rooftopsolutions.nl/) 
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
  */
 class Sabre_DAV_Locks_Plugin extends Sabre_DAV_ServerPlugin {
 
     /**
-     * locksBackend 
-     * 
-     * @var Sabre_DAV_Locks_Backend_Abstract 
+     * locksBackend
+     *
+     * @var Sabre_DAV_Locks_Backend_Abstract
      */
     private $locksBackend;
 
     /**
      * server
-     * 
-     * @var Sabre_DAV_Server 
+     *
+     * @var Sabre_DAV_Server
      */
     private $server;
 
     /**
-     * __construct 
-     * 
-     * @param Sabre_DAV_Locks_Backend_Abstract $locksBackend 
-     * @return void
+     * __construct
+     *
+     * @param Sabre_DAV_Locks_Backend_Abstract $locksBackend
      */
     public function __construct(Sabre_DAV_Locks_Backend_Abstract $locksBackend = null) {
 
-        $this->locksBackend = $locksBackend;        
+        $this->locksBackend = $locksBackend;
 
     }
 
@@ -48,8 +47,8 @@ class Sabre_DAV_Locks_Plugin extends Sabre_DAV_ServerPlugin {
      * Initializes the plugin
      *
      * This method is automatically called by the Server class after addPlugin.
-     * 
-     * @param Sabre_DAV_Server $server 
+     *
+     * @param Sabre_DAV_Server $server
      * @return void
      */
     public function initialize(Sabre_DAV_Server $server) {
@@ -63,11 +62,11 @@ class Sabre_DAV_Locks_Plugin extends Sabre_DAV_ServerPlugin {
 
     /**
      * Returns a plugin name.
-     * 
+     *
      * Using this name other plugins will be able to access other plugins
-     * using Sabre_DAV_Server::getPlugin 
-     * 
-     * @return string 
+     * using Sabre_DAV_Server::getPlugin
+     *
+     * @return string
      */
     public function getPluginName() {
 
@@ -76,20 +75,21 @@ class Sabre_DAV_Locks_Plugin extends Sabre_DAV_ServerPlugin {
     }
 
     /**
-     * This method is called by the Server if the user used an HTTP method 
+     * This method is called by the Server if the user used an HTTP method
      * the server didn't recognize.
      *
      * This plugin intercepts the LOCK and UNLOCK methods.
-     * 
-     * @param string $method 
-     * @return bool 
+     *
+     * @param string $method
+     * @param string $uri
+     * @return bool
      */
     public function unknownMethod($method, $uri) {
 
-        switch($method) { 
+        switch($method) {
 
-            case 'LOCK'   : $this->httpLock($uri); return false; 
-            case 'UNLOCK' : $this->httpUnlock($uri); return false; 
+            case 'LOCK'   : $this->httpLock($uri); return false;
+            case 'UNLOCK' : $this->httpUnlock($uri); return false;
 
         }
 
@@ -98,26 +98,20 @@ class Sabre_DAV_Locks_Plugin extends Sabre_DAV_ServerPlugin {
     /**
      * This method is called after most properties have been found
      * it allows us to add in any Lock-related properties
-     * 
-     * @param string $path 
-     * @param array $properties 
-     * @return bool 
+     *
+     * @param string $path
+     * @param array $newProperties
+     * @return bool
      */
-    public function afterGetProperties($path,&$newProperties) {
+    public function afterGetProperties($path, &$newProperties) {
 
         foreach($newProperties[404] as $propName=>$discard) {
 
-            $node = null;
-
             switch($propName) {
 
                 case '{DAV:}supportedlock' :
                     $val = false;
                     if ($this->locksBackend) $val = true;
-                    else {
-                        if (!$node) $node = $this->server->tree->getNodeForPath($path);
-                        if ($node instanceof Sabre_DAV_ILockable) $val = true;
-                    }
                     $newProperties[200][$propName] = new Sabre_DAV_Property_SupportedLock($val);
                     unset($newProperties[404][$propName]);
                     break;
@@ -141,10 +135,10 @@ class Sabre_DAV_Locks_Plugin extends Sabre_DAV_ServerPlugin {
      * handled.
      *
      * This plugin uses that feature to intercept access to locked resources.
-     * 
+     *
      * @param string $method
      * @param string $uri
-     * @return bool 
+     * @return bool
      */
     public function beforeMethod($method, $uri) {
 
@@ -187,18 +181,17 @@ class Sabre_DAV_Locks_Plugin extends Sabre_DAV_ServerPlugin {
      * Use this method to tell the server this plugin defines additional
      * HTTP methods.
      *
-     * This method is passed a uri. It should only return HTTP methods that are 
+     * This method is passed a uri. It should only return HTTP methods that are
      * available for the specified uri.
      *
      * @param string $uri
-     * @return array 
+     * @return array
      */
     public function getHTTPMethods($uri) {
 
-        if ($this->locksBackend ||
-            $this->server->tree->getNodeForPath($uri) instanceof Sabre_DAV_ILocks) {
+        if ($this->locksBackend)
             return array('LOCK','UNLOCK');
-        }
+
         return array();
 
     }
@@ -208,8 +201,8 @@ class Sabre_DAV_Locks_Plugin extends Sabre_DAV_ServerPlugin {
      *
      * In this case this is only the number 2. The 2 in the Dav: header
      * indicates the server supports locks.
-     * 
-     * @return array 
+     *
+     * @return array
      */
     public function getFeatures() {
 
@@ -218,49 +211,23 @@ class Sabre_DAV_Locks_Plugin extends Sabre_DAV_ServerPlugin {
     }
 
     /**
-     * Returns all lock information on a particular uri 
-     * 
+     * Returns all lock information on a particular uri
+     *
      * This function should return an array with Sabre_DAV_Locks_LockInfo objects. If there are no locks on a file, return an empty array.
      *
-     * Additionally there is also the possibility of locks on parent nodes, so we'll need to traverse every part of the tree 
+     * Additionally there is also the possibility of locks on parent nodes, so we'll need to traverse every part of the tree
      * If the $returnChildLocks argument is set to true, we'll also traverse all the children of the object
      * for any possible locks and return those as well.
      *
-     * @param string $uri 
+     * @param string $uri
      * @param bool $returnChildLocks
-     * @return array 
+     * @return array
      */
     public function getLocks($uri, $returnChildLocks = false) {
 
         $lockList = array();
-        $currentPath = '';
-        foreach(explode('/',$uri) as $uriPart) {
 
-            $uriLocks = array();
-            if ($currentPath) $currentPath.='/'; 
-            $currentPath.=$uriPart;
-
-            try {
-
-                $node = $this->server->tree->getNodeForPath($currentPath);
-                if ($node instanceof Sabre_DAV_ILockable) $uriLocks = $node->getLocks();
-
-            } catch (Sabre_DAV_Exception_FileNotFound $e){
-                // In case the node didn't exist, this could be a lock-null request
-            }
-
-            foreach($uriLocks as $uriLock) {
-
-                // Unless we're on the leaf of the uri-tree we should ignore locks with depth 0
-                if($uri==$currentPath || $uriLock->depth!=0) {
-                    $uriLock->uri = $currentPath;
-                    $lockList[] = $uriLock;
-                }
-
-            }
-
-        }
-        if ($this->locksBackend) 
+        if ($this->locksBackend)
             $lockList = array_merge($lockList,$this->locksBackend->getLocks($uri, $returnChildLocks));
 
         return $lockList;
@@ -271,13 +238,13 @@ class Sabre_DAV_Locks_Plugin extends Sabre_DAV_ServerPlugin {
      * Locks an uri
      *
      * The WebDAV lock request can be operated to either create a new lock on a file, or to refresh an existing lock
-     * If a new lock is created, a full XML body should be supplied, containing information about the lock such as the type 
+     * If a new lock is created, a full XML body should be supplied, containing information about the lock such as the type
      * of lock (shared or exclusive) and the owner of the lock
      *
      * If a lock is to be refreshed, no body should be supplied and there should be a valid If header containing the lock
      *
-     * Additionally, a lock can be requested for a non-existant file. In these case we're obligated to create an empty file as per RFC4918:S7.3
-     * 
+     * Additionally, a lock can be requested for a non-existent file. In these case we're obligated to create an empty file as per RFC4918:S7.3
+     *
      * @param string $uri
      * @return void
      */
@@ -297,7 +264,7 @@ class Sabre_DAV_Locks_Plugin extends Sabre_DAV_ServerPlugin {
         if ($body = $this->server->httpRequest->getBody(true)) {
             // This is a new lock request
             $lockInfo = $this->parseLockRequest($body);
-            $lockInfo->depth = $this->server->getHTTPDepth(); 
+            $lockInfo->depth = $this->server->getHTTPDepth();
             $lockInfo->uri = $uri;
             if($lastLock && $lockInfo->scope != Sabre_DAV_Locks_LockInfo::SHARED) throw new Sabre_DAV_Exception_ConflictingLock($lastLock);
 
@@ -306,11 +273,11 @@ class Sabre_DAV_Locks_Plugin extends Sabre_DAV_ServerPlugin {
             // This must have been a lock refresh
             $lockInfo = $lastLock;
 
-            // The resource could have been locked through another uri. 
+            // The resource could have been locked through another uri.
             if ($uri!=$lockInfo->uri) $uri = $lockInfo->uri;
 
         } else {
-            
+
             // There was neither a lock refresh nor a new lock request
             throw new Sabre_DAV_Exception_BadRequest('An xml body is required for lock requests');
 
@@ -322,16 +289,16 @@ class Sabre_DAV_Locks_Plugin extends Sabre_DAV_ServerPlugin {
 
         // If we got this far.. we should go check if this node actually exists. If this is not the case, we need to create it first
         try {
-            $node = $this->server->tree->getNodeForPath($uri);
-            
+            $this->server->tree->getNodeForPath($uri);
+
             // We need to call the beforeWriteContent event for RFC3744
             $this->server->broadcastEvent('beforeWriteContent',array($uri));
 
-        } catch (Sabre_DAV_Exception_FileNotFound $e) {
-            
+        } catch (Sabre_DAV_Exception_NotFound $e) {
+
             // It didn't, lets create it
-            $this->server->createFile($uri,fopen('php://memory','r')); 
-            $newFile = true; 
+            $this->server->createFile($uri,fopen('php://memory','r'));
+            $newFile = true;
 
         }
 
@@ -362,7 +329,7 @@ class Sabre_DAV_Locks_Plugin extends Sabre_DAV_ServerPlugin {
 
         $locks = $this->getLocks($uri);
 
-        // Windows sometimes forgets to include < and > in the Lock-Token 
+        // Windows sometimes forgets to include < and > in the Lock-Token
         // header
         if ($lockToken[0]!=='<') $lockToken = '<' . $lockToken . '>';
 
@@ -370,7 +337,6 @@ class Sabre_DAV_Locks_Plugin extends Sabre_DAV_ServerPlugin {
 
             if ('<opaquelocktoken:' . $lock->token . '>' == $lockToken) {
 
-                $this->server->broadcastEvent('beforeUnlock',array($uri, $lock));
                 $this->unlockNode($uri,$lock);
                 $this->server->httpResponse->setHeader('Content-Length','0');
                 $this->server->httpResponse->sendStatus(204);
@@ -390,21 +356,15 @@ class Sabre_DAV_Locks_Plugin extends Sabre_DAV_ServerPlugin {
      *
      * All the locking information is supplied in the lockInfo object. The object has a suggested timeout, but this can be safely ignored
      * It is important that if the existing timeout is ignored, the property is overwritten, as this needs to be sent back to the client
-     * 
-     * @param string $uri 
-     * @param Sabre_DAV_Locks_LockInfo $lockInfo 
-     * @return void
+     *
+     * @param string $uri
+     * @param Sabre_DAV_Locks_LockInfo $lockInfo
+     * @return bool
      */
     public function lockNode($uri,Sabre_DAV_Locks_LockInfo $lockInfo) {
 
         if (!$this->server->broadcastEvent('beforeLock',array($uri,$lockInfo))) return;
 
-        try {
-            $node = $this->server->tree->getNodeForPath($uri);
-            if ($node instanceof Sabre_DAV_ILockable) return $node->lock($lockInfo);
-        } catch (Sabre_DAV_Exception_FileNotFound $e) {
-            // In case the node didn't exist, this could be a lock-null request
-        }
         if ($this->locksBackend) return $this->locksBackend->lock($uri,$lockInfo);
         throw new Sabre_DAV_Exception_MethodNotAllowed('Locking support is not enabled for this resource. No Locking backend was found so if you didn\'t expect this error, please check your configuration.');
 
@@ -414,29 +374,22 @@ class Sabre_DAV_Locks_Plugin extends Sabre_DAV_ServerPlugin {
      * Unlocks a uri
      *
      * This method removes a lock from a uri. It is assumed all the supplied information is correct and verified
-     * 
-     * @param string $uri 
-     * @param Sabre_DAV_Locks_LockInfo $lockInfo 
-     * @return void
+     *
+     * @param string $uri
+     * @param Sabre_DAV_Locks_LockInfo $lockInfo
+     * @return bool
      */
     public function unlockNode($uri,Sabre_DAV_Locks_LockInfo $lockInfo) {
 
         if (!$this->server->broadcastEvent('beforeUnlock',array($uri,$lockInfo))) return;
-        try {
-            $node = $this->server->tree->getNodeForPath($uri);
-            if ($node instanceof Sabre_DAV_ILockable) return $node->unlock($lockInfo);
-        } catch (Sabre_DAV_Exception_FileNotFound $e) {
-            // In case the node didn't exist, this could be a lock-null request
-        }
-
         if ($this->locksBackend) return $this->locksBackend->unlock($uri,$lockInfo);
 
     }
 
 
     /**
-     * Returns the contents of the HTTP Timeout header. 
-     * 
+     * Returns the contents of the HTTP Timeout header.
+     *
      * The method formats the header into an integer.
      *
      * @return int
@@ -444,7 +397,7 @@ class Sabre_DAV_Locks_Plugin extends Sabre_DAV_ServerPlugin {
     public function getTimeoutHeader() {
 
         $header = $this->server->httpRequest->getHeader('Timeout');
-        
+
         if ($header) {
 
             if (stripos($header,'second-')===0) $header = (int)(substr($header,7));
@@ -462,16 +415,16 @@ class Sabre_DAV_Locks_Plugin extends Sabre_DAV_ServerPlugin {
     }
 
     /**
-     * Generates the response for successfull LOCK requests 
-     * 
-     * @param Sabre_DAV_Locks_LockInfo $lockInfo 
-     * @return string 
+     * Generates the response for successful LOCK requests
+     *
+     * @param Sabre_DAV_Locks_LockInfo $lockInfo
+     * @return string
      */
     protected function generateLockResponse(Sabre_DAV_Locks_LockInfo $lockInfo) {
 
         $dom = new DOMDocument('1.0','utf-8');
         $dom->formatOutput = true;
-        
+
         $prop = $dom->createElementNS('DAV:','d:prop');
         $dom->appendChild($prop);
 
@@ -484,10 +437,10 @@ class Sabre_DAV_Locks_Plugin extends Sabre_DAV_ServerPlugin {
         return $dom->saveXML();
 
     }
-    
+
     /**
      * validateLock should be called when a write operation is about to happen
-     * It will check if the requested url is locked, and see if the correct lock tokens are passed 
+     * It will check if the requested url is locked, and see if the correct lock tokens are passed
      *
      * @param mixed $urls List of relevant urls. Can be an array, a string or nothing at all for the current request uri
      * @param mixed $lastLock This variable will be populated with the last checked lock object (Sabre_DAV_Locks_LockInfo)
@@ -511,13 +464,13 @@ class Sabre_DAV_Locks_Plugin extends Sabre_DAV_ServerPlugin {
 
             $locks = $this->getLocks($url, $checkChildLocks);
 
-            // If there were no conditions, but there were locks, we fail 
+            // If there were no conditions, but there were locks, we fail
             if (!$conditions && $locks) {
                 reset($locks);
                 $lastLock = current($locks);
                 return false;
             }
-          
+
             // If there were no locks or conditions, we go to the next url
             if (!$locks && !$conditions) continue;
 
@@ -542,7 +495,7 @@ class Sabre_DAV_Locks_Plugin extends Sabre_DAV_ServerPlugin {
                     // key 2 can contain an etag
                     if ($conditionToken[2]) {
 
-                        $uri = $conditionUri?$conditionUri:$this->server->getRequestUri(); 
+                        $uri = $conditionUri?$conditionUri:$this->server->getRequestUri();
                         $node = $this->server->tree->getNodeForPath($uri);
                         $etagValid = $node->getETag()==$conditionToken[2];
 
@@ -609,23 +562,23 @@ class Sabre_DAV_Locks_Plugin extends Sabre_DAV_ServerPlugin {
      * This method is created to extract information from the WebDAV HTTP 'If:' header
      *
      * The If header can be quite complex, and has a bunch of features. We're using a regex to extract all relevant information
-     * The function will return an array, containg structs with the following keys
+     * The function will return an array, containing structs with the following keys
      *
-     *   * uri   - the uri the condition applies to. If this is returned as an 
+     *   * uri   - the uri the condition applies to. If this is returned as an
      *     empty string, this implies it's referring to the request url.
-     *   * tokens - The lock token. another 2 dimensional array containg 2 elements (0 = true/false.. If this is a negative condition its set to false, 1 = the actual token)
+     *   * tokens - The lock token. another 2 dimensional array containing 2 elements (0 = true/false.. If this is a negative condition its set to false, 1 = the actual token)
      *   * etag - an etag, if supplied
-     * 
-     * @return void
+     *
+     * @return array
      */
     public function getIfConditions() {
 
-        $header = $this->server->httpRequest->getHeader('If'); 
+        $header = $this->server->httpRequest->getHeader('If');
         if (!$header) return array();
 
         $matches = array();
 
-        $regex = '/(?:\<(?P<uri>.*?)\>\s)?\((?P<not>Not\s)?(?:\<(?P<token>[^\>]*)\>)?(?:\s?)(?:\[(?P<etag>[^\]]*)\])?\)/im'; 
+        $regex = '/(?:\<(?P<uri>.*?)\>\s)?\((?P<not>Not\s)?(?:\<(?P<token>[^\>]*)\>)?(?:\s?)(?:\[(?P<etag>[^\]]*)\])?\)/im';
         preg_match_all($regex,$header,$matches,PREG_SET_ORDER);
 
         $conditions = array();
@@ -636,7 +589,7 @@ class Sabre_DAV_Locks_Plugin extends Sabre_DAV_ServerPlugin {
                 'uri'   => $match['uri'],
                 'tokens' => array(
                     array($match['not']?0:1,$match['token'],isset($match['etag'])?$match['etag']:'')
-                ),    
+                ),
             );
 
             if (!$condition['uri'] && count($conditions)) $conditions[count($conditions)-1]['tokens'][] = array(
@@ -655,9 +608,9 @@ class Sabre_DAV_Locks_Plugin extends Sabre_DAV_ServerPlugin {
     }
 
     /**
-     * Parses a webdav lock xml body, and returns a new Sabre_DAV_Locks_LockInfo object 
-     * 
-     * @param string $body 
+     * Parses a webdav lock xml body, and returns a new Sabre_DAV_Locks_LockInfo object
+     *
+     * @param string $body
      * @return Sabre_DAV_Locks_LockInfo
      */
     protected function parseLockRequest($body) {
diff --git a/3rdparty/Sabre/DAV/Mount/Plugin.php b/3rdparty/Sabre/DAV/Mount/Plugin.php
index f93a1aa25a1f00793e848d2fdb752ab092be785d..b37a90ae9939a1315e438a4bd55d5687e12cc28b 100644
--- a/3rdparty/Sabre/DAV/Mount/Plugin.php
+++ b/3rdparty/Sabre/DAV/Mount/Plugin.php
@@ -4,25 +4,25 @@
  * This plugin provides support for RFC4709: Mounting WebDAV servers
  *
  * Simply append ?mount to any collection to generate the davmount response.
- * 
+ *
  * @package Sabre
  * @subpackage DAV
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
- * @author Evert Pot (http://www.rooftopsolutions.nl/) 
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
  */
 class Sabre_DAV_Mount_Plugin extends Sabre_DAV_ServerPlugin {
 
     /**
-     * Reference to Server class 
-     * 
-     * @var Sabre_DAV_Server 
+     * Reference to Server class
+     *
+     * @var Sabre_DAV_Server
      */
     private $server;
 
     /**
-     * Initializes the plugin and registers event handles 
-     * 
-     * @param Sabre_DAV_Server $server 
+     * Initializes the plugin and registers event handles
+     *
+     * @param Sabre_DAV_Server $server
      * @return void
      */
     public function initialize(Sabre_DAV_Server $server) {
@@ -35,9 +35,10 @@ class Sabre_DAV_Mount_Plugin extends Sabre_DAV_ServerPlugin {
     /**
      * 'beforeMethod' event handles. This event handles intercepts GET requests ending
      * with ?mount
-     * 
-     * @param string $method 
-     * @return void
+     *
+     * @param string $method
+     * @param string $uri
+     * @return bool
      */
     public function beforeMethod($method, $uri) {
 
@@ -57,13 +58,13 @@ class Sabre_DAV_Mount_Plugin extends Sabre_DAV_ServerPlugin {
     }
 
     /**
-     * Generates the davmount response 
-     * 
-     * @param string $uri absolute uri 
+     * Generates the davmount response
+     *
+     * @param string $uri absolute uri
      * @return void
      */
     public function davMount($uri) {
-       
+
         $this->server->httpResponse->sendStatus(200);
         $this->server->httpResponse->setHeader('Content-Type','application/davmount+xml');
         ob_start();
diff --git a/3rdparty/Sabre/DAV/Node.php b/3rdparty/Sabre/DAV/Node.php
index 0510df5fdf28156bd1941cce78f1734992377308..070b7176afdf6ea09e47ba2c2084799028656d79 100644
--- a/3rdparty/Sabre/DAV/Node.php
+++ b/3rdparty/Sabre/DAV/Node.php
@@ -3,22 +3,22 @@
 /**
  * Node class
  *
- * This is a helper class, that should aid in getting nodes setup. 
- * 
+ * This is a helper class, that should aid in getting nodes setup.
+ *
  * @package Sabre
  * @subpackage DAV
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
- * @author Evert Pot (http://www.rooftopsolutions.nl/) 
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
  */
 abstract class Sabre_DAV_Node implements Sabre_DAV_INode {
 
     /**
-     * Returns the last modification time 
+     * Returns the last modification time
      *
      * In this case, it will simply return the current time
      *
-     * @return int 
+     * @return int
      */
     public function getLastModified() {
 
@@ -30,7 +30,7 @@ abstract class Sabre_DAV_Node implements Sabre_DAV_INode {
      * Deleted the current node
      *
      * @throws Sabre_DAV_Exception_Forbidden
-     * @return void 
+     * @return void
      */
     public function delete() {
 
@@ -40,7 +40,7 @@ abstract class Sabre_DAV_Node implements Sabre_DAV_INode {
 
     /**
      * Renames the node
-     * 
+     *
      * @throws Sabre_DAV_Exception_Forbidden
      * @param string $name The new name
      * @return void
diff --git a/3rdparty/Sabre/DAV/ObjectTree.php b/3rdparty/Sabre/DAV/ObjectTree.php
index f12a36837052c058d4a35e7ae30a0c48d4aeb13e..bce5146390026a417230243fc94be0299db93a6d 100644
--- a/3rdparty/Sabre/DAV/ObjectTree.php
+++ b/3rdparty/Sabre/DAV/ObjectTree.php
@@ -3,27 +3,27 @@
 /**
  * ObjectTree class
  *
- * This implementation of the Tree class makes use of the INode, IFile and ICollection API's 
- * 
+ * This implementation of the Tree class makes use of the INode, IFile and ICollection API's
+ *
  * @package Sabre
  * @subpackage DAV
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
- * @author Evert Pot (http://www.rooftopsolutions.nl/) 
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
  */
 class Sabre_DAV_ObjectTree extends Sabre_DAV_Tree {
 
     /**
-     * The root node 
-     * 
+     * The root node
+     *
      * @var Sabre_DAV_ICollection
      */
     protected $rootNode;
 
     /**
-     * This is the node cache. Accessed nodes are stored here 
-     * 
-     * @var array 
+     * This is the node cache. Accessed nodes are stored here
+     *
+     * @var array
      */
     protected $cache = array();
 
@@ -31,9 +31,8 @@ class Sabre_DAV_ObjectTree extends Sabre_DAV_Tree {
      * Creates the object
      *
      * This method expects the rootObject to be passed as a parameter
-     * 
-     * @param Sabre_DAV_ICollection $rootNode 
-     * @return void
+     *
+     * @param Sabre_DAV_ICollection $rootNode
      */
     public function __construct(Sabre_DAV_ICollection $rootNode) {
 
@@ -42,10 +41,10 @@ class Sabre_DAV_ObjectTree extends Sabre_DAV_Tree {
     }
 
     /**
-     * Returns the INode object for the requested path  
-     * 
-     * @param string $path 
-     * @return Sabre_DAV_INode 
+     * Returns the INode object for the requested path
+     *
+     * @param string $path
+     * @return Sabre_DAV_INode
      */
     public function getNodeForPath($path) {
 
@@ -54,17 +53,17 @@ class Sabre_DAV_ObjectTree extends Sabre_DAV_Tree {
 
         //if (!$path || $path=='.') return $this->rootNode;
         $currentNode = $this->rootNode;
-        $i=0;
-        // We're splitting up the path variable into folder/subfolder components and traverse to the correct node.. 
+
+        // We're splitting up the path variable into folder/subfolder components and traverse to the correct node..
         foreach(explode('/',$path) as $pathPart) {
 
             // If this part of the path is just a dot, it actually means we can skip it
             if ($pathPart=='.' || $pathPart=='') continue;
 
             if (!($currentNode instanceof Sabre_DAV_ICollection))
-                throw new Sabre_DAV_Exception_FileNotFound('Could not find node at path: ' . $path);
+                throw new Sabre_DAV_Exception_NotFound('Could not find node at path: ' . $path);
 
-            $currentNode = $currentNode->getChild($pathPart); 
+            $currentNode = $currentNode->getChild($pathPart);
 
         }
 
@@ -76,8 +75,8 @@ class Sabre_DAV_ObjectTree extends Sabre_DAV_Tree {
     /**
      * This function allows you to check if a node exists.
      *
-     * @param string $path 
-     * @return bool 
+     * @param string $path
+     * @return bool
      */
     public function nodeExists($path) {
 
@@ -92,7 +91,7 @@ class Sabre_DAV_ObjectTree extends Sabre_DAV_Tree {
             if (!$parentNode instanceof Sabre_DAV_ICollection) return false;
             return $parentNode->childExists($base);
 
-        } catch (Sabre_DAV_Exception_FileNotFound $e) {
+        } catch (Sabre_DAV_Exception_NotFound $e) {
 
             return false;
 
@@ -101,10 +100,10 @@ class Sabre_DAV_ObjectTree extends Sabre_DAV_Tree {
     }
 
     /**
-     * Returns a list of childnodes for a given path. 
-     * 
-     * @param string $path 
-     * @return array 
+     * Returns a list of childnodes for a given path.
+     *
+     * @param string $path
+     * @return array
      */
     public function getChildren($path) {
 
@@ -127,14 +126,14 @@ class Sabre_DAV_ObjectTree extends Sabre_DAV_Tree {
      *   * node creations
      *   * copy
      *   * move
-     *   * renaming nodes 
-     * 
+     *   * renaming nodes
+     *
      * If Tree classes implement a form of caching, this will allow
      * them to make sure caches will be expired.
-     * 
+     *
      * If a path is passed, it is assumed that the entire subtree is dirty
      *
-     * @param string $path 
+     * @param string $path
      * @return void
      */
     public function markDirty($path) {
@@ -145,7 +144,7 @@ class Sabre_DAV_ObjectTree extends Sabre_DAV_Tree {
         foreach($this->cache as $nodePath=>$node) {
             if ($nodePath == $path || strpos($nodePath,$path.'/')===0)
                 unset($this->cache[$nodePath]);
-            
+
         }
 
     }
diff --git a/3rdparty/Sabre/DAV/Property.php b/3rdparty/Sabre/DAV/Property.php
index 577535b012769b418a41f58487dd8c1718551a2e..1cfada3236c5500a64e4c343d0437db7f22dbb76 100644
--- a/3rdparty/Sabre/DAV/Property.php
+++ b/3rdparty/Sabre/DAV/Property.php
@@ -4,16 +4,16 @@
  * Abstract property class
  *
  * Extend this class to create custom complex properties
- * 
+ *
  * @package Sabre
  * @subpackage DAV
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
  * @author Evert Pot (http://www.rooftopsolutions.nl/)
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
  */
 abstract class Sabre_DAV_Property {
 
-    abstract function serialize(Sabre_DAV_Server $server, DOMElement $prop); 
+    abstract function serialize(Sabre_DAV_Server $server, DOMElement $prop);
 
     static function unserialize(DOMElement $prop) {
 
diff --git a/3rdparty/Sabre/DAV/Property/GetLastModified.php b/3rdparty/Sabre/DAV/Property/GetLastModified.php
index 4a81262997148025ecc68f28d55c243c8f6e0f1a..bd63f573140a72780f215fd0af8d42f509c571b3 100644
--- a/3rdparty/Sabre/DAV/Property/GetLastModified.php
+++ b/3rdparty/Sabre/DAV/Property/GetLastModified.php
@@ -2,33 +2,32 @@
 
 /**
  * This property represents the {DAV:}getlastmodified property.
- * 
+ *
  * Although this is normally a simple property, windows requires us to add
  * some new attributes.
  *
- * This class uses unix timestamps internally, and converts them to RFC 1123 times for 
+ * This class uses unix timestamps internally, and converts them to RFC 1123 times for
  * serialization
  *
  * @package Sabre
  * @subpackage DAV
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
- * @author Evert Pot (http://www.rooftopsolutions.nl/) 
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
  */
 class Sabre_DAV_Property_GetLastModified extends Sabre_DAV_Property {
 
     /**
-     * time 
-     * 
-     * @var int 
+     * time
+     *
+     * @var int
      */
     public $time;
 
     /**
-     * __construct 
-     * 
-     * @param int|DateTime $time 
-     * @return void
+     * __construct
+     *
+     * @param int|DateTime $time
      */
     public function __construct($time) {
 
@@ -46,9 +45,10 @@ class Sabre_DAV_Property_GetLastModified extends Sabre_DAV_Property {
     }
 
     /**
-     * serialize 
-     * 
-     * @param DOMElement $prop 
+     * serialize
+     *
+     * @param Sabre_DAV_Server $server
+     * @param DOMElement       $prop
      * @return void
      */
     public function serialize(Sabre_DAV_Server $server, DOMElement $prop) {
@@ -56,14 +56,14 @@ class Sabre_DAV_Property_GetLastModified extends Sabre_DAV_Property {
         $doc = $prop->ownerDocument;
         $prop->setAttribute('xmlns:b','urn:uuid:c2f41010-65b3-11d1-a29f-00aa00c14882/');
         $prop->setAttribute('b:dt','dateTime.rfc1123');
-        $prop->nodeValue = $this->time->format(DateTime::RFC1123);
+        $prop->nodeValue = Sabre_HTTP_Util::toHTTPDate($this->time);
 
     }
 
     /**
-     * getTime 
-     * 
-     * @return DateTime 
+     * getTime
+     *
+     * @return DateTime
      */
     public function getTime() {
 
diff --git a/3rdparty/Sabre/DAV/Property/Href.php b/3rdparty/Sabre/DAV/Property/Href.php
index 3294ff2ac6848fcf0564af191c10c2a7e9cd010b..dac564f24d70745d18f88970fc494267bb9081c7 100644
--- a/3rdparty/Sabre/DAV/Property/Href.php
+++ b/3rdparty/Sabre/DAV/Property/Href.php
@@ -3,36 +3,36 @@
 /**
  * Href property
  *
- * The href property represpents a url within a {DAV:}href element.
+ * The href property represents a url within a {DAV:}href element.
  * This is used by many WebDAV extensions, but not really within the WebDAV core spec
- * 
+ *
  * @package Sabre
  * @subpackage DAV
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
- * @author Evert Pot (http://www.rooftopsolutions.nl/) 
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
  */
 class Sabre_DAV_Property_Href extends Sabre_DAV_Property implements Sabre_DAV_Property_IHref {
 
     /**
-     * href 
-     * 
-     * @var string 
+     * href
+     *
+     * @var string
      */
     private $href;
 
     /**
-     * Automatically prefix the url with the server base directory 
-     * 
-     * @var bool 
+     * Automatically prefix the url with the server base directory
+     *
+     * @var bool
      */
     private $autoPrefix = true;
 
     /**
-     * __construct 
-     * 
-     * @param string $href 
-     * @return void
+     * __construct
+     *
+     * @param string $href
+     * @param bool $autoPrefix
      */
     public function __construct($href, $autoPrefix = true) {
 
@@ -42,9 +42,9 @@ class Sabre_DAV_Property_Href extends Sabre_DAV_Property implements Sabre_DAV_Pr
     }
 
     /**
-     * Returns the uri 
-     * 
-     * @return string 
+     * Returns the uri
+     *
+     * @return string
      */
     public function getHref() {
 
@@ -56,12 +56,12 @@ class Sabre_DAV_Property_Href extends Sabre_DAV_Property implements Sabre_DAV_Pr
      * Serializes this property.
      *
      * It will additionally prepend the href property with the server's base uri.
-     * 
-     * @param Sabre_DAV_Server $server 
-     * @param DOMElement $dom 
+     *
+     * @param Sabre_DAV_Server $server
+     * @param DOMElement $dom
      * @return void
      */
-    public function serialize(Sabre_DAV_Server $server,DOMElement $dom) {
+    public function serialize(Sabre_DAV_Server $server, DOMElement $dom) {
 
         $prefix = $server->xmlNamespaces['DAV:'];
 
@@ -72,13 +72,13 @@ class Sabre_DAV_Property_Href extends Sabre_DAV_Property implements Sabre_DAV_Pr
     }
 
     /**
-     * Unserializes this property from a DOM Element 
+     * Unserializes this property from a DOM Element
      *
      * This method returns an instance of this class.
      * It will only decode {DAV:}href values. For non-compatible elements null will be returned.
      *
-     * @param DOMElement $dom 
-     * @return Sabre_DAV_Property_Href 
+     * @param DOMElement $dom
+     * @return Sabre_DAV_Property_Href
      */
     static function unserialize(DOMElement $dom) {
 
@@ -86,6 +86,6 @@ class Sabre_DAV_Property_Href extends Sabre_DAV_Property implements Sabre_DAV_Pr
             return new self($dom->firstChild->textContent,false);
         }
 
-    } 
+    }
 
 }
diff --git a/3rdparty/Sabre/DAV/Property/HrefList.php b/3rdparty/Sabre/DAV/Property/HrefList.php
index 76a5512901c6ded74e7ccfc33d2f1460dfcae8d3..7a52272e8859fe9c6e17fb71a590c4678d6a4525 100644
--- a/3rdparty/Sabre/DAV/Property/HrefList.php
+++ b/3rdparty/Sabre/DAV/Property/HrefList.php
@@ -3,35 +3,35 @@
 /**
  * HrefList property
  *
- * This property contains multiple {DAV:}href elements, each containing a url. 
- * 
+ * This property contains multiple {DAV:}href elements, each containing a url.
+ *
  * @package Sabre
  * @subpackage DAV
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
- * @author Evert Pot (http://www.rooftopsolutions.nl/) 
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
  */
 class Sabre_DAV_Property_HrefList extends Sabre_DAV_Property {
 
     /**
-     * hrefs 
-     * 
-     * @var array 
+     * hrefs
+     *
+     * @var array
      */
     private $hrefs;
 
     /**
-     * Automatically prefix the url with the server base directory 
-     * 
-     * @var bool 
+     * Automatically prefix the url with the server base directory
+     *
+     * @var bool
      */
     private $autoPrefix = true;
 
     /**
-     * __construct 
-     * 
+     * __construct
+     *
      * @param array $hrefs
-     * @param bool $autoPrefix 
+     * @param bool $autoPrefix
      */
     public function __construct(array $hrefs, $autoPrefix = true) {
 
@@ -41,9 +41,9 @@ class Sabre_DAV_Property_HrefList extends Sabre_DAV_Property {
     }
 
     /**
-     * Returns the uris 
-     * 
-     * @return array 
+     * Returns the uris
+     *
+     * @return array
      */
     public function getHrefs() {
 
@@ -55,9 +55,9 @@ class Sabre_DAV_Property_HrefList extends Sabre_DAV_Property {
      * Serializes this property.
      *
      * It will additionally prepend the href property with the server's base uri.
-     * 
-     * @param Sabre_DAV_Server $server 
-     * @param DOMElement $dom 
+     *
+     * @param Sabre_DAV_Server $server
+     * @param DOMElement $dom
      * @return void
      */
     public function serialize(Sabre_DAV_Server $server,DOMElement $dom) {
@@ -73,13 +73,13 @@ class Sabre_DAV_Property_HrefList extends Sabre_DAV_Property {
     }
 
     /**
-     * Unserializes this property from a DOM Element 
+     * Unserializes this property from a DOM Element
      *
      * This method returns an instance of this class.
      * It will only decode {DAV:}href values.
      *
-     * @param DOMElement $dom 
-     * @return Sabre_DAV_Property_Href 
+     * @param DOMElement $dom
+     * @return Sabre_DAV_Property_Href
      */
     static function unserialize(DOMElement $dom) {
 
@@ -91,6 +91,6 @@ class Sabre_DAV_Property_HrefList extends Sabre_DAV_Property {
         }
         return new self($hrefs, false);
 
-    } 
+    }
 
 }
diff --git a/3rdparty/Sabre/DAV/Property/IHref.php b/3rdparty/Sabre/DAV/Property/IHref.php
index 29d76a44fcd3fb5cbcc143c829c72b07eeb53b3a..5c0409064cb3d69ecc3812a14f5cf3a5454ed34d 100644
--- a/3rdparty/Sabre/DAV/Property/IHref.php
+++ b/3rdparty/Sabre/DAV/Property/IHref.php
@@ -9,16 +9,16 @@
  *
  * @package Sabre
  * @subpackage DAV
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
- * @author Evert Pot (http://www.rooftopsolutions.nl/) 
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
  */
 interface Sabre_DAV_Property_IHref {
 
     /**
-     * getHref 
-     * 
-     * @return string 
+     * getHref
+     *
+     * @return string
      */
     function getHref();
 
diff --git a/3rdparty/Sabre/DAV/Property/LockDiscovery.php b/3rdparty/Sabre/DAV/Property/LockDiscovery.php
index 05c7470b4ed86f61448c47f6f11f6f76b74190e7..2ded5649a44951477f0517eade2510c9f78dd992 100644
--- a/3rdparty/Sabre/DAV/Property/LockDiscovery.php
+++ b/3rdparty/Sabre/DAV/Property/LockDiscovery.php
@@ -4,26 +4,26 @@
  * Represents {DAV:}lockdiscovery property
  *
  * This property contains all the open locks on a given resource
- * 
+ *
  * @package Sabre
  * @subpackage DAV
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
- * @author Evert Pot (http://www.rooftopsolutions.nl/) 
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
  */
 class Sabre_DAV_Property_LockDiscovery extends Sabre_DAV_Property {
 
     /**
-     * locks 
-     * 
-     * @var array 
+     * locks
+     *
+     * @var array
      */
     public $locks;
- 
+
     /**
-     * Should we show the locktoken as well? 
-     * 
-     * @var bool 
+     * Should we show the locktoken as well?
+     *
+     * @var bool
      */
     public $revealLockToken;
 
@@ -36,13 +36,12 @@ class Sabre_DAV_Property_LockDiscovery extends Sabre_DAV_Property {
     static public $hideLockRoot = false;
 
     /**
-     * __construct 
-     * 
-     * @param array $locks 
-     * @param bool $revealLockToken 
-     * @return void
+     * __construct
+     *
+     * @param array $locks
+     * @param bool $revealLockToken
      */
-    public function __construct($locks,$revealLockToken = false) {
+    public function __construct($locks, $revealLockToken = false) {
 
         $this->locks = $locks;
         $this->revealLockToken = $revealLockToken;
@@ -50,12 +49,13 @@ class Sabre_DAV_Property_LockDiscovery extends Sabre_DAV_Property {
     }
 
     /**
-     * serialize 
-     * 
-     * @param DOMElement $prop 
+     * serialize
+     *
+     * @param Sabre_DAV_Server $server
+     * @param DOMElement       $prop
      * @return void
      */
-    public function serialize(Sabre_DAV_Server $server,DOMElement $prop) {
+    public function serialize(Sabre_DAV_Server $server, DOMElement $prop) {
 
         $doc = $prop->ownerDocument;
 
@@ -74,7 +74,7 @@ class Sabre_DAV_Property_LockDiscovery extends Sabre_DAV_Property {
 
             $lockType->appendChild($doc->createElementNS('DAV:','d:write'));
 
-            /* {DAV:}lockroot */ 
+            /* {DAV:}lockroot */
             if (!self::$hideLockRoot) {
                 $lockRoot = $doc->createElementNS('DAV:','d:lockroot');
                 $activeLock->appendChild($lockRoot);
@@ -91,7 +91,7 @@ class Sabre_DAV_Property_LockDiscovery extends Sabre_DAV_Property {
                 $activeLock->appendChild($lockToken);
                 $lockToken->appendChild($doc->createElementNS('DAV:','d:href','opaquelocktoken:' . $lock->token));
             }
-           
+
             $activeLock->appendChild($doc->createElementNS('DAV:','d:owner',$lock->owner));
 
         }
diff --git a/3rdparty/Sabre/DAV/Property/ResourceType.php b/3rdparty/Sabre/DAV/Property/ResourceType.php
index 2c606c22d60de7c84e4711a3e8c00f8355436ab4..f6269611e54d1b2ecc4134f2104e74cb2f6a9997 100644
--- a/3rdparty/Sabre/DAV/Property/ResourceType.php
+++ b/3rdparty/Sabre/DAV/Property/ResourceType.php
@@ -4,28 +4,27 @@
  * This class represents the {DAV:}resourcetype property
  *
  * Normally for files this is empty, and for collection {DAV:}collection.
- * However, other specs define different values for this. 
- * 
+ * However, other specs define different values for this.
+ *
  * @package Sabre
  * @subpackage DAV
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
  * @author Evert Pot (http://www.rooftopsolutions.nl/)
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
  */
 class Sabre_DAV_Property_ResourceType extends Sabre_DAV_Property {
 
     /**
-     * resourceType 
-     * 
+     * resourceType
+     *
      * @var array
      */
     public $resourceType = array();
 
     /**
-     * __construct 
-     * 
-     * @param mixed $resourceType 
-     * @return void
+     * __construct
+     *
+     * @param mixed $resourceType
      */
     public function __construct($resourceType = array()) {
 
@@ -33,7 +32,7 @@ class Sabre_DAV_Property_ResourceType extends Sabre_DAV_Property {
             $this->resourceType = array();
         elseif ($resourceType === Sabre_DAV_Server::NODE_DIRECTORY)
             $this->resourceType = array('{DAV:}collection');
-        elseif (is_array($resourceType)) 
+        elseif (is_array($resourceType))
             $this->resourceType = $resourceType;
         else
             $this->resourceType = array($resourceType);
@@ -41,25 +40,26 @@ class Sabre_DAV_Property_ResourceType extends Sabre_DAV_Property {
     }
 
     /**
-     * serialize 
-     * 
-     * @param DOMElement $prop 
+     * serialize
+     *
+     * @param Sabre_DAV_Server $server
+     * @param DOMElement $prop
      * @return void
      */
-    public function serialize(Sabre_DAV_Server $server,DOMElement $prop) {
+    public function serialize(Sabre_DAV_Server $server, DOMElement $prop) {
 
         $propName = null;
         $rt = $this->resourceType;
-        
+
         foreach($rt as $resourceType) {
-            if (preg_match('/^{([^}]*)}(.*)$/',$resourceType,$propName)) { 
-       
+            if (preg_match('/^{([^}]*)}(.*)$/',$resourceType,$propName)) {
+
                 if (isset($server->xmlNamespaces[$propName[1]])) {
                     $prop->appendChild($prop->ownerDocument->createElement($server->xmlNamespaces[$propName[1]] . ':' . $propName[2]));
                 } else {
                     $prop->appendChild($prop->ownerDocument->createElementNS($propName[1],'custom:' . $propName[2]));
                 }
-            
+
             }
         }
 
@@ -69,8 +69,8 @@ class Sabre_DAV_Property_ResourceType extends Sabre_DAV_Property {
      * Returns the values in clark-notation
      *
      * For example array('{DAV:}collection')
-     * 
-     * @return array 
+     *
+     * @return array
      */
     public function getValue() {
 
@@ -79,10 +79,10 @@ class Sabre_DAV_Property_ResourceType extends Sabre_DAV_Property {
     }
 
     /**
-     * Checks if the principal contains a certain value 
-     * 
-     * @param string $type 
-     * @return bool 
+     * Checks if the principal contains a certain value
+     *
+     * @param string $type
+     * @return bool
      */
     public function is($type) {
 
@@ -104,10 +104,10 @@ class Sabre_DAV_Property_ResourceType extends Sabre_DAV_Property {
     }
 
     /**
-     * Unserializes a DOM element into a ResourceType property. 
-     * 
-     * @param DOMElement $dom 
-     * @return void
+     * Unserializes a DOM element into a ResourceType property.
+     *
+     * @param DOMElement $dom
+     * @return Sabre_DAV_Property_ResourceType
      */
     static public function unserialize(DOMElement $dom) {
 
diff --git a/3rdparty/Sabre/DAV/Property/Response.php b/3rdparty/Sabre/DAV/Property/Response.php
index 7d3a2db0387d190966a801d0488a69f3e610be5e..88afbcfb26d4e6d8b96f27e6b6e6d2978e81ed3d 100644
--- a/3rdparty/Sabre/DAV/Property/Response.php
+++ b/3rdparty/Sabre/DAV/Property/Response.php
@@ -1,53 +1,52 @@
 <?php
 
 /**
- * Response property 
- * 
+ * Response property
+ *
  * This class represents the {DAV:}response XML element.
- * This is used by the Server class to encode individual items within a multistatus 
+ * This is used by the Server class to encode individual items within a multistatus
  * response.
  *
  * @package Sabre
  * @subpackage DAV
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
- * @author Evert Pot (http://www.rooftopsolutions.nl/) 
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
  */
 class Sabre_DAV_Property_Response extends Sabre_DAV_Property implements Sabre_DAV_Property_IHref {
 
     /**
-     * Url for the response 
-     * 
-     * @var string 
+     * Url for the response
+     *
+     * @var string
      */
     private $href;
 
     /**
-     * Propertylist, ordered by HTTP status code 
-     * 
-     * @var array 
+     * Propertylist, ordered by HTTP status code
+     *
+     * @var array
      */
     private $responseProperties;
 
     /**
      * The responseProperties argument is a list of properties
      * within an array with keys representing HTTP status codes
-     * 
-     * @param string $href 
-     * @param array $responseProperties 
-     * @return void
+     *
+     * @param string $href
+     * @param array $responseProperties
      */
-    public function __construct($href,array $responseProperties) {
+    public function __construct($href, array $responseProperties) {
 
         $this->href = $href;
-        $this->responseProperties = $responseProperties; 
+        $this->responseProperties = $responseProperties;
 
     }
 
     /**
-     * Returns the url 
-     * 
-     * @return string 
+     * Returns the url
+     *
+     * @return string
      */
     public function getHref() {
 
@@ -56,9 +55,9 @@ class Sabre_DAV_Property_Response extends Sabre_DAV_Property implements Sabre_DA
     }
 
     /**
-     * Returns the property list 
-     * 
-     * @return array 
+     * Returns the property list
+     *
+     * @return array
      */
     public function getResponseProperties() {
 
@@ -67,19 +66,19 @@ class Sabre_DAV_Property_Response extends Sabre_DAV_Property implements Sabre_DA
     }
 
     /**
-     * serialize 
-     * 
-     * @param Sabre_DAV_Server $server 
-     * @param DOMElement $dom 
+     * serialize
+     *
+     * @param Sabre_DAV_Server $server
+     * @param DOMElement $dom
      * @return void
      */
-    public function serialize(Sabre_DAV_Server $server,DOMElement $dom) {
+    public function serialize(Sabre_DAV_Server $server, DOMElement $dom) {
 
         $document = $dom->ownerDocument;
         $properties = $this->responseProperties;
-        
+
         $xresponse = $document->createElement('d:response');
-        $dom->appendChild($xresponse); 
+        $dom->appendChild($xresponse);
 
         $uri = Sabre_DAV_URLUtil::encodePath($this->href);
 
@@ -87,7 +86,7 @@ class Sabre_DAV_Property_Response extends Sabre_DAV_Property implements Sabre_DA
         $uri = $server->getBaseUri() . $uri;
 
         $xresponse->appendChild($document->createElement('d:href',$uri));
-       
+
         // The properties variable is an array containing properties, grouped by
         // HTTP status
         foreach($properties as $httpStatus=>$propertyGroup) {
@@ -111,7 +110,7 @@ class Sabre_DAV_Property_Response extends Sabre_DAV_Property implements Sabre_DA
 
                 $propName = null;
                 preg_match('/^{([^}]*)}(.*)$/',$propertyName,$propName);
-            
+
                 // special case for empty namespaces
                 if ($propName[1]=='') {
 
@@ -125,7 +124,7 @@ class Sabre_DAV_Property_Response extends Sabre_DAV_Property implements Sabre_DA
                         $nsList[$propName[1]] = 'x' . count($nsList);
                     }
 
-                    // If the namespace was defined in the top-level xml namespaces, it means 
+                    // If the namespace was defined in the top-level xml namespaces, it means
                     // there was already a namespace declaration, and we don't have to worry about it.
                     if (isset($server->xmlNamespaces[$propName[1]])) {
                         $currentProperty = $document->createElement($nsList[$propName[1]] . ':' . $propName[2]);
diff --git a/3rdparty/Sabre/DAV/Property/ResponseList.php b/3rdparty/Sabre/DAV/Property/ResponseList.php
index cd70b12861d05130f1cf0f399bdf74b2be710109..cae923afbf9d542110623023d9e87ddd98be9452 100644
--- a/3rdparty/Sabre/DAV/Property/ResponseList.php
+++ b/3rdparty/Sabre/DAV/Property/ResponseList.php
@@ -1,33 +1,32 @@
 <?php
 
 /**
- * ResponseList property 
- * 
+ * ResponseList property
+ *
  * This class represents multiple {DAV:}response XML elements.
- * This is used by the Server class to encode items within a multistatus 
+ * This is used by the Server class to encode items within a multistatus
  * response.
  *
  * @package Sabre
  * @subpackage DAV
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
- * @author Evert Pot (http://www.rooftopsolutions.nl/) 
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
  */
 class Sabre_DAV_Property_ResponseList extends Sabre_DAV_Property {
 
     /**
-     * Response objects. 
-     * 
-     * @var array 
+     * Response objects.
+     *
+     * @var array
      */
     private $responses;
 
     /**
-     * The only valid argument is a list of Sabre_DAV_Property_Response 
+     * The only valid argument is a list of Sabre_DAV_Property_Response
      * objects.
-     * 
-     * @param array $responses; 
-     * @return void
+     *
+     * @param array $responses;
      */
     public function __construct($responses) {
 
@@ -41,10 +40,10 @@ class Sabre_DAV_Property_ResponseList extends Sabre_DAV_Property {
     }
 
     /**
-     * serialize 
-     * 
-     * @param Sabre_DAV_Server $server 
-     * @param DOMElement $dom 
+     * serialize
+     *
+     * @param Sabre_DAV_Server $server
+     * @param DOMElement $dom
      * @return void
      */
     public function serialize(Sabre_DAV_Server $server,DOMElement $dom) {
diff --git a/3rdparty/Sabre/DAV/Property/SupportedLock.php b/3rdparty/Sabre/DAV/Property/SupportedLock.php
index 01e63f58d9d5136a4f4b9aa5734d8acfdfd4b231..4e3aaf23a1a6229fbc24224509238ff320534e6d 100644
--- a/3rdparty/Sabre/DAV/Property/SupportedLock.php
+++ b/3rdparty/Sabre/DAV/Property/SupportedLock.php
@@ -5,27 +5,26 @@
  *
  * This property contains information about what kind of locks
  * this server supports.
- * 
+ *
  * @package Sabre
  * @subpackage DAV
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
  * @author Evert Pot (http://www.rooftopsolutions.nl/)
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
  */
 class Sabre_DAV_Property_SupportedLock extends Sabre_DAV_Property {
 
     /**
-     * supportsLocks 
-     * 
+     * supportsLocks
+     *
      * @var mixed
      */
     public $supportsLocks = false;
 
     /**
-     * __construct 
-     * 
-     * @param mixed $supportsLocks 
-     * @return void
+     * __construct
+     *
+     * @param mixed $supportsLocks
      */
     public function __construct($supportsLocks) {
 
@@ -34,9 +33,10 @@ class Sabre_DAV_Property_SupportedLock extends Sabre_DAV_Property {
     }
 
     /**
-     * serialize 
-     * 
-     * @param DOMElement $prop 
+     * serialize
+     *
+     * @param Sabre_DAV_Server $server
+     * @param DOMElement       $prop
      * @return void
      */
     public function serialize(Sabre_DAV_Server $server,DOMElement $prop) {
diff --git a/3rdparty/Sabre/DAV/Property/SupportedReportSet.php b/3rdparty/Sabre/DAV/Property/SupportedReportSet.php
index acd9219c0f70656392622d700aebcba38f81e52c..e62699f3b5a7fc3f1fbe16b5d0cd8d8f3178546d 100644
--- a/3rdparty/Sabre/DAV/Property/SupportedReportSet.php
+++ b/3rdparty/Sabre/DAV/Property/SupportedReportSet.php
@@ -5,18 +5,18 @@
  *
  * This property is defined in RFC3253, but since it's
  * so common in other webdav-related specs, it is part of the core server.
- * 
+ *
  * @package Sabre
  * @subpackage DAV
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
- * @author Evert Pot (http://www.rooftopsolutions.nl/) 
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
  */
 class Sabre_DAV_Property_SupportedReportSet extends Sabre_DAV_Property {
 
     /**
-     * List of reports 
-     * 
+     * List of reports
+     *
      * @var array
      */
     protected $reports = array();
@@ -28,13 +28,12 @@ class Sabre_DAV_Property_SupportedReportSet extends Sabre_DAV_Property {
      * should be valid report-types in clark-notation.
      *
      * Either a string or an array of strings must be passed.
-     * 
-     * @param mixed $reports 
-     * @return void
+     *
+     * @param mixed $reports
      */
     public function __construct($reports = null) {
 
-        if (!is_null($reports)) 
+        if (!is_null($reports))
             $this->addReport($reports);
 
     }
@@ -44,8 +43,8 @@ class Sabre_DAV_Property_SupportedReportSet extends Sabre_DAV_Property {
      *
      * The report must be a string in clark-notation.
      * Multiple reports can be specified as an array.
-     * 
-     * @param mixed $report 
+     *
+     * @param mixed $report
      * @return void
      */
     public function addReport($report) {
@@ -54,7 +53,7 @@ class Sabre_DAV_Property_SupportedReportSet extends Sabre_DAV_Property {
 
         foreach($report as $r) {
 
-            if (!preg_match('/^{([^}]*)}(.*)$/',$r)) 
+            if (!preg_match('/^{([^}]*)}(.*)$/',$r))
                 throw new Sabre_DAV_Exception('Reportname must be in clark-notation');
 
             $this->reports[] = $r;
@@ -65,8 +64,8 @@ class Sabre_DAV_Property_SupportedReportSet extends Sabre_DAV_Property {
 
     /**
      * Returns the list of supported reports
-     * 
-     * @return array 
+     *
+     * @return array
      */
     public function getValue() {
 
@@ -75,16 +74,16 @@ class Sabre_DAV_Property_SupportedReportSet extends Sabre_DAV_Property {
     }
 
     /**
-     * Serializes the node 
+     * Serializes the node
      *
      * @param Sabre_DAV_Server $server
-     * @param DOMElement $prop 
+     * @param DOMElement $prop
      * @return void
      */
-    public function serialize(Sabre_DAV_Server $server,DOMElement $prop) {
+    public function serialize(Sabre_DAV_Server $server, DOMElement $prop) {
 
         foreach($this->reports as $reportName) {
-     
+
             $supportedReport = $prop->ownerDocument->createElement('d:supported-report');
             $prop->appendChild($supportedReport);
 
@@ -92,9 +91,9 @@ class Sabre_DAV_Property_SupportedReportSet extends Sabre_DAV_Property {
             $supportedReport->appendChild($report);
 
             preg_match('/^{([^}]*)}(.*)$/',$reportName,$matches);
-            
+
             list(, $namespace, $element) = $matches;
-       
+
             $prefix = isset($server->xmlNamespaces[$namespace])?$server->xmlNamespaces[$namespace]:null;
 
             if ($prefix) {
diff --git a/3rdparty/Sabre/DAV/Server.php b/3rdparty/Sabre/DAV/Server.php
index 3d76d4f1918e9cabff7576e6d94805d4cdd02d5d..4284c127b6e120ac33b110e5df019e0502d6d797 100644
--- a/3rdparty/Sabre/DAV/Server.php
+++ b/3rdparty/Sabre/DAV/Server.php
@@ -2,11 +2,11 @@
 
 /**
  * Main DAV server class
- * 
+ *
  * @package Sabre
  * @subpackage DAV
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
- * @author Evert Pot (http://www.rooftopsolutions.nl/) 
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
  */
 class Sabre_DAV_Server {
@@ -26,9 +26,6 @@ class Sabre_DAV_Server {
      */
     const NODE_DIRECTORY = 2;
 
-    const PROP_SET = 1;
-    const PROP_REMOVE = 2;
-
     /**
      * XML namespace for all SabreDAV related elements
      */
@@ -36,42 +33,42 @@ class Sabre_DAV_Server {
 
     /**
      * The tree object
-     * 
-     * @var Sabre_DAV_Tree 
+     *
+     * @var Sabre_DAV_Tree
      */
     public $tree;
 
     /**
-     * The base uri 
-     * 
-     * @var string 
+     * The base uri
+     *
+     * @var string
      */
-    protected $baseUri = null; 
+    protected $baseUri = null;
 
     /**
-     * httpResponse 
-     * 
-     * @var Sabre_HTTP_Response 
+     * httpResponse
+     *
+     * @var Sabre_HTTP_Response
      */
     public $httpResponse;
 
     /**
      * httpRequest
-     * 
-     * @var Sabre_HTTP_Request 
+     *
+     * @var Sabre_HTTP_Request
      */
     public $httpRequest;
 
     /**
-     * The list of plugins 
-     * 
-     * @var array 
+     * The list of plugins
+     *
+     * @var array
      */
     protected $plugins = array();
 
     /**
-     * This array contains a list of callbacks we should call when certain events are triggered 
-     * 
+     * This array contains a list of callbacks we should call when certain events are triggered
+     *
      * @var array
      */
     protected $eventSubscriptions = array();
@@ -81,7 +78,7 @@ class Sabre_DAV_Server {
      *
      * If you are defining your own custom namespace, add it here to reduce
      * bandwidth and improve legibility of xml bodies.
-     * 
+     *
      * @var array
      */
     public $xmlNamespaces = array(
@@ -90,9 +87,9 @@ class Sabre_DAV_Server {
     );
 
     /**
-     * The propertymap can be used to map properties from 
+     * The propertymap can be used to map properties from
      * requests to property classes.
-     * 
+     *
      * @var array
      */
     public $propertyMap = array(
@@ -125,23 +122,32 @@ class Sabre_DAV_Server {
      * This is a flag that allow or not showing file, line and code
      * of the exception in the returned XML
      *
-     * @var bool 
+     * @var bool
      */
     public $debugExceptions = false;
 
     /**
-     * This property allows you to automatically add the 'resourcetype' value 
+     * This property allows you to automatically add the 'resourcetype' value
      * based on a node's classname or interface.
      *
-     * The preset ensures that {DAV:}collection is automaticlly added for nodes 
+     * The preset ensures that {DAV:}collection is automaticlly added for nodes
      * implementing Sabre_DAV_ICollection.
-     * 
+     *
      * @var array
      */
     public $resourceTypeMapping = array(
         'Sabre_DAV_ICollection' => '{DAV:}collection',
     );
 
+    /**
+     * If this setting is turned off, SabreDAV's version number will be hidden
+     * from various places.
+     *
+     * Some people feel this is a good security measure.
+     *
+     * @var bool
+     */
+    static public $exposeVersion = true;
 
     /**
      * Sets up the server
@@ -150,14 +156,13 @@ class Sabre_DAV_Server {
      * use it as the directory tree. If a Sabre_DAV_INode is passed, it
      * will create a Sabre_DAV_ObjectTree and use the node as the root.
      *
-     * If nothing is passed, a Sabre_DAV_SimpleCollection is created in 
+     * If nothing is passed, a Sabre_DAV_SimpleCollection is created in
      * a Sabre_DAV_ObjectTree.
      *
      * If an array is passed, we automatically create a root node, and use
-     * the nodes in the array as top-level children. 
-     * 
-     * @param Sabre_DAV_Tree $tree The tree object 
-     * @return void
+     * the nodes in the array as top-level children.
+     *
+     * @param Sabre_DAV_Tree|Sabre_DAV_INode|null $treeOrNode The tree object
      */
     public function __construct($treeOrNode = null) {
 
@@ -190,7 +195,7 @@ class Sabre_DAV_Server {
     }
 
     /**
-     * Starts the DAV Server 
+     * Starts the DAV Server
      *
      * @return void
      */
@@ -218,7 +223,9 @@ class Sabre_DAV_Server {
                 $error->appendChild($DOM->createElement('s:stacktrace',$e->getTraceAsString()));
 
             }
-            $error->appendChild($DOM->createElement('s:sabredav-version',Sabre_DAV_Version::VERSION));
+            if (self::$exposeVersion) {
+                $error->appendChild($DOM->createElement('s:sabredav-version',Sabre_DAV_Version::VERSION));
+            }
 
             if($e instanceof Sabre_DAV_Exception) {
 
@@ -233,7 +240,7 @@ class Sabre_DAV_Server {
 
             }
             $headers['Content-Type'] = 'application/xml; charset=utf-8';
-            
+
             $this->httpResponse->sendStatus($httpCode);
             $this->httpResponse->setHeaders($headers);
             $this->httpResponse->sendBody($DOM->saveXML());
@@ -244,24 +251,24 @@ class Sabre_DAV_Server {
 
     /**
      * Sets the base server uri
-     * 
+     *
      * @param string $uri
      * @return void
      */
     public function setBaseUri($uri) {
 
         // If the baseUri does not end with a slash, we must add it
-        if ($uri[strlen($uri)-1]!=='/') 
+        if ($uri[strlen($uri)-1]!=='/')
             $uri.='/';
 
-        $this->baseUri = $uri;    
+        $this->baseUri = $uri;
 
     }
 
     /**
      * Returns the base responding uri
-     * 
-     * @return string 
+     *
+     * @return string
      */
     public function getBaseUri() {
 
@@ -272,11 +279,11 @@ class Sabre_DAV_Server {
 
     /**
      * This method attempts to detect the base uri.
-     * Only the PATH_INFO variable is considered. 
-     * 
-     * If this variable is not set, the root (/) is assumed. 
+     * Only the PATH_INFO variable is considered.
      *
-     * @return void
+     * If this variable is not set, the root (/) is assumed.
+     *
+     * @return string
      */
     public function guessBaseUri() {
 
@@ -303,21 +310,21 @@ class Sabre_DAV_Server {
                 return rtrim($baseUri,'/') . '/';
             }
 
-            throw new Sabre_DAV_Exception('The REQUEST_URI ('. $uri . ') did not end with the contents of PATH_INFO (' . $pathInfo . '). This server might be misconfigured.'); 
+            throw new Sabre_DAV_Exception('The REQUEST_URI ('. $uri . ') did not end with the contents of PATH_INFO (' . $pathInfo . '). This server might be misconfigured.');
 
-        } 
+        }
 
-        // The last fallback is that we're just going to assume the server root. 
+        // The last fallback is that we're just going to assume the server root.
         return '/';
 
     }
 
     /**
      * Adds a plugin to the server
-     * 
+     *
      * For more information, console the documentation of Sabre_DAV_ServerPlugin
      *
-     * @param Sabre_DAV_ServerPlugin $plugin 
+     * @param Sabre_DAV_ServerPlugin $plugin
      * @return void
      */
     public function addPlugin(Sabre_DAV_ServerPlugin $plugin) {
@@ -333,11 +340,11 @@ class Sabre_DAV_Server {
      * This function returns null if the plugin was not found.
      *
      * @param string $name
-     * @return Sabre_DAV_ServerPlugin 
+     * @return Sabre_DAV_ServerPlugin
      */
     public function getPlugin($name) {
 
-        if (isset($this->plugins[$name])) 
+        if (isset($this->plugins[$name]))
             return $this->plugins[$name];
 
         // This is a fallback and deprecated.
@@ -350,9 +357,9 @@ class Sabre_DAV_Server {
     }
 
     /**
-     * Returns all plugins 
-     * 
-     * @return array 
+     * Returns all plugins
+     *
+     * @return array
      */
     public function getPlugins() {
 
@@ -361,7 +368,6 @@ class Sabre_DAV_Server {
     }
 
 
-
     /**
      * Subscribe to an event.
      *
@@ -371,9 +377,9 @@ class Sabre_DAV_Server {
      *
      * This is for example used to make sure that the authentication plugin
      * is triggered before anything else. If it's not needed to change this
-     * number, it is recommended to ommit.  
-     * 
-     * @param string $event 
+     * number, it is recommended to ommit.
+     *
+     * @param string $event
      * @param callback $callback
      * @param int $priority
      * @return void
@@ -398,7 +404,7 @@ class Sabre_DAV_Server {
      *
      * @param string $eventName
      * @param array $arguments
-     * @return bool 
+     * @return bool
      */
     public function broadcastEvent($eventName,$arguments = array()) {
 
@@ -418,7 +424,7 @@ class Sabre_DAV_Server {
     }
 
     /**
-     * Handles a http request, and execute a method based on its name 
+     * Handles a http request, and execute a method based on its name
      *
      * @param string $method
      * @param string $uri
@@ -426,7 +432,7 @@ class Sabre_DAV_Server {
      */
     public function invokeMethod($method, $uri) {
 
-        $method = strtoupper($method); 
+        $method = strtoupper($method);
 
         if (!$this->broadcastEvent('beforeMethod',array($method, $uri))) return;
 
@@ -453,7 +459,7 @@ class Sabre_DAV_Server {
 
             if ($this->broadcastEvent('unknownMethod',array($method, $uri))) {
                 // Unsupported method
-                throw new Sabre_DAV_Exception_NotImplemented();
+                throw new Sabre_DAV_Exception_NotImplemented('There was no handler found for this "' . $method . '" method');
             }
 
         }
@@ -461,9 +467,9 @@ class Sabre_DAV_Server {
     }
 
     // {{{ HTTP Method implementations
-    
+
     /**
-     * HTTP OPTIONS 
+     * HTTP OPTIONS
      *
      * @param string $uri
      * @return void
@@ -476,11 +482,13 @@ class Sabre_DAV_Server {
         $features = array('1','3', 'extended-mkcol');
 
         foreach($this->plugins as $plugin) $features = array_merge($features,$plugin->getFeatures());
-        
+
         $this->httpResponse->setHeader('DAV',implode(', ',$features));
         $this->httpResponse->setHeader('MS-Author-Via','DAV');
         $this->httpResponse->setHeader('Accept-Ranges','bytes');
-        $this->httpResponse->setHeader('X-Sabre-Version',Sabre_DAV_Version::VERSION);
+        if (self::$exposeVersion) {
+            $this->httpResponse->setHeader('X-Sabre-Version',Sabre_DAV_Version::VERSION);
+        }
         $this->httpResponse->setHeader('Content-Length',0);
         $this->httpResponse->sendStatus(200);
 
@@ -492,13 +500,13 @@ class Sabre_DAV_Server {
      * This method simply fetches the contents of a uri, like normal
      *
      * @param string $uri
-     * @return void
+     * @return bool
      */
     protected function httpGet($uri) {
 
         $node = $this->tree->getNodeForPath($uri,0);
 
-        if (!$this->checkPreconditions(true)) return false; 
+        if (!$this->checkPreconditions(true)) return false;
 
         if (!($node instanceof Sabre_DAV_IFile)) throw new Sabre_DAV_Exception_NotImplemented('GET is only implemented on File objects');
         $body = $node->get();
@@ -535,7 +543,7 @@ class Sabre_DAV_Server {
         } else {
             $nodeSize = null;
         }
-        
+
         $this->httpResponse->setHeaders($httpHeaders);
 
         $range = $this->getHTTPRange();
@@ -545,12 +553,12 @@ class Sabre_DAV_Server {
         // If ifRange is set, and range is specified, we first need to check
         // the precondition.
         if ($nodeSize && $range && $ifRange) {
-             
+
             // if IfRange is parsable as a date we'll treat it as a DateTime
             // otherwise, we must treat it as an etag.
             try {
                 $ifRangeDate = new DateTime($ifRange);
-               
+
                 // It's a date. We must check if the entity is modified since
                 // the specified date.
                 if (!isset($httpHeaders['Last-Modified'])) $ignoreRangeHeader = true;
@@ -560,8 +568,8 @@ class Sabre_DAV_Server {
                 }
 
             } catch (Exception $e) {
-               
-                // It's an entity. We can do a simple comparison. 
+
+                // It's an entity. We can do a simple comparison.
                 if (!isset($httpHeaders['ETag'])) $ignoreRangeHeader = true;
                 elseif ($httpHeaders['ETag']!==$ifRange) $ignoreRangeHeader = true;
             }
@@ -575,7 +583,7 @@ class Sabre_DAV_Server {
 
                 $start = $range[0];
                 $end = $range[1]?$range[1]:$nodeSize-1;
-                if($start >= $nodeSize) 
+                if($start >= $nodeSize)
                     throw new Sabre_DAV_Exception_RequestedRangeNotSatisfiable('The start offset (' . $range[0] . ') exceeded the size of the entity (' . $nodeSize . ')');
 
                 if($end < $start) throw new Sabre_DAV_Exception_RequestedRangeNotSatisfiable('The end offset (' . $range[1] . ') is lower than the start offset (' . $range[0] . ')');
@@ -625,7 +633,7 @@ class Sabre_DAV_Server {
 
         $node = $this->tree->getNodeForPath($uri);
         /* This information is only collection for File objects.
-         * Ideally we want to throw 405 Method Not Allowed for every 
+         * Ideally we want to throw 405 Method Not Allowed for every
          * non-file, but MS Office does not like this
          */
         if ($node instanceof Sabre_DAV_IFile) {
@@ -640,7 +648,7 @@ class Sabre_DAV_Server {
     }
 
     /**
-     * HTTP Delete 
+     * HTTP Delete
      *
      * The HTTP delete method, deletes a given uri
      *
@@ -651,6 +659,7 @@ class Sabre_DAV_Server {
 
         if (!$this->broadcastEvent('beforeUnbind',array($uri))) return;
         $this->tree->delete($uri);
+        $this->broadcastEvent('afterUnbind',array($uri));
 
         $this->httpResponse->sendStatus(204);
         $this->httpResponse->setHeader('Content-Length','0');
@@ -659,13 +668,13 @@ class Sabre_DAV_Server {
 
 
     /**
-     * WebDAV PROPFIND 
+     * WebDAV PROPFIND
      *
      * This WebDAV method requests information about an uri resource, or a list of resources
      * If a client wants to receive the properties for a single resource it will add an HTTP Depth: header with a 0 value
      * If the value is 1, it means that it also expects a list of sub-resources (e.g.: files in a directory)
      *
-     * The request body contains an XML data structure that has a list of properties the client understands 
+     * The request body contains an XML data structure that has a list of properties the client understands
      * The response body is also an xml document, containing information about every uri resource and the requested properties
      *
      * It has to return a HTTP 207 Multi-status status code
@@ -679,7 +688,7 @@ class Sabre_DAV_Server {
         $requestedProperties = $this->parsePropfindRequest($this->httpRequest->getBody(true));
 
         $depth = $this->getHTTPDepth(1);
-        // The only two options for the depth of a propfind is 0 or 1 
+        // The only two options for the depth of a propfind is 0 or 1
         if ($depth!=0) $depth = 1;
 
         $newProperties = $this->getPropertiesForPath($uri,$requestedProperties,$depth);
@@ -688,8 +697,8 @@ class Sabre_DAV_Server {
         $this->httpResponse->sendStatus(207);
         $this->httpResponse->setHeader('Content-Type','application/xml; charset=utf-8');
 
-        // Normally this header is only needed for OPTIONS responses, however.. 
-        // iCal seems to also depend on these being set for PROPFIND. Since 
+        // Normally this header is only needed for OPTIONS responses, however..
+        // iCal seems to also depend on these being set for PROPFIND. Since
         // this is not harmful, we'll add it.
         $features = array('1','3', 'extended-mkcol');
         foreach($this->plugins as $plugin) $features = array_merge($features,$plugin->getFeatures());
@@ -712,7 +721,7 @@ class Sabre_DAV_Server {
     protected function httpPropPatch($uri) {
 
         $newProperties = $this->parsePropPatchRequest($this->httpRequest->getBody(true));
-        
+
         $result = $this->updateProperties($uri, $newProperties);
 
         $this->httpResponse->sendStatus(207);
@@ -725,14 +734,14 @@ class Sabre_DAV_Server {
     }
 
     /**
-     * HTTP PUT method 
-     * 
+     * HTTP PUT method
+     *
      * This HTTP method updates a file, or creates a new one.
      *
-     * If a new resource was created, a 201 Created status code should be returned. If an existing resource is updated, it's a 200 Ok
+     * If a new resource was created, a 201 Created status code should be returned. If an existing resource is updated, it's a 204 No Content
      *
      * @param string $uri
-     * @return void
+     * @return bool
      */
     protected function httpPut($uri) {
 
@@ -768,13 +777,13 @@ class Sabre_DAV_Server {
 
         // Intercepting the Finder problem
         if (($expected = $this->httpRequest->getHeader('X-Expected-Entity-Length')) && $expected > 0) {
-           
+
             /**
-            Many webservers will not cooperate well with Finder PUT requests, 
+            Many webservers will not cooperate well with Finder PUT requests,
             because it uses 'Chunked' transfer encoding for the request body.
 
-            The symptom of this problem is that Finder sends files to the 
-            server, but they arrive as 0-lenght files in PHP.
+            The symptom of this problem is that Finder sends files to the
+            server, but they arrive as 0-length files in PHP.
 
             If we don't do anything, the user might think they are uploading
             files successfully, but they end up empty on the server. Instead,
@@ -808,29 +817,36 @@ class Sabre_DAV_Server {
 
         }
 
-        if ($this->tree->nodeExists($uri)) { 
+        if ($this->tree->nodeExists($uri)) {
 
             $node = $this->tree->getNodeForPath($uri);
-          
+
             // Checking If-None-Match and related headers.
             if (!$this->checkPreconditions()) return;
-            
+
             // If the node is a collection, we'll deny it
             if (!($node instanceof Sabre_DAV_IFile)) throw new Sabre_DAV_Exception_Conflict('PUT is not allowed on non-files.');
-            if (!$this->broadcastEvent('beforeWriteContent',array($this->getRequestUri()))) return false;
+            if (!$this->broadcastEvent('beforeWriteContent',array($uri, $node, &$body))) return false;
+
+            $etag = $node->put($body);
+
+            $this->broadcastEvent('afterWriteContent',array($uri, $node));
 
-            $node->put($body);
             $this->httpResponse->setHeader('Content-Length','0');
+            if ($etag) $this->httpResponse->setHeader('ETag',$etag);
             $this->httpResponse->sendStatus(204);
 
         } else {
 
+            $etag = null;
             // If we got here, the resource didn't exist yet.
-            if (!$this->createFile($this->getRequestUri(),$body)) {
+            if (!$this->createFile($this->getRequestUri(),$body,$etag)) {
                 // For one reason or another the file was not created.
                 return;
             }
+
             $this->httpResponse->setHeader('Content-Length','0');
+            if ($etag) $this->httpResponse->setHeader('ETag', $etag);
             $this->httpResponse->sendStatus(201);
 
         }
@@ -855,7 +871,7 @@ class Sabre_DAV_Server {
             $contentType = $this->httpRequest->getHeader('Content-Type');
             if (strpos($contentType,'application/xml')!==0 && strpos($contentType,'text/xml')!==0) {
 
-                // We must throw 415 for unsupport mkcol bodies
+                // We must throw 415 for unsupported mkcol bodies
                 throw new Sabre_DAV_Exception_UnsupportedMediaType('The request body for the MKCOL request must have an xml Content-Type');
 
             }
@@ -863,7 +879,7 @@ class Sabre_DAV_Server {
             $dom = Sabre_DAV_XMLUtil::loadDOMDocument($requestBody);
             if (Sabre_DAV_XMLUtil::toClarkNotation($dom->firstChild)!=='{DAV:}mkcol') {
 
-                // We must throw 415 for unsupport mkcol bodies
+                // We must throw 415 for unsupported mkcol bodies
                 throw new Sabre_DAV_Exception_UnsupportedMediaType('The request body for the MKCOL request must be a {DAV:}mkcol request construct.');
 
             }
@@ -875,7 +891,7 @@ class Sabre_DAV_Server {
                 $properties = array_merge($properties, Sabre_DAV_XMLUtil::parseProperties($childNode, $this->propertyMap));
 
             }
-            if (!isset($properties['{DAV:}resourcetype'])) 
+            if (!isset($properties['{DAV:}resourcetype']))
                 throw new Sabre_DAV_Exception_BadRequest('The mkcol request must include a {DAV:}resourcetype property');
 
             $resourceType = $properties['{DAV:}resourcetype']->getValue();
@@ -918,19 +934,21 @@ class Sabre_DAV_Server {
         $moveInfo = $this->getCopyAndMoveInfo();
 
         // If the destination is part of the source tree, we must fail
-        if ($moveInfo['destination']==$uri) 
+        if ($moveInfo['destination']==$uri)
             throw new Sabre_DAV_Exception_Forbidden('Source and destination uri are identical.');
 
         if ($moveInfo['destinationExists']) {
 
             if (!$this->broadcastEvent('beforeUnbind',array($moveInfo['destination']))) return false;
             $this->tree->delete($moveInfo['destination']);
+            $this->broadcastEvent('afterUnbind',array($moveInfo['destination']));
 
         }
 
         if (!$this->broadcastEvent('beforeUnbind',array($uri))) return false;
         if (!$this->broadcastEvent('beforeBind',array($moveInfo['destination']))) return false;
         $this->tree->move($uri,$moveInfo['destination']);
+        $this->broadcastEvent('afterUnbind',array($uri));
         $this->broadcastEvent('afterBind',array($moveInfo['destination']));
 
         // If a resource was overwritten we should send a 204, otherwise a 201
@@ -946,13 +964,13 @@ class Sabre_DAV_Server {
      * A lot of the actual request processing is done in getCopyMoveInfo
      *
      * @param string $uri
-     * @return void
+     * @return bool
      */
     protected function httpCopy($uri) {
 
         $copyInfo = $this->getCopyAndMoveInfo();
         // If the destination is part of the source tree, we must fail
-        if ($copyInfo['destination']==$uri) 
+        if ($copyInfo['destination']==$uri)
             throw new Sabre_DAV_Exception_Forbidden('Source and destination uri are identical.');
 
         if ($copyInfo['destinationExists']) {
@@ -998,13 +1016,13 @@ class Sabre_DAV_Server {
     }
 
     // }}}
-    // {{{ HTTP/WebDAV protocol helpers 
+    // {{{ HTTP/WebDAV protocol helpers
 
     /**
-     * Returns an array with all the supported HTTP methods for a specific uri. 
+     * Returns an array with all the supported HTTP methods for a specific uri.
      *
-     * @param string $uri 
-     * @return array 
+     * @param string $uri
+     * @return array
      */
     public function getAllowedMethods($uri) {
 
@@ -1023,13 +1041,13 @@ class Sabre_DAV_Server {
 
         // The MKCOL is only allowed on an unmapped uri
         try {
-            $node = $this->tree->getNodeForPath($uri);
-        } catch (Sabre_DAV_Exception_FileNotFound $e) {
+            $this->tree->getNodeForPath($uri);
+        } catch (Sabre_DAV_Exception_NotFound $e) {
             $methods[] = 'MKCOL';
         }
 
         // We're also checking if any of the plugins register any new methods
-        foreach($this->plugins as $plugin) $methods = array_merge($methods,$plugin->getHTTPMethods($uri));
+        foreach($this->plugins as $plugin) $methods = array_merge($methods, $plugin->getHTTPMethods($uri));
         array_unique($methods);
 
         return $methods;
@@ -1037,8 +1055,8 @@ class Sabre_DAV_Server {
     }
 
     /**
-     * Gets the uri for the request, keeping the base uri into consideration 
-     * 
+     * Gets the uri for the request, keeping the base uri into consideration
+     *
      * @return string
      */
     public function getRequestUri() {
@@ -1048,9 +1066,9 @@ class Sabre_DAV_Server {
     }
 
     /**
-     * Calculates the uri for a request, making sure that the base uri is stripped out 
-     * 
-     * @param string $uri 
+     * Calculates the uri for a request, making sure that the base uri is stripped out
+     *
+     * @param string $uri
      * @throws Sabre_DAV_Exception_Forbidden A permission denied exception is thrown whenever there was an attempt to supply a uri outside of the base uri
      * @return string
      */
@@ -1068,9 +1086,9 @@ class Sabre_DAV_Server {
 
             return trim(Sabre_DAV_URLUtil::decodePath(substr($uri,strlen($this->getBaseUri()))),'/');
 
-        // A special case, if the baseUri was accessed without a trailing 
-        // slash, we'll accept it as well. 
-        } elseif ($uri.'/' === $this->getBaseUri()) { 
+        // A special case, if the baseUri was accessed without a trailing
+        // slash, we'll accept it as well.
+        } elseif ($uri.'/' === $this->getBaseUri()) {
 
             return '';
 
@@ -1086,10 +1104,10 @@ class Sabre_DAV_Server {
      * Returns the HTTP depth header
      *
      * This method returns the contents of the HTTP depth request header. If the depth header was 'infinity' it will return the Sabre_DAV_Server::DEPTH_INFINITY object
-     * It is possible to supply a default depth value, which is used when the depth header has invalid content, or is completely non-existant
-     * 
-     * @param mixed $default 
-     * @return int 
+     * It is possible to supply a default depth value, which is used when the depth header has invalid content, or is completely non-existent
+     *
+     * @param mixed $default
+     * @return int
      */
     public function getHTTPDepth($default = self::DEPTH_INFINITY) {
 
@@ -1100,7 +1118,7 @@ class Sabre_DAV_Server {
 
         if ($depth == 'infinity') return self::DEPTH_INFINITY;
 
-           
+
         // If its an unknown value. we'll grab the default
         if (!ctype_digit($depth)) return $default;
 
@@ -1118,14 +1136,14 @@ class Sabre_DAV_Server {
      * The second number is the offset of the last byte in the range.
      *
      * If the second offset is null, it should be treated as the offset of the last byte of the entity
-     * If the first offset is null, the second offset should be used to retrieve the last x bytes of the entity 
+     * If the first offset is null, the second offset should be used to retrieve the last x bytes of the entity
      *
-     * return $mixed
+     * @return array|null
      */
     public function getHTTPRange() {
 
         $range = $this->httpRequest->getHeader('range');
-        if (is_null($range)) return null; 
+        if (is_null($range)) return null;
 
         // Matching "Range: bytes=1234-5678: both numbers are optional
 
@@ -1143,15 +1161,15 @@ class Sabre_DAV_Server {
 
     /**
      * Returns information about Copy and Move requests
-     * 
-     * This function is created to help getting information about the source and the destination for the 
-     * WebDAV MOVE and COPY HTTP request. It also validates a lot of information and throws proper exceptions 
-     * 
+     *
+     * This function is created to help getting information about the source and the destination for the
+     * WebDAV MOVE and COPY HTTP request. It also validates a lot of information and throws proper exceptions
+     *
      * The returned value is an array with the following keys:
      *   * destination - Destination path
-     *   * destinationExists - Wether or not the destination is an existing url (and should therefore be overwritten)
+     *   * destinationExists - Whether or not the destination is an existing url (and should therefore be overwritten)
      *
-     * @return array 
+     * @return array
      */
     public function getCopyAndMoveInfo() {
 
@@ -1170,7 +1188,7 @@ class Sabre_DAV_Server {
         try {
             $destinationParent = $this->tree->getNodeForPath($destinationDir);
             if (!($destinationParent instanceof Sabre_DAV_ICollection)) throw new Sabre_DAV_Exception_UnsupportedMediaType('The destination node is not a collection');
-        } catch (Sabre_DAV_Exception_FileNotFound $e) {
+        } catch (Sabre_DAV_Exception_NotFound $e) {
 
             // If the destination parent node is not found, we throw a 409
             throw new Sabre_DAV_Exception_Conflict('The destination node is not found');
@@ -1179,12 +1197,12 @@ class Sabre_DAV_Server {
         try {
 
             $destinationNode = $this->tree->getNodeForPath($destination);
-            
+
             // If this succeeded, it means the destination already exists
             // we'll need to throw precondition failed in case overwrite is false
             if (!$overwrite) throw new Sabre_DAV_Exception_PreconditionFailed('The destination node already exists, and the overwrite header is set to false','Overwrite');
 
-        } catch (Sabre_DAV_Exception_FileNotFound $e) {
+        } catch (Sabre_DAV_Exception_NotFound $e) {
 
             // Destination didn't exist, we're all good
             $destinationNode = false;
@@ -1219,23 +1237,51 @@ class Sabre_DAV_Server {
 
     }
 
+    /**
+     * A kid-friendly way to fetch properties for a node's children.
+     *
+     * The returned array will be indexed by the path of the of child node.
+     * Only properties that are actually found will be returned.
+     *
+     * The parent node will not be returned.
+     *
+     * @param string $path
+     * @param array $propertyNames
+     * @return array
+     */
+    public function getPropertiesForChildren($path, $propertyNames) {
+
+        $result = array();
+        foreach($this->getPropertiesForPath($path,$propertyNames,1) as $k=>$row) {
+
+            // Skipping the parent path
+            if ($k === 0) continue;
+
+            $result[$row['href']] = $row[200];
+
+        }
+        return $result;
+
+    }
+
     /**
      * Returns a list of HTTP headers for a particular resource
      *
-     * The generated http headers are based on properties provided by the 
+     * The generated http headers are based on properties provided by the
      * resource. The method basically provides a simple mapping between
      * DAV property and HTTP header.
      *
      * The headers are intended to be used for HEAD and GET requests.
-     * 
+     *
      * @param string $path
+     * @return array
      */
     public function getHTTPHeaders($path) {
 
         $propertyMap = array(
             '{DAV:}getcontenttype'   => 'Content-Type',
             '{DAV:}getcontentlength' => 'Content-Length',
-            '{DAV:}getlastmodified'  => 'Last-Modified', 
+            '{DAV:}getlastmodified'  => 'Last-Modified',
             '{DAV:}getetag'          => 'ETag',
         );
 
@@ -1245,40 +1291,40 @@ class Sabre_DAV_Server {
         foreach($propertyMap as $property=>$header) {
             if (!isset($properties[$property])) continue;
 
-            if (is_scalar($properties[$property])) { 
+            if (is_scalar($properties[$property])) {
                 $headers[$header] = $properties[$property];
 
-            // GetLastModified gets special cased 
+            // GetLastModified gets special cased
             } elseif ($properties[$property] instanceof Sabre_DAV_Property_GetLastModified) {
-                $headers[$header] = $properties[$property]->getTime()->format(DateTime::RFC1123);
+                $headers[$header] = Sabre_HTTP_Util::toHTTPDate($properties[$property]->getTime());
             }
 
         }
 
         return $headers;
-        
+
     }
 
     /**
      * Returns a list of properties for a given path
-     * 
+     *
      * The path that should be supplied should have the baseUrl stripped out
      * The list of properties should be supplied in Clark notation. If the list is empty
      * 'allprops' is assumed.
      *
      * If a depth of 1 is requested child elements will also be returned.
      *
-     * @param string $path 
+     * @param string $path
      * @param array $propertyNames
-     * @param int $depth 
+     * @param int $depth
      * @return array
      */
-    public function getPropertiesForPath($path,$propertyNames = array(),$depth = 0) {
+    public function getPropertiesForPath($path, $propertyNames = array(), $depth = 0) {
 
         if ($depth!=0) $depth = 1;
 
         $returnPropertyList = array();
-        
+
         $parentNode = $this->tree->getNodeForPath($path);
         $nodes = array(
             $path => $parentNode
@@ -1286,11 +1332,11 @@ class Sabre_DAV_Server {
         if ($depth==1 && $parentNode instanceof Sabre_DAV_ICollection) {
             foreach($this->tree->getChildren($path) as $childNode)
                 $nodes[$path . '/' . $childNode->getName()] = $childNode;
-        }            
-       
+        }
+
         // If the propertyNames array is empty, it means all properties are requested.
         // We shouldn't actually return everything we know though, and only return a
-        // sensible list. 
+        // sensible list.
         $allProperties = count($propertyNames)==0;
 
         foreach($nodes as $myPath=>$node) {
@@ -1315,8 +1361,8 @@ class Sabre_DAV_Server {
                 );
             }
 
-            // If the resourceType was not part of the list, we manually add it 
-            // and mark it for removal. We need to know the resourcetype in order 
+            // If the resourceType was not part of the list, we manually add it
+            // and mark it for removal. We need to know the resourcetype in order
             // to make certain decisions about the entry.
             // WebDAV dictates we should add a / and the end of href's for collections
             $removeRT = false;
@@ -1326,32 +1372,39 @@ class Sabre_DAV_Server {
             }
 
             $result = $this->broadcastEvent('beforeGetProperties',array($myPath, $node, &$currentPropertyNames, &$newProperties));
-            // If this method explicitly returned false, we must ignore this 
-            // node as it is inacessible.
+            // If this method explicitly returned false, we must ignore this
+            // node as it is inaccessible.
             if ($result===false) continue;
 
             if (count($currentPropertyNames) > 0) {
 
-                if ($node instanceof Sabre_DAV_IProperties) 
+                if ($node instanceof Sabre_DAV_IProperties)
                     $newProperties['200'] = $newProperties[200] + $node->getProperties($currentPropertyNames);
 
             }
 
 
             foreach($currentPropertyNames as $prop) {
-                
+
                 if (isset($newProperties[200][$prop])) continue;
 
                 switch($prop) {
                     case '{DAV:}getlastmodified'       : if ($node->getLastModified()) $newProperties[200][$prop] = new Sabre_DAV_Property_GetLastModified($node->getLastModified()); break;
-                    case '{DAV:}getcontentlength'      : if ($node instanceof Sabre_DAV_IFile) $newProperties[200][$prop] = (int)$node->getSize(); break;
-                    case '{DAV:}quota-used-bytes'      : 
+                    case '{DAV:}getcontentlength'      :
+                        if ($node instanceof Sabre_DAV_IFile) {
+                            $size = $node->getSize();
+                            if (!is_null($size)) {
+                                $newProperties[200][$prop] = (int)$node->getSize();
+                            }
+                        }
+                        break;
+                    case '{DAV:}quota-used-bytes'      :
                         if ($node instanceof Sabre_DAV_IQuota) {
                             $quotaInfo = $node->getQuotaInfo();
                             $newProperties[200][$prop] = $quotaInfo[0];
                         }
                         break;
-                    case '{DAV:}quota-available-bytes' : 
+                    case '{DAV:}quota-available-bytes' :
                         if ($node instanceof Sabre_DAV_IQuota) {
                             $quotaInfo = $node->getQuotaInfo();
                             $newProperties[200][$prop] = $quotaInfo[1];
@@ -1364,7 +1417,7 @@ class Sabre_DAV_Server {
                         foreach($this->plugins as $plugin) {
                             $reports = array_merge($reports, $plugin->getSupportedReportSet($myPath));
                         }
-                        $newProperties[200][$prop] = new Sabre_DAV_Property_SupportedReportSet($reports); 
+                        $newProperties[200][$prop] = new Sabre_DAV_Property_SupportedReportSet($reports);
                         break;
                     case '{DAV:}resourcetype' :
                         $newProperties[200]['{DAV:}resourcetype'] = new Sabre_DAV_Property_ResourceType();
@@ -1379,14 +1432,14 @@ class Sabre_DAV_Server {
                 if (!$allProperties && !isset($newProperties[200][$prop])) $newProperties[404][$prop] = null;
 
             }
-         
+
             $this->broadcastEvent('afterGetProperties',array(trim($myPath,'/'),&$newProperties));
 
-            $newProperties['href'] = trim($myPath,'/'); 
+            $newProperties['href'] = trim($myPath,'/');
 
             // Its is a WebDAV recommendation to add a trailing slash to collectionnames.
             // Apple's iCal also requires a trailing slash for principals (rfc 3744).
-            // Therefore we add a trailing / for any non-file. This might need adjustments 
+            // Therefore we add a trailing / for any non-file. This might need adjustments
             // if we find there are other edge cases.
             if ($myPath!='' && isset($newProperties[200]['{DAV:}resourcetype']) && count($newProperties[200]['{DAV:}resourcetype']->getValue())>0) $newProperties['href'] .='/';
 
@@ -1397,7 +1450,7 @@ class Sabre_DAV_Server {
             $returnPropertyList[] = $newProperties;
 
         }
-        
+
         return $returnPropertyList;
 
     }
@@ -1406,27 +1459,31 @@ class Sabre_DAV_Server {
      * This method is invoked by sub-systems creating a new file.
      *
      * Currently this is done by HTTP PUT and HTTP LOCK (in the Locks_Plugin).
-     * It was important to get this done through a centralized function, 
+     * It was important to get this done through a centralized function,
      * allowing plugins to intercept this using the beforeCreateFile event.
      *
      * This method will return true if the file was actually created
-     * 
-     * @param string $uri 
-     * @param resource $data 
-     * @return bool 
+     *
+     * @param string   $uri
+     * @param resource $data
+     * @param string   $etag
+     * @return bool
      */
-    public function createFile($uri,$data) {
+    public function createFile($uri,$data, &$etag = null) {
 
         list($dir,$name) = Sabre_DAV_URLUtil::splitPath($uri);
 
         if (!$this->broadcastEvent('beforeBind',array($uri))) return false;
-        if (!$this->broadcastEvent('beforeCreateFile',array($uri,$data))) return false;
 
         $parent = $this->tree->getNodeForPath($dir);
-        $parent->createFile($name,$data);
+
+        if (!$this->broadcastEvent('beforeCreateFile',array($uri, &$data, $parent))) return false;
+
+        $etag = $parent->createFile($name,$data);
         $this->tree->markDirty($dir);
 
         $this->broadcastEvent('afterBind',array($uri));
+        $this->broadcastEvent('afterCreateFile',array($uri, $parent));
 
         return true;
     }
@@ -1434,7 +1491,7 @@ class Sabre_DAV_Server {
     /**
      * This method is invoked by sub-systems creating a new directory.
      *
-     * @param string $uri 
+     * @param string $uri
      * @return void
      */
     public function createDirectory($uri) {
@@ -1447,14 +1504,14 @@ class Sabre_DAV_Server {
      * Use this method to create a new collection
      *
      * The {DAV:}resourcetype is specified using the resourceType array.
-     * At the very least it must contain {DAV:}collection. 
+     * At the very least it must contain {DAV:}collection.
      *
      * The properties array can contain a list of additional properties.
-     * 
-     * @param string $uri The new uri 
-     * @param array $resourceType The resourceType(s) 
+     *
+     * @param string $uri The new uri
+     * @param array $resourceType The resourceType(s)
      * @param array $properties A list of properties
-     * @return void
+     * @return array|null
      */
     public function createCollection($uri, array $resourceType, array $properties) {
 
@@ -1471,7 +1528,7 @@ class Sabre_DAV_Server {
 
             $parent = $this->tree->getNodeForPath($parentUri);
 
-        } catch (Sabre_DAV_Exception_FileNotFound $e) {
+        } catch (Sabre_DAV_Exception_NotFound $e) {
 
             throw new Sabre_DAV_Exception_Conflict('Parent node does not exist');
 
@@ -1491,14 +1548,14 @@ class Sabre_DAV_Server {
             // If we got here.. it means there's already a node on that url, and we need to throw a 405
             throw new Sabre_DAV_Exception_MethodNotAllowed('The resource you tried to create already exists');
 
-        } catch (Sabre_DAV_Exception_FileNotFound $e) {
+        } catch (Sabre_DAV_Exception_NotFound $e) {
             // This is correct
         }
 
-        
+
         if (!$this->broadcastEvent('beforeBind',array($uri))) return;
 
-        // There are 2 modes of operation. The standard collection 
+        // There are 2 modes of operation. The standard collection
         // creates the directory, and then updates properties
         // the extended collection can create it directly.
         if ($parent instanceof Sabre_DAV_IExtendedCollection) {
@@ -1513,7 +1570,7 @@ class Sabre_DAV_Server {
             }
 
             $parent->createDirectory($newName);
-            $rollBack = false; 
+            $rollBack = false;
             $exception = null;
             $errorResult = null;
 
@@ -1544,7 +1601,7 @@ class Sabre_DAV_Server {
 
                 return $errorResult;
             }
-                
+
         }
         $this->tree->markDirty($parentUri);
         $this->broadcastEvent('afterBind',array($uri));
@@ -1557,29 +1614,29 @@ class Sabre_DAV_Server {
      * The properties array must be a list of properties. Array-keys are
      * property names in clarknotation, array-values are it's values.
      * If a property must be deleted, the value should be null.
-     * 
-     * Note that this request should either completely succeed, or 
+     *
+     * Note that this request should either completely succeed, or
      * completely fail.
      *
      * The response is an array with statuscodes for keys, which in turn
      * contain arrays with propertynames. This response can be used
      * to generate a multistatus body.
-     * 
-     * @param string $uri 
-     * @param array $properties 
-     * @return array 
+     *
+     * @param string $uri
+     * @param array $properties
+     * @return array
      */
     public function updateProperties($uri, array $properties) {
 
         // we'll start by grabbing the node, this will throw the appropriate
-        // exceptions if it doesn't. 
+        // exceptions if it doesn't.
         $node = $this->tree->getNodeForPath($uri);
-       
+
         $result = array(
             200 => array(),
             403 => array(),
             424 => array(),
-        ); 
+        );
         $remainingProperties = $properties;
         $hasError = false;
 
@@ -1684,14 +1741,15 @@ class Sabre_DAV_Server {
      * the appropriate HTTP response headers are already set.
      *
      * Normally this method will throw 412 Precondition Failed for failures
-     * related to If-None-Match, If-Match and If-Unmodified Since. It will 
+     * related to If-None-Match, If-Match and If-Unmodified Since. It will
      * set the status to 304 Not Modified for If-Modified_since.
      *
-     * If the $handleAsGET argument is set to true, it will also return 304 
+     * If the $handleAsGET argument is set to true, it will also return 304
      * Not Modified for failure of the If-None-Match precondition. This is the
      * desired behaviour for HTTP GET and HTTP HEAD requests.
      *
-     * @return bool 
+     * @param bool $handleAsGET
+     * @return bool
      */
     public function checkPreconditions($handleAsGET = false) {
 
@@ -1708,7 +1766,7 @@ class Sabre_DAV_Server {
             // request succeed if a resource exists at that url.
             try {
                 $node = $this->tree->getNodeForPath($uri);
-            } catch (Sabre_DAV_Exception_FileNotFound $e) {
+            } catch (Sabre_DAV_Exception_NotFound $e) {
                 throw new Sabre_DAV_Exception_PreconditionFailed('An If-Match header was specified and the resource did not exist','If-Match');
             }
 
@@ -1722,7 +1780,7 @@ class Sabre_DAV_Server {
 
                     // Stripping any extra spaces
                     $ifMatchItem = trim($ifMatchItem,' ');
-                    
+
                     $etag = $node->getETag();
                     if ($etag===$ifMatchItem) {
                         $haveMatch = true;
@@ -1744,7 +1802,7 @@ class Sabre_DAV_Server {
             if (!$node) {
                 try {
                     $node = $this->tree->getNodeForPath($uri);
-                } catch (Sabre_DAV_Exception_FileNotFound $e) {
+                } catch (Sabre_DAV_Exception_NotFound $e) {
                     $nodeExists = false;
                 }
             }
@@ -1758,10 +1816,10 @@ class Sabre_DAV_Server {
                     $etag = $node->getETag();
 
                     foreach($ifNoneMatch as $ifNoneMatchItem) {
-                        
+
                         // Stripping any extra spaces
                         $ifNoneMatchItem = trim($ifNoneMatchItem,' ');
-                        
+
                         if ($etag===$ifNoneMatchItem) $haveMatch = true;
 
                     }
@@ -1781,7 +1839,7 @@ class Sabre_DAV_Server {
         }
 
         if (!$ifNoneMatch && ($ifModifiedSince = $this->httpRequest->getHeader('If-Modified-Since'))) {
-            
+
             // The If-Modified-Since header contains a date. We
             // will only return the entity if it has been changed since
             // that date. If it hasn't been changed, we return a 304
@@ -1799,23 +1857,24 @@ class Sabre_DAV_Server {
                     $lastMod = new DateTime('@' . $lastMod);
                     if ($lastMod <= $date) {
                         $this->httpResponse->sendStatus(304);
+                        $this->httpResponse->setHeader('Last-Modified', Sabre_HTTP_Util::toHTTPDate($lastMod));
                         return false;
-                    } 
+                    }
                 }
             }
         }
 
         if ($ifUnmodifiedSince = $this->httpRequest->getHeader('If-Unmodified-Since')) {
-            
+
             // The If-Unmodified-Since will allow allow the request if the
             // entity has not changed since the specified date.
             $date = Sabre_HTTP_Util::parseHTTPDate($ifUnmodifiedSince);
-           
+
             // We must only check the date if it's valid
             if ($date) {
                 if (is_null($node)) {
                     $node = $this->tree->getNodeForPath($uri);
-                }   
+                }
                 $lastMod = $node->getLastModified();
                 if ($lastMod) {
                     $lastMod = new DateTime('@' . $lastMod);
@@ -1830,16 +1889,15 @@ class Sabre_DAV_Server {
 
     }
 
-    // }}} 
-    // {{{ XML Readers & Writers  
-    
-    
+    // }}}
+    // {{{ XML Readers & Writers
+
+
     /**
-     * Generates a WebDAV propfind response body based on a list of nodes 
-     * 
+     * Generates a WebDAV propfind response body based on a list of nodes
+     *
      * @param array $fileProperties The list with nodes
-     * @param array $requestedProperties The properties that should be returned
-     * @return string 
+     * @return string
      */
     public function generateMultiStatus(array $fileProperties) {
 
@@ -1859,7 +1917,7 @@ class Sabre_DAV_Server {
 
             $href = $entry['href'];
             unset($entry['href']);
-            
+
             $response = new Sabre_DAV_Property_Response($href,$entry);
             $response->serialize($this,$multiStatus);
 
@@ -1878,7 +1936,7 @@ class Sabre_DAV_Server {
      * The keys in the returned array contain the property name (e.g.: {DAV:}displayname,
      * and the value contains the property value. If a property is to be removed the value
      * will be null.
-     * 
+     *
      * @param string $body xml body
      * @return array list of properties in need of updating or deletion
      */
@@ -1886,17 +1944,17 @@ class Sabre_DAV_Server {
 
         //We'll need to change the DAV namespace declaration to something else in order to make it parsable
         $dom = Sabre_DAV_XMLUtil::loadDOMDocument($body);
-        
+
         $newProperties = array();
 
         foreach($dom->firstChild->childNodes as $child) {
 
-            if ($child->nodeType !== XML_ELEMENT_NODE) continue; 
+            if ($child->nodeType !== XML_ELEMENT_NODE) continue;
 
             $operation = Sabre_DAV_XMLUtil::toClarkNotation($child);
 
             if ($operation!=='{DAV:}set' && $operation!=='{DAV:}remove') continue;
-            
+
             $innerProperties = Sabre_DAV_XMLUtil::parseProperties($child, $this->propertyMap);
 
             foreach($innerProperties as $propertyName=>$propertyValue) {
@@ -1920,9 +1978,9 @@ class Sabre_DAV_Server {
      *
      * This will either be a list of properties, or an empty array; in which case
      * an {DAV:}allprop was requested.
-     * 
-     * @param string $body 
-     * @return array 
+     *
+     * @param string $body
+     * @return array
      */
     public function parsePropFindRequest($body) {
 
@@ -1931,7 +1989,7 @@ class Sabre_DAV_Server {
 
         $dom = Sabre_DAV_XMLUtil::loadDOMDocument($body);
         $elem = $dom->getElementsByTagNameNS('urn:DAV','propfind')->item(0);
-        return array_keys(Sabre_DAV_XMLUtil::parseProperties($elem)); 
+        return array_keys(Sabre_DAV_XMLUtil::parseProperties($elem));
 
     }
 
diff --git a/3rdparty/Sabre/DAV/ServerPlugin.php b/3rdparty/Sabre/DAV/ServerPlugin.php
index 6909f600c216a169df4a1cee8030d2f205063b6b..131863d13fbf3a9823282d0b9aebb5b7c4e9a760 100644
--- a/3rdparty/Sabre/DAV/ServerPlugin.php
+++ b/3rdparty/Sabre/DAV/ServerPlugin.php
@@ -3,12 +3,12 @@
 /**
  * The baseclass for all server plugins.
  *
- * Plugins can modify or extend the servers behaviour. 
- * 
+ * Plugins can modify or extend the servers behaviour.
+ *
  * @package Sabre
  * @subpackage DAV
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
- * @author Evert Pot (http://www.rooftopsolutions.nl/) 
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
  */
 abstract class Sabre_DAV_ServerPlugin {
@@ -20,18 +20,18 @@ abstract class Sabre_DAV_ServerPlugin {
      * addPlugin is called.
      *
      * This method should set up the requires event subscriptions.
-     * 
-     * @param Sabre_DAV_Server $server 
+     *
+     * @param Sabre_DAV_Server $server
      * @return void
      */
     abstract public function initialize(Sabre_DAV_Server $server);
-    
+
     /**
-     * This method should return a list of server-features. 
+     * This method should return a list of server-features.
      *
      * This is for example 'versioning' and is added to the DAV: header
      * in an OPTIONS response.
-     * 
+     *
      * @return array
      */
     public function getFeatures() {
@@ -44,11 +44,11 @@ abstract class Sabre_DAV_ServerPlugin {
      * Use this method to tell the server this plugin defines additional
      * HTTP methods.
      *
-     * This method is passed a uri. It should only return HTTP methods that are 
+     * This method is passed a uri. It should only return HTTP methods that are
      * available for the specified uri.
      *
      * @param string $uri
-     * @return array 
+     * @return array
      */
     public function getHTTPMethods($uri) {
 
@@ -58,11 +58,11 @@ abstract class Sabre_DAV_ServerPlugin {
 
     /**
      * Returns a plugin name.
-     * 
+     *
      * Using this name other plugins will be able to access other plugins
-     * using Sabre_DAV_Server::getPlugin 
-     * 
-     * @return string 
+     * using Sabre_DAV_Server::getPlugin
+     *
+     * @return string
      */
     public function getPluginName() {
 
@@ -74,11 +74,11 @@ abstract class Sabre_DAV_ServerPlugin {
      * Returns a list of reports this plugin supports.
      *
      * This will be used in the {DAV:}supported-report-set property.
-     * Note that you still need to subscribe to the 'report' event to actually 
-     * implement them 
-     * 
+     * Note that you still need to subscribe to the 'report' event to actually
+     * implement them
+     *
      * @param string $uri
-     * @return array 
+     * @return array
      */
     public function getSupportedReportSet($uri) {
 
diff --git a/3rdparty/Sabre/DAV/SimpleCollection.php b/3rdparty/Sabre/DAV/SimpleCollection.php
index 223d05fed554bbba58ed608b9fdaff4677c9fb14..4acf971caa5c457905b0a02a65bb524e12b59a60 100644
--- a/3rdparty/Sabre/DAV/SimpleCollection.php
+++ b/3rdparty/Sabre/DAV/SimpleCollection.php
@@ -8,23 +8,23 @@
  *
  * @package Sabre
  * @subpackage DAV
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
- * @author Evert Pot (http://www.rooftopsolutions.nl/) 
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
  */
 class Sabre_DAV_SimpleCollection extends Sabre_DAV_Collection {
 
     /**
-     * List of childnodes 
+     * List of childnodes
      *
      * @var array
      */
     protected $children = array();
 
     /**
-     * Name of this resource 
-     * 
-     * @var string 
+     * Name of this resource
+     *
+     * @var string
      */
     protected $name;
 
@@ -33,10 +33,9 @@ class Sabre_DAV_SimpleCollection extends Sabre_DAV_Collection {
      *
      * The name of the node must be passed, child nodes can also be bassed.
      * This nodes must be instances of Sabre_DAV_INode
-     * 
-     * @param string $name 
-     * @param array $children 
-     * @return void
+     *
+     * @param string $name
+     * @param array $children
      */
     public function __construct($name,array $children = array()) {
 
@@ -51,9 +50,9 @@ class Sabre_DAV_SimpleCollection extends Sabre_DAV_Collection {
     }
 
     /**
-     * Adds a new childnode to this collection 
-     * 
-     * @param Sabre_DAV_INode $child 
+     * Adds a new childnode to this collection
+     *
+     * @param Sabre_DAV_INode $child
      * @return void
      */
     public function addChild(Sabre_DAV_INode $child) {
@@ -63,9 +62,9 @@ class Sabre_DAV_SimpleCollection extends Sabre_DAV_Collection {
     }
 
     /**
-     * Returns the name of the collection 
-     * 
-     * @return string 
+     * Returns the name of the collection
+     *
+     * @return string
      */
     public function getName() {
 
@@ -76,24 +75,24 @@ class Sabre_DAV_SimpleCollection extends Sabre_DAV_Collection {
     /**
      * Returns a child object, by its name.
      *
-     * This method makes use of the getChildren method to grab all the child nodes, and compares the name. 
+     * This method makes use of the getChildren method to grab all the child nodes, and compares the name.
      * Generally its wise to override this, as this can usually be optimized
-     * 
+     *
      * @param string $name
-     * @throws Sabre_DAV_Exception_FileNotFound
-     * @return Sabre_DAV_INode 
+     * @throws Sabre_DAV_Exception_NotFound
+     * @return Sabre_DAV_INode
      */
     public function getChild($name) {
 
         if (isset($this->children[$name])) return $this->children[$name];
-        throw new Sabre_DAV_Exception_FileNotFound('File not found: ' . $name . ' in \'' . $this->getName() . '\'');
+        throw new Sabre_DAV_Exception_NotFound('File not found: ' . $name . ' in \'' . $this->getName() . '\'');
 
     }
 
     /**
-     * Returns a list of children for this collection 
-     * 
-     * @return array 
+     * Returns a list of children for this collection
+     *
+     * @return array
      */
     public function getChildren() {
 
diff --git a/3rdparty/Sabre/DAV/SimpleDirectory.php b/3rdparty/Sabre/DAV/SimpleDirectory.php
index 516a3aa907c8d55511e7d15d421baa29e17a1738..621222ebc53a6dbfc4e3b89f1b58288cee7652bc 100644
--- a/3rdparty/Sabre/DAV/SimpleDirectory.php
+++ b/3rdparty/Sabre/DAV/SimpleDirectory.php
@@ -11,8 +11,8 @@
  * @package Sabre
  * @subpackage DAV
  * @deprecated Use Sabre_DAV_SimpleCollection instead.
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
- * @author Evert Pot (http://www.rooftopsolutions.nl/) 
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
  */
 class Sabre_DAV_SimpleDirectory extends Sabre_DAV_SimpleCollection {
diff --git a/3rdparty/Sabre/DAV/SimpleFile.php b/3rdparty/Sabre/DAV/SimpleFile.php
index 304dff1c5ec22f594281cbef96c36f19e4e9d347..58330d6861de476db3dbf879013166c0fd8261da 100644
--- a/3rdparty/Sabre/DAV/SimpleFile.php
+++ b/3rdparty/Sabre/DAV/SimpleFile.php
@@ -3,47 +3,48 @@
 /**
  * SimpleFile
  *
- * The 'SimpleFile' class is used to easily add read-only immutable files to 
- * the directory structure. One usecase would be to add a 'readme.txt' to a 
+ * The 'SimpleFile' class is used to easily add read-only immutable files to
+ * the directory structure. One usecase would be to add a 'readme.txt' to a
  * root of a webserver with some standard content.
  *
  * @package Sabre
  * @subpackage DAV
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
- * @author Evert Pot (http://www.rooftopsolutions.nl/) 
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
  */
 class Sabre_DAV_SimpleFile extends Sabre_DAV_File {
 
     /**
-     * File contents 
+     * File contents
      *
-     * @var string 
+     * @var string
      */
     protected $contents = array();
 
     /**
-     * Name of this resource 
-     * 
-     * @var string 
+     * Name of this resource
+     *
+     * @var string
      */
     protected $name;
 
     /**
      * A mimetype, such as 'text/plain' or 'text/html'
-     * 
-     * @var string 
+     *
+     * @var string
      */
     protected $mimeType;
 
     /**
      * Creates this node
      *
-     * The name of the node must be passed, as well as the contents of the 
+     * The name of the node must be passed, as well as the contents of the
      * file.
-     * 
-     * @param string $name 
-     * @param string $contents 
+     *
+     * @param string $name
+     * @param string $contents
+     * @param string|null $mimeType
      */
     public function __construct($name, $contents, $mimeType = null) {
 
@@ -57,8 +58,8 @@ class Sabre_DAV_SimpleFile extends Sabre_DAV_File {
      * Returns the node name for this file.
      *
      * This name is used to construct the url.
-     * 
-     * @return string 
+     *
+     * @return string
      */
     public function getName() {
 
@@ -67,7 +68,7 @@ class Sabre_DAV_SimpleFile extends Sabre_DAV_File {
     }
 
     /**
-     * Returns the data 
+     * Returns the data
      *
      * This method may either return a string or a readable stream resource
      *
@@ -75,14 +76,14 @@ class Sabre_DAV_SimpleFile extends Sabre_DAV_File {
      */
     public function get() {
 
-        return $this->contents; 
+        return $this->contents;
 
     }
 
     /**
-     * Returns the size of the file, in bytes. 
-     * 
-     * @return int 
+     * Returns the size of the file, in bytes.
+     *
+     * @return int
      */
     public function getSize() {
 
@@ -94,13 +95,14 @@ class Sabre_DAV_SimpleFile extends Sabre_DAV_File {
      * Returns the ETag for a file
      *
      * An ETag is a unique identifier representing the current version of the file. If the file changes, the ETag MUST change.
-     * The ETag is an arbritrary string, but MUST be surrounded by double-quotes.
+     * The ETag is an arbitrary string, but MUST be surrounded by double-quotes.
      *
      * Return null if the ETag can not effectively be determined
+     * @return string
      */
     public function getETag() {
 
-        return '"' . md5($this->contents) . '"'; 
+        return '"' . md5($this->contents) . '"';
 
     }
 
@@ -108,13 +110,12 @@ class Sabre_DAV_SimpleFile extends Sabre_DAV_File {
      * Returns the mime-type for a file
      *
      * If null is returned, we'll assume application/octet-stream
-     */ 
+     * @return string
+     */
     public function getContentType() {
 
-        return $this->mimeType; 
+        return $this->mimeType;
 
     }
 
 }
-
-?>
diff --git a/3rdparty/Sabre/DAV/StringUtil.php b/3rdparty/Sabre/DAV/StringUtil.php
index 440cf6866ca6a68d5b8e7f2356342db961468b27..b126a94c82579b7b7602324632c8b368e7d275da 100644
--- a/3rdparty/Sabre/DAV/StringUtil.php
+++ b/3rdparty/Sabre/DAV/StringUtil.php
@@ -3,14 +3,14 @@
 /**
  * String utility
  *
- * This class is mainly used to implement the 'text-match' filter, used by both 
- * the CalDAV calendar-query REPORT, and CardDAV addressbook-query REPORT. 
+ * This class is mainly used to implement the 'text-match' filter, used by both
+ * the CalDAV calendar-query REPORT, and CardDAV addressbook-query REPORT.
  * Because they both need it, it was decided to put it in Sabre_DAV instead.
- * 
+ *
  * @package Sabre
  * @subpackage DAV
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
- * @author Evert Pot (http://www.rooftopsolutions.nl/) 
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
  */
 class Sabre_DAV_StringUtil {
@@ -18,11 +18,11 @@ class Sabre_DAV_StringUtil {
     /**
      * Checks if a needle occurs in a haystack ;)
      *
-     * @param string $haystack 
-     * @param string $needle 
-     * @param string $collation 
-     * @param string $matchType 
-     * @return bool 
+     * @param string $haystack
+     * @param string $needle
+     * @param string $collation
+     * @param string $matchType
+     * @return bool
      */
     static public function textMatch($haystack, $needle, $collation, $matchType = 'contains') {
 
@@ -37,7 +37,7 @@ class Sabre_DAV_StringUtil {
 
             case 'i;octet' :
                 // Do nothing
-                break; 
+                break;
 
             case 'i;unicode-casemap' :
                 $haystack = mb_strtoupper($haystack, 'UTF-8');
@@ -63,18 +63,18 @@ class Sabre_DAV_StringUtil {
                 throw new Sabre_DAV_Exception_BadRequest('Match-type: ' . $matchType . ' is not supported');
 
         }
-        
+
     }
 
     /**
-     * This method takes an input string, checks if it's not valid UTF-8 and 
+     * This method takes an input string, checks if it's not valid UTF-8 and
      * attempts to convert it to UTF-8 if it's not.
      *
-     * Note that currently this can only convert ISO-8559-1 to UTF-8 (latin-1), 
+     * Note that currently this can only convert ISO-8559-1 to UTF-8 (latin-1),
      * anything else will likely fail.
      *
-     * @param string $input 
-     * @return string 
+     * @param string $input
+     * @return string
      */
     static public function ensureUTF8($input) {
 
@@ -84,7 +84,7 @@ class Sabre_DAV_StringUtil {
             return utf8_encode($input);
         } else {
             return $input;
-        } 
+        }
 
     }
 
diff --git a/3rdparty/Sabre/DAV/TemporaryFileFilterPlugin.php b/3rdparty/Sabre/DAV/TemporaryFileFilterPlugin.php
index e8276af5613c7815c40be5a308f10c3de52a912b..36096e677752e61fc1b62e53f3caf64c47e131aa 100644
--- a/3rdparty/Sabre/DAV/TemporaryFileFilterPlugin.php
+++ b/3rdparty/Sabre/DAV/TemporaryFileFilterPlugin.php
@@ -22,8 +22,8 @@
  *
  * @package Sabre
  * @subpackage DAV
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
- * @author Evert Pot (http://www.rooftopsolutions.nl/) 
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
  */
 class Sabre_DAV_TemporaryFileFilterPlugin extends Sabre_DAV_ServerPlugin {
@@ -31,7 +31,7 @@ class Sabre_DAV_TemporaryFileFilterPlugin extends Sabre_DAV_ServerPlugin {
     /**
      * This is the list of patterns we intercept.
      * If new patterns are added, they must be valid patterns for preg_match.
-     * 
+     *
      * @var array
      */
     public $temporaryFilePatterns = array(
@@ -43,19 +43,19 @@ class Sabre_DAV_TemporaryFileFilterPlugin extends Sabre_DAV_ServerPlugin {
         '/^\.dat(.*)$/',   // Smultron seems to create these
         '/^~lock.(.*)#$/', // Windows 7 lockfiles
     );
-    
+
     /**
      * This is the directory where this plugin
      * will store it's files.
-     * 
-     * @var string 
+     *
+     * @var string
      */
     private $dataDir;
 
     /**
      * A reference to the main Server class
-     * 
-     * @var Sabre_DAV_Server 
+     *
+     * @var Sabre_DAV_Server
      */
     private $server;
 
@@ -65,9 +65,8 @@ class Sabre_DAV_TemporaryFileFilterPlugin extends Sabre_DAV_ServerPlugin {
      * Make sure you specify a directory for your files. If you don't, we
      * will use PHP's directory for session-storage instead, and you might
      * not want that.
-     * 
-     * @param string $dataDir 
-     * @return void
+     *
+     * @param string|null $dataDir
      */
     public function __construct($dataDir = null) {
 
@@ -75,15 +74,15 @@ class Sabre_DAV_TemporaryFileFilterPlugin extends Sabre_DAV_ServerPlugin {
         if (!is_dir($dataDir)) mkdir($dataDir);
         $this->dataDir = $dataDir;
 
-    } 
+    }
 
     /**
      * Initialize the plugin
      *
      * This is called automatically be the Server class after this plugin is
      * added with Sabre_DAV_Server::addPlugin()
-     * 
-     * @param Sabre_DAV_Server $server 
+     *
+     * @param Sabre_DAV_Server $server
      * @return void
      */
     public function initialize(Sabre_DAV_Server $server) {
@@ -97,11 +96,12 @@ class Sabre_DAV_TemporaryFileFilterPlugin extends Sabre_DAV_ServerPlugin {
     /**
      * This method is called before any HTTP method handler
      *
-     * This method intercepts any GET, DELETE, PUT and PROPFIND calls to 
+     * This method intercepts any GET, DELETE, PUT and PROPFIND calls to
      * filenames that are known to match the 'temporary file' regex.
-     * 
-     * @param string $method 
-     * @return bool 
+     *
+     * @param string $method
+     * @param string $uri
+     * @return bool
      */
     public function beforeMethod($method, $uri) {
 
@@ -125,33 +125,33 @@ class Sabre_DAV_TemporaryFileFilterPlugin extends Sabre_DAV_ServerPlugin {
     /**
      * This method is invoked if some subsystem creates a new file.
      *
-     * This is used to deal with HTTP LOCK requests which create a new 
+     * This is used to deal with HTTP LOCK requests which create a new
      * file.
-     * 
-     * @param string $uri 
-     * @param resource $data 
-     * @return bool 
+     *
+     * @param string $uri
+     * @param resource $data
+     * @return bool
      */
     public function beforeCreateFile($uri,$data) {
 
         if ($tempPath = $this->isTempFile($uri)) {
-            
+
             $hR = $this->server->httpResponse;
             $hR->setHeader('X-Sabre-Temp','true');
             file_put_contents($tempPath,$data);
             return false;
         }
-        return true; 
+        return true;
 
     }
 
     /**
      * This method will check if the url matches the temporary file pattern
-     * if it does, it will return an path based on $this->dataDir for the 
+     * if it does, it will return an path based on $this->dataDir for the
      * temporary file storage.
-     * 
-     * @param string $path 
-     * @return boolean|string 
+     *
+     * @param string $path
+     * @return boolean|string
      */
     protected function isTempFile($path) {
 
@@ -161,7 +161,7 @@ class Sabre_DAV_TemporaryFileFilterPlugin extends Sabre_DAV_ServerPlugin {
         foreach($this->temporaryFilePatterns as $tempFile) {
 
             if (preg_match($tempFile,$tempPath)) {
-                return $this->dataDir . '/sabredav_' . md5($path) . '.tempfile';
+                return $this->getDataDir() . '/sabredav_' . md5($path) . '.tempfile';
             }
 
         }
@@ -175,9 +175,9 @@ class Sabre_DAV_TemporaryFileFilterPlugin extends Sabre_DAV_ServerPlugin {
      * This method handles the GET method for temporary files.
      * If the file doesn't exist, it will return false which will kick in
      * the regular system for the GET method.
-     * 
-     * @param string $tempLocation 
-     * @return bool 
+     *
+     * @param string $tempLocation
+     * @return bool
      */
     public function httpGet($tempLocation) {
 
@@ -195,9 +195,9 @@ class Sabre_DAV_TemporaryFileFilterPlugin extends Sabre_DAV_ServerPlugin {
 
     /**
      * This method handles the PUT method.
-     * 
-     * @param string $tempLocation 
-     * @return bool 
+     *
+     * @param string $tempLocation
+     * @return bool
      */
     public function httpPut($tempLocation) {
 
@@ -205,7 +205,7 @@ class Sabre_DAV_TemporaryFileFilterPlugin extends Sabre_DAV_ServerPlugin {
         $hR->setHeader('X-Sabre-Temp','true');
 
         $newFile = !file_exists($tempLocation);
-       
+
         if (!$newFile && ($this->server->httpRequest->getHeader('If-None-Match'))) {
              throw new Sabre_DAV_Exception_PreconditionFailed('The resource already exists, and an If-None-Match header was supplied');
         }
@@ -219,11 +219,11 @@ class Sabre_DAV_TemporaryFileFilterPlugin extends Sabre_DAV_ServerPlugin {
     /**
      * This method handles the DELETE method.
      *
-     * If the file didn't exist, it will return false, which will make the 
+     * If the file didn't exist, it will return false, which will make the
      * standard HTTP DELETE handler kick in.
-     * 
-     * @param string $tempLocation 
-     * @return bool 
+     *
+     * @param string $tempLocation
+     * @return bool
      */
     public function httpDelete($tempLocation) {
 
@@ -238,25 +238,26 @@ class Sabre_DAV_TemporaryFileFilterPlugin extends Sabre_DAV_ServerPlugin {
     }
 
     /**
-     * This method handles the PROPFIND method. 
+     * This method handles the PROPFIND method.
      *
      * It's a very lazy method, it won't bother checking the request body
      * for which properties were requested, and just sends back a default
      * set of properties.
      *
-     * @param string $tempLocation 
-     * @return void
+     * @param string $tempLocation
+     * @param string $uri
+     * @return bool
      */
     public function httpPropfind($tempLocation, $uri) {
 
         if (!file_exists($tempLocation)) return true;
-       
+
         $hR = $this->server->httpResponse;
         $hR->setHeader('X-Sabre-Temp','true');
         $hR->sendStatus(207);
         $hR->setHeader('Content-Type','application/xml; charset=utf-8');
 
-        $requestedProps = $this->server->parsePropFindRequest($this->server->httpRequest->getBody(true)); 
+        $this->server->parsePropFindRequest($this->server->httpRequest->getBody(true));
 
         $properties = array(
             'href' => $uri,
@@ -264,7 +265,7 @@ class Sabre_DAV_TemporaryFileFilterPlugin extends Sabre_DAV_ServerPlugin {
                 '{DAV:}getlastmodified' => new Sabre_DAV_Property_GetLastModified(filemtime($tempLocation)),
                 '{DAV:}getcontentlength' => filesize($tempLocation),
                 '{DAV:}resourcetype' => new Sabre_DAV_Property_ResourceType(null),
-                '{'.Sabre_DAV_Server::NS_SABREDAV.'}tempFile' => true, 
+                '{'.Sabre_DAV_Server::NS_SABREDAV.'}tempFile' => true,
 
             ),
          );
@@ -276,4 +277,13 @@ class Sabre_DAV_TemporaryFileFilterPlugin extends Sabre_DAV_ServerPlugin {
     }
 
 
+    /**
+     * This method returns the directory where the temporary files should be stored.
+     *
+     * @return string
+     */
+    protected function getDataDir()
+    {
+        return $this->dataDir;
+    }
 }
diff --git a/3rdparty/Sabre/DAV/Tree.php b/3rdparty/Sabre/DAV/Tree.php
index 98e6f62c9e588cb5462408884b1bbd9206abde3d..502163941555d209837c3dee0c59b76981d72ab4 100644
--- a/3rdparty/Sabre/DAV/Tree.php
+++ b/3rdparty/Sabre/DAV/Tree.php
@@ -1,34 +1,34 @@
 <?php
 
 /**
- * Abstract tree object 
- * 
+ * Abstract tree object
+ *
  * @package Sabre
  * @subpackage DAV
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
- * @author Evert Pot (http://www.rooftopsolutions.nl/) 
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
  */
 abstract class Sabre_DAV_Tree {
-    
+
     /**
      * This function must return an INode object for a path
-     * If a Path doesn't exist, thrown an Exception_FileNotFound
-     * 
-     * @param string $path 
-     * @throws Exception_FileNotFound
-     * @return Sabre_DAV_INode 
+     * If a Path doesn't exist, thrown a Exception_NotFound
+     *
+     * @param string $path
+     * @throws Sabre_DAV_Exception_NotFound
+     * @return Sabre_DAV_INode
      */
     abstract function getNodeForPath($path);
 
     /**
      * This function allows you to check if a node exists.
      *
-     * Implementors of this class should override this method to make 
+     * Implementors of this class should override this method to make
      * it cheaper.
-     * 
-     * @param string $path 
-     * @return bool 
+     *
+     * @param string $path
+     * @return bool
      */
     public function nodeExists($path) {
 
@@ -37,7 +37,7 @@ abstract class Sabre_DAV_Tree {
             $this->getNodeForPath($path);
             return true;
 
-        } catch (Sabre_DAV_Exception_FileNotFound $e) {
+        } catch (Sabre_DAV_Exception_NotFound $e) {
 
             return false;
 
@@ -50,12 +50,12 @@ abstract class Sabre_DAV_Tree {
      *
      * @param string $sourcePath The source location
      * @param string $destinationPath The full destination path
-     * @return void 
+     * @return void
      */
     public function copy($sourcePath, $destinationPath) {
 
         $sourceNode = $this->getNodeForPath($sourcePath);
-       
+
         // grab the dirname and basename components
         list($destinationDir, $destinationName) = Sabre_DAV_URLUtil::splitPath($destinationPath);
 
@@ -67,9 +67,9 @@ abstract class Sabre_DAV_Tree {
     }
 
     /**
-     * Moves a file from one location to another 
-     * 
-     * @param string $sourcePath The path to the file which should be moved 
+     * Moves a file from one location to another
+     *
+     * @param string $sourcePath The path to the file which should be moved
      * @param string $destinationPath The full destination path, so not just the destination parent node
      * @return int
      */
@@ -91,26 +91,26 @@ abstract class Sabre_DAV_Tree {
     }
 
     /**
-     * Deletes a node from the tree 
-     * 
-     * @param string $path 
+     * Deletes a node from the tree
+     *
+     * @param string $path
      * @return void
      */
     public function delete($path) {
 
         $node = $this->getNodeForPath($path);
         $node->delete();
-        
+
         list($parent) = Sabre_DAV_URLUtil::splitPath($path);
         $this->markDirty($parent);
 
     }
 
     /**
-     * Returns a list of childnodes for a given path. 
-     * 
-     * @param string $path 
-     * @return array 
+     * Returns a list of childnodes for a given path.
+     *
+     * @param string $path
+     * @return array
      */
     public function getChildren($path) {
 
@@ -127,14 +127,14 @@ abstract class Sabre_DAV_Tree {
      *   * node creations
      *   * copy
      *   * move
-     *   * renaming nodes 
-     * 
+     *   * renaming nodes
+     *
      * If Tree classes implement a form of caching, this will allow
      * them to make sure caches will be expired.
-     * 
+     *
      * If a path is passed, it is assumed that the entire subtree is dirty
      *
-     * @param string $path 
+     * @param string $path
      * @return void
      */
     public function markDirty($path) {
@@ -143,10 +143,11 @@ abstract class Sabre_DAV_Tree {
     }
 
     /**
-     * copyNode 
-     * 
-     * @param Sabre_DAV_INode $source 
-     * @param Sabre_DAV_ICollection $destination 
+     * copyNode
+     *
+     * @param Sabre_DAV_INode $source
+     * @param Sabre_DAV_ICollection $destinationParent
+     * @param string $destinationName
      * @return void
      */
     protected function copyNode(Sabre_DAV_INode $source,Sabre_DAV_ICollection $destinationParent,$destinationName = null) {
@@ -163,14 +164,14 @@ abstract class Sabre_DAV_Tree {
                 fwrite($stream,$data);
                 rewind($stream);
                 $data = $stream;
-            } 
+            }
             $destinationParent->createFile($destinationName,$data);
             $destination = $destinationParent->getChild($destinationName);
 
         } elseif ($source instanceof Sabre_DAV_ICollection) {
 
             $destinationParent->createDirectory($destinationName);
-            
+
             $destination = $destinationParent->getChild($destinationName);
             foreach($source->getChildren() as $child) {
 
diff --git a/3rdparty/Sabre/DAV/Tree/Filesystem.php b/3rdparty/Sabre/DAV/Tree/Filesystem.php
index 5c611047e073fd4c2642babf24696517c53b2201..85a9ee317be3c43daa2495908e2800d119ddc11c 100644
--- a/3rdparty/Sabre/DAV/Tree/Filesystem.php
+++ b/3rdparty/Sabre/DAV/Tree/Filesystem.php
@@ -1,12 +1,12 @@
 <?php
 
 /**
- * Sabre_DAV_Tree_Filesystem 
- * 
+ * Sabre_DAV_Tree_Filesystem
+ *
  * @package Sabre
  * @subpackage DAV
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
- * @author Evert Pot (http://www.rooftopsolutions.nl/) 
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
  */
 class Sabre_DAV_Tree_Filesystem extends Sabre_DAV_Tree {
@@ -14,7 +14,7 @@ class Sabre_DAV_Tree_Filesystem extends Sabre_DAV_Tree {
     /**
      * Base url on the filesystem.
      *
-     * @var string 
+     * @var string
      */
     protected $basePath;
 
@@ -22,9 +22,8 @@ class Sabre_DAV_Tree_Filesystem extends Sabre_DAV_Tree {
      * Creates this tree
      *
      * Supply the path you'd like to share.
-     * 
-     * @param string $basePath 
-     * @return void
+     *
+     * @param string $basePath
      */
     public function __construct($basePath) {
 
@@ -33,16 +32,16 @@ class Sabre_DAV_Tree_Filesystem extends Sabre_DAV_Tree {
     }
 
     /**
-     * Returns a new node for the given path 
-     * 
-     * @param string $path 
-     * @return void
+     * Returns a new node for the given path
+     *
+     * @param string $path
+     * @return Sabre_DAV_FS_Node
      */
     public function getNodeForPath($path) {
 
         $realPath = $this->getRealPath($path);
-        if (!file_exists($realPath)) throw new Sabre_DAV_Exception_FileNotFound('File at location ' . $realPath . ' not found');
-        if (is_dir($realPath)) { 
+        if (!file_exists($realPath)) throw new Sabre_DAV_Exception_NotFound('File at location ' . $realPath . ' not found');
+        if (is_dir($realPath)) {
             return new Sabre_DAV_FS_Directory($path);
         } else {
             return new Sabre_DAV_FS_File($path);
@@ -51,10 +50,10 @@ class Sabre_DAV_Tree_Filesystem extends Sabre_DAV_Tree {
     }
 
     /**
-     * Returns the real filesystem path for a webdav url. 
-     * 
-     * @param string $publicPath 
-     * @return string 
+     * Returns the real filesystem path for a webdav url.
+     *
+     * @param string $publicPath
+     * @return string
      */
     protected function getRealPath($publicPath) {
 
@@ -67,24 +66,24 @@ class Sabre_DAV_Tree_Filesystem extends Sabre_DAV_Tree {
      *
      * This method must work recursively and delete the destination
      * if it exists
-     * 
-     * @param string $source 
-     * @param string $destination 
+     *
+     * @param string $source
+     * @param string $destination
      * @return void
      */
     public function copy($source,$destination) {
 
         $source = $this->getRealPath($source);
         $destination = $this->getRealPath($destination);
-        $this->realCopy($source,$destination); 
+        $this->realCopy($source,$destination);
 
     }
 
     /**
-     * Used by self::copy 
-     * 
-     * @param string $source 
-     * @param string $destination 
+     * Used by self::copy
+     *
+     * @param string $source
+     * @param string $destination
      * @return void
      */
     protected function realCopy($source,$destination) {
@@ -107,9 +106,9 @@ class Sabre_DAV_Tree_Filesystem extends Sabre_DAV_Tree {
      * Moves a file or directory recursively.
      *
      * If the destination exists, delete it first.
-     * 
-     * @param string $source 
-     * @param string $destination 
+     *
+     * @param string $source
+     * @param string $destination
      * @return void
      */
     public function move($source,$destination) {
diff --git a/3rdparty/Sabre/DAV/URLUtil.php b/3rdparty/Sabre/DAV/URLUtil.php
index 8f38749264b1f5e3c5b87ec0195f05aa749dbee2..794665a44f68b0ef8fe9d8c7a15adc6841405fe3 100644
--- a/3rdparty/Sabre/DAV/URLUtil.php
+++ b/3rdparty/Sabre/DAV/URLUtil.php
@@ -11,11 +11,11 @@
  * Specifically, it was found that GVFS (gnome's webdav client) does not like encoding of ( and
  * ). Since these are reserved, but don't have a reserved meaning in url, these characters are
  * kept as-is.
- * 
+ *
  * @package Sabre
  * @subpackage DAV
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
- * @author Evert Pot (http://www.rooftopsolutions.nl/) 
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
  */
 class Sabre_DAV_URLUtil {
@@ -24,46 +24,42 @@ class Sabre_DAV_URLUtil {
      * Encodes the path of a url.
      *
      * slashes (/) are treated as path-separators.
-     * 
-     * @param string $path 
-     * @return string 
+     *
+     * @param string $path
+     * @return string
      */
     static function encodePath($path) {
 
-    	$valid_chars = '/ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-.~()';
-        $newStr = '';
-        for( $i=0; isset($path[$i]); ++$i ) {
-            if( strpos($valid_chars,($c=$path[$i]))===false ) $newStr .= '%'.sprintf('%02x',ord($c));
-            else $newStr .= $c;
-        }
-        return $newStr;
-    	
+        return preg_replace_callback('/([^A-Za-z0-9_\-\.~\(\)\/])/',function($match) {
+
+            return '%'.sprintf('%02x',ord($match[0]));
+
+        }, $path);
+
     }
 
     /**
      * Encodes a 1 segment of a path
      *
      * Slashes are considered part of the name, and are encoded as %2f
-     * 
-     * @param string $pathSegment 
-     * @return string 
+     *
+     * @param string $pathSegment
+     * @return string
      */
     static function encodePathSegment($pathSegment) {
 
-    	$valid_chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-.~()';
-        $newStr = '';
-        for( $i=0; isset($pathSegment[$i]); ++$i ) {
-            if( strpos($valid_chars,($c=$pathSegment[$i]))===false ) $newStr .= '%'.sprintf('%02x',ord($c));
-            else $newStr .= $c;
-        }
-        return $newStr;
+        return preg_replace_callback('/([^A-Za-z0-9_\-\.~\(\)])/',function($match) {
+
+            return '%'.sprintf('%02x',ord($match[0]));
+
+        }, $pathSegment);
     }
 
     /**
      * Decodes a url-encoded path
      *
-     * @param string $path 
-     * @return string 
+     * @param string $path
+     * @return string
      */
     static function decodePath($path) {
 
@@ -74,17 +70,17 @@ class Sabre_DAV_URLUtil {
     /**
      * Decodes a url-encoded path segment
      *
-     * @param string $path 
-     * @return string 
+     * @param string $path
+     * @return string
      */
     static function decodePathSegment($path) {
 
-        $path = urldecode($path);
+        $path = rawurldecode($path);
         $encoding = mb_detect_encoding($path, array('UTF-8','ISO-8859-1'));
 
         switch($encoding) {
 
-            case 'ISO-8859-1' : 
+            case 'ISO-8859-1' :
                 $path = utf8_encode($path);
 
         }
@@ -94,7 +90,7 @@ class Sabre_DAV_URLUtil {
     }
 
     /**
-     * Returns the 'dirname' and 'basename' for a path. 
+     * Returns the 'dirname' and 'basename' for a path.
      *
      * The reason there is a custom function for this purpose, is because
      * basename() is locale aware (behaviour changes if C locale or a UTF-8 locale is used)
@@ -108,8 +104,8 @@ class Sabre_DAV_URLUtil {
      * If there is no dirname, it will return an empty string. Any / appearing at the end of the
      * string is stripped off.
      *
-     * @param string $path 
-     * @return array 
+     * @param string $path
+     * @return array
      */
     static function splitPath($path) {
 
diff --git a/3rdparty/Sabre/DAV/UUIDUtil.php b/3rdparty/Sabre/DAV/UUIDUtil.php
index e42a536ad8a3feff157c8c2cebec4be534d30967..f0eebe598e5d74d0d61e403e26a9d66adaf3eecb 100644
--- a/3rdparty/Sabre/DAV/UUIDUtil.php
+++ b/3rdparty/Sabre/DAV/UUIDUtil.php
@@ -4,13 +4,13 @@
  * UUID Utility
  *
  * This class has static methods to generate and validate UUID's.
- * UUIDs are used a decent amount within various *DAV standards, so it made 
+ * UUIDs are used a decent amount within various *DAV standards, so it made
  * sense to include it.
- * 
+ *
  * @package Sabre
  * @subpackage DAV
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
- * @author Evert Pot (http://www.rooftopsolutions.nl/) 
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
  */
 class Sabre_DAV_UUIDUtil {
@@ -18,10 +18,10 @@ class Sabre_DAV_UUIDUtil {
     /**
      * Returns a pseudo-random v4 UUID
      *
-     * This function is based on a comment by Andrew Moore on php.net 
-     * 
+     * This function is based on a comment by Andrew Moore on php.net
+     *
      * @see http://www.php.net/manual/en/function.uniqid.php#94959
-     * @return void
+     * @return string
      */
     static function getUUID() {
 
@@ -48,9 +48,9 @@ class Sabre_DAV_UUIDUtil {
 
     /**
      * Checks if a string is a valid UUID.
-     * 
-     * @param string $uuid 
-     * @return bool 
+     *
+     * @param string $uuid
+     * @return bool
      */
     static function validateUUID($uuid) {
 
diff --git a/3rdparty/Sabre/DAV/Version.php b/3rdparty/Sabre/DAV/Version.php
index 6bece1985e4e9706b7a7e41f1b738a61672e7b73..5e5d15e40397e700ab6d821c7862b3a7a026f9e5 100644
--- a/3rdparty/Sabre/DAV/Version.php
+++ b/3rdparty/Sabre/DAV/Version.php
@@ -2,10 +2,10 @@
 
 /**
  * This class contains the SabreDAV version constants.
- * 
+ *
  * @package Sabre
  * @subpackage DAV
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
  * @author Evert Pot (http://www.rooftopsolutions.nl/)
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
  */
@@ -14,7 +14,7 @@ class Sabre_DAV_Version {
     /**
      * Full version number
      */
-    const VERSION = '1.5.4';
+    const VERSION = '1.6.2';
 
     /**
      * Stability : alpha, beta, stable
diff --git a/3rdparty/Sabre/DAV/XMLUtil.php b/3rdparty/Sabre/DAV/XMLUtil.php
index bd05be4b2297b77e36c47d62904ff964617a0516..60eff3b159ac15bf34a4f09fd0f2d7a721542785 100644
--- a/3rdparty/Sabre/DAV/XMLUtil.php
+++ b/3rdparty/Sabre/DAV/XMLUtil.php
@@ -2,32 +2,32 @@
 
 /**
  * XML utilities for WebDAV
- * 
+ *
  * @package Sabre
  * @subpackage DAV
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
- * @author Evert Pot (http://www.rooftopsolutions.nl/) 
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
  */
 class Sabre_DAV_XMLUtil {
 
     /**
      * Returns the 'clark notation' for an element.
-     * 
+     *
      * For example, and element encoded as:
      * <b:myelem xmlns:b="http://www.example.org/" />
      * will be returned as:
      * {http://www.example.org}myelem
      *
      * This format is used throughout the SabreDAV sourcecode.
-     * Elements encoded with the urn:DAV namespace will 
+     * Elements encoded with the urn:DAV namespace will
      * be returned as if they were in the DAV: namespace. This is to avoid
      * compatibility problems.
      *
      * This function will return null if a nodetype other than an Element is passed.
      *
-     * @param DOMElement $dom 
-     * @return string 
+     * @param DOMNode $dom
+     * @return string
      */
     static function toClarkNotation(DOMNode $dom) {
 
@@ -35,21 +35,21 @@ class Sabre_DAV_XMLUtil {
 
         // Mapping back to the real namespace, in case it was dav
         if ($dom->namespaceURI=='urn:DAV') $ns = 'DAV:'; else $ns = $dom->namespaceURI;
-        
+
         // Mapping to clark notation
         return '{' . $ns . '}' . $dom->localName;
 
     }
 
     /**
-     * Parses a clark-notation string, and returns the namespace and element 
+     * Parses a clark-notation string, and returns the namespace and element
      * name components.
      *
      * If the string was invalid, it will throw an InvalidArgumentException.
-     * 
+     *
      * @param string $str
-     * @throws InvalidArgumentException 
-     * @return array 
+     * @throws InvalidArgumentException
+     * @return array
      */
     static function parseClarkNotation($str) {
 
@@ -70,6 +70,9 @@ class Sabre_DAV_XMLUtil {
      *
      * This is unfortunately needed, because the DAV: namespace violates the xml namespaces
      * spec, and causes the DOM to throw errors
+     *
+     * @param string $xmlDocument
+     * @return array|string|null
      */
     static function convertDAVNamespace($xmlDocument) {
 
@@ -83,17 +86,17 @@ class Sabre_DAV_XMLUtil {
      * This method provides a generic way to load a DOMDocument for WebDAV use.
      *
      * This method throws a Sabre_DAV_Exception_BadRequest exception for any xml errors.
-     * It does not preserve whitespace, and it converts the DAV: namespace to urn:DAV. 
-     * 
+     * It does not preserve whitespace, and it converts the DAV: namespace to urn:DAV.
+     *
      * @param string $xml
-     * @throws Sabre_DAV_Exception_BadRequest 
-     * @return DOMDocument 
+     * @throws Sabre_DAV_Exception_BadRequest
+     * @return DOMDocument
      */
     static function loadDOMDocument($xml) {
 
         if (empty($xml))
             throw new Sabre_DAV_Exception_BadRequest('Empty XML document sent');
-       
+
         // The BitKinex client sends xml documents as UTF-16. PHP 5.3.1 (and presumably lower)
         // does not support this, so we must intercept this and convert to UTF-8.
         if (substr($xml,0,12) === "\x3c\x00\x3f\x00\x78\x00\x6d\x00\x6c\x00\x20\x00") {
@@ -111,7 +114,7 @@ class Sabre_DAV_XMLUtil {
         // Retaining old error setting
         $oldErrorSetting =  libxml_use_internal_errors(true);
 
-        // Clearing any previous errors 
+        // Clearing any previous errors
         libxml_clear_errors();
 
         $dom = new DOMDocument();
@@ -135,7 +138,7 @@ class Sabre_DAV_XMLUtil {
     /**
      * Parses all WebDAV properties out of a DOM Element
      *
-     * Generally WebDAV properties are encloded in {DAV:}prop elements. This
+     * Generally WebDAV properties are enclosed in {DAV:}prop elements. This
      * method helps by going through all these and pulling out the actual
      * propertynames, making them array keys and making the property values,
      * well.. the array values.
@@ -145,7 +148,7 @@ class Sabre_DAV_XMLUtil {
      *
      * Complex values are supported through the propertyMap argument. The
      * propertyMap should have the clark-notation properties as it's keys, and
-     * classnames as values. 
+     * classnames as values.
      *
      * When any of these properties are found, the unserialize() method will be
      * (statically) called. The result of this method is used as the value.
@@ -168,7 +171,7 @@ class Sabre_DAV_XMLUtil {
 
                 $propertyName = Sabre_DAV_XMLUtil::toClarkNotation($propNodeData);
                 if (isset($propertyMap[$propertyName])) {
-                    $propList[$propertyName] = call_user_func(array($propertyMap[$propertyName],'unserialize'),$propNodeData); 
+                    $propList[$propertyName] = call_user_func(array($propertyMap[$propertyName],'unserialize'),$propNodeData);
                 } else {
                     $propList[$propertyName] = $propNodeData->textContent;
                 }
diff --git a/3rdparty/Sabre/DAV/includes.php b/3rdparty/Sabre/DAV/includes.php
new file mode 100644
index 0000000000000000000000000000000000000000..6a4890677ea2bdad500410eae9e47ee89f6b914e
--- /dev/null
+++ b/3rdparty/Sabre/DAV/includes.php
@@ -0,0 +1,97 @@
+<?php
+
+/**
+ * Sabre_DAV includes file
+ *
+ * Including this file will automatically include all files from the Sabre_DAV
+ * package.
+ *
+ * This often allows faster loadtimes, as autoload-speed is often quite slow.
+ *
+ * @package Sabre
+ * @subpackage DAV
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
+ * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
+ */
+
+// Begin includes
+include __DIR__ . '/Auth/IBackend.php';
+include __DIR__ . '/Client.php';
+include __DIR__ . '/Exception.php';
+include __DIR__ . '/INode.php';
+include __DIR__ . '/IProperties.php';
+include __DIR__ . '/Locks/Backend/Abstract.php';
+include __DIR__ . '/Locks/Backend/File.php';
+include __DIR__ . '/Locks/Backend/FS.php';
+include __DIR__ . '/Locks/Backend/PDO.php';
+include __DIR__ . '/Locks/LockInfo.php';
+include __DIR__ . '/Node.php';
+include __DIR__ . '/Property/IHref.php';
+include __DIR__ . '/Property.php';
+include __DIR__ . '/Server.php';
+include __DIR__ . '/ServerPlugin.php';
+include __DIR__ . '/StringUtil.php';
+include __DIR__ . '/TemporaryFileFilterPlugin.php';
+include __DIR__ . '/Tree.php';
+include __DIR__ . '/URLUtil.php';
+include __DIR__ . '/UUIDUtil.php';
+include __DIR__ . '/Version.php';
+include __DIR__ . '/XMLUtil.php';
+include __DIR__ . '/Auth/Backend/AbstractBasic.php';
+include __DIR__ . '/Auth/Backend/AbstractDigest.php';
+include __DIR__ . '/Auth/Backend/Apache.php';
+include __DIR__ . '/Auth/Backend/File.php';
+include __DIR__ . '/Auth/Backend/PDO.php';
+include __DIR__ . '/Auth/Plugin.php';
+include __DIR__ . '/Browser/GuessContentType.php';
+include __DIR__ . '/Browser/MapGetToPropFind.php';
+include __DIR__ . '/Browser/Plugin.php';
+include __DIR__ . '/Exception/BadRequest.php';
+include __DIR__ . '/Exception/Conflict.php';
+include __DIR__ . '/Exception/Forbidden.php';
+include __DIR__ . '/Exception/InsufficientStorage.php';
+include __DIR__ . '/Exception/InvalidResourceType.php';
+include __DIR__ . '/Exception/Locked.php';
+include __DIR__ . '/Exception/LockTokenMatchesRequestUri.php';
+include __DIR__ . '/Exception/MethodNotAllowed.php';
+include __DIR__ . '/Exception/NotAuthenticated.php';
+include __DIR__ . '/Exception/NotFound.php';
+include __DIR__ . '/Exception/NotImplemented.php';
+include __DIR__ . '/Exception/PaymentRequired.php';
+include __DIR__ . '/Exception/PreconditionFailed.php';
+include __DIR__ . '/Exception/ReportNotImplemented.php';
+include __DIR__ . '/Exception/RequestedRangeNotSatisfiable.php';
+include __DIR__ . '/Exception/UnsupportedMediaType.php';
+include __DIR__ . '/FS/Node.php';
+include __DIR__ . '/FSExt/Node.php';
+include __DIR__ . '/ICollection.php';
+include __DIR__ . '/IExtendedCollection.php';
+include __DIR__ . '/IFile.php';
+include __DIR__ . '/IQuota.php';
+include __DIR__ . '/Locks/Plugin.php';
+include __DIR__ . '/Mount/Plugin.php';
+include __DIR__ . '/ObjectTree.php';
+include __DIR__ . '/Property/GetLastModified.php';
+include __DIR__ . '/Property/Href.php';
+include __DIR__ . '/Property/HrefList.php';
+include __DIR__ . '/Property/LockDiscovery.php';
+include __DIR__ . '/Property/ResourceType.php';
+include __DIR__ . '/Property/Response.php';
+include __DIR__ . '/Property/ResponseList.php';
+include __DIR__ . '/Property/SupportedLock.php';
+include __DIR__ . '/Property/SupportedReportSet.php';
+include __DIR__ . '/Tree/Filesystem.php';
+include __DIR__ . '/Collection.php';
+include __DIR__ . '/Directory.php';
+include __DIR__ . '/Exception/ConflictingLock.php';
+include __DIR__ . '/Exception/FileNotFound.php';
+include __DIR__ . '/File.php';
+include __DIR__ . '/FS/Directory.php';
+include __DIR__ . '/FS/File.php';
+include __DIR__ . '/FSExt/Directory.php';
+include __DIR__ . '/FSExt/File.php';
+include __DIR__ . '/SimpleCollection.php';
+include __DIR__ . '/SimpleDirectory.php';
+include __DIR__ . '/SimpleFile.php';
+// End includes
diff --git a/3rdparty/Sabre/DAVACL/AbstractPrincipalCollection.php b/3rdparty/Sabre/DAVACL/AbstractPrincipalCollection.php
index a361e054610dd2251f3bb1961b879a95de39d79a..e05b7749805c8cc40306f527f54734b72d17f830 100644
--- a/3rdparty/Sabre/DAVACL/AbstractPrincipalCollection.php
+++ b/3rdparty/Sabre/DAVACL/AbstractPrincipalCollection.php
@@ -3,53 +3,52 @@
 /**
  * Principals Collection
  *
- * This is a helper class that easily allows you to create a collection that 
+ * This is a helper class that easily allows you to create a collection that
  * has a childnode for every principal.
- * 
- * To use this class, simply implement the getChildForPrincipal method. 
+ *
+ * To use this class, simply implement the getChildForPrincipal method.
  *
  * @package Sabre
  * @subpackage DAVACL
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
- * @author Evert Pot (http://www.rooftopsolutions.nl/) 
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
  */
 abstract class Sabre_DAVACL_AbstractPrincipalCollection extends Sabre_DAV_Collection  {
 
     /**
-     * Node or 'directory' name. 
-     * 
-     * @var string 
+     * Node or 'directory' name.
+     *
+     * @var string
      */
     protected $path;
 
     /**
-     * Principal backend 
-     * 
-     * @var Sabre_DAVACL_IPrincipalBackend 
+     * Principal backend
+     *
+     * @var Sabre_DAVACL_IPrincipalBackend
      */
     protected $principalBackend;
 
     /**
      * If this value is set to true, it effectively disables listing of users
-     * it still allows user to find other users if they have an exact url. 
-     * 
-     * @var bool 
+     * it still allows user to find other users if they have an exact url.
+     *
+     * @var bool
      */
     public $disableListing = false;
 
     /**
      * Creates the object
      *
-     * This object must be passed the principal backend. This object will 
-     * filter all principals from a specfied prefix ($principalPrefix). The 
-     * default is 'principals', if your principals are stored in a different 
+     * This object must be passed the principal backend. This object will
+     * filter all principals from a specified prefix ($principalPrefix). The
+     * default is 'principals', if your principals are stored in a different
      * collection, override $principalPrefix
-     * 
-     * 
-     * @param Sabre_DAVACL_IPrincipalBackend $principalBackend 
+     *
+     *
+     * @param Sabre_DAVACL_IPrincipalBackend $principalBackend
      * @param string $principalPrefix
-     * @param string $nodeName
      */
     public function __construct(Sabre_DAVACL_IPrincipalBackend $principalBackend, $principalPrefix = 'principals') {
 
@@ -64,28 +63,28 @@ abstract class Sabre_DAVACL_AbstractPrincipalCollection extends Sabre_DAV_Collec
      * The passed array contains principal information, and is guaranteed to
      * at least contain a uri item. Other properties may or may not be
      * supplied by the authentication backend.
-     * 
-     * @param array $principalInfo 
+     *
+     * @param array $principalInfo
      * @return Sabre_DAVACL_IPrincipal
      */
     abstract function getChildForPrincipal(array $principalInfo);
 
     /**
-     * Returns the name of this collection. 
-     * 
-     * @return string 
+     * Returns the name of this collection.
+     *
+     * @return string
      */
     public function getName() {
 
         list(,$name) = Sabre_DAV_URLUtil::splitPath($this->principalPrefix);
-        return $name; 
+        return $name;
 
     }
 
     /**
-     * Return the list of users 
-     * 
-     * @return void
+     * Return the list of users
+     *
+     * @return array
      */
     public function getChildren() {
 
@@ -99,23 +98,57 @@ abstract class Sabre_DAVACL_AbstractPrincipalCollection extends Sabre_DAV_Collec
 
 
         }
-        return $children; 
+        return $children;
 
     }
 
     /**
      * Returns a child object, by its name.
-     * 
+     *
      * @param string $name
-     * @throws Sabre_DAV_Exception_FileNotFound
+     * @throws Sabre_DAV_Exception_NotFound
      * @return Sabre_DAV_IPrincipal
      */
     public function getChild($name) {
 
         $principalInfo = $this->principalBackend->getPrincipalByPath($this->principalPrefix . '/' . $name);
-        if (!$principalInfo) throw new Sabre_DAV_Exception_FileNotFound('Principal with name ' . $name . ' not found');
+        if (!$principalInfo) throw new Sabre_DAV_Exception_NotFound('Principal with name ' . $name . ' not found');
         return $this->getChildForPrincipal($principalInfo);
 
     }
 
+    /**
+     * This method is used to search for principals matching a set of
+     * properties.
+     *
+     * This search is specifically used by RFC3744's principal-property-search
+     * REPORT. You should at least allow searching on
+     * http://sabredav.org/ns}email-address.
+     *
+     * The actual search should be a unicode-non-case-sensitive search. The
+     * keys in searchProperties are the WebDAV property names, while the values
+     * are the property values to search on.
+     *
+     * If multiple properties are being searched on, the search should be
+     * AND'ed.
+     *
+     * This method should simply return a list of 'child names', which may be
+     * used to call $this->getChild in the future.
+     *
+     * @param array $searchProperties
+     * @return array
+     */
+    public function searchPrincipals(array $searchProperties) {
+
+        $result = $this->principalBackend->searchPrincipals($this->principalPrefix, $searchProperties);
+        $r = array();
+
+        foreach($result as $row) {
+            list(, $r[]) = Sabre_DAV_URLUtil::splitPath($row);
+        }
+
+        return $r;
+
+    }
+
 }
diff --git a/3rdparty/Sabre/DAVACL/Exception/AceConflict.php b/3rdparty/Sabre/DAVACL/Exception/AceConflict.php
index d10aeb4345c6ff2c653f139db50f904dbf779093..4b9f93b003631770b295bcd0937db863d2971383 100644
--- a/3rdparty/Sabre/DAVACL/Exception/AceConflict.php
+++ b/3rdparty/Sabre/DAVACL/Exception/AceConflict.php
@@ -1,12 +1,12 @@
 <?php
 
 /**
- * Sabre_DAVACL_Exception_AceConflict 
- * 
+ * Sabre_DAVACL_Exception_AceConflict
+ *
  * @package Sabre
  * @subpackage DAVACL
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
- * @author Evert Pot (http://www.rooftopsolutions.nl/) 
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
  */
 class Sabre_DAVACL_Exception_AceConflict extends Sabre_DAV_Exception_Conflict {
@@ -15,20 +15,18 @@ class Sabre_DAVACL_Exception_AceConflict extends Sabre_DAV_Exception_Conflict {
      * Adds in extra information in the xml response.
      *
      * This method adds the {DAV:}no-ace-conflict element as defined in rfc3744
-     * 
-     * @param Sabre_DAV_Server $server 
-     * @param DOMElement $errorNode 
+     *
+     * @param Sabre_DAV_Server $server
+     * @param DOMElement $errorNode
      * @return void
      */
     public function serialize(Sabre_DAV_Server $server,DOMElement $errorNode) {
-        
+
         $doc = $errorNode->ownerDocument;
-        
+
         $np = $doc->createElementNS('DAV:','d:no-ace-conflict');
         $errorNode->appendChild($np);
 
     }
 
 }
-
-?>
diff --git a/3rdparty/Sabre/DAVACL/Exception/NeedPrivileges.php b/3rdparty/Sabre/DAVACL/Exception/NeedPrivileges.php
index 024ab6641f35a851aad6d01b1790482dda6e058d..9b055dd9709ec8a9db6df77c98c9523fec426f52 100644
--- a/3rdparty/Sabre/DAVACL/Exception/NeedPrivileges.php
+++ b/3rdparty/Sabre/DAVACL/Exception/NeedPrivileges.php
@@ -1,60 +1,61 @@
 <?php
 
 /**
- * NeedPrivileges 
+ * NeedPrivileges
  *
  * The 403-need privileges is thrown when a user didn't have the appropriate
  * permissions to perform an operation
- * 
+ *
  * @package Sabre
  * @subpackage DAVACL
- * @version $Id$
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
- * @author Evert Pot (http://www.rooftopsolutions.nl/) 
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
  */
 class Sabre_DAVACL_Exception_NeedPrivileges extends Sabre_DAV_Exception_Forbidden {
 
     /**
-     * The relevant uri 
-     * 
-     * @var string 
+     * The relevant uri
+     *
+     * @var string
      */
     protected $uri;
 
     /**
-     * The privileges the user didn't have. 
-     * 
-     * @var array 
+     * The privileges the user didn't have.
+     *
+     * @var array
      */
     protected $privileges;
 
     /**
-     * Constructor 
-     * 
-     * @param string $uri 
-     * @param array $privileges 
+     * Constructor
+     *
+     * @param string $uri
+     * @param array $privileges
      */
     public function __construct($uri,array $privileges) {
 
         $this->uri = $uri;
         $this->privileges = $privileges;
 
+        parent::__construct('User did not have the required privileges (' . implode(',', $privileges) . ') for path "' . $uri . '"');
+
     }
 
     /**
      * Adds in extra information in the xml response.
      *
      * This method adds the {DAV:}need-privileges element as defined in rfc3744
-     * 
-     * @param Sabre_DAV_Server $server 
-     * @param DOMElement $errorNode 
+     *
+     * @param Sabre_DAV_Server $server
+     * @param DOMElement $errorNode
      * @return void
      */
     public function serialize(Sabre_DAV_Server $server,DOMElement $errorNode) {
-        
+
         $doc = $errorNode->ownerDocument;
-        
+
         $np = $doc->createElementNS('DAV:','d:need-privileges');
         $errorNode->appendChild($np);
 
diff --git a/3rdparty/Sabre/DAVACL/Exception/NoAbstract.php b/3rdparty/Sabre/DAVACL/Exception/NoAbstract.php
index 60f49ebff4adec68e1eee8454628737909961310..f44e3e32281719878e0aa9819272fafaf09ff4f1 100644
--- a/3rdparty/Sabre/DAVACL/Exception/NoAbstract.php
+++ b/3rdparty/Sabre/DAVACL/Exception/NoAbstract.php
@@ -2,11 +2,11 @@
 
 /**
  * Sabre_DAVACL_Exception_NoAbstract
- * 
+ *
  * @package Sabre
  * @subpackage DAVACL
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
- * @author Evert Pot (http://www.rooftopsolutions.nl/) 
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
  */
 class Sabre_DAVACL_Exception_NoAbstract extends Sabre_DAV_Exception_PreconditionFailed {
@@ -15,20 +15,18 @@ class Sabre_DAVACL_Exception_NoAbstract extends Sabre_DAV_Exception_Precondition
      * Adds in extra information in the xml response.
      *
      * This method adds the {DAV:}no-abstract element as defined in rfc3744
-     * 
-     * @param Sabre_DAV_Server $server 
-     * @param DOMElement $errorNode 
+     *
+     * @param Sabre_DAV_Server $server
+     * @param DOMElement $errorNode
      * @return void
      */
     public function serialize(Sabre_DAV_Server $server,DOMElement $errorNode) {
-        
+
         $doc = $errorNode->ownerDocument;
-        
+
         $np = $doc->createElementNS('DAV:','d:no-abstract');
         $errorNode->appendChild($np);
 
     }
 
 }
-
-?>
diff --git a/3rdparty/Sabre/DAVACL/Exception/NotRecognizedPrincipal.php b/3rdparty/Sabre/DAVACL/Exception/NotRecognizedPrincipal.php
index e056dc9e4f70ff2c25e2a679fdb4e4669f2db2c9..8d1e38ca1b470d84d9ce38182bf02507c423b114 100644
--- a/3rdparty/Sabre/DAVACL/Exception/NotRecognizedPrincipal.php
+++ b/3rdparty/Sabre/DAVACL/Exception/NotRecognizedPrincipal.php
@@ -2,11 +2,11 @@
 
 /**
  * Sabre_DAVACL_Exception_NotRecognizedPrincipal
- * 
+ *
  * @package Sabre
  * @subpackage DAVACL
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
- * @author Evert Pot (http://www.rooftopsolutions.nl/) 
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
  */
 class Sabre_DAVACL_Exception_NotRecognizedPrincipal extends Sabre_DAV_Exception_PreconditionFailed {
@@ -15,20 +15,18 @@ class Sabre_DAVACL_Exception_NotRecognizedPrincipal extends Sabre_DAV_Exception_
      * Adds in extra information in the xml response.
      *
      * This method adds the {DAV:}recognized-principal element as defined in rfc3744
-     * 
-     * @param Sabre_DAV_Server $server 
-     * @param DOMElement $errorNode 
+     *
+     * @param Sabre_DAV_Server $server
+     * @param DOMElement $errorNode
      * @return void
      */
     public function serialize(Sabre_DAV_Server $server,DOMElement $errorNode) {
-        
+
         $doc = $errorNode->ownerDocument;
-        
+
         $np = $doc->createElementNS('DAV:','d:recognized-principal');
         $errorNode->appendChild($np);
 
     }
 
 }
-
-?>
diff --git a/3rdparty/Sabre/DAVACL/Exception/NotSupportedPrivilege.php b/3rdparty/Sabre/DAVACL/Exception/NotSupportedPrivilege.php
index 27db7cdd7dd43be716b6248a8d4acdf73505e707..3b5d012d7fa25f35d7a5b8e6ad5a6dea005238cb 100644
--- a/3rdparty/Sabre/DAVACL/Exception/NotSupportedPrivilege.php
+++ b/3rdparty/Sabre/DAVACL/Exception/NotSupportedPrivilege.php
@@ -2,11 +2,11 @@
 
 /**
  * Sabre_DAVACL_Exception_NotSupportedPrivilege
- * 
+ *
  * @package Sabre
  * @subpackage DAVACL
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
- * @author Evert Pot (http://www.rooftopsolutions.nl/) 
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
  */
 class Sabre_DAVACL_Exception_NotSupportedPrivilege extends Sabre_DAV_Exception_PreconditionFailed {
@@ -15,20 +15,18 @@ class Sabre_DAVACL_Exception_NotSupportedPrivilege extends Sabre_DAV_Exception_P
      * Adds in extra information in the xml response.
      *
      * This method adds the {DAV:}not-supported-privilege element as defined in rfc3744
-     * 
-     * @param Sabre_DAV_Server $server 
-     * @param DOMElement $errorNode 
+     *
+     * @param Sabre_DAV_Server $server
+     * @param DOMElement $errorNode
      * @return void
      */
     public function serialize(Sabre_DAV_Server $server,DOMElement $errorNode) {
-        
+
         $doc = $errorNode->ownerDocument;
-        
+
         $np = $doc->createElementNS('DAV:','d:not-supported-privilege');
         $errorNode->appendChild($np);
 
     }
 
 }
-
-?>
diff --git a/3rdparty/Sabre/DAVACL/IACL.php b/3rdparty/Sabre/DAVACL/IACL.php
index 506be4248d76b8bca9facd87097c128846e4f2bd..003e69934834a3b4ef0780b51c723ab486120d40 100644
--- a/3rdparty/Sabre/DAVACL/IACL.php
+++ b/3rdparty/Sabre/DAVACL/IACL.php
@@ -4,11 +4,11 @@
  * ACL-enabled node
  *
  * If you want to add WebDAV ACL to a node, you must implement this class
- * 
+ *
  * @package Sabre
  * @subpackage DAVACL
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
- * @author Evert Pot (http://www.rooftopsolutions.nl/) 
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
  */
 interface Sabre_DAVACL_IACL extends Sabre_DAV_INode {
@@ -16,8 +16,8 @@ interface Sabre_DAVACL_IACL extends Sabre_DAV_INode {
     /**
      * Returns the owner principal
      *
-     * This must be a url to a principal, or null if there's no owner 
-     * 
+     * This must be a url to a principal, or null if there's no owner
+     *
      * @return string|null
      */
     function getOwner();
@@ -26,8 +26,8 @@ interface Sabre_DAVACL_IACL extends Sabre_DAV_INode {
      * Returns a group principal
      *
      * This must be a url to a principal, or null if there's no owner
-     * 
-     * @return string|null 
+     *
+     * @return string|null
      */
     function getGroup();
 
@@ -35,24 +35,39 @@ interface Sabre_DAVACL_IACL extends Sabre_DAV_INode {
      * Returns a list of ACE's for this node.
      *
      * Each ACE has the following properties:
-     *   * 'privilege', a string such as {DAV:}read or {DAV:}write. These are 
+     *   * 'privilege', a string such as {DAV:}read or {DAV:}write. These are
      *     currently the only supported privileges
      *   * 'principal', a url to the principal who owns the node
-     *   * 'protected' (optional), indicating that this ACE is not allowed to 
-     *      be updated. 
-     * 
-     * @return array 
+     *   * 'protected' (optional), indicating that this ACE is not allowed to
+     *      be updated.
+     *
+     * @return array
      */
     function getACL();
 
     /**
      * Updates the ACL
      *
-     * This method will receive a list of new ACE's. 
-     * 
-     * @param array $acl 
+     * This method will receive a list of new ACE's.
+     *
+     * @param array $acl
      * @return void
      */
     function setACL(array $acl);
 
+    /**
+     * Returns the list of supported privileges for this node.
+     *
+     * The returned data structure is a list of nested privileges.
+     * See Sabre_DAVACL_Plugin::getDefaultSupportedPrivilegeSet for a simple
+     * standard structure.
+     *
+     * If null is returned from this method, the default privilege set is used,
+     * which is fine for most common usecases.
+     *
+     * @return array|null
+     */
+    function getSupportedPrivilegeSet();
+
+
 }
diff --git a/3rdparty/Sabre/DAVACL/IPrincipal.php b/3rdparty/Sabre/DAVACL/IPrincipal.php
index 7868811db76394ef6101516b627bde7d1da54929..fc7605bf625bc9e27f95aae5926d69e30554ca9f 100644
--- a/3rdparty/Sabre/DAVACL/IPrincipal.php
+++ b/3rdparty/Sabre/DAVACL/IPrincipal.php
@@ -2,50 +2,50 @@
 
 /**
  * IPrincipal interface
- * 
+ *
  * Implement this interface to define your own principals
- * 
+ *
  * @package Sabre
  * @subpackage DAVACL
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
- * @author Evert Pot (http://www.rooftopsolutions.nl/) 
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
  */
 interface Sabre_DAVACL_IPrincipal extends Sabre_DAV_INode {
 
     /**
-     * Returns a list of altenative urls for a principal
-     * 
+     * Returns a list of alternative urls for a principal
+     *
      * This can for example be an email address, or ldap url.
-     * 
-     * @return array 
+     *
+     * @return array
      */
     function getAlternateUriSet();
 
     /**
-     * Returns the full principal url 
-     * 
-     * @return string 
+     * Returns the full principal url
+     *
+     * @return string
      */
     function getPrincipalUrl();
 
     /**
      * Returns the list of group members
-     * 
+     *
      * If this principal is a group, this function should return
-     * all member principal uri's for the group. 
-     * 
+     * all member principal uri's for the group.
+     *
      * @return array
      */
     function getGroupMemberSet();
 
     /**
      * Returns the list of groups this principal is member of
-     * 
+     *
      * If this principal is a member of a (list of) groups, this function
-     * should return a list of principal uri's for it's members. 
-     * 
-     * @return array 
+     * should return a list of principal uri's for it's members.
+     *
+     * @return array
      */
     function getGroupMembership();
 
@@ -54,11 +54,11 @@ interface Sabre_DAVACL_IPrincipal extends Sabre_DAV_INode {
      *
      * If this principal is a group, this method sets all the group members.
      * The list of members is always overwritten, never appended to.
-     * 
-     * This method should throw an exception if the members could not be set. 
-     * 
-     * @param array $principals 
-     * @return void 
+     *
+     * This method should throw an exception if the members could not be set.
+     *
+     * @param array $principals
+     * @return void
      */
     function setGroupMemberSet(array $principals);
 
@@ -66,9 +66,9 @@ interface Sabre_DAVACL_IPrincipal extends Sabre_DAV_INode {
      * Returns the displayname
      *
      * This should be a human readable name for the principal.
-     * If none is available, return the nodename. 
-     * 
-     * @return string 
+     * If none is available, return the nodename.
+     *
+     * @return string
      */
     function getDisplayName();
 
diff --git a/3rdparty/Sabre/DAVACL/IPrincipalBackend.php b/3rdparty/Sabre/DAVACL/IPrincipalBackend.php
index 8899f6f80dffda4e838cf963ec1ce6ade41660f7..e798bf890c0a1e87aba4e2fad001eb68397bf785 100644
--- a/3rdparty/Sabre/DAVACL/IPrincipalBackend.php
+++ b/3rdparty/Sabre/DAVACL/IPrincipalBackend.php
@@ -3,14 +3,14 @@
 /**
  * Implement this interface to create your own principal backends.
  *
- * Creating backends for principals is entirely optional. You can also 
- * implement Sabre_DAVACL_IPrincipal directly. This interface is used solely by 
+ * Creating backends for principals is entirely optional. You can also
+ * implement Sabre_DAVACL_IPrincipal directly. This interface is used solely by
  * Sabre_DAVACL_AbstractPrincipalCollection.
  *
  * @package Sabre
  * @subpackage DAVACL
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
- * @author Evert Pot (http://www.rooftopsolutions.nl/) 
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
  */
 interface Sabre_DAVACL_IPrincipalBackend {
@@ -18,56 +18,136 @@ interface Sabre_DAVACL_IPrincipalBackend {
     /**
      * Returns a list of principals based on a prefix.
      *
-     * This prefix will often contain something like 'principals'. You are only 
+     * This prefix will often contain something like 'principals'. You are only
      * expected to return principals that are in this base path.
      *
-     * You are expected to return at least a 'uri' for every user, you can 
+     * You are expected to return at least a 'uri' for every user, you can
      * return any additional properties if you wish so. Common properties are:
-     *   {DAV:}displayname 
-     *   {http://sabredav.org/ns}email-address - This is a custom SabreDAV 
-     *     field that's actualy injected in a number of other properties. If
+     *   {DAV:}displayname
+     *   {http://sabredav.org/ns}email-address - This is a custom SabreDAV
+     *     field that's actually injected in a number of other properties. If
      *     you have an email address, use this property.
-     * 
-     * @param string $prefixPath 
-     * @return array 
+     *
+     * @param string $prefixPath
+     * @return array
      */
     function getPrincipalsByPrefix($prefixPath);
 
     /**
      * Returns a specific principal, specified by it's path.
-     * The returned structure should be the exact same as from 
-     * getPrincipalsByPrefix. 
-     * 
-     * @param string $path 
-     * @return array 
+     * The returned structure should be the exact same as from
+     * getPrincipalsByPrefix.
+     *
+     * @param string $path
+     * @return array
      */
     function getPrincipalByPath($path);
 
     /**
-     * Returns the list of members for a group-principal 
-     * 
-     * @param string $principal 
-     * @return array 
+     * Updates one ore more webdav properties on a principal.
+     *
+     * The list of mutations is supplied as an array. Each key in the array is
+     * a propertyname, such as {DAV:}displayname.
+     *
+     * Each value is the actual value to be updated. If a value is null, it
+     * must be deleted.
+     *
+     * This method should be atomic. It must either completely succeed, or
+     * completely fail. Success and failure can simply be returned as 'true' or
+     * 'false'.
+     *
+     * It is also possible to return detailed failure information. In that case
+     * an array such as this should be returned:
+     *
+     * array(
+     *   200 => array(
+     *      '{DAV:}prop1' => null,
+     *   ),
+     *   201 => array(
+     *      '{DAV:}prop2' => null,
+     *   ),
+     *   403 => array(
+     *      '{DAV:}prop3' => null,
+     *   ),
+     *   424 => array(
+     *      '{DAV:}prop4' => null,
+     *   ),
+     * );
+     *
+     * In this previous example prop1 was successfully updated or deleted, and
+     * prop2 was succesfully created.
+     *
+     * prop3 failed to update due to '403 Forbidden' and because of this prop4
+     * also could not be updated with '424 Failed dependency'.
+     *
+     * This last example was actually incorrect. While 200 and 201 could appear
+     * in 1 response, if there's any error (403) the other properties should
+     * always fail with 423 (failed dependency).
+     *
+     * But anyway, if you don't want to scratch your head over this, just
+     * return true or false.
+     *
+     * @param string $path
+     * @param array $mutations
+     * @return array|bool
+     */
+    function updatePrincipal($path, $mutations);
+
+    /**
+     * This method is used to search for principals matching a set of
+     * properties.
+     *
+     * This search is specifically used by RFC3744's principal-property-search
+     * REPORT. You should at least allow searching on
+     * http://sabredav.org/ns}email-address.
+     *
+     * The actual search should be a unicode-non-case-sensitive search. The
+     * keys in searchProperties are the WebDAV property names, while the values
+     * are the property values to search on.
+     *
+     * If multiple properties are being searched on, the search should be
+     * AND'ed.
+     *
+     * This method should simply return an array with full principal uri's.
+     *
+     * If somebody attempted to search on a property the backend does not
+     * support, you should simply return 0 results.
+     *
+     * You can also just return 0 results if you choose to not support
+     * searching at all, but keep in mind that this may stop certain features
+     * from working.
+     *
+     * @param string $prefixPath
+     * @param array $searchProperties
+     * @return array
+     */
+    function searchPrincipals($prefixPath, array $searchProperties);
+
+    /**
+     * Returns the list of members for a group-principal
+     *
+     * @param string $principal
+     * @return array
      */
     function getGroupMemberSet($principal);
 
     /**
-     * Returns the list of groups a principal is a member of 
-     * 
-     * @param string $principal 
-     * @return array 
+     * Returns the list of groups a principal is a member of
+     *
+     * @param string $principal
+     * @return array
      */
     function getGroupMembership($principal);
 
     /**
      * Updates the list of group members for a group principal.
      *
-     * The principals should be passed as a list of uri's. 
-     * 
-     * @param string $principal 
-     * @param array $members 
+     * The principals should be passed as a list of uri's.
+     *
+     * @param string $principal
+     * @param array $members
      * @return void
      */
-    function setGroupMemberSet($principal, array $members); 
+    function setGroupMemberSet($principal, array $members);
 
 }
diff --git a/3rdparty/Sabre/DAVACL/Plugin.php b/3rdparty/Sabre/DAVACL/Plugin.php
index b964bdb5dec84466b71002cf4cce356174b5bb97..5c828c6d97be4f0cfc1273303daacc2284c432b6 100644
--- a/3rdparty/Sabre/DAVACL/Plugin.php
+++ b/3rdparty/Sabre/DAVACL/Plugin.php
@@ -6,14 +6,14 @@
  * This plugin provides funcitonality to enforce ACL permissions.
  * ACL is defined in RFC3744.
  *
- * In addition it also provides support for the {DAV:}current-user-principal 
- * property, defined in RFC5397 and the {DAV:}expand-property report, as 
- * defined in RFC3253. 
- * 
+ * In addition it also provides support for the {DAV:}current-user-principal
+ * property, defined in RFC5397 and the {DAV:}expand-property report, as
+ * defined in RFC3253.
+ *
  * @package Sabre
  * @subpackage DAVACL
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
- * @author Evert Pot (http://www.rooftopsolutions.nl/) 
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
  */
 class Sabre_DAVACL_Plugin extends Sabre_DAV_ServerPlugin {
@@ -40,16 +40,16 @@ class Sabre_DAVACL_Plugin extends Sabre_DAV_ServerPlugin {
     const R_RECURSIVEPARENTS = 3;
 
     /**
-     * Reference to server object. 
-     * 
-     * @var Sabre_DAV_Server 
+     * Reference to server object.
+     *
+     * @var Sabre_DAV_Server
      */
     protected $server;
 
     /**
      * List of urls containing principal collections.
-     * Modify this if your principals are located elsewhere. 
-     * 
+     * Modify this if your principals are located elsewhere.
+     *
      * @var array
      */
     public $principalCollectionSet = array(
@@ -57,14 +57,14 @@ class Sabre_DAVACL_Plugin extends Sabre_DAV_ServerPlugin {
     );
 
     /**
-     * By default ACL is only enforced for nodes that have ACL support (the 
-     * ones that implement Sabre_DAVACL_IACL). For any other node, access is 
+     * By default ACL is only enforced for nodes that have ACL support (the
+     * ones that implement Sabre_DAVACL_IACL). For any other node, access is
      * always granted.
      *
-     * To override this behaviour you can turn this setting off. This is useful 
+     * To override this behaviour you can turn this setting off. This is useful
      * if you plan to fully support ACL in the entire tree.
      *
-     * @var bool 
+     * @var bool
      */
     public $allowAccessToNodesWithoutACL = true;
 
@@ -72,28 +72,50 @@ class Sabre_DAVACL_Plugin extends Sabre_DAV_ServerPlugin {
      * By default nodes that are inaccessible by the user, can still be seen
      * in directory listings (PROPFIND on parent with Depth: 1)
      *
-     * In certain cases it's desirable to hide inaccessible nodes. Setting this 
+     * In certain cases it's desirable to hide inaccessible nodes. Setting this
      * to true will cause these nodes to be hidden from directory listings.
-     * 
-     * @var bool 
+     *
+     * @var bool
      */
     public $hideNodesFromListings = false;
 
     /**
-     * This string is prepended to the username of the currently logged in 
-     * user. This allows the plugin to determine the principal path based on 
+     * This string is prepended to the username of the currently logged in
+     * user. This allows the plugin to determine the principal path based on
      * the username.
-     * 
+     *
      * @var string
      */
     public $defaultUsernamePath = 'principals';
 
+    /**
+     * This list of properties are the properties a client can search on using
+     * the {DAV:}principal-property-search report.
+     *
+     * The keys are the property names, values are descriptions.
+     *
+     * @var array
+     */
+    public $principalSearchPropertySet = array(
+        '{DAV:}displayname' => 'Display name',
+        '{http://sabredav.org/ns}email-address' => 'Email address',
+    );
+
+    /**
+     * Any principal uri's added here, will automatically be added to the list 
+     * of ACL's. They will effectively receive {DAV:}all privileges, as a 
+     * protected privilege.
+     * 
+     * @var array 
+     */
+    public $adminPrincipals = array();
+
     /**
      * Returns a list of features added by this plugin.
      *
      * This list is used in the response of a HTTP OPTIONS request.
-     * 
-     * @return array 
+     *
+     * @return array
      */
     public function getFeatures() {
 
@@ -102,10 +124,10 @@ class Sabre_DAVACL_Plugin extends Sabre_DAV_ServerPlugin {
     }
 
     /**
-     * Returns a list of available methods for a given url 
-     * 
-     * @param string $uri 
-     * @return array 
+     * Returns a list of available methods for a given url
+     *
+     * @param string $uri
+     * @return array
      */
     public function getMethods($uri) {
 
@@ -115,11 +137,11 @@ class Sabre_DAVACL_Plugin extends Sabre_DAV_ServerPlugin {
 
     /**
      * Returns a plugin name.
-     * 
+     *
      * Using this name other plugins will be able to access other plugins
-     * using Sabre_DAV_Server::getPlugin 
-     * 
-     * @return string 
+     * using Sabre_DAV_Server::getPlugin
+     *
+     * @return string
      */
     public function getPluginName() {
 
@@ -131,37 +153,38 @@ class Sabre_DAVACL_Plugin extends Sabre_DAV_ServerPlugin {
      * Returns a list of reports this plugin supports.
      *
      * This will be used in the {DAV:}supported-report-set property.
-     * Note that you still need to subscribe to the 'report' event to actually 
-     * implement them 
-     * 
+     * Note that you still need to subscribe to the 'report' event to actually
+     * implement them
+     *
      * @param string $uri
-     * @return array 
+     * @return array
      */
     public function getSupportedReportSet($uri) {
 
         return array(
             '{DAV:}expand-property',
             '{DAV:}principal-property-search',
-            '{DAV:}principal-search-property-set', 
+            '{DAV:}principal-search-property-set',
         );
 
     }
 
 
     /**
-     * Checks if the current user has the specified privilege(s). 
-     * 
+     * Checks if the current user has the specified privilege(s).
+     *
      * You can specify a single privilege, or a list of privileges.
      * This method will throw an exception if the privilege is not available
      * and return true otherwise.
      *
      * @param string $uri
      * @param array|string $privileges
-     * @param bool $throwExceptions if set to false, this method won't through exceptions. 
+     * @param int $recursion
+     * @param bool $throwExceptions if set to false, this method won't through exceptions.
      * @throws Sabre_DAVACL_Exception_NeedPrivileges
-     * @return bool 
+     * @return bool
      */
-    public function checkPrivileges($uri,$privileges,$recursion = self::R_PARENT, $throwExceptions = true) {
+    public function checkPrivileges($uri, $privileges, $recursion = self::R_PARENT, $throwExceptions = true) {
 
         if (!is_array($privileges)) $privileges = array($privileges);
 
@@ -171,7 +194,7 @@ class Sabre_DAVACL_Plugin extends Sabre_DAV_ServerPlugin {
             if ($this->allowAccessToNodesWithoutACL) {
                 return true;
             } else {
-                if ($throwExceptions) 
+                if ($throwExceptions)
                     throw new Sabre_DAVACL_Exception_NeedPrivileges($uri,$privileges);
                 else
                     return false;
@@ -189,7 +212,7 @@ class Sabre_DAVACL_Plugin extends Sabre_DAV_ServerPlugin {
         }
 
         if ($failed) {
-            if ($throwExceptions) 
+            if ($throwExceptions)
                 throw new Sabre_DAVACL_Exception_NeedPrivileges($uri,$failed);
             else
                 return false;
@@ -202,9 +225,9 @@ class Sabre_DAVACL_Plugin extends Sabre_DAV_ServerPlugin {
      * Returns the standard users' principal.
      *
      * This is one authorative principal url for the current user.
-     * This method will return null if the user wasn't logged in. 
-     * 
-     * @return string|null 
+     * This method will return null if the user wasn't logged in.
+     *
+     * @return string|null
      */
     public function getCurrentUserPrincipal() {
 
@@ -220,9 +243,9 @@ class Sabre_DAVACL_Plugin extends Sabre_DAV_ServerPlugin {
 
     /**
      * Returns a list of principals that's associated to the current
-     * user, either directly or through group membership. 
-     * 
-     * @return array 
+     * user, either directly or through group membership.
+     *
+     * @return array
      */
     public function getCurrentUserPrincipals() {
 
@@ -236,7 +259,7 @@ class Sabre_DAVACL_Plugin extends Sabre_DAV_ServerPlugin {
         while(count($check)) {
 
             $principal = array_shift($check);
- 
+
             $node = $this->server->tree->getNodeForPath($principal);
             if ($node instanceof Sabre_DAVACL_IPrincipal) {
                 foreach($node->getGroupMembership() as $groupMember) {
@@ -262,11 +285,38 @@ class Sabre_DAVACL_Plugin extends Sabre_DAV_ServerPlugin {
      * Returns the supported privilege structure for this ACL plugin.
      *
      * See RFC3744 for more details. Currently we default on a simple,
-     * standard structure. 
-     * 
-     * @return array 
+     * standard structure.
+     *
+     * You can either get the list of privileges by a uri (path) or by
+     * specifying a Node.
+     *
+     * @param string|Sabre_DAV_INode $node
+     * @return array
      */
-    public function getSupportedPrivilegeSet() {
+    public function getSupportedPrivilegeSet($node) {
+
+        if (is_string($node)) {
+            $node = $this->server->tree->getNodeForPath($node);
+        }
+
+        if ($node instanceof Sabre_DAVACL_IACL) {
+            $result = $node->getSupportedPrivilegeSet();
+
+            if ($result)
+                return $result;
+        }
+
+        return self::getDefaultSupportedPrivilegeSet();
+
+    }
+
+    /**
+     * Returns a fairly standard set of privileges, which may be useful for
+     * other systems to use as a basis.
+     *
+     * @return array
+     */
+    static function getDefaultSupportedPrivilegeSet() {
 
         return array(
             'privilege'  => '{DAV:}all',
@@ -314,7 +364,7 @@ class Sabre_DAVACL_Plugin extends Sabre_DAV_ServerPlugin {
                         ),
                     ),
                 ), // {DAV:}write
-            ), 
+            ),
         ); // {DAV:}all
 
     }
@@ -329,12 +379,13 @@ class Sabre_DAVACL_Plugin extends Sabre_DAV_ServerPlugin {
      *   - aggregates
      *   - abstract
      *   - concrete
-     * 
-     * @return array 
+     *
+     * @param string|Sabre_DAV_INode $node
+     * @return array
      */
-    final public function getFlatPrivilegeSet() {
+    final public function getFlatPrivilegeSet($node) {
 
-        $privs = $this->getSupportedPrivilegeSet();
+        $privs = $this->getSupportedPrivilegeSet($node);
 
         $flat = array();
         $this->getFPSTraverse($privs, null, $flat);
@@ -346,9 +397,12 @@ class Sabre_DAVACL_Plugin extends Sabre_DAV_ServerPlugin {
     /**
      * Traverses the privilege set tree for reordering
      *
-     * This function is solely used by getFlatPrivilegeSet, and would have been 
+     * This function is solely used by getFlatPrivilegeSet, and would have been
      * a closure if it wasn't for the fact I need to support PHP 5.2.
-     * 
+     *
+     * @param array $priv
+     * @param $concrete
+     * @param array $flat
      * @return void
      */
     final private function getFPSTraverse($priv, $concrete, &$flat) {
@@ -368,7 +422,7 @@ class Sabre_DAVACL_Plugin extends Sabre_DAV_ServerPlugin {
         if (isset($priv['aggregates'])) {
 
             foreach($priv['aggregates'] as $subPriv) {
-            
+
                 $this->getFPSTraverse($subPriv, $myPriv['concrete'], $flat);
 
             }
@@ -382,8 +436,8 @@ class Sabre_DAVACL_Plugin extends Sabre_DAV_ServerPlugin {
      *
      * Either a uri or a Sabre_DAV_INode may be passed.
      *
-     * null will be returned if the node doesn't support ACLs. 
-     * 
+     * null will be returned if the node doesn't support ACLs.
+     *
      * @param string|Sabre_DAV_INode $node
      * @return array
      */
@@ -392,10 +446,18 @@ class Sabre_DAVACL_Plugin extends Sabre_DAV_ServerPlugin {
         if (is_string($node)) {
             $node = $this->server->tree->getNodeForPath($node);
         }
-        if ($node instanceof Sabre_DAVACL_IACL) {
-            return $node->getACL();
+        if (!$node instanceof Sabre_DAVACL_IACL) {
+            return null;
         }
-        return null; 
+        $acl = $node->getACL();
+        foreach($this->adminPrincipals as $adminPrincipal) {
+            $acl[] = array(
+                'principal' => $adminPrincipal,
+                'privilege' => '{DAV:}all',
+                'protected' => true,
+            );
+        }
+        return $acl;
 
     }
 
@@ -405,10 +467,10 @@ class Sabre_DAVACL_Plugin extends Sabre_DAV_ServerPlugin {
      *
      * Either a uri or a Sabre_DAV_INode may be passed.
      *
-     * null will be returned if the node doesn't support ACLs. 
-     * 
-     * @param string|Sabre_DAV_INode $node 
-     * @return array 
+     * null will be returned if the node doesn't support ACLs.
+     *
+     * @param string|Sabre_DAV_INode $node
+     * @return array
      */
     public function getCurrentUserPrivilegeSet($node) {
 
@@ -417,6 +479,7 @@ class Sabre_DAVACL_Plugin extends Sabre_DAV_ServerPlugin {
         }
 
         $acl = $this->getACL($node);
+
         if (is_null($acl)) return null;
 
         $principals = $this->getCurrentUserPrincipals();
@@ -425,27 +488,121 @@ class Sabre_DAVACL_Plugin extends Sabre_DAV_ServerPlugin {
 
         foreach($acl as $ace) {
 
-            if (in_array($ace['principal'], $principals)) {
-                $collected[] = $ace;
+            $principal = $ace['principal'];
+
+            switch($principal) {
+
+                case '{DAV:}owner' :
+                    $owner = $node->getOwner();
+                    if ($owner && in_array($owner, $principals)) {
+                        $collected[] = $ace;
+                    }
+                    break;
+
+
+                // 'all' matches for every user
+                case '{DAV:}all' :
+
+                // 'authenticated' matched for every user that's logged in.
+                // Since it's not possible to use ACL while not being logged
+                // in, this is also always true.
+                case '{DAV:}authenticated' :
+                    $collected[] = $ace;
+                    break;
+
+                // 'unauthenticated' can never occur either, so we simply
+                // ignore these.
+                case '{DAV:}unauthenticated' :
+                    break;
+
+                default :
+                    if (in_array($ace['principal'], $principals)) {
+                        $collected[] = $ace;
+                    }
+                    break;
+
             }
 
+
+
         }
 
         // Now we deduct all aggregated privileges.
-        $flat = $this->getFlatPrivilegeSet();
+        $flat = $this->getFlatPrivilegeSet($node);
 
         $collected2 = array();
-        foreach($collected as $privilege) {
+        while(count($collected)) {
+
+            $current = array_pop($collected);
+            $collected2[] = $current['privilege'];
 
-            $collected2[] = $privilege['privilege'];
-            foreach($flat[$privilege['privilege']]['aggregates'] as $subPriv) {
-                if (!in_array($subPriv, $collected2)) 
-                    $collected2[] = $subPriv;
+            foreach($flat[$current['privilege']]['aggregates'] as $subPriv) {
+                $collected2[] = $subPriv;
+                $collected[] = $flat[$subPriv];
             }
 
         }
 
-        return $collected2;
+        return array_values(array_unique($collected2));
+
+    }
+
+    /**
+     * Principal property search
+     *
+     * This method can search for principals matching certain values in
+     * properties.
+     *
+     * This method will return a list of properties for the matched properties.
+     *
+     * @param array $searchProperties    The properties to search on. This is a
+     *                                   key-value list. The keys are property
+     *                                   names, and the values the strings to
+     *                                   match them on.
+     * @param array $requestedProperties This is the list of properties to
+     *                                   return for every match.
+     * @param string $collectionUri      The principal collection to search on.
+     *                                   If this is ommitted, the standard
+     *                                   principal collection-set will be used.
+     * @return array     This method returns an array structure similar to
+     *                  Sabre_DAV_Server::getPropertiesForPath. Returned
+     *                  properties are index by a HTTP status code.
+     *
+     */
+    public function principalSearch(array $searchProperties, array $requestedProperties, $collectionUri = null) {
+
+        if (!is_null($collectionUri)) {
+            $uris = array($collectionUri);
+        } else {
+            $uris = $this->principalCollectionSet;
+        }
+
+        $lookupResults = array();
+        foreach($uris as $uri) {
+
+            $principalCollection = $this->server->tree->getNodeForPath($uri);
+            if (!$principalCollection instanceof Sabre_DAVACL_AbstractPrincipalCollection) {
+                // Not a principal collection, we're simply going to ignore
+                // this.
+                continue;
+            }
+
+            $results = $principalCollection->searchPrincipals($searchProperties);
+            foreach($results as $result) {
+                $lookupResults[] = rtrim($uri,'/') . '/' . $result;
+            }
+
+        }
+
+        $matches = array();
+
+        foreach($lookupResults as $lookupResult) {
+
+            list($matches[]) = $this->server->getPropertiesForPath($lookupResult, $requestedProperties, 0);
+
+        }
+
+        return $matches;
 
     }
 
@@ -453,8 +610,8 @@ class Sabre_DAVACL_Plugin extends Sabre_DAV_ServerPlugin {
      * Sets up the plugin
      *
      * This method is automatically called by the server class.
-     * 
-     * @param Sabre_DAV_Server $server 
+     *
+     * @param Sabre_DAV_Server $server
      * @return void
      */
     public function initialize(Sabre_DAV_Server $server) {
@@ -485,11 +642,11 @@ class Sabre_DAVACL_Plugin extends Sabre_DAV_ServerPlugin {
             '{DAV:}group'
         );
 
-        // Automatically mapping nodes implementing IPrincipal to the 
+        // Automatically mapping nodes implementing IPrincipal to the
         // {DAV:}principal resourcetype.
         $server->resourceTypeMapping['Sabre_DAVACL_IPrincipal'] = '{DAV:}principal';
 
-        // Mapping the group-member-set property to the HrefList property 
+        // Mapping the group-member-set property to the HrefList property
         // class.
         $server->propertyMap['{DAV:}group-member-set'] = 'Sabre_DAV_Property_HrefList';
 
@@ -499,10 +656,10 @@ class Sabre_DAVACL_Plugin extends Sabre_DAV_ServerPlugin {
     /* {{{ Event handlers */
 
     /**
-     * Triggered before any method is handled 
-     * 
-     * @param string $method 
-     * @param string $uri 
+     * Triggered before any method is handled
+     *
+     * @param string $method
+     * @param string $uri
      * @return void
      */
     public function beforeMethod($method, $uri) {
@@ -523,14 +680,14 @@ class Sabre_DAVACL_Plugin extends Sabre_DAV_ServerPlugin {
 
             case 'PUT' :
             case 'LOCK' :
-            case 'UNLOCK' : 
-                // This method requires the write-content priv if the node 
-                // already exists, and bind on the parent if the node is being 
-                // created. 
-                // The bind privilege is handled in the beforeBind event. 
+            case 'UNLOCK' :
+                // This method requires the write-content priv if the node
+                // already exists, and bind on the parent if the node is being
+                // created.
+                // The bind privilege is handled in the beforeBind event.
                 $this->checkPrivileges($uri,'{DAV:}write-content');
                 break;
-            
+
 
             case 'PROPPATCH' :
                 $this->checkPrivileges($uri,'{DAV:}write-properties');
@@ -543,16 +700,16 @@ class Sabre_DAVACL_Plugin extends Sabre_DAV_ServerPlugin {
             case 'COPY' :
             case 'MOVE' :
                 // Copy requires read privileges on the entire source tree.
-                // If the target exists write-content normally needs to be 
-                // checked, however, we're deleting the node beforehand and 
-                // creating a new one after, so this is handled by the 
+                // If the target exists write-content normally needs to be
+                // checked, however, we're deleting the node beforehand and
+                // creating a new one after, so this is handled by the
                 // beforeUnbind event.
-                // 
-                // The creation of the new node is handled by the beforeBind 
+                //
+                // The creation of the new node is handled by the beforeBind
                 // event.
                 //
-                // If MOVE is used beforeUnbind will also be used to check if 
-                // the sourcenode can be deleted. 
+                // If MOVE is used beforeUnbind will also be used to check if
+                // the sourcenode can be deleted.
                 $this->checkPrivileges($uri,'{DAV:}read',self::R_RECURSIVE);
 
                 break;
@@ -563,11 +720,11 @@ class Sabre_DAVACL_Plugin extends Sabre_DAV_ServerPlugin {
 
     /**
      * Triggered before a new node is created.
-     * 
+     *
      * This allows us to check permissions for any operation that creates a
      * new node, such as PUT, MKCOL, MKCALENDAR, LOCK, COPY and MOVE.
-     * 
-     * @param string $uri 
+     *
+     * @param string $uri
      * @return void
      */
     public function beforeBind($uri) {
@@ -578,12 +735,12 @@ class Sabre_DAVACL_Plugin extends Sabre_DAV_ServerPlugin {
     }
 
     /**
-     * Triggered before a node is deleted 
-     * 
-     * This allows us to check permissions for any operation that will delete 
-     * an existing node. 
-     * 
-     * @param string $uri 
+     * Triggered before a node is deleted
+     *
+     * This allows us to check permissions for any operation that will delete
+     * an existing node.
+     *
+     * @param string $uri
      * @return void
      */
     public function beforeUnbind($uri) {
@@ -594,26 +751,26 @@ class Sabre_DAVACL_Plugin extends Sabre_DAV_ServerPlugin {
     }
 
     /**
-     * Triggered before a node is unlocked. 
-     * 
-     * @param string $uri 
+     * Triggered before a node is unlocked.
+     *
+     * @param string $uri
      * @param Sabre_DAV_Locks_LockInfo $lock
-     * @TODO: not yet implemented 
+     * @TODO: not yet implemented
      * @return void
      */
     public function beforeUnlock($uri, Sabre_DAV_Locks_LockInfo $lock) {
-           
+
 
     }
 
     /**
-     * Triggered before properties are looked up in specific nodes. 
-     * 
-     * @param string $uri 
-     * @param Sabre_DAV_INode $node 
-     * @param array $requestedProperties 
+     * Triggered before properties are looked up in specific nodes.
+     *
+     * @param string $uri
+     * @param Sabre_DAV_INode $node
+     * @param array $requestedProperties
      * @param array $returnedProperties
-     * @TODO really should be broken into multiple methods, or even a class. 
+     * @TODO really should be broken into multiple methods, or even a class.
      * @return void
      */
     public function beforeGetProperties($uri, Sabre_DAV_INode $node, &$requestedProperties, &$returnedProperties) {
@@ -633,7 +790,7 @@ class Sabre_DAVACL_Plugin extends Sabre_DAV_ServerPlugin {
             }
             return;
 
-        } 
+        }
 
         /* Adding principal properties */
         if ($node instanceof Sabre_DAVACL_IPrincipal) {
@@ -692,7 +849,7 @@ class Sabre_DAVACL_Plugin extends Sabre_DAV_ServerPlugin {
         if (false !== ($index = array_search('{DAV:}supported-privilege-set', $requestedProperties))) {
 
             unset($requestedProperties[$index]);
-            $returnedProperties[200]['{DAV:}supported-privilege-set'] = new Sabre_DAVACL_Property_SupportedPrivilegeSet($this->getSupportedPrivilegeSet());
+            $returnedProperties[200]['{DAV:}supported-privilege-set'] = new Sabre_DAVACL_Property_SupportedPrivilegeSet($this->getSupportedPrivilegeSet($node));
 
         }
         if (false !== ($index = array_search('{DAV:}current-user-privilege-set', $requestedProperties))) {
@@ -730,16 +887,24 @@ class Sabre_DAVACL_Plugin extends Sabre_DAV_ServerPlugin {
 
         }
 
+        /* The acl-restrictions property contains information on how privileges
+         * must behave.
+         */
+        if (false !== ($index = array_search('{DAV:}acl-restrictions', $requestedProperties))) {
+            unset($requestedProperties[$index]);
+            $returnedProperties[200]['{DAV:}acl-restrictions'] = new Sabre_DAVACL_Property_AclRestrictions();
+        }
+
     }
 
     /**
-     * This method intercepts PROPPATCH methods and make sure the 
-     * group-member-set is updated correctly. 
-     * 
-     * @param array $propertyDelta 
-     * @param array $result 
-     * @param Sabre_DAV_INode $node 
-     * @return void
+     * This method intercepts PROPPATCH methods and make sure the
+     * group-member-set is updated correctly.
+     *
+     * @param array $propertyDelta
+     * @param array $result
+     * @param Sabre_DAV_INode $node
+     * @return bool
      */
     public function updateProperties(&$propertyDelta, &$result, Sabre_DAV_INode $node) {
 
@@ -763,18 +928,18 @@ class Sabre_DAVACL_Plugin extends Sabre_DAV_ServerPlugin {
         }
 
         $node->setGroupMemberSet($memberSet);
-        
+
         $result[200]['{DAV:}group-member-set'] = null;
         unset($propertyDelta['{DAV:}group-member-set']);
 
     }
 
     /**
-     * This method handels HTTP REPORT requests 
-     * 
-     * @param string $reportName 
-     * @param DOMNode $dom 
-     * @return void
+     * This method handels HTTP REPORT requests
+     *
+     * @param string $reportName
+     * @param DOMNode $dom
+     * @return bool
      */
     public function report($reportName, $dom) {
 
@@ -785,7 +950,7 @@ class Sabre_DAVACL_Plugin extends Sabre_DAV_ServerPlugin {
                 return false;
             case '{DAV:}principal-search-property-set' :
                 $this->principalSearchPropertySetReport($dom);
-                return false; 
+                return false;
             case '{DAV:}expand-property' :
                 $this->expandPropertyReport($dom);
                 return false;
@@ -795,12 +960,12 @@ class Sabre_DAVACL_Plugin extends Sabre_DAV_ServerPlugin {
     }
 
     /**
-     * This event is triggered for any HTTP method that is not known by the 
-     * webserver. 
+     * This event is triggered for any HTTP method that is not known by the
+     * webserver.
      *
-     * @param string $method 
-     * @param string $uri 
-     * @return void
+     * @param string $method
+     * @param string $uri
+     * @return bool
      */
     public function unknownMethod($method, $uri) {
 
@@ -817,12 +982,12 @@ class Sabre_DAVACL_Plugin extends Sabre_DAV_ServerPlugin {
      * @param string $uri
      * @return void
      */
-    public function httpACL($uri) { 
+    public function httpACL($uri) {
 
         $body = $this->server->httpRequest->getBody(true);
         $dom = Sabre_DAV_XMLUtil::loadDOMDocument($body);
 
-        $newAcl = 
+        $newAcl =
             Sabre_DAVACL_Property_Acl::unserialize($dom->firstChild)
             ->getPrivileges();
 
@@ -839,13 +1004,13 @@ class Sabre_DAVACL_Plugin extends Sabre_DAV_ServerPlugin {
 
         $oldAcl = $this->getACL($node);
 
-        $supportedPrivileges = $this->getFlatPrivilegeSet(); 
+        $supportedPrivileges = $this->getFlatPrivilegeSet($node);
 
-        /* Checking if protected principals from the existing principal set are 
+        /* Checking if protected principals from the existing principal set are
            not overwritten. */
-        foreach($oldAcl as $k=>$oldAce) {
+        foreach($oldAcl as $oldAce) {
 
-            if (!isset($oldAce['protected']) || !$oldAce['protected']) continue; 
+            if (!isset($oldAce['protected']) || !$oldAce['protected']) continue;
 
             $found = false;
             foreach($newAcl as $newAce) {
@@ -853,16 +1018,16 @@ class Sabre_DAVACL_Plugin extends Sabre_DAV_ServerPlugin {
                     $newAce['privilege'] === $oldAce['privilege'] &&
                     $newAce['principal'] === $oldAce['principal'] &&
                     $newAce['protected']
-                ) 
+                )
                 $found = true;
             }
 
-            if (!$found) 
+            if (!$found)
                 throw new Sabre_DAVACL_Exception_AceConflict('This resource contained a protected {DAV:}ace, but this privilege did not occur in the ACL request');
 
         }
 
-        foreach($newAcl as $k=>$newAce) {
+        foreach($newAcl as $newAce) {
 
             // Do we recognize the privilege
             if (!isset($supportedPrivileges[$newAce['privilege']])) {
@@ -876,12 +1041,12 @@ class Sabre_DAVACL_Plugin extends Sabre_DAV_ServerPlugin {
             // Looking up the principal
             try {
                 $principal = $this->server->tree->getNodeForPath($newAce['principal']);
-            } catch (Sabre_DAV_Exception_FileNotFound $e) {
+            } catch (Sabre_DAV_Exception_NotFound $e) {
                 throw new Sabre_DAVACL_Exception_NotRecognizedPrincipal('The specified principal (' . $newAce['principal'] . ') does not exist');
             }
             if (!($principal instanceof Sabre_DAVACL_IPrincipal)) {
                 throw new Sabre_DAVACL_Exception_NotRecognizedPrincipal('The specified uri (' . $newAce['principal'] . ') is not a principal');
-            } 
+            }
 
         }
         $node->setACL($newAcl);
@@ -893,7 +1058,7 @@ class Sabre_DAVACL_Plugin extends Sabre_DAV_ServerPlugin {
     /* Reports {{{ */
 
     /**
-     * The expand-property report is defined in RFC3253 section 3-8. 
+     * The expand-property report is defined in RFC3253 section 3-8.
      *
      * This report is very similar to a standard PROPFIND. The difference is
      * that it has the additional ability to look at properties containing a
@@ -903,7 +1068,7 @@ class Sabre_DAVACL_Plugin extends Sabre_DAV_ServerPlugin {
      * Other rfc's, such as ACL rely on this report, so it made sense to put
      * it in this plugin.
      *
-     * @param DOMElement $dom 
+     * @param DOMElement $dom
      * @return void
      */
     protected function expandPropertyReport($dom) {
@@ -940,9 +1105,9 @@ class Sabre_DAVACL_Plugin extends Sabre_DAV_ServerPlugin {
     /**
      * This method is used by expandPropertyReport to parse
      * out the entire HTTP request.
-     * 
-     * @param DOMElement $node 
-     * @return array 
+     *
+     * @param DOMElement $node
+     * @return array
      */
     protected function parseExpandPropertyReportRequest($node) {
 
@@ -950,9 +1115,9 @@ class Sabre_DAVACL_Plugin extends Sabre_DAV_ServerPlugin {
         do {
 
             if (Sabre_DAV_XMLUtil::toClarkNotation($node)!=='{DAV:}property') continue;
-                
+
             if ($node->firstChild) {
-                
+
                 $children = $this->parseExpandPropertyReportRequest($node->firstChild);
 
             } else {
@@ -965,7 +1130,7 @@ class Sabre_DAVACL_Plugin extends Sabre_DAV_ServerPlugin {
             if (!$namespace) $namespace = 'DAV:';
 
             $propName = '{'.$namespace.'}' . $node->getAttribute('name');
-            $requestedProperties[$propName] = $children; 
+            $requestedProperties[$propName] = $children;
 
         } while ($node = $node->nextSibling);
 
@@ -979,11 +1144,12 @@ class Sabre_DAVACL_Plugin extends Sabre_DAV_ServerPlugin {
      *
      * @param array $path
      * @param array $requestedProperties the list of required properties
-     * @param array $depth
+     * @param int $depth
+     * @return array
      */
-    protected function expandProperties($path,array $requestedProperties,$depth) { 
+    protected function expandProperties($path, array $requestedProperties, $depth) {
 
-        $foundProperties = $this->server->getPropertiesForPath($path,array_keys($requestedProperties),$depth);
+        $foundProperties = $this->server->getPropertiesForPath($path, array_keys($requestedProperties), $depth);
 
         $result = array();
 
@@ -993,7 +1159,7 @@ class Sabre_DAVACL_Plugin extends Sabre_DAV_ServerPlugin {
 
                 // We're only traversing if sub-properties were requested
                 if(count($childRequestedProperties)===0) continue;
-                
+
                 // We only have to do the expansion if the property was found
                 // and it contains an href element.
                 if (!array_key_exists($propertyName,$node[200])) continue;
@@ -1006,7 +1172,7 @@ class Sabre_DAVACL_Plugin extends Sabre_DAV_ServerPlugin {
 
                 $childProps = array();
                 foreach($hrefs as $href) {
-                    $childProps = array_merge($childProps, $this->expandProperties($href,$childRequestedProperties,0));
+                    $childProps = array_merge($childProps, $this->expandProperties($href, $childRequestedProperties, 0));
                 }
                 $node[200][$propertyName] = new Sabre_DAV_Property_ResponseList($childProps);
 
@@ -1022,27 +1188,23 @@ class Sabre_DAVACL_Plugin extends Sabre_DAV_ServerPlugin {
     /**
      * principalSearchPropertySetReport
      *
-     * This method responsible for handing the 
+     * This method responsible for handing the
      * {DAV:}principal-search-property-set report. This report returns a list
      * of properties the client may search on, using the
      * {DAV:}principal-property-search report.
-     * 
-     * @param DOMDocument $dom 
+     *
+     * @param DOMDocument $dom
      * @return void
      */
     protected function principalSearchPropertySetReport(DOMDocument $dom) {
 
-        $searchProperties = array(
-            '{DAV:}displayname' => 'display name'
-        );
-
         $httpDepth = $this->server->getHTTPDepth(0);
         if ($httpDepth!==0) {
             throw new Sabre_DAV_Exception_BadRequest('This report is only defined when Depth: 0');
         }
-        
-        if ($dom->firstChild->hasChildNodes()) 
-            throw new Sabre_DAV_Exception_BadRequest('The principal-search-property-set report element is not allowed to have child elements'); 
+
+        if ($dom->firstChild->hasChildNodes())
+            throw new Sabre_DAV_Exception_BadRequest('The principal-search-property-set report element is not allowed to have child elements');
 
         $dom = new DOMDocument('1.0','utf-8');
         $dom->formatOutput = true;
@@ -1055,16 +1217,16 @@ class Sabre_DAVACL_Plugin extends Sabre_DAV_ServerPlugin {
 
         }
 
-        $nsList = $this->server->xmlNamespaces; 
+        $nsList = $this->server->xmlNamespaces;
 
-        foreach($searchProperties as $propertyName=>$description) {
+        foreach($this->principalSearchPropertySet as $propertyName=>$description) {
 
             $psp = $dom->createElement('d:principal-search-property');
             $root->appendChild($psp);
 
             $prop = $dom->createElement('d:prop');
             $psp->appendChild($prop);
-  
+
             $propName = null;
             preg_match('/^{([^}]*)}(.*)$/',$propertyName,$propName);
 
@@ -1088,78 +1250,25 @@ class Sabre_DAVACL_Plugin extends Sabre_DAV_ServerPlugin {
     /**
      * principalPropertySearchReport
      *
-     * This method is reponsible for handing the 
-     * {DAV:}principal-property-search report. This report can be used for 
+     * This method is responsible for handing the
+     * {DAV:}principal-property-search report. This report can be used for
      * clients to search for groups of principals, based on the value of one
      * or more properties.
-     * 
-     * @param DOMDocument $dom 
+     *
+     * @param DOMDocument $dom
      * @return void
      */
     protected function principalPropertySearchReport(DOMDocument $dom) {
 
-        $searchableProperties = array(
-            '{DAV:}displayname' => 'display name'
-
-        );
-
         list($searchProperties, $requestedProperties, $applyToPrincipalCollectionSet) = $this->parsePrincipalPropertySearchReportRequest($dom);
 
-        $result = array();
-
-        if ($applyToPrincipalCollectionSet) {
-            $uris = array();
-        } else {
-            $uris = array($this->server->getRequestUri());
-        }
-
-        $lookupResults = array();
-        foreach($uris as $uri) {
-
-            $p = array_keys($searchProperties);
-            $p[] = '{DAV:}resourcetype';
-            $r = $this->server->getPropertiesForPath($uri, $p, 1);
-
-            // The first item in the results is the parent, so we get rid of it.
-            array_shift($r);
-            $lookupResults = array_merge($lookupResults, $r);
-        } 
-
-        $matches = array();
-
-        foreach($lookupResults as $lookupResult) {
-
-            // We're only looking for principals 
-            if (!isset($lookupResult[200]['{DAV:}resourcetype']) || 
-                (!($lookupResult[200]['{DAV:}resourcetype'] instanceof Sabre_DAV_Property_ResourceType)) ||
-                !$lookupResult[200]['{DAV:}resourcetype']->is('{DAV:}principal')) continue;
-
-            foreach($searchProperties as $searchProperty=>$searchValue) {
-                if (!isset($searchableProperties[$searchProperty])) {
-                    // If a property is not 'searchable', the spec dictates 
-                    // this is not a match. 
-                    continue;
-                }
-
-                if (isset($lookupResult[200][$searchProperty]) &&
-                    mb_stripos($lookupResult[200][$searchProperty], $searchValue, 0, 'UTF-8')!==false) {
-                        $matches[] = $lookupResult['href'];
-                }
-
-            }
-
+        $uri = null;
+        if (!$applyToPrincipalCollectionSet) {
+            $uri = $this->server->getRequestUri();
         }
+        $result = $this->principalSearch($searchProperties, $requestedProperties, $uri);
 
-        $matchProperties = array();
-
-        foreach($matches as $match) {
-            
-           list($result) = $this->server->getPropertiesForPath($match, $requestedProperties, 0);
-           $matchProperties[] = $result;
-
-        }
-
-        $xml = $this->server->generateMultiStatus($matchProperties);
+        $xml = $this->server->generateMultiStatus($result);
         $this->server->httpResponse->setHeader('Content-Type','application/xml; charset=utf-8');
         $this->server->httpResponse->sendStatus(207);
         $this->server->httpResponse->sendBody($xml);
@@ -1175,9 +1284,9 @@ class Sabre_DAVACL_Plugin extends Sabre_DAV_ServerPlugin {
      * This method returns an array with two elements:
      *  1. an array with properties to search on, and their values
      *  2. a list of propertyvalues that should be returned for the request.
-     * 
-     * @param DOMDocument $dom 
-     * @return array 
+     *
+     * @param DOMDocument $dom
+     * @return array
      */
     protected function parsePrincipalPropertySearchReportRequest($dom) {
 
@@ -1193,8 +1302,9 @@ class Sabre_DAVACL_Plugin extends Sabre_DAV_ServerPlugin {
         // Parsing the search request
         foreach($dom->firstChild->childNodes as $searchNode) {
 
-            if (Sabre_DAV_XMLUtil::toClarkNotation($searchNode) == '{DAV:}apply-to-principal-collection-set')
+            if (Sabre_DAV_XMLUtil::toClarkNotation($searchNode) == '{DAV:}apply-to-principal-collection-set') {
                 $applyToPrincipalCollectionSet = true;
+            }
 
             if (Sabre_DAV_XMLUtil::toClarkNotation($searchNode)!=='{DAV:}property-search')
                 continue;
@@ -1208,7 +1318,7 @@ class Sabre_DAVACL_Plugin extends Sabre_DAV_ServerPlugin {
 
                     case '{DAV:}prop' :
                         $property = Sabre_DAV_XMLUtil::parseProperties($searchNode);
-                        reset($property); 
+                        reset($property);
                         $propertyName = key($property);
                         break;
 
diff --git a/3rdparty/Sabre/DAVACL/Principal.php b/3rdparty/Sabre/DAVACL/Principal.php
index 790603c900f33f3361bcab9cdbea308744dd1383..51c6658afd64ce3c626682208389965a1ddce361 100644
--- a/3rdparty/Sabre/DAVACL/Principal.php
+++ b/3rdparty/Sabre/DAVACL/Principal.php
@@ -4,17 +4,17 @@
  * Principal class
  *
  * This class is a representation of a simple principal
- * 
- * Many WebDAV specs require a user to show up in the directory 
- * structure. 
+ *
+ * Many WebDAV specs require a user to show up in the directory
+ * structure.
  *
  * This principal also has basic ACL settings, only allowing the principal
- * access it's own principal. 
- * 
+ * access it's own principal.
+ *
  * @package Sabre
  * @subpackage DAVACL
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
- * @author Evert Pot (http://www.rooftopsolutions.nl/) 
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
  */
 class Sabre_DAVACL_Principal extends Sabre_DAV_Node implements Sabre_DAVACL_IPrincipal, Sabre_DAV_IProperties, Sabre_DAVACL_IACL {
@@ -22,20 +22,21 @@ class Sabre_DAVACL_Principal extends Sabre_DAV_Node implements Sabre_DAVACL_IPri
     /**
      * Struct with principal information.
      *
-     * @var array 
+     * @var array
      */
     protected $principalProperties;
 
     /**
-     * Principal backend 
-     * 
-     * @var Sabre_DAVACL_IPrincipalBackend 
+     * Principal backend
+     *
+     * @var Sabre_DAVACL_IPrincipalBackend
      */
     protected $principalBackend;
 
     /**
-     * Creates the principal object 
+     * Creates the principal object
      *
+     * @param Sabre_DAVACL_IPrincipalBackend $principalBackend
      * @param array $principalProperties
      */
     public function __construct(Sabre_DAVACL_IPrincipalBackend $principalBackend, array $principalProperties = array()) {
@@ -49,22 +50,22 @@ class Sabre_DAVACL_Principal extends Sabre_DAV_Node implements Sabre_DAVACL_IPri
     }
 
     /**
-     * Returns the full principal url 
-     * 
-     * @return string 
+     * Returns the full principal url
+     *
+     * @return string
      */
     public function getPrincipalUrl() {
 
         return $this->principalProperties['uri'];
 
-    } 
+    }
 
     /**
-     * Returns a list of altenative urls for a principal
-     * 
+     * Returns a list of alternative urls for a principal
+     *
      * This can for example be an email address, or ldap url.
-     * 
-     * @return array 
+     *
+     * @return array
      */
     public function getAlternateUriSet() {
 
@@ -79,16 +80,16 @@ class Sabre_DAVACL_Principal extends Sabre_DAV_Node implements Sabre_DAVACL_IPri
             $uris[] = 'mailto:' . $this->principalProperties['{http://sabredav.org/ns}email-address'];
         }
 
-        return array_unique($uris); 
+        return array_unique($uris);
 
     }
 
     /**
      * Returns the list of group members
-     * 
+     *
      * If this principal is a group, this function should return
-     * all member principal uri's for the group. 
-     * 
+     * all member principal uri's for the group.
+     *
      * @return array
      */
     public function getGroupMemberSet() {
@@ -99,11 +100,11 @@ class Sabre_DAVACL_Principal extends Sabre_DAV_Node implements Sabre_DAVACL_IPri
 
     /**
      * Returns the list of groups this principal is member of
-     * 
+     *
      * If this principal is a member of a (list of) groups, this function
-     * should return a list of principal uri's for it's members. 
-     * 
-     * @return array 
+     * should return a list of principal uri's for it's members.
+     *
+     * @return array
      */
     public function getGroupMembership() {
 
@@ -117,11 +118,11 @@ class Sabre_DAVACL_Principal extends Sabre_DAV_Node implements Sabre_DAVACL_IPri
      *
      * If this principal is a group, this method sets all the group members.
      * The list of members is always overwritten, never appended to.
-     * 
-     * This method should throw an exception if the members could not be set. 
-     * 
-     * @param array $principals 
-     * @return void 
+     *
+     * This method should throw an exception if the members could not be set.
+     *
+     * @param array $groupMembers
+     * @return void
      */
     public function setGroupMemberSet(array $groupMembers) {
 
@@ -132,22 +133,21 @@ class Sabre_DAVACL_Principal extends Sabre_DAV_Node implements Sabre_DAVACL_IPri
 
     /**
      * Returns this principals name.
-     * 
-     * @return string 
+     *
+     * @return string
      */
     public function getName() {
 
         $uri = $this->principalProperties['uri'];
         list(, $name) = Sabre_DAV_URLUtil::splitPath($uri);
-
         return $name;
 
     }
 
     /**
-     * Returns the name of the user 
-     * 
-     * @return void
+     * Returns the name of the user
+     *
+     * @return string
      */
     public function getDisplayName() {
 
@@ -160,16 +160,16 @@ class Sabre_DAVACL_Principal extends Sabre_DAV_Node implements Sabre_DAVACL_IPri
     }
 
     /**
-     * Returns a list of properties 
-     * 
-     * @param array $requestedProperties 
-     * @return void
+     * Returns a list of properties
+     *
+     * @param array $requestedProperties
+     * @return array
      */
     public function getProperties($requestedProperties) {
 
         $newProperties = array();
         foreach($requestedProperties as $propName) {
-            
+
             if (isset($this->principalProperties[$propName])) {
                 $newProperties[$propName] = $this->principalProperties[$propName];
             }
@@ -177,29 +177,27 @@ class Sabre_DAVACL_Principal extends Sabre_DAV_Node implements Sabre_DAVACL_IPri
         }
 
         return $newProperties;
-        
+
     }
 
     /**
      * Updates this principals properties.
-     *
-     * Currently this is not supported
      * 
-     * @param array $properties
+     * @param array $mutations
      * @see Sabre_DAV_IProperties::updateProperties
-     * @return bool|array 
+     * @return bool|array
      */
-    public function updateProperties($properties) {
+    public function updateProperties($mutations) {
 
-        return false;
+        return $this->principalBackend->updatePrincipal($this->principalProperties['uri'], $mutations);
 
     }
 
     /**
      * Returns the owner principal
      *
-     * This must be a url to a principal, or null if there's no owner 
-     * 
+     * This must be a url to a principal, or null if there's no owner
+     *
      * @return string|null
      */
     public function getOwner() {
@@ -213,8 +211,8 @@ class Sabre_DAVACL_Principal extends Sabre_DAV_Node implements Sabre_DAVACL_IPri
      * Returns a group principal
      *
      * This must be a url to a principal, or null if there's no owner
-     * 
-     * @return string|null 
+     *
+     * @return string|null
      */
     public function getGroup() {
 
@@ -226,20 +224,20 @@ class Sabre_DAVACL_Principal extends Sabre_DAV_Node implements Sabre_DAVACL_IPri
      * Returns a list of ACE's for this node.
      *
      * Each ACE has the following properties:
-     *   * 'privilege', a string such as {DAV:}read or {DAV:}write. These are 
+     *   * 'privilege', a string such as {DAV:}read or {DAV:}write. These are
      *     currently the only supported privileges
      *   * 'principal', a url to the principal who owns the node
-     *   * 'protected' (optional), indicating that this ACE is not allowed to 
-     *      be updated. 
-     * 
-     * @return array 
+     *   * 'protected' (optional), indicating that this ACE is not allowed to
+     *      be updated.
+     *
+     * @return array
      */
     public function getACL() {
 
         return array(
             array(
                 'privilege' => '{DAV:}read',
-                'principal' => $this->principalProperties['uri'],
+                'principal' => $this->getPrincipalUrl(),
                 'protected' => true,
             ),
         );
@@ -249,9 +247,9 @@ class Sabre_DAVACL_Principal extends Sabre_DAV_Node implements Sabre_DAVACL_IPri
     /**
      * Updates the ACL
      *
-     * This method will receive a list of new ACE's. 
-     * 
-     * @param array $acl 
+     * This method will receive a list of new ACE's.
+     *
+     * @param array $acl
      * @return void
      */
     public function setACL(array $acl) {
@@ -260,4 +258,22 @@ class Sabre_DAVACL_Principal extends Sabre_DAV_Node implements Sabre_DAVACL_IPri
 
     }
 
+    /**
+     * Returns the list of supported privileges for this node.
+     *
+     * The returned data structure is a list of nested privileges.
+     * See Sabre_DAVACL_Plugin::getDefaultSupportedPrivilegeSet for a simple
+     * standard structure.
+     *
+     * If null is returned from this method, the default privilege set is used,
+     * which is fine for most common usecases.
+     *
+     * @return array|null
+     */
+    public function getSupportedPrivilegeSet() {
+
+        return null;
+
+    }
+
 }
diff --git a/3rdparty/Sabre/DAVACL/PrincipalBackend/PDO.php b/3rdparty/Sabre/DAVACL/PrincipalBackend/PDO.php
index 55bd1903c9bfe5a626524bcf9f6d01b17eeca78a..a76b4a9d7279dcaf47e7286eb718c237b6ca4d5a 100644
--- a/3rdparty/Sabre/DAVACL/PrincipalBackend/PDO.php
+++ b/3rdparty/Sabre/DAVACL/PrincipalBackend/PDO.php
@@ -3,46 +3,80 @@
 /**
  * PDO principal backend
  *
- * This is a simple principal backend that maps exactly to the users table, as 
+ * This is a simple principal backend that maps exactly to the users table, as
  * used by Sabre_DAV_Auth_Backend_PDO.
  *
- * It assumes all principals are in a single collection. The default collection 
+ * It assumes all principals are in a single collection. The default collection
  * is 'principals/', but this can be overriden.
  *
  * @package Sabre
  * @subpackage DAVACL
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
- * @author Evert Pot (http://www.rooftopsolutions.nl/) 
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
  */
 class Sabre_DAVACL_PrincipalBackend_PDO implements Sabre_DAVACL_IPrincipalBackend {
 
     /**
-     * pdo 
-     * 
-     * @var PDO 
+     * pdo
+     *
+     * @var PDO
      */
     protected $pdo;
 
     /**
-     * PDO table name for 'principals' 
-     * 
-     * @var string 
+     * PDO table name for 'principals'
+     *
+     * @var string
      */
     protected $tableName;
 
     /**
-     * PDO table name for 'group members' 
-     * 
-     * @var string 
+     * PDO table name for 'group members'
+     *
+     * @var string
      */
     protected $groupMembersTableName;
 
+    /**
+     * A list of additional fields to support
+     *
+     * @var array
+     */
+    protected $fieldMap = array(
+
+        /**
+         * This property can be used to display the users' real name.
+         */
+        '{DAV:}displayname' => array(
+            'dbField' => 'displayname',
+        ),
+
+        /**
+         * This property is actually used by the CardDAV plugin, where it gets
+         * mapped to {http://calendarserver.orgi/ns/}me-card.
+         *
+         * The reason we don't straight-up use that property, is because
+         * me-card is defined as a property on the users' addressbook
+         * collection.
+         */
+        '{http://sabredav.org/ns}vcard-url' => array(
+            'dbField' => 'vcardurl',
+        ),
+        /**
+         * This is the users' primary email-address.
+         */
+        '{http://sabredav.org/ns}email-address' => array(
+            'dbField' => 'email',
+        ),
+    );
+
     /**
      * Sets up the backend.
-     * 
+     *
      * @param PDO $pdo
-     * @param string $tableName 
+     * @param string $tableName
+     * @param string $groupMembersTableName
      */
     public function __construct(PDO $pdo, $tableName = 'principals', $groupMembersTableName = 'groupmembers') {
 
@@ -50,27 +84,35 @@ class Sabre_DAVACL_PrincipalBackend_PDO implements Sabre_DAVACL_IPrincipalBacken
         $this->tableName = $tableName;
         $this->groupMembersTableName = $groupMembersTableName;
 
-    } 
+    }
 
 
     /**
      * Returns a list of principals based on a prefix.
      *
-     * This prefix will often contain something like 'principals'. You are only 
+     * This prefix will often contain something like 'principals'. You are only
      * expected to return principals that are in this base path.
      *
-     * You are expected to return at least a 'uri' for every user, you can 
+     * You are expected to return at least a 'uri' for every user, you can
      * return any additional properties if you wish so. Common properties are:
-     *   {DAV:}displayname 
-     *   {http://sabredav.org/ns}email-address - This is a custom SabreDAV 
+     *   {DAV:}displayname
+     *   {http://sabredav.org/ns}email-address - This is a custom SabreDAV
      *     field that's actualy injected in a number of other properties. If
      *     you have an email address, use this property.
-     * 
-     * @param string $prefixPath 
-     * @return array 
+     *
+     * @param string $prefixPath
+     * @return array
      */
     public function getPrincipalsByPrefix($prefixPath) {
-        $result = $this->pdo->query('SELECT uri, email, displayname FROM `'. $this->tableName . '`');
+
+        $fields = array(
+            'uri',
+        );
+
+        foreach($this->fieldMap as $key=>$value) {
+            $fields[] = $value['dbField'];
+        }
+        $result = $this->pdo->query('SELECT '.implode(',', $fields).'  FROM '. $this->tableName);
 
         $principals = array();
 
@@ -80,11 +122,15 @@ class Sabre_DAVACL_PrincipalBackend_PDO implements Sabre_DAVACL_IPrincipalBacken
             list($rowPrefix) = Sabre_DAV_URLUtil::splitPath($row['uri']);
             if ($rowPrefix !== $prefixPath) continue;
 
-            $principals[] = array(
+            $principal = array(
                 'uri' => $row['uri'],
-                '{DAV:}displayname' => $row['displayname']?$row['displayname']:basename($row['uri']),
-                '{http://sabredav.org/ns}email-address' => $row['email'],
             );
+            foreach($this->fieldMap as $key=>$value) {
+                if ($row[$value['dbField']]) {
+                    $principal[$key] = $row[$value['dbField']];
+                }
+            }
+            $principals[] = $principal;
 
         }
 
@@ -94,43 +140,218 @@ class Sabre_DAVACL_PrincipalBackend_PDO implements Sabre_DAVACL_IPrincipalBacken
 
     /**
      * Returns a specific principal, specified by it's path.
-     * The returned structure should be the exact same as from 
-     * getPrincipalsByPrefix. 
-     * 
-     * @param string $path 
-     * @return array 
+     * The returned structure should be the exact same as from
+     * getPrincipalsByPrefix.
+     *
+     * @param string $path
+     * @return array
      */
     public function getPrincipalByPath($path) {
 
-        $stmt = $this->pdo->prepare('SELECT id, uri, email, displayname FROM `'.$this->tableName.'` WHERE uri = ?');
-        $stmt->execute(array($path));
+        $fields = array(
+            'id',
+            'uri',
+        );
 
-        $users = array();
+        foreach($this->fieldMap as $key=>$value) {
+            $fields[] = $value['dbField'];
+        }
+        $stmt = $this->pdo->prepare('SELECT '.implode(',', $fields).'  FROM '. $this->tableName . ' WHERE uri = ?');
+        $stmt->execute(array($path));
 
         $row = $stmt->fetch(PDO::FETCH_ASSOC);
         if (!$row) return;
 
-        return array(
+        $principal = array(
             'id'  => $row['id'],
             'uri' => $row['uri'],
-            '{DAV:}displayname' => $row['displayname']?$row['displayname']:basename($row['uri']),
-            '{http://sabredav.org/ns}email-address' => $row['email'],
         );
+        foreach($this->fieldMap as $key=>$value) {
+            if ($row[$value['dbField']]) {
+                $principal[$key] = $row[$value['dbField']];
+            }
+        }
+        return $principal;
+
+    }
+
+    /**
+     * Updates one ore more webdav properties on a principal.
+     *
+     * The list of mutations is supplied as an array. Each key in the array is
+     * a propertyname, such as {DAV:}displayname.
+     *
+     * Each value is the actual value to be updated. If a value is null, it
+     * must be deleted.
+     *
+     * This method should be atomic. It must either completely succeed, or
+     * completely fail. Success and failure can simply be returned as 'true' or
+     * 'false'.
+     *
+     * It is also possible to return detailed failure information. In that case
+     * an array such as this should be returned:
+     *
+     * array(
+     *   200 => array(
+     *      '{DAV:}prop1' => null,
+     *   ),
+     *   201 => array(
+     *      '{DAV:}prop2' => null,
+     *   ),
+     *   403 => array(
+     *      '{DAV:}prop3' => null,
+     *   ),
+     *   424 => array(
+     *      '{DAV:}prop4' => null,
+     *   ),
+     * );
+     *
+     * In this previous example prop1 was successfully updated or deleted, and
+     * prop2 was succesfully created.
+     *
+     * prop3 failed to update due to '403 Forbidden' and because of this prop4
+     * also could not be updated with '424 Failed dependency'.
+     *
+     * This last example was actually incorrect. While 200 and 201 could appear
+     * in 1 response, if there's any error (403) the other properties should
+     * always fail with 423 (failed dependency).
+     *
+     * But anyway, if you don't want to scratch your head over this, just
+     * return true or false.
+     *
+     * @param string $path
+     * @param array $mutations
+     * @return array|bool
+     */
+    public function updatePrincipal($path, $mutations) {
+
+        $updateAble = array();
+        foreach($mutations as $key=>$value) {
+
+            // We are not aware of this field, we must fail.
+            if (!isset($this->fieldMap[$key])) {
+
+                $response = array(
+                    403 => array(
+                        $key => null,
+                    ),
+                    424 => array(),
+                );
+
+                // Adding the rest to the response as a 424
+                foreach($mutations as $subKey=>$subValue) {
+                    if ($subKey !== $key) {
+                        $response[424][$subKey] = null;
+                    }
+                }
+                return $response;
+            }
+
+            $updateAble[$this->fieldMap[$key]['dbField']] = $value;
+
+        }
+
+        // No fields to update
+        $query = "UPDATE " . $this->tableName . " SET ";
+
+        $first = true;
+        foreach($updateAble as $key => $value) {
+            if (!$first) {
+                $query.= ', ';
+            }
+            $first = false;
+            $query.= "$key = :$key ";
+        }
+        $query.='WHERE uri = :uri';
+        $stmt = $this->pdo->prepare($query);
+        $updateAble['uri'] =  $path;
+        $stmt->execute($updateAble);
+
+        return true;
 
     }
 
     /**
-     * Returns the list of members for a group-principal 
-     * 
-     * @param string $principal 
-     * @return array 
+     * This method is used to search for principals matching a set of
+     * properties.
+     *
+     * This search is specifically used by RFC3744's principal-property-search
+     * REPORT. You should at least allow searching on
+     * http://sabredav.org/ns}email-address.
+     *
+     * The actual search should be a unicode-non-case-sensitive search. The
+     * keys in searchProperties are the WebDAV property names, while the values
+     * are the property values to search on.
+     *
+     * If multiple properties are being searched on, the search should be
+     * AND'ed.
+     *
+     * This method should simply return an array with full principal uri's.
+     *
+     * If somebody attempted to search on a property the backend does not
+     * support, you should simply return 0 results.
+     *
+     * You can also just return 0 results if you choose to not support
+     * searching at all, but keep in mind that this may stop certain features
+     * from working.
+     *
+     * @param string $prefixPath
+     * @param array $searchProperties
+     * @return array
+     */
+    public function searchPrincipals($prefixPath, array $searchProperties) {
+
+        $query = 'SELECT uri FROM ' . $this->tableName . ' WHERE 1=1 ';
+        $values = array();
+        foreach($searchProperties as $property => $value) {
+
+            switch($property) {
+
+                case '{DAV:}displayname' :
+                    $query.=' AND displayname LIKE ?';
+                    $values[] = '%' . $value . '%';
+                    break;
+                case '{http://sabredav.org/ns}email-address' :
+                    $query.=' AND email LIKE ?';
+                    $values[] = '%' . $value . '%';
+                    break;
+                default :
+                    // Unsupported property
+                    return array();
+
+            }
+
+        }
+        $stmt = $this->pdo->prepare($query);
+        $stmt->execute($values);
+
+        $principals = array();
+        while($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
+
+            // Checking if the principal is in the prefix
+            list($rowPrefix) = Sabre_DAV_URLUtil::splitPath($row['uri']);
+            if ($rowPrefix !== $prefixPath) continue;
+
+            $principals[] = $row['uri'];
+
+        }
+
+        return $principals;
+
+    }
+
+    /**
+     * Returns the list of members for a group-principal
+     *
+     * @param string $principal
+     * @return array
      */
     public function getGroupMemberSet($principal) {
 
         $principal = $this->getPrincipalByPath($principal);
         if (!$principal) throw new Sabre_DAV_Exception('Principal not found');
 
-        $stmt = $this->pdo->prepare('SELECT principals.uri as uri FROM `'.$this->groupMembersTableName.'` AS groupmembers LEFT JOIN `'.$this->tableName.'` AS principals ON groupmembers.member_id = principals.id WHERE groupmembers.principal_id = ?');
+        $stmt = $this->pdo->prepare('SELECT principals.uri as uri FROM '.$this->groupMembersTableName.' AS groupmembers LEFT JOIN '.$this->tableName.' AS principals ON groupmembers.member_id = principals.id WHERE groupmembers.principal_id = ?');
         $stmt->execute(array($principal['id']));
 
         $result = array();
@@ -138,21 +359,21 @@ class Sabre_DAVACL_PrincipalBackend_PDO implements Sabre_DAVACL_IPrincipalBacken
             $result[] = $row['uri'];
         }
         return $result;
-    
+
     }
 
     /**
-     * Returns the list of groups a principal is a member of 
-     * 
-     * @param string $principal 
-     * @return array 
+     * Returns the list of groups a principal is a member of
+     *
+     * @param string $principal
+     * @return array
      */
     public function getGroupMembership($principal) {
 
         $principal = $this->getPrincipalByPath($principal);
         if (!$principal) throw new Sabre_DAV_Exception('Principal not found');
 
-        $stmt = $this->pdo->prepare('SELECT principals.uri as uri FROM `'.$this->groupMembersTableName.'` AS groupmembers LEFT JOIN `'.$this->tableName.'` AS principals ON groupmembers.principal_id = principals.id WHERE groupmembers.member_id = ?');
+        $stmt = $this->pdo->prepare('SELECT principals.uri as uri FROM '.$this->groupMembersTableName.' AS groupmembers LEFT JOIN '.$this->tableName.' AS principals ON groupmembers.principal_id = principals.id WHERE groupmembers.member_id = ?');
         $stmt->execute(array($principal['id']));
 
         $result = array();
@@ -166,16 +387,16 @@ class Sabre_DAVACL_PrincipalBackend_PDO implements Sabre_DAVACL_IPrincipalBacken
     /**
      * Updates the list of group members for a group principal.
      *
-     * The principals should be passed as a list of uri's. 
-     * 
-     * @param string $principal 
-     * @param array $members 
+     * The principals should be passed as a list of uri's.
+     *
+     * @param string $principal
+     * @param array $members
      * @return void
      */
     public function setGroupMemberSet($principal, array $members) {
 
         // Grabbing the list of principal id's.
-        $stmt = $this->pdo->prepare('SELECT id, uri FROM `'.$this->tableName.'` WHERE uri IN (? ' . str_repeat(', ? ', count($members)) . ');');
+        $stmt = $this->pdo->prepare('SELECT id, uri FROM '.$this->tableName.' WHERE uri IN (? ' . str_repeat(', ? ', count($members)) . ');');
         $stmt->execute(array_merge(array($principal), $members));
 
         $memberIds = array();
@@ -191,12 +412,12 @@ class Sabre_DAVACL_PrincipalBackend_PDO implements Sabre_DAVACL_IPrincipalBacken
         if (!$principalId) throw new Sabre_DAV_Exception('Principal not found');
 
         // Wiping out old members
-        $stmt = $this->pdo->prepare('DELETE FROM `'.$this->groupMembersTableName.'` WHERE principal_id = ?;');
+        $stmt = $this->pdo->prepare('DELETE FROM '.$this->groupMembersTableName.' WHERE principal_id = ?;');
         $stmt->execute(array($principalId));
 
         foreach($memberIds as $memberId) {
 
-            $stmt = $this->pdo->prepare('INSERT INTO `'.$this->groupMembersTableName.'` (principal_id, member_id) VALUES (?, ?);');
+            $stmt = $this->pdo->prepare('INSERT INTO '.$this->groupMembersTableName.' (principal_id, member_id) VALUES (?, ?);');
             $stmt->execute(array($principalId, $memberId));
 
         }
diff --git a/3rdparty/Sabre/DAVACL/PrincipalCollection.php b/3rdparty/Sabre/DAVACL/PrincipalCollection.php
index 4d22bf8aa7509b5e6d153e8f4788ffa3bbf80df6..c3e4cb83f23c4d004b15c884f0a5253a70c5fbf1 100644
--- a/3rdparty/Sabre/DAVACL/PrincipalCollection.php
+++ b/3rdparty/Sabre/DAVACL/PrincipalCollection.php
@@ -7,11 +7,11 @@
  * Sabre_DAV_Auth_Backend to determine which users are available on the list.
  *
  * The users are instances of Sabre_DAV_Auth_Principal
- * 
+ *
  * @package Sabre
  * @subpackage DAVACL
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
- * @author Evert Pot (http://www.rooftopsolutions.nl/) 
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
  */
 class Sabre_DAVACL_PrincipalCollection extends Sabre_DAVACL_AbstractPrincipalCollection {
@@ -22,9 +22,9 @@ class Sabre_DAVACL_PrincipalCollection extends Sabre_DAVACL_AbstractPrincipalCol
      * The passed array contains principal information, and is guaranteed to
      * at least contain a uri item. Other properties may or may not be
      * supplied by the authentication backend.
-     * 
-     * @param array $principal 
-     * @return Sabre_DAV_INode 
+     *
+     * @param array $principal
+     * @return Sabre_DAV_INode
      */
     public function getChildForPrincipal(array $principal) {
 
diff --git a/3rdparty/Sabre/DAVACL/Property/Acl.php b/3rdparty/Sabre/DAVACL/Property/Acl.php
index e41e7411310af9e7286da705c45ae587ad9431bc..05e1a690b3cb23c1fdb3ba05ce19b18aa41f9fd7 100644
--- a/3rdparty/Sabre/DAVACL/Property/Acl.php
+++ b/3rdparty/Sabre/DAVACL/Property/Acl.php
@@ -1,47 +1,47 @@
 <?php
 
 /**
- * This class represents the {DAV:}acl property 
- * 
+ * This class represents the {DAV:}acl property
+ *
  * @package Sabre
  * @subpackage DAVACL
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
- * @author Evert Pot (http://www.rooftopsolutions.nl/) 
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
  */
 class Sabre_DAVACL_Property_Acl extends Sabre_DAV_Property {
 
     /**
-     * List of privileges 
-     * 
-     * @var array 
+     * List of privileges
+     *
+     * @var array
      */
     private $privileges;
 
     /**
-     * Wether or not the server base url is required to be prefixed when 
-     * serializing the property. 
-     * 
-     * @var boolean 
+     * Whether or not the server base url is required to be prefixed when
+     * serializing the property.
+     *
+     * @var boolean
      */
     private $prefixBaseUrl;
 
     /**
      * Constructor
      *
-     * This object requires a structure similar to the return value from 
+     * This object requires a structure similar to the return value from
      * Sabre_DAVACL_Plugin::getACL().
      *
-     * Each privilege is a an array with at least a 'privilege' property, and a 
-     * 'principal' property. A privilege may have a 'protected' property as 
-     * well. 
+     * Each privilege is a an array with at least a 'privilege' property, and a
+     * 'principal' property. A privilege may have a 'protected' property as
+     * well.
      *
-     * The prefixBaseUrl should be set to false, if the supplied principal urls 
-     * are already full urls. If this is kept to true, the servers base url 
-     * will automatically be prefixed. 
+     * The prefixBaseUrl should be set to false, if the supplied principal urls
+     * are already full urls. If this is kept to true, the servers base url
+     * will automatically be prefixed.
      *
-     * @param bool $prefixBaseUrl 
-     * @param array $privileges 
+     * @param bool $prefixBaseUrl
+     * @param array $privileges
      */
     public function __construct(array $privileges, $prefixBaseUrl = true) {
 
@@ -51,9 +51,9 @@ class Sabre_DAVACL_Property_Acl extends Sabre_DAV_Property {
     }
 
     /**
-     * Returns the list of privileges for this property 
-     * 
-     * @return array 
+     * Returns the list of privileges for this property
+     *
+     * @return array
      */
     public function getPrivileges() {
 
@@ -62,10 +62,10 @@ class Sabre_DAVACL_Property_Acl extends Sabre_DAV_Property {
     }
 
     /**
-     * Serializes the property into a DOMElement 
-     * 
-     * @param Sabre_DAV_Server $server 
-     * @param DOMElement $node 
+     * Serializes the property into a DOMElement
+     *
+     * @param Sabre_DAV_Server $server
+     * @param DOMElement $node
      * @return void
      */
     public function serialize(Sabre_DAV_Server $server,DOMElement $node) {
@@ -80,10 +80,10 @@ class Sabre_DAVACL_Property_Acl extends Sabre_DAV_Property {
     }
 
     /**
-     * Unserializes the {DAV:}acl xml element. 
-     * 
-     * @param DOMElement $dom 
-     * @return Sabre_DAVACL_Property_Acl 
+     * Unserializes the {DAV:}acl xml element.
+     *
+     * @param DOMElement $dom
+     * @return Sabre_DAVACL_Property_Acl
      */
     static public function unserialize(DOMElement $dom) {
 
@@ -98,11 +98,22 @@ class Sabre_DAVACL_Property_Acl extends Sabre_DAV_Property {
             }
             $principal = Sabre_DAVACL_Property_Principal::unserialize($principal->item(0));
 
-            if ($principal->getType()!==Sabre_DAVACL_Property_Principal::HREF) {
-                throw new Sabre_DAV_Exception_NotImplemented('Currently only uri based principals are support, {DAV:}all, {DAV:}unauthenticated and {DAV:}authenticated are not implemented yet');
+            switch($principal->getType()) {
+                case Sabre_DAVACL_Property_Principal::HREF :
+                    $principal = $principal->getHref();
+                    break;
+                case Sabre_DAVACL_Property_Principal::AUTHENTICATED :
+                    $principal = '{DAV:}authenticated';
+                    break;
+                case Sabre_DAVACL_Property_Principal::UNAUTHENTICATED :
+                    $principal = '{DAV:}unauthenticated';
+                    break;
+                case Sabre_DAVACL_Property_Principal::ALL :
+                    $principal = '{DAV:}all';
+                    break;
+
             }
 
-            $principal = $principal->getHref();
             $protected = false;
 
             if ($xace->getElementsByTagNameNS('urn:DAV','protected')->length > 0) {
@@ -140,7 +151,7 @@ class Sabre_DAVACL_Property_Acl extends Sabre_DAV_Property {
                     'privilege' => $privilegeName,
                 );
 
-            } 
+            }
 
         }
 
@@ -149,12 +160,12 @@ class Sabre_DAVACL_Property_Acl extends Sabre_DAV_Property {
     }
 
     /**
-     * Serializes a single access control entry. 
-     * 
-     * @param DOMDocument $doc 
-     * @param DOMElement $node 
+     * Serializes a single access control entry.
+     *
+     * @param DOMDocument $doc
+     * @param DOMElement $node
      * @param array $ace
-     * @param Sabre_DAV_Server $server 
+     * @param Sabre_DAV_Server $server
      * @return void
      */
     private function serializeAce($doc,$node,$ace, $server) {
@@ -164,7 +175,19 @@ class Sabre_DAVACL_Property_Acl extends Sabre_DAV_Property {
 
         $principal = $doc->createElementNS('DAV:','d:principal');
         $xace->appendChild($principal);
-        $principal->appendChild($doc->createElementNS('DAV:','d:href',($this->prefixBaseUrl?$server->getBaseUri():'') . $ace['principal'] . '/'));
+        switch($ace['principal']) {
+            case '{DAV:}authenticated' :
+                $principal->appendChild($doc->createElementNS('DAV:','d:authenticated'));
+                break;
+            case '{DAV:}unauthenticated' :
+                $principal->appendChild($doc->createElementNS('DAV:','d:unauthenticated'));
+                break;
+            case '{DAV:}all' :
+                $principal->appendChild($doc->createElementNS('DAV:','d:all'));
+                break;
+            default:
+                $principal->appendChild($doc->createElementNS('DAV:','d:href',($this->prefixBaseUrl?$server->getBaseUri():'') . $ace['principal'] . '/'));
+        }
 
         $grant = $doc->createElementNS('DAV:','d:grant');
         $xace->appendChild($grant);
diff --git a/3rdparty/Sabre/DAVACL/Property/AclRestrictions.php b/3rdparty/Sabre/DAVACL/Property/AclRestrictions.php
new file mode 100644
index 0000000000000000000000000000000000000000..a8b054956ddc705eb1e6b01c9610199ae02199d7
--- /dev/null
+++ b/3rdparty/Sabre/DAVACL/Property/AclRestrictions.php
@@ -0,0 +1,32 @@
+<?php
+
+/**
+ * AclRestrictions property
+ *
+ * This property represents {DAV:}acl-restrictions, as defined in RFC3744.
+ *
+ * @package Sabre
+ * @subpackage DAVACL
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
+ * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
+ */
+class Sabre_DAVACL_Property_AclRestrictions extends Sabre_DAV_Property {
+
+    /**
+     * Serializes the property into a DOMElement
+     *
+     * @param Sabre_DAV_Server $server
+     * @param DOMElement $elem
+     * @return void
+     */
+    public function serialize(Sabre_DAV_Server $server,DOMElement $elem) {
+
+        $doc = $elem->ownerDocument;
+
+        $elem->appendChild($doc->createElementNS('DAV:','d:grant-only'));
+        $elem->appendChild($doc->createElementNS('DAV:','d:no-invert'));
+
+    }
+
+}
diff --git a/3rdparty/Sabre/DAVACL/Property/CurrentUserPrivilegeSet.php b/3rdparty/Sabre/DAVACL/Property/CurrentUserPrivilegeSet.php
index 72274597b3194c5309039799b9cad51417b83cb8..94a29640615ecdb4229d8a8971b8811edb33933e 100644
--- a/3rdparty/Sabre/DAVACL/Property/CurrentUserPrivilegeSet.php
+++ b/3rdparty/Sabre/DAVACL/Property/CurrentUserPrivilegeSet.php
@@ -2,31 +2,31 @@
 
 /**
  * CurrentUserPrivilegeSet
- * 
- * This class represents the current-user-privilege-set property. When 
- * requested, it contain all the privileges a user has on a specific node. 
- * 
+ *
+ * This class represents the current-user-privilege-set property. When
+ * requested, it contain all the privileges a user has on a specific node.
+ *
  * @package Sabre
  * @subpackage DAVACL
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
- * @author Evert Pot (http://www.rooftopsolutions.nl/) 
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
  */
 class Sabre_DAVACL_Property_CurrentUserPrivilegeSet extends Sabre_DAV_Property {
 
     /**
-     * List of privileges 
-     * 
-     * @var array 
+     * List of privileges
+     *
+     * @var array
      */
     private $privileges;
 
     /**
      * Creates the object
      *
-     * Pass the privileges in clark-notation 
-     * 
-     * @param array $privileges 
+     * Pass the privileges in clark-notation
+     *
+     * @param array $privileges
      */
     public function __construct(array $privileges) {
 
@@ -35,10 +35,10 @@ class Sabre_DAVACL_Property_CurrentUserPrivilegeSet extends Sabre_DAV_Property {
     }
 
     /**
-     * Serializes the property in the DOM 
-     * 
-     * @param Sabre_DAV_Server $server 
-     * @param DOMElement $node 
+     * Serializes the property in the DOM
+     *
+     * @param Sabre_DAV_Server $server
+     * @param DOMElement $node
      * @return void
      */
     public function serialize(Sabre_DAV_Server $server,DOMElement $node) {
@@ -53,11 +53,11 @@ class Sabre_DAVACL_Property_CurrentUserPrivilegeSet extends Sabre_DAV_Property {
     }
 
     /**
-     * Serializes one privilege 
-     * 
-     * @param DOMDocument $doc 
-     * @param DOMElement $node 
-     * @param string $privName 
+     * Serializes one privilege
+     *
+     * @param DOMDocument $doc
+     * @param DOMElement $node
+     * @param string $privName
      * @return void
      */
     protected function serializePriv($doc,$node,$privName) {
diff --git a/3rdparty/Sabre/DAVACL/Property/Principal.php b/3rdparty/Sabre/DAVACL/Property/Principal.php
index dad9a3550fb5678f493d74dd8efcaacc6d77ca53..c36328a58e0b877086d43bb34f02050f5a0a1c8e 100644
--- a/3rdparty/Sabre/DAVACL/Property/Principal.php
+++ b/3rdparty/Sabre/DAVACL/Property/Principal.php
@@ -4,12 +4,12 @@
  * Principal property
  *
  * The principal property represents a principal from RFC3744 (ACL).
- * The property can be used to specify a principal or pseudo principals. 
+ * The property can be used to specify a principal or pseudo principals.
  *
  * @package Sabre
  * @subpackage DAVACL
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
- * @author Evert Pot (http://www.rooftopsolutions.nl/) 
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
  */
 class Sabre_DAVACL_Property_Principal extends Sabre_DAV_Property implements Sabre_DAV_Property_IHref {
@@ -25,16 +25,21 @@ class Sabre_DAVACL_Property_Principal extends Sabre_DAV_Property implements Sabr
     const AUTHENTICATED = 2;
 
     /**
-     * Specific princpals can be specified with the HREF
+     * Specific principals can be specified with the HREF
      */
     const HREF = 3;
 
+    /**
+     * Everybody, basically
+     */
+    const ALL = 4;
+
     /**
      * Principal-type
      *
      * Must be one of the UNAUTHENTICATED, AUTHENTICATED or HREF constants.
-     * 
-     * @var int 
+     *
+     * @var int
      */
     private $type;
 
@@ -42,8 +47,8 @@ class Sabre_DAVACL_Property_Principal extends Sabre_DAV_Property implements Sabr
      * Url to principal
      *
      * This value is only used for the HREF principal type.
-     * 
-     * @var string 
+     *
+     * @var string
      */
     private $href;
 
@@ -53,10 +58,9 @@ class Sabre_DAVACL_Property_Principal extends Sabre_DAV_Property implements Sabr
      * The 'type' argument must be one of the type constants defined in this class.
      *
      * 'href' is only required for the HREF type.
-     * 
-     * @param int $type 
-     * @param string $href 
-     * @return void
+     *
+     * @param int $type
+     * @param string|null $href
      */
     public function __construct($type, $href = null) {
 
@@ -70,9 +74,9 @@ class Sabre_DAVACL_Property_Principal extends Sabre_DAV_Property implements Sabr
     }
 
     /**
-     * Returns the principal type 
-     * 
-     * @return int 
+     * Returns the principal type
+     *
+     * @return int
      */
     public function getType() {
 
@@ -81,8 +85,8 @@ class Sabre_DAVACL_Property_Principal extends Sabre_DAV_Property implements Sabr
     }
 
     /**
-     * Returns the principal uri. 
-     * 
+     * Returns the principal uri.
+     *
      * @return string
      */
     public function getHref() {
@@ -92,10 +96,10 @@ class Sabre_DAVACL_Property_Principal extends Sabre_DAV_Property implements Sabr
     }
 
     /**
-     * Serializes the property into a DOMElement. 
-     * 
-     * @param Sabre_DAV_Server $server 
-     * @param DOMElement $node 
+     * Serializes the property into a DOMElement.
+     *
+     * @param Sabre_DAV_Server $server
+     * @param DOMElement $node
      * @return void
      */
     public function serialize(Sabre_DAV_Server $server, DOMElement $node) {
@@ -124,10 +128,10 @@ class Sabre_DAVACL_Property_Principal extends Sabre_DAV_Property implements Sabr
     }
 
     /**
-     * Deserializes a DOM element into a property object. 
-     * 
-     * @param DOMElement $dom 
-     * @return Sabre_DAV_Property_Principal 
+     * Deserializes a DOM element into a property object.
+     *
+     * @param DOMElement $dom
+     * @return Sabre_DAV_Property_Principal
      */
     static public function unserialize(DOMElement $dom) {
 
@@ -144,6 +148,8 @@ class Sabre_DAVACL_Property_Principal extends Sabre_DAV_Property implements Sabr
                 return new self(self::AUTHENTICATED);
             case '{DAV:}href':
                 return new self(self::HREF, $parent->textContent);
+            case '{DAV:}all':
+                return new self(self::ALL);
             default :
                 throw new Sabre_DAV_Exception_BadRequest('Unexpected element (' . Sabre_DAV_XMLUtil::toClarkNotation($parent) . '). Could not deserialize');
 
diff --git a/3rdparty/Sabre/DAVACL/Property/SupportedPrivilegeSet.php b/3rdparty/Sabre/DAVACL/Property/SupportedPrivilegeSet.php
index 93c3895035d0a44c115ce095a0b3e4bda0406380..276d57ae0938fca6cde2f195a2cbbece0ed1c8df 100644
--- a/3rdparty/Sabre/DAVACL/Property/SupportedPrivilegeSet.php
+++ b/3rdparty/Sabre/DAVACL/Property/SupportedPrivilegeSet.php
@@ -3,32 +3,32 @@
 /**
  * SupportedPrivilegeSet property
  *
- * This property encodes the {DAV:}supported-privilege-set property, as defined 
+ * This property encodes the {DAV:}supported-privilege-set property, as defined
  * in rfc3744. Please consult the rfc for details about it's structure.
  *
- * This class expects a structure like the one given from 
- * Sabre_DAVACL_Plugin::getSupportedPrivilegeSet as the argument in its 
+ * This class expects a structure like the one given from
+ * Sabre_DAVACL_Plugin::getSupportedPrivilegeSet as the argument in its
  * constructor.
- *   
+ *
  * @package Sabre
  * @subpackage DAVACL
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
- * @author Evert Pot (http://www.rooftopsolutions.nl/) 
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
  */
 class Sabre_DAVACL_Property_SupportedPrivilegeSet extends Sabre_DAV_Property {
 
     /**
-     * privileges 
-     * 
-     * @var array 
+     * privileges
+     *
+     * @var array
      */
     private $privileges;
 
     /**
-     * Constructor 
-     * 
-     * @param array $privileges 
+     * Constructor
+     *
+     * @param array $privileges
      */
     public function __construct(array $privileges) {
 
@@ -37,10 +37,10 @@ class Sabre_DAVACL_Property_SupportedPrivilegeSet extends Sabre_DAV_Property {
     }
 
     /**
-     * Serializes the property into a domdocument. 
-     * 
-     * @param Sabre_DAV_Server $server 
-     * @param DOMElement $node 
+     * Serializes the property into a domdocument.
+     *
+     * @param Sabre_DAV_Server $server
+     * @param DOMElement $node
      * @return void
      */
     public function serialize(Sabre_DAV_Server $server,DOMElement $node) {
@@ -53,11 +53,11 @@ class Sabre_DAVACL_Property_SupportedPrivilegeSet extends Sabre_DAV_Property {
     /**
      * Serializes a property
      *
-     * This is a recursive function. 
-     * 
-     * @param DOMDocument $doc 
-     * @param DOMElement $node 
-     * @param array $privilege 
+     * This is a recursive function.
+     *
+     * @param DOMDocument $doc
+     * @param DOMElement $node
+     * @param array $privilege
      * @return void
      */
     private function serializePriv($doc,$node,$privilege) {
@@ -81,7 +81,7 @@ class Sabre_DAVACL_Property_SupportedPrivilegeSet extends Sabre_DAV_Property {
             $xsp->appendChild($doc->createElementNS('DAV:','d:description',$privilege['description']));
         }
 
-        if (isset($privilege['aggregates'])) { 
+        if (isset($privilege['aggregates'])) {
             foreach($privilege['aggregates'] as $subPrivilege) {
                 $this->serializePriv($doc,$xsp,$subPrivilege);
             }
diff --git a/3rdparty/Sabre/DAVACL/Version.php b/3rdparty/Sabre/DAVACL/Version.php
index 124463e311e1c04d01acbc1f9da56e5d6d38bc4e..9950f748741b150087c6504afb6a65df5a005aef 100644
--- a/3rdparty/Sabre/DAVACL/Version.php
+++ b/3rdparty/Sabre/DAVACL/Version.php
@@ -2,10 +2,10 @@
 
 /**
  * This class contains the SabreDAV version constants.
- * 
+ *
  * @package Sabre
  * @subpackage DAVACL
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
  * @author Evert Pot (http://www.rooftopsolutions.nl/)
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
  */
@@ -14,7 +14,7 @@ class Sabre_DAVACL_Version {
     /**
      * Full version number
      */
-    const VERSION = '1.5.2';
+    const VERSION = '1.6.0';
 
     /**
      * Stability : alpha, beta, stable
diff --git a/3rdparty/Sabre/DAVACL/includes.php b/3rdparty/Sabre/DAVACL/includes.php
new file mode 100644
index 0000000000000000000000000000000000000000..28fa3eed2258e771e831e02e2c57f652435049f1
--- /dev/null
+++ b/3rdparty/Sabre/DAVACL/includes.php
@@ -0,0 +1,38 @@
+<?php
+
+/**
+ * Sabre_DAVACL includes file
+ *
+ * Including this file will automatically include all files from the
+ * Sabre_DAVACL package.
+ *
+ * This often allows faster loadtimes, as autoload-speed is often quite slow.
+ *
+ * @package Sabre
+ * @subpackage DAVACL
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
+ * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
+ */
+
+// Begin includes
+include __DIR__ . '/AbstractPrincipalCollection.php';
+include __DIR__ . '/Exception/AceConflict.php';
+include __DIR__ . '/Exception/NeedPrivileges.php';
+include __DIR__ . '/Exception/NoAbstract.php';
+include __DIR__ . '/Exception/NotRecognizedPrincipal.php';
+include __DIR__ . '/Exception/NotSupportedPrivilege.php';
+include __DIR__ . '/IACL.php';
+include __DIR__ . '/IPrincipal.php';
+include __DIR__ . '/IPrincipalBackend.php';
+include __DIR__ . '/Plugin.php';
+include __DIR__ . '/Principal.php';
+include __DIR__ . '/PrincipalBackend/PDO.php';
+include __DIR__ . '/PrincipalCollection.php';
+include __DIR__ . '/Property/Acl.php';
+include __DIR__ . '/Property/AclRestrictions.php';
+include __DIR__ . '/Property/CurrentUserPrivilegeSet.php';
+include __DIR__ . '/Property/Principal.php';
+include __DIR__ . '/Property/SupportedPrivilegeSet.php';
+include __DIR__ . '/Version.php';
+// End includes
diff --git a/3rdparty/Sabre/HTTP/AWSAuth.php b/3rdparty/Sabre/HTTP/AWSAuth.php
index 5e4668cd94d8ff35589282aa4af9d9cba2d828bd..fb8245c8cbf71d15b0aac05a2953387382842b32 100644
--- a/3rdparty/Sabre/HTTP/AWSAuth.php
+++ b/3rdparty/Sabre/HTTP/AWSAuth.php
@@ -4,34 +4,34 @@
  * HTTP AWS Authentication handler
  *
  * Use this class to leverage amazon's AWS authentication header
- * 
+ *
  * @package Sabre
- * @subpackage HTTP 
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
- * @author Evert Pot (http://www.rooftopsolutions.nl/) 
+ * @subpackage HTTP
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
  */
 class Sabre_HTTP_AWSAuth extends Sabre_HTTP_AbstractAuth {
 
     /**
-     * The signature supplied by the HTTP client 
-     * 
-     * @var string 
+     * The signature supplied by the HTTP client
+     *
+     * @var string
      */
     private $signature = null;
 
     /**
-     * The accesskey supplied by the HTTP client 
-     * 
-     * @var string 
+     * The accesskey supplied by the HTTP client
+     *
+     * @var string
      */
     private $accessKey = null;
 
     /**
      * An error code, if any
      *
-     * This value will be filled with one of the ERR_* contants
-     * 
+     * This value will be filled with one of the ERR_* constants
+     *
      * @var int
      */
     public $errorCode = 0;
@@ -46,8 +46,8 @@ class Sabre_HTTP_AWSAuth extends Sabre_HTTP_AbstractAuth {
      * Gathers all information from the headers
      *
      * This method needs to be called prior to anything else.
-     * 
-     * @return bool 
+     *
+     * @return bool
      */
     public function init() {
 
@@ -66,9 +66,9 @@ class Sabre_HTTP_AWSAuth extends Sabre_HTTP_AbstractAuth {
     }
 
     /**
-     * Returns the username for the request 
-     * 
-     * @return string 
+     * Returns the username for the request
+     *
+     * @return string
      */
     public function getAccessKey() {
 
@@ -78,8 +78,9 @@ class Sabre_HTTP_AWSAuth extends Sabre_HTTP_AbstractAuth {
 
     /**
      * Validates the signature based on the secretKey
-     * 
-     * @return bool 
+     *
+     * @param string $secretKey
+     * @return bool
      */
     public function validate($secretKey) {
 
@@ -89,7 +90,7 @@ class Sabre_HTTP_AWSAuth extends Sabre_HTTP_AbstractAuth {
             // We need to validate the integrity of the request
             $body = $this->httpRequest->getBody(true);
             $this->httpRequest->setBody($body,true);
-           
+
             if ($contentMD5!=base64_encode(md5($body,true))) {
                 // content-md5 header did not match md5 signature of body
                 $this->errorCode = self::ERR_MD5CHECKSUMWRONG;
@@ -98,10 +99,10 @@ class Sabre_HTTP_AWSAuth extends Sabre_HTTP_AbstractAuth {
 
         }
 
-        if (!$requestDate = $this->httpRequest->getHeader('x-amz-date')) 
+        if (!$requestDate = $this->httpRequest->getHeader('x-amz-date'))
             $requestDate = $this->httpRequest->getHeader('Date');
 
-        if (!$this->validateRFC2616Date($requestDate)) 
+        if (!$this->validateRFC2616Date($requestDate))
             return false;
 
         $amzHeaders = $this->getAmzHeaders();
@@ -109,10 +110,10 @@ class Sabre_HTTP_AWSAuth extends Sabre_HTTP_AbstractAuth {
         $signature = base64_encode(
             $this->hmacsha1($secretKey,
                 $this->httpRequest->getMethod() . "\n" .
-                $contentMD5 . "\n" . 
+                $contentMD5 . "\n" .
                 $this->httpRequest->getHeader('Content-type') . "\n" .
                 $requestDate . "\n" .
-                $amzHeaders . 
+                $amzHeaders .
                 $this->httpRequest->getURI()
             )
         );
@@ -146,14 +147,14 @@ class Sabre_HTTP_AWSAuth extends Sabre_HTTP_AbstractAuth {
     /**
      * Makes sure the supplied value is a valid RFC2616 date.
      *
-     * If we would just use strtotime to get a valid timestamp, we have no way of checking if a 
+     * If we would just use strtotime to get a valid timestamp, we have no way of checking if a
      * user just supplied the word 'now' for the date header.
      *
-     * This function also makes sure the Date header is within 15 minutes of the operating 
+     * This function also makes sure the Date header is within 15 minutes of the operating
      * system date, to prevent replay attacks.
-     * 
-     * @param string $dateHeader 
-     * @return bool 
+     *
+     * @param string $dateHeader
+     * @return bool
      */
     protected function validateRFC2616Date($dateHeader) {
 
@@ -177,11 +178,11 @@ class Sabre_HTTP_AWSAuth extends Sabre_HTTP_AbstractAuth {
         return $date;
 
     }
-    
+
     /**
-     * Returns a list of AMZ headers 
-     * 
-     * @return void
+     * Returns a list of AMZ headers
+     *
+     * @return string
      */
     protected function getAmzHeaders() {
 
@@ -193,7 +194,7 @@ class Sabre_HTTP_AWSAuth extends Sabre_HTTP_AbstractAuth {
             }
         }
         ksort($amzHeaders);
-       
+
         $headerStr = '';
         foreach($amzHeaders as $h=>$v) {
             $headerStr.=$h.':'.$v;
@@ -204,11 +205,11 @@ class Sabre_HTTP_AWSAuth extends Sabre_HTTP_AbstractAuth {
     }
 
     /**
-     * Generates an HMAC-SHA1 signature 
-     * 
-     * @param string $key 
-     * @param string $message 
-     * @return string 
+     * Generates an HMAC-SHA1 signature
+     *
+     * @param string $key
+     * @param string $message
+     * @return string
      */
     private function hmacsha1($key, $message) {
 
diff --git a/3rdparty/Sabre/HTTP/AbstractAuth.php b/3rdparty/Sabre/HTTP/AbstractAuth.php
index eb528f6fdee56dd507f63eb511952ff6298d49d2..3bccabcd1c17833aded522cc77214f84175337f3 100644
--- a/3rdparty/Sabre/HTTP/AbstractAuth.php
+++ b/3rdparty/Sabre/HTTP/AbstractAuth.php
@@ -4,10 +4,10 @@
  * HTTP Authentication baseclass
  *
  * This class has the common functionality for BasicAuth and DigestAuth
- * 
+ *
  * @package Sabre
- * @subpackage HTTP 
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
+ * @subpackage HTTP
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
  * @author Evert Pot (http://www.rooftopsolutions.nl/) 
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
  */
@@ -17,29 +17,29 @@ abstract class Sabre_HTTP_AbstractAuth {
      * The realm will be displayed in the dialog boxes
      *
      * This identifier can be changed through setRealm()
-     * 
+     *
      * @var string
      */
     protected $realm = 'SabreDAV';
 
     /**
-     * HTTP response helper 
-     * 
-     * @var Sabre_HTTP_Response 
+     * HTTP response helper
+     *
+     * @var Sabre_HTTP_Response
      */
     protected $httpResponse;
 
 
     /**
-     * HTTP request helper 
-     * 
-     * @var Sabre_HTTP_Request 
+     * HTTP request helper
+     *
+     * @var Sabre_HTTP_Request
      */
     protected $httpRequest;
 
     /**
-     * __construct 
-     * 
+     * __construct
+     *
      */
     public function __construct() {
 
@@ -49,9 +49,9 @@ abstract class Sabre_HTTP_AbstractAuth {
     }
 
     /**
-     * Sets an alternative HTTP response object 
-     * 
-     * @param Sabre_HTTP_Response $response 
+     * Sets an alternative HTTP response object
+     *
+     * @param Sabre_HTTP_Response $response
      * @return void
      */
     public function setHTTPResponse(Sabre_HTTP_Response $response) {
@@ -61,9 +61,9 @@ abstract class Sabre_HTTP_AbstractAuth {
     }
 
     /**
-     * Sets an alternative HTTP request object 
-     * 
-     * @param Sabre_HTTP_Request $request 
+     * Sets an alternative HTTP request object
+     *
+     * @param Sabre_HTTP_Request $request
      * @return void
      */
     public function setHTTPRequest(Sabre_HTTP_Request $request) {
@@ -78,8 +78,8 @@ abstract class Sabre_HTTP_AbstractAuth {
      *
      * The realm is often displayed in authentication dialog boxes
      * Commonly an application name displayed here
-     * 
-     * @param string $realm 
+     *
+     * @param string $realm
      * @return void
      */
     public function setRealm($realm) {
@@ -91,7 +91,7 @@ abstract class Sabre_HTTP_AbstractAuth {
     /**
      * Returns the realm
      *
-     * @return string 
+     * @return string
      */
     public function getRealm() {
 
@@ -106,6 +106,6 @@ abstract class Sabre_HTTP_AbstractAuth {
      *
      * @return void
      */
-    abstract public function requireLogin(); 
+    abstract public function requireLogin();
 
 }
diff --git a/3rdparty/Sabre/HTTP/BasicAuth.php b/3rdparty/Sabre/HTTP/BasicAuth.php
index 35c22d22dc3837dcd51fe7d87f654b9ff3c1ce18..a747cc6a31bf134e2b409d4d39d002d12e38c6f9 100644
--- a/3rdparty/Sabre/HTTP/BasicAuth.php
+++ b/3rdparty/Sabre/HTTP/BasicAuth.php
@@ -4,11 +4,11 @@
  * HTTP Basic Authentication handler
  *
  * Use this class for easy http authentication setup
- * 
+ *
  * @package Sabre
- * @subpackage HTTP 
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
- * @author Evert Pot (http://www.rooftopsolutions.nl/) 
+ * @subpackage HTTP
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
  */
 class Sabre_HTTP_BasicAuth extends Sabre_HTTP_AbstractAuth {
@@ -22,7 +22,7 @@ class Sabre_HTTP_BasicAuth extends Sabre_HTTP_AbstractAuth {
      *
      * If nothing was supplied, 'false' will be returned
      *
-     * @return mixed 
+     * @return mixed
      */
     public function getUserPass() {
 
@@ -33,12 +33,18 @@ class Sabre_HTTP_BasicAuth extends Sabre_HTTP_AbstractAuth {
 
         }
 
-        // Most other webservers 
+        // Most other webservers
         $auth = $this->httpRequest->getHeader('Authorization');
 
+        // Apache could prefix environment variables with REDIRECT_ when urls
+        // are passed through mod_rewrite
+        if (!$auth) {
+            $auth = $this->httpRequest->getRawServerValue('REDIRECT_HTTP_AUTHORIZATION');
+        }
+
         if (!$auth) return false;
 
-        if (strpos(strtolower($auth),'basic')!==0) return false; 
+        if (strpos(strtolower($auth),'basic')!==0) return false;
 
         return explode(':', base64_decode(substr($auth, 6)));
 
diff --git a/3rdparty/Sabre/HTTP/DigestAuth.php b/3rdparty/Sabre/HTTP/DigestAuth.php
index 5e7559295710025ba5bd86f777f75b68a1fac17e..ee7f05c08ed848d61945d938200de5908bb6929d 100644
--- a/3rdparty/Sabre/HTTP/DigestAuth.php
+++ b/3rdparty/Sabre/HTTP/DigestAuth.php
@@ -10,18 +10,18 @@
  *  2. Call the setRealm() method with the realm you plan to use
  *  3. Call the init method function.
  *  4. Call the getUserName() function. This function may return false if no
- *     authentication information was supplied. Based on the username you 
+ *     authentication information was supplied. Based on the username you
  *     should check your internal database for either the associated password,
  *     or the so-called A1 hash of the digest.
  *  5. Call either validatePassword() or validateA1(). This will return true
- *     or false. 
+ *     or false.
  *  6. To make sure an authentication prompt is displayed, call the
  *     requireLogin() method.
- * 
- * 
+ *
+ *
  * @package Sabre
- * @subpackage HTTP 
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
+ * @subpackage HTTP
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
  * @author Evert Pot (http://www.rooftopsolutions.nl/) 
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
  */
@@ -40,7 +40,7 @@ class Sabre_HTTP_DigestAuth extends Sabre_HTTP_AbstractAuth {
     protected $qop = self::QOP_AUTH;
 
     /**
-     * Initializes the object 
+     * Initializes the object
      */
     public function __construct() {
 
@@ -54,7 +54,7 @@ class Sabre_HTTP_DigestAuth extends Sabre_HTTP_AbstractAuth {
      * Gathers all information from the headers
      *
      * This method needs to be called prior to anything else.
-     * 
+     *
      * @return void
      */
     public function init() {
@@ -73,11 +73,11 @@ class Sabre_HTTP_DigestAuth extends Sabre_HTTP_AbstractAuth {
      *
      * Multiple values can be specified using logical OR.
      *
-     * QOP_AUTHINT ensures integrity of the request body, but this is not 
-     * supported by most HTTP clients. QOP_AUTHINT also requires the entire 
+     * QOP_AUTHINT ensures integrity of the request body, but this is not
+     * supported by most HTTP clients. QOP_AUTHINT also requires the entire
      * request body to be md5'ed, which can put strains on CPU and memory.
      *
-     * @param int $qop 
+     * @param int $qop
      * @return void
      */
     public function setQOP($qop) {
@@ -91,8 +91,8 @@ class Sabre_HTTP_DigestAuth extends Sabre_HTTP_AbstractAuth {
      *
      * The A1 parameter should be md5($username . ':' . $realm . ':' . $password);
      *
-     * @param string $A1 
-     * @return bool 
+     * @param string $A1
+     * @return bool
      */
     public function validateA1($A1) {
 
@@ -104,9 +104,9 @@ class Sabre_HTTP_DigestAuth extends Sabre_HTTP_AbstractAuth {
     /**
      * Validates authentication through a password. The actual password must be provided here.
      * It is strongly recommended not store the password in plain-text and use validateA1 instead.
-     * 
-     * @param string $password 
-     * @return bool 
+     *
+     * @param string $password
+     * @return bool
      */
     public function validatePassword($password) {
 
@@ -116,9 +116,9 @@ class Sabre_HTTP_DigestAuth extends Sabre_HTTP_AbstractAuth {
     }
 
     /**
-     * Returns the username for the request 
-     * 
-     * @return string 
+     * Returns the username for the request
+     *
+     * @return string
      */
     public function getUsername() {
 
@@ -127,14 +127,14 @@ class Sabre_HTTP_DigestAuth extends Sabre_HTTP_AbstractAuth {
     }
 
     /**
-     * Validates the digest challenge 
-     * 
-     * @return bool 
+     * Validates the digest challenge
+     *
+     * @return bool
      */
     protected function validate() {
 
         $A2 = $this->httpRequest->getMethod() . ':' . $this->digestParts['uri'];
-    
+
         if ($this->digestParts['qop']=='auth-int') {
             // Making sure we support this qop value
             if (!($this->qop & self::QOP_AUTHINT)) return false;
@@ -144,16 +144,16 @@ class Sabre_HTTP_DigestAuth extends Sabre_HTTP_AbstractAuth {
             $A2 .= ':' . md5($body);
         } else {
 
-            // We need to make sure we support this qop value 
-            if (!($this->qop & self::QOP_AUTH)) return false; 
+            // We need to make sure we support this qop value
+            if (!($this->qop & self::QOP_AUTH)) return false;
         }
 
         $A2 = md5($A2);
 
-        $validResponse = md5("{$this->A1}:{$this->digestParts['nonce']}:{$this->digestParts['nc']}:{$this->digestParts['cnonce']}:{$this->digestParts['qop']}:{$A2}"); 
+        $validResponse = md5("{$this->A1}:{$this->digestParts['nonce']}:{$this->digestParts['nc']}:{$this->digestParts['cnonce']}:{$this->digestParts['qop']}:{$A2}");
 
         return $this->digestParts['response']==$validResponse;
-        
+
 
     }
 
@@ -186,7 +186,7 @@ class Sabre_HTTP_DigestAuth extends Sabre_HTTP_AbstractAuth {
      *
      * If the header could not be found, null will be returned
      *
-     * @return mixed 
+     * @return mixed
      */
     public function getDigest() {
 
@@ -197,6 +197,12 @@ class Sabre_HTTP_DigestAuth extends Sabre_HTTP_AbstractAuth {
         // most other servers
         $digest = $this->httpRequest->getHeader('Authorization');
 
+        // Apache could prefix environment variables with REDIRECT_ when urls
+        // are passed through mod_rewrite
+        if (!$digest) {
+            $digest = $this->httpRequest->getRawServerValue('REDIRECT_HTTP_AUTHORIZATION');
+        }
+
         if ($digest && strpos(strtolower($digest),'digest')===0) {
             return substr($digest,7);
         } else {
@@ -208,11 +214,11 @@ class Sabre_HTTP_DigestAuth extends Sabre_HTTP_AbstractAuth {
 
     /**
      * Parses the different pieces of the digest string into an array.
-     * 
+     *
      * This method returns false if an incomplete digest was supplied
      *
-     * @param string $digest 
-     * @return mixed 
+     * @param string $digest
+     * @return mixed
      */
     protected function parseDigest($digest) {
 
@@ -227,7 +233,7 @@ class Sabre_HTTP_DigestAuth extends Sabre_HTTP_AbstractAuth {
             unset($needed_parts[$m[1]]);
         }
 
-        return $needed_parts ? false : $data; 
+        return $needed_parts ? false : $data;
 
     }
 
diff --git a/3rdparty/Sabre/HTTP/Request.php b/3rdparty/Sabre/HTTP/Request.php
index 95a64171aab612faed7a2459f7bbedb4d983d3a7..4746ef777047e06b4b3c3ec0dd01267c749f7460 100644
--- a/3rdparty/Sabre/HTTP/Request.php
+++ b/3rdparty/Sabre/HTTP/Request.php
@@ -6,74 +6,85 @@
  * This object can be used to easily access information about an HTTP request.
  * It can additionally be used to create 'mock' requests.
  *
- * This class mostly operates indepentend, but because of the nature of a single 
- * request per run it can operate as a singleton. For more information check out 
+ * This class mostly operates independent, but because of the nature of a single
+ * request per run it can operate as a singleton. For more information check out
  * the behaviour around 'defaultInputStream'.
  *
  * @package Sabre
- * @subpackage HTTP 
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
- * @author Evert Pot (http://www.rooftopsolutions.nl/) 
+ * @subpackage HTTP
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
  */
 class Sabre_HTTP_Request {
 
     /**
      * PHP's $_SERVER data
-     * 
-     * @var string 
+     *
+     * @var array
      */
     protected $_SERVER;
 
+    /**
+     * PHP's $_POST data
+     *
+     * @var array
+     */
+    protected $_POST;
+
     /**
      * The request body, if any.
      *
      * This is stored in the form of a stream resource.
      *
-     * @var resource 
+     * @var resource
      */
     protected $body = null;
 
     /**
      * This will be set as the 'default' inputStream for a specific HTTP request
-     * We sometimes need to retain, or rebuild this if we need multiple runs 
+     * We sometimes need to retain, or rebuild this if we need multiple runs
      * of parsing the original HTTP request.
-     * 
-     * @var resource 
+     *
+     * @var resource
      */
     static $defaultInputStream=null;
 
     /**
      * Sets up the object
      *
-     * The serverData array can be used to override usage of PHP's 
-     * global _SERVER variable. 
-     * 
-     * @param array $serverData 
+     * The serverData and postData array can be used to override usage of PHP's
+     * global _SERVER and _POST variable respectively.
+     *
+     * @param array $serverData
+     * @param array $postData
      */
-    public function __construct($serverData = null) {
+    public function __construct(array $serverData = null, array $postData = null) {
 
        if ($serverData) $this->_SERVER = $serverData;
        else $this->_SERVER =& $_SERVER;
 
+       if ($postData) $this->_POST = $postData;
+       else $this->_POST =& $_POST;
+
     }
 
     /**
      * Returns the value for a specific http header.
      *
      * This method returns null if the header did not exist.
-     * 
-     * @param string $name 
-     * @return string 
+     *
+     * @param string $name
+     * @return string
      */
     public function getHeader($name) {
 
         $name = strtoupper(str_replace(array('-'),array('_'),$name));
         if (isset($this->_SERVER['HTTP_' . $name])) {
             return $this->_SERVER['HTTP_' . $name];
-        } 
+        }
 
-        // There's a few headers that seem to end up in the top-level 
+        // There's a few headers that seem to end up in the top-level
         // server array.
         switch($name) {
             case 'CONTENT_TYPE' :
@@ -92,9 +103,9 @@ class Sabre_HTTP_Request {
      * Returns all (known) HTTP headers.
      *
      * All headers are converted to lower-case, and additionally all underscores
-     * are automatically converted to dashes 
-     * 
-     * @return array 
+     * are automatically converted to dashes
+     *
+     * @return array
      */
     public function getHeaders() {
 
@@ -122,9 +133,9 @@ class Sabre_HTTP_Request {
     /**
      * Returns the HTTP request method
      *
-     * This is for example POST or GET 
+     * This is for example POST or GET
      *
-     * @return string 
+     * @return string
      */
     public function getMethod() {
 
@@ -135,18 +146,18 @@ class Sabre_HTTP_Request {
     /**
      * Returns the requested uri
      *
-     * @return string 
+     * @return string
      */
     public function getUri() {
-       
+
         return $this->_SERVER['REQUEST_URI'];
 
     }
 
     /**
-     * Will return protocol + the hostname + the uri 
-     * 
-     * @return void
+     * Will return protocol + the hostname + the uri
+     *
+     * @return string
      */
     public function getAbsoluteUri() {
 
@@ -157,9 +168,9 @@ class Sabre_HTTP_Request {
     }
 
     /**
-     * Returns everything after the ? from the current url 
-     * 
-     * @return string 
+     * Returns everything after the ? from the current url
+     *
+     * @return string
      */
     public function getQueryString() {
 
@@ -168,13 +179,13 @@ class Sabre_HTTP_Request {
     }
 
     /**
-     * Returns the HTTP request body body 
+     * Returns the HTTP request body body
      *
      * This method returns a readable stream resource.
-     * If the asString parameter is set to true, a string is sent instead. 
+     * If the asString parameter is set to true, a string is sent instead.
      *
      * @param bool asString
-     * @return resource 
+     * @return resource
      */
     public function getBody($asString = false) {
 
@@ -196,14 +207,14 @@ class Sabre_HTTP_Request {
     }
 
     /**
-     * Sets the contents of the HTTP request body 
-     * 
+     * Sets the contents of the HTTP request body
+     *
      * This method can either accept a string, or a readable stream resource.
      *
-     * If the setAsDefaultInputStream is set to true, it means for this run of the 
+     * If the setAsDefaultInputStream is set to true, it means for this run of the
      * script the supplied body will be used instead of php://input.
      *
-     * @param mixed $body 
+     * @param mixed $body
      * @param bool $setAsDefaultInputStream
      * @return void
      */
@@ -226,12 +237,26 @@ class Sabre_HTTP_Request {
     }
 
     /**
-     * Returns a specific item from the _SERVER array. 
+     * Returns PHP's _POST variable.
+     *
+     * The reason this is in a method is so it can be subclassed and
+     * overridden.
+     *
+     * @return array
+     */
+    public function getPostVars() {
+
+        return $this->_POST;
+
+    }
+
+    /**
+     * Returns a specific item from the _SERVER array.
      *
      * Do not rely on this feature, it is for internal use only.
      *
-     * @param string $field 
-     * @return string 
+     * @param string $field
+     * @return string
      */
     public function getRawServerValue($field) {
 
diff --git a/3rdparty/Sabre/HTTP/Response.php b/3rdparty/Sabre/HTTP/Response.php
index dce6feac55336bab4e20ac6ed00c3ed5edd48c5f..ffe9bda2082d5fd65395038fae36cfa179da0062 100644
--- a/3rdparty/Sabre/HTTP/Response.php
+++ b/3rdparty/Sabre/HTTP/Response.php
@@ -1,20 +1,20 @@
 <?php
 
 /**
- * Sabre_HTTP_Response 
- * 
+ * Sabre_HTTP_Response
+ *
  * @package Sabre
  * @subpackage HTTP 
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
- * @author Evert Pot (http://www.rooftopsolutions.nl/) 
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
  */
 class Sabre_HTTP_Response {
 
     /**
-     * Returns a full HTTP status message for an HTTP status code 
-     * 
-     * @param int $code 
+     * Returns a full HTTP status message for an HTTP status code
+     *
+     * @param int $code
      * @return string
      */
     public function getStatusMessage($code) {
@@ -64,6 +64,9 @@ class Sabre_HTTP_Response {
             423 => 'Locked', // RFC 4918
             424 => 'Failed Dependency', // RFC 4918
             426 => 'Upgrade required',
+            428 => 'Precondition required', // draft-nottingham-http-new-status
+            429 => 'Too Many Requests', // draft-nottingham-http-new-status
+            431 => 'Request Header Fields Too Large', // draft-nottingham-http-new-status
             500 => 'Internal Server Error',
             501 => 'Not Implemented',
             502 => 'Bad Gateway',
@@ -71,25 +74,26 @@ class Sabre_HTTP_Response {
             504 => 'Gateway Timeout',
             505 => 'HTTP Version not supported',
             506 => 'Variant Also Negotiates',
-            507 => 'Unsufficient Storage', // RFC 4918
+            507 => 'Insufficient Storage', // RFC 4918
             508 => 'Loop Detected', // RFC 5842
             509 => 'Bandwidth Limit Exceeded', // non-standard
             510 => 'Not extended',
-       ); 
+            511 => 'Network Authentication Required', // draft-nottingham-http-new-status
+       );
 
        return 'HTTP/1.1 ' . $code . ' ' . $msg[$code];
 
     }
 
     /**
-     * Sends an HTTP status header to the client 
-     * 
-     * @param int $code HTTP status code 
-     * @return void
+     * Sends an HTTP status header to the client
+     *
+     * @param int $code HTTP status code
+     * @return bool
      */
     public function sendStatus($code) {
 
-        if (!headers_sent()) 
+        if (!headers_sent())
             return header($this->getStatusMessage($code));
         else return false;
 
@@ -97,15 +101,16 @@ class Sabre_HTTP_Response {
 
     /**
      * Sets an HTTP header for the response
-     * 
-     * @param string $name 
-     * @param string $value 
-     * @return void
+     *
+     * @param string $name
+     * @param string $value
+     * @param bool $replace
+     * @return bool
      */
     public function setHeader($name, $value, $replace = true) {
 
         $value = str_replace(array("\r","\n"),array('\r','\n'),$value);
-        if (!headers_sent()) 
+        if (!headers_sent())
             return header($name . ': ' . $value, $replace);
         else return false;
 
@@ -115,8 +120,8 @@ class Sabre_HTTP_Response {
      * Sets a bunch of HTTP Headers
      *
      * headersnames are specified as keys, value in the array value
-     * 
-     * @param array $headers 
+     *
+     * @param array $headers
      * @return void
      */
     public function setHeaders(array $headers) {
@@ -130,14 +135,14 @@ class Sabre_HTTP_Response {
      * Sends the entire response body
      *
      * This method can accept either an open filestream, or a string.
-     * 
-     * @param mixed $body 
+     *
+     * @param mixed $body
      * @return void
      */
     public function sendBody($body) {
 
         if (is_resource($body)) {
-        
+
             fpassthru($body);
 
         } else {
diff --git a/3rdparty/Sabre/HTTP/Util.php b/3rdparty/Sabre/HTTP/Util.php
index 8a6bd7df487bd297982d0a8a00d4e0692fd07aba..67bdd489e1e5f654c4d9c41d34292bcbfefe0c39 100644
--- a/3rdparty/Sabre/HTTP/Util.php
+++ b/3rdparty/Sabre/HTTP/Util.php
@@ -1,11 +1,11 @@
 <?php
 
 /**
- * HTTP utility methods 
- * 
+ * HTTP utility methods
+ *
  * @package Sabre
  * @subpackage HTTP
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
  * @author Evert Pot (http://www.rooftopsolutions.nl/)
  * @author Paul Voegler
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
@@ -16,9 +16,9 @@ class Sabre_HTTP_Util {
      * Parses a RFC2616-compatible date string
      *
      * This method returns false if the date is invalid
-     * 
-     * @param string $dateHeader 
-     * @return bool|DateTime 
+     *
+     * @param string $dateHeader
+     * @return bool|DateTime
      */
     static function parseHTTPDate($dateHeader) {
 
@@ -42,7 +42,7 @@ class Sabre_HTTP_Util {
         $rfc1123_date = $wkday . ', ' . $date1 . ' ' . $time . ' GMT';
         //allowed date formats by RFC 2616
         $HTTP_date = "($rfc1123_date|$rfc850_date|$asctime_date)";
-        
+
         //allow for space around the string and strip it
         $dateHeader = trim($dateHeader, ' ');
         if (!preg_match('/^' . $HTTP_date . '$/', $dateHeader))
@@ -58,7 +58,24 @@ class Sabre_HTTP_Util {
         if ($realDate !== false && $realDate >= 0)
             return new DateTime('@' . $realDate, new DateTimeZone('UTC'));
 
-        return false;
+    }
+
+    /**
+     * Transforms a DateTime object to HTTP's most common date format.
+     *
+     * We're serializing it as the RFC 1123 date, which, for HTTP must be
+     * specified as GMT.
+     *
+     * @param DateTime $dateTime
+     * @return string
+     */
+    static function toHTTPDate(DateTime $dateTime) {
+
+        // We need to clone it, as we don't want to affect the existing
+        // DateTime.
+        $dateTime = clone $dateTime;
+        $dateTime->setTimeZone(new DateTimeZone('GMT'));
+        return $dateTime->format('D, d M Y H:i:s \G\M\T');
 
     }
 
diff --git a/3rdparty/Sabre/HTTP/Version.php b/3rdparty/Sabre/HTTP/Version.php
index 67be232fc26b4ce1ec0519775995ebf25bb4ff2b..23dc7f8a7a17d9de217836a293c09e01645d5af0 100644
--- a/3rdparty/Sabre/HTTP/Version.php
+++ b/3rdparty/Sabre/HTTP/Version.php
@@ -2,10 +2,10 @@
 
 /**
  * This class contains the Sabre_HTTP version constants.
- * 
+ *
  * @package Sabre
- * @subpackage HTTP 
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
+ * @subpackage HTTP
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
  * @author Evert Pot (http://www.rooftopsolutions.nl/)
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
  */
@@ -14,7 +14,7 @@ class Sabre_HTTP_Version {
     /**
      * Full version number
      */
-    const VERSION = '1.5.3';
+    const VERSION = '1.6.2';
 
     /**
      * Stability : alpha, beta, stable
diff --git a/3rdparty/Sabre/HTTP/includes.php b/3rdparty/Sabre/HTTP/includes.php
new file mode 100644
index 0000000000000000000000000000000000000000..9d34bf3a8becc8946c4759b71457e76b39cf5da1
--- /dev/null
+++ b/3rdparty/Sabre/HTTP/includes.php
@@ -0,0 +1,27 @@
+<?php
+
+/**
+ * Sabre_HTTP includes file
+ *
+ * Including this file will automatically include all files from the Sabre_HTTP
+ * package.
+ *
+ * This often allows faster loadtimes, as autoload-speed is often quite slow.
+ *
+ * @package Sabre
+ * @subpackage HTTP
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
+ * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
+ */
+
+// Begin includes
+include __DIR__ . '/AbstractAuth.php';
+include __DIR__ . '/AWSAuth.php';
+include __DIR__ . '/BasicAuth.php';
+include __DIR__ . '/DigestAuth.php';
+include __DIR__ . '/Request.php';
+include __DIR__ . '/Response.php';
+include __DIR__ . '/Util.php';
+include __DIR__ . '/Version.php';
+// End includes
diff --git a/3rdparty/Sabre/LICENCE b/3rdparty/Sabre/LICENCE
deleted file mode 100644
index 3d07eaace836198ab96fe64cc329c02872516ca4..0000000000000000000000000000000000000000
--- a/3rdparty/Sabre/LICENCE
+++ /dev/null
@@ -1,27 +0,0 @@
-Copyright (C) 2007-2011 Rooftop Solutions.
-Copyright (C) 2007-2009 FileMobile inc.
-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 SabreDAV nor the names of its 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. 
diff --git a/3rdparty/Sabre/VObject/Component.php b/3rdparty/Sabre/VObject/Component.php
index 47cf9f3d8125b889cdf16ac9c49199c22cc38170..b78a26133fa19e1f9e9dc19c333b7744188da190 100644
--- a/3rdparty/Sabre/VObject/Component.php
+++ b/3rdparty/Sabre/VObject/Component.php
@@ -4,39 +4,73 @@
  * VObject Component
  *
  * This class represents a VCALENDAR/VCARD component. A component is for example
- * VEVENT, VTODO and also VCALENDAR. It starts with BEGIN:COMPONENTNAME and 
+ * VEVENT, VTODO and also VCALENDAR. It starts with BEGIN:COMPONENTNAME and
  * ends with END:COMPONENTNAME
  *
  * @package Sabre
  * @subpackage VObject
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
- * @author Evert Pot (http://www.rooftopsolutions.nl/) 
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
  */
 class Sabre_VObject_Component extends Sabre_VObject_Element {
 
     /**
-     * Name, for example VEVENT 
-     * 
-     * @var string 
+     * Name, for example VEVENT
+     *
+     * @var string
      */
     public $name;
 
     /**
-     * Children properties and components 
-     * 
+     * Children properties and components
+     *
      * @var array
      */
     public $children = array();
 
+    /**
+     * If coponents are added to this map, they will be automatically mapped
+     * to their respective classes, if parsed by the reader or constructed with
+     * the 'create' method.
+     *
+     * @var array
+     */
+    static public $classMap = array(
+        'VCALENDAR'     => 'Sabre_VObject_Component_VCalendar',
+        'VEVENT'        => 'Sabre_VObject_Component_VEvent',
+        'VTODO'         => 'Sabre_VObject_Component_VTodo',
+        'VJOURNAL'      => 'Sabre_VObject_Component_VJournal',
+        'VALARM'        => 'Sabre_VObject_Component_VAlarm',
+    );
+
+    /**
+     * Creates the new component by name, but in addition will also see if
+     * there's a class mapped to the property name.
+     *
+     * @param string $name
+     * @param string $value
+     * @return Sabre_VObject_Component
+     */
+    static public function create($name, $value = null) {
+
+        $name = strtoupper($name);
+
+        if (isset(self::$classMap[$name])) {
+            return new self::$classMap[$name]($name, $value);
+        } else {
+            return new self($name, $value);
+        }
+
+    }
 
     /**
      * Creates a new component.
      *
-     * By default this object will iterate over its own children, but this can 
+     * By default this object will iterate over its own children, but this can
      * be overridden with the iterator argument
-     * 
-     * @param string $name 
+     *
+     * @param string $name
      * @param Sabre_VObject_ElementList $iterator
      */
     public function __construct($name, Sabre_VObject_ElementList $iterator = null) {
@@ -47,23 +81,65 @@ class Sabre_VObject_Component extends Sabre_VObject_Element {
     }
 
     /**
-     * Turns the object back into a serialized blob. 
-     * 
-     * @return string 
+     * Turns the object back into a serialized blob.
+     *
+     * @return string
      */
     public function serialize() {
 
         $str = "BEGIN:" . $this->name . "\r\n";
+
+        /**
+         * Gives a component a 'score' for sorting purposes.
+         *
+         * This is solely used by the childrenSort method.
+         *
+         * A higher score means the item will be higher in the list
+         *
+         * @param Sabre_VObject_Node $n
+         * @return int
+         */
+        $sortScore = function($n) {
+
+            if ($n instanceof Sabre_VObject_Component) {
+                // We want to encode VTIMEZONE first, this is a personal
+                // preference.
+                if ($n->name === 'VTIMEZONE') {
+                    return 1;
+                } else {
+                    return 0;
+                }
+            } else {
+                // VCARD version 4.0 wants the VERSION property to appear first
+                if ($n->name === 'VERSION') {
+                    return 3;
+                } else {
+                    return 2;
+                }
+            }
+
+        };
+
+        usort($this->children, function($a, $b) use ($sortScore) {
+
+            $sA = $sortScore($a);
+            $sB = $sortScore($b);
+
+            if ($sA === $sB) return 0;
+
+            return ($sA > $sB) ? -1 : 1;
+
+        });
+
         foreach($this->children as $child) $str.=$child->serialize();
         $str.= "END:" . $this->name . "\r\n";
-        
+
         return $str;
 
     }
 
-
     /**
-     * Adds a new componenten or element
+     * Adds a new component or element
      *
      * You can call this method with the following syntaxes:
      *
@@ -71,10 +147,10 @@ class Sabre_VObject_Component extends Sabre_VObject_Element {
      * add(string $name, $value)
      *
      * The first version adds an Element
-     * The second adds a property as a string. 
-     * 
-     * @param mixed $item 
-     * @param mixed $itemValue 
+     * The second adds a property as a string.
+     *
+     * @param mixed $item
+     * @param mixed $itemValue
      * @return void
      */
     public function add($item, $itemValue = null) {
@@ -90,12 +166,12 @@ class Sabre_VObject_Component extends Sabre_VObject_Element {
             if (!is_scalar($itemValue)) {
                 throw new InvalidArgumentException('The second argument must be scalar');
             }
-            $item = new Sabre_VObject_Property($item,$itemValue);
+            $item = Sabre_VObject_Property::create($item,$itemValue);
             $item->parent = $this;
             $this->children[] = $item;
 
         } else {
-            
+
             throw new InvalidArgumentException('The first argument must either be a Sabre_VObject_Element or a string');
 
         }
@@ -103,9 +179,9 @@ class Sabre_VObject_Component extends Sabre_VObject_Element {
     }
 
     /**
-     * Returns an iterable list of children 
-     * 
-     * @return Sabre_VObject_ElementList 
+     * Returns an iterable list of children
+     *
+     * @return Sabre_VObject_ElementList
      */
     public function children() {
 
@@ -116,18 +192,18 @@ class Sabre_VObject_Component extends Sabre_VObject_Element {
     /**
      * Returns an array with elements that match the specified name.
      *
-     * This function is also aware of MIME-Directory groups (as they appear in 
-     * vcards). This means that if a property is grouped as "HOME.EMAIL", it 
-     * will also be returned when searching for just "EMAIL". If you want to 
-     * search for a property in a specific group, you can select on the entire 
-     * string ("HOME.EMAIL"). If you want to search on a specific property that 
+     * This function is also aware of MIME-Directory groups (as they appear in
+     * vcards). This means that if a property is grouped as "HOME.EMAIL", it
+     * will also be returned when searching for just "EMAIL". If you want to
+     * search for a property in a specific group, you can select on the entire
+     * string ("HOME.EMAIL"). If you want to search on a specific property that
      * has not been assigned a group, specify ".EMAIL".
      *
-     * Keys are retained from the 'children' array, which may be confusing in 
-     * certain cases. 
+     * Keys are retained from the 'children' array, which may be confusing in
+     * certain cases.
      *
-     * @param string $name 
-     * @return array 
+     * @param string $name
+     * @return array
      */
     public function select($name) {
 
@@ -144,7 +220,7 @@ class Sabre_VObject_Component extends Sabre_VObject_Element {
                 strtoupper($child->name) === $name &&
                 (is_null($group) || ( $child instanceof Sabre_VObject_Property && strtoupper($child->group) === $group))
             ) {
-                
+
                 $result[$key] = $child;
 
             }
@@ -155,16 +231,35 @@ class Sabre_VObject_Component extends Sabre_VObject_Element {
 
     }
 
+    /**
+     * This method only returns a list of sub-components. Properties are
+     * ignored.
+     *
+     * @return array
+     */
+    public function getComponents() {
+
+        $result = array();
+        foreach($this->children as $child) {
+            if ($child instanceof Sabre_VObject_Component) {
+                $result[] = $child;
+            }
+        }
+
+        return $result;
+
+    }
+
     /* Magic property accessors {{{ */
 
     /**
-     * Using 'get' you will either get a propery or component, 
+     * Using 'get' you will either get a property or component,
      *
      * If there were no child-elements found with the specified name,
      * null is returned.
-     * 
-     * @param string $name 
-     * @return void
+     *
+     * @param string $name
+     * @return Sabre_VObject_Property
      */
     public function __get($name) {
 
@@ -173,6 +268,7 @@ class Sabre_VObject_Component extends Sabre_VObject_Element {
             return null;
         } else {
             $firstMatch = current($matches);
+            /** @var $firstMatch Sabre_VObject_Property */
             $firstMatch->setIterator(new Sabre_VObject_ElementList(array_values($matches)));
             return $firstMatch;
         }
@@ -180,10 +276,10 @@ class Sabre_VObject_Component extends Sabre_VObject_Element {
     }
 
     /**
-     * This method checks if a sub-element with the specified name exists. 
-     * 
-     * @param string $name 
-     * @return bool 
+     * This method checks if a sub-element with the specified name exists.
+     *
+     * @param string $name
+     * @return bool
      */
     public function __isset($name) {
 
@@ -200,7 +296,7 @@ class Sabre_VObject_Component extends Sabre_VObject_Element {
      *
      * If the item already exists, it will be removed. If you want to add
      * a new item with the same name, always use the add() method.
-     * 
+     *
      * @param string $name
      * @param mixed $value
      * @return void
@@ -218,7 +314,7 @@ class Sabre_VObject_Component extends Sabre_VObject_Element {
                 $this->children[] = $value;
             }
         } elseif (is_scalar($value)) {
-            $property = new Sabre_VObject_Property($name,$value);
+            $property = Sabre_VObject_Property::create($name,$value);
             $property->parent = $this;
             if (!is_null($overWrite)) {
                 $this->children[$overWrite] = $property;
@@ -232,9 +328,9 @@ class Sabre_VObject_Component extends Sabre_VObject_Element {
     }
 
     /**
-     * Removes all properties and components within this component. 
-     * 
-     * @param string $name 
+     * Removes all properties and components within this component.
+     *
+     * @param string $name
      * @return void
      */
     public function __unset($name) {
@@ -251,4 +347,19 @@ class Sabre_VObject_Component extends Sabre_VObject_Element {
 
     /* }}} */
 
+    /**
+     * This method is automatically called when the object is cloned.
+     * Specifically, this will ensure all child elements are also cloned.
+     *
+     * @return void
+     */
+    public function __clone() {
+
+        foreach($this->children as $key=>$child) {
+            $this->children[$key] = clone $child;
+            $this->children[$key]->parent = $this;
+        }
+
+    }
+
 }
diff --git a/3rdparty/Sabre/VObject/Component/VAlarm.php b/3rdparty/Sabre/VObject/Component/VAlarm.php
new file mode 100644
index 0000000000000000000000000000000000000000..ebb4a9b18f69962a0446a6f4dece59ea2db1605a
--- /dev/null
+++ b/3rdparty/Sabre/VObject/Component/VAlarm.php
@@ -0,0 +1,102 @@
+<?php
+
+/**
+ * VAlarm component
+ *
+ * This component contains some additional functionality specific for VALARMs.
+ *
+ * @package Sabre
+ * @subpackage VObject
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
+ * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
+ */
+class Sabre_VObject_Component_VAlarm extends Sabre_VObject_Component {
+
+    /**
+     * Returns a DateTime object when this alarm is going to trigger.
+     *
+     * This ignores repeated alarm, only the first trigger is returned.
+     *
+     * @return DateTime
+     */
+    public function getEffectiveTriggerTime() {
+
+        $trigger = $this->TRIGGER;
+        if(!isset($trigger['VALUE']) || strtoupper($trigger['VALUE']) === 'DURATION') {
+            $triggerDuration = Sabre_VObject_DateTimeParser::parseDuration($this->TRIGGER);
+            $related = (isset($trigger['RELATED']) && strtoupper($trigger['RELATED']) == 'END') ? 'END' : 'START';
+
+            $parentComponent = $this->parent;
+            if ($related === 'START') {
+                $effectiveTrigger = clone $parentComponent->DTSTART->getDateTime();
+                $effectiveTrigger->add($triggerDuration);
+            } else {
+                if ($parentComponent->name === 'VTODO') {
+                    $endProp = 'DUE';
+                } elseif ($parentComponent->name === 'VEVENT') {
+                    $endProp = 'DTEND';
+                } else {
+                    throw new Sabre_DAV_Exception('time-range filters on VALARM components are only supported when they are a child of VTODO or VEVENT');
+                }
+
+                if (isset($parentComponent->$endProp)) {
+                    $effectiveTrigger = clone $parentComponent->$endProp->getDateTime();
+                    $effectiveTrigger->add($triggerDuration);
+                } elseif (isset($parentComponent->DURATION)) {
+                    $effectiveTrigger = clone $parentComponent->DTSTART->getDateTime();
+                    $duration = Sabre_VObject_DateTimeParser::parseDuration($parentComponent->DURATION);
+                    $effectiveTrigger->add($duration);
+                    $effectiveTrigger->add($triggerDuration);
+                } else {
+                    $effectiveTrigger = clone $parentComponent->DTSTART->getDateTime();
+                    $effectiveTrigger->add($triggerDuration);
+                }
+            }
+        } else {
+            $effectiveTrigger = $trigger->getDateTime();
+        }
+        return $effectiveTrigger;
+
+    }
+
+    /**
+     * Returns true or false depending on if the event falls in the specified
+     * time-range. This is used for filtering purposes.
+     *
+     * The rules used to determine if an event falls within the specified
+     * time-range is based on the CalDAV specification.
+     *
+     * @param DateTime $start
+     * @param DateTime $end
+     * @return bool
+     */
+    public function isInTimeRange(DateTime $start, DateTime $end) {
+
+        $effectiveTrigger = $this->getEffectiveTriggerTime();
+
+        if (isset($this->DURATION)) {
+            $duration = Sabre_VObject_DateTimeParser::parseDuration($this->DURATION);
+            $repeat = (string)$this->repeat;
+            if (!$repeat) {
+                $repeat = 1;
+            }
+
+            $period = new DatePeriod($effectiveTrigger, $duration, (int)$repeat);
+
+            foreach($period as $occurrence) {
+
+                if ($start <= $occurrence && $end > $occurrence) {
+                    return true;
+                }
+            }
+            return false;
+        } else {
+            return ($start <= $effectiveTrigger && $end > $effectiveTrigger);
+        }
+
+    }
+
+}
+
+?>
diff --git a/3rdparty/Sabre/VObject/Component/VCalendar.php b/3rdparty/Sabre/VObject/Component/VCalendar.php
new file mode 100644
index 0000000000000000000000000000000000000000..f3be29afdbb492c16b7fe28f0e04888c3291fd43
--- /dev/null
+++ b/3rdparty/Sabre/VObject/Component/VCalendar.php
@@ -0,0 +1,133 @@
+<?php
+
+/**
+ * The VCalendar component
+ *
+ * This component adds functionality to a component, specific for a VCALENDAR.
+ * 
+ * @package Sabre
+ * @subpackage VObject
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/) 
+ * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
+ */
+class Sabre_VObject_Component_VCalendar extends Sabre_VObject_Component {
+
+    /**
+     * Returns a list of all 'base components'. For instance, if an Event has 
+     * a recurrence rule, and one instance is overridden, the overridden event 
+     * will have the same UID, but will be excluded from this list.
+     *
+     * VTIMEZONE components will always be excluded. 
+     *
+     * @param string $componentName filter by component name 
+     * @return array 
+     */
+    public function getBaseComponents($componentName = null) {
+
+        $components = array();
+        foreach($this->children as $component) {
+
+            if (!$component instanceof Sabre_VObject_Component)
+                continue;
+
+            if (isset($component->{'RECURRENCE-ID'})) 
+                continue;
+
+            if ($componentName && $component->name !== strtoupper($componentName)) 
+                continue;
+
+            if ($component->name === 'VTIMEZONE')
+                continue;
+
+            $components[] = $component;
+
+        }
+
+        return $components;
+
+    }
+
+    /**
+     * If this calendar object, has events with recurrence rules, this method 
+     * can be used to expand the event into multiple sub-events.
+     *
+     * Each event will be stripped from it's recurrence information, and only 
+     * the instances of the event in the specified timerange will be left 
+     * alone.
+     *
+     * In addition, this method will cause timezone information to be stripped, 
+     * and normalized to UTC.
+     *
+     * This method will alter the VCalendar. This cannot be reversed.
+     *
+     * This functionality is specifically used by the CalDAV standard. It is 
+     * possible for clients to request expand events, if they are rather simple 
+     * clients and do not have the possibility to calculate recurrences.
+     *
+     * @param DateTime $start
+     * @param DateTime $end 
+     * @return void
+     */
+    public function expand(DateTime $start, DateTime $end) {
+
+        $newEvents = array();
+
+        foreach($this->select('VEVENT') as $key=>$vevent) {
+
+            if (isset($vevent->{'RECURRENCE-ID'})) {
+                unset($this->children[$key]);
+                continue;
+            } 
+
+
+            if (!$vevent->rrule) {
+                unset($this->children[$key]);
+                if ($vevent->isInTimeRange($start, $end)) {
+                    $newEvents[] = $vevent;
+                }
+                continue;
+            }
+
+            $uid = (string)$vevent->uid;
+            if (!$uid) {
+                throw new LogicException('Event did not have a UID!');
+            }
+
+            $it = new Sabre_VObject_RecurrenceIterator($this, $vevent->uid);
+            $it->fastForward($start);
+
+            while($it->valid() && $it->getDTStart() < $end) {
+
+                if ($it->getDTEnd() > $start) {
+
+                    $newEvents[] = $it->getEventObject();
+
+                }
+                $it->next();
+
+            }
+            unset($this->children[$key]);
+
+        }
+
+        foreach($newEvents as $newEvent) {
+
+            foreach($newEvent->children as $child) {
+                if ($child instanceof Sabre_VObject_Property_DateTime &&
+                    $child->getDateType() == Sabre_VObject_Property_DateTime::LOCALTZ) {
+                        $child->setDateTime($child->getDateTime(),Sabre_VObject_Property_DateTime::UTC);
+                    }
+            }
+
+            $this->add($newEvent);
+
+        }
+
+        // Removing all VTIMEZONE components
+        unset($this->VTIMEZONE);
+
+    } 
+
+}
+
diff --git a/3rdparty/Sabre/VObject/Component/VEvent.php b/3rdparty/Sabre/VObject/Component/VEvent.php
new file mode 100644
index 0000000000000000000000000000000000000000..4cc1e36d7d6b6175fd61122bab3dc6c58447d058
--- /dev/null
+++ b/3rdparty/Sabre/VObject/Component/VEvent.php
@@ -0,0 +1,70 @@
+<?php
+
+/**
+ * VEvent component
+ *
+ * This component contains some additional functionality specific for VEVENT's.
+ *
+ * @package Sabre
+ * @subpackage VObject
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
+ * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
+ */
+class Sabre_VObject_Component_VEvent extends Sabre_VObject_Component {
+
+    /**
+     * Returns true or false depending on if the event falls in the specified
+     * time-range. This is used for filtering purposes.
+     *
+     * The rules used to determine if an event falls within the specified
+     * time-range is based on the CalDAV specification.
+     *
+     * @param DateTime $start
+     * @param DateTime $end
+     * @return bool
+     */
+    public function isInTimeRange(DateTime $start, DateTime $end) {
+
+        if ($this->RRULE) {
+            $it = new Sabre_VObject_RecurrenceIterator($this);
+            $it->fastForward($start);
+
+            // We fast-forwarded to a spot where the end-time of the
+            // recurrence instance exceeded the start of the requested
+            // time-range.
+            //
+            // If the starttime of the recurrence did not exceed the
+            // end of the time range as well, we have a match.
+            return ($it->getDTStart() < $end && $it->getDTEnd() > $start);
+
+        }
+
+        $effectiveStart = $this->DTSTART->getDateTime();
+        if (isset($this->DTEND)) {
+            $effectiveEnd = $this->DTEND->getDateTime();
+            // If this was an all-day event, we should just increase the
+            // end-date by 1. Otherwise the event will last until the second
+            // the date changed, by increasing this by 1 day the event lasts
+            // all of the last day as well.
+            if ($this->DTSTART->getDateType() == Sabre_VObject_Element_DateTime::DATE) {
+                $effectiveEnd->modify('+1 day');
+            }
+        } elseif (isset($this->DURATION)) {
+            $effectiveEnd = clone $effectiveStart;
+            $effectiveEnd->add( Sabre_VObject_DateTimeParser::parseDuration($this->DURATION) );
+        } elseif ($this->DTSTART->getDateType() == Sabre_VObject_Element_DateTime::DATE) {
+            $effectiveEnd = clone $effectiveStart;
+            $effectiveEnd->modify('+1 day');
+        } else {
+            $effectiveEnd = clone $effectiveStart;
+        }
+        return (
+            ($start <= $effectiveEnd) && ($end > $effectiveStart)
+        );
+
+    }
+
+}
+
+?>
diff --git a/3rdparty/Sabre/VObject/Component/VJournal.php b/3rdparty/Sabre/VObject/Component/VJournal.php
new file mode 100644
index 0000000000000000000000000000000000000000..22b3ec921e5a1b6e67dbdb0253ba5d6fece53cb8
--- /dev/null
+++ b/3rdparty/Sabre/VObject/Component/VJournal.php
@@ -0,0 +1,46 @@
+<?php
+
+/**
+ * VJournal component
+ *
+ * This component contains some additional functionality specific for VJOURNALs.
+ * 
+ * @package Sabre
+ * @subpackage VObject
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/) 
+ * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
+ */
+class Sabre_VObject_Component_VJournal extends Sabre_VObject_Component {
+
+    /**
+     * Returns true or false depending on if the event falls in the specified 
+     * time-range. This is used for filtering purposes. 
+     *
+     * The rules used to determine if an event falls within the specified 
+     * time-range is based on the CalDAV specification.
+     *
+     * @param DateTime $start
+     * @param DateTime $end 
+     * @return bool 
+     */
+    public function isInTimeRange(DateTime $start, DateTime $end) {
+
+        $dtstart = isset($this->DTSTART)?$this->DTSTART->getDateTime():null;
+        if ($dtstart) {
+            $effectiveEnd = clone $dtstart;
+            if ($this->DTSTART->getDateType() == Sabre_VObject_Element_DateTime::DATE) {
+                $effectiveEnd->modify('+1 day');
+            }
+
+            return ($start <= $effectiveEnd && $end > $dtstart);
+
+        }
+        return false;
+
+
+    }
+
+}
+
+?>
diff --git a/3rdparty/Sabre/VObject/Component/VTodo.php b/3rdparty/Sabre/VObject/Component/VTodo.php
new file mode 100644
index 0000000000000000000000000000000000000000..79d06298d7f864ea5953f51f714906c3119feef8
--- /dev/null
+++ b/3rdparty/Sabre/VObject/Component/VTodo.php
@@ -0,0 +1,68 @@
+<?php
+
+/**
+ * VTodo component
+ *
+ * This component contains some additional functionality specific for VTODOs.
+ * 
+ * @package Sabre
+ * @subpackage VObject
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/) 
+ * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
+ */
+class Sabre_VObject_Component_VTodo extends Sabre_VObject_Component {
+
+    /**
+     * Returns true or false depending on if the event falls in the specified 
+     * time-range. This is used for filtering purposes. 
+     *
+     * The rules used to determine if an event falls within the specified 
+     * time-range is based on the CalDAV specification.
+     *
+     * @param DateTime $start
+     * @param DateTime $end 
+     * @return bool 
+     */
+    public function isInTimeRange(DateTime $start, DateTime $end) {
+
+        $dtstart = isset($this->DTSTART)?$this->DTSTART->getDateTime():null;
+        $duration = isset($this->DURATION)?Sabre_VObject_DateTimeParser::parseDuration($this->DURATION):null;
+        $due = isset($this->DUE)?$this->DUE->getDateTime():null;
+        $completed = isset($this->COMPLETED)?$this->COMPLETED->getDateTime():null;
+        $created = isset($this->CREATED)?$this->CREATED->getDateTime():null;
+
+        if ($dtstart) {
+            if ($duration) {
+                $effectiveEnd = clone $dtstart;
+                $effectiveEnd->add($duration);
+                return $start <= $effectiveEnd && $end > $dtstart;
+            } elseif ($due) {
+                return
+                    ($start < $due || $start <= $dtstart) &&
+                    ($end > $dtstart || $end >= $due);
+            } else {
+                return $start <= $dtstart && $end > $dtstart;
+            }
+        }
+        if ($due) {
+            return ($start < $due && $end >= $due);
+        }
+        if ($completed && $created) {
+            return
+                ($start <= $created || $start <= $completed) &&
+                ($end >= $created || $end >= $completed);
+        }
+        if ($completed) {
+            return ($start <= $completed && $end >= $completed);
+        }
+        if ($created) {
+            return ($end > $created);
+        }
+        return true;
+
+    }
+
+}
+
+?>
diff --git a/3rdparty/Sabre/VObject/DateTimeParser.php b/3rdparty/Sabre/VObject/DateTimeParser.php
new file mode 100644
index 0000000000000000000000000000000000000000..1e2d54ef3a9b3e115dd608e5e7a91c3b6c4ae74a
--- /dev/null
+++ b/3rdparty/Sabre/VObject/DateTimeParser.php
@@ -0,0 +1,177 @@
+<?php
+
+/**
+ * DateTimeParser
+ *
+ * This class is responsible for parsing the several different date and time
+ * formats iCalendar and vCards have.
+ *
+ * @package Sabre
+ * @subpackage VObject
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
+ * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
+ */
+class Sabre_VObject_DateTimeParser {
+
+    /**
+     * Parses an iCalendar (rfc5545) formatted datetime and returns a DateTime object
+     *
+     * Specifying a reference timezone is optional. It will only be used
+     * if the non-UTC format is used. The argument is used as a reference, the
+     * returned DateTime object will still be in the UTC timezone.
+     *
+     * @param string $dt
+     * @param DateTimeZone $tz
+     * @return DateTime
+     */
+    static public function parseDateTime($dt,DateTimeZone $tz = null) {
+
+        // Format is YYYYMMDD + "T" + hhmmss
+        $result = preg_match('/^([1-3][0-9]{3})([0-1][0-9])([0-3][0-9])T([0-2][0-9])([0-5][0-9])([0-5][0-9])([Z]?)$/',$dt,$matches);
+
+        if (!$result) {
+            throw new Sabre_DAV_Exception_BadRequest('The supplied iCalendar datetime value is incorrect: ' . $dt);
+        }
+
+        if ($matches[7]==='Z' || is_null($tz)) {
+            $tz = new DateTimeZone('UTC');
+        }
+        $date = new DateTime($matches[1] . '-' . $matches[2] . '-' . $matches[3] . ' ' . $matches[4] . ':' . $matches[5] .':' . $matches[6], $tz);
+
+        // Still resetting the timezone, to normalize everything to UTC
+        $date->setTimeZone(new DateTimeZone('UTC'));
+        return $date;
+
+    }
+
+    /**
+     * Parses an iCalendar (rfc5545) formatted date and returns a DateTime object
+     *
+     * @param string $date
+     * @return DateTime
+     */
+    static public function parseDate($date) {
+
+        // Format is YYYYMMDD
+        $result = preg_match('/^([1-3][0-9]{3})([0-1][0-9])([0-3][0-9])$/',$date,$matches);
+
+        if (!$result) {
+            throw new Sabre_DAV_Exception_BadRequest('The supplied iCalendar date value is incorrect: ' . $date);
+        }
+
+        $date = new DateTime($matches[1] . '-' . $matches[2] . '-' . $matches[3], new DateTimeZone('UTC'));
+        return $date;
+
+    }
+
+    /**
+     * Parses an iCalendar (RFC5545) formatted duration value.
+     *
+     * This method will either return a DateTimeInterval object, or a string
+     * suitable for strtotime or DateTime::modify.
+     *
+     * @param string $duration
+     * @param bool $asString
+     * @return DateInterval|string
+     */
+    static public function parseDuration($duration, $asString = false) {
+
+        $result = preg_match('/^(?P<plusminus>\+|-)?P((?P<week>\d+)W)?((?P<day>\d+)D)?(T((?P<hour>\d+)H)?((?P<minute>\d+)M)?((?P<second>\d+)S)?)?$/', $duration, $matches);
+        if (!$result) {
+            throw new Sabre_DAV_Exception_BadRequest('The supplied iCalendar duration value is incorrect: ' . $duration);
+        }
+
+        if (!$asString) {
+            $invert = false;
+            if ($matches['plusminus']==='-') {
+                $invert = true;
+            }
+
+
+            $parts = array(
+                'week',
+                'day',
+                'hour',
+                'minute',
+                'second',
+            );
+            foreach($parts as $part) {
+                $matches[$part] = isset($matches[$part])&&$matches[$part]?(int)$matches[$part]:0;
+            }
+
+
+            // We need to re-construct the $duration string, because weeks and
+            // days are not supported by DateInterval in the same string.
+            $duration = 'P';
+            $days = $matches['day'];
+            if ($matches['week']) {
+                $days+=$matches['week']*7;
+            }
+            if ($days)
+                $duration.=$days . 'D';
+
+            if ($matches['minute'] || $matches['second'] || $matches['hour']) {
+                $duration.='T';
+
+                if ($matches['hour'])
+                    $duration.=$matches['hour'].'H';
+
+                if ($matches['minute'])
+                    $duration.=$matches['minute'].'M';
+
+                if ($matches['second'])
+                    $duration.=$matches['second'].'S';
+
+            }
+
+            $iv = new DateInterval($duration);
+            if ($invert) $iv->invert = true;
+
+            return $iv;
+
+        }
+
+
+
+        $parts = array(
+            'week',
+            'day',
+            'hour',
+            'minute',
+            'second',
+        );
+
+        $newDur = '';
+        foreach($parts as $part) {
+            if (isset($matches[$part]) && $matches[$part]) {
+                $newDur.=' '.$matches[$part] . ' ' . $part . 's';
+            }
+        }
+
+        $newDur = ($matches['plusminus']==='-'?'-':'+') . trim($newDur);
+        return $newDur;
+
+    }
+
+    /**
+     * Parses either a Date or DateTime, or Duration value.
+     *
+     * @param string $date
+     * @param DateTimeZone|string $referenceTZ
+     * @return DateTime|DateInterval
+     */
+    static public function parse($date, $referenceTZ = null) {
+
+        if ($date[0]==='P' || ($date[0]==='-' && $date[1]==='P')) {
+            return self::parseDuration($date);
+        } elseif (strlen($date)===8) {
+            return self::parseDate($date);
+        } else {
+            return self::parseDateTime($date, $referenceTZ);
+        }
+
+    }
+
+
+}
diff --git a/3rdparty/Sabre/VObject/Element.php b/3rdparty/Sabre/VObject/Element.php
index 8d2b0aaacd1ee5ce9bde985eb00b058f8151da55..e20ff0b353c4491cd166ccad47a39c16a7f46c4f 100644
--- a/3rdparty/Sabre/VObject/Element.php
+++ b/3rdparty/Sabre/VObject/Element.php
@@ -2,14 +2,15 @@
 
 /**
  * Base class for all elements
- * 
+ *
  * @package Sabre
  * @subpackage VObject
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
- * @author Evert Pot (http://www.rooftopsolutions.nl/) 
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
  */
 abstract class Sabre_VObject_Element extends Sabre_VObject_Node {
 
+    public $parent = null;
 
 }
diff --git a/3rdparty/Sabre/VObject/Element/DateTime.php b/3rdparty/Sabre/VObject/Element/DateTime.php
index 3350ec02c88a9b00705790e338a1e3c9e9303fb3..5e5eb7ab6f2e8a96485d33b9173c9a1726648edf 100644
--- a/3rdparty/Sabre/VObject/Element/DateTime.php
+++ b/3rdparty/Sabre/VObject/Element/DateTime.php
@@ -1,25 +1,18 @@
 <?php
 
 /**
- * DateTime property 
+ * DateTime property
  *
- * This element is used for iCalendar properties such as the DTSTART property. 
- * It basically provides a few helper functions that make it easier to deal 
- * with these. It supports both DATE-TIME and DATE values.
+ * this class got renamed to Sabre_VObject_Property_DateTime
  *
- * In order to use this correctly, you must call setDateTime and getDateTime to 
- * retrieve and modify dates respectively.
- *
- * If you use the 'value' or properties directly, this object does not keep 
- * reference and results might appear incorrectly.
- * 
  * @package Sabre
  * @subpackage VObject
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
- * @author Evert Pot (http://www.rooftopsolutions.nl/) 
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
+ * @deprecated
  */
-class Sabre_VObject_Element_DateTime extends Sabre_VObject_Property {
+class Sabre_VObject_Element_DateTime extends Sabre_VObject_Property_DateTime {
 
     /**
      * Local 'floating' time
@@ -41,205 +34,4 @@ class Sabre_VObject_Element_DateTime extends Sabre_VObject_Property {
      */
     const DATE = 4;
 
-    /**
-     * DateTime representation
-     *
-     * @var DateTime
-     */
-    protected $dateTime;
-
-    /**
-     * dateType 
-     * 
-     * @var int 
-     */
-    protected $dateType;
-
-    /**
-     * Updates the Date and Time. 
-     * 
-     * @param DateTime $dt 
-     * @param int $dateType 
-     * @return void
-     */
-    public function setDateTime(DateTime $dt, $dateType = self::LOCALTZ) {
-
-        switch($dateType) {
-
-            case self::LOCAL :
-                $this->setValue($dt->format('Ymd\\THis'));
-                $this->offsetUnset('VALUE');
-                $this->offsetUnset('TZID');
-                $this->offsetSet('VALUE','DATE-TIME'); 
-                break;
-            case self::UTC :
-                $dt->setTimeZone(new DateTimeZone('UTC'));
-                $this->setValue($dt->format('Ymd\\THis\\Z'));
-                $this->offsetUnset('VALUE');
-                $this->offsetUnset('TZID');
-                $this->offsetSet('VALUE','DATE-TIME');
-                break;
-            case self::LOCALTZ :
-                $this->setValue($dt->format('Ymd\\THis'));
-                $this->offsetUnset('VALUE');
-                $this->offsetUnset('TZID');
-                $this->offsetSet('VALUE','DATE-TIME');
-                $this->offsetSet('TZID', $dt->getTimeZone()->getName());
-                break; 
-            case self::DATE :
-                $this->setValue($dt->format('Ymd'));
-                $this->offsetUnset('VALUE');
-                $this->offsetUnset('TZID');
-                $this->offsetSet('VALUE','DATE');
-                break;
-            default :
-                throw new InvalidArgumentException('You must pass a valid dateType constant');
-
-        }
-        $this->dateTime = $dt;
-        $this->dateType = $dateType;
-
-    }
-
-    /**
-     * Returns the current DateTime value.
-     *
-     * If no value was set, this method returns null.
-     *
-     * @return DateTime|null 
-     */
-    public function getDateTime() {
-
-        if ($this->dateTime)
-            return $this->dateTime;
-
-        list(
-            $this->dateType,
-            $this->dateTime
-        ) = self::parseData($this->value, $this);
-        return $this->dateTime;
-
-    }
-
-    /**
-     * Returns the type of Date format.
-     *
-     * This method returns one of the format constants. If no date was set, 
-     * this method will return null.
-     *
-     * @return int|null
-     */
-    public function getDateType() {
-
-        if ($this->dateType)
-            return $this->dateType;
-
-        list(
-            $this->dateType,
-            $this->dateTime,
-        ) = self::parseData($this->value, $this);
-        return $this->dateType;
-
-    }
-
-    /**
-     * Parses the internal data structure to figure out what the current date 
-     * and time is.
-     *
-     * The returned array contains two elements:
-     *   1. A 'DateType' constant (as defined on this class), or null. 
-     *   2. A DateTime object (or null)
-     *
-     * @param string|null $propertyValue The string to parse (yymmdd or 
-     *                                   ymmddThhmmss, etc..)
-     * @param Sabre_VObject_Property|null $property The instance of the 
-     *                                              property we're parsing. 
-     * @return array 
-     */
-    static public function parseData($propertyValue, Sabre_VObject_Property $property = null) {
-
-        if (is_null($propertyValue)) {
-            return array(null, null);
-        }
-
-        $date = '(?P<year>[1-2][0-9]{3})(?P<month>[0-1][0-9])(?P<date>[0-3][0-9])';
-        $time = '(?P<hour>[0-2][0-9])(?P<minute>[0-5][0-9])(?P<second>[0-5][0-9])';
-        $regex = "/^$date(T$time(?P<isutc>Z)?)?$/";
-
-        if (!preg_match($regex, $propertyValue, $matches)) {
-            throw new InvalidArgumentException($propertyValue . ' is not a valid DateTime or Date string');
-        }
-
-        if (!isset($matches['hour'])) {
-            // Date-only
-            return array(
-                self::DATE,
-                new DateTime($matches['year'] . '-' . $matches['month'] . '-' . $matches['date'] . ' 00:00:00'),
-            );
-        }
-
-        $dateStr = 
-            $matches['year'] .'-' . 
-            $matches['month'] . '-' . 
-            $matches['date'] . ' ' .
-            $matches['hour'] . ':' .
-            $matches['minute'] . ':' .
-            $matches['second']; 
-
-        if (isset($matches['isutc'])) {
-            $dt = new DateTime($dateStr,new DateTimeZone('UTC'));
-            $dt->setTimeZone(new DateTimeZone('UTC'));
-            return array(
-                self::UTC,
-                $dt
-            );
-        }
-
-        // Finding the timezone.
-        $tzid = $property['TZID'];
-        if (!$tzid) {
-            return array(
-                self::LOCAL,
-                new DateTime($dateStr)
-            );
-        }
-
-        try {
-            $tz = new DateTimeZone($tzid->value);
-        } catch (Exception $e) {
-
-            // The id was invalid, we're going to try to find the information 
-            // through the VTIMEZONE object.
-
-            // First we find the root object
-            $root = $property;
-            while($root->parent) {
-                $root = $root->parent;
-            }
-
-            if (isset($root->VTIMEZONE)) {
-                foreach($root->VTIMEZONE as $vtimezone) {
-                    if (((string)$vtimezone->TZID) == $tzid) {
-                        if (isset($vtimezone->{'X-LIC-LOCATION'})) {
-                            $tzid = (string)$vtimezone->{'X-LIC-LOCATION'};
-                        }
-                    }
-                }
-            }
-
-            $tz = new DateTimeZone($tzid);
-            
-        }
-        $dt = new DateTime($dateStr, $tz);
-        $dt->setTimeZone($tz);
-
-        return array(
-            self::LOCALTZ,
-            $dt
-        );
-
-    }
-
 }
-
-?>
diff --git a/3rdparty/Sabre/VObject/Element/MultiDateTime.php b/3rdparty/Sabre/VObject/Element/MultiDateTime.php
index dc6ca5abb8021e90300f97176c05ec0686fd6530..8a12ced94a80418c2c3640bd975c948cab75672c 100644
--- a/3rdparty/Sabre/VObject/Element/MultiDateTime.php
+++ b/3rdparty/Sabre/VObject/Element/MultiDateTime.php
@@ -1,168 +1,17 @@
 <?php
 
 /**
- * Multi-DateTime property 
+ * Multi-DateTime property
  *
- * This element is used for iCalendar properties such as the EXDATE property. 
- * It basically provides a few helper functions that make it easier to deal 
- * with these. It supports both DATE-TIME and DATE values.
+ * This class got renamed to Sabre_VObject_Property_MultiDateTime
  *
- * In order to use this correctly, you must call setDateTimes and getDateTimes 
- * to retrieve and modify dates respectively.
- *
- * If you use the 'value' or properties directly, this object does not keep 
- * reference and results might appear incorrectly.
- * 
  * @package Sabre
  * @subpackage VObject
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
- * @author Evert Pot (http://www.rooftopsolutions.nl/) 
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
+ * @deprecated
  */
-class Sabre_VObject_Element_MultiDateTime extends Sabre_VObject_Property {
-
-    /**
-     * DateTime representation
-     *
-     * @var DateTime[]
-     */
-    protected $dateTimes;
-
-    /**
-     * dateType
-     *
-     * This is one of the Sabre_VObject_Element_DateTime constants.
-     *
-     * @var int 
-     */
-    protected $dateType;
-
-    /**
-     * Updates the value 
-     * 
-     * @param array $dt Must be an array of DateTime objects. 
-     * @param int $dateType 
-     * @return void
-     */
-    public function setDateTimes(array $dt, $dateType = Sabre_VObject_Element_DateTime::LOCALTZ) {
-
-        foreach($dt as $i) 
-            if (!$i instanceof DateTime) 
-                throw new InvalidArgumentException('You must pass an array of DateTime objects');
-
-        $this->offsetUnset('VALUE');
-        $this->offsetUnset('TZID');
-        switch($dateType) {
-
-            case Sabre_VObject_Element_DateTime::LOCAL :
-                $val = array();
-                foreach($dt as $i) {
-                    $val[] = $i->format('Ymd\\THis');
-                }
-                $this->setValue(implode(',',$val));
-                $this->offsetSet('VALUE','DATE-TIME'); 
-                break;
-            case Sabre_VObject_Element_DateTime::UTC :
-                $val = array();
-                foreach($dt as $i) {
-                    $i->setTimeZone(new DateTimeZone('UTC'));
-                    $val[] = $i->format('Ymd\\THis\\Z');
-                }
-                $this->setValue(implode(',',$val));
-                $this->offsetSet('VALUE','DATE-TIME');
-                break;
-            case Sabre_VObject_Element_DateTime::LOCALTZ :
-                $val = array();
-                foreach($dt as $i) {
-                    $val[] = $i->format('Ymd\\THis');
-                }
-                $this->setValue(implode(',',$val));
-                $this->offsetSet('VALUE','DATE-TIME');
-                $this->offsetSet('TZID', $dt[0]->getTimeZone()->getName());
-                break; 
-            case Sabre_VObject_Element_DateTime::DATE :
-                $val = array();
-                foreach($dt as $i) {
-                    $val[] = $i->format('Ymd');
-                }
-                $this->setValue(implode(',',$val));
-                $this->offsetSet('VALUE','DATE');
-                break;
-            default :
-                throw new InvalidArgumentException('You must pass a valid dateType constant');
-
-        }
-        $this->dateTimes = $dt;
-        $this->dateType = $dateType;
-
-    }
-
-    /**
-     * Returns the current DateTime value.
-     *
-     * If no value was set, this method returns null.
-     *
-     * @return array|null 
-     */
-    public function getDateTimes() {
-
-        if ($this->dateTimes)
-            return $this->dateTimes;
-
-        $dts = array();
-    
-        if (!$this->value) {
-            $this->dateTimes = null;
-            $this->dateType = null;
-            return null;
-        }
-
-        foreach(explode(',',$this->value) as $val) {
-            list(
-                $type,
-                $dt
-            ) = Sabre_VObject_Element_DateTime::parseData($val, $this);
-            $dts[] = $dt;
-            $this->dateType = $type;
-        }
-        $this->dateTimes = $dts;
-        return $this->dateTimes;
-
-    }
-
-    /**
-     * Returns the type of Date format.
-     *
-     * This method returns one of the format constants. If no date was set, 
-     * this method will return null.
-     *
-     * @return int|null
-     */
-    public function getDateType() {
-
-        if ($this->dateType)
-            return $this->dateType;
-    
-        if (!$this->value) {
-            $this->dateTimes = null;
-            $this->dateType = null;
-            return null;
-        }
-
-        $dts = array();
-        foreach(explode(',',$this->value) as $val) {
-            list(
-                $type,
-                $dt
-            ) = Sabre_VObject_Element_DateTime::parseData($val, $this);
-            $dts[] = $dt;
-            $this->dateType = $type; 
-        }
-        $this->dateTimes = $dts;
-        return $this->dateType;
-
-    }
+class Sabre_VObject_Element_MultiDateTime extends Sabre_VObject_Property_MultiDateTime {
 
 }
-
-?>
diff --git a/3rdparty/Sabre/VObject/ElementList.php b/3rdparty/Sabre/VObject/ElementList.php
index 9922cd587bcdaa3603dc574c130c8bf0faa9a34d..7e508db20f0841ff3f26b4300fe2ca85bdb19f90 100644
--- a/3rdparty/Sabre/VObject/ElementList.php
+++ b/3rdparty/Sabre/VObject/ElementList.php
@@ -8,15 +8,15 @@
  *
  * @package Sabre
  * @subpackage VObject
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
- * @author Evert Pot (http://www.rooftopsolutions.nl/) 
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
  */
 class Sabre_VObject_ElementList implements Iterator, Countable, ArrayAccess {
 
     /**
-     * Inner elements 
-     * 
+     * Inner elements
+     *
      * @var array
      */
     protected $elements = array();
@@ -24,37 +24,37 @@ class Sabre_VObject_ElementList implements Iterator, Countable, ArrayAccess {
     /**
      * Creates the element list.
      *
-     * @param array $elements 
+     * @param array $elements
      */
     public function __construct(array $elements) {
 
         $this->elements = $elements;
 
-    } 
+    }
 
     /* {{{ Iterator interface */
 
     /**
-     * Current position  
-     * 
-     * @var int 
+     * Current position
+     *
+     * @var int
      */
     private $key = 0;
 
     /**
-     * Returns current item in iteration 
-     * 
-     * @return Sabre_VObject_Element 
+     * Returns current item in iteration
+     *
+     * @return Sabre_VObject_Element
      */
     public function current() {
 
         return $this->elements[$this->key];
 
     }
-   
+
     /**
-     * To the next item in the iterator 
-     * 
+     * To the next item in the iterator
+     *
      * @return void
      */
     public function next() {
@@ -64,8 +64,8 @@ class Sabre_VObject_ElementList implements Iterator, Countable, ArrayAccess {
     }
 
     /**
-     * Returns the current iterator key 
-     * 
+     * Returns the current iterator key
+     *
      * @return int
      */
     public function key() {
@@ -75,9 +75,9 @@ class Sabre_VObject_ElementList implements Iterator, Countable, ArrayAccess {
     }
 
     /**
-     * Returns true if the current position in the iterator is a valid one 
-     * 
-     * @return bool 
+     * Returns true if the current position in the iterator is a valid one
+     *
+     * @return bool
      */
     public function valid() {
 
@@ -86,9 +86,9 @@ class Sabre_VObject_ElementList implements Iterator, Countable, ArrayAccess {
     }
 
     /**
-     * Rewinds the iterator 
-     * 
-     * @return void 
+     * Rewinds the iterator
+     *
+     * @return void
      */
     public function rewind() {
 
@@ -101,9 +101,9 @@ class Sabre_VObject_ElementList implements Iterator, Countable, ArrayAccess {
     /* {{{ Countable interface */
 
     /**
-     * Returns the number of elements 
-     * 
-     * @return int 
+     * Returns the number of elements
+     *
+     * @return int
      */
     public function count() {
 
@@ -115,12 +115,12 @@ class Sabre_VObject_ElementList implements Iterator, Countable, ArrayAccess {
 
     /* {{{ ArrayAccess Interface */
 
-    
+
     /**
      * Checks if an item exists through ArrayAccess.
      *
-     * @param int $offset 
-     * @return bool 
+     * @param int $offset
+     * @return bool
      */
     public function offsetExists($offset) {
 
@@ -131,8 +131,8 @@ class Sabre_VObject_ElementList implements Iterator, Countable, ArrayAccess {
     /**
      * Gets an item through ArrayAccess.
      *
-     * @param int $offset 
-     * @return mixed 
+     * @param int $offset
+     * @return mixed
      */
     public function offsetGet($offset) {
 
@@ -143,8 +143,8 @@ class Sabre_VObject_ElementList implements Iterator, Countable, ArrayAccess {
     /**
      * Sets an item through ArrayAccess.
      *
-     * @param int $offset 
-     * @param mixed $value 
+     * @param int $offset
+     * @param mixed $value
      * @return void
      */
     public function offsetSet($offset,$value) {
@@ -158,7 +158,7 @@ class Sabre_VObject_ElementList implements Iterator, Countable, ArrayAccess {
      *
      * This method just forwards the request to the inner iterator
      *
-     * @param int $offset 
+     * @param int $offset
      * @return void
      */
     public function offsetUnset($offset) {
diff --git a/3rdparty/Sabre/VObject/FreeBusyGenerator.php b/3rdparty/Sabre/VObject/FreeBusyGenerator.php
new file mode 100644
index 0000000000000000000000000000000000000000..1c96a64a004b6a7055c0568f80903c122de6d9dd
--- /dev/null
+++ b/3rdparty/Sabre/VObject/FreeBusyGenerator.php
@@ -0,0 +1,297 @@
+<?php
+
+/**
+ * This class helps with generating FREEBUSY reports based on existing sets of
+ * objects.
+ *
+ * It only looks at VEVENT and VFREEBUSY objects from the sourcedata, and
+ * generates a single VFREEBUSY object.
+ *
+ * VFREEBUSY components are described in RFC5545, The rules for what should
+ * go in a single freebusy report is taken from RFC4791, section 7.10.
+ *
+ * @package Sabre
+ * @subpackage VObject
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
+ * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
+ */
+class Sabre_VObject_FreeBusyGenerator {
+
+    /**
+     * Input objects
+     *
+     * @var array
+     */
+    protected $objects;
+
+    /**
+     * Start of range
+     *
+     * @var DateTime|null
+     */
+    protected $start;
+
+    /**
+     * End of range
+     *
+     * @var DateTime|null
+     */
+    protected $end;
+
+    /**
+     * VCALENDAR object
+     *
+     * @var Sabre_VObject_Component
+     */
+    protected $baseObject;
+
+    /**
+     * Sets the VCALENDAR object.
+     *
+     * If this is set, it will not be generated for you. You are responsible
+     * for setting things like the METHOD, CALSCALE, VERSION, etc..
+     *
+     * The VFREEBUSY object will be automatically added though.
+     *
+     * @param Sabre_VObject_Component $vcalendar
+     * @return void
+     */
+    public function setBaseObject(Sabre_VObject_Component $vcalendar) {
+
+        $this->baseObject = $vcalendar;
+
+    }
+
+    /**
+     * Sets the input objects
+     *
+     * Every object must either be a string or a Sabre_VObject_Component.
+     *
+     * @param array $objects
+     * @return void
+     */
+    public function setObjects(array $objects) {
+
+        $this->objects = array();
+        foreach($objects as $object) {
+
+            if (is_string($object)) {
+                $this->objects[] = Sabre_VObject_Reader::read($object);
+            } elseif ($object instanceof Sabre_VObject_Component) {
+                $this->objects[] = $object;
+            } else {
+                throw new InvalidArgumentException('You can only pass strings or Sabre_VObject_Component arguments to setObjects');
+            }
+
+        }
+
+    }
+
+    /**
+     * Sets the time range
+     *
+     * Any freebusy object falling outside of this time range will be ignored.
+     *
+     * @param DateTime $start
+     * @param DateTime $end
+     * @return void
+     */
+    public function setTimeRange(DateTime $start = null, DateTime $end = null) {
+
+        $this->start = $start;
+        $this->end = $end;
+
+    }
+
+    /**
+     * Parses the input data and returns a correct VFREEBUSY object, wrapped in
+     * a VCALENDAR.
+     *
+     * @return Sabre_VObject_Component
+     */
+    public function getResult() {
+
+        $busyTimes = array();
+
+        foreach($this->objects as $object) {
+
+            foreach($object->getBaseComponents() as $component) {
+
+                switch($component->name) {
+
+                    case 'VEVENT' :
+
+                        $FBTYPE = 'BUSY';
+                        if (isset($component->TRANSP) && (strtoupper($component->TRANSP) === 'TRANSPARENT')) {
+                            break;
+                        }
+                        if (isset($component->STATUS)) {
+                            $status = strtoupper($component->STATUS);
+                            if ($status==='CANCELLED') {
+                                break;
+                            }
+                            if ($status==='TENTATIVE') {
+                                $FBTYPE = 'BUSY-TENTATIVE';
+                            }
+                        }
+
+                        $times = array();
+
+                        if ($component->RRULE) {
+
+                            $iterator = new Sabre_VObject_RecurrenceIterator($object, (string)$component->uid);
+                            if ($this->start) {
+                                $iterator->fastForward($this->start);
+                            }
+
+                            $maxRecurrences = 200;
+
+                            while($iterator->valid() && --$maxRecurrences) {
+
+                                $startTime = $iterator->getDTStart();
+                                if ($this->end && $startTime > $this->end) {
+                                    break;
+                                }
+                                $times[] = array(
+                                    $iterator->getDTStart(),
+                                    $iterator->getDTEnd(),
+                                );
+
+                                $iterator->next();
+
+                            }
+
+                        } else {
+
+                            $startTime = $component->DTSTART->getDateTime();
+                            if ($this->end && $startTime > $this->end) {
+                                break;
+                            }
+                            $endTime = null;
+                            if (isset($component->DTEND)) {
+                                $endTime = $component->DTEND->getDateTime();
+                            } elseif (isset($component->DURATION)) {
+                                $duration = Sabre_VObject_DateTimeParser::parseDuration((string)$component->DURATION);
+                                $endTime = clone $startTime;
+                                $endTime->add($duration);
+                            } elseif ($component->DTSTART->getDateType() === Sabre_VObject_Property_DateTime::DATE) {
+                                $endTime = clone $startTime;
+                                $endTime->modify('+1 day');
+                            } else {
+                                // The event had no duration (0 seconds)
+                                break;
+                            }
+
+                            $times[] = array($startTime, $endTime);
+
+                        }
+
+                        foreach($times as $time) {
+
+                            if ($this->end && $time[0] > $this->end) break;
+                            if ($this->start && $time[1] < $this->start) break;
+
+                            $busyTimes[] = array(
+                                $time[0],
+                                $time[1],
+                                $FBTYPE,
+                            );
+                        }
+                        break;
+
+                    case 'VFREEBUSY' :
+                        foreach($component->FREEBUSY as $freebusy) {
+
+                            $fbType = isset($freebusy['FBTYPE'])?strtoupper($freebusy['FBTYPE']):'BUSY';
+
+                            // Skipping intervals marked as 'free'
+                            if ($fbType==='FREE')
+                                continue;
+
+                            $values = explode(',', $freebusy);
+                            foreach($values as $value) {
+                                list($startTime, $endTime) = explode('/', $value);
+                                $startTime = Sabre_VObject_DateTimeParser::parseDateTime($startTime);
+
+                                if (substr($endTime,0,1)==='P' || substr($endTime,0,2)==='-P') {
+                                    $duration = Sabre_VObject_DateTimeParser::parseDuration($endTime);
+                                    $endTime = clone $startTime;
+                                    $endTime->add($duration);
+                                } else {
+                                    $endTime = Sabre_VObject_DateTimeParser::parseDateTime($endTime);
+                                }
+
+                                if($this->start && $this->start > $endTime) continue;
+                                if($this->end && $this->end < $startTime) continue;
+                                $busyTimes[] = array(
+                                    $startTime,
+                                    $endTime,
+                                    $fbType
+                                );
+
+                            }
+
+
+                        }
+                        break;
+
+
+
+                }
+
+
+            }
+
+        }
+
+        if ($this->baseObject) {
+            $calendar = $this->baseObject;
+        } else {
+            $calendar = new Sabre_VObject_Component('VCALENDAR');
+            $calendar->version = '2.0';
+            if (Sabre_DAV_Server::$exposeVersion) {
+                $calendar->prodid = '-//SabreDAV//Sabre VObject ' . Sabre_VObject_Version::VERSION . '//EN';
+            } else {
+                $calendar->prodid = '-//SabreDAV//Sabre VObject//EN';
+            }
+            $calendar->calscale = 'GREGORIAN';
+        }
+
+        $vfreebusy = new Sabre_VObject_Component('VFREEBUSY');
+        $calendar->add($vfreebusy);
+
+        if ($this->start) {
+            $dtstart = new Sabre_VObject_Property_DateTime('DTSTART');
+            $dtstart->setDateTime($this->start,Sabre_VObject_Property_DateTime::UTC);
+            $vfreebusy->add($dtstart);
+        }
+        if ($this->end) {
+            $dtend = new Sabre_VObject_Property_DateTime('DTEND');
+            $dtend->setDateTime($this->start,Sabre_VObject_Property_DateTime::UTC);
+            $vfreebusy->add($dtend);
+        }
+        $dtstamp = new Sabre_VObject_Property_DateTime('DTSTAMP');
+        $dtstamp->setDateTime(new DateTime('now'), Sabre_VObject_Property_DateTime::UTC);
+        $vfreebusy->add($dtstamp);
+
+        foreach($busyTimes as $busyTime) {
+
+            $busyTime[0]->setTimeZone(new DateTimeZone('UTC'));
+            $busyTime[1]->setTimeZone(new DateTimeZone('UTC'));
+
+            $prop = new Sabre_VObject_Property(
+                'FREEBUSY',
+                $busyTime[0]->format('Ymd\\THis\\Z') . '/' . $busyTime[1]->format('Ymd\\THis\\Z')
+            );
+            $prop['FBTYPE'] = $busyTime[2];
+            $vfreebusy->add($prop);
+
+        }
+
+        return $calendar;
+
+    }
+
+}
+
diff --git a/3rdparty/Sabre/VObject/Node.php b/3rdparty/Sabre/VObject/Node.php
index 7100b62f1cb2a916f43bb64190fae8734539172a..d89e01b56c69e60904bbdc9496611951128b618a 100644
--- a/3rdparty/Sabre/VObject/Node.php
+++ b/3rdparty/Sabre/VObject/Node.php
@@ -1,47 +1,47 @@
 <?php
 
 /**
- * Base class for all nodes 
- * 
+ * Base class for all nodes
+ *
  * @package Sabre
  * @subpackage VObject
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
- * @author Evert Pot (http://www.rooftopsolutions.nl/) 
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
  */
 abstract class Sabre_VObject_Node implements IteratorAggregate, ArrayAccess, Countable {
 
     /**
-     * Turns the object back into a serialized blob. 
-     * 
-     * @return string 
+     * Turns the object back into a serialized blob.
+     *
+     * @return string
      */
     abstract function serialize();
 
     /**
-     * Iterator override 
-     * 
-     * @var Sabre_VObject_ElementList 
+     * Iterator override
+     *
+     * @var Sabre_VObject_ElementList
      */
     protected $iterator = null;
 
     /**
      * A link to the parent node
-     * 
-     * @var Sabre_VObject_Node 
+     *
+     * @var Sabre_VObject_Node
      */
-    protected $parent = null;
+    public $parent = null;
 
     /* {{{ IteratorAggregator interface */
 
     /**
-     * Returns the iterator for this object 
-     * 
-     * @return Sabre_VObject_ElementList 
+     * Returns the iterator for this object
+     *
+     * @return Sabre_VObject_ElementList
      */
     public function getIterator() {
 
-        if (!is_null($this->iterator)) 
+        if (!is_null($this->iterator))
             return $this->iterator;
 
         return new Sabre_VObject_ElementList(array($this));
@@ -52,8 +52,8 @@ abstract class Sabre_VObject_Node implements IteratorAggregate, ArrayAccess, Cou
      * Sets the overridden iterator
      *
      * Note that this is not actually part of the iterator interface
-     * 
-     * @param Sabre_VObject_ElementList $iterator 
+     *
+     * @param Sabre_VObject_ElementList $iterator
      * @return void
      */
     public function setIterator(Sabre_VObject_ElementList $iterator) {
@@ -67,9 +67,9 @@ abstract class Sabre_VObject_Node implements IteratorAggregate, ArrayAccess, Cou
     /* {{{ Countable interface */
 
     /**
-     * Returns the number of elements 
-     * 
-     * @return int 
+     * Returns the number of elements
+     *
+     * @return int
      */
     public function count() {
 
@@ -82,14 +82,14 @@ abstract class Sabre_VObject_Node implements IteratorAggregate, ArrayAccess, Cou
 
     /* {{{ ArrayAccess Interface */
 
-    
+
     /**
      * Checks if an item exists through ArrayAccess.
      *
      * This method just forwards the request to the inner iterator
-     * 
-     * @param int $offset 
-     * @return bool 
+     *
+     * @param int $offset
+     * @return bool
      */
     public function offsetExists($offset) {
 
@@ -103,8 +103,8 @@ abstract class Sabre_VObject_Node implements IteratorAggregate, ArrayAccess, Cou
      *
      * This method just forwards the request to the inner iterator
      *
-     * @param int $offset 
-     * @return mixed 
+     * @param int $offset
+     * @return mixed
      */
     public function offsetGet($offset) {
 
@@ -118,8 +118,8 @@ abstract class Sabre_VObject_Node implements IteratorAggregate, ArrayAccess, Cou
      *
      * This method just forwards the request to the inner iterator
      *
-     * @param int $offset 
-     * @param mixed $value 
+     * @param int $offset
+     * @param mixed $value
      * @return void
      */
     public function offsetSet($offset,$value) {
@@ -134,7 +134,7 @@ abstract class Sabre_VObject_Node implements IteratorAggregate, ArrayAccess, Cou
      *
      * This method just forwards the request to the inner iterator
      *
-     * @param int $offset 
+     * @param int $offset
      * @return void
      */
     public function offsetUnset($offset) {
diff --git a/3rdparty/Sabre/VObject/Parameter.php b/3rdparty/Sabre/VObject/Parameter.php
index 9ebab6ec69ba89d929efd85a7f5544d48444c126..2e39af5f78ab1788067335f7b3f703845e26f4e8 100644
--- a/3rdparty/Sabre/VObject/Parameter.php
+++ b/3rdparty/Sabre/VObject/Parameter.php
@@ -5,51 +5,54 @@
  *
  * This class represents a parameter. A parameter is always tied to a property.
  * In the case of:
- *   DTSTART;VALUE=DATE:20101108 
+ *   DTSTART;VALUE=DATE:20101108
  * VALUE=DATE would be the parameter name and value.
- * 
+ *
  * @package Sabre
  * @subpackage VObject
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
- * @author Evert Pot (http://www.rooftopsolutions.nl/) 
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
  */
 class Sabre_VObject_Parameter extends Sabre_VObject_Node {
 
     /**
-     * Parameter name 
-     * 
-     * @var string 
+     * Parameter name
+     *
+     * @var string
      */
     public $name;
 
     /**
-     * Parameter value 
-     * 
-     * @var string 
+     * Parameter value
+     *
+     * @var string
      */
     public $value;
 
     /**
-     * Sets up the object 
-     * 
-     * @param string $name 
-     * @param string $value 
+     * Sets up the object
+     *
+     * @param string $name
+     * @param string $value
      */
     public function __construct($name, $value = null) {
 
         $this->name = strtoupper($name);
         $this->value = $value;
 
-    } 
+    }
 
     /**
-     * Turns the object back into a serialized blob. 
-     * 
-     * @return string 
+     * Turns the object back into a serialized blob.
+     *
+     * @return string
      */
     public function serialize() {
 
+        if (is_null($this->value)) {
+            return $this->name;
+        }
         $src = array(
             '\\',
             "\n",
@@ -68,9 +71,9 @@ class Sabre_VObject_Parameter extends Sabre_VObject_Node {
     }
 
     /**
-     * Called when this object is being cast to a string 
-     * 
-     * @return string 
+     * Called when this object is being cast to a string
+     *
+     * @return string
      */
     public function __toString() {
 
diff --git a/3rdparty/Sabre/VObject/ParseException.php b/3rdparty/Sabre/VObject/ParseException.php
index ed4ef2e859275a5e3bf24015bf5870b632a35b2c..1b5e95bf16e49b5184b5fc089ec063457c5d3bab 100644
--- a/3rdparty/Sabre/VObject/ParseException.php
+++ b/3rdparty/Sabre/VObject/ParseException.php
@@ -2,11 +2,11 @@
 
 /**
  * Exception thrown by Sabre_VObject_Reader if an invalid object was attempted to be parsed.
- * 
+ *
  * @package Sabre
  * @subpackage VObject
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
- * @author Evert Pot (http://www.rooftopsolutions.nl/) 
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
  */
 class Sabre_VObject_ParseException extends Exception { }
diff --git a/3rdparty/Sabre/VObject/Property.php b/3rdparty/Sabre/VObject/Property.php
index 060582290438d8dd520960c54b79a108305eb2e9..ce74fe3865b86d38d0fa9a8a05d9363116d926f4 100644
--- a/3rdparty/Sabre/VObject/Property.php
+++ b/3rdparty/Sabre/VObject/Property.php
@@ -4,58 +4,103 @@
  * VObject Property
  *
  * A property in VObject is usually in the form PARAMNAME:paramValue.
- * An example is : SUMMARY:Weekly meeting 
+ * An example is : SUMMARY:Weekly meeting
  *
  * Properties can also have parameters:
  * SUMMARY;LANG=en:Weekly meeting.
  *
- * Parameters can be accessed using the ArrayAccess interface. 
+ * Parameters can be accessed using the ArrayAccess interface.
  *
  * @package Sabre
  * @subpackage VObject
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
- * @author Evert Pot (http://www.rooftopsolutions.nl/) 
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
  */
 class Sabre_VObject_Property extends Sabre_VObject_Element {
 
     /**
-     * Propertyname 
-     * 
-     * @var string 
+     * Propertyname
+     *
+     * @var string
      */
     public $name;
 
     /**
      * Group name
-     * 
+     *
      * This may be something like 'HOME' for vcards.
      *
-     * @var string 
+     * @var string
      */
     public $group;
 
     /**
-     * Property parameters 
-     * 
-     * @var array 
+     * Property parameters
+     *
+     * @var array
      */
     public $parameters = array();
 
     /**
-     * Property value 
-     * 
-     * @var string 
+     * Property value
+     *
+     * @var string
      */
     public $value;
 
+    /**
+     * If properties are added to this map, they will be automatically mapped
+     * to their respective classes, if parsed by the reader or constructed with
+     * the 'create' method.
+     *
+     * @var array
+     */
+    static public $classMap = array(
+        'COMPLETED'     => 'Sabre_VObject_Property_DateTime',
+        'CREATED'       => 'Sabre_VObject_Property_DateTime',
+        'DTEND'         => 'Sabre_VObject_Property_DateTime',
+        'DTSTAMP'       => 'Sabre_VObject_Property_DateTime',
+        'DTSTART'       => 'Sabre_VObject_Property_DateTime',
+        'DUE'           => 'Sabre_VObject_Property_DateTime',
+        'EXDATE'        => 'Sabre_VObject_Property_MultiDateTime',
+        'LAST-MODIFIED' => 'Sabre_VObject_Property_DateTime',
+        'RECURRENCE-ID' => 'Sabre_VObject_Property_DateTime',
+        'TRIGGER'       => 'Sabre_VObject_Property_DateTime',
+    );
+
+    /**
+     * Creates the new property by name, but in addition will also see if
+     * there's a class mapped to the property name.
+     *
+     * @param string $name
+     * @param string $value
+     * @return void
+     */
+    static public function create($name, $value = null) {
+
+        $name = strtoupper($name);
+        $shortName = $name;
+        $group = null;
+        if (strpos($shortName,'.')!==false) {
+            list($group, $shortName) = explode('.', $shortName);
+        }
+
+        if (isset(self::$classMap[$shortName])) {
+            return new self::$classMap[$shortName]($name, $value);
+        } else {
+            return new self($name, $value);
+        }
+
+    }
+
     /**
      * Creates a new property object
-     * 
-     * By default this object will iterate over its own children, but this can 
+     *
+     * By default this object will iterate over its own children, but this can
      * be overridden with the iterator argument
-     * 
-     * @param string $name 
+     *
+     * @param string $name
      * @param string $value
      * @param Sabre_VObject_ElementList $iterator
      */
@@ -73,10 +118,12 @@ class Sabre_VObject_Property extends Sabre_VObject_Element {
 
     }
 
+
+
     /**
-     * Updates the internal value 
-     * 
-     * @param string $value 
+     * Updates the internal value
+     *
+     * @param string $value
      * @return void
      */
     public function setValue($value) {
@@ -86,9 +133,9 @@ class Sabre_VObject_Property extends Sabre_VObject_Element {
     }
 
     /**
-     * Turns the object back into a serialized blob. 
-     * 
-     * @return string 
+     * Turns the object back into a serialized blob.
+     *
+     * @return string
      */
     public function serialize() {
 
@@ -97,7 +144,7 @@ class Sabre_VObject_Property extends Sabre_VObject_Element {
 
         if (count($this->parameters)) {
             foreach($this->parameters as $param) {
-                
+
                 $str.=';' . $param->serialize();
 
             }
@@ -115,8 +162,8 @@ class Sabre_VObject_Property extends Sabre_VObject_Element {
         $out = '';
         while(strlen($str)>0) {
             if (strlen($str)>75) {
-                $out.= substr($str,0,75) . "\r\n";
-                $str = ' ' . substr($str,75);
+                $out.= mb_strcut($str,0,75,'utf-8') . "\r\n";
+                $str = ' ' . mb_strcut($str,75,strlen($str),'utf-8');
             } else {
                 $out.=$str . "\r\n";
                 $str='';
@@ -136,11 +183,11 @@ class Sabre_VObject_Property extends Sabre_VObject_Element {
      * add(Sabre_VObject_Parameter $element)
      * add(string $name, $value)
      *
-     * The first version adds an Parameter 
-     * The second adds a property as a string. 
-     * 
-     * @param mixed $item 
-     * @param mixed $itemValue 
+     * The first version adds an Parameter
+     * The second adds a property as a string.
+     *
+     * @param mixed $item
+     * @param mixed $itemValue
      * @return void
      */
     public function add($item, $itemValue = null) {
@@ -153,7 +200,7 @@ class Sabre_VObject_Property extends Sabre_VObject_Element {
             $this->parameters[] = $item;
         } elseif(is_string($item)) {
 
-            if (!is_scalar($itemValue)) {
+            if (!is_scalar($itemValue) && !is_null($itemValue)) {
                 throw new InvalidArgumentException('The second argument must be scalar');
             }
             $parameter = new Sabre_VObject_Parameter($item,$itemValue);
@@ -161,21 +208,20 @@ class Sabre_VObject_Property extends Sabre_VObject_Element {
             $this->parameters[] = $parameter;
 
         } else {
-            
+
             throw new InvalidArgumentException('The first argument must either be a Sabre_VObject_Element or a string');
 
         }
 
     }
 
-
     /* ArrayAccess interface {{{ */
 
     /**
      * Checks if an array element exists
-     * 
-     * @param mixed $name 
-     * @return bool 
+     *
+     * @param mixed $name
+     * @return bool
      */
     public function offsetExists($name) {
 
@@ -191,16 +237,16 @@ class Sabre_VObject_Property extends Sabre_VObject_Element {
     }
 
     /**
-     * Returns a parameter, or parameter list. 
-     * 
-     * @param string $name 
-     * @return Sabre_VObject_Element 
+     * Returns a parameter, or parameter list.
+     *
+     * @param string $name
+     * @return Sabre_VObject_Element
      */
     public function offsetGet($name) {
 
         if (is_int($name)) return parent::offsetGet($name);
         $name = strtoupper($name);
-        
+
         $result = array();
         foreach($this->parameters as $parameter) {
             if ($parameter->name == $name)
@@ -219,8 +265,8 @@ class Sabre_VObject_Property extends Sabre_VObject_Element {
     }
 
     /**
-     * Creates a new parameter 
-     * 
+     * Creates a new parameter
+     *
      * @param string $name
      * @param mixed $value
      * @return void
@@ -230,7 +276,7 @@ class Sabre_VObject_Property extends Sabre_VObject_Element {
         if (is_int($name)) return parent::offsetSet($name, $value);
 
         if (is_scalar($value)) {
-            if (!is_string($name)) 
+            if (!is_string($name))
                 throw new InvalidArgumentException('A parameter name must be specified. This means you cannot use the $array[]="string" to add parameters.');
 
             $this->offsetUnset($name);
@@ -242,7 +288,7 @@ class Sabre_VObject_Property extends Sabre_VObject_Element {
             if (!is_null($name))
                 throw new InvalidArgumentException('Don\'t specify a parameter name if you\'re passing a Sabre_VObject_Parameter. Add using $array[]=$parameterObject.');
 
-            $value->parent = $this; 
+            $value->parent = $this;
             $this->parameters[] = $value;
         } else {
             throw new InvalidArgumentException('You can only add parameters to the property object');
@@ -251,17 +297,16 @@ class Sabre_VObject_Property extends Sabre_VObject_Element {
     }
 
     /**
-     * Removes one or more parameters with the specified name 
-     * 
-     * @param string $name 
-     * @return void 
+     * Removes one or more parameters with the specified name
+     *
+     * @param string $name
+     * @return void
      */
     public function offsetUnset($name) {
 
-        if (is_int($name)) return parent::offsetUnset($name, $value);
+        if (is_int($name)) return parent::offsetUnset($name);
         $name = strtoupper($name);
-        
-        $result = array();
+
         foreach($this->parameters as $key=>$parameter) {
             if ($parameter->name == $name) {
                 $parameter->parent = null;
@@ -275,15 +320,29 @@ class Sabre_VObject_Property extends Sabre_VObject_Element {
     /* }}} */
 
     /**
-     * Called when this object is being cast to a string 
-     * 
-     * @return string 
+     * Called when this object is being cast to a string
+     *
+     * @return string
      */
     public function __toString() {
 
-        return $this->value;
+        return (string)$this->value;
 
     }
 
+    /**
+     * This method is automatically called when the object is cloned.
+     * Specifically, this will ensure all child elements are also cloned.
+     *
+     * @return void
+     */
+    public function __clone() {
+
+        foreach($this->parameters as $key=>$child) {
+            $this->parameters[$key] = clone $child;
+            $this->parameters[$key]->parent = $this;
+        }
+
+    }
 
 }
diff --git a/3rdparty/Sabre/VObject/Property/DateTime.php b/3rdparty/Sabre/VObject/Property/DateTime.php
new file mode 100644
index 0000000000000000000000000000000000000000..fe2372caa81cade8eb1aa149ea923e7fd62206dc
--- /dev/null
+++ b/3rdparty/Sabre/VObject/Property/DateTime.php
@@ -0,0 +1,260 @@
+<?php
+
+/**
+ * DateTime property
+ *
+ * This element is used for iCalendar properties such as the DTSTART property.
+ * It basically provides a few helper functions that make it easier to deal
+ * with these. It supports both DATE-TIME and DATE values.
+ *
+ * In order to use this correctly, you must call setDateTime and getDateTime to
+ * retrieve and modify dates respectively.
+ *
+ * If you use the 'value' or properties directly, this object does not keep
+ * reference and results might appear incorrectly.
+ *
+ * @package Sabre
+ * @subpackage VObject
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
+ * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
+ */
+class Sabre_VObject_Property_DateTime extends Sabre_VObject_Property {
+
+    /**
+     * Local 'floating' time
+     */
+    const LOCAL = 1;
+
+    /**
+     * UTC-based time
+     */
+    const UTC = 2;
+
+    /**
+     * Local time plus timezone
+     */
+    const LOCALTZ = 3;
+
+    /**
+     * Only a date, time is ignored
+     */
+    const DATE = 4;
+
+    /**
+     * DateTime representation
+     *
+     * @var DateTime
+     */
+    protected $dateTime;
+
+    /**
+     * dateType
+     *
+     * @var int
+     */
+    protected $dateType;
+
+    /**
+     * Updates the Date and Time.
+     *
+     * @param DateTime $dt
+     * @param int $dateType
+     * @return void
+     */
+    public function setDateTime(DateTime $dt, $dateType = self::LOCALTZ) {
+
+        switch($dateType) {
+
+            case self::LOCAL :
+                $this->setValue($dt->format('Ymd\\THis'));
+                $this->offsetUnset('VALUE');
+                $this->offsetUnset('TZID');
+                $this->offsetSet('VALUE','DATE-TIME');
+                break;
+            case self::UTC :
+                $dt->setTimeZone(new DateTimeZone('UTC'));
+                $this->setValue($dt->format('Ymd\\THis\\Z'));
+                $this->offsetUnset('VALUE');
+                $this->offsetUnset('TZID');
+                $this->offsetSet('VALUE','DATE-TIME');
+                break;
+            case self::LOCALTZ :
+                $this->setValue($dt->format('Ymd\\THis'));
+                $this->offsetUnset('VALUE');
+                $this->offsetUnset('TZID');
+                $this->offsetSet('VALUE','DATE-TIME');
+                $this->offsetSet('TZID', $dt->getTimeZone()->getName());
+                break;
+            case self::DATE :
+                $this->setValue($dt->format('Ymd'));
+                $this->offsetUnset('VALUE');
+                $this->offsetUnset('TZID');
+                $this->offsetSet('VALUE','DATE');
+                break;
+            default :
+                throw new InvalidArgumentException('You must pass a valid dateType constant');
+
+        }
+        $this->dateTime = $dt;
+        $this->dateType = $dateType;
+
+    }
+
+    /**
+     * Returns the current DateTime value.
+     *
+     * If no value was set, this method returns null.
+     *
+     * @return DateTime|null
+     */
+    public function getDateTime() {
+
+        if ($this->dateTime)
+            return $this->dateTime;
+
+        list(
+            $this->dateType,
+            $this->dateTime
+        ) = self::parseData($this->value, $this);
+        return $this->dateTime;
+
+    }
+
+    /**
+     * Returns the type of Date format.
+     *
+     * This method returns one of the format constants. If no date was set,
+     * this method will return null.
+     *
+     * @return int|null
+     */
+    public function getDateType() {
+
+        if ($this->dateType)
+            return $this->dateType;
+
+        list(
+            $this->dateType,
+            $this->dateTime,
+        ) = self::parseData($this->value, $this);
+        return $this->dateType;
+
+    }
+
+    /**
+     * Parses the internal data structure to figure out what the current date
+     * and time is.
+     *
+     * The returned array contains two elements:
+     *   1. A 'DateType' constant (as defined on this class), or null.
+     *   2. A DateTime object (or null)
+     *
+     * @param string|null $propertyValue The string to parse (yymmdd or
+     *                                   ymmddThhmmss, etc..)
+     * @param Sabre_VObject_Property|null $property The instance of the
+     *                                              property we're parsing.
+     * @return array
+     */
+    static public function parseData($propertyValue, Sabre_VObject_Property $property = null) {
+
+        if (is_null($propertyValue)) {
+            return array(null, null);
+        }
+
+        $date = '(?P<year>[1-2][0-9]{3})(?P<month>[0-1][0-9])(?P<date>[0-3][0-9])';
+        $time = '(?P<hour>[0-2][0-9])(?P<minute>[0-5][0-9])(?P<second>[0-5][0-9])';
+        $regex = "/^$date(T$time(?P<isutc>Z)?)?$/";
+
+        if (!preg_match($regex, $propertyValue, $matches)) {
+            throw new InvalidArgumentException($propertyValue . ' is not a valid DateTime or Date string');
+        }
+
+        if (!isset($matches['hour'])) {
+            // Date-only
+            return array(
+                self::DATE,
+                new DateTime($matches['year'] . '-' . $matches['month'] . '-' . $matches['date'] . ' 00:00:00'),
+            );
+        }
+
+        $dateStr =
+            $matches['year'] .'-' .
+            $matches['month'] . '-' .
+            $matches['date'] . ' ' .
+            $matches['hour'] . ':' .
+            $matches['minute'] . ':' .
+            $matches['second'];
+
+        if (isset($matches['isutc'])) {
+            $dt = new DateTime($dateStr,new DateTimeZone('UTC'));
+            $dt->setTimeZone(new DateTimeZone('UTC'));
+            return array(
+                self::UTC,
+                $dt
+            );
+        }
+
+        // Finding the timezone.
+        $tzid = $property['TZID'];
+        if (!$tzid) {
+            return array(
+                self::LOCAL,
+                new DateTime($dateStr)
+            );
+        }
+
+        try {
+            // tzid an Olson identifier?
+            $tz = new DateTimeZone($tzid->value);
+        } catch (Exception $e) {
+
+            // Not an Olson id, we're going to try to find the information 
+            // through the time zone name map.
+            $newtzid = Sabre_VObject_WindowsTimezoneMap::lookup($tzid->value);
+            if (is_null($newtzid)) {
+
+                // Not a well known time zone name either, we're going to try 
+                // to find the information through the VTIMEZONE object.
+
+                // First we find the root object
+                $root = $property;
+                while($root->parent) {
+                    $root = $root->parent;
+                }
+
+                if (isset($root->VTIMEZONE)) {
+                    foreach($root->VTIMEZONE as $vtimezone) {
+                        if (((string)$vtimezone->TZID) == $tzid) {
+                            if (isset($vtimezone->{'X-LIC-LOCATION'})) {
+                                $newtzid = (string)$vtimezone->{'X-LIC-LOCATION'};
+                            } else {
+                                // No libical location specified. As a last resort we could 
+                                // try matching $vtimezone's DST rules against all known 
+                                // time zones returned by DateTimeZone::list*
+
+                                // TODO
+                            }
+                        }
+                    }
+                }
+            }
+
+            try {
+                $tz = new DateTimeZone($newtzid);
+            } catch (Exception $e) {
+                // If all else fails, we use the default PHP timezone
+                $tz = new DateTimeZone(date_default_timezone_get()); 
+            }
+        }
+        $dt = new DateTime($dateStr, $tz);
+        $dt->setTimeZone($tz);
+
+        return array(
+            self::LOCALTZ,
+            $dt
+        );
+
+    }
+
+}
diff --git a/3rdparty/Sabre/VObject/Property/MultiDateTime.php b/3rdparty/Sabre/VObject/Property/MultiDateTime.php
new file mode 100644
index 0000000000000000000000000000000000000000..ae53ab6a6173a87922c90f8a5bb129ab8a341d92
--- /dev/null
+++ b/3rdparty/Sabre/VObject/Property/MultiDateTime.php
@@ -0,0 +1,166 @@
+<?php
+
+/**
+ * Multi-DateTime property
+ *
+ * This element is used for iCalendar properties such as the EXDATE property.
+ * It basically provides a few helper functions that make it easier to deal
+ * with these. It supports both DATE-TIME and DATE values.
+ *
+ * In order to use this correctly, you must call setDateTimes and getDateTimes
+ * to retrieve and modify dates respectively.
+ *
+ * If you use the 'value' or properties directly, this object does not keep
+ * reference and results might appear incorrectly.
+ *
+ * @package Sabre
+ * @subpackage VObject
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
+ * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
+ */
+class Sabre_VObject_Property_MultiDateTime extends Sabre_VObject_Property {
+
+    /**
+     * DateTime representation
+     *
+     * @var DateTime[]
+     */
+    protected $dateTimes;
+
+    /**
+     * dateType
+     *
+     * This is one of the Sabre_VObject_Property_DateTime constants.
+     *
+     * @var int
+     */
+    protected $dateType;
+
+    /**
+     * Updates the value
+     *
+     * @param array $dt Must be an array of DateTime objects.
+     * @param int $dateType
+     * @return void
+     */
+    public function setDateTimes(array $dt, $dateType = Sabre_VObject_Property_DateTime::LOCALTZ) {
+
+        foreach($dt as $i)
+            if (!$i instanceof DateTime)
+                throw new InvalidArgumentException('You must pass an array of DateTime objects');
+
+        $this->offsetUnset('VALUE');
+        $this->offsetUnset('TZID');
+        switch($dateType) {
+
+            case Sabre_VObject_Property_DateTime::LOCAL :
+                $val = array();
+                foreach($dt as $i) {
+                    $val[] = $i->format('Ymd\\THis');
+                }
+                $this->setValue(implode(',',$val));
+                $this->offsetSet('VALUE','DATE-TIME');
+                break;
+            case Sabre_VObject_Property_DateTime::UTC :
+                $val = array();
+                foreach($dt as $i) {
+                    $i->setTimeZone(new DateTimeZone('UTC'));
+                    $val[] = $i->format('Ymd\\THis\\Z');
+                }
+                $this->setValue(implode(',',$val));
+                $this->offsetSet('VALUE','DATE-TIME');
+                break;
+            case Sabre_VObject_Property_DateTime::LOCALTZ :
+                $val = array();
+                foreach($dt as $i) {
+                    $val[] = $i->format('Ymd\\THis');
+                }
+                $this->setValue(implode(',',$val));
+                $this->offsetSet('VALUE','DATE-TIME');
+                $this->offsetSet('TZID', $dt[0]->getTimeZone()->getName());
+                break;
+            case Sabre_VObject_Property_DateTime::DATE :
+                $val = array();
+                foreach($dt as $i) {
+                    $val[] = $i->format('Ymd');
+                }
+                $this->setValue(implode(',',$val));
+                $this->offsetSet('VALUE','DATE');
+                break;
+            default :
+                throw new InvalidArgumentException('You must pass a valid dateType constant');
+
+        }
+        $this->dateTimes = $dt;
+        $this->dateType = $dateType;
+
+    }
+
+    /**
+     * Returns the current DateTime value.
+     *
+     * If no value was set, this method returns null.
+     *
+     * @return array|null
+     */
+    public function getDateTimes() {
+
+        if ($this->dateTimes)
+            return $this->dateTimes;
+
+        $dts = array();
+
+        if (!$this->value) {
+            $this->dateTimes = null;
+            $this->dateType = null;
+            return null;
+        }
+
+        foreach(explode(',',$this->value) as $val) {
+            list(
+                $type,
+                $dt
+            ) = Sabre_VObject_Property_DateTime::parseData($val, $this);
+            $dts[] = $dt;
+            $this->dateType = $type;
+        }
+        $this->dateTimes = $dts;
+        return $this->dateTimes;
+
+    }
+
+    /**
+     * Returns the type of Date format.
+     *
+     * This method returns one of the format constants. If no date was set,
+     * this method will return null.
+     *
+     * @return int|null
+     */
+    public function getDateType() {
+
+        if ($this->dateType)
+            return $this->dateType;
+
+        if (!$this->value) {
+            $this->dateTimes = null;
+            $this->dateType = null;
+            return null;
+        }
+
+        $dts = array();
+        foreach(explode(',',$this->value) as $val) {
+            list(
+                $type,
+                $dt
+            ) = Sabre_VObject_Property_DateTime::parseData($val, $this);
+            $dts[] = $dt;
+            $this->dateType = $type;
+        }
+        $this->dateTimes = $dts;
+        return $this->dateType;
+
+    }
+
+}
diff --git a/3rdparty/Sabre/VObject/Reader.php b/3rdparty/Sabre/VObject/Reader.php
index 7d1c282838e84e09cccaa4e57f540537e5f3b74d..eea73fa3dcee68163a42e9703a748feb783007fb 100644
--- a/3rdparty/Sabre/VObject/Reader.php
+++ b/3rdparty/Sabre/VObject/Reader.php
@@ -5,40 +5,22 @@
  *
  * This class reads the vobject file, and returns a full element tree.
  *
+ * TODO: this class currently completely works 'statically'. This is pointless,
+ * and defeats OOP principals. Needs refactoring in a future version.
  *
- * TODO: this class currently completely works 'statically'. This is pointless, 
- * and defeats OOP principals. Needs refaxtoring in a future version.
- * 
  * @package Sabre
  * @subpackage VObject
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
- * @author Evert Pot (http://www.rooftopsolutions.nl/) 
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
  */
 class Sabre_VObject_Reader {
 
     /**
-     * This array contains a list of Property names that are automatically 
-     * mapped to specific class names.
+     * Parses the file and returns the top component
      *
-     * Adding to this list allows you to specify custom property classes, 
-     * adding extra functionality. 
-     * 
-     * @var array
-     */
-    static public $elementMap = array(
-        'DTSTART'   => 'Sabre_VObject_Element_DateTime',
-        'DTEND'     => 'Sabre_VObject_Element_DateTime',
-        'COMPLETED' => 'Sabre_VObject_Element_DateTime',
-        'DUE'       => 'Sabre_VObject_Element_DateTime',
-        'EXDATE'    => 'Sabre_VObject_Element_MultiDateTime',
-    );
-
-    /**
-     * Parses the file and returns the top component 
-     * 
-     * @param string $data 
-     * @return Sabre_VObject_Element 
+     * @param string $data
+     * @return Sabre_VObject_Element
      */
     static function read($data) {
 
@@ -63,11 +45,11 @@ class Sabre_VObject_Reader {
         }
 
         unset($lines);
-        
+
         reset($lines2);
 
         return self::readLine($lines2);
-       
+
     }
 
     /**
@@ -75,9 +57,9 @@ class Sabre_VObject_Reader {
      *
      * This method receives the full array of lines. The array pointer is used
      * to traverse.
-     * 
-     * @param array $lines 
-     * @return Sabre_VObject_Element 
+     *
+     * @param array $lines
+     * @return Sabre_VObject_Element
      */
     static private function readLine(&$lines) {
 
@@ -88,22 +70,23 @@ class Sabre_VObject_Reader {
         // Components
         if (stripos($line,"BEGIN:")===0) {
 
-            // This is a component
-            $obj = new Sabre_VObject_Component(strtoupper(substr($line,6)));
+            $componentName = strtoupper(substr($line,6));
+            $obj = Sabre_VObject_Component::create($componentName);
 
             $nextLine = current($lines);
 
             while(stripos($nextLine,"END:")!==0) {
 
                 $obj->add(self::readLine($lines));
+
                 $nextLine = current($lines);
 
-                if ($nextLine===false) 
+                if ($nextLine===false)
                     throw new Sabre_VObject_ParseException('Invalid VObject. Document ended prematurely.');
 
             }
 
-            // Checking component name of the 'END:' line. 
+            // Checking component name of the 'END:' line.
             if (substr($nextLine,4)!==$obj->name) {
                 throw new Sabre_VObject_ParseException('Invalid VObject, expected: "END:' . $obj->name . '" got: "' . $nextLine . '"');
             }
@@ -117,7 +100,7 @@ class Sabre_VObject_Reader {
         //$result = preg_match('/(?P<name>[A-Z0-9-]+)(?:;(?P<parameters>^(?<!:):))(.*)$/',$line,$matches);
 
 
-        $token = '[A-Z0-9-\/\.]+';
+        $token = '[A-Z0-9-\.]+';
         $parameters = "(?:;(?P<parameters>([^:^\"]|\"([^\"]*)\")*))?";
         $regex = "/^(?P<name>$token)$parameters:(?P<value>.*)$/i";
 
@@ -128,22 +111,23 @@ class Sabre_VObject_Reader {
         }
 
         $propertyName = strtoupper($matches['name']);
-        $propertyValue = stripcslashes($matches['value']);
-
-        if (isset(self::$elementMap[$propertyName])) {
-            $className = self::$elementMap[$propertyName];
-        } else {
-            $className = 'Sabre_VObject_Property';
-        }
+        $propertyValue = preg_replace_callback('#(\\\\(\\\\|N|n|;|,))#',function($matches) {
+            if ($matches[2]==='n' || $matches[2]==='N') {
+                return "\n";
+            } else {
+                return $matches[2];
+            }
+        }, $matches['value']);
 
-        $obj = new $className($propertyName, $propertyValue);
+        $obj = Sabre_VObject_Property::create($propertyName, $propertyValue);
 
         if ($matches['parameters']) {
 
             foreach(self::readParameters($matches['parameters']) as $param) {
                 $obj->add($param);
             }
-        } 
+
+        }
 
         return $obj;
 
@@ -151,12 +135,12 @@ class Sabre_VObject_Reader {
     }
 
     /**
-     * Reads a parameter list from a property 
+     * Reads a parameter list from a property
      *
      * This method returns an array of Sabre_VObject_Parameter
      *
-     * @param string $parameters 
-     * @return array 
+     * @param string $parameters
+     * @return array
      */
     static private function readParameters($parameters) {
 
@@ -179,7 +163,15 @@ class Sabre_VObject_Reader {
                 $value = '';
             }
 
-            $params[] = new Sabre_VObject_Parameter($match['paramName'], stripcslashes($value));
+            $value = preg_replace_callback('#(\\\\(\\\\|N|n|;|,))#',function($matches) {
+                if ($matches[2]==='n' || $matches[2]==='N') {
+                    return "\n";
+                } else {
+                    return $matches[2];
+                }
+            }, $value);
+
+            $params[] = new Sabre_VObject_Parameter($match['paramName'], $value);
 
         }
 
diff --git a/3rdparty/Sabre/VObject/RecurrenceIterator.php b/3rdparty/Sabre/VObject/RecurrenceIterator.php
new file mode 100644
index 0000000000000000000000000000000000000000..833aa091ab759cb0a0f7d290ddd6471c7ff99df8
--- /dev/null
+++ b/3rdparty/Sabre/VObject/RecurrenceIterator.php
@@ -0,0 +1,1009 @@
+<?php
+
+/**
+ * This class is used to determine new for a recurring event, when the next
+ * events occur.
+ *
+ * This iterator may loop infinitely in the future, therefore it is important
+ * that if you use this class, you set hard limits for the amount of iterations
+ * you want to handle.
+ *
+ * Note that currently there is not full support for the entire iCalendar
+ * specification, as it's very complex and contains a lot of permutations
+ * that's not yet used very often in software.
+ *
+ * For the focus has been on features as they actually appear in Calendaring
+ * software, but this may well get expanded as needed / on demand
+ *
+ * The following RRULE properties are supported
+ *   * UNTIL
+ *   * INTERVAL
+ *   * COUNT
+ *   * FREQ=DAILY
+ *     * BYDAY
+ *   * FREQ=WEEKLY
+ *     * BYDAY
+ *     * WKST
+ *   * FREQ=MONTHLY
+ *     * BYMONTHDAY
+ *     * BYDAY
+ *     * BYSETPOS
+ *   * FREQ=YEARLY
+ *     * BYMONTH
+ *     * BYMONTHDAY (only if BYMONTH is also set)
+ *     * BYDAY (only if BYMONTH is also set)
+ *
+ * Anything beyond this is 'undefined', which means that it may get ignored, or
+ * you may get unexpected results. The effect is that in some applications the
+ * specified recurrence may look incorrect, or is missing.
+ *
+ * @package Sabre
+ * @subpackage VObject
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
+ * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
+ */
+class Sabre_VObject_RecurrenceIterator implements Iterator {
+
+    /**
+     * The initial event date
+     *
+     * @var DateTime
+     */
+    public $startDate;
+
+    /**
+     * The end-date of the initial event
+     *
+     * @var DateTime
+     */
+    public $endDate;
+
+    /**
+     * The 'current' recurrence.
+     *
+     * This will be increased for every iteration.
+     *
+     * @var DateTime
+     */
+    public $currentDate;
+
+
+    /**
+     * List of dates that are excluded from the rules.
+     *
+     * This list contains the items that have been overriden by the EXDATE
+     * property.
+     *
+     * @var array
+     */
+    public $exceptionDates = array();
+
+    /**
+     * Base event
+     *
+     * @var Sabre_VObject_Component_VEvent
+     */
+    public $baseEvent;
+
+    /**
+     * List of dates that are overridden by other events.
+     * Similar to $overriddenEvents, but this just contains the original dates.
+     *
+     * @var array
+     */
+    public $overriddenDates = array();
+
+    /**
+     * list of events that are 'overridden'.
+     *
+     * This is an array of Sabre_VObject_Component_VEvent objects.
+     *
+     * @var array
+     */
+    public $overriddenEvents = array();
+
+
+    /**
+     * Frequency is one of: secondly, minutely, hourly, daily, weekly, monthly,
+     * yearly.
+     *
+     * @var string
+     */
+    public $frequency;
+
+    /**
+     * The last instance of this recurrence, inclusively
+     *
+     * @var DateTime|null
+     */
+    public $until;
+
+    /**
+     * The number of recurrences, or 'null' if infinitely recurring.
+     *
+     * @var int
+     */
+    public $count;
+
+    /**
+     * The interval.
+     *
+     * If for example frequency is set to daily, interval = 2 would mean every
+     * 2 days.
+     *
+     * @var int
+     */
+    public $interval = 1;
+
+    /**
+     * Which seconds to recur.
+     *
+     * This is an array of integers (between 0 and 60)
+     *
+     * @var array
+     */
+    public $bySecond;
+
+    /**
+     * Which minutes to recur
+     *
+     * This is an array of integers (between 0 and 59)
+     *
+     * @var array
+     */
+    public $byMinute;
+
+    /**
+     * Which hours to recur
+     *
+     * This is an array of integers (between 0 and 23)
+     *
+     * @var array
+     */
+    public $byHour;
+
+    /**
+     * Which weekdays to recur.
+     *
+     * This is an array of weekdays
+     *
+     * This may also be preceeded by a positive or negative integer. If present,
+     * this indicates the nth occurrence of a specific day within the monthly or
+     * yearly rrule. For instance, -2TU indicates the second-last tuesday of
+     * the month, or year.
+     *
+     * @var array
+     */
+    public $byDay;
+
+    /**
+     * Which days of the month to recur
+     *
+     * This is an array of days of the months (1-31). The value can also be
+     * negative. -5 for instance means the 5th last day of the month.
+     *
+     * @var array
+     */
+    public $byMonthDay;
+
+    /**
+     * Which days of the year to recur.
+     *
+     * This is an array with days of the year (1 to 366). The values can also
+     * be negative. For instance, -1 will always represent the last day of the
+     * year. (December 31st).
+     *
+     * @var array
+     */
+    public $byYearDay;
+
+    /**
+     * Which week numbers to recur.
+     *
+     * This is an array of integers from 1 to 53. The values can also be
+     * negative. -1 will always refer to the last week of the year.
+     *
+     * @var array
+     */
+    public $byWeekNo;
+
+    /**
+     * Which months to recur
+     *
+     * This is an array of integers from 1 to 12.
+     *
+     * @var array
+     */
+    public $byMonth;
+
+    /**
+     * Which items in an existing st to recur.
+     *
+     * These numbers work together with an existing by* rule. It specifies
+     * exactly which items of the existing by-rule to filter.
+     *
+     * Valid values are 1 to 366 and -1 to -366. As an example, this can be
+     * used to recur the last workday of the month.
+     *
+     * This would be done by setting frequency to 'monthly', byDay to
+     * 'MO,TU,WE,TH,FR' and bySetPos to -1.
+     *
+     * @var array
+     */
+    public $bySetPos;
+
+    /**
+     * When a week starts
+     *
+     * @var string
+     */
+    public $weekStart = 'MO';
+
+    /**
+     * The current item in the list
+     *
+     * @var int
+     */
+    public $counter = 0;
+
+    /**
+     * Simple mapping from iCalendar day names to day numbers
+     *
+     * @var array
+     */
+    private $dayMap = array(
+        'SU' => 0,
+        'MO' => 1,
+        'TU' => 2,
+        'WE' => 3,
+        'TH' => 4,
+        'FR' => 5,
+        'SA' => 6,
+    );
+
+    /**
+     * Mappings between the day number and english day name.
+     *
+     * @var array
+     */
+    private $dayNames = array(
+        0 => 'Sunday',
+        1 => 'Monday',
+        2 => 'Tuesday',
+        3 => 'Wednesday',
+        4 => 'Thursday',
+        5 => 'Friday',
+        6 => 'Saturday',
+    );
+
+    /**
+     * If the current iteration of the event is an overriden event, this
+     * property will hold the VObject
+     *
+     * @var Sabre_Component_VObject
+     */
+    private $currentOverriddenEvent;
+
+    /**
+     * This property may contain the date of the next not-overridden event.
+     * This date is calculated sometimes a bit early, before overridden events
+     * are evaluated.
+     *
+     * @var DateTime
+     */
+    private $nextDate;
+
+    /**
+     * Creates the iterator
+     *
+     * You should pass a VCALENDAR component, as well as the UID of the event
+     * we're going to traverse.
+     *
+     * @param Sabre_VObject_Component $vcal
+     * @param string|null $uid
+     */
+    public function __construct(Sabre_VObject_Component $vcal, $uid=null) {
+
+        if (is_null($uid)) {
+            if ($vcal->name === 'VCALENDAR') {
+                throw new InvalidArgumentException('If you pass a VCALENDAR object, you must pass a uid argument as well');
+            }
+            $components = array($vcal);
+            $uid = (string)$vcal->uid;
+        } else {
+            $components = $vcal->select('VEVENT');
+        }
+        foreach($components as $component) {
+            if ((string)$component->uid == $uid) {
+                if (isset($component->{'RECURRENCE-ID'})) {
+                    $this->overriddenEvents[$component->DTSTART->getDateTime()->getTimeStamp()] = $component;
+                    $this->overriddenDates[] = $component->{'RECURRENCE-ID'}->getDateTime();
+                } else {
+                    $this->baseEvent = $component;
+                }
+            }
+        }
+        if (!$this->baseEvent) {
+            throw new InvalidArgumentException('Could not find a base event with uid: ' . $uid);
+        }
+
+        $this->startDate = clone $this->baseEvent->DTSTART->getDateTime();
+
+        $this->endDate = null;
+        if (isset($this->baseEvent->DTEND)) {
+            $this->endDate = clone $this->baseEvent->DTEND->getDateTime();
+        } else {
+            $this->endDate = clone $this->startDate;
+            if (isset($this->baseEvent->DURATION)) {
+                $this->endDate->add(Sabre_VObject_DateTimeParser::parse($this->baseEvent->DURATION->value));
+            }
+        }
+        $this->currentDate = clone $this->startDate;
+
+        $rrule = (string)$this->baseEvent->RRULE;
+
+        $parts = explode(';', $rrule);
+
+        foreach($parts as $part) {
+
+            list($key, $value) = explode('=', $part, 2);
+
+            switch(strtoupper($key)) {
+
+                case 'FREQ' :
+                    if (!in_array(
+                        strtolower($value),
+                        array('secondly','minutely','hourly','daily','weekly','monthly','yearly')
+                    )) {
+                        throw new InvalidArgumentException('Unknown value for FREQ=' . strtoupper($value));
+
+                    }
+                    $this->frequency = strtolower($value);
+                    break;
+
+                case 'UNTIL' :
+                    $this->until = Sabre_VObject_DateTimeParser::parse($value);
+                    break;
+
+                case 'COUNT' :
+                    $this->count = (int)$value;
+                    break;
+
+                case 'INTERVAL' :
+                    $this->interval = (int)$value;
+                    break;
+
+                case 'BYSECOND' :
+                    $this->bySecond = explode(',', $value);
+                    break;
+
+                case 'BYMINUTE' :
+                    $this->byMinute = explode(',', $value);
+                    break;
+
+                case 'BYHOUR' :
+                    $this->byHour = explode(',', $value);
+                    break;
+
+                case 'BYDAY' :
+                    $this->byDay = explode(',', strtoupper($value));
+                    break;
+
+                case 'BYMONTHDAY' :
+                    $this->byMonthDay = explode(',', $value);
+                    break;
+
+                case 'BYYEARDAY' :
+                    $this->byYearDay = explode(',', $value);
+                    break;
+
+                case 'BYWEEKNO' :
+                    $this->byWeekNo = explode(',', $value);
+                    break;
+
+                case 'BYMONTH' :
+                    $this->byMonth = explode(',', $value);
+                    break;
+
+                case 'BYSETPOS' :
+                    $this->bySetPos = explode(',', $value);
+                    break;
+
+                case 'WKST' :
+                    $this->weekStart = strtoupper($value);
+                    break;
+
+            }
+
+        }
+
+        // Parsing exception dates
+        if (isset($this->baseEvent->EXDATE)) {
+            foreach($this->baseEvent->EXDATE as $exDate) {
+
+                foreach(explode(',', (string)$exDate) as $exceptionDate) {
+
+                    $this->exceptionDates[] =
+                        Sabre_VObject_DateTimeParser::parse($exceptionDate, $this->startDate->getTimeZone());
+
+                }
+
+            }
+
+        }
+
+    }
+
+    /**
+     * Returns the current item in the list
+     *
+     * @return DateTime
+     */
+    public function current() {
+
+        if (!$this->valid()) return null;
+        return clone $this->currentDate;
+
+    }
+
+    /**
+     * This method returns the startdate for the current iteration of the
+     * event.
+     *
+     * @return DateTime
+     */
+    public function getDtStart() {
+
+        if (!$this->valid()) return null;
+        return clone $this->currentDate;
+
+    }
+
+    /**
+     * This method returns the enddate for the current iteration of the
+     * event.
+     *
+     * @return DateTime
+     */
+    public function getDtEnd() {
+
+        if (!$this->valid()) return null;
+        $dtEnd = clone $this->currentDate;
+        $dtEnd->add( $this->startDate->diff( $this->endDate ) );
+        return clone $dtEnd;
+
+    }
+
+    /**
+     * Returns a VEVENT object with the updated start and end date.
+     *
+     * Any recurrence information is removed, and this function may return an
+     * 'overridden' event instead.
+     *
+     * This method always returns a cloned instance.
+     *
+     * @return void
+     */
+    public function getEventObject() {
+
+        if ($this->currentOverriddenEvent) {
+            return clone $this->currentOverriddenEvent;
+        }
+        $event = clone $this->baseEvent;
+        unset($event->RRULE);
+        unset($event->EXDATE);
+        unset($event->RDATE);
+        unset($event->EXRULE);
+
+        $event->DTSTART->setDateTime($this->getDTStart(), $event->DTSTART->getDateType());
+        if (isset($event->DTEND)) {
+            $event->DTEND->setDateTime($this->getDtEnd(), $event->DTSTART->getDateType());
+        }
+        if ($this->counter > 0) {
+            $event->{'RECURRENCE-ID'} = (string)$event->DTSTART;
+        }
+
+        return $event;
+
+    }
+
+    /**
+     * Returns the current item number
+     *
+     * @return int
+     */
+    public function key() {
+
+        return $this->counter;
+
+    }
+
+    /**
+     * Whether or not there is a 'next item'
+     *
+     * @return bool
+     */
+    public function valid() {
+
+        if (!is_null($this->count)) {
+            return $this->counter < $this->count;
+        }
+        if (!is_null($this->until)) {
+            return $this->currentDate <= $this->until;
+        }
+        return true;
+
+    }
+
+    /**
+     * Resets the iterator
+     *
+     * @return void
+     */
+    public function rewind() {
+
+        $this->currentDate = clone $this->startDate;
+        $this->counter = 0;
+
+    }
+
+    /**
+     * This method allows you to quickly go to the next occurrence after the
+     * specified date.
+     *
+     * Note that this checks the current 'endDate', not the 'stardDate'. This
+     * means that if you forward to January 1st, the iterator will stop at the
+     * first event that ends *after* January 1st.
+     *
+     * @param DateTime $dt
+     * @return void
+     */
+    public function fastForward(DateTime $dt) {
+
+        while($this->valid() && $this->getDTEnd() < $dt) {
+            $this->next();
+        }
+
+    }
+
+    /**
+     * Goes on to the next iteration
+     *
+     * @return void
+     */
+    public function next() {
+
+        /*
+        if (!is_null($this->count) && $this->counter >= $this->count) {
+            $this->currentDate = null;
+        }*/
+
+
+        $previousStamp = $this->currentDate->getTimeStamp();
+
+        while(true) {
+
+            $this->currentOverriddenEvent = null;
+
+            // If we have a next date 'stored', we use that
+            if ($this->nextDate) {
+                $this->currentDate = $this->nextDate;
+                $currentStamp = $this->currentDate->getTimeStamp();
+                $this->nextDate = null;
+            } else {
+
+                // Otherwise, we calculate it
+                switch($this->frequency) {
+
+                    case 'daily' :
+                        $this->nextDaily();
+                        break;
+
+                    case 'weekly' :
+                        $this->nextWeekly();
+                        break;
+
+                    case 'monthly' :
+                        $this->nextMonthly();
+                        break;
+
+                    case 'yearly' :
+                        $this->nextYearly();
+                        break;
+
+                }
+                $currentStamp = $this->currentDate->getTimeStamp();
+
+                // Checking exception dates
+                foreach($this->exceptionDates as $exceptionDate) {
+                    if ($this->currentDate == $exceptionDate) {
+                        $this->counter++;
+                        continue 2;
+                    }
+                }
+                foreach($this->overriddenDates as $overriddenDate) {
+                    if ($this->currentDate == $overriddenDate) {
+                        continue 2;
+                    }
+                }
+
+            }
+
+            // Checking overriden events
+            foreach($this->overriddenEvents as $index=>$event) {
+                if ($index > $previousStamp && $index <= $currentStamp) {
+
+                    // We're moving the 'next date' aside, for later use.
+                    $this->nextDate = clone $this->currentDate;
+
+                    $this->currentDate = $event->DTSTART->getDateTime();
+                    $this->currentOverriddenEvent = $event;
+
+                    break;
+                }
+            }
+
+            break;
+
+        }
+
+        /*
+        if (!is_null($this->until)) {
+            if($this->currentDate > $this->until) {
+                $this->currentDate = null;
+            }
+        }*/
+
+        $this->counter++;
+
+    }
+
+    /**
+     * Does the processing for advancing the iterator for daily frequency.
+     *
+     * @return void
+     */
+    protected function nextDaily() {
+
+        if (!$this->byDay) {
+            $this->currentDate->modify('+' . $this->interval . ' days');
+            return;
+        }
+
+        $recurrenceDays = array();
+        foreach($this->byDay as $byDay) {
+
+            // The day may be preceeded with a positive (+n) or
+            // negative (-n) integer. However, this does not make
+            // sense in 'weekly' so we ignore it here.
+            $recurrenceDays[] = $this->dayMap[substr($byDay,-2)];
+
+        }
+
+        do {
+
+            $this->currentDate->modify('+' . $this->interval . ' days');
+
+            // Current day of the week
+            $currentDay = $this->currentDate->format('w');
+
+        } while (!in_array($currentDay, $recurrenceDays));
+
+    }
+
+    /**
+     * Does the processing for advancing the iterator for weekly frequency.
+     *
+     * @return void
+     */
+    protected function nextWeekly() {
+
+        if (!$this->byDay) {
+            $this->currentDate->modify('+' . $this->interval . ' weeks');
+            return;
+        }
+
+        $recurrenceDays = array();
+        foreach($this->byDay as $byDay) {
+
+            // The day may be preceeded with a positive (+n) or
+            // negative (-n) integer. However, this does not make
+            // sense in 'weekly' so we ignore it here.
+            $recurrenceDays[] = $this->dayMap[substr($byDay,-2)];
+
+        }
+
+        // Current day of the week
+        $currentDay = $this->currentDate->format('w');
+
+        // First day of the week:
+        $firstDay = $this->dayMap[$this->weekStart];
+
+        $time = array(
+            $this->currentDate->format('H'),
+            $this->currentDate->format('i'),
+            $this->currentDate->format('s')
+        );
+
+        // Increasing the 'current day' until we find our next
+        // occurrence.
+        while(true) {
+
+            $currentDay++;
+
+            if ($currentDay>6) {
+                $currentDay = 0;
+            }
+
+            // We need to roll over to the next week
+            if ($currentDay === $firstDay) {
+                $this->currentDate->modify('+' . $this->interval . ' weeks');
+
+                // We need to go to the first day of this week, but only if we
+                // are not already on this first day of this week.
+                if($this->currentDate->format('w') != $firstDay) {
+                    $this->currentDate->modify('last ' . $this->dayNames[$this->dayMap[$this->weekStart]]);
+                    $this->currentDate->setTime($time[0],$time[1],$time[2]);
+                }
+            }
+
+            // We have a match
+            if (in_array($currentDay ,$recurrenceDays)) {
+                $this->currentDate->modify($this->dayNames[$currentDay]);
+                $this->currentDate->setTime($time[0],$time[1],$time[2]);
+                break;
+            }
+
+        }
+
+    }
+
+    /**
+     * Does the processing for advancing the iterator for monthly frequency.
+     *
+     * @return void
+     */
+    protected function nextMonthly() {
+
+        $currentDayOfMonth = $this->currentDate->format('j');
+        if (!$this->byMonthDay && !$this->byDay) {
+
+            // If the current day is higher than the 28th, rollover can
+            // occur to the next month. We Must skip these invalid
+            // entries.
+            if ($currentDayOfMonth < 29) {
+                $this->currentDate->modify('+' . $this->interval . ' months');
+            } else {
+                $increase = 0;
+                do {
+                    $increase++;
+                    $tempDate = clone $this->currentDate;
+                    $tempDate->modify('+ ' . ($this->interval*$increase) . ' months');
+                } while ($tempDate->format('j') != $currentDayOfMonth);
+                $this->currentDate = $tempDate;
+            }
+            return;
+        }
+
+        while(true) {
+
+            $occurrences = $this->getMonthlyOccurrences();
+
+            foreach($occurrences as $occurrence) {
+
+                // The first occurrence thats higher than the current
+                // day of the month wins.
+                if ($occurrence > $currentDayOfMonth) {
+                    break 2;
+                }
+
+            }
+
+            // If we made it all the way here, it means there were no
+            // valid occurrences, and we need to advance to the next
+            // month.
+            $this->currentDate->modify('first day of this month');
+            $this->currentDate->modify('+ ' . $this->interval . ' months');
+
+            // This goes to 0 because we need to start counting at hte
+            // beginning.
+            $currentDayOfMonth = 0;
+
+        }
+
+        $this->currentDate->setDate($this->currentDate->format('Y'), $this->currentDate->format('n'), $occurrence);
+
+    }
+
+    /**
+     * Does the processing for advancing the iterator for yearly frequency.
+     *
+     * @return void
+     */
+    protected function nextYearly() {
+
+        if (!$this->byMonth) {
+            $this->currentDate->modify('+' . $this->interval . ' years');
+            return;
+        }
+
+        $currentMonth = $this->currentDate->format('n');
+        $currentYear = $this->currentDate->format('Y');
+        $currentDayOfMonth = $this->currentDate->format('j');
+
+        $advancedToNewMonth = false;
+
+        // If we got a byDay or getMonthDay filter, we must first expand
+        // further.
+        if ($this->byDay || $this->byMonthDay) {
+
+            while(true) {
+
+                $occurrences = $this->getMonthlyOccurrences();
+
+                foreach($occurrences as $occurrence) {
+
+                    // The first occurrence that's higher than the current
+                    // day of the month wins.
+                    // If we advanced to the next month or year, the first
+                    // occurence is always correct.
+                    if ($occurrence > $currentDayOfMonth || $advancedToNewMonth) {
+                        break 2;
+                    }
+
+                }
+
+                // If we made it here, it means we need to advance to
+                // the next month or year.
+                $currentDayOfMonth = 1;
+                $advancedToNewMonth = true;
+                do {
+
+                    $currentMonth++;
+                    if ($currentMonth>12) {
+                        $currentYear+=$this->interval;
+                        $currentMonth = 1;
+                    }
+                } while (!in_array($currentMonth, $this->byMonth));
+
+                $this->currentDate->setDate($currentYear, $currentMonth, $currentDayOfMonth);
+
+            }
+
+            // If we made it here, it means we got a valid occurrence
+            $this->currentDate->setDate($currentYear, $currentMonth, $occurrence);
+            return;
+
+        } else {
+
+            // no byDay or byMonthDay, so we can just loop through the
+            // months.
+            do {
+
+                $currentMonth++;
+                if ($currentMonth>12) {
+                    $currentYear+=$this->interval;
+                    $currentMonth = 1;
+                }
+            } while (!in_array($currentMonth, $this->byMonth));
+            $this->currentDate->setDate($currentYear, $currentMonth, $currentDayOfMonth);
+            return;
+
+        }
+
+    }
+
+    /**
+     * Returns all the occurrences for a monthly frequency with a 'byDay' or
+     * 'byMonthDay' expansion for the current month.
+     *
+     * The returned list is an array of integers with the day of month (1-31).
+     *
+     * @return array
+     */
+    protected function getMonthlyOccurrences() {
+
+        $startDate = clone $this->currentDate;
+
+        $byDayResults = array();
+
+        // Our strategy is to simply go through the byDays, advance the date to
+        // that point and add it to the results.
+        if ($this->byDay) foreach($this->byDay as $day) {
+
+            $dayName = $this->dayNames[$this->dayMap[substr($day,-2)]];
+
+            // Dayname will be something like 'wednesday'. Now we need to find
+            // all wednesdays in this month.
+            $dayHits = array();
+
+            $checkDate = clone $startDate;
+            $checkDate->modify('first day of this month');
+            $checkDate->modify($dayName);
+
+            do {
+                $dayHits[] = $checkDate->format('j');
+                $checkDate->modify('next ' . $dayName);
+            } while ($checkDate->format('n') === $startDate->format('n'));
+
+            // So now we have 'all wednesdays' for month. It is however
+            // possible that the user only really wanted the 1st, 2nd or last
+            // wednesday.
+            if (strlen($day)>2) {
+                $offset = (int)substr($day,0,-2);
+
+                if ($offset>0) {
+                    // It is possible that the day does not exist, such as a
+                    // 5th or 6th wednesday of the month.
+                    if (isset($dayHits[$offset-1])) {
+                        $byDayResults[] = $dayHits[$offset-1];
+                    }
+                } else {
+
+                    // if it was negative we count from the end of the array
+                    $byDayResults[] = $dayHits[count($dayHits) + $offset];
+                }
+            } else {
+                // There was no counter (first, second, last wednesdays), so we
+                // just need to add the all to the list).
+                $byDayResults = array_merge($byDayResults, $dayHits);
+
+            }
+
+        }
+
+        $byMonthDayResults = array();
+        if ($this->byMonthDay) foreach($this->byMonthDay as $monthDay) {
+
+            // Removing values that are out of range for this month
+            if ($monthDay > $startDate->format('t') ||
+                $monthDay < 0-$startDate->format('t')) {
+                    continue;
+            }
+            if ($monthDay>0) {
+                $byMonthDayResults[] = $monthDay;
+            } else {
+                // Negative values
+                $byMonthDayResults[] = $startDate->format('t') + 1 + $monthDay;
+            }
+        }
+
+        // If there was just byDay or just byMonthDay, they just specify our
+        // (almost) final list. If both were provided, then byDay limits the
+        // list.
+        if ($this->byMonthDay && $this->byDay) {
+            $result = array_intersect($byMonthDayResults, $byDayResults);
+        } elseif ($this->byMonthDay) {
+            $result = $byMonthDayResults;
+        } else {
+            $result = $byDayResults;
+        }
+        $result = array_unique($result);
+        sort($result, SORT_NUMERIC);
+
+        // The last thing that needs checking is the BYSETPOS. If it's set, it
+        // means only certain items in the set survive the filter.
+        if (!$this->bySetPos) {
+            return $result;
+        }
+
+        $filteredResult = array();
+        foreach($this->bySetPos as $setPos) {
+
+            if ($setPos<0) {
+                $setPos = count($result)-($setPos+1);
+            }
+            if (isset($result[$setPos-1])) {
+                $filteredResult[] = $result[$setPos-1];
+            }
+        }
+
+        sort($filteredResult, SORT_NUMERIC);
+        return $filteredResult;
+
+    }
+
+
+}
+
diff --git a/3rdparty/Sabre/VObject/Version.php b/3rdparty/Sabre/VObject/Version.php
index 937c367e222afa447e57a3628519d860939e21e9..00110febc075802e5e595460530ba9f68f08a3a5 100644
--- a/3rdparty/Sabre/VObject/Version.php
+++ b/3rdparty/Sabre/VObject/Version.php
@@ -2,10 +2,10 @@
 
 /**
  * This class contains the version number for the VObject package
- * 
+ *
  * @package Sabre
- * @subpackage VObject 
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
+ * @subpackage VObject
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
  * @author Evert Pot (http://www.rooftopsolutions.nl/)
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
  */
@@ -14,7 +14,7 @@ class Sabre_VObject_Version {
     /**
      * Full version number
      */
-    const VERSION = '1.2.4';
+    const VERSION = '1.3.2';
 
     /**
      * Stability : alpha, beta, stable
diff --git a/3rdparty/Sabre/VObject/WindowsTimezoneMap.php b/3rdparty/Sabre/VObject/WindowsTimezoneMap.php
new file mode 100644
index 0000000000000000000000000000000000000000..5e1cc5d479bf9e4f28a27bcd1f0911e5ffeaec1d
--- /dev/null
+++ b/3rdparty/Sabre/VObject/WindowsTimezoneMap.php
@@ -0,0 +1,128 @@
+<?php
+
+/**
+ * Time zone name translation
+ *
+ * This file translates well-known time zone names into "Olson database" time zone names.
+ *
+ * @package Sabre
+ * @subpackage VObject 
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
+ * @author Frank Edelhaeuser (fedel@users.sourceforge.net) 
+ * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
+ */
+class Sabre_VObject_WindowsTimezoneMap {
+
+    protected static $map = array(
+
+        // from http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/zone_tzid.html
+        // snapshot taken on 2012/01/16
+
+        // windows
+        'AUS Central Standard Time'=>'Australia/Darwin',
+        'AUS Eastern Standard Time'=>'Australia/Sydney',
+        'Afghanistan Standard Time'=>'Asia/Kabul',
+        'Alaskan Standard Time'=>'America/Anchorage',
+        'Arab Standard Time'=>'Asia/Riyadh',
+        'Arabian Standard Time'=>'Asia/Dubai',
+        'Arabic Standard Time'=>'Asia/Baghdad',
+        'Argentina Standard Time'=>'America/Buenos_Aires',
+        'Armenian Standard Time'=>'Asia/Yerevan',
+        'Atlantic Standard Time'=>'America/Halifax',
+        'Azerbaijan Standard Time'=>'Asia/Baku',
+        'Azores Standard Time'=>'Atlantic/Azores',
+        'Bangladesh Standard Time'=>'Asia/Dhaka',
+        'Canada Central Standard Time'=>'America/Regina',
+        'Cape Verde Standard Time'=>'Atlantic/Cape_Verde',
+        'Caucasus Standard Time'=>'Asia/Yerevan',
+        'Cen. Australia Standard Time'=>'Australia/Adelaide',
+        'Central America Standard Time'=>'America/Guatemala',
+        'Central Asia Standard Time'=>'Asia/Almaty',
+        'Central Brazilian Standard Time'=>'America/Cuiaba',
+        'Central Europe Standard Time'=>'Europe/Budapest',
+        'Central European Standard Time'=>'Europe/Warsaw',
+        'Central Pacific Standard Time'=>'Pacific/Guadalcanal',
+        'Central Standard Time'=>'America/Chicago',
+        'Central Standard Time (Mexico)'=>'America/Mexico_City',
+        'China Standard Time'=>'Asia/Shanghai',
+        'Dateline Standard Time'=>'Etc/GMT+12',
+        'E. Africa Standard Time'=>'Africa/Nairobi',
+        'E. Australia Standard Time'=>'Australia/Brisbane',
+        'E. Europe Standard Time'=>'Europe/Minsk',
+        'E. South America Standard Time'=>'America/Sao_Paulo',
+        'Eastern Standard Time'=>'America/New_York',
+        'Egypt Standard Time'=>'Africa/Cairo',
+        'Ekaterinburg Standard Time'=>'Asia/Yekaterinburg',
+        'FLE Standard Time'=>'Europe/Kiev',
+        'Fiji Standard Time'=>'Pacific/Fiji',
+        'GMT Standard Time'=>'Europe/London',
+        'GTB Standard Time'=>'Europe/Istanbul',
+        'Georgian Standard Time'=>'Asia/Tbilisi',
+        'Greenland Standard Time'=>'America/Godthab',
+        'Greenwich Standard Time'=>'Atlantic/Reykjavik',
+        'Hawaiian Standard Time'=>'Pacific/Honolulu',
+        'India Standard Time'=>'Asia/Calcutta',
+        'Iran Standard Time'=>'Asia/Tehran',
+        'Israel Standard Time'=>'Asia/Jerusalem',
+        'Jordan Standard Time'=>'Asia/Amman',
+        'Kamchatka Standard Time'=>'Asia/Kamchatka',
+        'Korea Standard Time'=>'Asia/Seoul',
+        'Magadan Standard Time'=>'Asia/Magadan',
+        'Mauritius Standard Time'=>'Indian/Mauritius',
+        'Mexico Standard Time'=>'America/Mexico_City',
+        'Mexico Standard Time 2'=>'America/Chihuahua',
+        'Mid-Atlantic Standard Time'=>'Etc/GMT+2',
+        'Middle East Standard Time'=>'Asia/Beirut',
+        'Montevideo Standard Time'=>'America/Montevideo',
+        'Morocco Standard Time'=>'Africa/Casablanca',
+        'Mountain Standard Time'=>'America/Denver',
+        'Mountain Standard Time (Mexico)'=>'America/Chihuahua',
+        'Myanmar Standard Time'=>'Asia/Rangoon',
+        'N. Central Asia Standard Time'=>'Asia/Novosibirsk',
+        'Namibia Standard Time'=>'Africa/Windhoek',
+        'Nepal Standard Time'=>'Asia/Katmandu',
+        'New Zealand Standard Time'=>'Pacific/Auckland',
+        'Newfoundland Standard Time'=>'America/St_Johns',
+        'North Asia East Standard Time'=>'Asia/Irkutsk',
+        'North Asia Standard Time'=>'Asia/Krasnoyarsk',
+        'Pacific SA Standard Time'=>'America/Santiago',
+        'Pacific Standard Time'=>'America/Los_Angeles',
+        'Pacific Standard Time (Mexico)'=>'America/Santa_Isabel',
+        'Pakistan Standard Time'=>'Asia/Karachi',
+        'Paraguay Standard Time'=>'America/Asuncion',
+        'Romance Standard Time'=>'Europe/Paris',
+        'Russian Standard Time'=>'Europe/Moscow',
+        'SA Eastern Standard Time'=>'America/Cayenne',
+        'SA Pacific Standard Time'=>'America/Bogota',
+        'SA Western Standard Time'=>'America/La_Paz',
+        'SE Asia Standard Time'=>'Asia/Bangkok',
+        'Samoa Standard Time'=>'Pacific/Apia',
+        'Singapore Standard Time'=>'Asia/Singapore',
+        'South Africa Standard Time'=>'Africa/Johannesburg',
+        'Sri Lanka Standard Time'=>'Asia/Colombo',
+        'Syria Standard Time'=>'Asia/Damascus',
+        'Taipei Standard Time'=>'Asia/Taipei',
+        'Tasmania Standard Time'=>'Australia/Hobart',
+        'Tokyo Standard Time'=>'Asia/Tokyo',
+        'Tonga Standard Time'=>'Pacific/Tongatapu',
+        'US Eastern Standard Time'=>'America/Indianapolis',
+        'US Mountain Standard Time'=>'America/Phoenix',
+        'UTC'=>'Etc/GMT',
+        'UTC+12'=>'Etc/GMT-12',
+        'UTC-02'=>'Etc/GMT+2',
+        'UTC-11'=>'Etc/GMT+11',
+        'Ulaanbaatar Standard Time'=>'Asia/Ulaanbaatar',
+        'Venezuela Standard Time'=>'America/Caracas',
+        'Vladivostok Standard Time'=>'Asia/Vladivostok',
+        'W. Australia Standard Time'=>'Australia/Perth',
+        'W. Central Africa Standard Time'=>'Africa/Lagos',
+        'W. Europe Standard Time'=>'Europe/Berlin',
+        'West Asia Standard Time'=>'Asia/Tashkent',
+        'West Pacific Standard Time'=>'Pacific/Port_Moresby',
+        'Yakutsk Standard Time'=>'Asia/Yakutsk',
+    );
+
+    static public function lookup($tzid) {
+        return isset(self::$map[$tzid]) ? self::$map[$tzid] : null;
+    }
+}
diff --git a/3rdparty/Sabre/VObject/includes.php b/3rdparty/Sabre/VObject/includes.php
index f21010fb275a84ea9a672e2c2dd6a26a184e37cb..0177a8f1ba69089c467da2f6dbe67a14c2914fa6 100644
--- a/3rdparty/Sabre/VObject/includes.php
+++ b/3rdparty/Sabre/VObject/includes.php
@@ -1,29 +1,41 @@
 <?php
 
 /**
- * VObject includes 
+ * Sabre_VObject includes file
  *
- * This file automatically includes all VObject classes 
+ * Including this file will automatically include all files from the VObject
+ * package.
+ *
+ * This often allows faster loadtimes, as autoload-speed is often quite slow.
  *
  * @package Sabre
  * @subpackage VObject
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
- * @author Evert Pot (http://www.rooftopsolutions.nl/) 
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
  */
 
-
-include dirname(__FILE__) . '/ParseException.php';
-
-include dirname(__FILE__) . '/Node.php';
-include dirname(__FILE__) . '/Element.php';
-include dirname(__FILE__) . '/ElementList.php';
-include dirname(__FILE__) . '/Parameter.php';
-include dirname(__FILE__) . '/Property.php';
-include dirname(__FILE__) . '/Component.php';
-
-include dirname(__FILE__) . '/Element/DateTime.php';
-include dirname(__FILE__) . '/Element/MultiDateTime.php';
-
-include dirname(__FILE__) . '/Reader.php';
-include dirname(__FILE__) . '/Version.php';
+// Begin includes
+include __DIR__ . '/DateTimeParser.php';
+include __DIR__ . '/ElementList.php';
+include __DIR__ . '/FreeBusyGenerator.php';
+include __DIR__ . '/Node.php';
+include __DIR__ . '/Parameter.php';
+include __DIR__ . '/ParseException.php';
+include __DIR__ . '/Reader.php';
+include __DIR__ . '/RecurrenceIterator.php';
+include __DIR__ . '/Version.php';
+include __DIR__ . '/WindowsTimezoneMap.php';
+include __DIR__ . '/Element.php';
+include __DIR__ . '/Property.php';
+include __DIR__ . '/Component.php';
+include __DIR__ . '/Property/DateTime.php';
+include __DIR__ . '/Property/MultiDateTime.php';
+include __DIR__ . '/Component/VAlarm.php';
+include __DIR__ . '/Component/VCalendar.php';
+include __DIR__ . '/Component/VEvent.php';
+include __DIR__ . '/Component/VJournal.php';
+include __DIR__ . '/Component/VTodo.php';
+include __DIR__ . '/Element/DateTime.php';
+include __DIR__ . '/Element/MultiDateTime.php';
+// End includes
diff --git a/3rdparty/Sabre/autoload.php b/3rdparty/Sabre/autoload.php
index 0649df655b028c91f6229fe475e04e0df7865faa..c7b537d83d34ef7b0ea97ceb1cda770560bd5a66 100644
--- a/3rdparty/Sabre/autoload.php
+++ b/3rdparty/Sabre/autoload.php
@@ -8,11 +8,15 @@
  *
  * @package Sabre
  * @subpackage DAV
- * @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
- * @author Evert Pot (http://www.rooftopsolutions.nl/) 
+ * @copyright Copyright (C) 2007-2012 Rooftop Solutions. All rights reserved.
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
  */
 
+/**
+ * @param string $className
+ * @return void
+ */
 function Sabre_autoload($className) {
 
     if(strpos($className,'Sabre_')===0) {
diff --git a/3rdparty/class.phpmailer.php b/3rdparty/class.phpmailer.php
new file mode 100644
index 0000000000000000000000000000000000000000..4589cd791e9c2244d6a9b39485c07c6aef7a9148
--- /dev/null
+++ b/3rdparty/class.phpmailer.php
@@ -0,0 +1,2473 @@
+<?php
+/*~ class.phpmailer.php
+.---------------------------------------------------------------------------.
+|  Software: PHPMailer - PHP email class                                    |
+|   Version: 5.2                                                            |
+|      Site: https://code.google.com/a/apache-extras.org/p/phpmailer/       |
+| ------------------------------------------------------------------------- |
+|     Admin: Jim Jagielski (project admininistrator)                        |
+|   Authors: Andy Prevost (codeworxtech) codeworxtech@users.sourceforge.net |
+|          : Marcus Bointon (coolbru) coolbru@users.sourceforge.net         |
+|          : Jim Jagielski (jimjag) jimjag@gmail.com                        |
+|   Founder: Brent R. Matzelle (original founder)                           |
+| Copyright (c) 2010-2011, Jim Jagielski. All Rights Reserved.               |
+| Copyright (c) 2004-2009, Andy Prevost. All Rights Reserved.               |
+| Copyright (c) 2001-2003, Brent R. Matzelle                                |
+| ------------------------------------------------------------------------- |
+|   License: Distributed under the Lesser General Public License (LGPL)     |
+|            http://www.gnu.org/copyleft/lesser.html                        |
+| This program is distributed in the hope that it will be useful - WITHOUT  |
+| ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or     |
+| FITNESS FOR A PARTICULAR PURPOSE.                                         |
+'---------------------------------------------------------------------------'
+*/
+
+/**
+ * PHPMailer - PHP email transport class
+ * NOTE: Requires PHP version 5 or later
+ * @package PHPMailer
+ * @author Andy Prevost
+ * @author Marcus Bointon
+ * @author Jim Jagielski
+ * @copyright 2010 - 2011 Jim Jagielski
+ * @copyright 2004 - 2009 Andy Prevost
+ * @version $Id: class.phpmailer.php 450 2010-06-23 16:46:33Z coolbru $
+ * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
+ */
+
+if (version_compare(PHP_VERSION, '5.0.0', '<') ) exit("Sorry, this version of PHPMailer will only run on PHP version 5 or greater!\n");
+
+class PHPMailer {
+
+  /////////////////////////////////////////////////
+  // PROPERTIES, PUBLIC
+  /////////////////////////////////////////////////
+
+  /**
+   * Email priority (1 = High, 3 = Normal, 5 = low).
+   * @var int
+   */
+  public $Priority          = 3;
+
+  /**
+   * Sets the CharSet of the message.
+   * @var string
+   */
+  public $CharSet           = 'iso-8859-1';
+
+  /**
+   * Sets the Content-type of the message.
+   * @var string
+   */
+  public $ContentType       = 'text/plain';
+
+  /**
+   * Sets the Encoding of the message. Options for this are
+   *  "8bit", "7bit", "binary", "base64", and "quoted-printable".
+   * @var string
+   */
+  public $Encoding          = '8bit';
+
+  /**
+   * Holds the most recent mailer error message.
+   * @var string
+   */
+  public $ErrorInfo         = '';
+
+  /**
+   * Sets the From email address for the message.
+   * @var string
+   */
+  public $From              = 'root@localhost';
+
+  /**
+   * Sets the From name of the message.
+   * @var string
+   */
+  public $FromName          = 'Root User';
+
+  /**
+   * Sets the Sender email (Return-Path) of the message.  If not empty,
+   * will be sent via -f to sendmail or as 'MAIL FROM' in smtp mode.
+   * @var string
+   */
+  public $Sender            = '';
+
+  /**
+   * Sets the Subject of the message.
+   * @var string
+   */
+  public $Subject           = '';
+
+  /**
+   * Sets the Body of the message.  This can be either an HTML or text body.
+   * If HTML then run IsHTML(true).
+   * @var string
+   */
+  public $Body              = '';
+
+  /**
+   * Sets the text-only body of the message.  This automatically sets the
+   * email to multipart/alternative.  This body can be read by mail
+   * clients that do not have HTML email capability such as mutt. Clients
+   * that can read HTML will view the normal Body.
+   * @var string
+   */
+  public $AltBody           = '';
+
+  /**
+   * Stores the complete compiled MIME message body.
+   * @var string
+   * @access protected
+   */
+  protected $MIMEBody       = '';
+
+  /**
+   * Stores the complete compiled MIME message headers.
+   * @var string
+   * @access protected
+   */
+  protected $MIMEHeader     = '';
+
+  /**
+   * Sets word wrapping on the body of the message to a given number of
+   * characters.
+   * @var int
+   */
+  public $WordWrap          = 0;
+
+  /**
+   * Method to send mail: ("mail", "sendmail", or "smtp").
+   * @var string
+   */
+  public $Mailer            = 'mail';
+
+  /**
+   * Sets the path of the sendmail program.
+   * @var string
+   */
+  public $Sendmail          = '/usr/sbin/sendmail';
+
+  /**
+   * Path to PHPMailer plugins.  Useful if the SMTP class
+   * is in a different directory than the PHP include path.
+   * @var string
+   */
+  public $PluginDir         = '';
+
+  /**
+   * Sets the email address that a reading confirmation will be sent.
+   * @var string
+   */
+  public $ConfirmReadingTo  = '';
+
+  /**
+   * Sets the hostname to use in Message-Id and Received headers
+   * and as default HELO string. If empty, the value returned
+   * by SERVER_NAME is used or 'localhost.localdomain'.
+   * @var string
+   */
+  public $Hostname          = '';
+
+  /**
+   * Sets the message ID to be used in the Message-Id header.
+   * If empty, a unique id will be generated.
+   * @var string
+   */
+  public $MessageID         = '';
+
+  /////////////////////////////////////////////////
+  // PROPERTIES FOR SMTP
+  /////////////////////////////////////////////////
+
+  /**
+   * Sets the SMTP hosts.  All hosts must be separated by a
+   * semicolon.  You can also specify a different port
+   * for each host by using this format: [hostname:port]
+   * (e.g. "smtp1.example.com:25;smtp2.example.com").
+   * Hosts will be tried in order.
+   * @var string
+   */
+  public $Host          = 'localhost';
+
+  /**
+   * Sets the default SMTP server port.
+   * @var int
+   */
+  public $Port          = 25;
+
+  /**
+   * Sets the SMTP HELO of the message (Default is $Hostname).
+   * @var string
+   */
+  public $Helo          = '';
+
+  /**
+   * Sets connection prefix.
+   * Options are "", "ssl" or "tls"
+   * @var string
+   */
+  public $SMTPSecure    = '';
+
+  /**
+   * Sets SMTP authentication. Utilizes the Username and Password variables.
+   * @var bool
+   */
+  public $SMTPAuth      = false;
+
+  /**
+   * Sets SMTP username.
+   * @var string
+   */
+  public $Username      = '';
+
+  /**
+   * Sets SMTP password.
+   * @var string
+   */
+  public $Password      = '';
+
+  /**
+   * Sets the SMTP server timeout in seconds.
+   * This function will not work with the win32 version.
+   * @var int
+   */
+  public $Timeout       = 10;
+
+  /**
+   * Sets SMTP class debugging on or off.
+   * @var bool
+   */
+  public $SMTPDebug     = false;
+
+  /**
+   * Prevents the SMTP connection from being closed after each mail
+   * sending.  If this is set to true then to close the connection
+   * requires an explicit call to SmtpClose().
+   * @var bool
+   */
+  public $SMTPKeepAlive = false;
+
+  /**
+   * Provides the ability to have the TO field process individual
+   * emails, instead of sending to entire TO addresses
+   * @var bool
+   */
+  public $SingleTo      = false;
+
+   /**
+   * If SingleTo is true, this provides the array to hold the email addresses
+   * @var bool
+   */
+  public $SingleToArray = array();
+
+ /**
+   * Provides the ability to change the line ending
+   * @var string
+   */
+  public $LE              = "\n";
+
+  /**
+   * Used with DKIM DNS Resource Record
+   * @var string
+   */
+  public $DKIM_selector   = 'phpmailer';
+
+  /**
+   * Used with DKIM DNS Resource Record
+   * optional, in format of email address 'you@yourdomain.com'
+   * @var string
+   */
+  public $DKIM_identity   = '';
+
+  /**
+   * Used with DKIM DNS Resource Record
+   * @var string
+   */
+  public $DKIM_passphrase   = '';
+
+  /**
+   * Used with DKIM DNS Resource Record
+   * optional, in format of email address 'you@yourdomain.com'
+   * @var string
+   */
+  public $DKIM_domain     = '';
+
+  /**
+   * Used with DKIM DNS Resource Record
+   * optional, in format of email address 'you@yourdomain.com'
+   * @var string
+   */
+  public $DKIM_private    = '';
+
+  /**
+   * Callback Action function name
+   * the function that handles the result of the send email action. Parameters:
+   *   bool    $result        result of the send action
+   *   string  $to            email address of the recipient
+   *   string  $cc            cc email addresses
+   *   string  $bcc           bcc email addresses
+   *   string  $subject       the subject
+   *   string  $body          the email body
+   * @var string
+   */
+  public $action_function = ''; //'callbackAction';
+
+  /**
+   * Sets the PHPMailer Version number
+   * @var string
+   */
+  public $Version         = '5.2';
+
+  /**
+   * What to use in the X-Mailer header
+   * @var string
+   */
+  public $XMailer         = '';
+
+  /////////////////////////////////////////////////
+  // PROPERTIES, PRIVATE AND PROTECTED
+  /////////////////////////////////////////////////
+
+  protected   $smtp           = NULL;
+  protected   $to             = array();
+  protected   $cc             = array();
+  protected   $bcc            = array();
+  protected   $ReplyTo        = array();
+  protected   $all_recipients = array();
+  protected   $attachment     = array();
+  protected   $CustomHeader   = array();
+  protected   $message_type   = '';
+  protected   $boundary       = array();
+  protected   $language       = array();
+  protected   $error_count    = 0;
+  protected   $sign_cert_file = '';
+  protected   $sign_key_file  = '';
+  protected   $sign_key_pass  = '';
+  protected   $exceptions     = false;
+
+  /////////////////////////////////////////////////
+  // CONSTANTS
+  /////////////////////////////////////////////////
+
+  const STOP_MESSAGE  = 0; // message only, continue processing
+  const STOP_CONTINUE = 1; // message?, likely ok to continue processing
+  const STOP_CRITICAL = 2; // message, plus full stop, critical error reached
+
+  /////////////////////////////////////////////////
+  // METHODS, VARIABLES
+  /////////////////////////////////////////////////
+
+  /**
+   * Constructor
+   * @param boolean $exceptions Should we throw external exceptions?
+   */
+  public function __construct($exceptions = false) {
+    $this->exceptions = ($exceptions == true);
+  }
+
+  /**
+   * Sets message type to HTML.
+   * @param bool $ishtml
+   * @return void
+   */
+  public function IsHTML($ishtml = true) {
+    if ($ishtml) {
+      $this->ContentType = 'text/html';
+    } else {
+      $this->ContentType = 'text/plain';
+    }
+  }
+
+  /**
+   * Sets Mailer to send message using SMTP.
+   * @return void
+   */
+  public function IsSMTP() {
+    $this->Mailer = 'smtp';
+  }
+
+  /**
+   * Sets Mailer to send message using PHP mail() function.
+   * @return void
+   */
+  public function IsMail() {
+    $this->Mailer = 'mail';
+  }
+
+  /**
+   * Sets Mailer to send message using the $Sendmail program.
+   * @return void
+   */
+  public function IsSendmail() {
+    if (!stristr(ini_get('sendmail_path'), 'sendmail')) {
+      $this->Sendmail = '/var/qmail/bin/sendmail';
+    }
+    $this->Mailer = 'sendmail';
+  }
+
+  /**
+   * Sets Mailer to send message using the qmail MTA.
+   * @return void
+   */
+  public function IsQmail() {
+    if (stristr(ini_get('sendmail_path'), 'qmail')) {
+      $this->Sendmail = '/var/qmail/bin/sendmail';
+    }
+    $this->Mailer = 'sendmail';
+  }
+
+  /////////////////////////////////////////////////
+  // METHODS, RECIPIENTS
+  /////////////////////////////////////////////////
+
+  /**
+   * Adds a "To" address.
+   * @param string $address
+   * @param string $name
+   * @return boolean true on success, false if address already used
+   */
+  public function AddAddress($address, $name = '') {
+    return $this->AddAnAddress('to', $address, $name);
+  }
+
+  /**
+   * Adds a "Cc" address.
+   * Note: this function works with the SMTP mailer on win32, not with the "mail" mailer.
+   * @param string $address
+   * @param string $name
+   * @return boolean true on success, false if address already used
+   */
+  public function AddCC($address, $name = '') {
+    return $this->AddAnAddress('cc', $address, $name);
+  }
+
+  /**
+   * Adds a "Bcc" address.
+   * Note: this function works with the SMTP mailer on win32, not with the "mail" mailer.
+   * @param string $address
+   * @param string $name
+   * @return boolean true on success, false if address already used
+   */
+  public function AddBCC($address, $name = '') {
+    return $this->AddAnAddress('bcc', $address, $name);
+  }
+
+  /**
+   * Adds a "Reply-to" address.
+   * @param string $address
+   * @param string $name
+   * @return boolean
+   */
+  public function AddReplyTo($address, $name = '') {
+    return $this->AddAnAddress('ReplyTo', $address, $name);
+  }
+
+  /**
+   * Adds an address to one of the recipient arrays
+   * Addresses that have been added already return false, but do not throw exceptions
+   * @param string $kind One of 'to', 'cc', 'bcc', 'ReplyTo'
+   * @param string $address The email address to send to
+   * @param string $name
+   * @return boolean true on success, false if address already used or invalid in some way
+   * @access protected
+   */
+  protected function AddAnAddress($kind, $address, $name = '') {
+    if (!preg_match('/^(to|cc|bcc|ReplyTo)$/', $kind)) {
+      $this->SetError($this->Lang('Invalid recipient array').': '.$kind);
+      if ($this->exceptions) {
+        throw new phpmailerException('Invalid recipient array: ' . $kind);
+      }
+      echo $this->Lang('Invalid recipient array').': '.$kind;
+      return false;
+    }
+    $address = trim($address);
+    $name = trim(preg_replace('/[\r\n]+/', '', $name)); //Strip breaks and trim
+    if (!self::ValidateAddress($address)) {
+      $this->SetError($this->Lang('invalid_address').': '. $address);
+      if ($this->exceptions) {
+        throw new phpmailerException($this->Lang('invalid_address').': '.$address);
+      }
+      echo $this->Lang('invalid_address').': '.$address;
+      return false;
+    }
+    if ($kind != 'ReplyTo') {
+      if (!isset($this->all_recipients[strtolower($address)])) {
+        array_push($this->$kind, array($address, $name));
+        $this->all_recipients[strtolower($address)] = true;
+        return true;
+      }
+    } else {
+      if (!array_key_exists(strtolower($address), $this->ReplyTo)) {
+        $this->ReplyTo[strtolower($address)] = array($address, $name);
+      return true;
+    }
+  }
+  return false;
+}
+
+/**
+ * Set the From and FromName properties
+ * @param string $address
+ * @param string $name
+ * @return boolean
+ */
+  public function SetFrom($address, $name = '', $auto = 1) {
+    $address = trim($address);
+    $name = trim(preg_replace('/[\r\n]+/', '', $name)); //Strip breaks and trim
+    if (!self::ValidateAddress($address)) {
+      $this->SetError($this->Lang('invalid_address').': '. $address);
+      if ($this->exceptions) {
+        throw new phpmailerException($this->Lang('invalid_address').': '.$address);
+      }
+      echo $this->Lang('invalid_address').': '.$address;
+      return false;
+    }
+    $this->From = $address;
+    $this->FromName = $name;
+    if ($auto) {
+      if (empty($this->ReplyTo)) {
+        $this->AddAnAddress('ReplyTo', $address, $name);
+      }
+      if (empty($this->Sender)) {
+        $this->Sender = $address;
+      }
+    }
+    return true;
+  }
+
+  /**
+   * Check that a string looks roughly like an email address should
+   * Static so it can be used without instantiation
+   * Tries to use PHP built-in validator in the filter extension (from PHP 5.2), falls back to a reasonably competent regex validator
+   * Conforms approximately to RFC2822
+   * @link http://www.hexillion.com/samples/#Regex Original pattern found here
+   * @param string $address The email address to check
+   * @return boolean
+   * @static
+   * @access public
+   */
+  public static function ValidateAddress($address) {
+    if (function_exists('filter_var')) { //Introduced in PHP 5.2
+      if(filter_var($address, FILTER_VALIDATE_EMAIL) === FALSE) {
+        return false;
+      } else {
+        return true;
+      }
+    } else {
+      return preg_match('/^(?:[\w\!\#\$\%\&\'\*\+\-\/\=\?\^\`\{\|\}\~]+\.)*[\w\!\#\$\%\&\'\*\+\-\/\=\?\^\`\{\|\}\~]+@(?:(?:(?:[a-zA-Z0-9_](?:[a-zA-Z0-9_\-](?!\.)){0,61}[a-zA-Z0-9_-]?\.)+[a-zA-Z0-9_](?:[a-zA-Z0-9_\-](?!$)){0,61}[a-zA-Z0-9_]?)|(?:\[(?:(?:[01]?\d{1,2}|2[0-4]\d|25[0-5])\.){3}(?:[01]?\d{1,2}|2[0-4]\d|25[0-5])\]))$/', $address);
+    }
+  }
+
+  /////////////////////////////////////////////////
+  // METHODS, MAIL SENDING
+  /////////////////////////////////////////////////
+
+  /**
+   * Creates message and assigns Mailer. If the message is
+   * not sent successfully then it returns false.  Use the ErrorInfo
+   * variable to view description of the error.
+   * @return bool
+   */
+  public function Send() {
+    try {
+      if(!$this->PreSend()) return false;
+      return $this->PostSend();
+    } catch (phpmailerException $e) {
+      $this->SetError($e->getMessage());
+      if ($this->exceptions) {
+        throw $e;
+      }
+      return false;
+    }
+  }
+
+  protected function PreSend() {
+    try {
+      if ((count($this->to) + count($this->cc) + count($this->bcc)) < 1) {
+        throw new phpmailerException($this->Lang('provide_address'), self::STOP_CRITICAL);
+      }
+
+      // Set whether the message is multipart/alternative
+      if(!empty($this->AltBody)) {
+        $this->ContentType = 'multipart/alternative';
+      }
+
+      $this->error_count = 0; // reset errors
+      $this->SetMessageType();
+      //Refuse to send an empty message
+      if (empty($this->Body)) {
+        throw new phpmailerException($this->Lang('empty_message'), self::STOP_CRITICAL);
+      }
+
+      $this->MIMEHeader = $this->CreateHeader();
+      $this->MIMEBody = $this->CreateBody();
+
+
+      // digitally sign with DKIM if enabled
+      if ($this->DKIM_domain && $this->DKIM_private) {
+        $header_dkim = $this->DKIM_Add($this->MIMEHeader, $this->EncodeHeader($this->SecureHeader($this->Subject)), $this->MIMEBody);
+        $this->MIMEHeader = str_replace("\r\n", "\n", $header_dkim) . $this->MIMEHeader;
+      }
+
+      return true;
+    } catch (phpmailerException $e) {
+      $this->SetError($e->getMessage());
+      if ($this->exceptions) {
+        throw $e;
+      }
+      return false;
+    }
+  }
+
+  protected function PostSend() {
+    try {
+      // Choose the mailer and send through it
+      switch($this->Mailer) {
+        case 'sendmail':
+          return $this->SendmailSend($this->MIMEHeader, $this->MIMEBody);
+        case 'smtp':
+          return $this->SmtpSend($this->MIMEHeader, $this->MIMEBody);
+        default:
+          return $this->MailSend($this->MIMEHeader, $this->MIMEBody);
+      }
+
+    } catch (phpmailerException $e) {
+      $this->SetError($e->getMessage());
+      if ($this->exceptions) {
+        throw $e;
+      }
+      echo $e->getMessage()."\n";
+      return false;
+    }
+  }
+
+  /**
+   * Sends mail using the $Sendmail program.
+   * @param string $header The message headers
+   * @param string $body The message body
+   * @access protected
+   * @return bool
+   */
+  protected function SendmailSend($header, $body) {
+    if ($this->Sender != '') {
+      $sendmail = sprintf("%s -oi -f %s -t", escapeshellcmd($this->Sendmail), escapeshellarg($this->Sender));
+    } else {
+      $sendmail = sprintf("%s -oi -t", escapeshellcmd($this->Sendmail));
+    }
+    if ($this->SingleTo === true) {
+      foreach ($this->SingleToArray as $key => $val) {
+        if(!@$mail = popen($sendmail, 'w')) {
+          throw new phpmailerException($this->Lang('execute') . $this->Sendmail, self::STOP_CRITICAL);
+        }
+        fputs($mail, "To: " . $val . "\n");
+        fputs($mail, $header);
+        fputs($mail, $body);
+        $result = pclose($mail);
+        // implement call back function if it exists
+        $isSent = ($result == 0) ? 1 : 0;
+        $this->doCallback($isSent, $val, $this->cc, $this->bcc, $this->Subject, $body);
+        if($result != 0) {
+          throw new phpmailerException($this->Lang('execute') . $this->Sendmail, self::STOP_CRITICAL);
+        }
+      }
+    } else {
+      if(!@$mail = popen($sendmail, 'w')) {
+        throw new phpmailerException($this->Lang('execute') . $this->Sendmail, self::STOP_CRITICAL);
+      }
+      fputs($mail, $header);
+      fputs($mail, $body);
+      $result = pclose($mail);
+      // implement call back function if it exists
+      $isSent = ($result == 0) ? 1 : 0;
+      $this->doCallback($isSent, $this->to, $this->cc, $this->bcc, $this->Subject, $body);
+      if($result != 0) {
+        throw new phpmailerException($this->Lang('execute') . $this->Sendmail, self::STOP_CRITICAL);
+      }
+    }
+    return true;
+  }
+
+  /**
+   * Sends mail using the PHP mail() function.
+   * @param string $header The message headers
+   * @param string $body The message body
+   * @access protected
+   * @return bool
+   */
+  protected function MailSend($header, $body) {
+    $toArr = array();
+    foreach($this->to as $t) {
+      $toArr[] = $this->AddrFormat($t);
+    }
+    $to = implode(', ', $toArr);
+
+    if (empty($this->Sender)) {
+      $params = "-oi -f %s";
+    } else {
+      $params = sprintf("-oi -f %s", $this->Sender);
+    }
+    if ($this->Sender != '' and !ini_get('safe_mode')) {
+      $old_from = ini_get('sendmail_from');
+      ini_set('sendmail_from', $this->Sender);
+      if ($this->SingleTo === true && count($toArr) > 1) {
+        foreach ($toArr as $key => $val) {
+          $rt = @mail($val, $this->EncodeHeader($this->SecureHeader($this->Subject)), $body, $header, $params);
+          // implement call back function if it exists
+          $isSent = ($rt == 1) ? 1 : 0;
+          $this->doCallback($isSent, $val, $this->cc, $this->bcc, $this->Subject, $body);
+        }
+      } else {
+        $rt = @mail($to, $this->EncodeHeader($this->SecureHeader($this->Subject)), $body, $header, $params);
+        // implement call back function if it exists
+        $isSent = ($rt == 1) ? 1 : 0;
+        $this->doCallback($isSent, $to, $this->cc, $this->bcc, $this->Subject, $body);
+      }
+    } else {
+      if ($this->SingleTo === true && count($toArr) > 1) {
+        foreach ($toArr as $key => $val) {
+          $rt = @mail($val, $this->EncodeHeader($this->SecureHeader($this->Subject)), $body, $header, $params);
+          // implement call back function if it exists
+          $isSent = ($rt == 1) ? 1 : 0;
+          $this->doCallback($isSent, $val, $this->cc, $this->bcc, $this->Subject, $body);
+        }
+      } else {
+        $rt = @mail($to, $this->EncodeHeader($this->SecureHeader($this->Subject)), $body, $header);
+        // implement call back function if it exists
+        $isSent = ($rt == 1) ? 1 : 0;
+        $this->doCallback($isSent, $to, $this->cc, $this->bcc, $this->Subject, $body);
+      }
+    }
+    if (isset($old_from)) {
+      ini_set('sendmail_from', $old_from);
+    }
+    if(!$rt) {
+      throw new phpmailerException($this->Lang('instantiate'), self::STOP_CRITICAL);
+    }
+    return true;
+  }
+
+  /**
+   * Sends mail via SMTP using PhpSMTP
+   * Returns false if there is a bad MAIL FROM, RCPT, or DATA input.
+   * @param string $header The message headers
+   * @param string $body The message body
+   * @uses SMTP
+   * @access protected
+   * @return bool
+   */
+  protected function SmtpSend($header, $body) {
+    require_once $this->PluginDir . 'class.smtp.php';
+    $bad_rcpt = array();
+
+    if(!$this->SmtpConnect()) {
+      throw new phpmailerException($this->Lang('smtp_connect_failed'), self::STOP_CRITICAL);
+    }
+    $smtp_from = ($this->Sender == '') ? $this->From : $this->Sender;
+    if(!$this->smtp->Mail($smtp_from)) {
+      throw new phpmailerException($this->Lang('from_failed') . $smtp_from, self::STOP_CRITICAL);
+    }
+
+    // Attempt to send attach all recipients
+    foreach($this->to as $to) {
+      if (!$this->smtp->Recipient($to[0])) {
+        $bad_rcpt[] = $to[0];
+        // implement call back function if it exists
+        $isSent = 0;
+        $this->doCallback($isSent, $to[0], '', '', $this->Subject, $body);
+      } else {
+        // implement call back function if it exists
+        $isSent = 1;
+        $this->doCallback($isSent, $to[0], '', '', $this->Subject, $body);
+      }
+    }
+    foreach($this->cc as $cc) {
+      if (!$this->smtp->Recipient($cc[0])) {
+        $bad_rcpt[] = $cc[0];
+        // implement call back function if it exists
+        $isSent = 0;
+        $this->doCallback($isSent, '', $cc[0], '', $this->Subject, $body);
+      } else {
+        // implement call back function if it exists
+        $isSent = 1;
+        $this->doCallback($isSent, '', $cc[0], '', $this->Subject, $body);
+      }
+    }
+    foreach($this->bcc as $bcc) {
+      if (!$this->smtp->Recipient($bcc[0])) {
+        $bad_rcpt[] = $bcc[0];
+        // implement call back function if it exists
+        $isSent = 0;
+        $this->doCallback($isSent, '', '', $bcc[0], $this->Subject, $body);
+      } else {
+        // implement call back function if it exists
+        $isSent = 1;
+        $this->doCallback($isSent, '', '', $bcc[0], $this->Subject, $body);
+      }
+    }
+
+
+    if (count($bad_rcpt) > 0 ) { //Create error message for any bad addresses
+      $badaddresses = implode(', ', $bad_rcpt);
+      throw new phpmailerException($this->Lang('recipients_failed') . $badaddresses);
+    }
+    if(!$this->smtp->Data($header . $body)) {
+      throw new phpmailerException($this->Lang('data_not_accepted'), self::STOP_CRITICAL);
+    }
+    if($this->SMTPKeepAlive == true) {
+      $this->smtp->Reset();
+    }
+    return true;
+  }
+
+  /**
+   * Initiates a connection to an SMTP server.
+   * Returns false if the operation failed.
+   * @uses SMTP
+   * @access public
+   * @return bool
+   */
+  public function SmtpConnect() {
+    if(is_null($this->smtp)) {
+      $this->smtp = new SMTP();
+    }
+
+    $this->smtp->do_debug = $this->SMTPDebug;
+    $hosts = explode(';', $this->Host);
+    $index = 0;
+    $connection = $this->smtp->Connected();
+
+    // Retry while there is no connection
+    try {
+      while($index < count($hosts) && !$connection) {
+        $hostinfo = array();
+        if (preg_match('/^(.+):([0-9]+)$/', $hosts[$index], $hostinfo)) {
+          $host = $hostinfo[1];
+          $port = $hostinfo[2];
+        } else {
+          $host = $hosts[$index];
+          $port = $this->Port;
+        }
+
+        $tls = ($this->SMTPSecure == 'tls');
+        $ssl = ($this->SMTPSecure == 'ssl');
+
+        if ($this->smtp->Connect(($ssl ? 'ssl://':'').$host, $port, $this->Timeout)) {
+
+          $hello = ($this->Helo != '' ? $this->Helo : $this->ServerHostname());
+          $this->smtp->Hello($hello);
+
+          if ($tls) {
+            if (!$this->smtp->StartTLS()) {
+              throw new phpmailerException($this->Lang('tls'));
+            }
+
+            //We must resend HELO after tls negotiation
+            $this->smtp->Hello($hello);
+          }
+
+          $connection = true;
+          if ($this->SMTPAuth) {
+            if (!$this->smtp->Authenticate($this->Username, $this->Password)) {
+              throw new phpmailerException($this->Lang('authenticate'));
+            }
+          }
+        }
+        $index++;
+        if (!$connection) {
+          throw new phpmailerException($this->Lang('connect_host'));
+        }
+      }
+    } catch (phpmailerException $e) {
+      $this->smtp->Reset();
+      throw $e;
+    }
+    return true;
+  }
+
+  /**
+   * Closes the active SMTP session if one exists.
+   * @return void
+   */
+  public function SmtpClose() {
+    if(!is_null($this->smtp)) {
+      if($this->smtp->Connected()) {
+        $this->smtp->Quit();
+        $this->smtp->Close();
+      }
+    }
+  }
+
+  /**
+  * Sets the language for all class error messages.
+  * Returns false if it cannot load the language file.  The default language is English.
+  * @param string $langcode ISO 639-1 2-character language code (e.g. Portuguese: "br")
+  * @param string $lang_path Path to the language file directory
+  * @access public
+  */
+  function SetLanguage($langcode = 'en', $lang_path = 'language/') {
+    //Define full set of translatable strings
+    $PHPMAILER_LANG = array(
+      'provide_address' => 'You must provide at least one recipient email address.',
+      'mailer_not_supported' => ' mailer is not supported.',
+      'execute' => 'Could not execute: ',
+      'instantiate' => 'Could not instantiate mail function.',
+      'authenticate' => 'SMTP Error: Could not authenticate.',
+      'from_failed' => 'The following From address failed: ',
+      'recipients_failed' => 'SMTP Error: The following recipients failed: ',
+      'data_not_accepted' => 'SMTP Error: Data not accepted.',
+      'connect_host' => 'SMTP Error: Could not connect to SMTP host.',
+      'file_access' => 'Could not access file: ',
+      'file_open' => 'File Error: Could not open file: ',
+      'encoding' => 'Unknown encoding: ',
+      'signing' => 'Signing Error: ',
+      'smtp_error' => 'SMTP server error: ',
+      'empty_message' => 'Message body empty',
+      'invalid_address' => 'Invalid address',
+      'variable_set' => 'Cannot set or reset variable: '
+    );
+    //Overwrite language-specific strings. This way we'll never have missing translations - no more "language string failed to load"!
+    $l = true;
+    if ($langcode != 'en') { //There is no English translation file
+      $l = @include $lang_path.'phpmailer.lang-'.$langcode.'.php';
+    }
+    $this->language = $PHPMAILER_LANG;
+    return ($l == true); //Returns false if language not found
+  }
+
+  /**
+  * Return the current array of language strings
+  * @return array
+  */
+  public function GetTranslations() {
+    return $this->language;
+  }
+
+  /////////////////////////////////////////////////
+  // METHODS, MESSAGE CREATION
+  /////////////////////////////////////////////////
+
+  /**
+   * Creates recipient headers.
+   * @access public
+   * @return string
+   */
+  public function AddrAppend($type, $addr) {
+    $addr_str = $type . ': ';
+    $addresses = array();
+    foreach ($addr as $a) {
+      $addresses[] = $this->AddrFormat($a);
+    }
+    $addr_str .= implode(', ', $addresses);
+    $addr_str .= $this->LE;
+
+    return $addr_str;
+  }
+
+  /**
+   * Formats an address correctly.
+   * @access public
+   * @return string
+   */
+  public function AddrFormat($addr) {
+    if (empty($addr[1])) {
+      return $this->SecureHeader($addr[0]);
+    } else {
+      return $this->EncodeHeader($this->SecureHeader($addr[1]), 'phrase') . " <" . $this->SecureHeader($addr[0]) . ">";
+    }
+  }
+
+  /**
+   * Wraps message for use with mailers that do not
+   * automatically perform wrapping and for quoted-printable.
+   * Original written by philippe.
+   * @param string $message The message to wrap
+   * @param integer $length The line length to wrap to
+   * @param boolean $qp_mode Whether to run in Quoted-Printable mode
+   * @access public
+   * @return string
+   */
+  public function WrapText($message, $length, $qp_mode = false) {
+    $soft_break = ($qp_mode) ? sprintf(" =%s", $this->LE) : $this->LE;
+    // If utf-8 encoding is used, we will need to make sure we don't
+    // split multibyte characters when we wrap
+    $is_utf8 = (strtolower($this->CharSet) == "utf-8");
+
+    $message = $this->FixEOL($message);
+    if (substr($message, -1) == $this->LE) {
+      $message = substr($message, 0, -1);
+    }
+
+    $line = explode($this->LE, $message);
+    $message = '';
+    for ($i = 0 ;$i < count($line); $i++) {
+      $line_part = explode(' ', $line[$i]);
+      $buf = '';
+      for ($e = 0; $e<count($line_part); $e++) {
+        $word = $line_part[$e];
+        if ($qp_mode and (strlen($word) > $length)) {
+          $space_left = $length - strlen($buf) - 1;
+          if ($e != 0) {
+            if ($space_left > 20) {
+              $len = $space_left;
+              if ($is_utf8) {
+                $len = $this->UTF8CharBoundary($word, $len);
+              } elseif (substr($word, $len - 1, 1) == "=") {
+                $len--;
+              } elseif (substr($word, $len - 2, 1) == "=") {
+                $len -= 2;
+              }
+              $part = substr($word, 0, $len);
+              $word = substr($word, $len);
+              $buf .= ' ' . $part;
+              $message .= $buf . sprintf("=%s", $this->LE);
+            } else {
+              $message .= $buf . $soft_break;
+            }
+            $buf = '';
+          }
+          while (strlen($word) > 0) {
+            $len = $length;
+            if ($is_utf8) {
+              $len = $this->UTF8CharBoundary($word, $len);
+            } elseif (substr($word, $len - 1, 1) == "=") {
+              $len--;
+            } elseif (substr($word, $len - 2, 1) == "=") {
+              $len -= 2;
+            }
+            $part = substr($word, 0, $len);
+            $word = substr($word, $len);
+
+            if (strlen($word) > 0) {
+              $message .= $part . sprintf("=%s", $this->LE);
+            } else {
+              $buf = $part;
+            }
+          }
+        } else {
+          $buf_o = $buf;
+          $buf .= ($e == 0) ? $word : (' ' . $word);
+
+          if (strlen($buf) > $length and $buf_o != '') {
+            $message .= $buf_o . $soft_break;
+            $buf = $word;
+          }
+        }
+      }
+      $message .= $buf . $this->LE;
+    }
+
+    return $message;
+  }
+
+  /**
+   * Finds last character boundary prior to maxLength in a utf-8
+   * quoted (printable) encoded string.
+   * Original written by Colin Brown.
+   * @access public
+   * @param string $encodedText utf-8 QP text
+   * @param int    $maxLength   find last character boundary prior to this length
+   * @return int
+   */
+  public function UTF8CharBoundary($encodedText, $maxLength) {
+    $foundSplitPos = false;
+    $lookBack = 3;
+    while (!$foundSplitPos) {
+      $lastChunk = substr($encodedText, $maxLength - $lookBack, $lookBack);
+      $encodedCharPos = strpos($lastChunk, "=");
+      if ($encodedCharPos !== false) {
+        // Found start of encoded character byte within $lookBack block.
+        // Check the encoded byte value (the 2 chars after the '=')
+        $hex = substr($encodedText, $maxLength - $lookBack + $encodedCharPos + 1, 2);
+        $dec = hexdec($hex);
+        if ($dec < 128) { // Single byte character.
+          // If the encoded char was found at pos 0, it will fit
+          // otherwise reduce maxLength to start of the encoded char
+          $maxLength = ($encodedCharPos == 0) ? $maxLength :
+          $maxLength - ($lookBack - $encodedCharPos);
+          $foundSplitPos = true;
+        } elseif ($dec >= 192) { // First byte of a multi byte character
+          // Reduce maxLength to split at start of character
+          $maxLength = $maxLength - ($lookBack - $encodedCharPos);
+          $foundSplitPos = true;
+        } elseif ($dec < 192) { // Middle byte of a multi byte character, look further back
+          $lookBack += 3;
+        }
+      } else {
+        // No encoded character found
+        $foundSplitPos = true;
+      }
+    }
+    return $maxLength;
+  }
+
+
+  /**
+   * Set the body wrapping.
+   * @access public
+   * @return void
+   */
+  public function SetWordWrap() {
+    if($this->WordWrap < 1) {
+      return;
+    }
+
+    switch($this->message_type) {
+      case 'alt':
+      case 'alt_inline':
+      case 'alt_attach':
+      case 'alt_inline_attach':
+        $this->AltBody = $this->WrapText($this->AltBody, $this->WordWrap);
+        break;
+      default:
+        $this->Body = $this->WrapText($this->Body, $this->WordWrap);
+        break;
+    }
+  }
+
+  /**
+   * Assembles message header.
+   * @access public
+   * @return string The assembled header
+   */
+  public function CreateHeader() {
+    $result = '';
+
+    // Set the boundaries
+    $uniq_id = md5(uniqid(time()));
+    $this->boundary[1] = 'b1_' . $uniq_id;
+    $this->boundary[2] = 'b2_' . $uniq_id;
+    $this->boundary[3] = 'b3_' . $uniq_id;
+
+    $result .= $this->HeaderLine('Date', self::RFCDate());
+    if($this->Sender == '') {
+      $result .= $this->HeaderLine('Return-Path', trim($this->From));
+    } else {
+      $result .= $this->HeaderLine('Return-Path', trim($this->Sender));
+    }
+
+    // To be created automatically by mail()
+    if($this->Mailer != 'mail') {
+      if ($this->SingleTo === true) {
+        foreach($this->to as $t) {
+          $this->SingleToArray[] = $this->AddrFormat($t);
+        }
+      } else {
+        if(count($this->to) > 0) {
+          $result .= $this->AddrAppend('To', $this->to);
+        } elseif (count($this->cc) == 0) {
+          $result .= $this->HeaderLine('To', 'undisclosed-recipients:;');
+        }
+      }
+    }
+
+    $from = array();
+    $from[0][0] = trim($this->From);
+    $from[0][1] = $this->FromName;
+    $result .= $this->AddrAppend('From', $from);
+
+    // sendmail and mail() extract Cc from the header before sending
+    if(count($this->cc) > 0) {
+      $result .= $this->AddrAppend('Cc', $this->cc);
+    }
+
+    // sendmail and mail() extract Bcc from the header before sending
+    if((($this->Mailer == 'sendmail') || ($this->Mailer == 'mail')) && (count($this->bcc) > 0)) {
+      $result .= $this->AddrAppend('Bcc', $this->bcc);
+    }
+
+    if(count($this->ReplyTo) > 0) {
+      $result .= $this->AddrAppend('Reply-to', $this->ReplyTo);
+    }
+
+    // mail() sets the subject itself
+    if($this->Mailer != 'mail') {
+      $result .= $this->HeaderLine('Subject', $this->EncodeHeader($this->SecureHeader($this->Subject)));
+    }
+
+    if($this->MessageID != '') {
+      $result .= $this->HeaderLine('Message-ID', $this->MessageID);
+    } else {
+      $result .= sprintf("Message-ID: <%s@%s>%s", $uniq_id, $this->ServerHostname(), $this->LE);
+    }
+    $result .= $this->HeaderLine('X-Priority', $this->Priority);
+    if($this->XMailer) {
+      $result .= $this->HeaderLine('X-Mailer', $this->XMailer);
+    } else {
+      $result .= $this->HeaderLine('X-Mailer', 'PHPMailer '.$this->Version.' (http://code.google.com/a/apache-extras.org/p/phpmailer/)');
+    }
+
+    if($this->ConfirmReadingTo != '') {
+      $result .= $this->HeaderLine('Disposition-Notification-To', '<' . trim($this->ConfirmReadingTo) . '>');
+    }
+
+    // Add custom headers
+    for($index = 0; $index < count($this->CustomHeader); $index++) {
+      $result .= $this->HeaderLine(trim($this->CustomHeader[$index][0]), $this->EncodeHeader(trim($this->CustomHeader[$index][1])));
+    }
+    if (!$this->sign_key_file) {
+      $result .= $this->HeaderLine('MIME-Version', '1.0');
+      $result .= $this->GetMailMIME();
+    }
+
+    return $result;
+  }
+
+  /**
+   * Returns the message MIME.
+   * @access public
+   * @return string
+   */
+  public function GetMailMIME() {
+    $result = '';
+    switch($this->message_type) {
+      case 'plain':
+        $result .= $this->HeaderLine('Content-Transfer-Encoding', $this->Encoding);
+        $result .= $this->TextLine('Content-Type: '.$this->ContentType.'; charset="'.$this->CharSet.'"');
+        break;
+      case 'inline':
+        $result .= $this->HeaderLine('Content-Type', 'multipart/related;');
+        $result .= $this->TextLine("\tboundary=\"" . $this->boundary[1] . '"');
+        break;
+      case 'attach':
+      case 'inline_attach':
+      case 'alt_attach':
+      case 'alt_inline_attach':
+        $result .= $this->HeaderLine('Content-Type', 'multipart/mixed;');
+        $result .= $this->TextLine("\tboundary=\"" . $this->boundary[1] . '"');
+        break;
+      case 'alt':
+      case 'alt_inline':
+        $result .= $this->HeaderLine('Content-Type', 'multipart/alternative;');
+        $result .= $this->TextLine("\tboundary=\"" . $this->boundary[1] . '"');
+        break;
+    }
+
+    if($this->Mailer != 'mail') {
+      $result .= $this->LE.$this->LE;
+    }
+
+    return $result;
+  }
+
+  /**
+   * Assembles the message body.  Returns an empty string on failure.
+   * @access public
+   * @return string The assembled message body
+   */
+  public function CreateBody() {
+    $body = '';
+
+    if ($this->sign_key_file) {
+      $body .= $this->GetMailMIME();
+    }
+
+    $this->SetWordWrap();
+
+    switch($this->message_type) {
+      case 'plain':
+        $body .= $this->EncodeString($this->Body, $this->Encoding);
+        break;
+      case 'inline':
+        $body .= $this->GetBoundary($this->boundary[1], '', '', '');
+        $body .= $this->EncodeString($this->Body, $this->Encoding);
+        $body .= $this->LE.$this->LE;
+        $body .= $this->AttachAll("inline", $this->boundary[1]);
+        break;
+      case 'attach':
+        $body .= $this->GetBoundary($this->boundary[1], '', '', '');
+        $body .= $this->EncodeString($this->Body, $this->Encoding);
+        $body .= $this->LE.$this->LE;
+        $body .= $this->AttachAll("attachment", $this->boundary[1]);
+        break;
+      case 'inline_attach':
+        $body .= $this->TextLine("--" . $this->boundary[1]);
+        $body .= $this->HeaderLine('Content-Type', 'multipart/related;');
+        $body .= $this->TextLine("\tboundary=\"" . $this->boundary[2] . '"');
+        $body .= $this->LE;
+        $body .= $this->GetBoundary($this->boundary[2], '', '', '');
+        $body .= $this->EncodeString($this->Body, $this->Encoding);
+        $body .= $this->LE.$this->LE;
+        $body .= $this->AttachAll("inline", $this->boundary[2]);
+        $body .= $this->LE;
+        $body .= $this->AttachAll("attachment", $this->boundary[1]);
+        break;
+      case 'alt':
+        $body .= $this->GetBoundary($this->boundary[1], '', 'text/plain', '');
+        $body .= $this->EncodeString($this->AltBody, $this->Encoding);
+        $body .= $this->LE.$this->LE;
+        $body .= $this->GetBoundary($this->boundary[1], '', 'text/html', '');
+        $body .= $this->EncodeString($this->Body, $this->Encoding);
+        $body .= $this->LE.$this->LE;
+        $body .= $this->EndBoundary($this->boundary[1]);
+        break;
+      case 'alt_inline':
+        $body .= $this->GetBoundary($this->boundary[1], '', 'text/plain', '');
+        $body .= $this->EncodeString($this->AltBody, $this->Encoding);
+        $body .= $this->LE.$this->LE;
+        $body .= $this->TextLine("--" . $this->boundary[1]);
+        $body .= $this->HeaderLine('Content-Type', 'multipart/related;');
+        $body .= $this->TextLine("\tboundary=\"" . $this->boundary[2] . '"');
+        $body .= $this->LE;
+        $body .= $this->GetBoundary($this->boundary[2], '', 'text/html', '');
+        $body .= $this->EncodeString($this->Body, $this->Encoding);
+        $body .= $this->LE.$this->LE;
+        $body .= $this->AttachAll("inline", $this->boundary[2]);
+        $body .= $this->LE;
+        $body .= $this->EndBoundary($this->boundary[1]);
+        break;
+      case 'alt_attach':
+        $body .= $this->TextLine("--" . $this->boundary[1]);
+        $body .= $this->HeaderLine('Content-Type', 'multipart/alternative;');
+        $body .= $this->TextLine("\tboundary=\"" . $this->boundary[2] . '"');
+        $body .= $this->LE;
+        $body .= $this->GetBoundary($this->boundary[2], '', 'text/plain', '');
+        $body .= $this->EncodeString($this->AltBody, $this->Encoding);
+        $body .= $this->LE.$this->LE;
+        $body .= $this->GetBoundary($this->boundary[2], '', 'text/html', '');
+        $body .= $this->EncodeString($this->Body, $this->Encoding);
+        $body .= $this->LE.$this->LE;
+        $body .= $this->EndBoundary($this->boundary[2]);
+        $body .= $this->LE;
+        $body .= $this->AttachAll("attachment", $this->boundary[1]);
+        break;
+      case 'alt_inline_attach':
+        $body .= $this->TextLine("--" . $this->boundary[1]);
+        $body .= $this->HeaderLine('Content-Type', 'multipart/alternative;');
+        $body .= $this->TextLine("\tboundary=\"" . $this->boundary[2] . '"');
+        $body .= $this->LE;
+        $body .= $this->GetBoundary($this->boundary[2], '', 'text/plain', '');
+        $body .= $this->EncodeString($this->AltBody, $this->Encoding);
+        $body .= $this->LE.$this->LE;
+        $body .= $this->TextLine("--" . $this->boundary[2]);
+        $body .= $this->HeaderLine('Content-Type', 'multipart/related;');
+        $body .= $this->TextLine("\tboundary=\"" . $this->boundary[3] . '"');
+        $body .= $this->LE;
+        $body .= $this->GetBoundary($this->boundary[3], '', 'text/html', '');
+        $body .= $this->EncodeString($this->Body, $this->Encoding);
+        $body .= $this->LE.$this->LE;
+        $body .= $this->AttachAll("inline", $this->boundary[3]);
+        $body .= $this->LE;
+        $body .= $this->EndBoundary($this->boundary[2]);
+        $body .= $this->LE;
+        $body .= $this->AttachAll("attachment", $this->boundary[1]);
+        break;
+    }
+
+    if ($this->IsError()) {
+      $body = '';
+    } elseif ($this->sign_key_file) {
+      try {
+        $file = tempnam('', 'mail');
+        file_put_contents($file, $body); //TODO check this worked
+        $signed = tempnam("", "signed");
+        if (@openssl_pkcs7_sign($file, $signed, "file://".$this->sign_cert_file, array("file://".$this->sign_key_file, $this->sign_key_pass), NULL)) {
+          @unlink($file);
+          @unlink($signed);
+          $body = file_get_contents($signed);
+        } else {
+          @unlink($file);
+          @unlink($signed);
+          throw new phpmailerException($this->Lang("signing").openssl_error_string());
+        }
+      } catch (phpmailerException $e) {
+        $body = '';
+        if ($this->exceptions) {
+          throw $e;
+        }
+      }
+    }
+
+    return $body;
+  }
+
+  /**
+   * Returns the start of a message boundary.
+   * @access protected
+   * @return string
+   */
+  protected function GetBoundary($boundary, $charSet, $contentType, $encoding) {
+    $result = '';
+    if($charSet == '') {
+      $charSet = $this->CharSet;
+    }
+    if($contentType == '') {
+      $contentType = $this->ContentType;
+    }
+    if($encoding == '') {
+      $encoding = $this->Encoding;
+    }
+    $result .= $this->TextLine('--' . $boundary);
+    $result .= sprintf("Content-Type: %s; charset=\"%s\"", $contentType, $charSet);
+    $result .= $this->LE;
+    $result .= $this->HeaderLine('Content-Transfer-Encoding', $encoding);
+    $result .= $this->LE;
+
+    return $result;
+  }
+
+  /**
+   * Returns the end of a message boundary.
+   * @access protected
+   * @return string
+   */
+  protected function EndBoundary($boundary) {
+    return $this->LE . '--' . $boundary . '--' . $this->LE;
+  }
+
+  /**
+   * Sets the message type.
+   * @access protected
+   * @return void
+   */
+  protected function SetMessageType() {
+    $this->message_type = array();
+    if($this->AlternativeExists()) $this->message_type[] = "alt";
+    if($this->InlineImageExists()) $this->message_type[] = "inline";
+    if($this->AttachmentExists()) $this->message_type[] = "attach";
+    $this->message_type = implode("_", $this->message_type);
+    if($this->message_type == "") $this->message_type = "plain";
+  }
+
+  /**
+   *  Returns a formatted header line.
+   * @access public
+   * @return string
+   */
+  public function HeaderLine($name, $value) {
+    return $name . ': ' . $value . $this->LE;
+  }
+
+  /**
+   * Returns a formatted mail line.
+   * @access public
+   * @return string
+   */
+  public function TextLine($value) {
+    return $value . $this->LE;
+  }
+
+  /////////////////////////////////////////////////
+  // CLASS METHODS, ATTACHMENTS
+  /////////////////////////////////////////////////
+
+  /**
+   * Adds an attachment from a path on the filesystem.
+   * Returns false if the file could not be found
+   * or accessed.
+   * @param string $path Path to the attachment.
+   * @param string $name Overrides the attachment name.
+   * @param string $encoding File encoding (see $Encoding).
+   * @param string $type File extension (MIME) type.
+   * @return bool
+   */
+  public function AddAttachment($path, $name = '', $encoding = 'base64', $type = 'application/octet-stream') {
+    try {
+      if ( !@is_file($path) ) {
+        throw new phpmailerException($this->Lang('file_access') . $path, self::STOP_CONTINUE);
+      }
+      $filename = basename($path);
+      if ( $name == '' ) {
+        $name = $filename;
+      }
+
+      $this->attachment[] = array(
+        0 => $path,
+        1 => $filename,
+        2 => $name,
+        3 => $encoding,
+        4 => $type,
+        5 => false,  // isStringAttachment
+        6 => 'attachment',
+        7 => 0
+      );
+
+    } catch (phpmailerException $e) {
+      $this->SetError($e->getMessage());
+      if ($this->exceptions) {
+        throw $e;
+      }
+      echo $e->getMessage()."\n";
+      if ( $e->getCode() == self::STOP_CRITICAL ) {
+        return false;
+      }
+    }
+    return true;
+  }
+
+  /**
+  * Return the current array of attachments
+  * @return array
+  */
+  public function GetAttachments() {
+    return $this->attachment;
+  }
+
+  /**
+   * Attaches all fs, string, and binary attachments to the message.
+   * Returns an empty string on failure.
+   * @access protected
+   * @return string
+   */
+  protected function AttachAll($disposition_type, $boundary) {
+    // Return text of body
+    $mime = array();
+    $cidUniq = array();
+    $incl = array();
+
+    // Add all attachments
+    foreach ($this->attachment as $attachment) {
+      // CHECK IF IT IS A VALID DISPOSITION_FILTER
+      if($attachment[6] == $disposition_type) {
+        // Check for string attachment
+        $bString = $attachment[5];
+        if ($bString) {
+          $string = $attachment[0];
+        } else {
+          $path = $attachment[0];
+        }
+
+        $inclhash = md5(serialize($attachment));
+        if (in_array($inclhash, $incl)) { continue; }
+        $incl[]      = $inclhash;
+        $filename    = $attachment[1];
+        $name        = $attachment[2];
+        $encoding    = $attachment[3];
+        $type        = $attachment[4];
+        $disposition = $attachment[6];
+        $cid         = $attachment[7];
+        if ( $disposition == 'inline' && isset($cidUniq[$cid]) ) { continue; }
+        $cidUniq[$cid] = true;
+
+        $mime[] = sprintf("--%s%s", $boundary, $this->LE);
+        $mime[] = sprintf("Content-Type: %s; name=\"%s\"%s", $type, $this->EncodeHeader($this->SecureHeader($name)), $this->LE);
+        $mime[] = sprintf("Content-Transfer-Encoding: %s%s", $encoding, $this->LE);
+
+        if($disposition == 'inline') {
+          $mime[] = sprintf("Content-ID: <%s>%s", $cid, $this->LE);
+        }
+
+        $mime[] = sprintf("Content-Disposition: %s; filename=\"%s\"%s", $disposition, $this->EncodeHeader($this->SecureHeader($name)), $this->LE.$this->LE);
+
+        // Encode as string attachment
+        if($bString) {
+          $mime[] = $this->EncodeString($string, $encoding);
+          if($this->IsError()) {
+            return '';
+          }
+          $mime[] = $this->LE.$this->LE;
+        } else {
+          $mime[] = $this->EncodeFile($path, $encoding);
+          if($this->IsError()) {
+            return '';
+          }
+          $mime[] = $this->LE.$this->LE;
+        }
+      }
+    }
+
+    $mime[] = sprintf("--%s--%s", $boundary, $this->LE);
+
+    return implode("", $mime);
+  }
+
+  /**
+   * Encodes attachment in requested format.
+   * Returns an empty string on failure.
+   * @param string $path The full path to the file
+   * @param string $encoding The encoding to use; one of 'base64', '7bit', '8bit', 'binary', 'quoted-printable'
+   * @see EncodeFile()
+   * @access protected
+   * @return string
+   */
+  protected function EncodeFile($path, $encoding = 'base64') {
+    try {
+      if (!is_readable($path)) {
+        throw new phpmailerException($this->Lang('file_open') . $path, self::STOP_CONTINUE);
+      }
+      if (function_exists('get_magic_quotes')) {
+        function get_magic_quotes() {
+          return false;
+        }
+      }
+      if (version_compare(PHP_VERSION, '5.3.0', '<')) {
+        $magic_quotes = get_magic_quotes_runtime();
+        set_magic_quotes_runtime(0);
+      }
+      $file_buffer  = file_get_contents($path);
+      $file_buffer  = $this->EncodeString($file_buffer, $encoding);
+      if (version_compare(PHP_VERSION, '5.3.0', '<')) {
+        set_magic_quotes_runtime($magic_quotes);
+      }
+      return $file_buffer;
+    } catch (Exception $e) {
+      $this->SetError($e->getMessage());
+      return '';
+    }
+  }
+
+  /**
+   * Encodes string to requested format.
+   * Returns an empty string on failure.
+   * @param string $str The text to encode
+   * @param string $encoding The encoding to use; one of 'base64', '7bit', '8bit', 'binary', 'quoted-printable'
+   * @access public
+   * @return string
+   */
+  public function EncodeString($str, $encoding = 'base64') {
+    $encoded = '';
+    switch(strtolower($encoding)) {
+      case 'base64':
+        $encoded = chunk_split(base64_encode($str), 76, $this->LE);
+        break;
+      case '7bit':
+      case '8bit':
+        $encoded = $this->FixEOL($str);
+        //Make sure it ends with a line break
+        if (substr($encoded, -(strlen($this->LE))) != $this->LE)
+          $encoded .= $this->LE;
+        break;
+      case 'binary':
+        $encoded = $str;
+        break;
+      case 'quoted-printable':
+        $encoded = $this->EncodeQP($str);
+        break;
+      default:
+        $this->SetError($this->Lang('encoding') . $encoding);
+        break;
+    }
+    return $encoded;
+  }
+
+  /**
+   * Encode a header string to best (shortest) of Q, B, quoted or none.
+   * @access public
+   * @return string
+   */
+  public function EncodeHeader($str, $position = 'text') {
+    $x = 0;
+
+    switch (strtolower($position)) {
+      case 'phrase':
+        if (!preg_match('/[\200-\377]/', $str)) {
+          // Can't use addslashes as we don't know what value has magic_quotes_sybase
+          $encoded = addcslashes($str, "\0..\37\177\\\"");
+          if (($str == $encoded) && !preg_match('/[^A-Za-z0-9!#$%&\'*+\/=?^_`{|}~ -]/', $str)) {
+            return ($encoded);
+          } else {
+            return ("\"$encoded\"");
+          }
+        }
+        $x = preg_match_all('/[^\040\041\043-\133\135-\176]/', $str, $matches);
+        break;
+      case 'comment':
+        $x = preg_match_all('/[()"]/', $str, $matches);
+        // Fall-through
+      case 'text':
+      default:
+        $x += preg_match_all('/[\000-\010\013\014\016-\037\177-\377]/', $str, $matches);
+        break;
+    }
+
+    if ($x == 0) {
+      return ($str);
+    }
+
+    $maxlen = 75 - 7 - strlen($this->CharSet);
+    // Try to select the encoding which should produce the shortest output
+    if (strlen($str)/3 < $x) {
+      $encoding = 'B';
+      if (function_exists('mb_strlen') && $this->HasMultiBytes($str)) {
+        // Use a custom function which correctly encodes and wraps long
+        // multibyte strings without breaking lines within a character
+        $encoded = $this->Base64EncodeWrapMB($str);
+      } else {
+        $encoded = base64_encode($str);
+        $maxlen -= $maxlen % 4;
+        $encoded = trim(chunk_split($encoded, $maxlen, "\n"));
+      }
+    } else {
+      $encoding = 'Q';
+      $encoded = $this->EncodeQ($str, $position);
+      $encoded = $this->WrapText($encoded, $maxlen, true);
+      $encoded = str_replace('='.$this->LE, "\n", trim($encoded));
+    }
+
+    $encoded = preg_replace('/^(.*)$/m', " =?".$this->CharSet."?$encoding?\\1?=", $encoded);
+    $encoded = trim(str_replace("\n", $this->LE, $encoded));
+
+    return $encoded;
+  }
+
+  /**
+   * Checks if a string contains multibyte characters.
+   * @access public
+   * @param string $str multi-byte text to wrap encode
+   * @return bool
+   */
+  public function HasMultiBytes($str) {
+    if (function_exists('mb_strlen')) {
+      return (strlen($str) > mb_strlen($str, $this->CharSet));
+    } else { // Assume no multibytes (we can't handle without mbstring functions anyway)
+      return false;
+    }
+  }
+
+  /**
+   * Correctly encodes and wraps long multibyte strings for mail headers
+   * without breaking lines within a character.
+   * Adapted from a function by paravoid at http://uk.php.net/manual/en/function.mb-encode-mimeheader.php
+   * @access public
+   * @param string $str multi-byte text to wrap encode
+   * @return string
+   */
+  public function Base64EncodeWrapMB($str) {
+    $start = "=?".$this->CharSet."?B?";
+    $end = "?=";
+    $encoded = "";
+
+    $mb_length = mb_strlen($str, $this->CharSet);
+    // Each line must have length <= 75, including $start and $end
+    $length = 75 - strlen($start) - strlen($end);
+    // Average multi-byte ratio
+    $ratio = $mb_length / strlen($str);
+    // Base64 has a 4:3 ratio
+    $offset = $avgLength = floor($length * $ratio * .75);
+
+    for ($i = 0; $i < $mb_length; $i += $offset) {
+      $lookBack = 0;
+
+      do {
+        $offset = $avgLength - $lookBack;
+        $chunk = mb_substr($str, $i, $offset, $this->CharSet);
+        $chunk = base64_encode($chunk);
+        $lookBack++;
+      }
+      while (strlen($chunk) > $length);
+
+      $encoded .= $chunk . $this->LE;
+    }
+
+    // Chomp the last linefeed
+    $encoded = substr($encoded, 0, -strlen($this->LE));
+    return $encoded;
+  }
+
+  /**
+  * Encode string to quoted-printable.
+  * Only uses standard PHP, slow, but will always work
+  * @access public
+  * @param string $string the text to encode
+  * @param integer $line_max Number of chars allowed on a line before wrapping
+  * @return string
+  */
+  public function EncodeQPphp( $input = '', $line_max = 76, $space_conv = false) {
+    $hex = array('0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F');
+    $lines = preg_split('/(?:\r\n|\r|\n)/', $input);
+    $eol = "\r\n";
+    $escape = '=';
+    $output = '';
+    while( list(, $line) = each($lines) ) {
+      $linlen = strlen($line);
+      $newline = '';
+      for($i = 0; $i < $linlen; $i++) {
+        $c = substr( $line, $i, 1 );
+        $dec = ord( $c );
+        if ( ( $i == 0 ) && ( $dec == 46 ) ) { // convert first point in the line into =2E
+          $c = '=2E';
+        }
+        if ( $dec == 32 ) {
+          if ( $i == ( $linlen - 1 ) ) { // convert space at eol only
+            $c = '=20';
+          } else if ( $space_conv ) {
+            $c = '=20';
+          }
+        } elseif ( ($dec == 61) || ($dec < 32 ) || ($dec > 126) ) { // always encode "\t", which is *not* required
+          $h2 = floor($dec/16);
+          $h1 = floor($dec%16);
+          $c = $escape.$hex[$h2].$hex[$h1];
+        }
+        if ( (strlen($newline) + strlen($c)) >= $line_max ) { // CRLF is not counted
+          $output .= $newline.$escape.$eol; //  soft line break; " =\r\n" is okay
+          $newline = '';
+          // check if newline first character will be point or not
+          if ( $dec == 46 ) {
+            $c = '=2E';
+          }
+        }
+        $newline .= $c;
+      } // end of for
+      $output .= $newline.$eol;
+    } // end of while
+    return $output;
+  }
+
+  /**
+  * Encode string to RFC2045 (6.7) quoted-printable format
+  * Uses a PHP5 stream filter to do the encoding about 64x faster than the old version
+  * Also results in same content as you started with after decoding
+  * @see EncodeQPphp()
+  * @access public
+  * @param string $string the text to encode
+  * @param integer $line_max Number of chars allowed on a line before wrapping
+  * @param boolean $space_conv Dummy param for compatibility with existing EncodeQP function
+  * @return string
+  * @author Marcus Bointon
+  */
+  public function EncodeQP($string, $line_max = 76, $space_conv = false) {
+    if (function_exists('quoted_printable_encode')) { //Use native function if it's available (>= PHP5.3)
+      return quoted_printable_encode($string);
+    }
+    $filters = stream_get_filters();
+    if (!in_array('convert.*', $filters)) { //Got convert stream filter?
+      return $this->EncodeQPphp($string, $line_max, $space_conv); //Fall back to old implementation
+    }
+    $fp = fopen('php://temp/', 'r+');
+    $string = preg_replace('/\r\n?/', $this->LE, $string); //Normalise line breaks
+    $params = array('line-length' => $line_max, 'line-break-chars' => $this->LE);
+    $s = stream_filter_append($fp, 'convert.quoted-printable-encode', STREAM_FILTER_READ, $params);
+    fputs($fp, $string);
+    rewind($fp);
+    $out = stream_get_contents($fp);
+    stream_filter_remove($s);
+    $out = preg_replace('/^\./m', '=2E', $out); //Encode . if it is first char on a line, workaround for bug in Exchange
+    fclose($fp);
+    return $out;
+  }
+
+  /**
+   * Encode string to q encoding.
+   * @link http://tools.ietf.org/html/rfc2047
+   * @param string $str the text to encode
+   * @param string $position Where the text is going to be used, see the RFC for what that means
+   * @access public
+   * @return string
+   */
+  public function EncodeQ($str, $position = 'text') {
+    // There should not be any EOL in the string
+    $encoded = preg_replace('/[\r\n]*/', '', $str);
+
+    switch (strtolower($position)) {
+      case 'phrase':
+        $encoded = preg_replace("/([^A-Za-z0-9!*+\/ -])/e", "'='.sprintf('%02X', ord('\\1'))", $encoded);
+        break;
+      case 'comment':
+        $encoded = preg_replace("/([\(\)\"])/e", "'='.sprintf('%02X', ord('\\1'))", $encoded);
+      case 'text':
+      default:
+        // Replace every high ascii, control =, ? and _ characters
+        //TODO using /e (equivalent to eval()) is probably not a good idea
+        $encoded = preg_replace('/([\000-\011\013\014\016-\037\075\077\137\177-\377])/e',
+                                "'='.sprintf('%02X', ord(stripslashes('\\1')))", $encoded);
+        break;
+    }
+
+    // Replace every spaces to _ (more readable than =20)
+    $encoded = str_replace(' ', '_', $encoded);
+
+    return $encoded;
+  }
+
+  /**
+   * Adds a string or binary attachment (non-filesystem) to the list.
+   * This method can be used to attach ascii or binary data,
+   * such as a BLOB record from a database.
+   * @param string $string String attachment data.
+   * @param string $filename Name of the attachment.
+   * @param string $encoding File encoding (see $Encoding).
+   * @param string $type File extension (MIME) type.
+   * @return void
+   */
+  public function AddStringAttachment($string, $filename, $encoding = 'base64', $type = 'application/octet-stream') {
+    // Append to $attachment array
+    $this->attachment[] = array(
+      0 => $string,
+      1 => $filename,
+      2 => basename($filename),
+      3 => $encoding,
+      4 => $type,
+      5 => true,  // isStringAttachment
+      6 => 'attachment',
+      7 => 0
+    );
+  }
+
+  /**
+   * Adds an embedded attachment.  This can include images, sounds, and
+   * just about any other document.  Make sure to set the $type to an
+   * image type.  For JPEG images use "image/jpeg" and for GIF images
+   * use "image/gif".
+   * @param string $path Path to the attachment.
+   * @param string $cid Content ID of the attachment.  Use this to identify
+   *        the Id for accessing the image in an HTML form.
+   * @param string $name Overrides the attachment name.
+   * @param string $encoding File encoding (see $Encoding).
+   * @param string $type File extension (MIME) type.
+   * @return bool
+   */
+  public function AddEmbeddedImage($path, $cid, $name = '', $encoding = 'base64', $type = 'application/octet-stream') {
+
+    if ( !@is_file($path) ) {
+      $this->SetError($this->Lang('file_access') . $path);
+      return false;
+    }
+
+    $filename = basename($path);
+    if ( $name == '' ) {
+      $name = $filename;
+    }
+
+    // Append to $attachment array
+    $this->attachment[] = array(
+      0 => $path,
+      1 => $filename,
+      2 => $name,
+      3 => $encoding,
+      4 => $type,
+      5 => false,  // isStringAttachment
+      6 => 'inline',
+      7 => $cid
+    );
+
+    return true;
+  }
+
+  public function AddStringEmbeddedImage($string, $cid, $filename = '', $encoding = 'base64', $type = 'application/octet-stream') {
+    // Append to $attachment array
+    $this->attachment[] = array(
+      0 => $string,
+      1 => $filename,
+      2 => basename($filename),
+      3 => $encoding,
+      4 => $type,
+      5 => true,  // isStringAttachment
+      6 => 'inline',
+      7 => $cid
+    );
+  }
+
+  /**
+   * Returns true if an inline attachment is present.
+   * @access public
+   * @return bool
+   */
+  public function InlineImageExists() {
+    foreach($this->attachment as $attachment) {
+      if ($attachment[6] == 'inline') {
+        return true;
+      }
+    }
+    return false;
+  }
+
+  public function AttachmentExists() {
+    foreach($this->attachment as $attachment) {
+      if ($attachment[6] == 'attachment') {
+        return true;
+      }
+    }
+    return false;
+  }
+
+  public function AlternativeExists() {
+    return strlen($this->AltBody)>0;
+  }
+
+  /////////////////////////////////////////////////
+  // CLASS METHODS, MESSAGE RESET
+  /////////////////////////////////////////////////
+
+  /**
+   * Clears all recipients assigned in the TO array.  Returns void.
+   * @return void
+   */
+  public function ClearAddresses() {
+    foreach($this->to as $to) {
+      unset($this->all_recipients[strtolower($to[0])]);
+    }
+    $this->to = array();
+  }
+
+  /**
+   * Clears all recipients assigned in the CC array.  Returns void.
+   * @return void
+   */
+  public function ClearCCs() {
+    foreach($this->cc as $cc) {
+      unset($this->all_recipients[strtolower($cc[0])]);
+    }
+    $this->cc = array();
+  }
+
+  /**
+   * Clears all recipients assigned in the BCC array.  Returns void.
+   * @return void
+   */
+  public function ClearBCCs() {
+    foreach($this->bcc as $bcc) {
+      unset($this->all_recipients[strtolower($bcc[0])]);
+    }
+    $this->bcc = array();
+  }
+
+  /**
+   * Clears all recipients assigned in the ReplyTo array.  Returns void.
+   * @return void
+   */
+  public function ClearReplyTos() {
+    $this->ReplyTo = array();
+  }
+
+  /**
+   * Clears all recipients assigned in the TO, CC and BCC
+   * array.  Returns void.
+   * @return void
+   */
+  public function ClearAllRecipients() {
+    $this->to = array();
+    $this->cc = array();
+    $this->bcc = array();
+    $this->all_recipients = array();
+  }
+
+  /**
+   * Clears all previously set filesystem, string, and binary
+   * attachments.  Returns void.
+   * @return void
+   */
+  public function ClearAttachments() {
+    $this->attachment = array();
+  }
+
+  /**
+   * Clears all custom headers.  Returns void.
+   * @return void
+   */
+  public function ClearCustomHeaders() {
+    $this->CustomHeader = array();
+  }
+
+  /////////////////////////////////////////////////
+  // CLASS METHODS, MISCELLANEOUS
+  /////////////////////////////////////////////////
+
+  /**
+   * Adds the error message to the error container.
+   * @access protected
+   * @return void
+   */
+  protected function SetError($msg) {
+    $this->error_count++;
+    if ($this->Mailer == 'smtp' and !is_null($this->smtp)) {
+      $lasterror = $this->smtp->getError();
+      if (!empty($lasterror) and array_key_exists('smtp_msg', $lasterror)) {
+        $msg .= '<p>' . $this->Lang('smtp_error') . $lasterror['smtp_msg'] . "</p>\n";
+      }
+    }
+    $this->ErrorInfo = $msg;
+  }
+
+  /**
+   * Returns the proper RFC 822 formatted date.
+   * @access public
+   * @return string
+   * @static
+   */
+  public static function RFCDate() {
+    $tz = date('Z');
+    $tzs = ($tz < 0) ? '-' : '+';
+    $tz = abs($tz);
+    $tz = (int)($tz/3600)*100 + ($tz%3600)/60;
+    $result = sprintf("%s %s%04d", date('D, j M Y H:i:s'), $tzs, $tz);
+
+    return $result;
+  }
+
+  /**
+   * Returns the server hostname or 'localhost.localdomain' if unknown.
+   * @access protected
+   * @return string
+   */
+  protected function ServerHostname() {
+    if (!empty($this->Hostname)) {
+      $result = $this->Hostname;
+    } elseif (isset($_SERVER['SERVER_NAME'])) {
+      $result = $_SERVER['SERVER_NAME'];
+    } else {
+      $result = 'localhost.localdomain';
+    }
+
+    return $result;
+  }
+
+  /**
+   * Returns a message in the appropriate language.
+   * @access protected
+   * @return string
+   */
+  protected function Lang($key) {
+    if(count($this->language) < 1) {
+      $this->SetLanguage('en'); // set the default language
+    }
+
+    if(isset($this->language[$key])) {
+      return $this->language[$key];
+    } else {
+      return 'Language string failed to load: ' . $key;
+    }
+  }
+
+  /**
+   * Returns true if an error occurred.
+   * @access public
+   * @return bool
+   */
+  public function IsError() {
+    return ($this->error_count > 0);
+  }
+
+  /**
+   * Changes every end of line from CR or LF to CRLF.
+   * @access public
+   * @return string
+   */
+  public function FixEOL($str) {
+    $str = str_replace("\r\n", "\n", $str);
+    $str = str_replace("\r", "\n", $str);
+    $str = str_replace("\n", $this->LE, $str);
+    return $str;
+  }
+
+  /**
+   * Adds a custom header.
+   * @access public
+   * @return void
+   */
+  public function AddCustomHeader($custom_header) {
+    $this->CustomHeader[] = explode(':', $custom_header, 2);
+  }
+
+  /**
+   * Evaluates the message and returns modifications for inline images and backgrounds
+   * @access public
+   * @return $message
+   */
+  public function MsgHTML($message, $basedir = '') {
+    preg_match_all("/(src|background)=\"(.*)\"/Ui", $message, $images);
+    if(isset($images[2])) {
+      foreach($images[2] as $i => $url) {
+        // do not change urls for absolute images (thanks to corvuscorax)
+        if (!preg_match('#^[A-z]+://#', $url)) {
+          $filename = basename($url);
+          $directory = dirname($url);
+          ($directory == '.') ? $directory='': '';
+          $cid = 'cid:' . md5($filename);
+          $ext = pathinfo($filename, PATHINFO_EXTENSION);
+          $mimeType  = self::_mime_types($ext);
+          if ( strlen($basedir) > 1 && substr($basedir, -1) != '/') { $basedir .= '/'; }
+          if ( strlen($directory) > 1 && substr($directory, -1) != '/') { $directory .= '/'; }
+          if ( $this->AddEmbeddedImage($basedir.$directory.$filename, md5($filename), $filename, 'base64', $mimeType) ) {
+            $message = preg_replace("/".$images[1][$i]."=\"".preg_quote($url, '/')."\"/Ui", $images[1][$i]."=\"".$cid."\"", $message);
+          }
+        }
+      }
+    }
+    $this->IsHTML(true);
+    $this->Body = $message;
+    $textMsg = trim(strip_tags(preg_replace('/<(head|title|style|script)[^>]*>.*?<\/\\1>/s', '', $message)));
+    if (!empty($textMsg) && empty($this->AltBody)) {
+      $this->AltBody = html_entity_decode($textMsg);
+    }
+    if (empty($this->AltBody)) {
+      $this->AltBody = 'To view this email message, open it in a program that understands HTML!' . "\n\n";
+    }
+  }
+
+  /**
+   * Gets the MIME type of the embedded or inline image
+   * @param string File extension
+   * @access public
+   * @return string MIME type of ext
+   * @static
+   */
+  public static function _mime_types($ext = '') {
+    $mimes = array(
+      'hqx'   =>  'application/mac-binhex40',
+      'cpt'   =>  'application/mac-compactpro',
+      'doc'   =>  'application/msword',
+      'bin'   =>  'application/macbinary',
+      'dms'   =>  'application/octet-stream',
+      'lha'   =>  'application/octet-stream',
+      'lzh'   =>  'application/octet-stream',
+      'exe'   =>  'application/octet-stream',
+      'class' =>  'application/octet-stream',
+      'psd'   =>  'application/octet-stream',
+      'so'    =>  'application/octet-stream',
+      'sea'   =>  'application/octet-stream',
+      'dll'   =>  'application/octet-stream',
+      'oda'   =>  'application/oda',
+      'pdf'   =>  'application/pdf',
+      'ai'    =>  'application/postscript',
+      'eps'   =>  'application/postscript',
+      'ps'    =>  'application/postscript',
+      'smi'   =>  'application/smil',
+      'smil'  =>  'application/smil',
+      'mif'   =>  'application/vnd.mif',
+      'xls'   =>  'application/vnd.ms-excel',
+      'ppt'   =>  'application/vnd.ms-powerpoint',
+      'wbxml' =>  'application/vnd.wap.wbxml',
+      'wmlc'  =>  'application/vnd.wap.wmlc',
+      'dcr'   =>  'application/x-director',
+      'dir'   =>  'application/x-director',
+      'dxr'   =>  'application/x-director',
+      'dvi'   =>  'application/x-dvi',
+      'gtar'  =>  'application/x-gtar',
+      'php'   =>  'application/x-httpd-php',
+      'php4'  =>  'application/x-httpd-php',
+      'php3'  =>  'application/x-httpd-php',
+      'phtml' =>  'application/x-httpd-php',
+      'phps'  =>  'application/x-httpd-php-source',
+      'js'    =>  'application/x-javascript',
+      'swf'   =>  'application/x-shockwave-flash',
+      'sit'   =>  'application/x-stuffit',
+      'tar'   =>  'application/x-tar',
+      'tgz'   =>  'application/x-tar',
+      'xhtml' =>  'application/xhtml+xml',
+      'xht'   =>  'application/xhtml+xml',
+      'zip'   =>  'application/zip',
+      'mid'   =>  'audio/midi',
+      'midi'  =>  'audio/midi',
+      'mpga'  =>  'audio/mpeg',
+      'mp2'   =>  'audio/mpeg',
+      'mp3'   =>  'audio/mpeg',
+      'aif'   =>  'audio/x-aiff',
+      'aiff'  =>  'audio/x-aiff',
+      'aifc'  =>  'audio/x-aiff',
+      'ram'   =>  'audio/x-pn-realaudio',
+      'rm'    =>  'audio/x-pn-realaudio',
+      'rpm'   =>  'audio/x-pn-realaudio-plugin',
+      'ra'    =>  'audio/x-realaudio',
+      'rv'    =>  'video/vnd.rn-realvideo',
+      'wav'   =>  'audio/x-wav',
+      'bmp'   =>  'image/bmp',
+      'gif'   =>  'image/gif',
+      'jpeg'  =>  'image/jpeg',
+      'jpg'   =>  'image/jpeg',
+      'jpe'   =>  'image/jpeg',
+      'png'   =>  'image/png',
+      'tiff'  =>  'image/tiff',
+      'tif'   =>  'image/tiff',
+      'css'   =>  'text/css',
+      'html'  =>  'text/html',
+      'htm'   =>  'text/html',
+      'shtml' =>  'text/html',
+      'txt'   =>  'text/plain',
+      'text'  =>  'text/plain',
+      'log'   =>  'text/plain',
+      'rtx'   =>  'text/richtext',
+      'rtf'   =>  'text/rtf',
+      'xml'   =>  'text/xml',
+      'xsl'   =>  'text/xml',
+      'mpeg'  =>  'video/mpeg',
+      'mpg'   =>  'video/mpeg',
+      'mpe'   =>  'video/mpeg',
+      'qt'    =>  'video/quicktime',
+      'mov'   =>  'video/quicktime',
+      'avi'   =>  'video/x-msvideo',
+      'movie' =>  'video/x-sgi-movie',
+      'doc'   =>  'application/msword',
+      'word'  =>  'application/msword',
+      'xl'    =>  'application/excel',
+      'eml'   =>  'message/rfc822'
+    );
+    return (!isset($mimes[strtolower($ext)])) ? 'application/octet-stream' : $mimes[strtolower($ext)];
+  }
+
+  /**
+  * Set (or reset) Class Objects (variables)
+  *
+  * Usage Example:
+  * $page->set('X-Priority', '3');
+  *
+  * @access public
+  * @param string $name Parameter Name
+  * @param mixed $value Parameter Value
+  * NOTE: will not work with arrays, there are no arrays to set/reset
+  * @todo Should this not be using __set() magic function?
+  */
+  public function set($name, $value = '') {
+    try {
+      if (isset($this->$name) ) {
+        $this->$name = $value;
+      } else {
+        throw new phpmailerException($this->Lang('variable_set') . $name, self::STOP_CRITICAL);
+      }
+    } catch (Exception $e) {
+      $this->SetError($e->getMessage());
+      if ($e->getCode() == self::STOP_CRITICAL) {
+        return false;
+      }
+    }
+    return true;
+  }
+
+  /**
+   * Strips newlines to prevent header injection.
+   * @access public
+   * @param string $str String
+   * @return string
+   */
+  public function SecureHeader($str) {
+    $str = str_replace("\r", '', $str);
+    $str = str_replace("\n", '', $str);
+    return trim($str);
+  }
+
+  /**
+   * Set the private key file and password to sign the message.
+   *
+   * @access public
+   * @param string $key_filename Parameter File Name
+   * @param string $key_pass Password for private key
+   */
+  public function Sign($cert_filename, $key_filename, $key_pass) {
+    $this->sign_cert_file = $cert_filename;
+    $this->sign_key_file = $key_filename;
+    $this->sign_key_pass = $key_pass;
+  }
+
+  /**
+   * Set the private key file and password to sign the message.
+   *
+   * @access public
+   * @param string $key_filename Parameter File Name
+   * @param string $key_pass Password for private key
+   */
+  public function DKIM_QP($txt) {
+    $tmp = '';
+    $line = '';
+    for ($i = 0; $i < strlen($txt); $i++) {
+      $ord = ord($txt[$i]);
+      if ( ((0x21 <= $ord) && ($ord <= 0x3A)) || $ord == 0x3C || ((0x3E <= $ord) && ($ord <= 0x7E)) ) {
+        $line .= $txt[$i];
+      } else {
+        $line .= "=".sprintf("%02X", $ord);
+      }
+    }
+    return $line;
+  }
+
+  /**
+   * Generate DKIM signature
+   *
+   * @access public
+   * @param string $s Header
+   */
+  public function DKIM_Sign($s) {
+    $privKeyStr = file_get_contents($this->DKIM_private);
+    if ($this->DKIM_passphrase != '') {
+      $privKey = openssl_pkey_get_private($privKeyStr, $this->DKIM_passphrase);
+    } else {
+      $privKey = $privKeyStr;
+    }
+    if (openssl_sign($s, $signature, $privKey)) {
+      return base64_encode($signature);
+    }
+  }
+
+  /**
+   * Generate DKIM Canonicalization Header
+   *
+   * @access public
+   * @param string $s Header
+   */
+  public function DKIM_HeaderC($s) {
+    $s = preg_replace("/\r\n\s+/", " ", $s);
+    $lines = explode("\r\n", $s);
+    foreach ($lines as $key => $line) {
+      list($heading, $value) = explode(":", $line, 2);
+      $heading = strtolower($heading);
+      $value = preg_replace("/\s+/", " ", $value) ; // Compress useless spaces
+      $lines[$key] = $heading.":".trim($value) ; // Don't forget to remove WSP around the value
+    }
+    $s = implode("\r\n", $lines);
+    return $s;
+  }
+
+  /**
+   * Generate DKIM Canonicalization Body
+   *
+   * @access public
+   * @param string $body Message Body
+   */
+  public function DKIM_BodyC($body) {
+    if ($body == '') return "\r\n";
+    // stabilize line endings
+    $body = str_replace("\r\n", "\n", $body);
+    $body = str_replace("\n", "\r\n", $body);
+    // END stabilize line endings
+    while (substr($body, strlen($body) - 4, 4) == "\r\n\r\n") {
+      $body = substr($body, 0, strlen($body) - 2);
+    }
+    return $body;
+  }
+
+  /**
+   * Create the DKIM header, body, as new header
+   *
+   * @access public
+   * @param string $headers_line Header lines
+   * @param string $subject Subject
+   * @param string $body Body
+   */
+  public function DKIM_Add($headers_line, $subject, $body) {
+    $DKIMsignatureType    = 'rsa-sha1'; // Signature & hash algorithms
+    $DKIMcanonicalization = 'relaxed/simple'; // Canonicalization of header/body
+    $DKIMquery            = 'dns/txt'; // Query method
+    $DKIMtime             = time() ; // Signature Timestamp = seconds since 00:00:00 - Jan 1, 1970 (UTC time zone)
+    $subject_header       = "Subject: $subject";
+    $headers              = explode($this->LE, $headers_line);
+    foreach($headers as $header) {
+      if (strpos($header, 'From:') === 0) {
+        $from_header = $header;
+      } elseif (strpos($header, 'To:') === 0) {
+        $to_header = $header;
+      }
+    }
+    $from     = str_replace('|', '=7C', $this->DKIM_QP($from_header));
+    $to       = str_replace('|', '=7C', $this->DKIM_QP($to_header));
+    $subject  = str_replace('|', '=7C', $this->DKIM_QP($subject_header)) ; // Copied header fields (dkim-quoted-printable
+    $body     = $this->DKIM_BodyC($body);
+    $DKIMlen  = strlen($body) ; // Length of body
+    $DKIMb64  = base64_encode(pack("H*", sha1($body))) ; // Base64 of packed binary SHA-1 hash of body
+    $ident    = ($this->DKIM_identity == '')? '' : " i=" . $this->DKIM_identity . ";";
+    $dkimhdrs = "DKIM-Signature: v=1; a=" . $DKIMsignatureType . "; q=" . $DKIMquery . "; l=" . $DKIMlen . "; s=" . $this->DKIM_selector . ";\r\n".
+                "\tt=" . $DKIMtime . "; c=" . $DKIMcanonicalization . ";\r\n".
+                "\th=From:To:Subject;\r\n".
+                "\td=" . $this->DKIM_domain . ";" . $ident . "\r\n".
+                "\tz=$from\r\n".
+                "\t|$to\r\n".
+                "\t|$subject;\r\n".
+                "\tbh=" . $DKIMb64 . ";\r\n".
+                "\tb=";
+    $toSign   = $this->DKIM_HeaderC($from_header . "\r\n" . $to_header . "\r\n" . $subject_header . "\r\n" . $dkimhdrs);
+    $signed   = $this->DKIM_Sign($toSign);
+    return "X-PHPMAILER-DKIM: phpmailer.worxware.com\r\n".$dkimhdrs.$signed."\r\n";
+  }
+
+  protected function doCallback($isSent, $to, $cc, $bcc, $subject, $body) {
+    if (!empty($this->action_function) && function_exists($this->action_function)) {
+      $params = array($isSent, $to, $cc, $bcc, $subject, $body);
+      call_user_func_array($this->action_function, $params);
+    }
+  }
+}
+
+class phpmailerException extends Exception {
+  public function errorMessage() {
+    $errorMsg = '<strong>' . $this->getMessage() . "</strong><br />\n";
+    return $errorMsg;
+  }
+}
+?>
diff --git a/3rdparty/class.smtp.php b/3rdparty/class.smtp.php
new file mode 100644
index 0000000000000000000000000000000000000000..07c275936cf23a75d2e4732b5d9247271e4b752c
--- /dev/null
+++ b/3rdparty/class.smtp.php
@@ -0,0 +1,817 @@
+<?php
+/*~ class.smtp.php
+.---------------------------------------------------------------------------.
+|  Software: PHPMailer - PHP email class                                    |
+|   Version: 5.2                                                            |
+|      Site: https://code.google.com/a/apache-extras.org/p/phpmailer/       |
+| ------------------------------------------------------------------------- |
+|     Admin: Jim Jagielski (project admininistrator)                        |
+|   Authors: Andy Prevost (codeworxtech) codeworxtech@users.sourceforge.net |
+|          : Marcus Bointon (coolbru) coolbru@users.sourceforge.net         |
+|          : Jim Jagielski (jimjag) jimjag@gmail.com                        |
+|   Founder: Brent R. Matzelle (original founder)                           |
+| Copyright (c) 2010-2011, Jim Jagielski. All Rights Reserved.               |
+| Copyright (c) 2004-2009, Andy Prevost. All Rights Reserved.               |
+| Copyright (c) 2001-2003, Brent R. Matzelle                                |
+| ------------------------------------------------------------------------- |
+|   License: Distributed under the Lesser General Public License (LGPL)     |
+|            http://www.gnu.org/copyleft/lesser.html                        |
+| This program is distributed in the hope that it will be useful - WITHOUT  |
+| ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or     |
+| FITNESS FOR A PARTICULAR PURPOSE.                                         |
+'---------------------------------------------------------------------------'
+*/
+
+/**
+ * PHPMailer - PHP SMTP email transport class
+ * NOTE: Designed for use with PHP version 5 and up
+ * @package PHPMailer
+ * @author Andy Prevost
+ * @author Marcus Bointon
+ * @copyright 2004 - 2008 Andy Prevost
+ * @author Jim Jagielski
+ * @copyright 2010 - 2011 Jim Jagielski
+ * @license http://www.gnu.org/copyleft/lesser.html Distributed under the Lesser General Public License (LGPL)
+ * @version $Id: class.smtp.php 450 2010-06-23 16:46:33Z coolbru $
+ */
+
+/**
+ * SMTP is rfc 821 compliant and implements all the rfc 821 SMTP
+ * commands except TURN which will always return a not implemented
+ * error. SMTP also provides some utility methods for sending mail
+ * to an SMTP server.
+ * original author: Chris Ryan
+ */
+
+class SMTP {
+  /**
+   *  SMTP server port
+   *  @var int
+   */
+  public $SMTP_PORT = 25;
+
+  /**
+   *  SMTP reply line ending
+   *  @var string
+   */
+  public $CRLF = "\r\n";
+
+  /**
+   *  Sets whether debugging is turned on
+   *  @var bool
+   */
+  public $do_debug;       // the level of debug to perform
+
+  /**
+   *  Sets VERP use on/off (default is off)
+   *  @var bool
+   */
+  public $do_verp = false;
+
+  /**
+   * Sets the SMTP PHPMailer Version number
+   * @var string
+   */
+  public $Version         = '5.2';
+
+  /////////////////////////////////////////////////
+  // PROPERTIES, PRIVATE AND PROTECTED
+  /////////////////////////////////////////////////
+
+  private $smtp_conn; // the socket to the server
+  private $error;     // error if any on the last call
+  private $helo_rply; // the reply the server sent to us for HELO
+
+  /**
+   * Initialize the class so that the data is in a known state.
+   * @access public
+   * @return void
+   */
+  public function __construct() {
+    $this->smtp_conn = 0;
+    $this->error = null;
+    $this->helo_rply = null;
+
+    $this->do_debug = 0;
+  }
+
+  /////////////////////////////////////////////////
+  // CONNECTION FUNCTIONS
+  /////////////////////////////////////////////////
+
+  /**
+   * Connect to the server specified on the port specified.
+   * If the port is not specified use the default SMTP_PORT.
+   * If tval is specified then a connection will try and be
+   * established with the server for that number of seconds.
+   * If tval is not specified the default is 30 seconds to
+   * try on the connection.
+   *
+   * SMTP CODE SUCCESS: 220
+   * SMTP CODE FAILURE: 421
+   * @access public
+   * @return bool
+   */
+  public function Connect($host, $port = 0, $tval = 30) {
+    // set the error val to null so there is no confusion
+    $this->error = null;
+
+    // make sure we are __not__ connected
+    if($this->connected()) {
+      // already connected, generate error
+      $this->error = array("error" => "Already connected to a server");
+      return false;
+    }
+
+    if(empty($port)) {
+      $port = $this->SMTP_PORT;
+    }
+
+    // connect to the smtp server
+    $this->smtp_conn = @fsockopen($host,    // the host of the server
+                                 $port,    // the port to use
+                                 $errno,   // error number if any
+                                 $errstr,  // error message if any
+                                 $tval);   // give up after ? secs
+    // verify we connected properly
+    if(empty($this->smtp_conn)) {
+      $this->error = array("error" => "Failed to connect to server",
+                           "errno" => $errno,
+                           "errstr" => $errstr);
+      if($this->do_debug >= 1) {
+        echo "SMTP -> ERROR: " . $this->error["error"] . ": $errstr ($errno)" . $this->CRLF . '<br />';
+      }
+      return false;
+    }
+
+    // SMTP server can take longer to respond, give longer timeout for first read
+    // Windows does not have support for this timeout function
+    if(substr(PHP_OS, 0, 3) != "WIN")
+     socket_set_timeout($this->smtp_conn, $tval, 0);
+
+    // get any announcement
+    $announce = $this->get_lines();
+
+    if($this->do_debug >= 2) {
+      echo "SMTP -> FROM SERVER:" . $announce . $this->CRLF . '<br />';
+    }
+
+    return true;
+  }
+
+  /**
+   * Initiate a TLS communication with the server.
+   *
+   * SMTP CODE 220 Ready to start TLS
+   * SMTP CODE 501 Syntax error (no parameters allowed)
+   * SMTP CODE 454 TLS not available due to temporary reason
+   * @access public
+   * @return bool success
+   */
+  public function StartTLS() {
+    $this->error = null; # to avoid confusion
+
+    if(!$this->connected()) {
+      $this->error = array("error" => "Called StartTLS() without being connected");
+      return false;
+    }
+
+    fputs($this->smtp_conn,"STARTTLS" . $this->CRLF);
+
+    $rply = $this->get_lines();
+    $code = substr($rply,0,3);
+
+    if($this->do_debug >= 2) {
+      echo "SMTP -> FROM SERVER:" . $rply . $this->CRLF . '<br />';
+    }
+
+    if($code != 220) {
+      $this->error =
+         array("error"     => "STARTTLS not accepted from server",
+               "smtp_code" => $code,
+               "smtp_msg"  => substr($rply,4));
+      if($this->do_debug >= 1) {
+        echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />';
+      }
+      return false;
+    }
+
+    // Begin encrypted connection
+    if(!stream_socket_enable_crypto($this->smtp_conn, true, STREAM_CRYPTO_METHOD_TLS_CLIENT)) {
+      return false;
+    }
+
+    return true;
+  }
+
+  /**
+   * Performs SMTP authentication.  Must be run after running the
+   * Hello() method.  Returns true if successfully authenticated.
+   * @access public
+   * @return bool
+   */
+  public function Authenticate($username, $password) {
+    // Start authentication
+    fputs($this->smtp_conn,"AUTH LOGIN" . $this->CRLF);
+
+    $rply = $this->get_lines();
+    $code = substr($rply,0,3);
+
+    if($code != 334) {
+      $this->error =
+        array("error" => "AUTH not accepted from server",
+              "smtp_code" => $code,
+              "smtp_msg" => substr($rply,4));
+      if($this->do_debug >= 1) {
+        echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />';
+      }
+      return false;
+    }
+
+    // Send encoded username
+    fputs($this->smtp_conn, base64_encode($username) . $this->CRLF);
+
+    $rply = $this->get_lines();
+    $code = substr($rply,0,3);
+
+    if($code != 334) {
+      $this->error =
+        array("error" => "Username not accepted from server",
+              "smtp_code" => $code,
+              "smtp_msg" => substr($rply,4));
+      if($this->do_debug >= 1) {
+        echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />';
+      }
+      return false;
+    }
+
+    // Send encoded password
+    fputs($this->smtp_conn, base64_encode($password) . $this->CRLF);
+
+    $rply = $this->get_lines();
+    $code = substr($rply,0,3);
+
+    if($code != 235) {
+      $this->error =
+        array("error" => "Password not accepted from server",
+              "smtp_code" => $code,
+              "smtp_msg" => substr($rply,4));
+      if($this->do_debug >= 1) {
+        echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />';
+      }
+      return false;
+    }
+
+    return true;
+  }
+
+  /**
+   * Returns true if connected to a server otherwise false
+   * @access public
+   * @return bool
+   */
+  public function Connected() {
+    if(!empty($this->smtp_conn)) {
+      $sock_status = socket_get_status($this->smtp_conn);
+      if($sock_status["eof"]) {
+        // the socket is valid but we are not connected
+        if($this->do_debug >= 1) {
+            echo "SMTP -> NOTICE:" . $this->CRLF . "EOF caught while checking if connected";
+        }
+        $this->Close();
+        return false;
+      }
+      return true; // everything looks good
+    }
+    return false;
+  }
+
+  /**
+   * Closes the socket and cleans up the state of the class.
+   * It is not considered good to use this function without
+   * first trying to use QUIT.
+   * @access public
+   * @return void
+   */
+  public function Close() {
+    $this->error = null; // so there is no confusion
+    $this->helo_rply = null;
+    if(!empty($this->smtp_conn)) {
+      // close the connection and cleanup
+      fclose($this->smtp_conn);
+      $this->smtp_conn = 0;
+    }
+  }
+
+  /////////////////////////////////////////////////
+  // SMTP COMMANDS
+  /////////////////////////////////////////////////
+
+  /**
+   * Issues a data command and sends the msg_data to the server
+   * finializing the mail transaction. $msg_data is the message
+   * that is to be send with the headers. Each header needs to be
+   * on a single line followed by a <CRLF> with the message headers
+   * and the message body being seperated by and additional <CRLF>.
+   *
+   * Implements rfc 821: DATA <CRLF>
+   *
+   * SMTP CODE INTERMEDIATE: 354
+   *     [data]
+   *     <CRLF>.<CRLF>
+   *     SMTP CODE SUCCESS: 250
+   *     SMTP CODE FAILURE: 552,554,451,452
+   * SMTP CODE FAILURE: 451,554
+   * SMTP CODE ERROR  : 500,501,503,421
+   * @access public
+   * @return bool
+   */
+  public function Data($msg_data) {
+    $this->error = null; // so no confusion is caused
+
+    if(!$this->connected()) {
+      $this->error = array(
+              "error" => "Called Data() without being connected");
+      return false;
+    }
+
+    fputs($this->smtp_conn,"DATA" . $this->CRLF);
+
+    $rply = $this->get_lines();
+    $code = substr($rply,0,3);
+
+    if($this->do_debug >= 2) {
+      echo "SMTP -> FROM SERVER:" . $rply . $this->CRLF . '<br />';
+    }
+
+    if($code != 354) {
+      $this->error =
+        array("error" => "DATA command not accepted from server",
+              "smtp_code" => $code,
+              "smtp_msg" => substr($rply,4));
+      if($this->do_debug >= 1) {
+        echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />';
+      }
+      return false;
+    }
+
+    /* the server is ready to accept data!
+     * according to rfc 821 we should not send more than 1000
+     * including the CRLF
+     * characters on a single line so we will break the data up
+     * into lines by \r and/or \n then if needed we will break
+     * each of those into smaller lines to fit within the limit.
+     * in addition we will be looking for lines that start with
+     * a period '.' and append and additional period '.' to that
+     * line. NOTE: this does not count towards limit.
+     */
+
+    // normalize the line breaks so we know the explode works
+    $msg_data = str_replace("\r\n","\n",$msg_data);
+    $msg_data = str_replace("\r","\n",$msg_data);
+    $lines = explode("\n",$msg_data);
+
+    /* we need to find a good way to determine is headers are
+     * in the msg_data or if it is a straight msg body
+     * currently I am assuming rfc 822 definitions of msg headers
+     * and if the first field of the first line (':' sperated)
+     * does not contain a space then it _should_ be a header
+     * and we can process all lines before a blank "" line as
+     * headers.
+     */
+
+    $field = substr($lines[0],0,strpos($lines[0],":"));
+    $in_headers = false;
+    if(!empty($field) && !strstr($field," ")) {
+      $in_headers = true;
+    }
+
+    $max_line_length = 998; // used below; set here for ease in change
+
+    while(list(,$line) = @each($lines)) {
+      $lines_out = null;
+      if($line == "" && $in_headers) {
+        $in_headers = false;
+      }
+      // ok we need to break this line up into several smaller lines
+      while(strlen($line) > $max_line_length) {
+        $pos = strrpos(substr($line,0,$max_line_length)," ");
+
+        // Patch to fix DOS attack
+        if(!$pos) {
+          $pos = $max_line_length - 1;
+          $lines_out[] = substr($line,0,$pos);
+          $line = substr($line,$pos);
+        } else {
+          $lines_out[] = substr($line,0,$pos);
+          $line = substr($line,$pos + 1);
+        }
+
+        /* if processing headers add a LWSP-char to the front of new line
+         * rfc 822 on long msg headers
+         */
+        if($in_headers) {
+          $line = "\t" . $line;
+        }
+      }
+      $lines_out[] = $line;
+
+      // send the lines to the server
+      while(list(,$line_out) = @each($lines_out)) {
+        if(strlen($line_out) > 0)
+        {
+          if(substr($line_out, 0, 1) == ".") {
+            $line_out = "." . $line_out;
+          }
+        }
+        fputs($this->smtp_conn,$line_out . $this->CRLF);
+      }
+    }
+
+    // message data has been sent
+    fputs($this->smtp_conn, $this->CRLF . "." . $this->CRLF);
+
+    $rply = $this->get_lines();
+    $code = substr($rply,0,3);
+
+    if($this->do_debug >= 2) {
+      echo "SMTP -> FROM SERVER:" . $rply . $this->CRLF . '<br />';
+    }
+
+    if($code != 250) {
+      $this->error =
+        array("error" => "DATA not accepted from server",
+              "smtp_code" => $code,
+              "smtp_msg" => substr($rply,4));
+      if($this->do_debug >= 1) {
+        echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />';
+      }
+      return false;
+    }
+    return true;
+  }
+
+  /**
+   * Sends the HELO command to the smtp server.
+   * This makes sure that we and the server are in
+   * the same known state.
+   *
+   * Implements from rfc 821: HELO <SP> <domain> <CRLF>
+   *
+   * SMTP CODE SUCCESS: 250
+   * SMTP CODE ERROR  : 500, 501, 504, 421
+   * @access public
+   * @return bool
+   */
+  public function Hello($host = '') {
+    $this->error = null; // so no confusion is caused
+
+    if(!$this->connected()) {
+      $this->error = array(
+            "error" => "Called Hello() without being connected");
+      return false;
+    }
+
+    // if hostname for HELO was not specified send default
+    if(empty($host)) {
+      // determine appropriate default to send to server
+      $host = "localhost";
+    }
+
+    // Send extended hello first (RFC 2821)
+    if(!$this->SendHello("EHLO", $host)) {
+      if(!$this->SendHello("HELO", $host)) {
+        return false;
+      }
+    }
+
+    return true;
+  }
+
+  /**
+   * Sends a HELO/EHLO command.
+   * @access private
+   * @return bool
+   */
+  private function SendHello($hello, $host) {
+    fputs($this->smtp_conn, $hello . " " . $host . $this->CRLF);
+
+    $rply = $this->get_lines();
+    $code = substr($rply,0,3);
+
+    if($this->do_debug >= 2) {
+      echo "SMTP -> FROM SERVER: " . $rply . $this->CRLF . '<br />';
+    }
+
+    if($code != 250) {
+      $this->error =
+        array("error" => $hello . " not accepted from server",
+              "smtp_code" => $code,
+              "smtp_msg" => substr($rply,4));
+      if($this->do_debug >= 1) {
+        echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />';
+      }
+      return false;
+    }
+
+    $this->helo_rply = $rply;
+
+    return true;
+  }
+
+  /**
+   * Starts a mail transaction from the email address specified in
+   * $from. Returns true if successful or false otherwise. If True
+   * the mail transaction is started and then one or more Recipient
+   * commands may be called followed by a Data command.
+   *
+   * Implements rfc 821: MAIL <SP> FROM:<reverse-path> <CRLF>
+   *
+   * SMTP CODE SUCCESS: 250
+   * SMTP CODE SUCCESS: 552,451,452
+   * SMTP CODE SUCCESS: 500,501,421
+   * @access public
+   * @return bool
+   */
+  public function Mail($from) {
+    $this->error = null; // so no confusion is caused
+
+    if(!$this->connected()) {
+      $this->error = array(
+              "error" => "Called Mail() without being connected");
+      return false;
+    }
+
+    $useVerp = ($this->do_verp ? "XVERP" : "");
+    fputs($this->smtp_conn,"MAIL FROM:<" . $from . ">" . $useVerp . $this->CRLF);
+
+    $rply = $this->get_lines();
+    $code = substr($rply,0,3);
+
+    if($this->do_debug >= 2) {
+      echo "SMTP -> FROM SERVER:" . $rply . $this->CRLF . '<br />';
+    }
+
+    if($code != 250) {
+      $this->error =
+        array("error" => "MAIL not accepted from server",
+              "smtp_code" => $code,
+              "smtp_msg" => substr($rply,4));
+      if($this->do_debug >= 1) {
+        echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />';
+      }
+      return false;
+    }
+    return true;
+  }
+
+  /**
+   * Sends the quit command to the server and then closes the socket
+   * if there is no error or the $close_on_error argument is true.
+   *
+   * Implements from rfc 821: QUIT <CRLF>
+   *
+   * SMTP CODE SUCCESS: 221
+   * SMTP CODE ERROR  : 500
+   * @access public
+   * @return bool
+   */
+  public function Quit($close_on_error = true) {
+    $this->error = null; // so there is no confusion
+
+    if(!$this->connected()) {
+      $this->error = array(
+              "error" => "Called Quit() without being connected");
+      return false;
+    }
+
+    // send the quit command to the server
+    fputs($this->smtp_conn,"quit" . $this->CRLF);
+
+    // get any good-bye messages
+    $byemsg = $this->get_lines();
+
+    if($this->do_debug >= 2) {
+      echo "SMTP -> FROM SERVER:" . $byemsg . $this->CRLF . '<br />';
+    }
+
+    $rval = true;
+    $e = null;
+
+    $code = substr($byemsg,0,3);
+    if($code != 221) {
+      // use e as a tmp var cause Close will overwrite $this->error
+      $e = array("error" => "SMTP server rejected quit command",
+                 "smtp_code" => $code,
+                 "smtp_rply" => substr($byemsg,4));
+      $rval = false;
+      if($this->do_debug >= 1) {
+        echo "SMTP -> ERROR: " . $e["error"] . ": " . $byemsg . $this->CRLF . '<br />';
+      }
+    }
+
+    if(empty($e) || $close_on_error) {
+      $this->Close();
+    }
+
+    return $rval;
+  }
+
+  /**
+   * Sends the command RCPT to the SMTP server with the TO: argument of $to.
+   * Returns true if the recipient was accepted false if it was rejected.
+   *
+   * Implements from rfc 821: RCPT <SP> TO:<forward-path> <CRLF>
+   *
+   * SMTP CODE SUCCESS: 250,251
+   * SMTP CODE FAILURE: 550,551,552,553,450,451,452
+   * SMTP CODE ERROR  : 500,501,503,421
+   * @access public
+   * @return bool
+   */
+  public function Recipient($to) {
+    $this->error = null; // so no confusion is caused
+
+    if(!$this->connected()) {
+      $this->error = array(
+              "error" => "Called Recipient() without being connected");
+      return false;
+    }
+
+    fputs($this->smtp_conn,"RCPT TO:<" . $to . ">" . $this->CRLF);
+
+    $rply = $this->get_lines();
+    $code = substr($rply,0,3);
+
+    if($this->do_debug >= 2) {
+      echo "SMTP -> FROM SERVER:" . $rply . $this->CRLF . '<br />';
+    }
+
+    if($code != 250 && $code != 251) {
+      $this->error =
+        array("error" => "RCPT not accepted from server",
+              "smtp_code" => $code,
+              "smtp_msg" => substr($rply,4));
+      if($this->do_debug >= 1) {
+        echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />';
+      }
+      return false;
+    }
+    return true;
+  }
+
+  /**
+   * Sends the RSET command to abort and transaction that is
+   * currently in progress. Returns true if successful false
+   * otherwise.
+   *
+   * Implements rfc 821: RSET <CRLF>
+   *
+   * SMTP CODE SUCCESS: 250
+   * SMTP CODE ERROR  : 500,501,504,421
+   * @access public
+   * @return bool
+   */
+  public function Reset() {
+    $this->error = null; // so no confusion is caused
+
+    if(!$this->connected()) {
+      $this->error = array(
+              "error" => "Called Reset() without being connected");
+      return false;
+    }
+
+    fputs($this->smtp_conn,"RSET" . $this->CRLF);
+
+    $rply = $this->get_lines();
+    $code = substr($rply,0,3);
+
+    if($this->do_debug >= 2) {
+      echo "SMTP -> FROM SERVER:" . $rply . $this->CRLF . '<br />';
+    }
+
+    if($code != 250) {
+      $this->error =
+        array("error" => "RSET failed",
+              "smtp_code" => $code,
+              "smtp_msg" => substr($rply,4));
+      if($this->do_debug >= 1) {
+        echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />';
+      }
+      return false;
+    }
+
+    return true;
+  }
+
+  /**
+   * Starts a mail transaction from the email address specified in
+   * $from. Returns true if successful or false otherwise. If True
+   * the mail transaction is started and then one or more Recipient
+   * commands may be called followed by a Data command. This command
+   * will send the message to the users terminal if they are logged
+   * in and send them an email.
+   *
+   * Implements rfc 821: SAML <SP> FROM:<reverse-path> <CRLF>
+   *
+   * SMTP CODE SUCCESS: 250
+   * SMTP CODE SUCCESS: 552,451,452
+   * SMTP CODE SUCCESS: 500,501,502,421
+   * @access public
+   * @return bool
+   */
+  public function SendAndMail($from) {
+    $this->error = null; // so no confusion is caused
+
+    if(!$this->connected()) {
+      $this->error = array(
+          "error" => "Called SendAndMail() without being connected");
+      return false;
+    }
+
+    fputs($this->smtp_conn,"SAML FROM:" . $from . $this->CRLF);
+
+    $rply = $this->get_lines();
+    $code = substr($rply,0,3);
+
+    if($this->do_debug >= 2) {
+      echo "SMTP -> FROM SERVER:" . $rply . $this->CRLF . '<br />';
+    }
+
+    if($code != 250) {
+      $this->error =
+        array("error" => "SAML not accepted from server",
+              "smtp_code" => $code,
+              "smtp_msg" => substr($rply,4));
+      if($this->do_debug >= 1) {
+        echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />';
+      }
+      return false;
+    }
+    return true;
+  }
+
+  /**
+   * This is an optional command for SMTP that this class does not
+   * support. This method is here to make the RFC821 Definition
+   * complete for this class and __may__ be implimented in the future
+   *
+   * Implements from rfc 821: TURN <CRLF>
+   *
+   * SMTP CODE SUCCESS: 250
+   * SMTP CODE FAILURE: 502
+   * SMTP CODE ERROR  : 500, 503
+   * @access public
+   * @return bool
+   */
+  public function Turn() {
+    $this->error = array("error" => "This method, TURN, of the SMTP ".
+                                    "is not implemented");
+    if($this->do_debug >= 1) {
+      echo "SMTP -> NOTICE: " . $this->error["error"] . $this->CRLF . '<br />';
+    }
+    return false;
+  }
+
+  /**
+  * Get the current error
+  * @access public
+  * @return array
+  */
+  public function getError() {
+    return $this->error;
+  }
+
+  /////////////////////////////////////////////////
+  // INTERNAL FUNCTIONS
+  /////////////////////////////////////////////////
+
+  /**
+   * Read in as many lines as possible
+   * either before eof or socket timeout occurs on the operation.
+   * With SMTP we can tell if we have more lines to read if the
+   * 4th character is '-' symbol. If it is a space then we don't
+   * need to read anything else.
+   * @access private
+   * @return string
+   */
+  private function get_lines() {
+    $data = "";
+    while($str = @fgets($this->smtp_conn,515)) {
+      if($this->do_debug >= 4) {
+        echo "SMTP -> get_lines(): \$data was \"$data\"" . $this->CRLF . '<br />';
+        echo "SMTP -> get_lines(): \$str is \"$str\"" . $this->CRLF . '<br />';
+      }
+      $data .= $str;
+      if($this->do_debug >= 4) {
+        echo "SMTP -> get_lines(): \$data is \"$data\"" . $this->CRLF . '<br />';
+      }
+      // if 4th character is a space, we are done reading, break the loop
+      if(substr($str,3,1) == " ") { break; }
+    }
+    return $data;
+  }
+
+}
+
+?>
diff --git a/3rdparty/fullcalendar/changelog.txt b/3rdparty/fullcalendar/changelog.txt
deleted file mode 100644
index 50d0880fd7a3dd4e827c57152f3532b4f8a15dcb..0000000000000000000000000000000000000000
--- a/3rdparty/fullcalendar/changelog.txt
+++ /dev/null
@@ -1,313 +0,0 @@
-
-version 1.5.2 (8/21/11)
-	- correctly process UTC "Z" ISO8601 date strings (issue 750)
-
-version 1.5.1 (4/9/11)
-	- more flexible ISO8601 date parsing (issue 814)
-	- more flexible parsing of UNIX timestamps (issue 826)
-	- FullCalendar now buildable from source on a Mac (issue 795)
-	- FullCalendar QA'd in FF4 (issue 883)
-	- upgraded to jQuery 1.5.2 (which supports IE9) and jQuery UI 1.8.11
-
-version 1.5 (3/19/11)
-	- slicker default styling for buttons
-	- reworked a lot of the calendar's HTML and accompanying CSS
-	  (solves issues 327 and 395)
-	- more printer-friendly (fullcalendar-print.css)
-	- fullcalendar now inherits styles from jquery-ui themes differently.
-	  styles for buttons are distinct from styles for calendar cells.
-	  (solves issue 299)
-	- can now color events through FullCalendar options and Event-Object properties (issue 117)
-	  THIS IS NOW THE PREFERRED METHOD OF COLORING EVENTS (as opposed to using className and CSS)
-		- FullCalendar options:
-			- eventColor (changes both background and border)
-			- eventBackgroundColor
-			- eventBorderColor
-			- eventTextColor
-		- Event-Object options:
-			- color (changes both background and border)
-			- backgroundColor
-			- borderColor
-			- textColor
-	- can now specify an event source as an *object* with a `url` property (json feed) or
-	  an `events` property (function or array) with additional properties that will
-	  be applied to the entire event source:
-		- color (changes both background and border)
-		- backgroudColor
-		- borderColor
-		- textColor
-		- className
-		- editable
-		- allDayDefault
-		- ignoreTimezone
-		- startParam (for a feed)
-		- endParam   (for a feed)
-		- ANY OF THE JQUERY $.ajax OPTIONS
-		  allows for easily changing from GET to POST and sending additional parameters (issue 386)
-		  allows for easily attaching ajax handlers such as `error` (issue 754)
-		  allows for turning caching on (issue 355)
-	- Google Calendar feeds are now specified differently:
-		- specify a simple string of your feed's URL
-		- specify an *object* with a `url` property of your feed's URL.
-		  you can include any of the new Event-Source options in this object.
-		- the old `$.fullCalendar.gcalFeed` method still works
-	- no more IE7 SSL popup (issue 504)
-	- remove `cacheParam` - use json event source `cache` option instead
-	- latest jquery/jquery-ui
-
-version 1.4.11 (2/22/11)
-	- fixed rerenderEvents bug (issue 790)
-	- fixed bug with faulty dragging of events from all-day slot in agenda views
-	- bundled with jquery 1.5 and jquery-ui 1.8.9
-
-version 1.4.10 (1/2/11)
-	- fixed bug with resizing event to different week in 5-day month view (issue 740)
-	- fixed bug with events not sticking after a removeEvents call (issue 757)
-	- fixed bug with underlying parseTime method, and other uses of parseInt (issue 688)
-
-version 1.4.9 (11/16/10)
-	- new algorithm for vertically stacking events (issue 111)
-	- resizing an event to a different week (issue 306)
-	- bug: some events not rendered with consecutive calls to addEventSource (issue 679)
-
-version 1.4.8 (10/16/10)
-	- ignoreTimezone option (set to `false` to process UTC offsets in ISO8601 dates)
-	- bugfixes
-		- event refetching not being called under certain conditions (issues 417, 554)
-		- event refetching being called multiple times under certain conditions (issues 586, 616)
-		- selection cannot be triggered by right mouse button (issue 558)
-		- agenda view left axis sized incorrectly (issue 465)
-		- IE js error when calendar is too narrow (issue 517)
-		- agenda view looks strange when no scrollbars (issue 235)
-		- improved parsing of ISO8601 dates with UTC offsets
-	- $.fullCalendar.version
-	- an internal refactor of the code, for easier future development and modularity
-
-version 1.4.7 (7/5/10)
-	- "dropping" external objects onto the calendar
-		- droppable (boolean, to turn on/off)
-		- dropAccept (to filter which events the calendar will accept)
-		- drop (trigger)
-	- selectable options can now be specified with a View Option Hash
-	- bugfixes
-		- dragged & reverted events having wrong time text (issue 406)
-		- bug rendering events that have an endtime with seconds, but no hours/minutes (issue 477)
-		- gotoDate date overflow bug (issue 429)
-		- wrong date reported when clicking on edge of last column in agenda views (412)
-	- support newlines in event titles
-	- select/unselect callbacks now passes native js event
-
-version 1.4.6 (5/31/10)
-	- "selecting" days or timeslots
-		- options: selectable, selectHelper, unselectAuto, unselectCancel
-		- callbacks: select, unselect
-		- methods: select, unselect
-	- when dragging an event, the highlighting reflects the duration of the event
-	- code compressing by Google Closure Compiler
-	- bundled with jQuery 1.4.2 and jQuery UI 1.8.1
-
-version 1.4.5 (2/21/10)
-	- lazyFetching option, which can force the calendar to fetch events on every view/date change
-	- scroll state of agenda views are preserved when switching back to view
-	- bugfixes
-		- calling methods on an uninitialized fullcalendar throws error
-		- IE6/7 bug where an entire view becomes invisible (issue 320)
-		- error when rendering a hidden calendar (in jquery ui tabs for example) in IE (issue 340)
-		- interconnected bugs related to calendar resizing and scrollbars
-			- when switching views or clicking prev/next, calendar would "blink" (issue 333)
-			- liquid-width calendar's events shifted (depending on initial height of browser) (issue 341)
-			- more robust underlying algorithm for calendar resizing
-
-version 1.4.4 (2/3/10)
-	- optimized event rendering in all views (events render in 1/10 the time)
-	- gotoDate() does not force the calendar to unnecessarily rerender
-	- render() method now correctly readjusts height
-
-version 1.4.3 (12/22/09)
-	- added destroy method
-	- Google Calendar event pages respect currentTimezone
-	- caching now handled by jQuery's ajax
-	- protection from setting aspectRatio to zero
-	- bugfixes
-		- parseISO8601 and DST caused certain events to display day before
-		- button positioning problem in IE6
-		- ajax event source removed after recently being added, events still displayed
-		- event not displayed when end is an empty string
-		- dynamically setting calendar height when no events have been fetched, throws error
-
-version 1.4.2 (12/02/09)
-	- eventAfterRender trigger
-	- getDate & getView methods
-	- height & contentHeight options (explicitly sets the pixel height)
-	- minTime & maxTime options (restricts shown hours in agenda view)
-	- getters [for all options] and setters [for height, contentHeight, and aspectRatio ONLY! stay tuned..]
-	- render method now readjusts calendar's size
-	- bugfixes
-		- lightbox scripts that use iframes (like fancybox)
-		- day-of-week classNames were off when firstDay=1
-		- guaranteed space on right side of agenda events (even when stacked)
-		- accepts ISO8601 dates with a space (instead of 'T')
-
-version 1.4.1 (10/31/09)
-	- can exclude weekends with new 'weekends' option
-	- gcal feed 'currentTimezone' option
-	- bugfixes
-		- year/month/date option sometimes wouldn't set correctly (depending on current date)
-		- daylight savings issue caused agenda views to start at 1am (for BST users)
-	- cleanup of gcal.js code
-
-version 1.4 (10/19/09)
-	- agendaWeek and agendaDay views
-	- added some options for agenda views:
-		- allDaySlot
-		- allDayText
-		- firstHour
-		- slotMinutes
-		- defaultEventMinutes
-		- axisFormat
-	- modified some existing options/triggers to work with agenda views:
-		- dragOpacity and timeFormat can now accept a "View Hash" (a new concept)
-		- dayClick now has an allDay parameter
-		- eventDrop now has an an allDay parameter
-		  (this will affect those who use revertFunc, adjust parameter list)
-	- added 'prevYear' and 'nextYear' for buttons in header
-	- minor change for theme users, ui-state-hover not applied to active/inactive buttons
-	- added event-color-changing example in docs
-	- better defaults for right-to-left themed button icons
-
-version 1.3.2 (10/13/09)
-	- Bugfixes (please upgrade from 1.3.1!)
-		- squashed potential infinite loop when addMonths and addDays
-		  is called with an invalid date
-		- $.fullCalendar.parseDate() now correctly parses IETF format
-		- when switching views, the 'today' button sticks inactive, fixed
-	- gotoDate now can accept a single Date argument
-	- documentation for changes in 1.3.1 and 1.3.2 now on website
-
-version 1.3.1 (9/30/09)
-	- Important Bugfixes (please upgrade from 1.3!)
-		- When current date was late in the month, for long months, and prev/next buttons
-		  were clicked in month-view, some months would be skipped/repeated
-		- In certain time zones, daylight savings time would cause certain days
-		  to be misnumbered in month-view
-	- Subtle change in way week interval is chosen when switching from month to basicWeek/basicDay view
-	- Added 'allDayDefault' option
-	- Added 'changeView' and 'render' methods
-
-version 1.3 (9/21/09)
-	- different 'views': month/basicWeek/basicDay
-	- more flexible 'header' system for buttons
-	- themable by jQuery UI themes
-	- resizable events (require jQuery UI resizable plugin)
-	- rescoped & rewritten CSS, enhanced default look
-	- cleaner css & rendering techniques for right-to-left
-	- reworked options & API to support multiple views / be consistent with jQuery UI
-	- refactoring of entire codebase
-		- broken into different JS & CSS files, assembled w/ build scripts
-		- new test suite for new features, uses firebug-lite
-	- refactored docs
-	- Options
-		+ date
-		+ defaultView
-		+ aspectRatio
-		+ disableResizing
-		+ monthNames      (use instead of $.fullCalendar.monthNames)
-		+ monthNamesShort (use instead of $.fullCalendar.monthAbbrevs)
-		+ dayNames        (use instead of $.fullCalendar.dayNames)
-		+ dayNamesShort   (use instead of $.fullCalendar.dayAbbrevs)
-		+ theme
-		+ buttonText
-		+ buttonIcons
-		x draggable           -> editable/disableDragging
-		x fixedWeeks          -> weekMode
-		x abbrevDayHeadings   -> columnFormat
-		x buttons/title       -> header
-		x eventDragOpacity    -> dragOpacity
-		x eventRevertDuration -> dragRevertDuration
-		x weekStart           -> firstDay
-		x rightToLeft         -> isRTL
-		x showTime (use 'allDay' CalEvent property instead)
-	- Triggered Actions
-		+ eventResizeStart
-		+ eventResizeStop
-		+ eventResize
-		x monthDisplay -> viewDisplay
-		x resize       -> windowResize
-		'eventDrop' params changed, can revert if ajax cuts out
-	- CalEvent Properties
-		x showTime  -> allDay
-		x draggable -> editable
-		'end' is now INCLUSIVE when allDay=true
-		'url' now produces a real <a> tag, more native clicking/tab behavior
-	- Methods:
-		+ renderEvent
-		x prevMonth         -> prev
-		x nextMonth         -> next
-		x prevYear/nextYear -> moveDate
-		x refresh           -> rerenderEvents/refetchEvents
-		x removeEvent       -> removeEvents
-		x getEventsByID     -> clientEvents
-	- Utilities:
-		'formatDate' format string completely changed (inspired by jQuery UI datepicker + datejs)
-		'formatDates' added to support date-ranges
-	- Google Calendar Options:
-		x draggable -> editable
-	- Bugfixes
-		- gcal extension fetched 25 results max, now fetches all
-
-version 1.2.1 (6/29/09)
-	- bugfixes
-		- allows and corrects invalid end dates for events
-		- doesn't throw an error in IE while rendering when display:none
-		- fixed 'loading' callback when used w/ multiple addEventSource calls
-		- gcal className can now be an array
-
-version 1.2 (5/31/09)
-	- expanded API
-		- 'className' CalEvent attribute
-		- 'source' CalEvent attribute
-		- dynamically get/add/remove/update events of current month
-		- locale improvements: change month/day name text
-		- better date formatting ($.fullCalendar.formatDate)
-		- multiple 'event sources' allowed
-			- dynamically add/remove event sources
-	- options for prevYear and nextYear buttons
-	- docs have been reworked (include addition of Google Calendar docs)
-	- changed behavior of parseDate for number strings
-	  (now interpets as unix timestamp, not MS times)
-	- bugfixes
-		- rightToLeft month start bug
-		- off-by-one errors with month formatting commands
-		- events from previous months sticking when clicking prev/next quickly
-	- Google Calendar API changed to work w/ multiple event sources
-		- can also provide 'className' and 'draggable' options
-	- date utilties moved from $ to $.fullCalendar
-	- more documentation in source code
-	- minified version of fullcalendar.js
-	- test suit (available from svn)
-	- top buttons now use <button> w/ an inner <span> for better css cusomization
-		- thus CSS has changed. IF UPGRADING FROM PREVIOUS VERSIONS,
-		  UPGRADE YOUR FULLCALENDAR.CSS FILE!!!
-
-version 1.1 (5/10/09)
-	- Added the following options:
-		- weekStart
-		- rightToLeft
-		- titleFormat
-		- timeFormat
-		- cacheParam
-		- resize
-	- Fixed rendering bugs
-		- Opera 9.25 (events placement & window resizing)
-		- IE6 (window resizing)
-	- Optimized window resizing for ALL browsers
-	- Events on same day now sorted by start time (but first by timespan)
-	- Correct z-index when dragging
-	- Dragging contained in overflow DIV for IE6
-	- Modified fullcalendar.css
-		- for right-to-left support
-		- for variable start-of-week
-		- for IE6 resizing bug
-		- for THEAD and TBODY (in 1.0, just used TBODY, restructured in 1.1)
-		- IF UPGRADING FROM FULLCALENDAR 1.0, YOU MUST UPGRADE FULLCALENDAR.CSS
-		  !!!!!!!!!!!
diff --git a/3rdparty/fullcalendar/css/fullcalendar.css b/3rdparty/fullcalendar/css/fullcalendar.css
index 4e9e95e894f7732cc0e47f11a1864150dcd2389d..04f118493a4e6f9ba3626934578fe605c5244c14 100644
--- a/3rdparty/fullcalendar/css/fullcalendar.css
+++ b/3rdparty/fullcalendar/css/fullcalendar.css
@@ -1,11 +1,11 @@
 /*
- * FullCalendar v1.5.2 Stylesheet
+ * FullCalendar v1.5.3 Stylesheet
  *
  * Copyright (c) 2011 Adam Shaw
  * Dual licensed under the MIT and GPL licenses, located in
  * MIT-LICENSE.txt and GPL-LICENSE.txt respectively.
  *
- * Date: Sun Aug 21 22:06:09 2011 -0700
+ * Date: Mon Feb 6 22:40:40 2012 -0800
  *
  */
 
@@ -14,17 +14,17 @@
 	direction: ltr;
 	text-align: left;
 	}
-
+	
 .fc table {
 	border-collapse: collapse;
 	border-spacing: 0;
 	}
-
+	
 html .fc,
 .fc table {
 	font-size: 1em;
 	}
-
+	
 .fc td,
 .fc th {
 	padding: 0;
@@ -44,56 +44,56 @@ html .fc,
 	width: 25%;
 	text-align: left;
 	}
-
+	
 .fc-header-center {
 	text-align: center;
 	}
-
+	
 .fc-header-right {
 	width: 25%;
 	text-align: right;
 	}
-
+	
 .fc-header-title {
 	display: inline-block;
 	vertical-align: top;
 	}
-
+	
 .fc-header-title h2 {
 	margin-top: 0;
 	white-space: nowrap;
 	}
-
+	
 .fc .fc-header-space {
 	padding-left: 10px;
 	}
-
+	
 .fc-header .fc-button {
 	margin-bottom: 1em;
 	vertical-align: top;
 	}
-
+	
 /* buttons edges butting together */
 
 .fc-header .fc-button {
 	margin-right: -1px;
 	}
-
+	
 .fc-header .fc-corner-right {
 	margin-right: 1px; /* back to normal */
 	}
-
+	
 .fc-header .ui-corner-right {
 	margin-right: 0; /* back to normal */
 	}
-
+	
 /* button layering (for border precedence) */
-
+	
 .fc-header .fc-state-hover,
 .fc-header .ui-state-hover {
 	z-index: 2;
 	}
-
+	
 .fc-header .fc-state-down {
 	z-index: 3;
 	}
@@ -102,22 +102,22 @@ html .fc,
 .fc-header .ui-state-active {
 	z-index: 4;
 	}
-
-
-
+	
+	
+	
 /* Content
 ------------------------------------------------------------------------*/
-
+	
 .fc-content {
 	clear: both;
 	}
-
+	
 .fc-view {
 	width: 100%; /* needed for view switching (when view is absolute) */
 	overflow: hidden;
 	}
-
-
+	
+	
 
 /* Cell Styles
 ------------------------------------------------------------------------*/
@@ -126,17 +126,17 @@ html .fc,
 .fc-widget-content {  /* <td>, usually */
 	border: 1px solid #ccc;
 	}
-
+	
 .fc-state-highlight { /* <td> today cell */ /* TODO: add .fc-today to <th> */
 	background: #ffc;
 	}
-
+	
 .fc-cell-overlay { /* semi-transparent rectangle while dragging */
 	background: #9cf;
 	opacity: .2;
 	filter: alpha(opacity=20); /* for IE */
 	}
-
+	
 
 
 /* Buttons
@@ -147,23 +147,23 @@ html .fc,
 	display: inline-block;
 	cursor: pointer;
 	}
-
+	
 .fc-state-default { /* non-theme */
 	border-style: solid;
 	border-width: 1px 0;
 	}
-
+	
 .fc-button-inner {
 	position: relative;
 	float: left;
 	overflow: hidden;
 	}
-
+	
 .fc-state-default .fc-button-inner { /* non-theme */
 	border-style: solid;
 	border-width: 0 1px;
 	}
-
+	
 .fc-button-content {
 	position: relative;
 	float: left;
@@ -172,15 +172,15 @@ html .fc,
 	padding: 0 .6em;
 	white-space: nowrap;
 	}
-
+	
 /* icon (for jquery ui) */
-
+	
 .fc-button-content .fc-icon-wrap {
 	position: relative;
 	float: left;
 	top: 50%;
 	}
-
+	
 .fc-button-content .ui-icon {
 	position: relative;
 	float: left;
@@ -188,15 +188,15 @@ html .fc,
 	*margin-top: 0;
 	*top: -50%;
 	}
-
+	
 /* gloss effect */
-
+	
 .fc-state-default .fc-button-effect {
 	position: absolute;
 	top: 50%;
 	left: 0;
 	}
-
+	
 .fc-state-default .fc-button-effect span {
 	position: absolute;
 	top: -100px;
@@ -210,9 +210,9 @@ html .fc,
 	opacity: .09;
 	filter: alpha(opacity=9);
 	}
-
+	
 /* button states (determines colors)  */
-
+	
 .fc-state-default,
 .fc-state-default .fc-button-inner {
 	border-style: solid;
@@ -220,70 +220,70 @@ html .fc,
 	background: #F3F3F3;
 	color: #000;
 	}
-
+	
 .fc-state-hover,
 .fc-state-hover .fc-button-inner {
 	border-color: #999;
 	}
-
+	
 .fc-state-down,
 .fc-state-down .fc-button-inner {
 	border-color: #555;
 	background: #777;
 	}
-
+	
 .fc-state-active,
 .fc-state-active .fc-button-inner {
 	border-color: #555;
 	background: #777;
 	color: #fff;
 	}
-
+	
 .fc-state-disabled,
 .fc-state-disabled .fc-button-inner {
 	color: #999;
 	border-color: #ddd;
 	}
-
+	
 .fc-state-disabled {
 	cursor: default;
 	}
-
+	
 .fc-state-disabled .fc-button-effect {
 	display: none;
 	}
-
-
+	
+	
 
 /* Global Event Styles
 ------------------------------------------------------------------------*/
-
+	 
 .fc-event {
 	border-style: solid;
 	border-width: 0;
 	font-size: .85em;
 	cursor: default;
 	}
-
+	
 a.fc-event,
 .fc-event-draggable {
 	cursor: pointer;
 	}
-
+	
 a.fc-event {
 	text-decoration: none;
 	}
-
+	
 .fc-rtl .fc-event {
 	text-align: right;
 	}
-
+	
 .fc-event-skin {
 	border-color: #36c;     /* default BORDER color */
 	background-color: #36c; /* default BACKGROUND color */
 	color: #fff;            /* default TEXT color */
 	}
-
+	
 .fc-event-inner {
 	position: relative;
 	width: 100%;
@@ -292,12 +292,12 @@ a.fc-event {
 	border-width: 0;
 	overflow: hidden;
 	}
-
+	
 .fc-event-time,
 .fc-event-title {
 	padding: 0 1px;
 	}
-
+	
 .fc .ui-resizable-handle { /*** TODO: don't use ui-resizable anymore, change class ***/
 	display: block;
 	position: absolute;
@@ -306,9 +306,9 @@ a.fc-event {
 	font-size: 300%;  /* */
 	line-height: 50%; /* */
 	}
-
-
-
+	
+	
+	
 /* Horizontal Events
 ------------------------------------------------------------------------*/
 
@@ -316,9 +316,9 @@ a.fc-event {
 	border-width: 1px 0;
 	margin-bottom: 1px;
 	}
-
+	
 /* resizable */
-
+	
 .fc-event-hori .ui-resizable-e {
 	top: 0           !important; /* importants override pre jquery ui 1.7 styles */
 	right: -3px      !important;
@@ -326,7 +326,7 @@ a.fc-event {
 	height: 100%     !important;
 	cursor: e-resize;
 	}
-
+	
 .fc-event-hori .ui-resizable-w {
 	top: 0           !important;
 	left: -3px       !important;
@@ -334,101 +334,101 @@ a.fc-event {
 	height: 100%     !important;
 	cursor: w-resize;
 	}
-
+	
 .fc-event-hori .ui-resizable-handle {
 	_padding-bottom: 14px; /* IE6 had 0 height */
 	}
-
-
-
+	
+	
+	
 /* Fake Rounded Corners (for buttons and events)
 ------------------------------------------------------------*/
-
+	
 .fc-corner-left {
 	margin-left: 1px;
 	}
-
+	
 .fc-corner-left .fc-button-inner,
 .fc-corner-left .fc-event-inner {
 	margin-left: -1px;
 	}
-
+	
 .fc-corner-right {
 	margin-right: 1px;
 	}
-
+	
 .fc-corner-right .fc-button-inner,
 .fc-corner-right .fc-event-inner {
 	margin-right: -1px;
 	}
-
+	
 .fc-corner-top {
 	margin-top: 1px;
 	}
-
+	
 .fc-corner-top .fc-event-inner {
 	margin-top: -1px;
 	}
-
+	
 .fc-corner-bottom {
 	margin-bottom: 1px;
 	}
-
+	
 .fc-corner-bottom .fc-event-inner {
 	margin-bottom: -1px;
 	}
-
-
-
+	
+	
+	
 /* Fake Rounded Corners SPECIFICALLY FOR EVENTS
 -----------------------------------------------------------------*/
-
+	
 .fc-corner-left .fc-event-inner {
 	border-left-width: 1px;
 	}
-
+	
 .fc-corner-right .fc-event-inner {
 	border-right-width: 1px;
 	}
-
+	
 .fc-corner-top .fc-event-inner {
 	border-top-width: 1px;
 	}
-
+	
 .fc-corner-bottom .fc-event-inner {
 	border-bottom-width: 1px;
 	}
-
-
-
+	
+	
+	
 /* Reusable Separate-border Table
 ------------------------------------------------------------*/
 
 table.fc-border-separate {
 	border-collapse: separate;
 	}
-
+	
 .fc-border-separate th,
 .fc-border-separate td {
 	border-width: 1px 0 0 1px;
 	}
-
+	
 .fc-border-separate th.fc-last,
 .fc-border-separate td.fc-last {
 	border-right-width: 1px;
 	}
-
+	
 .fc-border-separate tr.fc-last th,
 .fc-border-separate tr.fc-last td {
 	border-bottom-width: 1px;
 	}
-
+	
 .fc-border-separate tbody tr.fc-first td,
 .fc-border-separate tbody tr.fc-first th {
 	border-top-width: 0;
 	}
-
-
+	
+	
 
 /* Month View, Basic Week View, Basic Day View
 ------------------------------------------------------------------------*/
@@ -436,12 +436,12 @@ table.fc-border-separate {
 .fc-grid th {
 	text-align: center;
 	}
-
+	
 .fc-grid .fc-day-number {
 	float: right;
 	padding: 0 2px;
 	}
-
+	
 .fc-grid .fc-other-month .fc-day-number {
 	opacity: 0.3;
 	filter: alpha(opacity=30); /* for IE */
@@ -449,29 +449,29 @@ table.fc-border-separate {
 	   might want to set the 'color' property instead
 	   making day-numbers bold also fixes the problem */
 	}
-
+	
 .fc-grid .fc-day-content {
 	clear: both;
 	padding: 2px 2px 1px; /* distance between events and day edges */
 	}
-
+	
 /* event styles */
-
+	
 .fc-grid .fc-event-time {
 	font-weight: bold;
 	}
-
+	
 /* right-to-left */
-
+	
 .fc-rtl .fc-grid .fc-day-number {
 	float: left;
 	}
-
+	
 .fc-rtl .fc-grid .fc-event-time {
 	float: right;
 	}
-
-
+	
+	
 
 /* Agenda Week View, Agenda Day View
 ------------------------------------------------------------------------*/
@@ -479,11 +479,11 @@ table.fc-border-separate {
 .fc-agenda table {
 	border-collapse: separate;
 	}
-
+	
 .fc-agenda-days th {
 	text-align: center;
 	}
-
+	
 .fc-agenda .fc-agenda-axis {
 	width: 50px;
 	padding: 0 4px;
@@ -492,58 +492,58 @@ table.fc-border-separate {
 	white-space: nowrap;
 	font-weight: normal;
 	}
-
+	
 .fc-agenda .fc-day-content {
 	padding: 2px 2px 1px;
 	}
-
+	
 /* make axis border take precedence */
-
+	
 .fc-agenda-days .fc-agenda-axis {
 	border-right-width: 1px;
 	}
-
+	
 .fc-agenda-days .fc-col0 {
 	border-left-width: 0;
 	}
-
+	
 /* all-day area */
-
+	
 .fc-agenda-allday th {
 	border-width: 0 1px;
 	}
-
+	
 .fc-agenda-allday .fc-day-content {
 	min-height: 34px; /* TODO: doesnt work well in quirksmode */
 	_height: 34px;
 	}
-
+	
 /* divider (between all-day and slots) */
-
+	
 .fc-agenda-divider-inner {
 	height: 2px;
 	overflow: hidden;
 	}
-
+	
 .fc-widget-header .fc-agenda-divider-inner {
 	background: #eee;
 	}
-
+	
 /* slot rows */
-
+	
 .fc-agenda-slots th {
 	border-width: 1px 1px 0;
 	}
-
+	
 .fc-agenda-slots td {
 	border-width: 1px 0 0;
 	background: none;
 	}
-
+	
 .fc-agenda-slots td div {
 	height: 20px;
 	}
-
+	
 .fc-agenda-slots tr.fc-slot0 th,
 .fc-agenda-slots tr.fc-slot0 td {
 	border-top-width: 0;
@@ -553,11 +553,11 @@ table.fc-border-separate {
 .fc-agenda-slots tr.fc-minor td {
 	border-top-style: dotted;
 	}
-
+	
 .fc-agenda-slots tr.fc-minor th.ui-widget-header {
 	*border-top-style: solid; /* doesn't work with background in IE6/7 */
 	}
-
+	
 
 
 /* Vertical Events
@@ -566,7 +566,7 @@ table.fc-border-separate {
 .fc-event-vert {
 	border-width: 0 1px;
 	}
-
+	
 .fc-event-vert .fc-event-head,
 .fc-event-vert .fc-event-content {
 	position: relative;
@@ -574,12 +574,12 @@ table.fc-border-separate {
 	width: 100%;
 	overflow: hidden;
 	}
-
+	
 .fc-event-vert .fc-event-time {
 	white-space: nowrap;
 	font-size: 10px;
 	}
-
+	
 .fc-event-vert .fc-event-bg { /* makes the event lighter w/ a semi-transparent overlay  */
 	position: absolute;
 	z-index: 1;
@@ -591,14 +591,14 @@ table.fc-border-separate {
 	opacity: .3;
 	filter: alpha(opacity=30);
 	}
-
+	
 .fc .ui-draggable-dragging .fc-event-bg, /* TODO: something nicer like .fc-opacity */
 .fc-select-helper .fc-event-bg {
 	display: none\9; /* for IE6/7/8. nested opacity filters while dragging don't work */
 	}
-
+	
 /* resizable */
-
+	
 .fc-event-vert .ui-resizable-s {
 	bottom: 0        !important; /* importants override pre jquery ui 1.7 styles */
 	width: 100%      !important;
@@ -610,7 +610,9 @@ table.fc-border-separate {
 	text-align: center;
 	cursor: s-resize;
 	}
-
+	
 .fc-agenda .ui-resizable-resizing { /* TODO: better selector */
 	_overflow: hidden;
 	}
+	
+	
diff --git a/3rdparty/fullcalendar/css/fullcalendar.print.css b/3rdparty/fullcalendar/css/fullcalendar.print.css
index 18c7c9b10af0e0ac0caae846249fb4b1d1fec3af..e11c1816373a8d1df99c7849c669fe8d28db3307 100644
--- a/3rdparty/fullcalendar/css/fullcalendar.print.css
+++ b/3rdparty/fullcalendar/css/fullcalendar.print.css
@@ -1,5 +1,5 @@
 /*
- * FullCalendar v1.5.2 Print Stylesheet
+ * FullCalendar v1.5.3 Print Stylesheet
  *
  * Include this stylesheet on your page to get a more printer-friendly calendar.
  * When including this stylesheet, use the media='print' attribute of the <link> tag.
@@ -9,51 +9,53 @@
  * Dual licensed under the MIT and GPL licenses, located in
  * MIT-LICENSE.txt and GPL-LICENSE.txt respectively.
  *
- * Date: Sun Aug 21 22:06:09 2011 -0700
+ * Date: Mon Feb 6 22:40:40 2012 -0800
  *
  */
-
-
+ 
+ 
  /* Events
 -----------------------------------------------------*/
-
+ 
 .fc-event-skin {
 	background: none !important;
 	color: #000 !important;
 	}
-
+	
 /* horizontal events */
-
+	
 .fc-event-hori {
 	border-width: 0 0 1px 0 !important;
 	border-bottom-style: dotted !important;
 	border-bottom-color: #000 !important;
 	padding: 1px 0 0 0 !important;
 	}
-
+	
 .fc-event-hori .fc-event-inner {
 	border-width: 0 !important;
 	padding: 0 1px !important;
 	}
-
+	
 /* vertical events */
-
+	
 .fc-event-vert {
 	border-width: 0 0 0 1px !important;
 	border-left-style: dotted !important;
 	border-left-color: #000 !important;
 	padding: 0 1px 0 0 !important;
 	}
-
+	
 .fc-event-vert .fc-event-inner {
 	border-width: 0 !important;
 	padding: 1px 0 !important;
 	}
-
+	
 .fc-event-bg {
 	display: none !important;
 	}
-
+	
 .fc-event .ui-resizable-handle {
 	display: none !important;
 	}
+	
+	
diff --git a/3rdparty/fullcalendar/js/fullcalendar.js b/3rdparty/fullcalendar/js/fullcalendar.js
index fcdafbfca49712aaba9a07a9206b48aba4cb3536..779a313c7611cfaa867ece2f740a7c5577477f11 100644
--- a/3rdparty/fullcalendar/js/fullcalendar.js
+++ b/3rdparty/fullcalendar/js/fullcalendar.js
@@ -1,6 +1,6 @@
 /**
  * @preserve
- * FullCalendar v1.5.2
+ * FullCalendar v1.5.3
  * http://arshaw.com/fullcalendar/
  *
  * Use fullcalendar.css for basic styling.
@@ -11,10 +11,10 @@
  * Dual licensed under the MIT and GPL licenses, located in
  * MIT-LICENSE.txt and GPL-LICENSE.txt respectively.
  *
- * Date: Sun Aug 21 22:06:09 2011 -0700
+ * Date: Mon Feb 6 22:40:40 2012 -0800
  *
  */
-
+ 
 (function($, undefined) {
 
 
@@ -29,20 +29,20 @@ var defaults = {
 		right: 'today prev,next'
 	},
 	weekends: true,
-
+	
 	// editing
 	//editable: false,
 	//disableDragging: false,
 	//disableResizing: false,
-
+	
 	allDayDefault: true,
 	ignoreTimezone: true,
-
+	
 	// event ajax
 	lazyFetching: true,
 	startParam: 'start',
 	endParam: 'end',
-
+	
 	// time formats
 	titleFormat: {
 		month: 'MMMM yyyy',
@@ -57,7 +57,7 @@ var defaults = {
 	timeFormat: { // for event elements
 		'': 'h(:mm)t' // default
 	},
-
+	
 	// locale
 	isRTL: false,
 	firstDay: 0,
@@ -75,19 +75,19 @@ var defaults = {
 		week: 'week',
 		day: 'day'
 	},
-
+	
 	// jquery-ui theming
 	theme: false,
 	buttonIcons: {
 		prev: 'circle-triangle-w',
 		next: 'circle-triangle-e'
 	},
-
+	
 	//selectable: false,
 	unselectAuto: true,
-
+	
 	dropAccept: '*'
-
+	
 };
 
 // right-to-left defaults
@@ -111,7 +111,7 @@ var rtlDefaults = {
 
 
 
-var fc = $.fullCalendar = { version: "1.5.2" };
+var fc = $.fullCalendar = { version: "1.5.3" };
 var fcViews = fc.views = {};
 
 
@@ -139,8 +139,8 @@ $.fn.fullCalendar = function(options) {
 		}
 		return this;
 	}
-
-
+	
+	
 	// would like to have this logic in EventManager, but needs to happen before options are recursively extended
 	var eventSources = options.eventSources || [];
 	delete options.eventSources;
@@ -148,25 +148,25 @@ $.fn.fullCalendar = function(options) {
 		eventSources.push(options.events);
 		delete options.events;
 	}
-
+	
 
 	options = $.extend(true, {},
 		defaults,
 		(options.isRTL || options.isRTL===undefined && defaults.isRTL) ? rtlDefaults : {},
 		options
 	);
-
-
+	
+	
 	this.each(function(i, _element) {
 		var element = $(_element);
 		var calendar = new Calendar(element, options, eventSources);
 		element.data('fullCalendar', calendar); // TODO: look into memory leak implications
 		calendar.render();
 	});
-
-
+	
+	
 	return this;
-
+	
 };
 
 
@@ -177,11 +177,11 @@ function setDefaults(d) {
 
 
 
-
+ 
 function Calendar(element, options, eventSources) {
 	var t = this;
-
-
+	
+	
 	// exports
 	t.options = options;
 	t.render = render;
@@ -206,14 +206,14 @@ function Calendar(element, options, eventSources) {
 	t.getView = getView;
 	t.option = option;
 	t.trigger = trigger;
-
-
+	
+	
 	// imports
 	EventManager.call(t, options, eventSources);
 	var isFetchNeeded = t.isFetchNeeded;
 	var fetchEvents = t.fetchEvents;
-
-
+	
+	
 	// locals
 	var _element = element[0];
 	var header;
@@ -230,16 +230,16 @@ function Calendar(element, options, eventSources) {
 	var date = new Date();
 	var events = [];
 	var _dragElement;
-
-
-
+	
+	
+	
 	/* Main Rendering
 	-----------------------------------------------------------------------------*/
-
-
+	
+	
 	setYMD(date, options.year, options.month, options.date);
-
-
+	
+	
 	function render(inc) {
 		if (!content) {
 			initialRender();
@@ -250,8 +250,8 @@ function Calendar(element, options, eventSources) {
 			renderView(inc);
 		}
 	}
-
-
+	
+	
 	function initialRender() {
 		tm = options.theme ? 'ui' : 'fc';
 		element.addClass('fc');
@@ -275,8 +275,8 @@ function Calendar(element, options, eventSources) {
 			lateRender();
 		}
 	}
-
-
+	
+	
 	// called when we know the calendar couldn't be rendered when it was initialized,
 	// but we think it's ready now
 	function lateRender() {
@@ -286,42 +286,42 @@ function Calendar(element, options, eventSources) {
 			}
 		},0);
 	}
-
-
+	
+	
 	function destroy() {
 		$(window).unbind('resize', windowResize);
 		header.destroy();
 		content.remove();
 		element.removeClass('fc fc-rtl ui-widget');
 	}
-
-
-
+	
+	
+	
 	function elementVisible() {
 		return _element.offsetWidth !== 0;
 	}
-
-
+	
+	
 	function bodyVisible() {
 		return $('body')[0].offsetWidth !== 0;
 	}
-
-
-
+	
+	
+	
 	/* View Rendering
 	-----------------------------------------------------------------------------*/
-
+	
 	// TODO: improve view switching (still weird transition in IE, and FF has whiteout problem)
-
+	
 	function changeView(newViewName) {
 		if (!currentView || newViewName != currentView.name) {
 			ignoreWindowResize++; // because setMinHeight might change the height before render (and subsequently setSize) is reached
 
 			unselect();
-
+			
 			var oldView = currentView;
 			var newViewElement;
-
+				
 			if (oldView) {
 				(oldView.beforeHide || noop)(); // called before changing min-height. if called after, scroll state is reset (in Opera)
 				setMinHeight(content, content.height());
@@ -330,7 +330,7 @@ function Calendar(element, options, eventSources) {
 				setMinHeight(content, 1); // needs to be 1 (not 0) for IE7, or else view dimensions miscalculated
 			}
 			content.css('overflow', 'hidden');
-
+			
 			currentView = viewInstances[newViewName];
 			if (currentView) {
 				currentView.element.show();
@@ -342,39 +342,39 @@ function Calendar(element, options, eventSources) {
 					t // the calendar object
 				);
 			}
-
+			
 			if (oldView) {
 				header.deactivateButton(oldView.name);
 			}
 			header.activateButton(newViewName);
-
+			
 			renderView(); // after height has been set, will make absoluteViewElement's position=relative, then set to null
-
+			
 			content.css('overflow', '');
 			if (oldView) {
 				setMinHeight(content, 1);
 			}
-
+			
 			if (!newViewElement) {
 				(currentView.afterShow || noop)(); // called after setting min-height/overflow, so in final scroll state (for Opera)
 			}
-
+			
 			ignoreWindowResize--;
 		}
 	}
-
-
-
+	
+	
+	
 	function renderView(inc) {
 		if (elementVisible()) {
 			ignoreWindowResize++; // because renderEvents might temporarily change the height before setSize is reached
 
 			unselect();
-
+			
 			if (suggestedViewHeight === undefined) {
 				calcSize();
 			}
-
+			
 			var forceEventRender = false;
 			if (!currentView.start || inc || date < currentView.start || date >= currentView.end) {
 				// view must render an entire new date range (and refetch/render events)
@@ -395,9 +395,9 @@ function Calendar(element, options, eventSources) {
 			currentView.sizeDirty = false;
 			currentView.eventsDirty = false;
 			updateEvents(forceEventRender);
-
+			
 			elementOuterWidth = element.outerWidth();
-
+			
 			header.updateTitle(currentView.title);
 			var today = new Date();
 			if (today >= currentView.start && today < currentView.end) {
@@ -405,18 +405,18 @@ function Calendar(element, options, eventSources) {
 			}else{
 				header.enableButton('today');
 			}
-
+			
 			ignoreWindowResize--;
 			currentView.trigger('viewDisplay', _element);
 		}
 	}
-
-
-
+	
+	
+	
 	/* Resizing
 	-----------------------------------------------------------------------------*/
-
-
+	
+	
 	function updateSize() {
 		markSizesDirty();
 		if (elementVisible()) {
@@ -428,15 +428,15 @@ function Calendar(element, options, eventSources) {
 			currentView.sizeDirty = false;
 		}
 	}
-
-
+	
+	
 	function markSizesDirty() {
 		$.each(viewInstances, function(i, inst) {
 			inst.sizeDirty = true;
 		});
 	}
-
-
+	
+	
 	function calcSize() {
 		if (options.contentHeight) {
 			suggestedViewHeight = options.contentHeight;
@@ -448,8 +448,8 @@ function Calendar(element, options, eventSources) {
 			suggestedViewHeight = Math.round(content.width() / Math.max(options.aspectRatio, .5));
 		}
 	}
-
-
+	
+	
 	function setSize(dateChanged) { // todo: dateChanged?
 		ignoreWindowResize++;
 		currentView.setHeight(suggestedViewHeight, dateChanged);
@@ -460,8 +460,8 @@ function Calendar(element, options, eventSources) {
 		currentView.setWidth(content.width(), dateChanged);
 		ignoreWindowResize--;
 	}
-
-
+	
+	
 	function windowResize() {
 		if (!ignoreWindowResize) {
 			if (currentView.start) { // view has already been rendered
@@ -482,13 +482,13 @@ function Calendar(element, options, eventSources) {
 			}
 		}
 	}
-
-
-
+	
+	
+	
 	/* Event Fetching/Rendering
 	-----------------------------------------------------------------------------*/
-
-
+	
+	
 	// fetches events if necessary, rerenders events if necessary (or if forced)
 	function updateEvents(forceRender) {
 		if (!options.lazyFetching || isFetchNeeded(currentView.visStart, currentView.visEnd)) {
@@ -498,26 +498,26 @@ function Calendar(element, options, eventSources) {
 			rerenderEvents();
 		}
 	}
-
-
+	
+	
 	function refetchEvents() {
 		fetchEvents(currentView.visStart, currentView.visEnd); // will call reportEvents
 	}
-
-
+	
+	
 	// called when event data arrives
 	function reportEvents(_events) {
 		events = _events;
 		rerenderEvents();
 	}
-
-
+	
+	
 	// called when a single event's data has been changed
 	function reportEventChange(eventID) {
 		rerenderEvents(eventID);
 	}
-
-
+	
+	
 	// attempts to rerenderEvents
 	function rerenderEvents(modifiedEventID) {
 		markEventsDirty();
@@ -527,65 +527,65 @@ function Calendar(element, options, eventSources) {
 			currentView.eventsDirty = false;
 		}
 	}
-
-
+	
+	
 	function markEventsDirty() {
 		$.each(viewInstances, function(i, inst) {
 			inst.eventsDirty = true;
 		});
 	}
-
+	
 
 
 	/* Selection
 	-----------------------------------------------------------------------------*/
-
+	
 
 	function select(start, end, allDay) {
 		currentView.select(start, end, allDay===undefined ? true : allDay);
 	}
-
+	
 
 	function unselect() { // safe to be called before renderView
 		if (currentView) {
 			currentView.unselect();
 		}
 	}
-
-
-
+	
+	
+	
 	/* Date
 	-----------------------------------------------------------------------------*/
-
-
+	
+	
 	function prev() {
 		renderView(-1);
 	}
-
-
+	
+	
 	function next() {
 		renderView(1);
 	}
-
-
+	
+	
 	function prevYear() {
 		addYears(date, -1);
 		renderView();
 	}
-
-
+	
+	
 	function nextYear() {
 		addYears(date, 1);
 		renderView();
 	}
-
-
+	
+	
 	function today() {
 		date = new Date();
 		renderView();
 	}
-
-
+	
+	
 	function gotoDate(year, month, dateOfMonth) {
 		if (year instanceof Date) {
 			date = cloneDate(year); // provided 1 argument, a Date
@@ -594,8 +594,8 @@ function Calendar(element, options, eventSources) {
 		}
 		renderView();
 	}
-
-
+	
+	
 	function incrementDate(years, months, days) {
 		if (years !== undefined) {
 			addYears(date, years);
@@ -608,23 +608,23 @@ function Calendar(element, options, eventSources) {
 		}
 		renderView();
 	}
-
-
+	
+	
 	function getDate() {
 		return cloneDate(date);
 	}
-
-
-
+	
+	
+	
 	/* Misc
 	-----------------------------------------------------------------------------*/
-
-
+	
+	
 	function getView() {
 		return currentView;
 	}
-
-
+	
+	
 	function option(name, value) {
 		if (value === undefined) {
 			return options[name];
@@ -634,8 +634,8 @@ function Calendar(element, options, eventSources) {
 			updateSize();
 		}
 	}
-
-
+	
+	
 	function trigger(name, thisObj) {
 		if (options[name]) {
 			return options[name].apply(
@@ -644,12 +644,12 @@ function Calendar(element, options, eventSources) {
 			);
 		}
 	}
-
-
-
+	
+	
+	
 	/* External Dragging
 	------------------------------------------------------------------------*/
-
+	
 	if (options.droppable) {
 		$(document)
 			.bind('dragstart', function(ev, ui) {
@@ -670,14 +670,14 @@ function Calendar(element, options, eventSources) {
 				}
 			});
 	}
-
+	
 
 }
 
 function Header(calendar, options) {
 	var t = this;
-
-
+	
+	
 	// exports
 	t.render = render;
 	t.destroy = destroy;
@@ -686,12 +686,12 @@ function Header(calendar, options) {
 	t.deactivateButton = deactivateButton;
 	t.disableButton = disableButton;
 	t.enableButton = enableButton;
-
-
+	
+	
 	// locals
 	var element = $([]);
 	var tm;
-
+	
 
 
 	function render() {
@@ -708,13 +708,13 @@ function Header(calendar, options) {
 			return element;
 		}
 	}
-
-
+	
+	
 	function destroy() {
 		element.remove();
 	}
-
-
+	
+	
 	function renderSection(position) {
 		var e = $("<td class='fc-header-" + position + "'/>");
 		var buttonStr = options.header[position];
@@ -805,32 +805,32 @@ function Header(calendar, options) {
 		}
 		return e;
 	}
-
-
+	
+	
 	function updateTitle(html) {
 		element.find('h2')
 			.html(html);
 	}
-
-
+	
+	
 	function activateButton(buttonName) {
 		element.find('span.fc-button-' + buttonName)
 			.addClass(tm + '-state-active');
 	}
-
-
+	
+	
 	function deactivateButton(buttonName) {
 		element.find('span.fc-button-' + buttonName)
 			.removeClass(tm + '-state-active');
 	}
-
-
+	
+	
 	function disableButton(buttonName) {
 		element.find('span.fc-button-' + buttonName)
 			.addClass(tm + '-state-disabled');
 	}
-
-
+	
+	
 	function enableButton(buttonName) {
 		element.find('span.fc-button-' + buttonName)
 			.removeClass(tm + '-state-disabled');
@@ -852,8 +852,8 @@ var eventGUID = 1;
 
 function EventManager(options, _sources) {
 	var t = this;
-
-
+	
+	
 	// exports
 	t.isFetchNeeded = isFetchNeeded;
 	t.fetchEvents = fetchEvents;
@@ -864,14 +864,14 @@ function EventManager(options, _sources) {
 	t.removeEvents = removeEvents;
 	t.clientEvents = clientEvents;
 	t.normalizeEvent = normalizeEvent;
-
-
+	
+	
 	// imports
 	var trigger = t.trigger;
 	var getView = t.getView;
 	var reportEvents = t.reportEvents;
-
-
+	
+	
 	// locals
 	var stickySource = { events: [] };
 	var sources = [ stickySource ];
@@ -880,23 +880,23 @@ function EventManager(options, _sources) {
 	var pendingSourceCnt = 0;
 	var loadingLevel = 0;
 	var cache = [];
-
-
+	
+	
 	for (var i=0; i<_sources.length; i++) {
 		_addEventSource(_sources[i]);
 	}
-
-
-
+	
+	
+	
 	/* Fetching
 	-----------------------------------------------------------------------------*/
-
-
+	
+	
 	function isFetchNeeded(start, end) {
 		return !rangeStart || start < rangeStart || end > rangeEnd;
 	}
-
-
+	
+	
 	function fetchEvents(start, end) {
 		rangeStart = start;
 		rangeEnd = end;
@@ -908,8 +908,8 @@ function EventManager(options, _sources) {
 			fetchEventSource(sources[i], fetchID);
 		}
 	}
-
-
+	
+	
 	function fetchEventSource(source, fetchID) {
 		_fetchEventSource(source, function(events) {
 			if (fetchID == currentFetchID) {
@@ -927,8 +927,8 @@ function EventManager(options, _sources) {
 			}
 		});
 	}
-
-
+	
+	
 	function _fetchEventSource(source, callback) {
 		var i;
 		var fetchers = fc.sourceFetchers;
@@ -1000,12 +1000,12 @@ function EventManager(options, _sources) {
 			}
 		}
 	}
-
-
-
+	
+	
+	
 	/* Sources
 	-----------------------------------------------------------------------------*/
-
+	
 
 	function addEventSource(source) {
 		source = _addEventSource(source);
@@ -1014,8 +1014,8 @@ function EventManager(options, _sources) {
 			fetchEventSource(source, currentFetchID); // will eventually call reportEvents
 		}
 	}
-
-
+	
+	
 	function _addEventSource(source) {
 		if ($.isFunction(source) || $.isArray(source)) {
 			source = { events: source };
@@ -1029,7 +1029,7 @@ function EventManager(options, _sources) {
 			return source;
 		}
 	}
-
+	
 
 	function removeEventSource(source) {
 		sources = $.grep(sources, function(src) {
@@ -1041,13 +1041,13 @@ function EventManager(options, _sources) {
 		});
 		reportEvents(cache);
 	}
-
-
-
+	
+	
+	
 	/* Manipulation
 	-----------------------------------------------------------------------------*/
-
-
+	
+	
 	function updateEvent(event) { // update an existing event
 		var i, len = cache.length, e,
 			defaultEventEnd = getView().defaultEventEnd, // getView???
@@ -1083,8 +1083,8 @@ function EventManager(options, _sources) {
 		normalizeEvent(event);
 		reportEvents(cache);
 	}
-
-
+	
+	
 	function renderEvent(event, stick) {
 		normalizeEvent(event);
 		if (!event.source) {
@@ -1096,8 +1096,8 @@ function EventManager(options, _sources) {
 		}
 		reportEvents(cache);
 	}
-
-
+	
+	
 	function removeEvents(filter) {
 		if (!filter) { // remove all
 			cache = [];
@@ -1124,8 +1124,8 @@ function EventManager(options, _sources) {
 		}
 		reportEvents(cache);
 	}
-
-
+	
+	
 	function clientEvents(filter) {
 		if ($.isFunction(filter)) {
 			return $.grep(cache, filter);
@@ -1138,32 +1138,32 @@ function EventManager(options, _sources) {
 		}
 		return cache; // else, return all
 	}
-
-
-
+	
+	
+	
 	/* Loading State
 	-----------------------------------------------------------------------------*/
-
-
+	
+	
 	function pushLoading() {
 		if (!loadingLevel++) {
 			trigger('loading', null, true);
 		}
 	}
-
-
+	
+	
 	function popLoading() {
 		if (!--loadingLevel) {
 			trigger('loading', null, false);
 		}
 	}
-
-
-
+	
+	
+	
 	/* Event Normalization
 	-----------------------------------------------------------------------------*/
-
-
+	
+	
 	function normalizeEvent(event) {
 		var source = event.source || {};
 		var ignoreTimezone = firstDefined(source.ignoreTimezone, options.ignoreTimezone);
@@ -1192,13 +1192,13 @@ function EventManager(options, _sources) {
 		}
 		// TODO: if there is no start date, return false to indicate an invalid event
 	}
-
-
-
+	
+	
+	
 	/* Utils
 	------------------------------------------------------------------------------*/
-
-
+	
+	
 	function normalizeSource(source) {
 		if (source.className) {
 			// TODO: repeat code, same code for event classNames
@@ -1213,13 +1213,13 @@ function EventManager(options, _sources) {
 			normalizers[i](source);
 		}
 	}
-
-
+	
+	
 	function isSourcesEqual(source1, source2) {
 		return source1 && source2 && getSourcePrimitive(source1) == getSourcePrimitive(source2);
 	}
-
-
+	
+	
 	function getSourcePrimitive(source) {
 		return ((typeof source == 'object') ? (source.events || source.url) : '') || source;
 	}
@@ -1245,7 +1245,7 @@ var dayIDs = ['sun', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat'],
 	DAY_MS = 86400000,
 	HOUR_MS = 3600000,
 	MINUTE_MS = 60000;
-
+	
 
 function addYears(d, n, keepTime) {
 	d.setFullYear(d.getFullYear() + n);
@@ -1308,7 +1308,7 @@ function addMinutes(d, n) {
 function clearTime(d) {
 	d.setHours(0);
 	d.setMinutes(0);
-	d.setSeconds(0);
+	d.setSeconds(0); 
 	d.setMilliseconds(0);
 	return d;
 }
@@ -1658,7 +1658,7 @@ function sliceSegs(events, visEventEnds, start, end) {
 				msLength: segEnd - segStart
 			});
 		}
-	}
+	} 
 	return segs.sort(segCmp);
 }
 
@@ -1961,20 +1961,20 @@ fcViews.month = MonthView;
 
 function MonthView(element, calendar) {
 	var t = this;
-
-
+	
+	
 	// exports
 	t.render = render;
-
-
+	
+	
 	// imports
 	BasicView.call(t, element, calendar, 'month');
 	var opt = t.opt;
 	var renderBasic = t.renderBasic;
 	var formatDate = calendar.formatDate;
-
-
-
+	
+	
+	
 	function render(date, delta) {
 		if (delta) {
 			addMonths(date, delta);
@@ -2005,28 +2005,28 @@ function MonthView(element, calendar) {
 		t.visEnd = visEnd;
 		renderBasic(6, rowCnt, nwe ? 5 : 7, true);
 	}
-
-
+	
+	
 }
 
 fcViews.basicWeek = BasicWeekView;
 
 function BasicWeekView(element, calendar) {
 	var t = this;
-
-
+	
+	
 	// exports
 	t.render = render;
-
-
+	
+	
 	// imports
 	BasicView.call(t, element, calendar, 'basicWeek');
 	var opt = t.opt;
 	var renderBasic = t.renderBasic;
 	var formatDates = calendar.formatDates;
-
-
-
+	
+	
+	
 	function render(date, delta) {
 		if (delta) {
 			addDays(date, delta * 7);
@@ -2051,8 +2051,8 @@ function BasicWeekView(element, calendar) {
 		t.visEnd = visEnd;
 		renderBasic(1, 1, weekends ? 7 : 5, false);
 	}
-
-
+	
+	
 }
 
 fcViews.basicDay = BasicDayView;
@@ -2062,20 +2062,20 @@ fcViews.basicDay = BasicDayView;
 
 function BasicDayView(element, calendar) {
 	var t = this;
-
-
+	
+	
 	// exports
 	t.render = render;
-
-
+	
+	
 	// imports
 	BasicView.call(t, element, calendar, 'basicDay');
 	var opt = t.opt;
 	var renderBasic = t.renderBasic;
 	var formatDate = calendar.formatDate;
-
-
-
+	
+	
+	
 	function render(date, delta) {
 		if (delta) {
 			addDays(date, delta);
@@ -2088,8 +2088,8 @@ function BasicDayView(element, calendar) {
 		t.end = t.visEnd = addDays(cloneDate(t.start), 1);
 		renderBasic(1, 1, 1, false);
 	}
-
-
+	
+	
 }
 
 setDefaults({
@@ -2099,8 +2099,8 @@ setDefaults({
 
 function BasicView(element, calendar, viewName) {
 	var t = this;
-
-
+	
+	
 	// exports
 	t.renderBasic = renderBasic;
 	t.setHeight = setHeight;
@@ -2126,8 +2126,8 @@ function BasicView(element, calendar, viewName) {
 	t.getColCnt = function() { return colCnt };
 	t.getColWidth = function() { return colWidth };
 	t.getDaySegmentContainer = function() { return daySegmentContainer };
-
-
+	
+	
 	// imports
 	View.call(t, element, calendar, viewName);
 	OverlayManager.call(t);
@@ -2140,10 +2140,10 @@ function BasicView(element, calendar, viewName) {
 	var clearOverlays = t.clearOverlays;
 	var daySelectionMousedown = t.daySelectionMousedown;
 	var formatDate = calendar.formatDate;
-
-
+	
+	
 	// locals
-
+	
 	var head;
 	var headCells;
 	var body;
@@ -2152,31 +2152,31 @@ function BasicView(element, calendar, viewName) {
 	var bodyFirstCells;
 	var bodyCellTopInners;
 	var daySegmentContainer;
-
+	
 	var viewWidth;
 	var viewHeight;
 	var colWidth;
-
+	
 	var rowCnt, colCnt;
 	var coordinateGrid;
 	var hoverListener;
 	var colContentPositions;
-
+	
 	var rtl, dis, dit;
 	var firstDay;
 	var nwe;
 	var tm;
 	var colFormat;
-
-
-
+	
+	
+	
 	/* Rendering
 	------------------------------------------------------------*/
-
-
+	
+	
 	disableTextSelection(element.addClass('fc-grid'));
-
-
+	
+	
 	function renderBasic(maxr, r, c, showNumbers) {
 		rowCnt = r;
 		colCnt = c;
@@ -2189,9 +2189,9 @@ function BasicView(element, calendar, viewName) {
 		}
 		updateCells(firstTime);
 	}
-
-
-
+	
+	
+	
 	function updateOptions() {
 		rtl = opt('isRTL');
 		if (rtl) {
@@ -2206,16 +2206,16 @@ function BasicView(element, calendar, viewName) {
 		tm = opt('theme') ? 'ui' : 'fc';
 		colFormat = opt('columnFormat');
 	}
-
-
-
+	
+	
+	
 	function buildSkeleton(maxRowCnt, showNumbers) {
 		var s;
 		var headerClass = tm + "-widget-header";
 		var contentClass = tm + "-widget-content";
 		var i, j;
 		var table;
-
+		
 		s =
 			"<table class='fc-border-separate' style='width:100%' cellspacing='0'>" +
 			"<thead>" +
@@ -2252,7 +2252,7 @@ function BasicView(element, calendar, viewName) {
 			"</tbody>" +
 			"</table>";
 		table = $(s).appendTo(element);
-
+		
 		head = table.find('thead');
 		headCells = head.find('th');
 		body = table.find('tbody');
@@ -2260,20 +2260,20 @@ function BasicView(element, calendar, viewName) {
 		bodyCells = body.find('td');
 		bodyFirstCells = bodyCells.filter(':first-child');
 		bodyCellTopInners = bodyRows.eq(0).find('div.fc-day-content div');
-
+		
 		markFirstLast(head.add(head.find('tr'))); // marks first+last tr/th's
 		markFirstLast(bodyRows); // marks first+last td's
 		bodyRows.eq(0).addClass('fc-first'); // fc-last is done in updateCells
-
+		
 		dayBind(bodyCells);
-
+		
 		daySegmentContainer =
 			$("<div style='position:absolute;z-index:8;top:0;left:0'/>")
 				.appendTo(element);
 	}
-
-
-
+	
+	
+	
 	function updateCells(firstTime) {
 		var dowDirty = firstTime || rowCnt == 1; // could the cells' day-of-weeks need updating?
 		var month = t.start.getMonth();
@@ -2281,7 +2281,7 @@ function BasicView(element, calendar, viewName) {
 		var cell;
 		var date;
 		var row;
-
+	
 		if (dowDirty) {
 			headCells.each(function(i, _cell) {
 				cell = $(_cell);
@@ -2290,7 +2290,7 @@ function BasicView(element, calendar, viewName) {
 				setDayID(cell, date);
 			});
 		}
-
+		
 		bodyCells.each(function(i, _cell) {
 			cell = $(_cell);
 			date = indexDate(i);
@@ -2309,7 +2309,7 @@ function BasicView(element, calendar, viewName) {
 				setDayID(cell, date);
 			}
 		});
-
+		
 		bodyRows.each(function(i, _row) {
 			row = $(_row);
 			if (i < rowCnt) {
@@ -2324,24 +2324,24 @@ function BasicView(element, calendar, viewName) {
 			}
 		});
 	}
-
-
-
+	
+	
+	
 	function setHeight(height) {
 		viewHeight = height;
-
+		
 		var bodyHeight = viewHeight - head.height();
 		var rowHeight;
 		var rowHeightLast;
 		var cell;
-
+			
 		if (opt('weekMode') == 'variable') {
 			rowHeight = rowHeightLast = Math.floor(bodyHeight / (rowCnt==1 ? 2 : 6));
 		}else{
 			rowHeight = Math.floor(bodyHeight / rowCnt);
 			rowHeightLast = bodyHeight - rowHeight * (rowCnt-1);
 		}
-
+		
 		bodyFirstCells.each(function(i, _cell) {
 			if (i < rowCnt) {
 				cell = $(_cell);
@@ -2351,29 +2351,29 @@ function BasicView(element, calendar, viewName) {
 				);
 			}
 		});
-
+		
 	}
-
-
+	
+	
 	function setWidth(width) {
 		viewWidth = width;
 		colContentPositions.clear();
 		colWidth = Math.floor(viewWidth / colCnt);
 		setOuterWidth(headCells.slice(0, -1), colWidth);
 	}
-
-
-
+	
+	
+	
 	/* Day clicking and binding
 	-----------------------------------------------------------*/
-
-
+	
+	
 	function dayBind(days) {
 		days.click(dayClick)
 			.mousedown(daySelectionMousedown);
 	}
-
-
+	
+	
 	function dayClick(ev) {
 		if (!opt('selectable')) { // if selectable, SelectionManager will worry about dayClick
 			var index = parseInt(this.className.match(/fc\-day(\d+)/)[1]); // TODO: maybe use .data
@@ -2381,13 +2381,13 @@ function BasicView(element, calendar, viewName) {
 			trigger('dayClick', this, date, true, ev);
 		}
 	}
-
-
-
+	
+	
+	
 	/* Semi-transparent Overlay Helpers
 	------------------------------------------------------*/
-
-
+	
+	
 	function renderDayOverlay(overlayStart, overlayEnd, refreshCoordinateGrid) { // overlayEnd is exclusive
 		if (refreshCoordinateGrid) {
 			coordinateGrid.build();
@@ -2414,46 +2414,46 @@ function BasicView(element, calendar, viewName) {
 			addDays(rowEnd, 7);
 		}
 	}
-
-
+	
+	
 	function renderCellOverlay(row0, col0, row1, col1) { // row1,col1 is inclusive
 		var rect = coordinateGrid.rect(row0, col0, row1, col1, element);
 		return renderOverlay(rect, element);
 	}
-
-
-
+	
+	
+	
 	/* Selection
 	-----------------------------------------------------------------------*/
-
-
+	
+	
 	function defaultSelectionEnd(startDate, allDay) {
 		return cloneDate(startDate);
 	}
-
-
+	
+	
 	function renderSelection(startDate, endDate, allDay) {
 		renderDayOverlay(startDate, addDays(cloneDate(endDate), 1), true); // rebuild every time???
 	}
-
-
+	
+	
 	function clearSelection() {
 		clearOverlays();
 	}
-
-
+	
+	
 	function reportDayClick(date, allDay, ev) {
 		var cell = dateCell(date);
 		var _element = bodyCells[cell.row*colCnt + cell.col];
 		trigger('dayClick', _element, date, allDay, ev);
 	}
-
-
-
+	
+	
+	
 	/* External Dragging
 	-----------------------------------------------------------------------*/
-
-
+	
+	
 	function dragStart(_dragElement, ev, ui) {
 		hoverListener.start(function(cell) {
 			clearOverlays();
@@ -2462,8 +2462,8 @@ function BasicView(element, calendar, viewName) {
 			}
 		}, ev);
 	}
-
-
+	
+	
 	function dragStop(_dragElement, ev, ui) {
 		var cell = hoverListener.stop();
 		clearOverlays();
@@ -2472,18 +2472,18 @@ function BasicView(element, calendar, viewName) {
 			trigger('drop', _dragElement, d, true, ev, ui);
 		}
 	}
-
-
-
+	
+	
+	
 	/* Utilities
 	--------------------------------------------------------*/
-
-
+	
+	
 	function defaultEventEnd(event) {
 		return cloneDate(event.start);
 	}
-
-
+	
+	
 	coordinateGrid = new CoordinateGrid(function(rows, cols) {
 		var e, n, p;
 		headCells.each(function(i, _e) {
@@ -2509,85 +2509,85 @@ function BasicView(element, calendar, viewName) {
 		});
 		p[1] = n + e.outerHeight();
 	});
-
-
+	
+	
 	hoverListener = new HoverListener(coordinateGrid);
-
-
+	
+	
 	colContentPositions = new HorizontalPositionCache(function(col) {
 		return bodyCellTopInners.eq(col);
 	});
-
-
+	
+	
 	function colContentLeft(col) {
 		return colContentPositions.left(col);
 	}
-
-
+	
+	
 	function colContentRight(col) {
 		return colContentPositions.right(col);
 	}
-
-
-
-
+	
+	
+	
+	
 	function dateCell(date) {
 		return {
 			row: Math.floor(dayDiff(date, t.visStart) / 7),
 			col: dayOfWeekCol(date.getDay())
 		};
 	}
-
-
+	
+	
 	function cellDate(cell) {
 		return _cellDate(cell.row, cell.col);
 	}
-
-
+	
+	
 	function _cellDate(row, col) {
 		return addDays(cloneDate(t.visStart), row*7 + col*dis+dit);
 		// what about weekends in middle of week?
 	}
-
-
+	
+	
 	function indexDate(index) {
 		return _cellDate(Math.floor(index/colCnt), index%colCnt);
 	}
-
-
+	
+	
 	function dayOfWeekCol(dayOfWeek) {
 		return ((dayOfWeek - Math.max(firstDay, nwe) + colCnt) % colCnt) * dis + dit;
 	}
-
-
-
-
+	
+	
+	
+	
 	function allDayRow(i) {
 		return bodyRows.eq(i);
 	}
-
-
+	
+	
 	function allDayBounds(i) {
 		return {
 			left: 0,
 			right: viewWidth
 		};
 	}
-
-
+	
+	
 }
 
 function BasicEventRenderer() {
 	var t = this;
-
-
+	
+	
 	// exports
 	t.renderEvents = renderEvents;
 	t.compileDaySegs = compileSegs; // for DayEventRenderer
 	t.clearEvents = clearEvents;
 	t.bindDaySeg = bindDaySeg;
-
-
+	
+	
 	// imports
 	DayEventRenderer.call(t);
 	var opt = t.opt;
@@ -2609,25 +2609,25 @@ function BasicEventRenderer() {
 	var getColCnt = t.getColCnt;
 	var renderDaySegs = t.renderDaySegs;
 	var resizableDayEvent = t.resizableDayEvent;
-
-
-
+	
+	
+	
 	/* Rendering
 	--------------------------------------------------------------------*/
-
-
+	
+	
 	function renderEvents(events, modifiedEventId) {
 		reportEvents(events);
 		renderDaySegs(compileSegs(events), modifiedEventId);
 	}
-
-
+	
+	
 	function clearEvents() {
 		reportEventClear();
 		getDaySegmentContainer().empty();
 	}
-
-
+	
+	
 	function compileSegs(events) {
 		var rowCnt = getRowCnt(),
 			colCnt = getColCnt(),
@@ -2654,8 +2654,8 @@ function BasicEventRenderer() {
 		}
 		return segs;
 	}
-
-
+	
+	
 	function bindDaySeg(event, eventElement, seg) {
 		if (isEventDraggable(event)) {
 			draggableDayEvent(event, eventElement);
@@ -2666,13 +2666,13 @@ function BasicEventRenderer() {
 		eventElementHandlers(event, eventElement);
 			// needs to be after, because resizableDayEvent might stopImmediatePropagation on click
 	}
-
-
-
+	
+	
+	
 	/* Dragging
 	----------------------------------------------------------------------------*/
-
-
+	
+	
 	function draggableDayEvent(event, eventElement) {
 		var hoverListener = getHoverListener();
 		var dayDelta;
@@ -2722,20 +2722,20 @@ fcViews.agendaWeek = AgendaWeekView;
 
 function AgendaWeekView(element, calendar) {
 	var t = this;
-
-
+	
+	
 	// exports
 	t.render = render;
-
-
+	
+	
 	// imports
 	AgendaView.call(t, element, calendar, 'agendaWeek');
 	var opt = t.opt;
 	var renderAgenda = t.renderAgenda;
 	var formatDates = calendar.formatDates;
-
-
-
+	
+	
+	
 	function render(date, delta) {
 		if (delta) {
 			addDays(date, delta * 7);
@@ -2760,7 +2760,7 @@ function AgendaWeekView(element, calendar) {
 		t.visEnd = visEnd;
 		renderAgenda(weekends ? 7 : 5);
 	}
-
+	
 
 }
 
@@ -2768,20 +2768,20 @@ fcViews.agendaDay = AgendaDayView;
 
 function AgendaDayView(element, calendar) {
 	var t = this;
-
-
+	
+	
 	// exports
 	t.render = render;
-
-
+	
+	
 	// imports
 	AgendaView.call(t, element, calendar, 'agendaDay');
 	var opt = t.opt;
 	var renderAgenda = t.renderAgenda;
 	var formatDate = calendar.formatDate;
-
-
-
+	
+	
+	
 	function render(date, delta) {
 		if (delta) {
 			addDays(date, delta);
@@ -2796,7 +2796,7 @@ function AgendaDayView(element, calendar) {
 		t.end = t.visEnd = end;
 		renderAgenda(1);
 	}
-
+	
 
 }
 
@@ -2824,8 +2824,8 @@ setDefaults({
 
 function AgendaView(element, calendar, viewName) {
 	var t = this;
-
-
+	
+	
 	// exports
 	t.renderAgenda = renderAgenda;
 	t.setWidth = setWidth;
@@ -2859,8 +2859,8 @@ function AgendaView(element, calendar, viewName) {
 	t.reportDayClick = reportDayClick; // selection mousedown hack
 	t.dragStart = dragStart;
 	t.dragStop = dragStop;
-
-
+	
+	
 	// imports
 	View.call(t, element, calendar, viewName);
 	OverlayManager.call(t);
@@ -2876,10 +2876,10 @@ function AgendaView(element, calendar, viewName) {
 	var daySelectionMousedown = t.daySelectionMousedown;
 	var slotSegHtml = t.slotSegHtml;
 	var formatDate = calendar.formatDate;
-
-
+	
+	
 	// locals
-
+	
 	var dayTable;
 	var dayHead;
 	var dayHeadCells;
@@ -2900,7 +2900,7 @@ function AgendaView(element, calendar, viewName) {
 	var axisFirstCells;
 	var gutterCells;
 	var selectionHelper;
-
+	
 	var viewWidth;
 	var viewHeight;
 	var axisWidth;
@@ -2908,30 +2908,30 @@ function AgendaView(element, calendar, viewName) {
 	var gutterWidth;
 	var slotHeight; // TODO: what if slotHeight changes? (see issue 650)
 	var savedScrollTop;
-
+	
 	var colCnt;
 	var slotCnt;
 	var coordinateGrid;
 	var hoverListener;
 	var colContentPositions;
 	var slotTopCache = {};
-
+	
 	var tm;
 	var firstDay;
 	var nwe;            // no weekends (int)
 	var rtl, dis, dit;  // day index sign / translate
 	var minMinute, maxMinute;
 	var colFormat;
+	
 
-
-
+	
 	/* Rendering
 	-----------------------------------------------------------------------------*/
-
-
+	
+	
 	disableTextSelection(element.addClass('fc-agenda'));
-
-
+	
+	
 	function renderAgenda(c) {
 		colCnt = c;
 		updateOptions();
@@ -2942,9 +2942,9 @@ function AgendaView(element, calendar, viewName) {
 		}
 		updateCells();
 	}
-
-
-
+	
+	
+	
 	function updateOptions() {
 		tm = opt('theme') ? 'ui' : 'fc';
 		nwe = opt('weekends') ? 0 : 1;
@@ -2960,9 +2960,9 @@ function AgendaView(element, calendar, viewName) {
 		maxMinute = parseTime(opt('maxTime'));
 		colFormat = opt('columnFormat');
 	}
-
-
-
+	
+	
+	
 	function buildSkeleton() {
 		var headerClass = tm + "-widget-header";
 		var contentClass = tm + "-widget-content";
@@ -2972,7 +2972,7 @@ function AgendaView(element, calendar, viewName) {
 		var maxd;
 		var minutes;
 		var slotNormal = opt('slotMinutes') % 15 == 0;
-
+		
 		s =
 			"<table style='width:100%' class='fc-agenda-days fc-border-separate' cellspacing='0'>" +
 			"<thead>" +
@@ -3012,23 +3012,23 @@ function AgendaView(element, calendar, viewName) {
 		dayBodyCellInners = dayBodyCells.find('div.fc-day-content div');
 		dayBodyFirstCell = dayBodyCells.eq(0);
 		dayBodyFirstCellStretcher = dayBodyFirstCell.find('> div');
-
+		
 		markFirstLast(dayHead.add(dayHead.find('tr')));
 		markFirstLast(dayBody.add(dayBody.find('tr')));
-
+		
 		axisFirstCells = dayHead.find('th:first');
 		gutterCells = dayTable.find('.fc-agenda-gutter');
-
+		
 		slotLayer =
 			$("<div style='position:absolute;z-index:2;left:0;width:100%'/>")
 				.appendTo(element);
-
+				
 		if (opt('allDaySlot')) {
-
+		
 			daySegmentContainer =
 				$("<div style='position:absolute;z-index:8;top:0;left:0'/>")
 					.appendTo(slotLayer);
-
+		
 			s =
 				"<table style='width:100%' class='fc-agenda-allday' cellspacing='0'>" +
 				"<tr>" +
@@ -3041,36 +3041,36 @@ function AgendaView(element, calendar, viewName) {
 				"</table>";
 			allDayTable = $(s).appendTo(slotLayer);
 			allDayRow = allDayTable.find('tr');
-
+			
 			dayBind(allDayRow.find('td'));
-
+			
 			axisFirstCells = axisFirstCells.add(allDayTable.find('th:first'));
 			gutterCells = gutterCells.add(allDayTable.find('th.fc-agenda-gutter'));
-
+			
 			slotLayer.append(
 				"<div class='fc-agenda-divider " + headerClass + "'>" +
 				"<div class='fc-agenda-divider-inner'/>" +
 				"</div>"
 			);
-
+			
 		}else{
-
+		
 			daySegmentContainer = $([]); // in jQuery 1.4, we can just do $()
-
+		
 		}
-
+		
 		slotScroller =
 			$("<div style='position:absolute;width:100%;overflow-x:hidden;overflow-y:auto'/>")
 				.appendTo(slotLayer);
-
+				
 		slotContent =
 			$("<div style='position:relative;width:100%;overflow:hidden'/>")
 				.appendTo(slotScroller);
-
+				
 		slotSegmentContainer =
 			$("<div style='position:absolute;z-index:8;top:0;left:0'/>")
 				.appendTo(slotContent);
-
+		
 		s =
 			"<table class='fc-agenda-slots' style='width:100%' cellspacing='0'>" +
 			"<tbody>";
@@ -3097,14 +3097,14 @@ function AgendaView(element, calendar, viewName) {
 			"</table>";
 		slotTable = $(s).appendTo(slotContent);
 		slotTableFirstInner = slotTable.find('div:first');
-
+		
 		slotBind(slotTable.find('td'));
-
+		
 		axisFirstCells = axisFirstCells.add(slotTable.find('th:first'));
 	}
-
-
-
+	
+	
+	
 	function updateCells() {
 		var i;
 		var headCell;
@@ -3124,43 +3124,43 @@ function AgendaView(element, calendar, viewName) {
 			setDayID(headCell.add(bodyCell), date);
 		}
 	}
-
-
-
+	
+	
+	
 	function setHeight(height, dateChanged) {
 		if (height === undefined) {
 			height = viewHeight;
 		}
 		viewHeight = height;
 		slotTopCache = {};
-
+	
 		var headHeight = dayBody.position().top;
 		var allDayHeight = slotScroller.position().top; // including divider
 		var bodyHeight = Math.min( // total body height, including borders
 			height - headHeight,   // when scrollbars
 			slotTable.height() + allDayHeight + 1 // when no scrollbars. +1 for bottom border
 		);
-
+		
 		dayBodyFirstCellStretcher
 			.height(bodyHeight - vsides(dayBodyFirstCell));
-
+		
 		slotLayer.css('top', headHeight);
-
+		
 		slotScroller.height(bodyHeight - allDayHeight - 1);
-
+		
 		slotHeight = slotTableFirstInner.height() + 1; // +1 for border
-
+		
 		if (dateChanged) {
 			resetScroll();
 		}
 	}
-
-
-
+	
+	
+	
 	function setWidth(width) {
 		viewWidth = width;
 		colContentPositions.clear();
-
+		
 		axisWidth = 0;
 		setOuterWidth(
 			axisFirstCells
@@ -3170,10 +3170,10 @@ function AgendaView(element, calendar, viewName) {
 				}),
 			axisWidth
 		);
-
+		
 		var slotTableWidth = slotScroller[0].clientWidth; // needs to be done after axisWidth (for IE7)
 		//slotTable.width(slotTableWidth);
-
+		
 		gutterWidth = slotScroller.width() - slotTableWidth;
 		if (gutterWidth) {
 			setOuterWidth(gutterCells, gutterWidth);
@@ -3187,11 +3187,11 @@ function AgendaView(element, calendar, viewName) {
 				.prev()
 				.addClass('fc-last');
 		}
-
+		
 		colWidth = Math.floor((slotTableWidth - axisWidth) / colCnt);
 		setOuterWidth(dayHeadCells.slice(0, -1), colWidth);
 	}
-
+	
 
 
 	function resetScroll() {
@@ -3205,22 +3205,22 @@ function AgendaView(element, calendar, viewName) {
 		scroll();
 		setTimeout(scroll, 0); // overrides any previous scroll state made by the browser
 	}
-
-
+	
+	
 	function beforeHide() {
 		savedScrollTop = slotScroller.scrollTop();
 	}
-
-
+	
+	
 	function afterShow() {
 		slotScroller.scrollTop(savedScrollTop);
 	}
-
-
-
+	
+	
+	
 	/* Slot/Day clicking and binding
 	-----------------------------------------------------------------------*/
-
+	
 
 	function dayBind(cells) {
 		cells.click(slotClick)
@@ -3232,8 +3232,8 @@ function AgendaView(element, calendar, viewName) {
 		cells.click(slotClick)
 			.mousedown(slotSelectionMousedown);
 	}
-
-
+	
+	
 	function slotClick(ev) {
 		if (!opt('selectable')) { // if selectable, SelectionManager will worry about dayClick
 			var col = Math.min(colCnt-1, Math.floor((ev.pageX - dayTable.offset().left - axisWidth) / colWidth));
@@ -3250,12 +3250,12 @@ function AgendaView(element, calendar, viewName) {
 			}
 		}
 	}
-
-
-
+	
+	
+	
 	/* Semi-transparent Overlay Helpers
 	-----------------------------------------------------*/
-
+	
 
 	function renderDayOverlay(startDate, endDate, refreshCoordinateGrid) { // endDate is exclusive
 		if (refreshCoordinateGrid) {
@@ -3278,13 +3278,13 @@ function AgendaView(element, calendar, viewName) {
 			);
 		}
 	}
-
-
+	
+	
 	function renderCellOverlay(row0, col0, row1, col1) { // only for all-day?
 		var rect = coordinateGrid.rect(row0, col0, row1, col1, slotLayer);
 		return renderOverlay(rect, slotLayer);
 	}
-
+	
 
 	function renderSlotOverlay(overlayStart, overlayEnd) {
 		var dayStart = cloneDate(t.visStart);
@@ -3307,13 +3307,13 @@ function AgendaView(element, calendar, viewName) {
 			addDays(dayEnd, 1);
 		}
 	}
-
-
-
+	
+	
+	
 	/* Coordinate Utilities
 	-----------------------------------------------------------------------------*/
-
-
+	
+	
 	coordinateGrid = new CoordinateGrid(function(rows, cols) {
 		var e, n, p;
 		dayHeadCells.each(function(i, _e) {
@@ -3344,36 +3344,36 @@ function AgendaView(element, calendar, viewName) {
 			]);
 		}
 	});
-
-
+	
+	
 	hoverListener = new HoverListener(coordinateGrid);
-
-
+	
+	
 	colContentPositions = new HorizontalPositionCache(function(col) {
 		return dayBodyCellInners.eq(col);
 	});
-
-
+	
+	
 	function colContentLeft(col) {
 		return colContentPositions.left(col);
 	}
-
-
+	
+	
 	function colContentRight(col) {
 		return colContentPositions.right(col);
 	}
-
-
-
-
+	
+	
+	
+	
 	function dateCell(date) { // "cell" terminology is now confusing
 		return {
 			row: Math.floor(dayDiff(date, t.visStart) / 7),
 			col: dayOfWeekCol(date.getDay())
 		};
 	}
-
-
+	
+	
 	function cellDate(cell) {
 		var d = colDate(cell.col);
 		var slotIndex = cell.row;
@@ -3385,25 +3385,25 @@ function AgendaView(element, calendar, viewName) {
 		}
 		return d;
 	}
-
-
+	
+	
 	function colDate(col) { // returns dates with 00:00:00
 		return addDays(cloneDate(t.visStart), col*dis+dit);
 	}
-
-
+	
+	
 	function cellIsAllDay(cell) {
 		return opt('allDaySlot') && !cell.row;
 	}
-
-
+	
+	
 	function dayOfWeekCol(dayOfWeek) {
 		return ((dayOfWeek - Math.max(firstDay, nwe) + colCnt) % colCnt)*dis+dit;
 	}
-
-
-
-
+	
+	
+	
+	
 	// get the Y coordinate of the given time on the given day (both Date objects)
 	function timePosition(day, time) { // both date objects. day holds 00:00 of current day
 		day = cloneDate(day, true);
@@ -3424,21 +3424,21 @@ function AgendaView(element, calendar, viewName) {
 			slotTop - 1 + slotHeight * ((minutes % slotMinutes) / slotMinutes)
 		));
 	}
-
-
+	
+	
 	function allDayBounds() {
 		return {
 			left: axisWidth,
 			right: viewWidth - gutterWidth
 		}
 	}
-
-
+	
+	
 	function getAllDayRow(index) {
 		return allDayRow;
 	}
-
-
+	
+	
 	function defaultEventEnd(event) {
 		var start = cloneDate(event.start);
 		if (event.allDay) {
@@ -3446,21 +3446,21 @@ function AgendaView(element, calendar, viewName) {
 		}
 		return addMinutes(start, opt('defaultEventMinutes'));
 	}
-
-
-
+	
+	
+	
 	/* Selection
 	---------------------------------------------------------------------------------*/
-
-
+	
+	
 	function defaultSelectionEnd(startDate, allDay) {
 		if (allDay) {
 			return cloneDate(startDate);
 		}
 		return addMinutes(cloneDate(startDate), opt('slotMinutes'));
 	}
-
-
+	
+	
 	function renderSelection(startDate, endDate, allDay) { // only for all-day
 		if (allDay) {
 			if (opt('allDaySlot')) {
@@ -3470,8 +3470,8 @@ function AgendaView(element, calendar, viewName) {
 			renderSlotSelection(startDate, endDate);
 		}
 	}
-
-
+	
+	
 	function renderSlotSelection(startDate, endDate) {
 		var helperOption = opt('selectHelper');
 		coordinateGrid.build();
@@ -3522,8 +3522,8 @@ function AgendaView(element, calendar, viewName) {
 			renderSlotOverlay(startDate, endDate);
 		}
 	}
-
-
+	
+	
 	function clearSelection() {
 		clearOverlays();
 		if (selectionHelper) {
@@ -3531,8 +3531,8 @@ function AgendaView(element, calendar, viewName) {
 			selectionHelper = null;
 		}
 	}
-
-
+	
+	
 	function slotSelectionMousedown(ev) {
 		if (ev.which == 1 && opt('selectable')) { // ev.which==1 means left mouse button
 			unselect(ev);
@@ -3564,18 +3564,18 @@ function AgendaView(element, calendar, viewName) {
 			});
 		}
 	}
-
-
+	
+	
 	function reportDayClick(date, allDay, ev) {
 		trigger('dayClick', dayBodyCells[dayOfWeekCol(date.getDay())], date, allDay, ev);
 	}
-
-
-
+	
+	
+	
 	/* External Dragging
 	--------------------------------------------------------------------------------*/
-
-
+	
+	
 	function dragStart(_dragElement, ev, ui) {
 		hoverListener.start(function(cell) {
 			clearOverlays();
@@ -3590,8 +3590,8 @@ function AgendaView(element, calendar, viewName) {
 			}
 		}, ev);
 	}
-
-
+	
+	
 	function dragStop(_dragElement, ev, ui) {
 		var cell = hoverListener.stop();
 		clearOverlays();
@@ -3605,16 +3605,16 @@ function AgendaView(element, calendar, viewName) {
 
 function AgendaEventRenderer() {
 	var t = this;
-
-
+	
+	
 	// exports
 	t.renderEvents = renderEvents;
 	t.compileDaySegs = compileDaySegs; // for DayEventRenderer
 	t.clearEvents = clearEvents;
 	t.slotSegHtml = slotSegHtml;
 	t.bindDaySeg = bindDaySeg;
-
-
+	
+	
 	// imports
 	DayEventRenderer.call(t);
 	var opt = t.opt;
@@ -3651,12 +3651,12 @@ function AgendaEventRenderer() {
 	var calendar = t.calendar;
 	var formatDate = calendar.formatDate;
 	var formatDates = calendar.formatDates;
-
-
-
+	
+	
+	
 	/* Rendering
 	----------------------------------------------------------------------------*/
-
+	
 
 	function renderEvents(events, modifiedEventId) {
 		reportEvents(events);
@@ -3676,15 +3676,15 @@ function AgendaEventRenderer() {
 		}
 		renderSlotSegs(compileSlotSegs(slotEvents), modifiedEventId);
 	}
-
-
+	
+	
 	function clearEvents() {
 		reportEventClear();
 		getDaySegmentContainer().empty();
 		getSlotSegmentContainer().empty();
 	}
-
-
+	
+	
 	function compileDaySegs(events) {
 		var levels = stackSegs(sliceSegs(events, $.map(events, exclEndDay), t.visStart, t.visEnd)),
 			i, levelCnt=levels.length, level,
@@ -3701,8 +3701,8 @@ function AgendaEventRenderer() {
 		}
 		return segs;
 	}
-
-
+	
+	
 	function compileSlotSegs(events) {
 		var colCnt = getColCnt(),
 			minMinute = getMinMinute(),
@@ -3729,8 +3729,8 @@ function AgendaEventRenderer() {
 		}
 		return segs;
 	}
-
-
+	
+	
 	function slotEventEnd(event) {
 		if (event.end) {
 			return cloneDate(event.end);
@@ -3738,12 +3738,12 @@ function AgendaEventRenderer() {
 			return addMinutes(cloneDate(event.start), opt('defaultEventMinutes'));
 		}
 	}
-
-
+	
+	
 	// renders events in the 'time slots' at the bottom
-
+	
 	function renderSlotSegs(segs, modifiedEventId) {
-
+	
 		var i, segCnt=segs.length, seg,
 			event,
 			classes,
@@ -3765,7 +3765,7 @@ function AgendaEventRenderer() {
 			slotSegmentContainer = getSlotSegmentContainer(),
 			rtl, dis, dit,
 			colCnt = getColCnt();
-
+			
 		if (rtl = opt('isRTL')) {
 			dis = -1;
 			dit = colCnt - 1;
@@ -3773,7 +3773,7 @@ function AgendaEventRenderer() {
 			dis = 1;
 			dit = 0;
 		}
-
+			
 		// calculate position/dimensions, create html
 		for (i=0; i<segCnt; i++) {
 			seg = segs[i];
@@ -3809,7 +3809,7 @@ function AgendaEventRenderer() {
 		}
 		slotSegmentContainer[0].innerHTML = html; // faster than html()
 		eventElements = slotSegmentContainer.children();
-
+		
 		// retrieve elements, run through eventRender callback, bind event handlers
 		for (i=0; i<segCnt; i++) {
 			seg = segs[i];
@@ -3838,9 +3838,9 @@ function AgendaEventRenderer() {
 				reportEventElement(event, eventElement);
 			}
 		}
-
+		
 		lazySegBind(slotSegmentContainer, segs, bindSlotSeg);
-
+		
 		// record event sides and title positions
 		for (i=0; i<segCnt; i++) {
 			seg = segs[i];
@@ -3855,7 +3855,7 @@ function AgendaEventRenderer() {
 				}
 			}
 		}
-
+		
 		// set all positions/dimensions at once
 		for (i=0; i<segCnt; i++) {
 			seg = segs[i];
@@ -3874,10 +3874,10 @@ function AgendaEventRenderer() {
 				trigger('eventAfterRender', event, event, eventElement);
 			}
 		}
-
+					
 	}
-
-
+	
+	
 	function slotSegHtml(event, seg) {
 		var html = "<";
 		var url = event.url;
@@ -3927,8 +3927,8 @@ function AgendaEventRenderer() {
 			"</" + (url ? "a" : "div") + ">";
 		return html;
 	}
-
-
+	
+	
 	function bindDaySeg(event, eventElement, seg) {
 		if (isEventDraggable(event)) {
 			draggableDayEvent(event, eventElement, seg.isStart);
@@ -3939,8 +3939,8 @@ function AgendaEventRenderer() {
 		eventElementHandlers(event, eventElement);
 			// needs to be after, because resizableDayEvent might stopImmediatePropagation on click
 	}
-
-
+	
+	
 	function bindSlotSeg(event, eventElement, seg) {
 		var timeElement = eventElement.find('div.fc-event-time');
 		if (isEventDraggable(event)) {
@@ -3951,15 +3951,15 @@ function AgendaEventRenderer() {
 		}
 		eventElementHandlers(event, eventElement);
 	}
-
-
-
+	
+	
+	
 	/* Dragging
 	-----------------------------------------------------------------------------------*/
-
-
+	
+	
 	// when event starts out FULL-DAY
-
+	
 	function draggableDayEvent(event, eventElement, isStart) {
 		var origWidth;
 		var revert;
@@ -4053,10 +4053,10 @@ function AgendaEventRenderer() {
 			}
 		}
 	}
-
-
+	
+	
 	// when event starts out IN TIMESLOTS
-
+	
 	function draggableSlotEvent(event, eventElement, timeElement) {
 		var origPosition;
 		var allDay=false;
@@ -4147,13 +4147,13 @@ function AgendaEventRenderer() {
 			}
 		}
 	}
-
-
-
+	
+	
+	
 	/* Resizing
 	--------------------------------------------------------------------------------------*/
-
-
+	
+	
 	function resizableSlotEvent(event, eventElement, timeElement) {
 		var slotDelta, prevSlotDelta;
 		var slotHeight = getSlotHeight();
@@ -4195,7 +4195,7 @@ function AgendaEventRenderer() {
 			}
 		});
 	}
-
+	
 
 }
 
@@ -4221,8 +4221,8 @@ function countForwardSegs(levels) {
 
 function View(element, calendar, viewName) {
 	var t = this;
-
-
+	
+	
 	// exports
 	t.element = element;
 	t.calendar = calendar;
@@ -4244,22 +4244,22 @@ function View(element, calendar, viewName) {
 	// t.title
 	// t.start, t.end
 	// t.visStart, t.visEnd
-
-
+	
+	
 	// imports
 	var defaultEventEnd = t.defaultEventEnd;
 	var normalizeEvent = calendar.normalizeEvent; // in EventManager
 	var reportEventChange = calendar.reportEventChange;
-
-
+	
+	
 	// locals
 	var eventsByID = {};
 	var eventElements = [];
 	var eventElementsByID = {};
 	var options = calendar.options;
-
-
-
+	
+	
+	
 	function opt(name, viewNameOverride) {
 		var v = options[name];
 		if (typeof v == 'object') {
@@ -4268,42 +4268,42 @@ function View(element, calendar, viewName) {
 		return v;
 	}
 
-
+	
 	function trigger(name, thisObj) {
 		return calendar.trigger.apply(
 			calendar,
 			[name, thisObj || t].concat(Array.prototype.slice.call(arguments, 2), [t])
 		);
 	}
-
-
+	
+	
 	/*
 	function setOverflowHidden(bool) {
 		element.css('overflow', bool ? 'hidden' : '');
 	}
 	*/
-
-
+	
+	
 	function isEventDraggable(event) {
 		return isEventEditable(event) && !opt('disableDragging');
 	}
-
-
+	
+	
 	function isEventResizable(event) { // but also need to make sure the seg.isEnd == true
 		return isEventEditable(event) && !opt('disableResizing');
 	}
-
-
+	
+	
 	function isEventEditable(event) {
 		return firstDefined(event.editable, (event.source || {}).editable, opt('editable'));
 	}
-
-
-
+	
+	
+	
 	/* Event Data
 	------------------------------------------------------------------------------*/
-
-
+	
+	
 	// report when view receives new events
 	function reportEvents(events) { // events are already normalized at this point
 		eventsByID = {};
@@ -4317,19 +4317,19 @@ function View(element, calendar, viewName) {
 			}
 		}
 	}
-
-
+	
+	
 	// returns a Date object for an event's end
 	function eventEnd(event) {
 		return event.end ? cloneDate(event.end) : defaultEventEnd(event);
 	}
-
-
-
+	
+	
+	
 	/* Event Elements
 	------------------------------------------------------------------------------*/
-
-
+	
+	
 	// report when view creates an element for an event
 	function reportEventElement(event, element) {
 		eventElements.push(element);
@@ -4339,14 +4339,14 @@ function View(element, calendar, viewName) {
 			eventElementsByID[event._id] = [element];
 		}
 	}
-
-
+	
+	
 	function reportEventClear() {
 		eventElements = [];
 		eventElementsByID = {};
 	}
-
-
+	
+	
 	// attaches eventClick, eventMouseover, eventMouseout
 	function eventElementHandlers(event, eventElement) {
 		eventElement
@@ -4367,18 +4367,18 @@ function View(element, calendar, viewName) {
 		// TODO: don't fire eventMouseover/eventMouseout *while* dragging is occuring (on subject element)
 		// TODO: same for resizing
 	}
-
-
+	
+	
 	function showEvents(event, exceptElement) {
 		eachEventElement(event, exceptElement, 'show');
 	}
-
-
+	
+	
 	function hideEvents(event, exceptElement) {
 		eachEventElement(event, exceptElement, 'hide');
 	}
-
-
+	
+	
 	function eachEventElement(event, exceptElement, funcName) {
 		var elements = eventElementsByID[event._id],
 			i, len = elements.length;
@@ -4388,13 +4388,13 @@ function View(element, calendar, viewName) {
 			}
 		}
 	}
-
-
-
+	
+	
+	
 	/* Event Modification Reporting
 	---------------------------------------------------------------------------------*/
-
-
+	
+	
 	function eventDrop(e, event, dayDelta, minuteDelta, allDay, ev, ui) {
 		var oldAllDay = event.allDay;
 		var eventId = event._id;
@@ -4416,8 +4416,8 @@ function View(element, calendar, viewName) {
 		);
 		reportEventChange(eventId);
 	}
-
-
+	
+	
 	function eventResize(e, event, dayDelta, minuteDelta, ev, ui) {
 		var eventId = event._id;
 		elongateEvents(eventsByID[eventId], dayDelta, minuteDelta);
@@ -4437,13 +4437,13 @@ function View(element, calendar, viewName) {
 		);
 		reportEventChange(eventId);
 	}
-
-
-
+	
+	
+	
 	/* Event Modification Math
 	---------------------------------------------------------------------------------*/
-
-
+	
+	
 	function moveEvents(events, dayDelta, minuteDelta, allDay) {
 		minuteDelta = minuteDelta || 0;
 		for (var e, len=events.length, i=0; i<len; i++) {
@@ -4458,8 +4458,8 @@ function View(element, calendar, viewName) {
 			normalizeEvent(e, options);
 		}
 	}
-
-
+	
+	
 	function elongateEvents(events, dayDelta, minuteDelta) {
 		minuteDelta = minuteDelta || 0;
 		for (var e, len=events.length, i=0; i<len; i++) {
@@ -4468,19 +4468,19 @@ function View(element, calendar, viewName) {
 			normalizeEvent(e, options);
 		}
 	}
-
+	
 
 }
 
 function DayEventRenderer() {
 	var t = this;
 
-
+	
 	// exports
 	t.renderDaySegs = renderDaySegs;
 	t.resizableDayEvent = resizableDayEvent;
-
-
+	
+	
 	// imports
 	var opt = t.opt;
 	var trigger = t.trigger;
@@ -4507,13 +4507,13 @@ function DayEventRenderer() {
 	var renderDayOverlay = t.renderDayOverlay;
 	var clearOverlays = t.clearOverlays;
 	var clearSelection = t.clearSelection;
-
-
-
+	
+	
+	
 	/* Rendering
 	-----------------------------------------------------------------------------*/
-
-
+	
+	
 	function renderDaySegs(segs, modifiedEventId) {
 		var segmentContainer = getDaySegmentContainer();
 		var rowDivs;
@@ -4557,8 +4557,8 @@ function DayEventRenderer() {
 		}
 		daySegSetTops(segs, getRowTops(rowDivs));
 	}
-
-
+	
+	
 	function renderTempDaySegs(segs, adjustRow, adjustTop) {
 		var tempContainer = $("<div/>");
 		var elements;
@@ -4586,8 +4586,8 @@ function DayEventRenderer() {
 		}
 		return $(elements);
 	}
-
-
+	
+	
 	function daySegHTML(segs) { // also sets seg.left and seg.outerWidth
 		var rtl = opt('isRTL');
 		var i;
@@ -4679,8 +4679,8 @@ function DayEventRenderer() {
 		}
 		return html;
 	}
-
-
+	
+	
 	function daySegElementResolve(segs, elements) { // sets seg.element
 		var i;
 		var segCnt = segs.length;
@@ -4709,8 +4709,8 @@ function DayEventRenderer() {
 			}
 		}
 	}
-
-
+	
+	
 	function daySegElementReport(segs) {
 		var i;
 		var segCnt = segs.length;
@@ -4724,8 +4724,8 @@ function DayEventRenderer() {
 			}
 		}
 	}
-
-
+	
+	
 	function daySegHandlers(segs, segmentContainer, modifiedEventId) {
 		var i;
 		var segCnt = segs.length;
@@ -4747,8 +4747,8 @@ function DayEventRenderer() {
 		}
 		lazySegBind(segmentContainer, segs, bindDaySeg);
 	}
-
-
+	
+	
 	function daySegCalcHSides(segs) { // also sets seg.key
 		var i;
 		var segCnt = segs.length;
@@ -4770,8 +4770,8 @@ function DayEventRenderer() {
 			}
 		}
 	}
-
-
+	
+	
 	function daySegSetWidths(segs) {
 		var i;
 		var segCnt = segs.length;
@@ -4785,8 +4785,8 @@ function DayEventRenderer() {
 			}
 		}
 	}
-
-
+	
+	
 	function daySegCalcHeights(segs) {
 		var i;
 		var segCnt = segs.length;
@@ -4808,8 +4808,8 @@ function DayEventRenderer() {
 			}
 		}
 	}
-
-
+	
+	
 	function getRowDivs() {
 		var i;
 		var rowCnt = getRowCnt();
@@ -4820,8 +4820,8 @@ function DayEventRenderer() {
 		}
 		return rowDivs;
 	}
-
-
+	
+	
 	function getRowTops(rowDivs) {
 		var i;
 		var rowCnt = rowDivs.length;
@@ -4831,8 +4831,8 @@ function DayEventRenderer() {
 		}
 		return tops;
 	}
-
-
+	
+	
 	function daySegSetTops(segs, rowTops) { // also triggers eventAfterRender
 		var i;
 		var segCnt = segs.length;
@@ -4849,19 +4849,19 @@ function DayEventRenderer() {
 			}
 		}
 	}
-
-
-
+	
+	
+	
 	/* Resizing
 	-----------------------------------------------------------------------------------*/
-
-
+	
+	
 	function resizableDayEvent(event, element, seg) {
 		var rtl = opt('isRTL');
 		var direction = rtl ? 'w' : 'e';
 		var handle = element.find('div.ui-resizable-' + direction);
 		var isResizing = false;
-
+		
 		// TODO: look into using jquery-ui mouse widget for this stuff
 		disableTextSelection(element); // prevent native <a> selection for IE
 		element
@@ -4875,7 +4875,7 @@ function DayEventRenderer() {
 					                               // (eventElementHandlers needs to be bound after resizableDayEvent)
 				}
 			});
-
+		
 		handle.mousedown(function(ev) {
 			if (ev.which != 1) {
 				return; // needs to be left mouse button
@@ -4932,7 +4932,7 @@ function DayEventRenderer() {
 					renderDayOverlay(event.start, addDays(cloneDate(newEnd), 1)); // coordinate grid already rebuild at hoverListener.start
 				}
 			}, ev);
-
+			
 			function mouseup(ev) {
 				trigger('eventResizeStop', this, event, ev);
 				$('body').css('cursor', '');
@@ -4943,15 +4943,15 @@ function DayEventRenderer() {
 					// event redraw will clear helpers
 				}
 				// otherwise, the drag handler already restored the old events
-
+				
 				setTimeout(function() { // make this happen after the element's click event
 					isResizing = false;
 				},0);
 			}
-
+			
 		});
 	}
-
+	
 
 }
 
@@ -4959,23 +4959,23 @@ function DayEventRenderer() {
 
 function SelectionManager() {
 	var t = this;
-
-
+	
+	
 	// exports
 	t.select = select;
 	t.unselect = unselect;
 	t.reportSelection = reportSelection;
 	t.daySelectionMousedown = daySelectionMousedown;
-
-
+	
+	
 	// imports
 	var opt = t.opt;
 	var trigger = t.trigger;
 	var defaultSelectionEnd = t.defaultSelectionEnd;
 	var renderSelection = t.renderSelection;
 	var clearSelection = t.clearSelection;
-
-
+	
+	
 	// locals
 	var selected = false;
 
@@ -4993,7 +4993,7 @@ function SelectionManager() {
 			unselect(ev);
 		});
 	}
-
+	
 
 	function select(startDate, endDate, allDay) {
 		unselect();
@@ -5003,8 +5003,8 @@ function SelectionManager() {
 		renderSelection(startDate, endDate, allDay);
 		reportSelection(startDate, endDate, allDay);
 	}
-
-
+	
+	
 	function unselect(ev) {
 		if (selected) {
 			selected = false;
@@ -5012,14 +5012,14 @@ function SelectionManager() {
 			trigger('unselect', null, ev);
 		}
 	}
-
-
+	
+	
 	function reportSelection(startDate, endDate, allDay, ev) {
 		selected = true;
 		trigger('select', null, startDate, endDate, allDay, ev);
 	}
-
-
+	
+	
 	function daySelectionMousedown(ev) { // not really a generic manager method, oh well
 		var cellDate = t.cellDate;
 		var cellIsAllDay = t.cellIsAllDay;
@@ -5052,21 +5052,21 @@ function SelectionManager() {
 
 
 }
-
+ 
 function OverlayManager() {
 	var t = this;
-
-
+	
+	
 	// exports
 	t.renderOverlay = renderOverlay;
 	t.clearOverlays = clearOverlays;
-
-
+	
+	
 	// locals
 	var usedOverlays = [];
 	var unusedOverlays = [];
-
-
+	
+	
 	function renderOverlay(rect, parent) {
 		var e = unusedOverlays.shift();
 		if (!e) {
@@ -5078,7 +5078,7 @@ function OverlayManager() {
 		usedOverlays.push(e.css(rect).show());
 		return e;
 	}
-
+	
 
 	function clearOverlays() {
 		var e;
@@ -5095,15 +5095,15 @@ function CoordinateGrid(buildFunc) {
 	var t = this;
 	var rows;
 	var cols;
-
-
+	
+	
 	t.build = function() {
 		rows = [];
 		cols = [];
 		buildFunc(rows, cols);
 	};
-
-
+	
+	
 	t.cell = function(x, y) {
 		var rowCnt = rows.length;
 		var colCnt = cols.length;
@@ -5122,8 +5122,8 @@ function CoordinateGrid(buildFunc) {
 		}
 		return (r>=0 && c>=0) ? { row:r, col:c } : null;
 	};
-
-
+	
+	
 	t.rect = function(row0, col0, row1, col1, originElement) { // row1,col1 is inclusive
 		var origin = originElement.offset();
 		return {
@@ -5144,8 +5144,8 @@ function HoverListener(coordinateGrid) {
 	var change;
 	var firstCell;
 	var cell;
-
-
+	
+	
 	t.start = function(_change, ev, _bindType) {
 		change = _change;
 		firstCell = cell = null;
@@ -5154,9 +5154,10 @@ function HoverListener(coordinateGrid) {
 		bindType = _bindType || 'mousemove';
 		$(document).bind(bindType, mouse);
 	};
-
-
+	
+	
 	function mouse(ev) {
+		_fixUIEvent(ev); // see below
 		var newCell = coordinateGrid.cell(ev.pageX, ev.pageY);
 		if (!newCell != !cell || newCell && (newCell.row != cell.row || newCell.col != cell.col)) {
 			if (newCell) {
@@ -5170,41 +5171,54 @@ function HoverListener(coordinateGrid) {
 			cell = newCell;
 		}
 	}
-
-
+	
+	
 	t.stop = function() {
 		$(document).unbind(bindType, mouse);
 		return cell;
 	};
+	
+	
+}
 
 
-}
 
+// this fix was only necessary for jQuery UI 1.8.16 (and jQuery 1.7 or 1.7.1)
+// upgrading to jQuery UI 1.8.17 (and using either jQuery 1.7 or 1.7.1) fixed the problem
+// but keep this in here for 1.8.16 users
+// and maybe remove it down the line
+
+function _fixUIEvent(event) { // for issue 1168
+	if (event.pageX === undefined) {
+		event.pageX = event.originalEvent.pageX;
+		event.pageY = event.originalEvent.pageY;
+	}
+}
 function HorizontalPositionCache(getElement) {
 
 	var t = this,
 		elements = {},
 		lefts = {},
 		rights = {};
-
+		
 	function e(i) {
 		return elements[i] = elements[i] || getElement(i);
 	}
-
+	
 	t.left = function(i) {
 		return lefts[i] = lefts[i] === undefined ? e(i).position().left : lefts[i];
 	};
-
+	
 	t.right = function(i) {
 		return rights[i] = rights[i] === undefined ? t.left(i) + e(i).width() : rights[i];
 	};
-
+	
 	t.clear = function() {
 		elements = {};
 		lefts = {};
 		rights = {};
 	};
-
+	
 }
-
+
 })(jQuery);
diff --git a/3rdparty/fullcalendar/js/fullcalendar.min.js b/3rdparty/fullcalendar/js/fullcalendar.min.js
index fc06a89a6106dd2e5a7380f87290cb86a21b8a70..df37bdfd803894789c0709aa2312432838bf1cf1 100644
--- a/3rdparty/fullcalendar/js/fullcalendar.min.js
+++ b/3rdparty/fullcalendar/js/fullcalendar.min.js
@@ -1,6 +1,6 @@
 /*
 
- FullCalendar v1.5.2
+ FullCalendar v1.5.3
  http://arshaw.com/fullcalendar/
 
  Use fullcalendar.css for basic styling.
@@ -11,103 +11,104 @@
  Dual licensed under the MIT and GPL licenses, located in
  MIT-LICENSE.txt and GPL-LICENSE.txt respectively.
 
- Date: Sun Aug 21 22:06:09 2011 -0700
+ Date: Mon Feb 6 22:40:40 2012 -0800
 
 */
-(function(m,oa){function wb(a){m.extend(true,Ya,a)}function Yb(a,b,e){function d(k){if(E){u();q();ma();S(k)}else f()}function f(){B=b.theme?"ui":"fc";a.addClass("fc");b.isRTL&&a.addClass("fc-rtl");b.theme&&a.addClass("ui-widget");E=m("<div class='fc-content' style='position:relative'/>").prependTo(a);C=new Zb(X,b);(P=C.render())&&a.prepend(P);y(b.defaultView);m(window).resize(na);t()||g()}function g(){setTimeout(function(){!n.start&&t()&&S()},0)}function l(){m(window).unbind("resize",na);C.destroy();
+(function(m,ma){function wb(a){m.extend(true,Ya,a)}function Yb(a,b,e){function d(k){if(E){u();q();na();S(k)}else f()}function f(){B=b.theme?"ui":"fc";a.addClass("fc");b.isRTL&&a.addClass("fc-rtl");b.theme&&a.addClass("ui-widget");E=m("<div class='fc-content' style='position:relative'/>").prependTo(a);C=new Zb(X,b);(P=C.render())&&a.prepend(P);y(b.defaultView);m(window).resize(oa);t()||g()}function g(){setTimeout(function(){!n.start&&t()&&S()},0)}function l(){m(window).unbind("resize",oa);C.destroy();
 E.remove();a.removeClass("fc fc-rtl ui-widget")}function j(){return i.offsetWidth!==0}function t(){return m("body")[0].offsetWidth!==0}function y(k){if(!n||k!=n.name){F++;pa();var D=n,Z;if(D){(D.beforeHide||xb)();Za(E,E.height());D.element.hide()}else Za(E,1);E.css("overflow","hidden");if(n=Y[k])n.element.show();else n=Y[k]=new Ja[k](Z=s=m("<div class='fc-view fc-view-"+k+"' style='position:absolute'/>").appendTo(E),X);D&&C.deactivateButton(D.name);C.activateButton(k);S();E.css("overflow","");D&&
-Za(E,1);Z||(n.afterShow||xb)();F--}}function S(k){if(j()){F++;pa();o===oa&&u();var D=false;if(!n.start||k||r<n.start||r>=n.end){n.render(r,k||0);fa(true);D=true}else if(n.sizeDirty){n.clearEvents();fa();D=true}else if(n.eventsDirty){n.clearEvents();D=true}n.sizeDirty=false;n.eventsDirty=false;ga(D);W=a.outerWidth();C.updateTitle(n.title);k=new Date;k>=n.start&&k<n.end?C.disableButton("today"):C.enableButton("today");F--;n.trigger("viewDisplay",i)}}function Q(){q();if(j()){u();fa();pa();n.clearEvents();
-n.renderEvents(J);n.sizeDirty=false}}function q(){m.each(Y,function(k,D){D.sizeDirty=true})}function u(){o=b.contentHeight?b.contentHeight:b.height?b.height-(P?P.height():0)-Sa(E):Math.round(E.width()/Math.max(b.aspectRatio,0.5))}function fa(k){F++;n.setHeight(o,k);if(s){s.css("position","relative");s=null}n.setWidth(E.width(),k);F--}function na(){if(!F)if(n.start){var k=++v;setTimeout(function(){if(k==v&&!F&&j())if(W!=(W=a.outerWidth())){F++;Q();n.trigger("windowResize",i);F--}},200)}else g()}function ga(k){if(!b.lazyFetching||
-ya(n.visStart,n.visEnd))ra();else k&&da()}function ra(){K(n.visStart,n.visEnd)}function sa(k){J=k;da()}function ha(k){da(k)}function da(k){ma();if(j()){n.clearEvents();n.renderEvents(J,k);n.eventsDirty=false}}function ma(){m.each(Y,function(k,D){D.eventsDirty=true})}function ua(k,D,Z){n.select(k,D,Z===oa?true:Z)}function pa(){n&&n.unselect()}function U(){S(-1)}function ca(){S(1)}function ka(){gb(r,-1);S()}function qa(){gb(r,1);S()}function G(){r=new Date;S()}function p(k,D,Z){if(k instanceof Date)r=
-N(k);else yb(r,k,D,Z);S()}function L(k,D,Z){k!==oa&&gb(r,k);D!==oa&&hb(r,D);Z!==oa&&ba(r,Z);S()}function c(){return N(r)}function z(){return n}function H(k,D){if(D===oa)return b[k];if(k=="height"||k=="contentHeight"||k=="aspectRatio"){b[k]=D;Q()}}function T(k,D){if(b[k])return b[k].apply(D||i,Array.prototype.slice.call(arguments,2))}var X=this;X.options=b;X.render=d;X.destroy=l;X.refetchEvents=ra;X.reportEvents=sa;X.reportEventChange=ha;X.rerenderEvents=da;X.changeView=y;X.select=ua;X.unselect=pa;
+Za(E,1);Z||(n.afterShow||xb)();F--}}function S(k){if(j()){F++;pa();o===ma&&u();var D=false;if(!n.start||k||r<n.start||r>=n.end){n.render(r,k||0);fa(true);D=true}else if(n.sizeDirty){n.clearEvents();fa();D=true}else if(n.eventsDirty){n.clearEvents();D=true}n.sizeDirty=false;n.eventsDirty=false;ga(D);W=a.outerWidth();C.updateTitle(n.title);k=new Date;k>=n.start&&k<n.end?C.disableButton("today"):C.enableButton("today");F--;n.trigger("viewDisplay",i)}}function Q(){q();if(j()){u();fa();pa();n.clearEvents();
+n.renderEvents(J);n.sizeDirty=false}}function q(){m.each(Y,function(k,D){D.sizeDirty=true})}function u(){o=b.contentHeight?b.contentHeight:b.height?b.height-(P?P.height():0)-Sa(E):Math.round(E.width()/Math.max(b.aspectRatio,0.5))}function fa(k){F++;n.setHeight(o,k);if(s){s.css("position","relative");s=null}n.setWidth(E.width(),k);F--}function oa(){if(!F)if(n.start){var k=++v;setTimeout(function(){if(k==v&&!F&&j())if(W!=(W=a.outerWidth())){F++;Q();n.trigger("windowResize",i);F--}},200)}else g()}function ga(k){if(!b.lazyFetching||
+ya(n.visStart,n.visEnd))ra();else k&&da()}function ra(){K(n.visStart,n.visEnd)}function sa(k){J=k;da()}function ha(k){da(k)}function da(k){na();if(j()){n.clearEvents();n.renderEvents(J,k);n.eventsDirty=false}}function na(){m.each(Y,function(k,D){D.eventsDirty=true})}function ua(k,D,Z){n.select(k,D,Z===ma?true:Z)}function pa(){n&&n.unselect()}function U(){S(-1)}function ca(){S(1)}function ka(){gb(r,-1);S()}function qa(){gb(r,1);S()}function G(){r=new Date;S()}function p(k,D,Z){if(k instanceof Date)r=
+N(k);else yb(r,k,D,Z);S()}function L(k,D,Z){k!==ma&&gb(r,k);D!==ma&&hb(r,D);Z!==ma&&ba(r,Z);S()}function c(){return N(r)}function z(){return n}function H(k,D){if(D===ma)return b[k];if(k=="height"||k=="contentHeight"||k=="aspectRatio"){b[k]=D;Q()}}function T(k,D){if(b[k])return b[k].apply(D||i,Array.prototype.slice.call(arguments,2))}var X=this;X.options=b;X.render=d;X.destroy=l;X.refetchEvents=ra;X.reportEvents=sa;X.reportEventChange=ha;X.rerenderEvents=da;X.changeView=y;X.select=ua;X.unselect=pa;
 X.prev=U;X.next=ca;X.prevYear=ka;X.nextYear=qa;X.today=G;X.gotoDate=p;X.incrementDate=L;X.formatDate=function(k,D){return Oa(k,D,b)};X.formatDates=function(k,D,Z){return ib(k,D,Z,b)};X.getDate=c;X.getView=z;X.option=H;X.trigger=T;$b.call(X,b,e);var ya=X.isFetchNeeded,K=X.fetchEvents,i=a[0],C,P,E,B,n,Y={},W,o,s,v=0,F=0,r=new Date,J=[],M;yb(r,b.year,b.month,b.date);b.droppable&&m(document).bind("dragstart",function(k,D){var Z=k.target,ja=m(Z);if(!ja.parents(".fc").length){var ia=b.dropAccept;if(m.isFunction(ia)?
-ia.call(Z,ja):ja.is(ia)){M=Z;n.dragStart(M,k,D)}}}).bind("dragstop",function(k,D){if(M){n.dragStop(M,k,D);M=null}})}function Zb(a,b){function e(){q=b.theme?"ui":"fc";if(b.header)return Q=m("<table class='fc-header' style='width:100%'/>").append(m("<tr/>").append(f("left")).append(f("center")).append(f("right")))}function d(){Q.remove()}function f(u){var fa=m("<td class='fc-header-"+u+"'/>");(u=b.header[u])&&m.each(u.split(" "),function(na){na>0&&fa.append("<span class='fc-header-space'/>");var ga;
-m.each(this.split(","),function(ra,sa){if(sa=="title"){fa.append("<span class='fc-header-title'><h2>&nbsp;</h2></span>");ga&&ga.addClass(q+"-corner-right");ga=null}else{var ha;if(a[sa])ha=a[sa];else if(Ja[sa])ha=function(){ma.removeClass(q+"-state-hover");a.changeView(sa)};if(ha){ra=b.theme?jb(b.buttonIcons,sa):null;var da=jb(b.buttonText,sa),ma=m("<span class='fc-button fc-button-"+sa+" "+q+"-state-default'><span class='fc-button-inner'><span class='fc-button-content'>"+(ra?"<span class='fc-icon-wrap'><span class='ui-icon ui-icon-"+
-ra+"'/></span>":da)+"</span><span class='fc-button-effect'><span></span></span></span></span>");if(ma){ma.click(function(){ma.hasClass(q+"-state-disabled")||ha()}).mousedown(function(){ma.not("."+q+"-state-active").not("."+q+"-state-disabled").addClass(q+"-state-down")}).mouseup(function(){ma.removeClass(q+"-state-down")}).hover(function(){ma.not("."+q+"-state-active").not("."+q+"-state-disabled").addClass(q+"-state-hover")},function(){ma.removeClass(q+"-state-hover").removeClass(q+"-state-down")}).appendTo(fa);
-ga||ma.addClass(q+"-corner-left");ga=ma}}}});ga&&ga.addClass(q+"-corner-right")});return fa}function g(u){Q.find("h2").html(u)}function l(u){Q.find("span.fc-button-"+u).addClass(q+"-state-active")}function j(u){Q.find("span.fc-button-"+u).removeClass(q+"-state-active")}function t(u){Q.find("span.fc-button-"+u).addClass(q+"-state-disabled")}function y(u){Q.find("span.fc-button-"+u).removeClass(q+"-state-disabled")}var S=this;S.render=e;S.destroy=d;S.updateTitle=g;S.activateButton=l;S.deactivateButton=
-j;S.disableButton=t;S.enableButton=y;var Q=m([]),q}function $b(a,b){function e(c,z){return!ca||c<ca||z>ka}function d(c,z){ca=c;ka=z;L=[];c=++qa;G=z=U.length;for(var H=0;H<z;H++)f(U[H],c)}function f(c,z){g(c,function(H){if(z==qa){if(H){for(var T=0;T<H.length;T++){H[T].source=c;na(H[T])}L=L.concat(H)}G--;G||ua(L)}})}function g(c,z){var H,T=Aa.sourceFetchers,X;for(H=0;H<T.length;H++){X=T[H](c,ca,ka,z);if(X===true)return;else if(typeof X=="object"){g(X,z);return}}if(H=c.events)if(m.isFunction(H)){u();
+ia.call(Z,ja):ja.is(ia)){M=Z;n.dragStart(M,k,D)}}}).bind("dragstop",function(k,D){if(M){n.dragStop(M,k,D);M=null}})}function Zb(a,b){function e(){q=b.theme?"ui":"fc";if(b.header)return Q=m("<table class='fc-header' style='width:100%'/>").append(m("<tr/>").append(f("left")).append(f("center")).append(f("right")))}function d(){Q.remove()}function f(u){var fa=m("<td class='fc-header-"+u+"'/>");(u=b.header[u])&&m.each(u.split(" "),function(oa){oa>0&&fa.append("<span class='fc-header-space'/>");var ga;
+m.each(this.split(","),function(ra,sa){if(sa=="title"){fa.append("<span class='fc-header-title'><h2>&nbsp;</h2></span>");ga&&ga.addClass(q+"-corner-right");ga=null}else{var ha;if(a[sa])ha=a[sa];else if(Ja[sa])ha=function(){na.removeClass(q+"-state-hover");a.changeView(sa)};if(ha){ra=b.theme?jb(b.buttonIcons,sa):null;var da=jb(b.buttonText,sa),na=m("<span class='fc-button fc-button-"+sa+" "+q+"-state-default'><span class='fc-button-inner'><span class='fc-button-content'>"+(ra?"<span class='fc-icon-wrap'><span class='ui-icon ui-icon-"+
+ra+"'/></span>":da)+"</span><span class='fc-button-effect'><span></span></span></span></span>");if(na){na.click(function(){na.hasClass(q+"-state-disabled")||ha()}).mousedown(function(){na.not("."+q+"-state-active").not("."+q+"-state-disabled").addClass(q+"-state-down")}).mouseup(function(){na.removeClass(q+"-state-down")}).hover(function(){na.not("."+q+"-state-active").not("."+q+"-state-disabled").addClass(q+"-state-hover")},function(){na.removeClass(q+"-state-hover").removeClass(q+"-state-down")}).appendTo(fa);
+ga||na.addClass(q+"-corner-left");ga=na}}}});ga&&ga.addClass(q+"-corner-right")});return fa}function g(u){Q.find("h2").html(u)}function l(u){Q.find("span.fc-button-"+u).addClass(q+"-state-active")}function j(u){Q.find("span.fc-button-"+u).removeClass(q+"-state-active")}function t(u){Q.find("span.fc-button-"+u).addClass(q+"-state-disabled")}function y(u){Q.find("span.fc-button-"+u).removeClass(q+"-state-disabled")}var S=this;S.render=e;S.destroy=d;S.updateTitle=g;S.activateButton=l;S.deactivateButton=
+j;S.disableButton=t;S.enableButton=y;var Q=m([]),q}function $b(a,b){function e(c,z){return!ca||c<ca||z>ka}function d(c,z){ca=c;ka=z;L=[];c=++qa;G=z=U.length;for(var H=0;H<z;H++)f(U[H],c)}function f(c,z){g(c,function(H){if(z==qa){if(H){for(var T=0;T<H.length;T++){H[T].source=c;oa(H[T])}L=L.concat(H)}G--;G||ua(L)}})}function g(c,z){var H,T=Aa.sourceFetchers,X;for(H=0;H<T.length;H++){X=T[H](c,ca,ka,z);if(X===true)return;else if(typeof X=="object"){g(X,z);return}}if(H=c.events)if(m.isFunction(H)){u();
 H(N(ca),N(ka),function(C){z(C);fa()})}else m.isArray(H)?z(H):z();else if(c.url){var ya=c.success,K=c.error,i=c.complete;H=m.extend({},c.data||{});T=Ta(c.startParam,a.startParam);X=Ta(c.endParam,a.endParam);if(T)H[T]=Math.round(+ca/1E3);if(X)H[X]=Math.round(+ka/1E3);u();m.ajax(m.extend({},ac,c,{data:H,success:function(C){C=C||[];var P=$a(ya,this,arguments);if(m.isArray(P))C=P;z(C)},error:function(){$a(K,this,arguments);z()},complete:function(){$a(i,this,arguments);fa()}}))}else z()}function l(c){if(c=
-j(c)){G++;f(c,qa)}}function j(c){if(m.isFunction(c)||m.isArray(c))c={events:c};else if(typeof c=="string")c={url:c};if(typeof c=="object"){ga(c);U.push(c);return c}}function t(c){U=m.grep(U,function(z){return!ra(z,c)});L=m.grep(L,function(z){return!ra(z.source,c)});ua(L)}function y(c){var z,H=L.length,T,X=ma().defaultEventEnd,ya=c.start-c._start,K=c.end?c.end-(c._end||X(c)):0;for(z=0;z<H;z++){T=L[z];if(T._id==c._id&&T!=c){T.start=new Date(+T.start+ya);T.end=c.end?T.end?new Date(+T.end+K):new Date(+X(T)+
-K):null;T.title=c.title;T.url=c.url;T.allDay=c.allDay;T.className=c.className;T.editable=c.editable;T.color=c.color;T.backgroudColor=c.backgroudColor;T.borderColor=c.borderColor;T.textColor=c.textColor;na(T)}}na(c);ua(L)}function S(c,z){na(c);if(!c.source){if(z){pa.events.push(c);c.source=pa}L.push(c)}ua(L)}function Q(c){if(c){if(!m.isFunction(c)){var z=c+"";c=function(T){return T._id==z}}L=m.grep(L,c,true);for(H=0;H<U.length;H++)if(m.isArray(U[H].events))U[H].events=m.grep(U[H].events,c,true)}else{L=
-[];for(var H=0;H<U.length;H++)if(m.isArray(U[H].events))U[H].events=[]}ua(L)}function q(c){if(m.isFunction(c))return m.grep(L,c);else if(c){c+="";return m.grep(L,function(z){return z._id==c})}return L}function u(){p++||da("loading",null,true)}function fa(){--p||da("loading",null,false)}function na(c){var z=c.source||{},H=Ta(z.ignoreTimezone,a.ignoreTimezone);c._id=c._id||(c.id===oa?"_fc"+bc++:c.id+"");if(c.date){if(!c.start)c.start=c.date;delete c.date}c._start=N(c.start=kb(c.start,H));c.end=kb(c.end,
-H);if(c.end&&c.end<=c.start)c.end=null;c._end=c.end?N(c.end):null;if(c.allDay===oa)c.allDay=Ta(z.allDayDefault,a.allDayDefault);if(c.className){if(typeof c.className=="string")c.className=c.className.split(/\s+/)}else c.className=[]}function ga(c){if(c.className){if(typeof c.className=="string")c.className=c.className.split(/\s+/)}else c.className=[];for(var z=Aa.sourceNormalizers,H=0;H<z.length;H++)z[H](c)}function ra(c,z){return c&&z&&sa(c)==sa(z)}function sa(c){return(typeof c=="object"?c.events||
-c.url:"")||c}var ha=this;ha.isFetchNeeded=e;ha.fetchEvents=d;ha.addEventSource=l;ha.removeEventSource=t;ha.updateEvent=y;ha.renderEvent=S;ha.removeEvents=Q;ha.clientEvents=q;ha.normalizeEvent=na;var da=ha.trigger,ma=ha.getView,ua=ha.reportEvents,pa={events:[]},U=[pa],ca,ka,qa=0,G=0,p=0,L=[];for(ha=0;ha<b.length;ha++)j(b[ha])}function gb(a,b,e){a.setFullYear(a.getFullYear()+b);e||Ka(a);return a}function hb(a,b,e){if(+a){b=a.getMonth()+b;var d=N(a);d.setDate(1);d.setMonth(b);a.setMonth(b);for(e||Ka(a);a.getMonth()!=
+j(c)){G++;f(c,qa)}}function j(c){if(m.isFunction(c)||m.isArray(c))c={events:c};else if(typeof c=="string")c={url:c};if(typeof c=="object"){ga(c);U.push(c);return c}}function t(c){U=m.grep(U,function(z){return!ra(z,c)});L=m.grep(L,function(z){return!ra(z.source,c)});ua(L)}function y(c){var z,H=L.length,T,X=na().defaultEventEnd,ya=c.start-c._start,K=c.end?c.end-(c._end||X(c)):0;for(z=0;z<H;z++){T=L[z];if(T._id==c._id&&T!=c){T.start=new Date(+T.start+ya);T.end=c.end?T.end?new Date(+T.end+K):new Date(+X(T)+
+K):null;T.title=c.title;T.url=c.url;T.allDay=c.allDay;T.className=c.className;T.editable=c.editable;T.color=c.color;T.backgroudColor=c.backgroudColor;T.borderColor=c.borderColor;T.textColor=c.textColor;oa(T)}}oa(c);ua(L)}function S(c,z){oa(c);if(!c.source){if(z){pa.events.push(c);c.source=pa}L.push(c)}ua(L)}function Q(c){if(c){if(!m.isFunction(c)){var z=c+"";c=function(T){return T._id==z}}L=m.grep(L,c,true);for(H=0;H<U.length;H++)if(m.isArray(U[H].events))U[H].events=m.grep(U[H].events,c,true)}else{L=
+[];for(var H=0;H<U.length;H++)if(m.isArray(U[H].events))U[H].events=[]}ua(L)}function q(c){if(m.isFunction(c))return m.grep(L,c);else if(c){c+="";return m.grep(L,function(z){return z._id==c})}return L}function u(){p++||da("loading",null,true)}function fa(){--p||da("loading",null,false)}function oa(c){var z=c.source||{},H=Ta(z.ignoreTimezone,a.ignoreTimezone);c._id=c._id||(c.id===ma?"_fc"+bc++:c.id+"");if(c.date){if(!c.start)c.start=c.date;delete c.date}c._start=N(c.start=kb(c.start,H));c.end=kb(c.end,
+H);if(c.end&&c.end<=c.start)c.end=null;c._end=c.end?N(c.end):null;if(c.allDay===ma)c.allDay=Ta(z.allDayDefault,a.allDayDefault);if(c.className){if(typeof c.className=="string")c.className=c.className.split(/\s+/)}else c.className=[]}function ga(c){if(c.className){if(typeof c.className=="string")c.className=c.className.split(/\s+/)}else c.className=[];for(var z=Aa.sourceNormalizers,H=0;H<z.length;H++)z[H](c)}function ra(c,z){return c&&z&&sa(c)==sa(z)}function sa(c){return(typeof c=="object"?c.events||
+c.url:"")||c}var ha=this;ha.isFetchNeeded=e;ha.fetchEvents=d;ha.addEventSource=l;ha.removeEventSource=t;ha.updateEvent=y;ha.renderEvent=S;ha.removeEvents=Q;ha.clientEvents=q;ha.normalizeEvent=oa;var da=ha.trigger,na=ha.getView,ua=ha.reportEvents,pa={events:[]},U=[pa],ca,ka,qa=0,G=0,p=0,L=[];for(ha=0;ha<b.length;ha++)j(b[ha])}function gb(a,b,e){a.setFullYear(a.getFullYear()+b);e||Ka(a);return a}function hb(a,b,e){if(+a){b=a.getMonth()+b;var d=N(a);d.setDate(1);d.setMonth(b);a.setMonth(b);for(e||Ka(a);a.getMonth()!=
 d.getMonth();)a.setDate(a.getDate()+(a<d?1:-1))}return a}function ba(a,b,e){if(+a){b=a.getDate()+b;var d=N(a);d.setHours(9);d.setDate(b);a.setDate(b);e||Ka(a);lb(a,d)}return a}function lb(a,b){if(+a)for(;a.getDate()!=b.getDate();)a.setTime(+a+(a<b?1:-1)*cc)}function xa(a,b){a.setMinutes(a.getMinutes()+b);return a}function Ka(a){a.setHours(0);a.setMinutes(0);a.setSeconds(0);a.setMilliseconds(0);return a}function N(a,b){if(b)return Ka(new Date(+a));return new Date(+a)}function zb(){var a=0,b;do b=new Date(1970,
-a++,1);while(b.getHours());return b}function Fa(a,b,e){for(b=b||1;!a.getDay()||e&&a.getDay()==1||!e&&a.getDay()==6;)ba(a,b);return a}function Ca(a,b){return Math.round((N(a,true)-N(b,true))/Ab)}function yb(a,b,e,d){if(b!==oa&&b!=a.getFullYear()){a.setDate(1);a.setMonth(0);a.setFullYear(b)}if(e!==oa&&e!=a.getMonth()){a.setDate(1);a.setMonth(e)}d!==oa&&a.setDate(d)}function kb(a,b){if(typeof a=="object")return a;if(typeof a=="number")return new Date(a*1E3);if(typeof a=="string"){if(a.match(/^\d+(\.\d+)?$/))return new Date(parseFloat(a)*
-1E3);if(b===oa)b=true;return Bb(a,b)||(a?new Date(a):null)}return null}function Bb(a,b){a=a.match(/^([0-9]{4})(-([0-9]{2})(-([0-9]{2})([T ]([0-9]{2}):([0-9]{2})(:([0-9]{2})(\.([0-9]+))?)?(Z|(([-+])([0-9]{2})(:?([0-9]{2}))?))?)?)?)?$/);if(!a)return null;var e=new Date(a[1],0,1);if(b||!a[13]){b=new Date(a[1],0,1,9,0);if(a[3]){e.setMonth(a[3]-1);b.setMonth(a[3]-1)}if(a[5]){e.setDate(a[5]);b.setDate(a[5])}lb(e,b);a[7]&&e.setHours(a[7]);a[8]&&e.setMinutes(a[8]);a[10]&&e.setSeconds(a[10]);a[12]&&e.setMilliseconds(Number("0."+
+a++,1);while(b.getHours());return b}function Fa(a,b,e){for(b=b||1;!a.getDay()||e&&a.getDay()==1||!e&&a.getDay()==6;)ba(a,b);return a}function Ca(a,b){return Math.round((N(a,true)-N(b,true))/Ab)}function yb(a,b,e,d){if(b!==ma&&b!=a.getFullYear()){a.setDate(1);a.setMonth(0);a.setFullYear(b)}if(e!==ma&&e!=a.getMonth()){a.setDate(1);a.setMonth(e)}d!==ma&&a.setDate(d)}function kb(a,b){if(typeof a=="object")return a;if(typeof a=="number")return new Date(a*1E3);if(typeof a=="string"){if(a.match(/^\d+(\.\d+)?$/))return new Date(parseFloat(a)*
+1E3);if(b===ma)b=true;return Bb(a,b)||(a?new Date(a):null)}return null}function Bb(a,b){a=a.match(/^([0-9]{4})(-([0-9]{2})(-([0-9]{2})([T ]([0-9]{2}):([0-9]{2})(:([0-9]{2})(\.([0-9]+))?)?(Z|(([-+])([0-9]{2})(:?([0-9]{2}))?))?)?)?)?$/);if(!a)return null;var e=new Date(a[1],0,1);if(b||!a[13]){b=new Date(a[1],0,1,9,0);if(a[3]){e.setMonth(a[3]-1);b.setMonth(a[3]-1)}if(a[5]){e.setDate(a[5]);b.setDate(a[5])}lb(e,b);a[7]&&e.setHours(a[7]);a[8]&&e.setMinutes(a[8]);a[10]&&e.setSeconds(a[10]);a[12]&&e.setMilliseconds(Number("0."+
 a[12])*1E3);lb(e,b)}else{e.setUTCFullYear(a[1],a[3]?a[3]-1:0,a[5]||1);e.setUTCHours(a[7]||0,a[8]||0,a[10]||0,a[12]?Number("0."+a[12])*1E3:0);if(a[14]){b=Number(a[16])*60+(a[18]?Number(a[18]):0);b*=a[15]=="-"?1:-1;e=new Date(+e+b*60*1E3)}}return e}function mb(a){if(typeof a=="number")return a*60;if(typeof a=="object")return a.getHours()*60+a.getMinutes();if(a=a.match(/(\d+)(?::(\d+))?\s*(\w+)?/)){var b=parseInt(a[1],10);if(a[3]){b%=12;if(a[3].toLowerCase().charAt(0)=="p")b+=12}return b*60+(a[2]?parseInt(a[2],
 10):0)}}function Oa(a,b,e){return ib(a,null,b,e)}function ib(a,b,e,d){d=d||Ya;var f=a,g=b,l,j=e.length,t,y,S,Q="";for(l=0;l<j;l++){t=e.charAt(l);if(t=="'")for(y=l+1;y<j;y++){if(e.charAt(y)=="'"){if(f){Q+=y==l+1?"'":e.substring(l+1,y);l=y}break}}else if(t=="(")for(y=l+1;y<j;y++){if(e.charAt(y)==")"){l=Oa(f,e.substring(l+1,y),d);if(parseInt(l.replace(/\D/,""),10))Q+=l;l=y;break}}else if(t=="[")for(y=l+1;y<j;y++){if(e.charAt(y)=="]"){t=e.substring(l+1,y);l=Oa(f,t,d);if(l!=Oa(g,t,d))Q+=l;l=y;break}}else if(t==
 "{"){f=b;g=a}else if(t=="}"){f=a;g=b}else{for(y=j;y>l;y--)if(S=dc[e.substring(l,y)]){if(f)Q+=S(f,d);l=y-1;break}if(y==l)if(f)Q+=t}}return Q}function Ua(a){return a.end?ec(a.end,a.allDay):ba(N(a.start),1)}function ec(a,b){a=N(a);return b||a.getHours()||a.getMinutes()?ba(a,1):Ka(a)}function fc(a,b){return(b.msLength-a.msLength)*100+(a.event.start-b.event.start)}function Cb(a,b){return a.end>b.start&&a.start<b.end}function nb(a,b,e,d){var f=[],g,l=a.length,j,t,y,S,Q;for(g=0;g<l;g++){j=a[g];t=j.start;
 y=b[g];if(y>e&&t<d){if(t<e){t=N(e);S=false}else{t=t;S=true}if(y>d){y=N(d);Q=false}else{y=y;Q=true}f.push({event:j,start:t,end:y,isStart:S,isEnd:Q,msLength:y-t})}}return f.sort(fc)}function ob(a){var b=[],e,d=a.length,f,g,l,j;for(e=0;e<d;e++){f=a[e];for(g=0;;){l=false;if(b[g])for(j=0;j<b[g].length;j++)if(Cb(b[g][j],f)){l=true;break}if(l)g++;else break}if(b[g])b[g].push(f);else b[g]=[f]}return b}function Db(a,b,e){a.unbind("mouseover").mouseover(function(d){for(var f=d.target,g;f!=this;){g=f;f=f.parentNode}if((f=
-g._fci)!==oa){g._fci=oa;g=b[f];e(g.event,g.element,g);m(d.target).trigger(d)}d.stopPropagation()})}function Va(a,b,e){for(var d=0,f;d<a.length;d++){f=m(a[d]);f.width(Math.max(0,b-pb(f,e)))}}function Eb(a,b,e){for(var d=0,f;d<a.length;d++){f=m(a[d]);f.height(Math.max(0,b-Sa(f,e)))}}function pb(a,b){return gc(a)+hc(a)+(b?ic(a):0)}function gc(a){return(parseFloat(m.curCSS(a[0],"paddingLeft",true))||0)+(parseFloat(m.curCSS(a[0],"paddingRight",true))||0)}function ic(a){return(parseFloat(m.curCSS(a[0],
+g._fci)!==ma){g._fci=ma;g=b[f];e(g.event,g.element,g);m(d.target).trigger(d)}d.stopPropagation()})}function Va(a,b,e){for(var d=0,f;d<a.length;d++){f=m(a[d]);f.width(Math.max(0,b-pb(f,e)))}}function Eb(a,b,e){for(var d=0,f;d<a.length;d++){f=m(a[d]);f.height(Math.max(0,b-Sa(f,e)))}}function pb(a,b){return gc(a)+hc(a)+(b?ic(a):0)}function gc(a){return(parseFloat(m.curCSS(a[0],"paddingLeft",true))||0)+(parseFloat(m.curCSS(a[0],"paddingRight",true))||0)}function ic(a){return(parseFloat(m.curCSS(a[0],
 "marginLeft",true))||0)+(parseFloat(m.curCSS(a[0],"marginRight",true))||0)}function hc(a){return(parseFloat(m.curCSS(a[0],"borderLeftWidth",true))||0)+(parseFloat(m.curCSS(a[0],"borderRightWidth",true))||0)}function Sa(a,b){return jc(a)+kc(a)+(b?Fb(a):0)}function jc(a){return(parseFloat(m.curCSS(a[0],"paddingTop",true))||0)+(parseFloat(m.curCSS(a[0],"paddingBottom",true))||0)}function Fb(a){return(parseFloat(m.curCSS(a[0],"marginTop",true))||0)+(parseFloat(m.curCSS(a[0],"marginBottom",true))||0)}
-function kc(a){return(parseFloat(m.curCSS(a[0],"borderTopWidth",true))||0)+(parseFloat(m.curCSS(a[0],"borderBottomWidth",true))||0)}function Za(a,b){b=typeof b=="number"?b+"px":b;a.each(function(e,d){d.style.cssText+=";min-height:"+b+";_height:"+b})}function xb(){}function Gb(a,b){return a-b}function Hb(a){return Math.max.apply(Math,a)}function Pa(a){return(a<10?"0":"")+a}function jb(a,b){if(a[b]!==oa)return a[b];b=b.split(/(?=[A-Z])/);for(var e=b.length-1,d;e>=0;e--){d=a[b[e].toLowerCase()];if(d!==
-oa)return d}return a[""]}function Qa(a){return a.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/'/g,"&#039;").replace(/"/g,"&quot;").replace(/\n/g,"<br />")}function Ib(a){return a.id+"/"+a.className+"/"+a.style.cssText.replace(/(^|;)\s*(top|left|width|height)\s*:[^;]*/ig,"")}function qb(a){a.attr("unselectable","on").css("MozUserSelect","none").bind("selectstart.ui",function(){return false})}function ab(a){a.children().removeClass("fc-first fc-last").filter(":first-child").addClass("fc-first").end().filter(":last-child").addClass("fc-last")}
+function kc(a){return(parseFloat(m.curCSS(a[0],"borderTopWidth",true))||0)+(parseFloat(m.curCSS(a[0],"borderBottomWidth",true))||0)}function Za(a,b){b=typeof b=="number"?b+"px":b;a.each(function(e,d){d.style.cssText+=";min-height:"+b+";_height:"+b})}function xb(){}function Gb(a,b){return a-b}function Hb(a){return Math.max.apply(Math,a)}function Pa(a){return(a<10?"0":"")+a}function jb(a,b){if(a[b]!==ma)return a[b];b=b.split(/(?=[A-Z])/);for(var e=b.length-1,d;e>=0;e--){d=a[b[e].toLowerCase()];if(d!==
+ma)return d}return a[""]}function Qa(a){return a.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/'/g,"&#039;").replace(/"/g,"&quot;").replace(/\n/g,"<br />")}function Ib(a){return a.id+"/"+a.className+"/"+a.style.cssText.replace(/(^|;)\s*(top|left|width|height)\s*:[^;]*/ig,"")}function qb(a){a.attr("unselectable","on").css("MozUserSelect","none").bind("selectstart.ui",function(){return false})}function ab(a){a.children().removeClass("fc-first fc-last").filter(":first-child").addClass("fc-first").end().filter(":last-child").addClass("fc-last")}
 function rb(a,b){a.each(function(e,d){d.className=d.className.replace(/^fc-\w*/,"fc-"+lc[b.getDay()])})}function Jb(a,b){var e=a.source||{},d=a.color,f=e.color,g=b("eventColor"),l=a.backgroundColor||d||e.backgroundColor||f||b("eventBackgroundColor")||g;d=a.borderColor||d||e.borderColor||f||b("eventBorderColor")||g;a=a.textColor||e.textColor||b("eventTextColor");b=[];l&&b.push("background-color:"+l);d&&b.push("border-color:"+d);a&&b.push("color:"+a);return b.join(";")}function $a(a,b,e){if(m.isFunction(a))a=
-[a];if(a){var d,f;for(d=0;d<a.length;d++)f=a[d].apply(b,e)||f;return f}}function Ta(){for(var a=0;a<arguments.length;a++)if(arguments[a]!==oa)return arguments[a]}function mc(a,b){function e(j,t){if(t){hb(j,t);j.setDate(1)}j=N(j,true);j.setDate(1);t=hb(N(j),1);var y=N(j),S=N(t),Q=f("firstDay"),q=f("weekends")?0:1;if(q){Fa(y);Fa(S,-1,true)}ba(y,-((y.getDay()-Math.max(Q,q)+7)%7));ba(S,(7-S.getDay()+Math.max(Q,q))%7);Q=Math.round((S-y)/(Ab*7));if(f("weekMode")=="fixed"){ba(S,(6-Q)*7);Q=6}d.title=l(j,
+[a];if(a){var d,f;for(d=0;d<a.length;d++)f=a[d].apply(b,e)||f;return f}}function Ta(){for(var a=0;a<arguments.length;a++)if(arguments[a]!==ma)return arguments[a]}function mc(a,b){function e(j,t){if(t){hb(j,t);j.setDate(1)}j=N(j,true);j.setDate(1);t=hb(N(j),1);var y=N(j),S=N(t),Q=f("firstDay"),q=f("weekends")?0:1;if(q){Fa(y);Fa(S,-1,true)}ba(y,-((y.getDay()-Math.max(Q,q)+7)%7));ba(S,(7-S.getDay()+Math.max(Q,q))%7);Q=Math.round((S-y)/(Ab*7));if(f("weekMode")=="fixed"){ba(S,(6-Q)*7);Q=6}d.title=l(j,
 f("titleFormat"));d.start=j;d.end=t;d.visStart=y;d.visEnd=S;g(6,Q,q?5:7,true)}var d=this;d.render=e;sb.call(d,a,b,"month");var f=d.opt,g=d.renderBasic,l=b.formatDate}function nc(a,b){function e(j,t){t&&ba(j,t*7);j=ba(N(j),-((j.getDay()-f("firstDay")+7)%7));t=ba(N(j),7);var y=N(j),S=N(t),Q=f("weekends");if(!Q){Fa(y);Fa(S,-1,true)}d.title=l(y,ba(N(S),-1),f("titleFormat"));d.start=j;d.end=t;d.visStart=y;d.visEnd=S;g(1,1,Q?7:5,false)}var d=this;d.render=e;sb.call(d,a,b,"basicWeek");var f=d.opt,g=d.renderBasic,
 l=b.formatDates}function oc(a,b){function e(j,t){if(t){ba(j,t);f("weekends")||Fa(j,t<0?-1:1)}d.title=l(j,f("titleFormat"));d.start=d.visStart=N(j,true);d.end=d.visEnd=ba(N(d.start),1);g(1,1,1,false)}var d=this;d.render=e;sb.call(d,a,b,"basicDay");var f=d.opt,g=d.renderBasic,l=b.formatDate}function sb(a,b,e){function d(w,I,R,V){v=I;F=R;f();(I=!C)?g(w,V):z();l(I)}function f(){if(k=L("isRTL")){D=-1;Z=F-1}else{D=1;Z=0}ja=L("firstDay");ia=L("weekends")?0:1;la=L("theme")?"ui":"fc";$=L("columnFormat")}function g(w,
 I){var R,V=la+"-widget-header",ea=la+"-widget-content",aa;R="<table class='fc-border-separate' style='width:100%' cellspacing='0'><thead><tr>";for(aa=0;aa<F;aa++)R+="<th class='fc- "+V+"'/>";R+="</tr></thead><tbody>";for(aa=0;aa<w;aa++){R+="<tr class='fc-week"+aa+"'>";for(V=0;V<F;V++)R+="<td class='fc- "+ea+" fc-day"+(aa*F+V)+"'><div>"+(I?"<div class='fc-day-number'/>":"")+"<div class='fc-day-content'><div style='position:relative'>&nbsp;</div></div></div></td>";R+="</tr>"}R+="</tbody></table>";w=
 m(R).appendTo(a);K=w.find("thead");i=K.find("th");C=w.find("tbody");P=C.find("tr");E=C.find("td");B=E.filter(":first-child");n=P.eq(0).find("div.fc-day-content div");ab(K.add(K.find("tr")));ab(P);P.eq(0).addClass("fc-first");y(E);Y=m("<div style='position:absolute;z-index:8;top:0;left:0'/>").appendTo(a)}function l(w){var I=w||v==1,R=p.start.getMonth(),V=Ka(new Date),ea,aa,va;I&&i.each(function(wa,Ga){ea=m(Ga);aa=ca(wa);ea.html(ya(aa,$));rb(ea,aa)});E.each(function(wa,Ga){ea=m(Ga);aa=ca(wa);aa.getMonth()==
 R?ea.removeClass("fc-other-month"):ea.addClass("fc-other-month");+aa==+V?ea.addClass(la+"-state-highlight fc-today"):ea.removeClass(la+"-state-highlight fc-today");ea.find("div.fc-day-number").text(aa.getDate());I&&rb(ea,aa)});P.each(function(wa,Ga){va=m(Ga);if(wa<v){va.show();wa==v-1?va.addClass("fc-last"):va.removeClass("fc-last")}else va.hide()})}function j(w){o=w;w=o-K.height();var I,R,V;if(L("weekMode")=="variable")I=R=Math.floor(w/(v==1?2:6));else{I=Math.floor(w/v);R=w-I*(v-1)}B.each(function(ea,
 aa){if(ea<v){V=m(aa);Za(V.find("> div"),(ea==v-1?R:I)-Sa(V))}})}function t(w){W=w;M.clear();s=Math.floor(W/F);Va(i.slice(0,-1),s)}function y(w){w.click(S).mousedown(X)}function S(w){if(!L("selectable")){var I=parseInt(this.className.match(/fc\-day(\d+)/)[1]);I=ca(I);c("dayClick",this,I,true,w)}}function Q(w,I,R){R&&r.build();R=N(p.visStart);for(var V=ba(N(R),F),ea=0;ea<v;ea++){var aa=new Date(Math.max(R,w)),va=new Date(Math.min(V,I));if(aa<va){var wa;if(k){wa=Ca(va,R)*D+Z+1;aa=Ca(aa,R)*D+Z+1}else{wa=
-Ca(aa,R);aa=Ca(va,R)}y(q(ea,wa,ea,aa-1))}ba(R,7);ba(V,7)}}function q(w,I,R,V){w=r.rect(w,I,R,V,a);return H(w,a)}function u(w){return N(w)}function fa(w,I){Q(w,ba(N(I),1),true)}function na(){T()}function ga(w,I,R){var V=ua(w);c("dayClick",E[V.row*F+V.col],w,I,R)}function ra(w,I){J.start(function(R){T();R&&q(R.row,R.col,R.row,R.col)},I)}function sa(w,I,R){var V=J.stop();T();if(V){V=pa(V);c("drop",w,V,true,I,R)}}function ha(w){return N(w.start)}function da(w){return M.left(w)}function ma(w){return M.right(w)}
-function ua(w){return{row:Math.floor(Ca(w,p.visStart)/7),col:ka(w.getDay())}}function pa(w){return U(w.row,w.col)}function U(w,I){return ba(N(p.visStart),w*7+I*D+Z)}function ca(w){return U(Math.floor(w/F),w%F)}function ka(w){return(w-Math.max(ja,ia)+F)%F*D+Z}function qa(w){return P.eq(w)}function G(){return{left:0,right:W}}var p=this;p.renderBasic=d;p.setHeight=j;p.setWidth=t;p.renderDayOverlay=Q;p.defaultSelectionEnd=u;p.renderSelection=fa;p.clearSelection=na;p.reportDayClick=ga;p.dragStart=ra;p.dragStop=
-sa;p.defaultEventEnd=ha;p.getHoverListener=function(){return J};p.colContentLeft=da;p.colContentRight=ma;p.dayOfWeekCol=ka;p.dateCell=ua;p.cellDate=pa;p.cellIsAllDay=function(){return true};p.allDayRow=qa;p.allDayBounds=G;p.getRowCnt=function(){return v};p.getColCnt=function(){return F};p.getColWidth=function(){return s};p.getDaySegmentContainer=function(){return Y};Kb.call(p,a,b,e);Lb.call(p);Mb.call(p);pc.call(p);var L=p.opt,c=p.trigger,z=p.clearEvents,H=p.renderOverlay,T=p.clearOverlays,X=p.daySelectionMousedown,
+Ca(aa,R);aa=Ca(va,R)}y(q(ea,wa,ea,aa-1))}ba(R,7);ba(V,7)}}function q(w,I,R,V){w=r.rect(w,I,R,V,a);return H(w,a)}function u(w){return N(w)}function fa(w,I){Q(w,ba(N(I),1),true)}function oa(){T()}function ga(w,I,R){var V=ua(w);c("dayClick",E[V.row*F+V.col],w,I,R)}function ra(w,I){J.start(function(R){T();R&&q(R.row,R.col,R.row,R.col)},I)}function sa(w,I,R){var V=J.stop();T();if(V){V=pa(V);c("drop",w,V,true,I,R)}}function ha(w){return N(w.start)}function da(w){return M.left(w)}function na(w){return M.right(w)}
+function ua(w){return{row:Math.floor(Ca(w,p.visStart)/7),col:ka(w.getDay())}}function pa(w){return U(w.row,w.col)}function U(w,I){return ba(N(p.visStart),w*7+I*D+Z)}function ca(w){return U(Math.floor(w/F),w%F)}function ka(w){return(w-Math.max(ja,ia)+F)%F*D+Z}function qa(w){return P.eq(w)}function G(){return{left:0,right:W}}var p=this;p.renderBasic=d;p.setHeight=j;p.setWidth=t;p.renderDayOverlay=Q;p.defaultSelectionEnd=u;p.renderSelection=fa;p.clearSelection=oa;p.reportDayClick=ga;p.dragStart=ra;p.dragStop=
+sa;p.defaultEventEnd=ha;p.getHoverListener=function(){return J};p.colContentLeft=da;p.colContentRight=na;p.dayOfWeekCol=ka;p.dateCell=ua;p.cellDate=pa;p.cellIsAllDay=function(){return true};p.allDayRow=qa;p.allDayBounds=G;p.getRowCnt=function(){return v};p.getColCnt=function(){return F};p.getColWidth=function(){return s};p.getDaySegmentContainer=function(){return Y};Kb.call(p,a,b,e);Lb.call(p);Mb.call(p);pc.call(p);var L=p.opt,c=p.trigger,z=p.clearEvents,H=p.renderOverlay,T=p.clearOverlays,X=p.daySelectionMousedown,
 ya=b.formatDate,K,i,C,P,E,B,n,Y,W,o,s,v,F,r,J,M,k,D,Z,ja,ia,la,$;qb(a.addClass("fc-grid"));r=new Nb(function(w,I){var R,V,ea;i.each(function(aa,va){R=m(va);V=R.offset().left;if(aa)ea[1]=V;ea=[V];I[aa]=ea});ea[1]=V+R.outerWidth();P.each(function(aa,va){if(aa<v){R=m(va);V=R.offset().top;if(aa)ea[1]=V;ea=[V];w[aa]=ea}});ea[1]=V+R.outerHeight()});J=new Ob(r);M=new Pb(function(w){return n.eq(w)})}function pc(){function a(U,ca){S(U);ua(e(U),ca)}function b(){Q();ga().empty()}function e(U){var ca=da(),ka=
-ma(),qa=N(g.visStart);ka=ba(N(qa),ka);var G=m.map(U,Ua),p,L,c,z,H,T,X=[];for(p=0;p<ca;p++){L=ob(nb(U,G,qa,ka));for(c=0;c<L.length;c++){z=L[c];for(H=0;H<z.length;H++){T=z[H];T.row=p;T.level=c;X.push(T)}}ba(qa,7);ba(ka,7)}return X}function d(U,ca,ka){t(U)&&f(U,ca);ka.isEnd&&y(U)&&pa(U,ca,ka);q(U,ca)}function f(U,ca){var ka=ra(),qa;ca.draggable({zIndex:9,delay:50,opacity:l("dragOpacity"),revertDuration:l("dragRevertDuration"),start:function(G,p){j("eventDragStart",ca,U,G,p);fa(U,ca);ka.start(function(L,
-c,z,H){ca.draggable("option","revert",!L||!z&&!H);ha();if(L){qa=z*7+H*(l("isRTL")?-1:1);sa(ba(N(U.start),qa),ba(Ua(U),qa))}else qa=0},G,"drag")},stop:function(G,p){ka.stop();ha();j("eventDragStop",ca,U,G,p);if(qa)na(this,U,qa,0,U.allDay,G,p);else{ca.css("filter","");u(U,ca)}}})}var g=this;g.renderEvents=a;g.compileDaySegs=e;g.clearEvents=b;g.bindDaySeg=d;Qb.call(g);var l=g.opt,j=g.trigger,t=g.isEventDraggable,y=g.isEventResizable,S=g.reportEvents,Q=g.reportEventClear,q=g.eventElementHandlers,u=g.showEvents,
-fa=g.hideEvents,na=g.eventDrop,ga=g.getDaySegmentContainer,ra=g.getHoverListener,sa=g.renderDayOverlay,ha=g.clearOverlays,da=g.getRowCnt,ma=g.getColCnt,ua=g.renderDaySegs,pa=g.resizableDayEvent}function qc(a,b){function e(j,t){t&&ba(j,t*7);j=ba(N(j),-((j.getDay()-f("firstDay")+7)%7));t=ba(N(j),7);var y=N(j),S=N(t),Q=f("weekends");if(!Q){Fa(y);Fa(S,-1,true)}d.title=l(y,ba(N(S),-1),f("titleFormat"));d.start=j;d.end=t;d.visStart=y;d.visEnd=S;g(Q?7:5)}var d=this;d.render=e;Rb.call(d,a,b,"agendaWeek");
+na(),qa=N(g.visStart);ka=ba(N(qa),ka);var G=m.map(U,Ua),p,L,c,z,H,T,X=[];for(p=0;p<ca;p++){L=ob(nb(U,G,qa,ka));for(c=0;c<L.length;c++){z=L[c];for(H=0;H<z.length;H++){T=z[H];T.row=p;T.level=c;X.push(T)}}ba(qa,7);ba(ka,7)}return X}function d(U,ca,ka){t(U)&&f(U,ca);ka.isEnd&&y(U)&&pa(U,ca,ka);q(U,ca)}function f(U,ca){var ka=ra(),qa;ca.draggable({zIndex:9,delay:50,opacity:l("dragOpacity"),revertDuration:l("dragRevertDuration"),start:function(G,p){j("eventDragStart",ca,U,G,p);fa(U,ca);ka.start(function(L,
+c,z,H){ca.draggable("option","revert",!L||!z&&!H);ha();if(L){qa=z*7+H*(l("isRTL")?-1:1);sa(ba(N(U.start),qa),ba(Ua(U),qa))}else qa=0},G,"drag")},stop:function(G,p){ka.stop();ha();j("eventDragStop",ca,U,G,p);if(qa)oa(this,U,qa,0,U.allDay,G,p);else{ca.css("filter","");u(U,ca)}}})}var g=this;g.renderEvents=a;g.compileDaySegs=e;g.clearEvents=b;g.bindDaySeg=d;Qb.call(g);var l=g.opt,j=g.trigger,t=g.isEventDraggable,y=g.isEventResizable,S=g.reportEvents,Q=g.reportEventClear,q=g.eventElementHandlers,u=g.showEvents,
+fa=g.hideEvents,oa=g.eventDrop,ga=g.getDaySegmentContainer,ra=g.getHoverListener,sa=g.renderDayOverlay,ha=g.clearOverlays,da=g.getRowCnt,na=g.getColCnt,ua=g.renderDaySegs,pa=g.resizableDayEvent}function qc(a,b){function e(j,t){t&&ba(j,t*7);j=ba(N(j),-((j.getDay()-f("firstDay")+7)%7));t=ba(N(j),7);var y=N(j),S=N(t),Q=f("weekends");if(!Q){Fa(y);Fa(S,-1,true)}d.title=l(y,ba(N(S),-1),f("titleFormat"));d.start=j;d.end=t;d.visStart=y;d.visEnd=S;g(Q?7:5)}var d=this;d.render=e;Rb.call(d,a,b,"agendaWeek");
 var f=d.opt,g=d.renderAgenda,l=b.formatDates}function rc(a,b){function e(j,t){if(t){ba(j,t);f("weekends")||Fa(j,t<0?-1:1)}t=N(j,true);var y=ba(N(t),1);d.title=l(j,f("titleFormat"));d.start=d.visStart=t;d.end=d.visEnd=y;g(1)}var d=this;d.render=e;Rb.call(d,a,b,"agendaDay");var f=d.opt,g=d.renderAgenda,l=b.formatDate}function Rb(a,b,e){function d(h){Ba=h;f();v?P():g();l()}function f(){Wa=i("theme")?"ui":"fc";Sb=i("weekends")?0:1;Tb=i("firstDay");if(Ub=i("isRTL")){Ha=-1;Ia=Ba-1}else{Ha=1;Ia=0}La=mb(i("minTime"));
 bb=mb(i("maxTime"));Vb=i("columnFormat")}function g(){var h=Wa+"-widget-header",O=Wa+"-widget-content",x,A,ta,za,Da,Ea=i("slotMinutes")%15==0;x="<table style='width:100%' class='fc-agenda-days fc-border-separate' cellspacing='0'><thead><tr><th class='fc-agenda-axis "+h+"'>&nbsp;</th>";for(A=0;A<Ba;A++)x+="<th class='fc- fc-col"+A+" "+h+"'/>";x+="<th class='fc-agenda-gutter "+h+"'>&nbsp;</th></tr></thead><tbody><tr><th class='fc-agenda-axis "+h+"'>&nbsp;</th>";for(A=0;A<Ba;A++)x+="<td class='fc- fc-col"+
 A+" "+O+"'><div><div class='fc-day-content'><div style='position:relative'>&nbsp;</div></div></div></td>";x+="<td class='fc-agenda-gutter "+O+"'>&nbsp;</td></tr></tbody></table>";v=m(x).appendTo(a);F=v.find("thead");r=F.find("th").slice(1,-1);J=v.find("tbody");M=J.find("td").slice(0,-1);k=M.find("div.fc-day-content div");D=M.eq(0);Z=D.find("> div");ab(F.add(F.find("tr")));ab(J.add(J.find("tr")));aa=F.find("th:first");va=v.find(".fc-agenda-gutter");ja=m("<div style='position:absolute;z-index:2;left:0;width:100%'/>").appendTo(a);
 if(i("allDaySlot")){ia=m("<div style='position:absolute;z-index:8;top:0;left:0'/>").appendTo(ja);x="<table style='width:100%' class='fc-agenda-allday' cellspacing='0'><tr><th class='"+h+" fc-agenda-axis'>"+i("allDayText")+"</th><td><div class='fc-day-content'><div style='position:relative'/></div></td><th class='"+h+" fc-agenda-gutter'>&nbsp;</th></tr></table>";la=m(x).appendTo(ja);$=la.find("tr");q($.find("td"));aa=aa.add(la.find("th:first"));va=va.add(la.find("th.fc-agenda-gutter"));ja.append("<div class='fc-agenda-divider "+
 h+"'><div class='fc-agenda-divider-inner'/></div>")}else ia=m([]);w=m("<div style='position:absolute;width:100%;overflow-x:hidden;overflow-y:auto'/>").appendTo(ja);I=m("<div style='position:relative;width:100%;overflow:hidden'/>").appendTo(w);R=m("<div style='position:absolute;z-index:8;top:0;left:0'/>").appendTo(I);x="<table class='fc-agenda-slots' style='width:100%' cellspacing='0'><tbody>";ta=zb();za=xa(N(ta),bb);xa(ta,La);for(A=tb=0;ta<za;A++){Da=ta.getMinutes();x+="<tr class='fc-slot"+A+" "+
 (!Da?"":"fc-minor")+"'><th class='fc-agenda-axis "+h+"'>"+(!Ea||!Da?s(ta,i("axisFormat")):"&nbsp;")+"</th><td class='"+O+"'><div style='position:relative'>&nbsp;</div></td></tr>";xa(ta,i("slotMinutes"));tb++}x+="</tbody></table>";V=m(x).appendTo(I);ea=V.find("div:first");u(V.find("td"));aa=aa.add(V.find("th:first"))}function l(){var h,O,x,A,ta=Ka(new Date);for(h=0;h<Ba;h++){A=ua(h);O=r.eq(h);O.html(s(A,Vb));x=M.eq(h);+A==+ta?x.addClass(Wa+"-state-highlight fc-today"):x.removeClass(Wa+"-state-highlight fc-today");
-rb(O.add(x),A)}}function j(h,O){if(h===oa)h=Wb;Wb=h;ub={};var x=J.position().top,A=w.position().top;h=Math.min(h-x,V.height()+A+1);Z.height(h-Sa(D));ja.css("top",x);w.height(h-A-1);Xa=ea.height()+1;O&&y()}function t(h){Ga=h;cb.clear();Ma=0;Va(aa.width("").each(function(O,x){Ma=Math.max(Ma,m(x).outerWidth())}),Ma);h=w[0].clientWidth;if(vb=w.width()-h){Va(va,vb);va.show().prev().removeClass("fc-last")}else va.hide().prev().addClass("fc-last");db=Math.floor((h-Ma)/Ba);Va(r.slice(0,-1),db)}function y(){function h(){w.scrollTop(A)}
+rb(O.add(x),A)}}function j(h,O){if(h===ma)h=Wb;Wb=h;ub={};var x=J.position().top,A=w.position().top;h=Math.min(h-x,V.height()+A+1);Z.height(h-Sa(D));ja.css("top",x);w.height(h-A-1);Xa=ea.height()+1;O&&y()}function t(h){Ga=h;cb.clear();Ma=0;Va(aa.width("").each(function(O,x){Ma=Math.max(Ma,m(x).outerWidth())}),Ma);h=w[0].clientWidth;if(vb=w.width()-h){Va(va,vb);va.show().prev().removeClass("fc-last")}else va.hide().prev().addClass("fc-last");db=Math.floor((h-Ma)/Ba);Va(r.slice(0,-1),db)}function y(){function h(){w.scrollTop(A)}
 var O=zb(),x=N(O);x.setHours(i("firstHour"));var A=ca(O,x)+1;h();setTimeout(h,0)}function S(){Xb=w.scrollTop()}function Q(){w.scrollTop(Xb)}function q(h){h.click(fa).mousedown(W)}function u(h){h.click(fa).mousedown(H)}function fa(h){if(!i("selectable")){var O=Math.min(Ba-1,Math.floor((h.pageX-v.offset().left-Ma)/db)),x=ua(O),A=this.parentNode.className.match(/fc-slot(\d+)/);if(A){A=parseInt(A[1])*i("slotMinutes");var ta=Math.floor(A/60);x.setHours(ta);x.setMinutes(A%60+La);C("dayClick",M[O],x,false,
-h)}else C("dayClick",M[O],x,true,h)}}function na(h,O,x){x&&Na.build();var A=N(K.visStart);if(Ub){x=Ca(O,A)*Ha+Ia+1;h=Ca(h,A)*Ha+Ia+1}else{x=Ca(h,A);h=Ca(O,A)}x=Math.max(0,x);h=Math.min(Ba,h);x<h&&q(ga(0,x,0,h-1))}function ga(h,O,x,A){h=Na.rect(h,O,x,A,ja);return E(h,ja)}function ra(h,O){for(var x=N(K.visStart),A=ba(N(x),1),ta=0;ta<Ba;ta++){var za=new Date(Math.max(x,h)),Da=new Date(Math.min(A,O));if(za<Da){var Ea=ta*Ha+Ia;Ea=Na.rect(0,Ea,0,Ea,I);za=ca(x,za);Da=ca(x,Da);Ea.top=za;Ea.height=Da-za;u(E(Ea,
-I))}ba(x,1);ba(A,1)}}function sa(h){return cb.left(h)}function ha(h){return cb.right(h)}function da(h){return{row:Math.floor(Ca(h,K.visStart)/7),col:U(h.getDay())}}function ma(h){var O=ua(h.col);h=h.row;i("allDaySlot")&&h--;h>=0&&xa(O,La+h*i("slotMinutes"));return O}function ua(h){return ba(N(K.visStart),h*Ha+Ia)}function pa(h){return i("allDaySlot")&&!h.row}function U(h){return(h-Math.max(Tb,Sb)+Ba)%Ba*Ha+Ia}function ca(h,O){h=N(h,true);if(O<xa(N(h),La))return 0;if(O>=xa(N(h),bb))return V.height();
-h=i("slotMinutes");O=O.getHours()*60+O.getMinutes()-La;var x=Math.floor(O/h),A=ub[x];if(A===oa)A=ub[x]=V.find("tr:eq("+x+") td div")[0].offsetTop;return Math.max(0,Math.round(A-1+Xa*(O%h/h)))}function ka(){return{left:Ma,right:Ga-vb}}function qa(){return $}function G(h){var O=N(h.start);if(h.allDay)return O;return xa(O,i("defaultEventMinutes"))}function p(h,O){if(O)return N(h);return xa(N(h),i("slotMinutes"))}function L(h,O,x){if(x)i("allDaySlot")&&na(h,ba(N(O),1),true);else c(h,O)}function c(h,O){var x=
+h)}else C("dayClick",M[O],x,true,h)}}function oa(h,O,x){x&&Na.build();var A=N(K.visStart);if(Ub){x=Ca(O,A)*Ha+Ia+1;h=Ca(h,A)*Ha+Ia+1}else{x=Ca(h,A);h=Ca(O,A)}x=Math.max(0,x);h=Math.min(Ba,h);x<h&&q(ga(0,x,0,h-1))}function ga(h,O,x,A){h=Na.rect(h,O,x,A,ja);return E(h,ja)}function ra(h,O){for(var x=N(K.visStart),A=ba(N(x),1),ta=0;ta<Ba;ta++){var za=new Date(Math.max(x,h)),Da=new Date(Math.min(A,O));if(za<Da){var Ea=ta*Ha+Ia;Ea=Na.rect(0,Ea,0,Ea,I);za=ca(x,za);Da=ca(x,Da);Ea.top=za;Ea.height=Da-za;u(E(Ea,
+I))}ba(x,1);ba(A,1)}}function sa(h){return cb.left(h)}function ha(h){return cb.right(h)}function da(h){return{row:Math.floor(Ca(h,K.visStart)/7),col:U(h.getDay())}}function na(h){var O=ua(h.col);h=h.row;i("allDaySlot")&&h--;h>=0&&xa(O,La+h*i("slotMinutes"));return O}function ua(h){return ba(N(K.visStart),h*Ha+Ia)}function pa(h){return i("allDaySlot")&&!h.row}function U(h){return(h-Math.max(Tb,Sb)+Ba)%Ba*Ha+Ia}function ca(h,O){h=N(h,true);if(O<xa(N(h),La))return 0;if(O>=xa(N(h),bb))return V.height();
+h=i("slotMinutes");O=O.getHours()*60+O.getMinutes()-La;var x=Math.floor(O/h),A=ub[x];if(A===ma)A=ub[x]=V.find("tr:eq("+x+") td div")[0].offsetTop;return Math.max(0,Math.round(A-1+Xa*(O%h/h)))}function ka(){return{left:Ma,right:Ga-vb}}function qa(){return $}function G(h){var O=N(h.start);if(h.allDay)return O;return xa(O,i("defaultEventMinutes"))}function p(h,O){if(O)return N(h);return xa(N(h),i("slotMinutes"))}function L(h,O,x){if(x)i("allDaySlot")&&oa(h,ba(N(O),1),true);else c(h,O)}function c(h,O){var x=
 i("selectHelper");Na.build();if(x){var A=Ca(h,K.visStart)*Ha+Ia;if(A>=0&&A<Ba){A=Na.rect(0,A,0,A,I);var ta=ca(h,h),za=ca(h,O);if(za>ta){A.top=ta;A.height=za-ta;A.left+=2;A.width-=5;if(m.isFunction(x)){if(h=x(h,O)){A.position="absolute";A.zIndex=8;wa=m(h).css(A).appendTo(I)}}else{A.isStart=true;A.isEnd=true;wa=m(o({title:"",start:h,end:O,className:["fc-select-helper"],editable:false},A));wa.css("opacity",i("dragOpacity"))}if(wa){u(wa);I.append(wa);Va(wa,A.width,true);Eb(wa,A.height,true)}}}}else ra(h,
-O)}function z(){B();if(wa){wa.remove();wa=null}}function H(h){if(h.which==1&&i("selectable")){Y(h);var O;Ra.start(function(x,A){z();if(x&&x.col==A.col&&!pa(x)){A=ma(A);x=ma(x);O=[A,xa(N(A),i("slotMinutes")),x,xa(N(x),i("slotMinutes"))].sort(Gb);c(O[0],O[3])}else O=null},h);m(document).one("mouseup",function(x){Ra.stop();if(O){+O[0]==+O[1]&&T(O[0],false,x);n(O[0],O[3],false,x)}})}}function T(h,O,x){C("dayClick",M[U(h.getDay())],h,O,x)}function X(h,O){Ra.start(function(x){B();if(x)if(pa(x))ga(x.row,
-x.col,x.row,x.col);else{x=ma(x);var A=xa(N(x),i("defaultEventMinutes"));ra(x,A)}},O)}function ya(h,O,x){var A=Ra.stop();B();A&&C("drop",h,ma(A),pa(A),O,x)}var K=this;K.renderAgenda=d;K.setWidth=t;K.setHeight=j;K.beforeHide=S;K.afterShow=Q;K.defaultEventEnd=G;K.timePosition=ca;K.dayOfWeekCol=U;K.dateCell=da;K.cellDate=ma;K.cellIsAllDay=pa;K.allDayRow=qa;K.allDayBounds=ka;K.getHoverListener=function(){return Ra};K.colContentLeft=sa;K.colContentRight=ha;K.getDaySegmentContainer=function(){return ia};
-K.getSlotSegmentContainer=function(){return R};K.getMinMinute=function(){return La};K.getMaxMinute=function(){return bb};K.getBodyContent=function(){return I};K.getRowCnt=function(){return 1};K.getColCnt=function(){return Ba};K.getColWidth=function(){return db};K.getSlotHeight=function(){return Xa};K.defaultSelectionEnd=p;K.renderDayOverlay=na;K.renderSelection=L;K.clearSelection=z;K.reportDayClick=T;K.dragStart=X;K.dragStop=ya;Kb.call(K,a,b,e);Lb.call(K);Mb.call(K);sc.call(K);var i=K.opt,C=K.trigger,
+O)}function z(){B();if(wa){wa.remove();wa=null}}function H(h){if(h.which==1&&i("selectable")){Y(h);var O;Ra.start(function(x,A){z();if(x&&x.col==A.col&&!pa(x)){A=na(A);x=na(x);O=[A,xa(N(A),i("slotMinutes")),x,xa(N(x),i("slotMinutes"))].sort(Gb);c(O[0],O[3])}else O=null},h);m(document).one("mouseup",function(x){Ra.stop();if(O){+O[0]==+O[1]&&T(O[0],false,x);n(O[0],O[3],false,x)}})}}function T(h,O,x){C("dayClick",M[U(h.getDay())],h,O,x)}function X(h,O){Ra.start(function(x){B();if(x)if(pa(x))ga(x.row,
+x.col,x.row,x.col);else{x=na(x);var A=xa(N(x),i("defaultEventMinutes"));ra(x,A)}},O)}function ya(h,O,x){var A=Ra.stop();B();A&&C("drop",h,na(A),pa(A),O,x)}var K=this;K.renderAgenda=d;K.setWidth=t;K.setHeight=j;K.beforeHide=S;K.afterShow=Q;K.defaultEventEnd=G;K.timePosition=ca;K.dayOfWeekCol=U;K.dateCell=da;K.cellDate=na;K.cellIsAllDay=pa;K.allDayRow=qa;K.allDayBounds=ka;K.getHoverListener=function(){return Ra};K.colContentLeft=sa;K.colContentRight=ha;K.getDaySegmentContainer=function(){return ia};
+K.getSlotSegmentContainer=function(){return R};K.getMinMinute=function(){return La};K.getMaxMinute=function(){return bb};K.getBodyContent=function(){return I};K.getRowCnt=function(){return 1};K.getColCnt=function(){return Ba};K.getColWidth=function(){return db};K.getSlotHeight=function(){return Xa};K.defaultSelectionEnd=p;K.renderDayOverlay=oa;K.renderSelection=L;K.clearSelection=z;K.reportDayClick=T;K.dragStart=X;K.dragStop=ya;Kb.call(K,a,b,e);Lb.call(K);Mb.call(K);sc.call(K);var i=K.opt,C=K.trigger,
 P=K.clearEvents,E=K.renderOverlay,B=K.clearOverlays,n=K.reportSelection,Y=K.unselect,W=K.daySelectionMousedown,o=K.slotSegHtml,s=b.formatDate,v,F,r,J,M,k,D,Z,ja,ia,la,$,w,I,R,V,ea,aa,va,wa,Ga,Wb,Ma,db,vb,Xa,Xb,Ba,tb,Na,Ra,cb,ub={},Wa,Tb,Sb,Ub,Ha,Ia,La,bb,Vb;qb(a.addClass("fc-agenda"));Na=new Nb(function(h,O){function x(eb){return Math.max(Ea,Math.min(tc,eb))}var A,ta,za;r.each(function(eb,uc){A=m(uc);ta=A.offset().left;if(eb)za[1]=ta;za=[ta];O[eb]=za});za[1]=ta+A.outerWidth();if(i("allDaySlot")){A=
-$;ta=A.offset().top;h[0]=[ta,ta+A.outerHeight()]}for(var Da=I.offset().top,Ea=w.offset().top,tc=Ea+w.outerHeight(),fb=0;fb<tb;fb++)h.push([x(Da+Xa*fb),x(Da+Xa*(fb+1))])});Ra=new Ob(Na);cb=new Pb(function(h){return k.eq(h)})}function sc(){function a(o,s){sa(o);var v,F=o.length,r=[],J=[];for(v=0;v<F;v++)o[v].allDay?r.push(o[v]):J.push(o[v]);if(u("allDaySlot")){L(e(r),s);ma()}g(d(J),s)}function b(){ha();ua().empty();pa().empty()}function e(o){o=ob(nb(o,m.map(o,Ua),q.visStart,q.visEnd));var s,v=o.length,
+$;ta=A.offset().top;h[0]=[ta,ta+A.outerHeight()]}for(var Da=I.offset().top,Ea=w.offset().top,tc=Ea+w.outerHeight(),fb=0;fb<tb;fb++)h.push([x(Da+Xa*fb),x(Da+Xa*(fb+1))])});Ra=new Ob(Na);cb=new Pb(function(h){return k.eq(h)})}function sc(){function a(o,s){sa(o);var v,F=o.length,r=[],J=[];for(v=0;v<F;v++)o[v].allDay?r.push(o[v]):J.push(o[v]);if(u("allDaySlot")){L(e(r),s);na()}g(d(J),s)}function b(){ha();ua().empty();pa().empty()}function e(o){o=ob(nb(o,m.map(o,Ua),q.visStart,q.visEnd));var s,v=o.length,
 F,r,J,M=[];for(s=0;s<v;s++){F=o[s];for(r=0;r<F.length;r++){J=F[r];J.row=0;J.level=s;M.push(J)}}return M}function d(o){var s=z(),v=ka(),F=ca(),r=xa(N(q.visStart),v),J=m.map(o,f),M,k,D,Z,ja,ia,la=[];for(M=0;M<s;M++){k=ob(nb(o,J,r,xa(N(r),F-v)));vc(k);for(D=0;D<k.length;D++){Z=k[D];for(ja=0;ja<Z.length;ja++){ia=Z[ja];ia.col=M;ia.level=D;la.push(ia)}}ba(r,1,true)}return la}function f(o){return o.end?N(o.end):xa(N(o.start),u("defaultEventMinutes"))}function g(o,s){var v,F=o.length,r,J,M,k,D,Z,ja,ia,la,
 $="",w,I,R={},V={},ea=pa(),aa;v=z();if(w=u("isRTL")){I=-1;aa=v-1}else{I=1;aa=0}for(v=0;v<F;v++){r=o[v];J=r.event;M=qa(r.start,r.start);k=qa(r.start,r.end);D=r.col;Z=r.level;ja=r.forward||0;ia=G(D*I+aa);la=p(D*I+aa)-ia;la=Math.min(la-6,la*0.95);D=Z?la/(Z+ja+1):ja?(la/(ja+1)-6)*2:la;Z=ia+la/(Z+ja+1)*Z*I+(w?la-D:0);r.top=M;r.left=Z;r.outerWidth=D;r.outerHeight=k-M;$+=l(J,r)}ea[0].innerHTML=$;w=ea.children();for(v=0;v<F;v++){r=o[v];J=r.event;$=m(w[v]);I=fa("eventRender",J,J,$);if(I===false)$.remove();
-else{if(I&&I!==true){$.remove();$=m(I).css({position:"absolute",top:r.top,left:r.left}).appendTo(ea)}r.element=$;if(J._id===s)t(J,$,r);else $[0]._fci=v;ya(J,$)}}Db(ea,o,t);for(v=0;v<F;v++){r=o[v];if($=r.element){J=R[s=r.key=Ib($[0])];r.vsides=J===oa?(R[s]=Sa($,true)):J;J=V[s];r.hsides=J===oa?(V[s]=pb($,true)):J;s=$.find("div.fc-event-content");if(s.length)r.contentTop=s[0].offsetTop}}for(v=0;v<F;v++){r=o[v];if($=r.element){$[0].style.width=Math.max(0,r.outerWidth-r.hsides)+"px";R=Math.max(0,r.outerHeight-
-r.vsides);$[0].style.height=R+"px";J=r.event;if(r.contentTop!==oa&&R-r.contentTop<10){$.find("div.fc-event-time").text(Y(J.start,u("timeFormat"))+" - "+J.title);$.find("div.fc-event-title").remove()}fa("eventAfterRender",J,J,$)}}}function l(o,s){var v="<",F=o.url,r=Jb(o,u),J=r?" style='"+r+"'":"",M=["fc-event","fc-event-skin","fc-event-vert"];na(o)&&M.push("fc-event-draggable");s.isStart&&M.push("fc-corner-top");s.isEnd&&M.push("fc-corner-bottom");M=M.concat(o.className);if(o.source)M=M.concat(o.source.className||
+else{if(I&&I!==true){$.remove();$=m(I).css({position:"absolute",top:r.top,left:r.left}).appendTo(ea)}r.element=$;if(J._id===s)t(J,$,r);else $[0]._fci=v;ya(J,$)}}Db(ea,o,t);for(v=0;v<F;v++){r=o[v];if($=r.element){J=R[s=r.key=Ib($[0])];r.vsides=J===ma?(R[s]=Sa($,true)):J;J=V[s];r.hsides=J===ma?(V[s]=pb($,true)):J;s=$.find("div.fc-event-content");if(s.length)r.contentTop=s[0].offsetTop}}for(v=0;v<F;v++){r=o[v];if($=r.element){$[0].style.width=Math.max(0,r.outerWidth-r.hsides)+"px";R=Math.max(0,r.outerHeight-
+r.vsides);$[0].style.height=R+"px";J=r.event;if(r.contentTop!==ma&&R-r.contentTop<10){$.find("div.fc-event-time").text(Y(J.start,u("timeFormat"))+" - "+J.title);$.find("div.fc-event-title").remove()}fa("eventAfterRender",J,J,$)}}}function l(o,s){var v="<",F=o.url,r=Jb(o,u),J=r?" style='"+r+"'":"",M=["fc-event","fc-event-skin","fc-event-vert"];oa(o)&&M.push("fc-event-draggable");s.isStart&&M.push("fc-corner-top");s.isEnd&&M.push("fc-corner-bottom");M=M.concat(o.className);if(o.source)M=M.concat(o.source.className||
 []);v+=F?"a href='"+Qa(o.url)+"'":"div";v+=" class='"+M.join(" ")+"' style='position:absolute;z-index:8;top:"+s.top+"px;left:"+s.left+"px;"+r+"'><div class='fc-event-inner fc-event-skin'"+J+"><div class='fc-event-head fc-event-skin'"+J+"><div class='fc-event-time'>"+Qa(W(o.start,o.end,u("timeFormat")))+"</div></div><div class='fc-event-content'><div class='fc-event-title'>"+Qa(o.title)+"</div></div><div class='fc-event-bg'></div></div>";if(s.isEnd&&ga(o))v+="<div class='ui-resizable-handle ui-resizable-s'>=</div>";
-v+="</"+(F?"a":"div")+">";return v}function j(o,s,v){na(o)&&y(o,s,v.isStart);v.isEnd&&ga(o)&&c(o,s,v);da(o,s)}function t(o,s,v){var F=s.find("div.fc-event-time");na(o)&&S(o,s,F);v.isEnd&&ga(o)&&Q(o,s,F);da(o,s)}function y(o,s,v){function F(){if(!M){s.width(r).height("").draggable("option","grid",null);M=true}}var r,J,M=true,k,D=u("isRTL")?-1:1,Z=U(),ja=H(),ia=T(),la=ka();s.draggable({zIndex:9,opacity:u("dragOpacity","month"),revertDuration:u("dragRevertDuration"),start:function($,w){fa("eventDragStart",
+v+="</"+(F?"a":"div")+">";return v}function j(o,s,v){oa(o)&&y(o,s,v.isStart);v.isEnd&&ga(o)&&c(o,s,v);da(o,s)}function t(o,s,v){var F=s.find("div.fc-event-time");oa(o)&&S(o,s,F);v.isEnd&&ga(o)&&Q(o,s,F);da(o,s)}function y(o,s,v){function F(){if(!M){s.width(r).height("").draggable("option","grid",null);M=true}}var r,J,M=true,k,D=u("isRTL")?-1:1,Z=U(),ja=H(),ia=T(),la=ka();s.draggable({zIndex:9,opacity:u("dragOpacity","month"),revertDuration:u("dragRevertDuration"),start:function($,w){fa("eventDragStart",
 s,o,$,w);i(o,s);r=s.width();Z.start(function(I,R,V,ea){B();if(I){J=false;k=ea*D;if(I.row)if(v){if(M){s.width(ja-10);Eb(s,ia*Math.round((o.end?(o.end-o.start)/wc:u("defaultEventMinutes"))/u("slotMinutes")));s.draggable("option","grid",[ja,1]);M=false}}else J=true;else{E(ba(N(o.start),k),ba(Ua(o),k));F()}J=J||M&&!k}else{F();J=true}s.draggable("option","revert",J)},$,"drag")},stop:function($,w){Z.stop();B();fa("eventDragStop",s,o,$,w);if(J){F();s.css("filter","");K(o,s)}else{var I=0;M||(I=Math.round((s.offset().top-
 X().offset().top)/ia)*u("slotMinutes")+la-(o.start.getHours()*60+o.start.getMinutes()));C(this,o,k,I,M,$,w)}}})}function S(o,s,v){function F(I){var R=xa(N(o.start),I),V;if(o.end)V=xa(N(o.end),I);v.text(W(R,V,u("timeFormat")))}function r(){if(M){v.css("display","");s.draggable("option","grid",[$,w]);M=false}}var J,M=false,k,D,Z,ja=u("isRTL")?-1:1,ia=U(),la=z(),$=H(),w=T();s.draggable({zIndex:9,scroll:false,grid:[$,w],axis:la==1?"y":false,opacity:u("dragOpacity"),revertDuration:u("dragRevertDuration"),
 start:function(I,R){fa("eventDragStart",s,o,I,R);i(o,s);J=s.position();D=Z=0;ia.start(function(V,ea,aa,va){s.draggable("option","revert",!V);B();if(V){k=va*ja;if(u("allDaySlot")&&!V.row){if(!M){M=true;v.hide();s.draggable("option","grid",null)}E(ba(N(o.start),k),ba(Ua(o),k))}else r()}},I,"drag")},drag:function(I,R){D=Math.round((R.position.top-J.top)/w)*u("slotMinutes");if(D!=Z){M||F(D);Z=D}},stop:function(I,R){var V=ia.stop();B();fa("eventDragStop",s,o,I,R);if(V&&(k||D||M))C(this,o,k,M?0:D,M,I,R);
 else{r();s.css("filter","");s.css(J);F(0);K(o,s)}}})}function Q(o,s,v){var F,r,J=T();s.resizable({handles:{s:"div.ui-resizable-s"},grid:J,start:function(M,k){F=r=0;i(o,s);s.css("z-index",9);fa("eventResizeStart",this,o,M,k)},resize:function(M,k){F=Math.round((Math.max(J,s.height())-k.originalSize.height)/J);if(F!=r){v.text(W(o.start,!F&&!o.end?null:xa(ra(o),u("slotMinutes")*F),u("timeFormat")));r=F}},stop:function(M,k){fa("eventResizeStop",this,o,M,k);if(F)P(this,o,0,u("slotMinutes")*F,M,k);else{s.css("z-index",
-8);K(o,s)}}})}var q=this;q.renderEvents=a;q.compileDaySegs=e;q.clearEvents=b;q.slotSegHtml=l;q.bindDaySeg=j;Qb.call(q);var u=q.opt,fa=q.trigger,na=q.isEventDraggable,ga=q.isEventResizable,ra=q.eventEnd,sa=q.reportEvents,ha=q.reportEventClear,da=q.eventElementHandlers,ma=q.setHeight,ua=q.getDaySegmentContainer,pa=q.getSlotSegmentContainer,U=q.getHoverListener,ca=q.getMaxMinute,ka=q.getMinMinute,qa=q.timePosition,G=q.colContentLeft,p=q.colContentRight,L=q.renderDaySegs,c=q.resizableDayEvent,z=q.getColCnt,
+8);K(o,s)}}})}var q=this;q.renderEvents=a;q.compileDaySegs=e;q.clearEvents=b;q.slotSegHtml=l;q.bindDaySeg=j;Qb.call(q);var u=q.opt,fa=q.trigger,oa=q.isEventDraggable,ga=q.isEventResizable,ra=q.eventEnd,sa=q.reportEvents,ha=q.reportEventClear,da=q.eventElementHandlers,na=q.setHeight,ua=q.getDaySegmentContainer,pa=q.getSlotSegmentContainer,U=q.getHoverListener,ca=q.getMaxMinute,ka=q.getMinMinute,qa=q.timePosition,G=q.colContentLeft,p=q.colContentRight,L=q.renderDaySegs,c=q.resizableDayEvent,z=q.getColCnt,
 H=q.getColWidth,T=q.getSlotHeight,X=q.getBodyContent,ya=q.reportEventElement,K=q.showEvents,i=q.hideEvents,C=q.eventDrop,P=q.eventResize,E=q.renderDayOverlay,B=q.clearOverlays,n=q.calendar,Y=n.formatDate,W=n.formatDates}function vc(a){var b,e,d,f,g,l;for(b=a.length-1;b>0;b--){f=a[b];for(e=0;e<f.length;e++){g=f[e];for(d=0;d<a[b-1].length;d++){l=a[b-1][d];if(Cb(g,l))l.forward=Math.max(l.forward||0,(g.forward||0)+1)}}}}function Kb(a,b,e){function d(G,p){G=qa[G];if(typeof G=="object")return jb(G,p||e);
-return G}function f(G,p){return b.trigger.apply(b,[G,p||da].concat(Array.prototype.slice.call(arguments,2),[da]))}function g(G){return j(G)&&!d("disableDragging")}function l(G){return j(G)&&!d("disableResizing")}function j(G){return Ta(G.editable,(G.source||{}).editable,d("editable"))}function t(G){U={};var p,L=G.length,c;for(p=0;p<L;p++){c=G[p];if(U[c._id])U[c._id].push(c);else U[c._id]=[c]}}function y(G){return G.end?N(G.end):ma(G)}function S(G,p){ca.push(p);if(ka[G._id])ka[G._id].push(p);else ka[G._id]=
-[p]}function Q(){ca=[];ka={}}function q(G,p){p.click(function(L){if(!p.hasClass("ui-draggable-dragging")&&!p.hasClass("ui-resizable-resizing"))return f("eventClick",this,G,L)}).hover(function(L){f("eventMouseover",this,G,L)},function(L){f("eventMouseout",this,G,L)})}function u(G,p){na(G,p,"show")}function fa(G,p){na(G,p,"hide")}function na(G,p,L){G=ka[G._id];var c,z=G.length;for(c=0;c<z;c++)if(!p||G[c][0]!=p[0])G[c][L]()}function ga(G,p,L,c,z,H,T){var X=p.allDay,ya=p._id;sa(U[ya],L,c,z);f("eventDrop",
-G,p,L,c,z,function(){sa(U[ya],-L,-c,X);pa(ya)},H,T);pa(ya)}function ra(G,p,L,c,z,H){var T=p._id;ha(U[T],L,c);f("eventResize",G,p,L,c,function(){ha(U[T],-L,-c);pa(T)},z,H);pa(T)}function sa(G,p,L,c){L=L||0;for(var z,H=G.length,T=0;T<H;T++){z=G[T];if(c!==oa)z.allDay=c;xa(ba(z.start,p,true),L);if(z.end)z.end=xa(ba(z.end,p,true),L);ua(z,qa)}}function ha(G,p,L){L=L||0;for(var c,z=G.length,H=0;H<z;H++){c=G[H];c.end=xa(ba(y(c),p,true),L);ua(c,qa)}}var da=this;da.element=a;da.calendar=b;da.name=e;da.opt=
-d;da.trigger=f;da.isEventDraggable=g;da.isEventResizable=l;da.reportEvents=t;da.eventEnd=y;da.reportEventElement=S;da.reportEventClear=Q;da.eventElementHandlers=q;da.showEvents=u;da.hideEvents=fa;da.eventDrop=ga;da.eventResize=ra;var ma=da.defaultEventEnd,ua=b.normalizeEvent,pa=b.reportEventChange,U={},ca=[],ka={},qa=b.options}function Qb(){function a(i,C){var P=z(),E=pa(),B=U(),n=0,Y,W,o=i.length,s,v;P[0].innerHTML=e(i);d(i,P.children());f(i);g(i,P,C);l(i);j(i);t(i);C=y();for(P=0;P<E;P++){Y=[];for(W=
+return G}function f(G,p){return b.trigger.apply(b,[G,p||da].concat(Array.prototype.slice.call(arguments,2),[da]))}function g(G){return j(G)&&!d("disableDragging")}function l(G){return j(G)&&!d("disableResizing")}function j(G){return Ta(G.editable,(G.source||{}).editable,d("editable"))}function t(G){U={};var p,L=G.length,c;for(p=0;p<L;p++){c=G[p];if(U[c._id])U[c._id].push(c);else U[c._id]=[c]}}function y(G){return G.end?N(G.end):na(G)}function S(G,p){ca.push(p);if(ka[G._id])ka[G._id].push(p);else ka[G._id]=
+[p]}function Q(){ca=[];ka={}}function q(G,p){p.click(function(L){if(!p.hasClass("ui-draggable-dragging")&&!p.hasClass("ui-resizable-resizing"))return f("eventClick",this,G,L)}).hover(function(L){f("eventMouseover",this,G,L)},function(L){f("eventMouseout",this,G,L)})}function u(G,p){oa(G,p,"show")}function fa(G,p){oa(G,p,"hide")}function oa(G,p,L){G=ka[G._id];var c,z=G.length;for(c=0;c<z;c++)if(!p||G[c][0]!=p[0])G[c][L]()}function ga(G,p,L,c,z,H,T){var X=p.allDay,ya=p._id;sa(U[ya],L,c,z);f("eventDrop",
+G,p,L,c,z,function(){sa(U[ya],-L,-c,X);pa(ya)},H,T);pa(ya)}function ra(G,p,L,c,z,H){var T=p._id;ha(U[T],L,c);f("eventResize",G,p,L,c,function(){ha(U[T],-L,-c);pa(T)},z,H);pa(T)}function sa(G,p,L,c){L=L||0;for(var z,H=G.length,T=0;T<H;T++){z=G[T];if(c!==ma)z.allDay=c;xa(ba(z.start,p,true),L);if(z.end)z.end=xa(ba(z.end,p,true),L);ua(z,qa)}}function ha(G,p,L){L=L||0;for(var c,z=G.length,H=0;H<z;H++){c=G[H];c.end=xa(ba(y(c),p,true),L);ua(c,qa)}}var da=this;da.element=a;da.calendar=b;da.name=e;da.opt=
+d;da.trigger=f;da.isEventDraggable=g;da.isEventResizable=l;da.reportEvents=t;da.eventEnd=y;da.reportEventElement=S;da.reportEventClear=Q;da.eventElementHandlers=q;da.showEvents=u;da.hideEvents=fa;da.eventDrop=ga;da.eventResize=ra;var na=da.defaultEventEnd,ua=b.normalizeEvent,pa=b.reportEventChange,U={},ca=[],ka={},qa=b.options}function Qb(){function a(i,C){var P=z(),E=pa(),B=U(),n=0,Y,W,o=i.length,s,v;P[0].innerHTML=e(i);d(i,P.children());f(i);g(i,P,C);l(i);j(i);t(i);C=y();for(P=0;P<E;P++){Y=[];for(W=
 0;W<B;W++)Y[W]=0;for(;n<o&&(s=i[n]).row==P;){W=Hb(Y.slice(s.startCol,s.endCol));s.top=W;W+=s.outerHeight;for(v=s.startCol;v<s.endCol;v++)Y[v]=W;n++}C[P].height(Hb(Y))}Q(i,S(C))}function b(i,C,P){var E=m("<div/>"),B=z(),n=i.length,Y;E[0].innerHTML=e(i);E=E.children();B.append(E);d(i,E);l(i);j(i);t(i);Q(i,S(y()));E=[];for(B=0;B<n;B++)if(Y=i[B].element){i[B].row===C&&Y.css("top",P);E.push(Y[0])}return m(E)}function e(i){var C=fa("isRTL"),P,E=i.length,B,n,Y,W;P=ka();var o=P.left,s=P.right,v,F,r,J,M,k=
 "";for(P=0;P<E;P++){B=i[P];n=B.event;W=["fc-event","fc-event-skin","fc-event-hori"];ga(n)&&W.push("fc-event-draggable");if(C){B.isStart&&W.push("fc-corner-right");B.isEnd&&W.push("fc-corner-left");v=p(B.end.getDay()-1);F=p(B.start.getDay());r=B.isEnd?qa(v):o;J=B.isStart?G(F):s}else{B.isStart&&W.push("fc-corner-left");B.isEnd&&W.push("fc-corner-right");v=p(B.start.getDay());F=p(B.end.getDay()-1);r=B.isStart?qa(v):o;J=B.isEnd?G(F):s}W=W.concat(n.className);if(n.source)W=W.concat(n.source.className||
 []);Y=n.url;M=Jb(n,fa);k+=Y?"<a href='"+Qa(Y)+"'":"<div";k+=" class='"+W.join(" ")+"' style='position:absolute;z-index:8;left:"+r+"px;"+M+"'><div class='fc-event-inner fc-event-skin'"+(M?" style='"+M+"'":"")+">";if(!n.allDay&&B.isStart)k+="<span class='fc-event-time'>"+Qa(T(n.start,n.end,fa("timeFormat")))+"</span>";k+="<span class='fc-event-title'>"+Qa(n.title)+"</span></div>";if(B.isEnd&&ra(n))k+="<div class='ui-resizable-handle ui-resizable-"+(C?"w":"e")+"'>&nbsp;&nbsp;&nbsp;</div>";k+="</"+(Y?
-"a":"div")+">";B.left=r;B.outerWidth=J-r;B.startCol=v;B.endCol=F+1}return k}function d(i,C){var P,E=i.length,B,n,Y;for(P=0;P<E;P++){B=i[P];n=B.event;Y=m(C[P]);n=na("eventRender",n,n,Y);if(n===false)Y.remove();else{if(n&&n!==true){n=m(n).css({position:"absolute",left:B.left});Y.replaceWith(n);Y=n}B.element=Y}}}function f(i){var C,P=i.length,E,B;for(C=0;C<P;C++){E=i[C];(B=E.element)&&ha(E.event,B)}}function g(i,C,P){var E,B=i.length,n,Y,W;for(E=0;E<B;E++){n=i[E];if(Y=n.element){W=n.event;if(W._id===
-P)H(W,Y,n);else Y[0]._fci=E}}Db(C,i,H)}function l(i){var C,P=i.length,E,B,n,Y,W={};for(C=0;C<P;C++){E=i[C];if(B=E.element){n=E.key=Ib(B[0]);Y=W[n];if(Y===oa)Y=W[n]=pb(B,true);E.hsides=Y}}}function j(i){var C,P=i.length,E,B;for(C=0;C<P;C++){E=i[C];if(B=E.element)B[0].style.width=Math.max(0,E.outerWidth-E.hsides)+"px"}}function t(i){var C,P=i.length,E,B,n,Y,W={};for(C=0;C<P;C++){E=i[C];if(B=E.element){n=E.key;Y=W[n];if(Y===oa)Y=W[n]=Fb(B);E.outerHeight=B[0].offsetHeight+Y}}}function y(){var i,C=pa(),
-P=[];for(i=0;i<C;i++)P[i]=ca(i).find("td:first div.fc-day-content > div");return P}function S(i){var C,P=i.length,E=[];for(C=0;C<P;C++)E[C]=i[C][0].offsetTop;return E}function Q(i,C){var P,E=i.length,B,n;for(P=0;P<E;P++){B=i[P];if(n=B.element){n[0].style.top=C[B.row]+(B.top||0)+"px";B=B.event;na("eventAfterRender",B,B,n)}}}function q(i,C,P){var E=fa("isRTL"),B=E?"w":"e",n=C.find("div.ui-resizable-"+B),Y=false;qb(C);C.mousedown(function(W){W.preventDefault()}).click(function(W){if(Y){W.preventDefault();
-W.stopImmediatePropagation()}});n.mousedown(function(W){function o(ia){na("eventResizeStop",this,i,ia);m("body").css("cursor","");s.stop();ya();k&&ua(this,i,k,0,ia);setTimeout(function(){Y=false},0)}if(W.which==1){Y=true;var s=u.getHoverListener(),v=pa(),F=U(),r=E?-1:1,J=E?F-1:0,M=C.css("top"),k,D,Z=m.extend({},i),ja=L(i.start);K();m("body").css("cursor",B+"-resize").one("mouseup",o);na("eventResizeStart",this,i,W);s.start(function(ia,la){if(ia){var $=Math.max(ja.row,ia.row);ia=ia.col;if(v==1)$=0;
-if($==ja.row)ia=E?Math.min(ja.col,ia):Math.max(ja.col,ia);k=$*7+ia*r+J-(la.row*7+la.col*r+J);la=ba(sa(i),k,true);if(k){Z.end=la;$=D;D=b(c([Z]),P.row,M);D.find("*").css("cursor",B+"-resize");$&&$.remove();ma(i)}else if(D){da(i);D.remove();D=null}ya();X(i.start,ba(N(la),1))}},W)}})}var u=this;u.renderDaySegs=a;u.resizableDayEvent=q;var fa=u.opt,na=u.trigger,ga=u.isEventDraggable,ra=u.isEventResizable,sa=u.eventEnd,ha=u.reportEventElement,da=u.showEvents,ma=u.hideEvents,ua=u.eventResize,pa=u.getRowCnt,
+"a":"div")+">";B.left=r;B.outerWidth=J-r;B.startCol=v;B.endCol=F+1}return k}function d(i,C){var P,E=i.length,B,n,Y;for(P=0;P<E;P++){B=i[P];n=B.event;Y=m(C[P]);n=oa("eventRender",n,n,Y);if(n===false)Y.remove();else{if(n&&n!==true){n=m(n).css({position:"absolute",left:B.left});Y.replaceWith(n);Y=n}B.element=Y}}}function f(i){var C,P=i.length,E,B;for(C=0;C<P;C++){E=i[C];(B=E.element)&&ha(E.event,B)}}function g(i,C,P){var E,B=i.length,n,Y,W;for(E=0;E<B;E++){n=i[E];if(Y=n.element){W=n.event;if(W._id===
+P)H(W,Y,n);else Y[0]._fci=E}}Db(C,i,H)}function l(i){var C,P=i.length,E,B,n,Y,W={};for(C=0;C<P;C++){E=i[C];if(B=E.element){n=E.key=Ib(B[0]);Y=W[n];if(Y===ma)Y=W[n]=pb(B,true);E.hsides=Y}}}function j(i){var C,P=i.length,E,B;for(C=0;C<P;C++){E=i[C];if(B=E.element)B[0].style.width=Math.max(0,E.outerWidth-E.hsides)+"px"}}function t(i){var C,P=i.length,E,B,n,Y,W={};for(C=0;C<P;C++){E=i[C];if(B=E.element){n=E.key;Y=W[n];if(Y===ma)Y=W[n]=Fb(B);E.outerHeight=B[0].offsetHeight+Y}}}function y(){var i,C=pa(),
+P=[];for(i=0;i<C;i++)P[i]=ca(i).find("td:first div.fc-day-content > div");return P}function S(i){var C,P=i.length,E=[];for(C=0;C<P;C++)E[C]=i[C][0].offsetTop;return E}function Q(i,C){var P,E=i.length,B,n;for(P=0;P<E;P++){B=i[P];if(n=B.element){n[0].style.top=C[B.row]+(B.top||0)+"px";B=B.event;oa("eventAfterRender",B,B,n)}}}function q(i,C,P){var E=fa("isRTL"),B=E?"w":"e",n=C.find("div.ui-resizable-"+B),Y=false;qb(C);C.mousedown(function(W){W.preventDefault()}).click(function(W){if(Y){W.preventDefault();
+W.stopImmediatePropagation()}});n.mousedown(function(W){function o(ia){oa("eventResizeStop",this,i,ia);m("body").css("cursor","");s.stop();ya();k&&ua(this,i,k,0,ia);setTimeout(function(){Y=false},0)}if(W.which==1){Y=true;var s=u.getHoverListener(),v=pa(),F=U(),r=E?-1:1,J=E?F-1:0,M=C.css("top"),k,D,Z=m.extend({},i),ja=L(i.start);K();m("body").css("cursor",B+"-resize").one("mouseup",o);oa("eventResizeStart",this,i,W);s.start(function(ia,la){if(ia){var $=Math.max(ja.row,ia.row);ia=ia.col;if(v==1)$=0;
+if($==ja.row)ia=E?Math.min(ja.col,ia):Math.max(ja.col,ia);k=$*7+ia*r+J-(la.row*7+la.col*r+J);la=ba(sa(i),k,true);if(k){Z.end=la;$=D;D=b(c([Z]),P.row,M);D.find("*").css("cursor",B+"-resize");$&&$.remove();na(i)}else if(D){da(i);D.remove();D=null}ya();X(i.start,ba(N(la),1))}},W)}})}var u=this;u.renderDaySegs=a;u.resizableDayEvent=q;var fa=u.opt,oa=u.trigger,ga=u.isEventDraggable,ra=u.isEventResizable,sa=u.eventEnd,ha=u.reportEventElement,da=u.showEvents,na=u.hideEvents,ua=u.eventResize,pa=u.getRowCnt,
 U=u.getColCnt,ca=u.allDayRow,ka=u.allDayBounds,qa=u.colContentLeft,G=u.colContentRight,p=u.dayOfWeekCol,L=u.dateCell,c=u.compileDaySegs,z=u.getDaySegmentContainer,H=u.bindDaySeg,T=u.calendar.formatDates,X=u.renderDayOverlay,ya=u.clearOverlays,K=u.clearSelection}function Mb(){function a(Q,q,u){b();q||(q=j(Q,u));t(Q,q,u);e(Q,q,u)}function b(Q){if(S){S=false;y();l("unselect",null,Q)}}function e(Q,q,u,fa){S=true;l("select",null,Q,q,u,fa)}function d(Q){var q=f.cellDate,u=f.cellIsAllDay,fa=f.getHoverListener(),
-na=f.reportDayClick;if(Q.which==1&&g("selectable")){b(Q);var ga;fa.start(function(ra,sa){y();if(ra&&u(ra)){ga=[q(sa),q(ra)].sort(Gb);t(ga[0],ga[1],true)}else ga=null},Q);m(document).one("mouseup",function(ra){fa.stop();if(ga){+ga[0]==+ga[1]&&na(ga[0],true,ra);e(ga[0],ga[1],true,ra)}})}}var f=this;f.select=a;f.unselect=b;f.reportSelection=e;f.daySelectionMousedown=d;var g=f.opt,l=f.trigger,j=f.defaultSelectionEnd,t=f.renderSelection,y=f.clearSelection,S=false;g("selectable")&&g("unselectAuto")&&m(document).mousedown(function(Q){var q=
+oa=f.reportDayClick;if(Q.which==1&&g("selectable")){b(Q);var ga;fa.start(function(ra,sa){y();if(ra&&u(ra)){ga=[q(sa),q(ra)].sort(Gb);t(ga[0],ga[1],true)}else ga=null},Q);m(document).one("mouseup",function(ra){fa.stop();if(ga){+ga[0]==+ga[1]&&oa(ga[0],true,ra);e(ga[0],ga[1],true,ra)}})}}var f=this;f.select=a;f.unselect=b;f.reportSelection=e;f.daySelectionMousedown=d;var g=f.opt,l=f.trigger,j=f.defaultSelectionEnd,t=f.renderSelection,y=f.clearSelection,S=false;g("selectable")&&g("unselectAuto")&&m(document).mousedown(function(Q){var q=
 g("unselectCancel");if(q)if(m(Q.target).parents(q).length)return;b(Q)})}function Lb(){function a(g,l){var j=f.shift();j||(j=m("<div class='fc-cell-overlay' style='position:absolute;z-index:3'/>"));j[0].parentNode!=l[0]&&j.appendTo(l);d.push(j.css(g).show());return j}function b(){for(var g;g=d.shift();)f.push(g.hide().unbind())}var e=this;e.renderOverlay=a;e.clearOverlays=b;var d=[],f=[]}function Nb(a){var b=this,e,d;b.build=function(){e=[];d=[];a(e,d)};b.cell=function(f,g){var l=e.length,j=d.length,
-t,y=-1,S=-1;for(t=0;t<l;t++)if(g>=e[t][0]&&g<e[t][1]){y=t;break}for(t=0;t<j;t++)if(f>=d[t][0]&&f<d[t][1]){S=t;break}return y>=0&&S>=0?{row:y,col:S}:null};b.rect=function(f,g,l,j,t){t=t.offset();return{top:e[f][0]-t.top,left:d[g][0]-t.left,width:d[j][1]-d[g][0],height:e[l][1]-e[f][0]}}}function Ob(a){function b(j){j=a.cell(j.pageX,j.pageY);if(!j!=!l||j&&(j.row!=l.row||j.col!=l.col)){if(j){g||(g=j);f(j,g,j.row-g.row,j.col-g.col)}else f(j,g);l=j}}var e=this,d,f,g,l;e.start=function(j,t,y){f=j;g=l=null;
-a.build();b(t);d=y||"mousemove";m(document).bind(d,b)};e.stop=function(){m(document).unbind(d,b);return l}}function Pb(a){function b(l){return d[l]=d[l]||a(l)}var e=this,d={},f={},g={};e.left=function(l){return f[l]=f[l]===oa?b(l).position().left:f[l]};e.right=function(l){return g[l]=g[l]===oa?e.left(l)+b(l).width():g[l]};e.clear=function(){d={};f={};g={}}}var Ya={defaultView:"month",aspectRatio:1.35,header:{left:"title",center:"",right:"today prev,next"},weekends:true,allDayDefault:true,ignoreTimezone:true,
-lazyFetching:true,startParam:"start",endParam:"end",titleFormat:{month:"MMMM yyyy",week:"MMM d[ yyyy]{ '&#8212;'[ MMM] d yyyy}",day:"dddd, MMM d, yyyy"},columnFormat:{month:"ddd",week:"ddd M/d",day:"dddd M/d"},timeFormat:{"":"h(:mm)t"},isRTL:false,firstDay:0,monthNames:["January","February","March","April","May","June","July","August","September","October","November","December"],monthNamesShort:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],dayNames:["Sunday","Monday","Tuesday",
-"Wednesday","Thursday","Friday","Saturday"],dayNamesShort:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],buttonText:{prev:"&nbsp;&#9668;&nbsp;",next:"&nbsp;&#9658;&nbsp;",prevYear:"&nbsp;&lt;&lt;&nbsp;",nextYear:"&nbsp;&gt;&gt;&nbsp;",today:"today",month:"month",week:"week",day:"day"},theme:false,buttonIcons:{prev:"circle-triangle-w",next:"circle-triangle-e"},unselectAuto:true,dropAccept:"*"},xc={header:{left:"next,prev today",center:"",right:"title"},buttonText:{prev:"&nbsp;&#9658;&nbsp;",next:"&nbsp;&#9668;&nbsp;",
-prevYear:"&nbsp;&gt;&gt;&nbsp;",nextYear:"&nbsp;&lt;&lt;&nbsp;"},buttonIcons:{prev:"circle-triangle-e",next:"circle-triangle-w"}},Aa=m.fullCalendar={version:"1.5.2"},Ja=Aa.views={};m.fn.fullCalendar=function(a){if(typeof a=="string"){var b=Array.prototype.slice.call(arguments,1),e;this.each(function(){var f=m.data(this,"fullCalendar");if(f&&m.isFunction(f[a])){f=f[a].apply(f,b);if(e===oa)e=f;a=="destroy"&&m.removeData(this,"fullCalendar")}});if(e!==oa)return e;return this}var d=a.eventSources||[];
-delete a.eventSources;if(a.events){d.push(a.events);delete a.events}a=m.extend(true,{},Ya,a.isRTL||a.isRTL===oa&&Ya.isRTL?xc:{},a);this.each(function(f,g){f=m(g);g=new Yb(f,a,d);f.data("fullCalendar",g);g.render()});return this};Aa.sourceNormalizers=[];Aa.sourceFetchers=[];var ac={dataType:"json",cache:false},bc=1;Aa.addDays=ba;Aa.cloneDate=N;Aa.parseDate=kb;Aa.parseISO8601=Bb;Aa.parseTime=mb;Aa.formatDate=Oa;Aa.formatDates=ib;var lc=["sun","mon","tue","wed","thu","fri","sat"],Ab=864E5,cc=36E5,wc=
-6E4,dc={s:function(a){return a.getSeconds()},ss:function(a){return Pa(a.getSeconds())},m:function(a){return a.getMinutes()},mm:function(a){return Pa(a.getMinutes())},h:function(a){return a.getHours()%12||12},hh:function(a){return Pa(a.getHours()%12||12)},H:function(a){return a.getHours()},HH:function(a){return Pa(a.getHours())},d:function(a){return a.getDate()},dd:function(a){return Pa(a.getDate())},ddd:function(a,b){return b.dayNamesShort[a.getDay()]},dddd:function(a,b){return b.dayNames[a.getDay()]},
-M:function(a){return a.getMonth()+1},MM:function(a){return Pa(a.getMonth()+1)},MMM:function(a,b){return b.monthNamesShort[a.getMonth()]},MMMM:function(a,b){return b.monthNames[a.getMonth()]},yy:function(a){return(a.getFullYear()+"").substring(2)},yyyy:function(a){return a.getFullYear()},t:function(a){return a.getHours()<12?"a":"p"},tt:function(a){return a.getHours()<12?"am":"pm"},T:function(a){return a.getHours()<12?"A":"P"},TT:function(a){return a.getHours()<12?"AM":"PM"},u:function(a){return Oa(a,
-"yyyy-MM-dd'T'HH:mm:ss'Z'")},S:function(a){a=a.getDate();if(a>10&&a<20)return"th";return["st","nd","rd"][a%10-1]||"th"}};Aa.applyAll=$a;Ja.month=mc;Ja.basicWeek=nc;Ja.basicDay=oc;wb({weekMode:"fixed"});Ja.agendaWeek=qc;Ja.agendaDay=rc;wb({allDaySlot:true,allDayText:"all-day",firstHour:6,slotMinutes:30,defaultEventMinutes:120,axisFormat:"h(:mm)tt",timeFormat:{agenda:"h:mm{ - h:mm}"},dragOpacity:{agenda:0.5},minTime:0,maxTime:24})})(jQuery);
+t,y=-1,S=-1;for(t=0;t<l;t++)if(g>=e[t][0]&&g<e[t][1]){y=t;break}for(t=0;t<j;t++)if(f>=d[t][0]&&f<d[t][1]){S=t;break}return y>=0&&S>=0?{row:y,col:S}:null};b.rect=function(f,g,l,j,t){t=t.offset();return{top:e[f][0]-t.top,left:d[g][0]-t.left,width:d[j][1]-d[g][0],height:e[l][1]-e[f][0]}}}function Ob(a){function b(j){xc(j);j=a.cell(j.pageX,j.pageY);if(!j!=!l||j&&(j.row!=l.row||j.col!=l.col)){if(j){g||(g=j);f(j,g,j.row-g.row,j.col-g.col)}else f(j,g);l=j}}var e=this,d,f,g,l;e.start=function(j,t,y){f=j;
+g=l=null;a.build();b(t);d=y||"mousemove";m(document).bind(d,b)};e.stop=function(){m(document).unbind(d,b);return l}}function xc(a){if(a.pageX===ma){a.pageX=a.originalEvent.pageX;a.pageY=a.originalEvent.pageY}}function Pb(a){function b(l){return d[l]=d[l]||a(l)}var e=this,d={},f={},g={};e.left=function(l){return f[l]=f[l]===ma?b(l).position().left:f[l]};e.right=function(l){return g[l]=g[l]===ma?e.left(l)+b(l).width():g[l]};e.clear=function(){d={};f={};g={}}}var Ya={defaultView:"month",aspectRatio:1.35,
+header:{left:"title",center:"",right:"today prev,next"},weekends:true,allDayDefault:true,ignoreTimezone:true,lazyFetching:true,startParam:"start",endParam:"end",titleFormat:{month:"MMMM yyyy",week:"MMM d[ yyyy]{ '&#8212;'[ MMM] d yyyy}",day:"dddd, MMM d, yyyy"},columnFormat:{month:"ddd",week:"ddd M/d",day:"dddd M/d"},timeFormat:{"":"h(:mm)t"},isRTL:false,firstDay:0,monthNames:["January","February","March","April","May","June","July","August","September","October","November","December"],monthNamesShort:["Jan",
+"Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],dayNames:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],dayNamesShort:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],buttonText:{prev:"&nbsp;&#9668;&nbsp;",next:"&nbsp;&#9658;&nbsp;",prevYear:"&nbsp;&lt;&lt;&nbsp;",nextYear:"&nbsp;&gt;&gt;&nbsp;",today:"today",month:"month",week:"week",day:"day"},theme:false,buttonIcons:{prev:"circle-triangle-w",next:"circle-triangle-e"},unselectAuto:true,dropAccept:"*"},yc=
+{header:{left:"next,prev today",center:"",right:"title"},buttonText:{prev:"&nbsp;&#9658;&nbsp;",next:"&nbsp;&#9668;&nbsp;",prevYear:"&nbsp;&gt;&gt;&nbsp;",nextYear:"&nbsp;&lt;&lt;&nbsp;"},buttonIcons:{prev:"circle-triangle-e",next:"circle-triangle-w"}},Aa=m.fullCalendar={version:"1.5.3"},Ja=Aa.views={};m.fn.fullCalendar=function(a){if(typeof a=="string"){var b=Array.prototype.slice.call(arguments,1),e;this.each(function(){var f=m.data(this,"fullCalendar");if(f&&m.isFunction(f[a])){f=f[a].apply(f,
+b);if(e===ma)e=f;a=="destroy"&&m.removeData(this,"fullCalendar")}});if(e!==ma)return e;return this}var d=a.eventSources||[];delete a.eventSources;if(a.events){d.push(a.events);delete a.events}a=m.extend(true,{},Ya,a.isRTL||a.isRTL===ma&&Ya.isRTL?yc:{},a);this.each(function(f,g){f=m(g);g=new Yb(f,a,d);f.data("fullCalendar",g);g.render()});return this};Aa.sourceNormalizers=[];Aa.sourceFetchers=[];var ac={dataType:"json",cache:false},bc=1;Aa.addDays=ba;Aa.cloneDate=N;Aa.parseDate=kb;Aa.parseISO8601=
+Bb;Aa.parseTime=mb;Aa.formatDate=Oa;Aa.formatDates=ib;var lc=["sun","mon","tue","wed","thu","fri","sat"],Ab=864E5,cc=36E5,wc=6E4,dc={s:function(a){return a.getSeconds()},ss:function(a){return Pa(a.getSeconds())},m:function(a){return a.getMinutes()},mm:function(a){return Pa(a.getMinutes())},h:function(a){return a.getHours()%12||12},hh:function(a){return Pa(a.getHours()%12||12)},H:function(a){return a.getHours()},HH:function(a){return Pa(a.getHours())},d:function(a){return a.getDate()},dd:function(a){return Pa(a.getDate())},
+ddd:function(a,b){return b.dayNamesShort[a.getDay()]},dddd:function(a,b){return b.dayNames[a.getDay()]},M:function(a){return a.getMonth()+1},MM:function(a){return Pa(a.getMonth()+1)},MMM:function(a,b){return b.monthNamesShort[a.getMonth()]},MMMM:function(a,b){return b.monthNames[a.getMonth()]},yy:function(a){return(a.getFullYear()+"").substring(2)},yyyy:function(a){return a.getFullYear()},t:function(a){return a.getHours()<12?"a":"p"},tt:function(a){return a.getHours()<12?"am":"pm"},T:function(a){return a.getHours()<
+12?"A":"P"},TT:function(a){return a.getHours()<12?"AM":"PM"},u:function(a){return Oa(a,"yyyy-MM-dd'T'HH:mm:ss'Z'")},S:function(a){a=a.getDate();if(a>10&&a<20)return"th";return["st","nd","rd"][a%10-1]||"th"}};Aa.applyAll=$a;Ja.month=mc;Ja.basicWeek=nc;Ja.basicDay=oc;wb({weekMode:"fixed"});Ja.agendaWeek=qc;Ja.agendaDay=rc;wb({allDaySlot:true,allDayText:"all-day",firstHour:6,slotMinutes:30,defaultEventMinutes:120,axisFormat:"h(:mm)tt",timeFormat:{agenda:"h:mm{ - h:mm}"},dragOpacity:{agenda:0.5},minTime:0,
+maxTime:24})})(jQuery);
diff --git a/3rdparty/fullcalendar/js/gcal.js b/3rdparty/fullcalendar/js/gcal.js
index 709e25cb2622ae889488739f1543e5fc1e1bd4c2..e9bbe26d824fe65ca88fc1a5e751f817871caa1e 100644
--- a/3rdparty/fullcalendar/js/gcal.js
+++ b/3rdparty/fullcalendar/js/gcal.js
@@ -1,14 +1,14 @@
 /*
- * FullCalendar v1.5.2 Google Calendar Plugin
+ * FullCalendar v1.5.3 Google Calendar Plugin
  *
  * Copyright (c) 2011 Adam Shaw
  * Dual licensed under the MIT and GPL licenses, located in
  * MIT-LICENSE.txt and GPL-LICENSE.txt respectively.
  *
- * Date: Sun Aug 21 22:06:09 2011 -0700
+ * Date: Mon Feb 6 22:40:40 2012 -0800
  *
  */
-
+ 
 (function($) {
 
 
@@ -47,7 +47,7 @@ function transformOptions(sourceOptions, start, end) {
 		'singleevents': true,
 		'max-results': 9999
 	});
-
+	
 	var ctz = sourceOptions.currentTimezone;
 	if (ctz) {
 		data.ctz = ctz = ctz.replace(' ', '_');
@@ -99,7 +99,7 @@ function transformOptions(sourceOptions, start, end) {
 			return events;
 		}
 	});
-
+	
 }
 
 
diff --git a/3rdparty/granite/git/blob.php b/3rdparty/granite/git/blob.php
deleted file mode 100644
index 781a697d560cfcbb76b1b0486938cf209df866b6..0000000000000000000000000000000000000000
--- a/3rdparty/granite/git/blob.php
+++ /dev/null
@@ -1,162 +0,0 @@
-<?php
-/**
- * Blob - provides a Git blob object
- *
- * PHP version 5.3
- *
- * @category Git
- * @package  Granite
- * @author   Craig Roberts <craig0990@googlemail.com>
- * @license  http://www.opensource.org/licenses/mit-license.php MIT Expat License
- * @link     http://craig0990.github.com/Granite/
- */
-
-namespace Granite\Git;
-use \Granite\Git\Object\Raw as Raw;
-use \InvalidArgumentException as InvalidArgumentException;
-use \finfo as finfo;
-/**
- * **Granite\Git\Blob** represents the raw content of an object in a Git repository,
- * typically a **file**. This class provides methods related to the handling of
- * blob content, mimetypes, sizes and write support.
- *
- * @category Git
- * @package  Granite
- * @author   Craig Roberts <craig0990@googlemail.com>
- * @license  http://www.opensource.org/licenses/mit-license.php MIT Expat License
- * @link     http://craig0990.github.com/Granite/
- */
-class Blob
-{
-
-    /**
-     * Stores the SHA-1 id of the object requested; accessed through the `sha()`
-     * method where it is recalculated based on the blob content.
-     */
-    private $sha = null;
-    /**
-     * The raw binary string of the file contents.
-     */
-    private $content = "";
-    /**
-     * The path to the repository location.
-     */
-    private $path;
-
-    /**
-     * Fetches a raw Git object and parses the result. Throws an
-     * InvalidArgumentException if the object is not of the correct type,
-     * or cannot be found.
-     *
-     * @param string $path The path to the repository root.
-     * @param string $sha  The SHA-1 id of the requested object, or `null` if
-     *                     creating a new blob object.
-     *
-     * @throws InvalidArgumentException If the SHA-1 id provided is not a blob.
-     */
-    public function __construct($path, $sha = NULL)
-    {
-        $this->path = $path;
-        if ($sha !== NULL) {
-            $this->sha = $sha;
-            $object = Raw::factory($path, $sha);
-
-            if ($object->type() !== Raw::OBJ_BLOB) {
-                throw new InvalidArgumentException(
-                    "The object $sha is not a blob, type is {$object->type()}"
-                );
-            }
-
-            $this->content = $object->content();
-            unset($object);
-       }
-    }
-
-    /**
-     * Sets or returns the raw file content, depending whether the parameter is
-     * provided.
-     *
-     * @param string $content The object content to set, or `null` if requesting the
-     *                        current content.
-     *
-     * @return string The raw binary string of the file contents.
-     */
-    public function content($content = NULL)
-    {
-        if ($content == NULL) {
-            return $this->content;
-        }
-        $this->content = $content;
-    }
-
-    /**
-     * Returns the size of the file content in bytes, equivalent to
-     * `strlen($blob->content())`.
-     *
-     * @return int The size of the object in bytes.
-     */
-    public function size()
-    {
-        return strlen($this->content);
-    }
-
-    /**
-     * Updates and returns the SHA-1 id of the object, based on it's contents.
-     *
-     * @return int The SHA-1 id of the object.
-     */
-    public function sha()
-    {
-        $sha = hash_init('sha1');
-        $header = 'blob ' . strlen($this->content) . "\0";
-        hash_update($sha, $header);
-        hash_update($sha, $this->content);
-        $this->sha = hash_final($sha);
-        return $this->sha;
-    }
-
-    /**
-     * Returns the mimetype of the object, using `finfo()` to determine the mimetype
-     * of the string.
-     *
-     * @return string The object mimetype.
-     * @see http://php.net/manual/en/function.finfo-open.php
-     */
-    public function mimetype()
-    {
-        $finfo = new finfo(FILEINFO_MIME);
-        return $finfo->buffer($this->content);
-    }
-
-    /**
-     * Encode and compress the object content, saving it to a 'loose' file.
-     *
-     * @return boolean True on success, false on failure.
-     */
-    public function write()
-    {
-        $sha = $this->sha(TRUE);
-        $path = $this->path
-            . 'objects'
-            . DIRECTORY_SEPARATOR
-            . substr($sha, 0, 2)
-            . DIRECTORY_SEPARATOR
-            . substr($sha, 2);
-        // FIXME: currently writes loose objects only
-        if (file_exists($path)) {
-            return FALSE;
-        }
-
-        if (!is_dir(dirname($path))) {
-            mkdir(dirname($path), 0777, TRUE);
-        }
-
-        $loose = fopen($path, 'wb');
-        $data = 'blob ' . strlen($this->content) . "\0" . $this->content;
-        $write = fwrite($loose, gzcompress($data));
-        fclose($loose);
-
-        return ($write !== FALSE);
-    }
-
-}
diff --git a/3rdparty/granite/git/commit.php b/3rdparty/granite/git/commit.php
deleted file mode 100644
index 51077e89f3c19e00d0b8f248f8afeb74168026ca..0000000000000000000000000000000000000000
--- a/3rdparty/granite/git/commit.php
+++ /dev/null
@@ -1,232 +0,0 @@
-<?php
-/**
- * Commit - provides a 'commit' object
- *
- * PHP version 5.3
- *
- * @category Git
- * @package  Granite
- * @author   Craig Roberts <craig0990@googlemail.com>
- * @license  http://www.opensource.org/licenses/mit-license.php MIT Expat License
- * @link     http://craig0990.github.com/Granite/
- */
-
-namespace Granite\Git;
-use \Granite\Git\Object\Raw as Raw;
-use \InvalidArgumentException as InvalidArgumentException;
-
-/**
- * Commit represents a full commit object
- *
- * @category Git
- * @package  Granite
- * @author   Craig Roberts <craig0990@googlemail.com>
- * @license  http://www.opensource.org/licenses/mit-license.php MIT Expat License
- * @link     http://craig0990.github.com/Granite/
- */
-class Commit
-{
-
-    /**
-     * The path to the repository root
-     */
-    private $path;
-    /**
-     * The SHA-1 id of the requested commit
-     */
-    private $sha;
-    /**
-     * The size of the commit in bytes
-     */
-    private $size;
-    /**
-     * The commit message
-     */
-    private $message;
-    /**
-     * The full committer string
-     */
-    private $committer;
-    /**
-     * The full author string
-     */
-    private $author;
-    /**
-     * The SHA-1 ids of the parent commits
-     */
-    private $parents = array();
-
-    /**
-     * Fetches a raw Git object and parses the result. Throws an
-     * InvalidArgumentException if the object is not of the correct type,
-     * or cannot be found.
-     *
-     * @param string $path The path to the repository root
-     * @param string $sha  The SHA-1 id of the requested object
-     *
-     * @throws InvalidArgumentException
-     */
-    public function __construct($path, $sha = NULL)
-    {
-        $this->path = $path;
-        if ($sha !== NULL) {
-            $this->sha = $sha;
-            $object = Raw::factory($path, $sha);
-            $this->size = $object->size();
-
-            if ($object->type() !== Raw::OBJ_COMMIT) {
-                throw new InvalidArgumentException(
-                    "The object $sha is not a commit, type is " . $object->type()
-                );
-            }
-
-            // Parse headers and commit message (delimited with "\n\n")
-            list($headers, $this->message) = explode("\n\n", $object->content(), 2);
-            $headers = explode("\n", $headers);
-
-            foreach ($headers as $header) {
-                list($header, $value) = explode(' ', $header, 2);
-                if ($header == 'parent') {
-                    $this->parents[] = $value;
-                } else {
-                    $this->$header = $value;
-                }
-            }
-
-            $this->tree = new Tree($this->path, $this->tree);
-        }
-    }
-
-    /**
-     * Returns the message stored in the commit
-     *
-     * @return string The commit message
-     */
-    public function message($message = NULL)
-    {
-        if ($message !== NULL) {
-            $this->message = $message;
-            return $this;
-        }
-        return $this->message;
-    }
-
-    /**
-     * Returns the commiter string
-     *
-     * @return string The committer string
-     */
-    public function committer($committer = NULL)
-    {
-        if ($committer !== NULL) {
-            $this->committer = $committer;
-            return $this;
-        }
-        return $this->committer;
-    }
-
-    /**
-     * Returns the author string
-     *
-     * @return string The author string
-     */
-    public function author($author = NULL)
-    {
-        if ($author !== NULL) {
-            $this->author = $author;
-            return $this;
-        }
-        return $this->author;
-    }
-
-    /**
-     * Returns the parents of the commit, or an empty array if none
-     *
-     * @return array The parents of the commit
-     */
-    public function parents($parents = NULL)
-    {
-        if ($parents !== NULL) {
-            $this->parents = $parents;
-            return $this;
-        }
-        return $this->parents;
-    }
-
-    /**
-     * Returns a tree object associated with the commit
-     *
-     * @return Tree
-     */
-    public function tree(Tree $tree = NULL)
-    {
-        if ($tree !== NULL) {
-            $this->tree = $tree;
-            return $this;
-        }
-        return $this->tree;
-    }
-
-    /**
-     * Returns the size of the commit in bytes (Git header + data)
-     *
-     * @return int
-     */
-    public function size()
-    {
-        return $this->size;
-    }
-
-    /**
-     * Returns the size of the commit in bytes (Git header + data)
-     *
-     * @return int
-     */
-    public function sha()
-    {
-        $this->sha = hash('sha1', $this->_raw());
-        return $this->sha;
-    }
-
-    public function write()
-    {
-        $sha = $this->sha();
-        $path = $this->path
-            . 'objects'
-            . DIRECTORY_SEPARATOR
-            . substr($sha, 0, 2)
-            . DIRECTORY_SEPARATOR
-            . substr($sha, 2);
-        // FIXME: currently writes loose objects only
-        if (file_exists($path)) {
-            return FALSE;
-        }
-
-        if (!is_dir(dirname($path))) {
-            mkdir(dirname($path), 0777, TRUE);
-        }
-
-        $loose = fopen($path, 'wb');
-        $data = $this->_raw();
-        $write = fwrite($loose, gzcompress($data));
-        fclose($loose);
-
-        return ($write !== FALSE);
-    }
-
-    public function _raw()
-    {
-        $data = 'tree ' . $this->tree->sha() . "\n";
-        foreach ($this->parents as $parent)
-        {
-            $data .= "parent $parent\n";
-        }
-        $data .= 'author ' . $this->author . "\n";
-        $data .= 'committer ' . $this->committer . "\n\n";
-        $data .= $this->message;
-
-        $data = 'commit ' . strlen($data) . "\0" . $data;
-        return $data;
-    }
-
-}
diff --git a/3rdparty/granite/git/object/index.php b/3rdparty/granite/git/object/index.php
deleted file mode 100644
index 239706d4efdd05a7d613fdb0a18165eee1c9acc9..0000000000000000000000000000000000000000
--- a/3rdparty/granite/git/object/index.php
+++ /dev/null
@@ -1,210 +0,0 @@
-<?php
-/**
- * Index - provides an 'index' object for packfile indexes
- *
- * PHP version 5.3
- *
- * @category Git
- * @package  Granite
- * @author   Craig Roberts <craig0990@googlemail.com>
- * @license  http://www.opensource.org/licenses/mit-license.php MIT License
- * @link     http://craig0990.github.com/Granite/
- */
-
-namespace Granite\Git\Object;
-use \UnexpectedValueException as UnexpectedValueException;
-
-/**
- * Index represents a packfile index
- *
- * @category Git
- * @package  Granite
- * @author   Craig Roberts <craig0990@googlemail.com>
- * @license  http://www.opensource.org/licenses/mit-license.php MIT License
- * @link     http://craig0990.github.com/Granite/
- */
-class Index
-{
-    const INDEX_MAGIC = "\377tOc";
-
-    /**
-     * The full path to the packfile index
-     */
-    private $path;
-    /**
-     * The offset at which the fanout begins, version 2+ indexes have a 2-byte header
-     */
-    private $offset = 8;
-    /**
-     * The size of the SHA-1 entries, version 1 stores 4-byte offsets alongside to
-     * total 24 bytes, version 2+ stores offsets separately
-     */
-    private $size = 20;
-    /**
-     * The version of the index file format, versions 1 and 2 are in use and
-     * currently supported
-     */
-    private $version;
-
-    /**
-     * Fetches a raw Git object and parses the result
-     *
-     * @param string $path     The path to the repository root
-     * @param string $packname The name of the packfile index to read
-     */
-    public function __construct($path, $packname)
-    {
-        $this->path = $path
-            . 'objects'
-            . DIRECTORY_SEPARATOR
-            . 'pack'
-            . DIRECTORY_SEPARATOR
-            . 'pack-' . $packname . '.idx';
-
-        $this->version = $this->_readVersion();
-        if ($this->version !== 1 && $this->version !== 2) {
-            throw new UnexpectedValueException(
-                "Unsupported index version (version $version)"
-            );
-        }
-
-        if ($this->version == 1) {
-            $this->offset = 0; // Version 1 index has no header/version
-            $this->size = 24; // Offsets + SHA-1 ids are stored together
-        }
-    }
-
-    /**
-     * Returns the offset of the object stored in the index
-     *
-     * @param string $sha The SHA-1 id of the object being requested
-     *
-     * @return int The offset of the object in the packfile
-     */
-    public function find($sha)
-    {
-        $index = fopen($this->path, 'rb');
-        $offset = false; // Offset for object in packfile not found by default
-
-        // Read the fanout to skip to the start char in the sorted SHA-1 list
-        list($start, $after) = $this->_readFanout($index, $sha);
-
-        if ($start == $after) {
-            fclose($index);
-            return false; // Object is apparently located in a 0-length section
-        }
-
-        // Seek $offset + 255 4-byte fanout entries and read 256th entry
-        fseek($index, $this->offset + 4 * 255);
-        $totalObjects = $this->_uint32($index);
-
-        // Look up the SHA-1 id of the object
-        // TODO: Binary search
-        fseek($index, $this->offset + 1024 + $this->size * $start);
-        for ($i = $start; $i < $after; $i++) {
-            if ($this->version == 1) {
-                $offset = $this->_uint32($index);
-            }
-
-            $name = fread($index, 20);
-            if ($name == pack('H40', $sha)) {
-                break; // Found it
-            }
-        }
-
-        if ($i == $after) {
-            fclose($index);
-            return false; // Scanned entire section, couldn't find it
-        }
-
-        if ($this->version == 2) {
-            // Jump to the offset location and read it
-            fseek($index, 1032 + 24 * $totalObjects + 4 * $i);
-            $offset = $this->_uint32($index);
-            if ($offset & 0x80000000) {
-                // Offset is a 64-bit integer; packfile is larger than 2GB
-                fclose($index);
-                throw new UnexpectedValueException(
-                    "Packfile larger than 2GB, currently unsupported"
-                );
-            }
-        }
-
-        fclose($index);
-        return $offset;
-    }
-
-    /**
-     * Converts a binary string into a 32-bit unsigned integer
-     *
-     * @param handle $file Binary string to convert
-     *
-     * @return int Integer value
-     */
-    private function _uint32($file)
-    {
-        $val = unpack('Nx', fread($file, 4));
-        return $val['x'];
-    }
-
-    /**
-     * Reads the fanout for a particular SHA-1 id
-     *
-     * Largely modified from Glip, with some reference to Grit - largely because I
-     * can't see how to re-implement this in PHP
-     *
-     * @param handle $file   File handle to the index file
-     * @param string $sha    The SHA-1 id to search for
-     * @param int    $offset The offset at which the fanout begins
-     *
-     * @return array Array containing integer 'start' and
-     *               'past-the-end' locations
-     */
-    private function _readFanout($file, $sha)
-    {
-        $sha = pack('H40', $sha);
-        fseek($file, $this->offset);
-        if ($sha{0} == "\00") {
-            /**
-             * First character is 0, read first fanout entry to provide
-             * 'past-the-end' location (since first fanout entry provides start
-             * point for '1'-prefixed SHA-1 ids)
-             */
-            $start = 0;
-            fseek($file, $this->offset); // Jump to start of fanout, $offset bytes in
-            $after = $this->_uint32($file);
-        } else {
-            /**
-             * Take ASCII value of first character, minus one to get the fanout
-             * position of the offset (minus one because the fanout does not
-             * contain an entry for "\00"), multiplied by four bytes per entry
-             */
-            fseek($file, $this->offset + (ord($sha{0}) - 1) * 4);
-            $start = $this->_uint32($file);
-            $after = $this->_uint32($file);
-        }
-
-        return array($start, $after);
-    }
-
-    /**
-     * Returns the version number of the index file, or 1 if there is no version
-     * information
-     *
-     * @return int
-     */
-    private function _readVersion()
-    {
-        $file = fopen($this->path, 'rb');
-        $magic = fread($file, 4);
-        $version = $this->_uint32($file);
-
-        if ($magic !== self::INDEX_MAGIC) {
-            $version = 1;
-        }
-
-        fclose($file);
-        return $version;
-    }
-
-}
diff --git a/3rdparty/granite/git/object/loose.php b/3rdparty/granite/git/object/loose.php
deleted file mode 100644
index 32f894845b9902f6925514de1d7ca3cbc60a42ab..0000000000000000000000000000000000000000
--- a/3rdparty/granite/git/object/loose.php
+++ /dev/null
@@ -1,81 +0,0 @@
-<?php
-/**
- * Loose - provides a 'loose object' object
- *
- * PHP version 5.3
- *
- * @category Git
- * @package  Granite
- * @author   Craig Roberts <craig0990@googlemail.com>
- * @license  http://www.opensource.org/licenses/mit-license.php MIT Expat License
- * @link     http://craig0990.github.com/Granite/
- */
-
-namespace Granite\Git\Object;
-use \UnexpectedValueException as UnexpectedValueException;
-
-/**
- * Loose represents a loose object in the Git repository
- *
- * @category Git
- * @package  Granite
- * @author   Craig Roberts <craig0990@googlemail.com>
- * @license  http://www.opensource.org/licenses/mit-license.php MIT Expat License
- * @link     http://craig0990.github.com/Granite/
- */
-class Loose extends Raw
-{
-
-    /**
-     * Reads an object from a loose object file based on the SHA-1 id
-     *
-     * @param string $path The path to the repository root
-     * @param string $sha  The SHA-1 id of the requested object
-     *
-     * @throws UnexpectedValueException If the type is not 'commit', 'tree',
-     * 'tag' or 'blob'
-     */
-    public function __construct($path, $sha)
-    {
-        $this->sha = $sha;
-
-        $loose_path = $path
-                      . 'objects/'
-                      . substr($sha, 0, 2)
-                      . '/'
-                      . substr($sha, 2);
-
-        if (!file_exists($loose_path)) {
-            throw new InvalidArgumentException("Cannot open loose object file for $sha");
-        }
-
-        $raw = gzuncompress(file_get_contents($loose_path));
-        $data = explode("\0", $raw, 2);
-
-        $header = $data[0];
-        $this->content = $data[1];
-
-        list($this->type, $this->size) = explode(' ', $header);
-
-        switch ($this->type) {
-            case 'commit':
-                $this->type = Raw::OBJ_COMMIT;
-            break;
-            case 'tree':
-                $this->type = Raw::OBJ_TREE;
-            break;
-            case 'blob':
-                $this->type = Raw::OBJ_BLOB;
-            break;
-            case 'tag':
-                $this->type = Raw::OBJ_TAG;
-            break;
-            default:
-                throw new UnexpectedValueException(
-                     "Unexpected type '{$this->type}'"
-                );
-            break;
-        }
-    }
-
-}
diff --git a/3rdparty/granite/git/object/packed.php b/3rdparty/granite/git/object/packed.php
deleted file mode 100644
index 7e8d663b32e160b5ff4a9ac25a7e0200a59aff49..0000000000000000000000000000000000000000
--- a/3rdparty/granite/git/object/packed.php
+++ /dev/null
@@ -1,304 +0,0 @@
-<?php
-/**
- * Packed - provides a 'packed object' object
- *
- * PHP version 5.3
- *
- * @category Git
- * @package  Granite
- * @author   Craig Roberts <craig0990@googlemail.com>
- * @license  http://www.opensource.org/licenses/mit-license.php MIT Expat License
- * @link     http://craig0990.github.com/Granite/
- */
-
-namespace Granite\Git\Object;
-use \UnexpectedValueException as UnexpectedValueException;
-
-/**
- * Packed represents a packed object in the Git repository
- *
- * @category Git
- * @package  Granite
- * @author   Craig Roberts <craig0990@googlemail.com>
- * @license  http://www.opensource.org/licenses/mit-license.php MIT Expat License
- * @link     http://craig0990.github.com/Granite/
- */
-class Packed extends Raw
-{
-
-    /**
-     * The name of the packfile being read
-     */
-    private $_packfile;
-
-    /**
-     * Added to the object size to make a 'best-guess' effort at how much compressed
-     * data to read - should be reimplemented, ideally with streams.
-     */
-    const OBJ_PADDING = 512;
-
-    /**
-     * Reads the object data from the compressed data at $offset in $packfile
-     *
-     * @param string $packfile The path to the packfile
-     * @param int    $offset   The offset of the object data
-     */
-    public function __construct($packfile, $offset)
-    {
-        $this->_packfile = $packfile;
-
-        list($this->type, $this->size, $this->content)
-            = $this->_readPackedObject($offset);
-    }
-
-    /**
-     * Reads the object data at $this->_offset
-     *
-     * @param int $offset Offset of the object header
-     *
-     * @return array Containing the type, size and object data
-     */
-    private function _readPackedObject($offset)
-    {
-        $file = fopen($this->_packfile, 'rb');
-        fseek($file, $offset);
-        // Read the type and uncompressed size from the object header
-        list($type, $size) = $this->_readHeader($file, $offset);
-        $object_offset = ftell($file);
-
-        if ($type == self::OBJ_OFS_DELTA || $type == self::OBJ_REF_DELTA) {
-            return $this->_unpackDeltified(
-                $file, $offset, $object_offset, $type, $size
-            );
-        }
-
-        $content = gzuncompress(fread($file, $size + self::OBJ_PADDING), $size);
-
-        return array($type, $size, $content);
-    }
-
-    /**
-     * Reads a packed object header, returning the type and the size. For more
-     * detailed information, refer to the @see tag.
-     *
-     * From the @see tag: "Each byte is really 7 bits of data, with the first bit
-     * being used to say if that hunk is the last one or not before the data starts.
-     * If the first bit is a 1, you will read another byte, otherwise the data starts
-     * next. The first 3 bits in the first byte specifies the type of data..."
-     *
-     * @param handle $file   File handle to read
-     * @param int    $offset Offset of the object header
-     *
-     * @return array Containing the type and the size
-     * @see http://book.git-scm.com/7_the_packfile.html
-     */
-    private function _readHeader($file, $offset)
-    {
-        // Read the object header byte-by-byte
-        fseek($file, $offset);
-        $byte = ord(fgetc($file));
-        /**
-         * Bit-shift right by four, then ignore the first bit with a bitwise AND
-         * This gives us the object type in binary:
-         *  001    commit           self::OBJ_COMMIT
-         *  010    tree             self::OBJ_TREE
-         *  011    blob             self::OBJ_BLOB
-         *  100    tag              self::OBJ_TAG
-         *  110    offset delta     self::OBJ_OFS_DELTA
-         *  111    ref delta        self::OBJ_REF_DELTA
-         *
-         *  (000 is undefined, 101 is not currently in use)
-         * See http://book.git-scm.com/7_the_packfile.html for details
-         */
-        $type = ($byte >> 4) & 0x07;
-
-        // Read the last four bits of the first byte, used to find the size
-        $size = $byte & 0x0F;
-
-        /**
-         * $shift initially set to four, since we use the last four bits of the first
-         * byte
-         *
-         * $byte & 0x80 checks the initial bit is set to 1 (i.e. keep reading data)
-         *
-         * Finally, $shift is incremented by seven for each consecutive byte (because
-         * we ignore the initial bit)
-         */
-        for ($shift = 4; $byte & 0x80; $shift += 7) {
-            $byte = ord(fgetc($file));
-            /**
-             * The size is ANDed against 0x7F to strip the initial bit, then
-             * bitshifted by left $shift (4 or 7, depending on whether it's the
-             * initial byte) and ORed against the existing binary $size. This
-             * continuously increments the $size variable.
-             */
-            $size |= (($byte & 0x7F) << $shift);
-        }
-
-        return array($type, $size);
-    }
-
-    /**
-     * Unpacks a deltified object located at $offset in $file
-     *
-     * @param handle $file          File handle to read
-     * @param int    $offset        Offset of the object data
-     * @param int    $object_offset Offset of the object data, past the header
-     * @param int    $type          The object type, either OBJ_REF_DELTA
-                                    or OBJ_OFS_DELTA
-     * @param int    $size          The expected size of the uncompressed data
-     *
-     * @return array Containing the type, size and object data
-     */
-    private function _unpackDeltified($file, $offset, $object_offset, $type, $size)
-    {
-        fseek($file, $object_offset);
-
-        if ($type == self::OBJ_REF_DELTA) {
-
-            $base_sha = bin2hex(fread($file, 20));
-
-            $path = substr($this->_packfile, 0, strpos($this->_packfile, '.git')+5);
-            $base = Raw::factory($path, $base_sha);
-            $type = $base->type();
-            $base = $base->content();
-
-            $delta = gzuncompress(
-                fread($file, $size + self::OBJ_PADDING), $size
-            );
-
-            $content = $this->_applyDelta($base, $delta);
-
-        } elseif ($type == self::OBJ_OFS_DELTA) {
-
-            // 20 = maximum varint size according to Glip
-            $data = fread($file, $size + self::OBJ_PADDING + 20);
-
-            list($base_offset, $length) = $this->_bigEndianNumber($data);
-
-            $delta = gzuncompress(substr($data, $length), $size);
-            unset($data);
-
-            $base_offset = $offset - $base_offset;
-            list($type, $size, $base) = $this->_readPackedObject($base_offset);
-
-            $content = $this->_applyDelta($base, $delta);
-
-        } else {
-            throw new UnexpectedValueException(
-                "Unknown type $type for deltified object"
-            );
-        }
-
-        return array($type, strlen($content), $content);
-    }
-
-    /**
-     * Applies the $delta byte-sequence to $base and returns the
-     * resultant binary string.
-     *
-     * This code is modified from Grit (see below), the Ruby
-     * implementation used for GitHub under an MIT license.
-     *
-     * @param string $base  The base string for the delta to be applied to
-     * @param string $delta The delta string to apply
-     *
-     * @return string The patched binary string
-     * @see
-     * https://github.com/mojombo/grit/blob/master/lib/grit/git-ruby/internal/pack.rb
-     */
-    private function _applyDelta($base, $delta)
-    {
-        $pos = 0;
-        $src_size = $this->_varint($delta, $pos);
-        $dst_size = $this->_varint($delta, $pos);
-
-        if ($src_size !== strlen($base)) {
-            throw new UnexpectedValueException(
-                'Expected base delta size ' . strlen($base) . ' does not match the expected '
-                . "value $src_size"
-            );
-        }
-
-        $dest = "";
-        while ($pos < strlen($delta)) {
-            $byte = ord($delta{$pos++});
-
-      if ($byte & 0x80) {
-        /* copy a part of $base */
-        $offset = 0;
-        if ($byte & 0x01) $offset = ord($delta{$pos++});
-        if ($byte & 0x02) $offset |= ord($delta{$pos++}) <<  8;
-        if ($byte & 0x04) $offset |= ord($delta{$pos++}) << 16;
-        if ($byte & 0x08) $offset |= ord($delta{$pos++}) << 24;
-        $length = 0;
-        if ($byte & 0x10) $length = ord($delta{$pos++});
-        if ($byte & 0x20) $length |= ord($delta{$pos++}) <<  8;
-        if ($byte & 0x40) $length |= ord($delta{$pos++}) << 16;
-        if ($length == 0) $length = 0x10000;
-        $dest .= substr($base, $offset, $length);
-      } else {
-        /* take the next $byte bytes as they are */
-        $dest .= substr($delta, $pos, $byte);
-        $pos += $byte;
-      }
-        }
-
-        if (strlen($dest) !== $dst_size) {
-            throw new UnexpectedValueException(
-                "Deltified string expected to be $dst_size bytes, but actually "
-                . strlen($dest) . ' bytes'
-            );
-        }
-
-        return $dest;
-    }
-
-    /**
-     * Parse a Git varint (variable-length integer). Used in the `_applyDelta()`
-     * method to read the delta header.
-     *
-     * @param string $string The string to parse
-     * @param int    &$pos   The position in the string to read from
-     *
-     * @return int The integer value
-     */
-    private function _varint($string, &$pos = 0)
-    {
-        $varint = 0;
-        $bitmask = 0x80;
-        for ($i = 0; $bitmask & 0x80; $i += 7) {
-            $bitmask = ord($string{$pos++});
-            $varint |= (($bitmask & 0x7F) << $i);
-        }
-        return $varint;
-    }
-
-    /**
-     * Decodes a big endian modified base 128 number (refer to @see tag); this only
-     * appears to be used in one place, the offset delta in packfiles. The offset
-     * is the number of bytes to seek back from the start of the delta object to find
-     * the base object.
-     *
-     * This code has been implemented using the C code given in the @see tag below.
-     *
-     * @param string &$data The data to read from and decode the number
-     *
-     * @return Array Containing the base offset (number of bytes to seek back) and
-     * the length to use when reading the delta
-     * @see http://git.rsbx.net/Documents/Git_Data_Formats.txt
-     */
-    private function _bigEndianNumber(&$data)
-    {
-        $i = 0;
-        $byte = ord($data{$i++});
-        $number = $byte & 0x7F;
-        while ($byte & 0x80) {
-            $byte = ord($data{$i++});
-            $number = (($number + 1) << 7) | ($byte & 0x7F);
-        }
-
-        return array($number, $i);
-    }
-
-}
diff --git a/3rdparty/granite/git/object/raw.php b/3rdparty/granite/git/object/raw.php
deleted file mode 100644
index 56f363c37b29b98747413a4999428e7a4568627b..0000000000000000000000000000000000000000
--- a/3rdparty/granite/git/object/raw.php
+++ /dev/null
@@ -1,153 +0,0 @@
-<?php
-/**
- * Raw - provides a raw Git object
- *
- * PHP version 5.3
- *
- * @category Git
- * @package  Granite
- * @author   Craig Roberts <craig0990@googlemail.com>
- * @license  http://www.opensource.org/licenses/mit-license.php MIT Expat License
- * @link     http://craig0990.github.com/Granite/
- */
-
-namespace Granite\Git\Object;
-use \InvalidArgumentException as InvalidArgumentException;
-
-/**
- * Raw represents a raw Git object, using Index to locate
- * packed objects.
- *
- * @category Git
- * @package  Granite
- * @author   Craig Roberts <craig0990@googlemail.com>
- * @license  http://www.opensource.org/licenses/mit-license.php MIT Expat License
- * @link     http://craig0990.github.com/Granite/
- */
-class Raw
-{
-    /**
-     * Integer values for Git objects
-     * @see http://book.git-scm.com/7_the_packfile.html
-     */
-    const OBJ_COMMIT = 1;
-    const OBJ_TREE = 2;
-    const OBJ_BLOB = 3;
-    const OBJ_TAG = 4;
-    const OBJ_OFS_DELTA = 6;
-    const OBJ_REF_DELTA = 7;
-
-    /**
-     * The SHA-1 id of the requested object
-     */
-    protected $sha;
-    /**
-     * The type of the requested object (see class constants)
-     */
-    protected $type;
-    /**
-     * The binary string content of the requested object
-     */
-    protected $content;
-
-    /**
-     * Returns an instance of a raw Git object
-     *
-     * @param string $path The path to the repository root
-     * @param string $sha  The SHA-1 id of the requested object
-     *
-     * @return Packed|Loose
-     */
-    public static function factory($path, $sha)
-    {
-        $loose_path = $path
-                      . 'objects/'
-                      . substr($sha, 0, 2)
-                      . '/'
-                      . substr($sha, 2);
-        if (file_exists($loose_path)) {
-            return new Loose($path, $sha);
-        } else {
-            return self::_findPackedObject($path, $sha);
-        }
-    }
-
-    /**
-     * Returns the raw content of the Git object requested
-     *
-     * @return string Raw object content
-     */
-    public function content()
-    {
-        return $this->content;
-    }
-
-    /**
-     * Returns the size of the Git object
-     *
-     * @return int The size of the object in bytes
-     */
-    public function size()
-    {
-        return strlen($this->content);
-    }
-
-    /**
-     * Returns the type of the object as either commit, tag, blob or tree
-     *
-     * @return string The object type
-     */
-    public function type()
-    {
-        return $this->type;
-    }
-
-    /**
-     * Searches a packfile for the SHA id and reads the object from the packfile
-     *
-     * @param string $path The path to the repository
-     * @param string $sha  The SHA-1 id of the object being requested
-     *
-     * @throws \InvalidArgumentException
-     * @return array An array containing the type, size and object data
-     */
-    private static function _findPackedObject($path, $sha)
-    {
-        $packfiles = glob(
-            $path
-            . 'objects'
-            . DIRECTORY_SEPARATOR
-            . 'pack'
-            . DIRECTORY_SEPARATOR
-            . 'pack-*.pack'
-        );
-
-        $offset = false;
-        foreach ($packfiles as $packfile) {
-            $packname = substr(basename($packfile, '.pack'), 5);
-            $idx = new Index($path, $packname);
-            $offset = $idx->find($sha);
-
-            if ($offset !== false) {
-                break; // Found it
-            }
-        }
-
-        if ($offset == false) {
-            throw new InvalidArgumentException("Could not find packed object $sha");
-        }
-
-        $packname = $path
-            . 'objects'
-            . DIRECTORY_SEPARATOR
-            . 'pack'
-            . DIRECTORY_SEPARATOR
-            . 'pack-' . $packname . '.pack';
-        $object = new Packed($packname, $offset);
-
-        return $object;
-    }
-
-}
-
-?>
diff --git a/3rdparty/granite/git/repository.php b/3rdparty/granite/git/repository.php
deleted file mode 100644
index 30b58a39f5a525bed8ec3741c51d27b3eb315c97..0000000000000000000000000000000000000000
--- a/3rdparty/granite/git/repository.php
+++ /dev/null
@@ -1,293 +0,0 @@
-<?php
-/**
- * Repository - provides a 'repository' object with a set of helper methods
- *
- * PHP version 5.3
- *
- * @category Git
- * @package  Granite
- * @author   Craig Roberts <craig0990@googlemail.com>
- * @license  http://www.opensource.org/licenses/mit-license.php MIT Expat License
- * @link     http://craig0990.github.com/Granite/
- */
-
-namespace Granite\Git;
-use \InvalidArgumentException as InvalidArgumentException;
-use \UnexpectedValueException as UnexpectedValueException;
-
-/**
- * Repository represents a Git repository, providing a variety of methods for
- * fetching objects from SHA-1 ids or the tip of a branch with `head()`
- *
- * @category Git
- * @package  Granite
- * @author   Craig Roberts <craig0990@googlemail.com>
- * @license  http://www.opensource.org/licenses/mit-license.php MIT Expat License
- * @link     http://craig0990.github.com/Granite/
- */
-class Repository
-{
-
-    /**
-     * The path to the repository root
-     */
-    private $_path;
-    /**
-     * The indexed version of a commit, ready to write with `commit()`
-     */
-    private $idx_commit;
-    /**
-     * The indexed version of a tree, modified to with `add()` and `remove()`
-     */
-    private $idx_tree;
-
-    /**
-     * Sets the repository path
-     *
-     * @param string $path The path to the repository root (i.e. /repo/.git/)
-     */
-    public function __construct($path)
-    {
-        if (!is_dir($path)) {
-            throw new InvalidArgumentException("Unable to find directory $path");
-        } elseif (!is_readable($path)) {
-            throw new InvalidArgumentException("Unable to read directory $path");
-        } elseif (!is_dir($path . DIRECTORY_SEPARATOR . 'objects')
-            || !is_dir($path . DIRECTORY_SEPARATOR . 'refs')
-        ) {
-            throw new UnexpectedValueException(
-                "Invalid directory, could not find 'objects' or 'refs' in $path"
-            );
-        }
-
-        $this->_path = $path;
-        $this->idx_commit = $this->factory('commit');
-        $this->idx_tree = $this->factory('tree');
-    }
-
-    /**
-     * Returns an object from the Repository of the given type, with the given
-     * SHA-1 id, or false if it cannot be found
-     *
-     * @param string $type The type (blob, commit, tag or tree) of object being
-     * requested
-     * @param string $sha  The SHA-1 id of the object (or the name of a tag)
-     *
-     * @return Blob|Commit|Tag|Tree
-     */
-    public function factory($type, $sha = null)
-    {
-        if (!in_array($type, array('blob', 'commit', 'tag', 'tree'))) {
-            throw new InvalidArgumentException("Invalid type: $type");
-        }
-
-        if ($type == 'tag') {
-            $sha = $this->_ref('tags' . DIRECTORY_SEPARATOR . $sha);
-        }
-        $type = 'Granite\\Git\\' . ucwords($type);
-
-        return new $type($this->_path, $sha);
-    }
-
-    /**
-     * Returns a Commit object representing the HEAD commit
-     *
-     * @param string $branch The branch name to lookup, defaults to 'master'
-     *
-     * @return Commit An object representing the HEAD commit
-     */
-    public function head($branch = 'master', $value = NULL)
-    {
-        if ($value == NULL)
-            return $this->factory(
-                'commit', $this->_ref('heads' . DIRECTORY_SEPARATOR . $branch)
-            );
-
-        file_put_contents(
-            $this->_path . DIRECTORY_SEPARATOR
-            . 'refs' . DIRECTORY_SEPARATOR
-            . 'heads' . DIRECTORY_SEPARATOR . 'master',
-            $value
-        );
-    }
-
-    /**
-     * Returns a string representing the repository's location, which may or may
-     * not be initialised
-     *
-     * @return string A string representing the repository's location
-     */
-    public function path()
-    {
-        return $this->_path;
-    }
-
-    /**
-     * Returns an array of the local branches under `refs/heads`
-     *
-     * @return array
-     */
-    public function tags()
-    {
-      return $this->_refs('tags');
-    }
-
-    /**
-     * Returns an array of the local tags under `refs/tags`
-     *
-     * @return array
-     */
-    public function branches()
-    {
-      return $this->_refs('heads');
-    }
-
-    private function _refs($type)
-    {
-      $dir = $this->_path . 'refs' . DIRECTORY_SEPARATOR . $type;
-      $refs = glob($dir . DIRECTORY_SEPARATOR . '*');
-      foreach ($refs as &$ref) {
-        $ref = basename($ref);
-      }
-      return $refs;
-    }
-
-    /**
-     * Initialises a Git repository
-     *
-     * @return boolean Returns true on success, false on error
-     */
-    public static function init($path)
-    {
-      $path .= '/';
-      if (!is_dir($path)) {
-        mkdir($path);
-      } elseif (is_dir($path . 'objects')) {
-        return false;
-      }
-
-      mkdir($path . 'objects');
-      mkdir($path . 'objects/info');
-      mkdir($path . 'objects/pack');
-      mkdir($path . 'refs');
-      mkdir($path . 'refs/heads');
-      mkdir($path . 'refs/tags');
-
-      file_put_contents($path . 'HEAD', 'ref: refs/heads/master');
-
-      return true;
-    }
-
-    /**
-     * Writes the indexed commit to disk, with blobs added/removed via `add()` and
-     * `rm()`
-     *
-     * @param string $message The commit message
-     * @param string $author  The author name
-     *
-     * @return boolean True on success, or false on failure
-     */
-    public function commit($message, $author)
-    {
-        $user_string = $username . ' ' . time() . ' +0000';
-
-        try {
-            $parents = array($this->repo->head()->sha());
-        } catch (InvalidArgumentException $e) {
-            $parents = array();
-        }
-
-        $this->idx_commit->message($message);
-        $this->idx_commit->author($user_string);
-        $this->idx_commit->committer($user_string);
-        $this->idx_commit->tree($this->idx_tree);
-        $commit->parents($parents);
-
-        $this->idx_tree->write();
-        $this->idx_commit->write();
-
-        $this->repo->head('master', $this->idx_commit->sha());
-
-        $this->idx_commit = $this->factory('commit');
-        $this->idx_tree = $this->factory('tree');
-    }
-
-    /**
-     * Adds a file to the indexed commit, to be written to disk with `commit()`
-     *
-     * @param string           $filename The filename to save it under
-     * @param Granite\Git\Blob $blob     The raw blob object to add to the tree
-     */
-    public function add($filename, Granite\Git\Blob $blob)
-    {
-        $blob->write();
-        $nodes = $this->idx_tree->nodes();
-        $nodes[$filename] = new Granite\Git\Tree\Node($filename, '100644', $blob->sha());
-        $this->idx_tree->nodes($nodes);
-    }
-
-    /**
-     * Removes a file from the indexed commit
-     */
-    public function rm($filename)
-    {
-        $nodes = $this->idx_tree->nodes();
-        unset($nodes[$filename]);
-        $this->idx_tree->nodes($nodes);
-    }
-
-    /**
-     * Returns an SHA-1 id of the ref resource
-     *
-     * @param string $ref The ref name to lookup
-     *
-     * @return string An SHA-1 id of the ref resource
-     */
-    private function _ref($ref)
-    {
-        // All refs are stored in `.git/refs`
-        $file = $this->_path . 'refs' . DIRECTORY_SEPARATOR . $ref;
-
-        if (file_exists($file)) {
-            return trim(file_get_contents($file));
-        }
-
-        $sha = $this->_packedRef($ref);
-
-        if ($sha == false) {
-            throw new InvalidArgumentException("The ref $ref could not be found");
-        }
-
-        return $sha;
-    }
-
-    /**
-     * Returns an SHA-1 id of the ref resource, or false if it cannot be found
-     *
-     * @param string $ref The ref name to lookup
-     *
-     * @return string An SHA-1 id of the ref resource
-     */
-    private function _packedRef($ref)
-    {
-        $sha = false;
-        if (file_exists($this->_path . 'packed-refs')) {
-            $file = fopen($this->_path . 'packed-refs', 'r');
-
-            while (($line = fgets($file)) !== false) {
-                $info = explode(' ', $line);
-                if (count($info) == 2
-                    && trim($info[1]) == 'refs' . DIRECTORY_SEPARATOR . $ref
-                ) {
-                    $sha = trim($info[0]);
-                    break;
-                }
-            }
-
-            fclose($file);
-        }
-
-        return $sha;
-    }
-
-}
diff --git a/3rdparty/granite/git/tag.php b/3rdparty/granite/git/tag.php
deleted file mode 100644
index e26ddaffa6dd28cdc831ca903d38eda274330600..0000000000000000000000000000000000000000
--- a/3rdparty/granite/git/tag.php
+++ /dev/null
@@ -1,38 +0,0 @@
-<?php
-/**
- * Tag - provides a 'tag' object
- *
- * PHP version 5.3
- *
- * @category Git
- * @package  Granite
- * @author   Craig Roberts <craig0990@googlemail.com>
- * @license  http://www.opensource.org/licenses/mit-license.php MIT Expat License
- * @link     http://craig0990.github.com/Granite/
- */
-
-namespace Granite\Git;
-
-/**
- * Tag represents a full tag object
- *
- * @category Git
- * @package  Granite
- * @author   Craig Roberts <craig0990@googlemail.com>
- * @license  http://www.opensource.org/licenses/mit-license.php MIT Expat License
- * @link     http://craig0990.github.com/Granite/
- */
-class Tag
-{
-
-    public function __construct($path, $sha)
-    {
-      $this->sha = $sha;
-    }
-
-    public function sha()
-    {
-      return $this->sha;
-    }
-
-}
diff --git a/3rdparty/granite/git/tree.php b/3rdparty/granite/git/tree.php
deleted file mode 100644
index 2de722745320f36a811281d813631b6717f3a26e..0000000000000000000000000000000000000000
--- a/3rdparty/granite/git/tree.php
+++ /dev/null
@@ -1,198 +0,0 @@
-<?php
-/**
- * Tree - provides a 'tree' object
- *
- * PHP version 5.3
- *
- * @category Git
- * @package  Granite
- * @author   Craig Roberts <craig0990@googlemail.com>
- * @license  http://www.opensource.org/licenses/mit-license.php MIT Expat License
- * @link     http://craig0990.github.com/Granite/
- */
-
-namespace Granite\Git;
-use \Granite\Git\Tree\Node as Node;
-
-/**
- * Tree represents a full tree object, with nodes pointing to other tree objects
- * and file blobs
- *
- * @category Git
- * @package  Granite
- * @author   Craig Roberts <craig0990@googlemail.com>
- * @license  http://www.opensource.org/licenses/mit-license.php MIT Expat License
- * @link     http://craig0990.github.com/Granite/
- */
-class Tree
-{
-
-    /**
-     * The SHA-1 id of the requested tree
-     */
-    private $sha;
-    /**
-     * The nodes/entries for the requested tree
-     */
-    private $nodes = array();
-    /**
-     * The path to the repository
-     */
-    private $path;
-
-    /**
-     * Reads a tree object by fetching the raw object
-     *
-     * @param string $path The path to the repository root
-     * @param string $sha  The SHA-1 id of the requested object
-     */
-    public function __construct($path, $sha = NULL,  $dbg = FALSE)
-    {
-        $this->path = $path;
-        if ($sha !== NULL) {
-            $object = Object\Raw::factory($path, $sha);
-            $this->sha = $sha;
-
-            if ($object->type() !== Object\Raw::OBJ_TREE) {
-                throw new \InvalidArgumentException(
-                    "The object $sha is not a tree, type is " . $object->type()
-                );
-            }
-
-            $content = $object->content();
-            file_put_contents('/tmp/tree_from_real_repo'.time(), $content);
-            $nodes = array();
-
-            for ($i = 0; $i < strlen($content); $i = $data_start + 21) {
-                $data_start = strpos($content, "\0", $i);
-                $info = substr($content, $i, $data_start-$i);
-                list($mode, $name) = explode(' ', $info, 2);
-                // Read the object SHA-1 id
-                $sha = bin2hex(substr($content, $data_start + 1, 20));
-
-                $this->nodes[$name] = new Node($name, $mode, $sha);
-            }
-        }
-    }
-
-    /**
-     * Returns an array of Tree and Granite\Git\Blob objects,
-     * representing subdirectories and files
-     *
-     * @return array Array of Tree and Granite\Git\Blob objects
-     */
-    public function nodes($nodes = null)
-    {
-        if ($nodes == null) {
-            return $this->nodes;
-        }
-        $this->nodes = $nodes;
-    }
-
-    /**
-     * Adds a blob or a tree to the list of nodes
-     *
-     * @param string $name The basename (filename) of the blob or tree
-     * @param string $mode The mode of the blob or tree (see above)
-     * @param string $sha  The SHA-1 id of the blob or tree to add
-     */
-    public function add($name, $mode, $sha)
-    {
-        $this->nodes[$name] = new Node($name, $mode, $sha);
-        uasort($this->nodes, array($this, '_sort'));
-    }
-
-    public function write()
-    {
-        $sha = $this->sha();
-        $path = $this->path
-            . 'objects'
-            . DIRECTORY_SEPARATOR
-            . substr($sha, 0, 2)
-            . DIRECTORY_SEPARATOR
-            . substr($sha, 2);
-        // FIXME: currently writes loose objects only
-        if (file_exists($path)) {
-            return FALSE;
-        }
-
-        if (!is_dir(dirname($path))) {
-            mkdir(dirname($path), 0777, TRUE);
-        }
-
-        $loose = fopen($path, 'wb');
-        $data = $this->_raw();
-        $data = 'tree ' . strlen($data) . "\0" . $data;
-        $write = fwrite($loose, gzcompress($data));
-        fclose($loose);
-
-        return ($write !== FALSE);
-    }
-
-    /**
-     * Returns the SHA-1 id of the Tree
-     *
-     * @return string SHA-1 id of the Tree
-     */
-    public function sha()
-    {
-        $data = $this->_raw();
-        $raw = 'tree ' . strlen($data) . "\0" . $data;
-        $this->sha = hash('sha1', $raw);
-        return $this->sha;
-    }
-
-    /**
-     * Generates the raw object content to be saved to disk
-     */
-    public function _raw()
-    {
-        uasort($this->nodes, array($this, '_sort'));
-        $data = '';
-        foreach ($this->nodes as $node)
-        {
-            $data .= base_convert($node->mode(), 10, 8) . ' ' . $node->name() . "\0";
-            $data .= pack('H40', $node->sha());
-        }
-        file_put_contents('/tmp/tree_made'.time(), $data);
-        return $data;
-    }
-
-    /**
-     * Sorts the node entries in a tree, general sort method adapted from original
-     * Git C code (see @see tag below).
-     *
-     * @return 1, 0 or -1 if the first entry is greater than, the same as, or less
-     *         than the second, respectively.
-     * @see https://github.com/gitster/git/blob/master/read-cache.c Around line 352,
-     *      the `base_name_compare` function
-     */
-    public function _sort(&$a, &$b)
-    {
-        $length = strlen($a->name()) < strlen($b->name()) ? strlen($a->name()) : strlen($b->name());
-
-        $cmp = strncmp($a->name(), $b->name(), $length);
-        if ($cmp) {
-            return $cmp;
-        }
-
-        $suffix1 = $a->name();
-        $suffix1 = (strlen($suffix1) > $length) ? $suffix1{$length} : FALSE;
-        $suffix2 = $b->name();
-        $suffix2 = (strlen($suffix2) > $length) ? $suffix2{$length} : FALSE;
-        if (!$suffix1 && $a->isDirectory()) {
-            $suffix1 = '/';
-        }
-        if (!$suffix2 && $b->isDirectory()) {
-            $suffix2 = '/';
-        }
-        if ($suffix1 < $suffix2) {
-            return -1;
-        } elseif ($suffix1  > $suffix2) {
-            return 1;
-        }
-
-        return 0;
-    }
-
-}
diff --git a/3rdparty/granite/git/tree/node.php b/3rdparty/granite/git/tree/node.php
deleted file mode 100644
index f99eb1ae28107e6a3f91c990d2ce73dc97f8a103..0000000000000000000000000000000000000000
--- a/3rdparty/granite/git/tree/node.php
+++ /dev/null
@@ -1,126 +0,0 @@
-<?php
-/**
- * Node - provides a tree node object for tree entries
- *
- * PHP version 5.3
- *
- * @category Git
- * @package  Granite
- * @author   Craig Roberts <craig0990@googlemail.com>
- * @license  http://www.opensource.org/licenses/mit-license.php MIT Expat License
- * @link     http://craig0990.github.com/Granite/
- */
-
-namespace Granite\Git\Tree;
-
-/**
- * Node represents an entry in a Tree
- *
- * @category Git
- * @package  Granite
- * @author   Craig Roberts <craig0990@googlemail.com>
- * @license  http://www.opensource.org/licenses/mit-license.php MIT Expat License
- * @link     http://craig0990.github.com/Granite/
- */
-class Node
-{
-
-    /**
-     * Name of the file, directory or submodule
-     */
-    private $_name;
-    /**
-     * Mode of the object, in octal
-     */
-    private $_mode;
-    /**
-     * SHA-1 id of the tree
-     */
-    private $_sha;
-    /**
-     * Boolean value for whether the entry represents a directory
-     */
-    private $_is_dir;
-    /**
-     * Boolean value for whether the entry represents a submodule
-     */
-    private $_is_submodule;
-
-    /**
-     * Sets up a Node class with properties corresponding to the $mode parameter
-     *
-     * @param string $name The name of the object (file, directory or submodule name)
-     * @param int    $mode The mode of the object, retrieved from the repository
-     * @param string $sha  The SHA-1 id of the object
-     */
-    public function __construct($name, $mode, $sha)
-    {
-        $this->_name = $name;
-        $this->_mode = intval($mode, 8);
-        $this->_sha = $sha;
-
-        $this->_is_dir = (bool) ($this->_mode & 0x4000);
-        $this->_is_submodule = ($this->_mode == 0xE000);
-    }
-
-    /**
-     * Returns a boolean value indicating whether the node is a directory
-     *
-     * @return boolean
-     */
-    public function isDirectory()
-    {
-        return $this->_is_dir;
-    }
-
-    /**
-     * Returns a boolean value indicating whether the node is a submodule
-     *
-     * @return boolean
-     */
-    public function isSubmodule()
-    {
-        return $this->_is_submodule;
-    }
-
-    /**
-     * Returns the object name
-     *
-     * @return string
-     */
-    public function name()
-    {
-        return $this->_name;
-    }
-
-    /**
-     * Returns the object's SHA-1 id
-     *
-     * @return string
-     */
-    public function sha()
-    {
-        return $this->_sha;
-    }
-
-    /**
-     * Returns the octal value of the file mode
-     *
-     * @return int
-     */
-    public function mode()
-    {
-        return $this->_mode;
-    }
-
-    public function type()
-    {
-        if ($this->isDirectory()) {
-            return 'tree';
-        } elseif ($this->isSubmodule()) {
-            return 'commit';
-        } else {
-            return 'blob';
-        }
-    }
-}
diff --git a/3rdparty/php-cloudfiles/.gitignore b/3rdparty/php-cloudfiles/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..875b72b27e76a4928fb6e44a6579ad06b0b596ee
--- /dev/null
+++ b/3rdparty/php-cloudfiles/.gitignore
@@ -0,0 +1,3 @@
+*.swp
+*~
+tests/output.log
diff --git a/3rdparty/php-cloudfiles/AUTHORS b/3rdparty/php-cloudfiles/AUTHORS
new file mode 100644
index 0000000000000000000000000000000000000000..a92cfa7c1a975b7a329568925f8fb6ee5ef24e49
--- /dev/null
+++ b/3rdparty/php-cloudfiles/AUTHORS
@@ -0,0 +1,11 @@
+Current maintainer:
+    Conrad Weidenkeller <conrad.weidenkeller@rackspace.com>
+
+Previous maintainer:
+    Eric "EJ" Johnson <ej@racklabs.com>
+    Chmouel Boudjnah <chmouel.boudjnah@rackspace.co.uk>
+
+Contributors:
+    Paul Kehrer
+    Ben Arwin
+    Jordan Callicoat
diff --git a/3rdparty/php-cloudfiles/COPYING b/3rdparty/php-cloudfiles/COPYING
new file mode 100644
index 0000000000000000000000000000000000000000..0e10239d001c295ce1b5a29048824a0c98514499
--- /dev/null
+++ b/3rdparty/php-cloudfiles/COPYING
@@ -0,0 +1,27 @@
+Unless otherwise noted, all files are released under the MIT license,
+exceptions contain licensing information in them.
+
+  Copyright (C) 2008 Rackspace US, Inc.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions: 
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software. 
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+Except as contained in this notice, the name of Rackspace US, Inc. shall not
+be used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from Rackspace US, Inc. 
+
diff --git a/3rdparty/php-cloudfiles/Changelog b/3rdparty/php-cloudfiles/Changelog
new file mode 100644
index 0000000000000000000000000000000000000000..df9303c3e5b1a05ecef3b4ad4b9d76ec8c88687b
--- /dev/null
+++ b/3rdparty/php-cloudfiles/Changelog
@@ -0,0 +1,93 @@
+1.7.10 Conrad Weidenkeller <conrad.weidenkeller@rackspace.com>
+  * Added Streaming URI Functionality
+
+1.7.9 Conrad Weidenkeller <conrad.weidenkeller@rackspace.com>
+  * Added Manifest file support for Large Objects
+
+1.7.8 Conrad Weidenkeller <conrad.weidenkeller@rackspace.com>
+  * Added CDN SSL URI Stuff
+
+1.7.7 Conrad Weidenkeller <conrad.weidenkeller@rackspace.com>
+  * Added CDN Purge Functionality
+
+1.7.6 - Chmouel Boudjnah <chmouel.boudjnah@rackspace.co.uk>
+  * Add Cloud UK Support (conrad.weidenkeller).
+
+1.7.5 - Conrad Weidenkeller <conrad.weidenkeller@rackspace.com>
+  * Added the ability to list only currently enabled CDN containers
+  * Added curl timeout to CF_Http
+  * Fixed some logic errors in some if statements.
+
+1.7.4 - Conrad Weidenkeller <conrad.weidenkeller@rackspace.com>
+  * Added Manual SSL support for MacOSX users
+
+1.7.3 - Conrad Weidenkeller <conrad.weidenkeller@rackspace.com>
+  * Fixed a Small Bug where some users were seeing response bodies for PUTs
+
+1.7.1 - Conrad Weidenkeller <conrad.weidenkeller@rackspace.com>
+  * Added Support for Auth Token Caching. 
+
+1.7.0 - Chmouel Boudjnah <chmouel.boudjnah@rackspace.co.uk>
+  * Adjust api auth to rackspacecloud not mosso (mshuler).
+
+1.6.2 - Chmouel Boudjnah <chmouel.boudjnah@rackspace.co.uk>
+  * Add a close method to close all the current connection.
+  * Fix when container_name is named 0.
+
+1.6.1 - Chmouel Boudjnah <chmouel.boudjnah@rackspace.co.uk>
+  * Fix setting etag on objects.
+  * Fix throwing proper exception when an invalid etag has been set.
+  * Fix throwing proper exception when no content type has been set.
+
+1.6.0 - Chmouel Boudjnah <chmouel.boudjnah@rackspace.co.uk>
+  * Add CDN ACL restriction by referrer feature.
+  * Add CDN ACL restriction by User Agent feature.
+  * Add documentation for log_retention method.
+  * Return True if log_retention as succeeded.
+  * Invalid the PHP stats cache before getting filesize.
+
+1.5.1 - Chmouel Boudjnah <chmouel.boudjnah@rackspace.co.uk> - 20091020
+  * If the environement variable RACKSPACE_SERVICENET is defined then force to
+    connect via rakcspace servicenet.
+
+1.5.0 - Chmouel Boudjnah <chmouel.boudjnah@rackspace.co.uk> - 20091015
+  * Add the option servicenet to connection to use Rackspace service net
+    instead of public network.
+
+1.4.0 - Chmouel Boudjnah <chmouel.boudjnah@rackspace.co.uk> - 20090808
+
+  * Add the ability to store the container log.
+
+1.3.2 - Chmouel Boudjnah <chmouel.boudjnah@rackspace.co.uk> - 20090606
+
+  * Change the Unit Tests to phpunit.
+  * Automatically set the updated CA bundle when on the windows OS.
+  * More simplification of the mimetype detection and support for PHP 5.3.
+  * Fix documentation information about the ttl for cached object.
+  * Use the hash library to compute MD5 for streams instead of storing the
+    stream in memory.
+  * Fix CF_Connection::get_containers to display the container name properly.
+
+1.3.1 - <ej@racklabs.com> - 20090325
+
+  * Simplify use of FileInfo, remove packaged MIME/Magic file
+  * Throw Exception if no Content-Type is set
+  * Fix bug with tracking bytes transferred
+  * Support/tested on Windows XP (PHP v5.2.9)
+
+1.3.0  - <ej@racklabs.com> - 20090311
+
+  * Support for list operations in JSON/XML
+  * Added support for FileInfo automatic Content-Type/MIME detection
+  * Workaround for cURL's old CA bundle with CF_Connection->ssl_use_cabundle()
+  * Supports limit/marker on Account and Container lists
+  * Support "pathname" traversal on Container lists
+  * Helper function on Container to create directory marker Objects
+  * Support for chunked transfer on PUT requests
+
+1.2.3 - <ej@racklabs.com> - 20081210
+
+  * Improved in-line comments and generated HTML docs
+  * Callbacks for read/write progress on CF_Connection class
+  * Fixed minor bugs
+  * Started this Changelog
diff --git a/3rdparty/php-cloudfiles/README b/3rdparty/php-cloudfiles/README
new file mode 100644
index 0000000000000000000000000000000000000000..4bcbeade1a4b80ad25042f8730d3fe77a8df8f13
--- /dev/null
+++ b/3rdparty/php-cloudfiles/README
@@ -0,0 +1,73 @@
+;; PHP Cloud Files API
+;; ========================================================================
+;;   This package contains the PHP API for the Cloud Files storage system.
+;;
+;;   Please see http://www.rackspacecloud.com/ for more information regarding the
+;;   Cloud Files storage system.
+;;
+;; Install
+;; ------------------------------------------------------------------------
+;;   Extract this archive and make sure the source code files are in your
+;;   PHP "include path".  To use the API in your source code, just make
+;;   sure to include/require the "cloudfiles.php" script.
+;;
+;; Requirements
+;; ------------------------------------------------------------------------
+;;   [mandatory] PHP version 5.x (developed against 5.2.0)
+;;   [mandatory] PHP's cURL module
+;;   [mandatory] PHP enabled with mbstring (multi-byte string) support
+;;   [suggested] PEAR FileInfo module (for Content-Type detection)
+;;
+;; Examples
+;; ------------------------------------------------------------------------
+;;   For sample code, please see the tests and API docs.
+;;
+;; Docs
+;; ------------------------------------------------------------------------
+;;   The included documentation was generated directly from the source
+;;   code files using the PHPDocumentor tool.
+;;
+;;   This README file is actually the PHPDocumentor INI configuration file.
+;;   The following packages were installed via PEAR to generate the HTML
+;;   API documentation.
+;;
+;;     * PEAR              1.4.11  (stable)
+;;     * PhpDocumentor     1.4.2   (stable)
+;;     * XML_Beautifier    1.2.0   (stable)
+;;     * XML_Parser        1.3.1   (stable)
+;;     * XML_Util          1.2.0   (stable)
+;;
+;;   To re-generate the API docs, make sure the above software is
+;;   available and run:
+;;      rm -rf docs && phpdoc -c phpdoc.ini
+;;
+;; Tests
+;; ------------------------------------------------------------------------ 
+;; The tests are based on phpunit and are run with PHPUnit 3.3.17
+;; please follow the instructions on :
+;;
+;; http://www.phpunit.de/manual/current/en/installation.html
+;; 
+;; to install PHPUnit. When installed just run the command phpunit on
+;; the top of the directory and it will launch the tests.
+;;
+;; The tests/Comprehensive.php is not enabled by default since
+;; generating big files. If you want to run it you need to go in the
+;; tests directory and run with phpunit Comprehensive.php
+;;
+;; ========================================================================
+;; The lines below here are the configuration settings for re-generating
+;; the PHP API documentation.
+;;
+[Parse Data]
+title = php-cloudfiles
+hidden = false
+parseprivate = off
+javadocdesc = off
+defaultpackagename = php-cloudfiles
+defaultcategoryname = php-cloudfiles
+target = docs
+directory = .
+ignore = share/,examples/,tests/,.git/,.gitignore,*.ini,*.swp
+output=HTML:Smarty:PHP
+readmeinstallchangelog = README,COPYING,AUTHORS,Changelog
diff --git a/3rdparty/php-cloudfiles/cloudfiles.php b/3rdparty/php-cloudfiles/cloudfiles.php
new file mode 100644
index 0000000000000000000000000000000000000000..5f7e2100a9908407acf370375b5eb52ece955e0a
--- /dev/null
+++ b/3rdparty/php-cloudfiles/cloudfiles.php
@@ -0,0 +1,2599 @@
+<?php
+/**
+ * This is the PHP Cloud Files API.
+ *
+ * <code>
+ *   # Authenticate to Cloud Files.  The default is to automatically try
+ *   # to re-authenticate if an authentication token expires.
+ *   #
+ *   # NOTE: Some versions of cURL include an outdated certificate authority (CA)
+ *   #       file.  This API ships with a newer version obtained directly from
+ *   #       cURL's web site (http://curl.haxx.se).  To use the newer CA bundle,
+ *   #       call the CF_Authentication instance's 'ssl_use_cabundle()' method.
+ *   #
+ *   $auth = new CF_Authentication($username, $api_key);
+ *   # $auth->ssl_use_cabundle();  # bypass cURL's old CA bundle
+ *   $auth->authenticate();
+ *
+ *   # Establish a connection to the storage system
+ *   #
+ *   # NOTE: Some versions of cURL include an outdated certificate authority (CA)
+ *   #       file.  This API ships with a newer version obtained directly from
+ *   #       cURL's web site (http://curl.haxx.se).  To use the newer CA bundle,
+ *   #       call the CF_Connection instance's 'ssl_use_cabundle()' method.
+ *   #
+ *   $conn = new CF_Connection($auth);
+ *   # $conn->ssl_use_cabundle();  # bypass cURL's old CA bundle
+ *
+ *   # Create a remote Container and storage Object
+ *   #
+ *   $images = $conn->create_container("photos");
+ *   $bday = $images->create_object("first_birthday.jpg");
+ *
+ *   # Upload content from a local file by streaming it.  Note that we use
+ *   # a "float" for the file size to overcome PHP's 32-bit integer limit for
+ *   # very large files.
+ *   #
+ *   $fname = "/home/user/photos/birthdays/birthday1.jpg";  # filename to upload
+ *   $size = (float) sprintf("%u", filesize($fname));
+ *   $fp = open($fname, "r");
+ *   $bday->write($fp, $size);
+ *
+ *   # Or... use a convenience function instead
+ *   #
+ *   $bday->load_from_filename("/home/user/photos/birthdays/birthday1.jpg");
+ *
+ *   # Now, publish the "photos" container to serve the images by CDN.
+ *   # Use the "$uri" value to put in your web pages or send the link in an
+ *   # email message, etc.
+ *   #
+ *   $uri = $images->make_public();
+ *
+ *   # Or... print out the Object's public URI
+ *   #
+ *   print $bday->public_uri();
+ * </code>
+ *
+ * See the included tests directory for additional sample code.
+ *
+ * Requres PHP 5.x (for Exceptions and OO syntax) and PHP's cURL module.
+ *
+ * It uses the supporting "cloudfiles_http.php" module for HTTP(s) support and
+ * allows for connection re-use and streaming of content into/out of Cloud Files
+ * via PHP's cURL module.
+ *
+ * See COPYING for license information.
+ *
+ * @author Eric "EJ" Johnson <ej@racklabs.com>
+ * @copyright Copyright (c) 2008, Rackspace US, Inc.
+ * @package php-cloudfiles
+ */
+
+/**
+ */
+require_once("cloudfiles_exceptions.php");
+require("cloudfiles_http.php");
+define("DEFAULT_CF_API_VERSION", 1);
+define("MAX_CONTAINER_NAME_LEN", 256);
+define("MAX_OBJECT_NAME_LEN", 1024);
+define("MAX_OBJECT_SIZE", 5*1024*1024*1024+1);
+define("US_AUTHURL", "https://auth.api.rackspacecloud.com");
+define("UK_AUTHURL", "https://lon.auth.api.rackspacecloud.com");
+/**
+ * Class for handling Cloud Files Authentication, call it's {@link authenticate()}
+ * method to obtain authorized service urls and an authentication token.
+ *
+ * Example:
+ * <code>
+ * # Create the authentication instance
+ * #
+ * $auth = new CF_Authentication("username", "api_key");
+ *
+ * # NOTE: For UK Customers please specify your AuthURL Manually
+ * # There is a Predfined constant to use EX:
+ * #
+ * # $auth = new CF_Authentication("username, "api_key", NULL, UK_AUTHURL);
+ * # Using the UK_AUTHURL keyword will force the api to use the UK AuthUrl.
+ * # rather then the US one. The NULL Is passed for legacy purposes and must
+ * # be passed to function correctly.
+ *
+ * # NOTE: Some versions of cURL include an outdated certificate authority (CA)
+ * #       file.  This API ships with a newer version obtained directly from
+ * #       cURL's web site (http://curl.haxx.se).  To use the newer CA bundle,
+ * #       call the CF_Authentication instance's 'ssl_use_cabundle()' method.
+ * #
+ * # $auth->ssl_use_cabundle(); # bypass cURL's old CA bundle
+ *
+ * # Perform authentication request
+ * #
+ * $auth->authenticate();
+ * </code>
+ *
+ * @package php-cloudfiles
+ */
+class CF_Authentication
+{
+    public $dbug;
+    public $username;
+    public $api_key;
+    public $auth_host;
+    public $account;
+
+    /**
+     * Instance variables that are set after successful authentication
+     */
+    public $storage_url;
+    public $cdnm_url;
+    public $auth_token;
+
+    /**
+     * Class constructor (PHP 5 syntax)
+     *
+     * @param string $username Mosso username
+     * @param string $api_key Mosso API Access Key
+     * @param string $account  <i>Account name</i>
+     * @param string $auth_host  <i>Authentication service URI</i>
+     */
+    function __construct($username=NULL, $api_key=NULL, $account=NULL, $auth_host=US_AUTHURL)
+    {
+
+        $this->dbug = False;
+        $this->username = $username;
+        $this->api_key = $api_key;
+        $this->account_name = $account;
+        $this->auth_host = $auth_host;
+
+        $this->storage_url = NULL;
+        $this->cdnm_url = NULL;
+        $this->auth_token = NULL;
+
+        $this->cfs_http = new CF_Http(DEFAULT_CF_API_VERSION);
+    }
+
+    /**
+     * Use the Certificate Authority bundle included with this API
+     *
+     * Most versions of PHP with cURL support include an outdated Certificate
+     * Authority (CA) bundle (the file that lists all valid certificate
+     * signing authorities).  The SSL certificates used by the Cloud Files
+     * storage system are perfectly valid but have been created/signed by
+     * a CA not listed in these outdated cURL distributions.
+     *
+     * As a work-around, we've included an updated CA bundle obtained
+     * directly from cURL's web site (http://curl.haxx.se).  You can direct
+     * the API to use this CA bundle by calling this method prior to making
+     * any remote calls.  The best place to use this method is right after
+     * the CF_Authentication instance has been instantiated.
+     *
+     * You can specify your own CA bundle by passing in the full pathname
+     * to the bundle.  You can use the included CA bundle by leaving the
+     * argument blank.
+     *
+     * @param string $path Specify path to CA bundle (default to included)
+     */
+    function ssl_use_cabundle($path=NULL)
+    {
+        $this->cfs_http->ssl_use_cabundle($path);
+    }
+
+    /**
+     * Attempt to validate Username/API Access Key
+     *
+     * Attempts to validate credentials with the authentication service.  It
+     * either returns <kbd>True</kbd> or throws an Exception.  Accepts a single
+     * (optional) argument for the storage system API version.
+     *
+     * Example:
+     * <code>
+     * # Create the authentication instance
+     * #
+     * $auth = new CF_Authentication("username", "api_key");
+     *
+     * # Perform authentication request
+     * #
+     * $auth->authenticate();
+     * </code>
+     *
+     * @param string $version API version for Auth service (optional)
+     * @return boolean <kbd>True</kbd> if successfully authenticated
+     * @throws AuthenticationException invalid credentials
+     * @throws InvalidResponseException invalid response
+     */
+    function authenticate($version=DEFAULT_CF_API_VERSION)
+    {
+        list($status,$reason,$surl,$curl,$atoken) = 
+                $this->cfs_http->authenticate($this->username, $this->api_key,
+                $this->account_name, $this->auth_host);
+
+        if ($status == 401) {
+            throw new AuthenticationException("Invalid username or access key.");
+        }
+        if ($status < 200 || $status > 299) {
+            throw new InvalidResponseException(
+                "Unexpected response (".$status."): ".$reason);
+        }
+
+        if (!($surl || $curl) || !$atoken) {
+            throw new InvalidResponseException(
+                "Expected headers missing from auth service.");
+        }
+        $this->storage_url = $surl;
+        $this->cdnm_url = $curl;
+        $this->auth_token = $atoken;
+        return True;
+    }
+	/**
+	 * Use Cached Token and Storage URL's rather then grabbing from the Auth System
+         *
+         * Example:
+ 	 * <code>
+         * #Create an Auth instance
+         * $auth = new CF_Authentication();
+         * #Pass Cached URL's and Token as Args
+	 * $auth->load_cached_credentials("auth_token", "storage_url", "cdn_management_url");
+         * </code>
+	 * 
+	 * @param string $auth_token A Cloud Files Auth Token (Required)
+         * @param string $storage_url The Cloud Files Storage URL (Required)
+         * @param string $cdnm_url CDN Management URL (Required)
+         * @return boolean <kbd>True</kbd> if successful 
+	 * @throws SyntaxException If any of the Required Arguments are missing
+         */
+	function load_cached_credentials($auth_token, $storage_url, $cdnm_url)
+    {
+        if(!$storage_url || !$cdnm_url)
+        {
+                throw new SyntaxException("Missing Required Interface URL's!");
+                return False;
+        }
+        if(!$auth_token)
+        {
+                throw new SyntaxException("Missing Auth Token!");
+                return False;
+        }
+
+        $this->storage_url = $storage_url;
+        $this->cdnm_url    = $cdnm_url;
+        $this->auth_token  = $auth_token;
+        return True;
+    }
+	/**
+         * Grab Cloud Files info to be Cached for later use with the load_cached_credentials method.
+         *
+	 * Example:
+         * <code>
+         * #Create an Auth instance
+         * $auth = new CF_Authentication("UserName","API_Key");
+         * $auth->authenticate();
+         * $array = $auth->export_credentials();
+         * </code>
+         * 
+	 * @return array of url's and an auth token.
+         */
+    function export_credentials()
+    {
+        $arr = array();
+        $arr['storage_url'] = $this->storage_url;
+        $arr['cdnm_url']    = $this->cdnm_url;
+        $arr['auth_token']  = $this->auth_token;
+
+        return $arr;
+    }
+
+
+    /**
+     * Make sure the CF_Authentication instance has authenticated.
+     *
+     * Ensures that the instance variables necessary to communicate with
+     * Cloud Files have been set from a previous authenticate() call.
+     *
+     * @return boolean <kbd>True</kbd> if successfully authenticated
+     */
+    function authenticated()
+    {
+        if (!($this->storage_url || $this->cdnm_url) || !$this->auth_token) {
+            return False;
+        }
+        return True;
+    }
+
+    /**
+     * Toggle debugging - set cURL verbose flag
+     */
+    function setDebug($bool)
+    {
+        $this->dbug = $bool;
+        $this->cfs_http->setDebug($bool);
+    }
+}
+
+/**
+ * Class for establishing connections to the Cloud Files storage system.
+ * Connection instances are used to communicate with the storage system at
+ * the account level; listing and deleting Containers and returning Container
+ * instances.
+ *
+ * Example:
+ * <code>
+ * # Create the authentication instance
+ * #
+ * $auth = new CF_Authentication("username", "api_key");
+ *
+ * # Perform authentication request
+ * #
+ * $auth->authenticate();
+ *
+ * # Create a connection to the storage/cdn system(s) and pass in the
+ * # validated CF_Authentication instance.
+ * #
+ * $conn = new CF_Connection($auth);
+ *
+ * # NOTE: Some versions of cURL include an outdated certificate authority (CA)
+ * #       file.  This API ships with a newer version obtained directly from
+ * #       cURL's web site (http://curl.haxx.se).  To use the newer CA bundle,
+ * #       call the CF_Authentication instance's 'ssl_use_cabundle()' method.
+ * #
+ * # $conn->ssl_use_cabundle(); # bypass cURL's old CA bundle
+ * </code>
+ *
+ * @package php-cloudfiles
+ */
+class CF_Connection
+{
+    public $dbug;
+    public $cfs_http;
+    public $cfs_auth;
+
+    /**
+     * Pass in a previously authenticated CF_Authentication instance.
+     *
+     * Example:
+     * <code>
+     * # Create the authentication instance
+     * #
+     * $auth = new CF_Authentication("username", "api_key");
+     *
+     * # Perform authentication request
+     * #
+     * $auth->authenticate();
+     *
+     * # Create a connection to the storage/cdn system(s) and pass in the
+     * # validated CF_Authentication instance.
+     * #
+     * $conn = new CF_Connection($auth);
+     *
+     * # If you are connecting via Rackspace servers and have access
+     * # to the servicenet network you can set the $servicenet to True
+     * # like this.
+     *
+     * $conn = new CF_Connection($auth, $servicenet=True);
+     *
+     * </code>
+     *
+     * If the environement variable RACKSPACE_SERVICENET is defined it will
+     * force to connect via the servicenet.
+     *
+     * @param obj $cfs_auth previously authenticated CF_Authentication instance
+     * @param boolean $servicenet enable/disable access via Rackspace servicenet.
+     * @throws AuthenticationException not authenticated
+     */
+    function __construct($cfs_auth, $servicenet=False)
+    {
+        if (isset($_ENV['RACKSPACE_SERVICENET']))
+            $servicenet=True;
+        $this->cfs_http = new CF_Http(DEFAULT_CF_API_VERSION);
+        $this->cfs_auth = $cfs_auth;
+        if (!$this->cfs_auth->authenticated()) {
+            $e = "Need to pass in a previously authenticated ";
+            $e .= "CF_Authentication instance.";
+            throw new AuthenticationException($e);
+        }
+        $this->cfs_http->setCFAuth($this->cfs_auth, $servicenet=$servicenet);
+        $this->dbug = False;
+    }
+
+    /**
+     * Toggle debugging of instance and back-end HTTP module
+     *
+     * @param boolean $bool enable/disable cURL debugging
+     */
+    function setDebug($bool)
+    {
+        $this->dbug = (boolean) $bool;
+        $this->cfs_http->setDebug($this->dbug);
+    }
+
+    /**
+     * Close a connection
+     *
+     * Example:
+     * <code>
+     *  
+     * $conn->close();
+     * 
+     * </code>
+     *
+     * Will close all current cUrl active connections.
+     * 
+     */
+    public function close()
+    {
+        $this->cfs_http->close();
+    }
+    
+    /**
+     * Cloud Files account information
+     *
+     * Return an array of two floats (since PHP only supports 32-bit integers);
+     * number of containers on the account and total bytes used for the account.
+     *
+     * Example:
+     * <code>
+     * # ... authentication code excluded (see previous examples) ...
+     * #
+     * $conn = new CF_Authentication($auth);
+     *
+     * list($quantity, $bytes) = $conn->get_info();
+     * print "Number of containers: " . $quantity . "\n";
+     * print "Bytes stored in container: " . $bytes . "\n";
+     * </code>
+     *
+     * @return array (number of containers, total bytes stored)
+     * @throws InvalidResponseException unexpected response
+     */
+    function get_info()
+    {
+        list($status, $reason, $container_count, $total_bytes) =
+                $this->cfs_http->head_account();
+        #if ($status == 401 && $this->_re_auth()) {
+        #    return $this->get_info();
+        #}
+        if ($status < 200 || $status > 299) {
+            throw new InvalidResponseException(
+                "Invalid response (".$status."): ".$this->cfs_http->get_error());
+        }
+        return array($container_count, $total_bytes);
+    }
+
+    /**
+     * Create a Container
+     *
+     * Given a Container name, return a Container instance, creating a new
+     * remote Container if it does not exit.
+     *
+     * Example:
+     * <code>
+     * # ... authentication code excluded (see previous examples) ...
+     * #
+     * $conn = new CF_Authentication($auth);
+     *
+     * $images = $conn->create_container("my photos");
+     * </code>
+     *
+     * @param string $container_name container name
+     * @return CF_Container
+     * @throws SyntaxException invalid name
+     * @throws InvalidResponseException unexpected response
+     */
+    function create_container($container_name=NULL)
+    {
+        if ($container_name != "0" and !isset($container_name))
+            throw new SyntaxException("Container name not set.");
+        
+        if (!isset($container_name) or $container_name == "") 
+            throw new SyntaxException("Container name not set.");
+
+        if (strpos($container_name, "/") !== False) {
+            $r = "Container name '".$container_name;
+            $r .= "' cannot contain a '/' character.";
+            throw new SyntaxException($r);
+        }
+        if (strlen($container_name) > MAX_CONTAINER_NAME_LEN) {
+            throw new SyntaxException(sprintf(
+                "Container name exeeds %d bytes.",
+                MAX_CONTAINER_NAME_LEN));
+        }
+
+        $return_code = $this->cfs_http->create_container($container_name);
+        if (!$return_code) {
+            throw new InvalidResponseException("Invalid response ("
+                . $return_code. "): " . $this->cfs_http->get_error());
+        }
+        #if ($status == 401 && $this->_re_auth()) {
+        #    return $this->create_container($container_name);
+        #}
+        if ($return_code != 201 && $return_code != 202) {
+            throw new InvalidResponseException(
+                "Invalid response (".$return_code."): "
+                    . $this->cfs_http->get_error());
+        }
+        return new CF_Container($this->cfs_auth, $this->cfs_http, $container_name);
+    }
+
+    /**
+     * Delete a Container
+     *
+     * Given either a Container instance or name, remove the remote Container.
+     * The Container must be empty prior to removing it.
+     *
+     * Example:
+     * <code>
+     * # ... authentication code excluded (see previous examples) ...
+     * #
+     * $conn = new CF_Authentication($auth);
+     *
+     * $conn->delete_container("my photos");
+     * </code>
+     *
+     * @param string|obj $container container name or instance
+     * @return boolean <kbd>True</kbd> if successfully deleted
+     * @throws SyntaxException missing proper argument
+     * @throws InvalidResponseException invalid response
+     * @throws NonEmptyContainerException container not empty
+     * @throws NoSuchContainerException remote container does not exist
+     */
+    function delete_container($container=NULL)
+    {
+        $container_name = NULL;
+        
+        if (is_object($container)) {
+            if (get_class($container) == "CF_Container") {
+                $container_name = $container->name;
+            }
+        }
+        if (is_string($container)) {
+            $container_name = $container;
+        }
+
+        if ($container_name != "0" and !isset($container_name))
+            throw new SyntaxException("Must specify container object or name.");
+
+        $return_code = $this->cfs_http->delete_container($container_name);
+
+        if (!$return_code) {
+            throw new InvalidResponseException("Failed to obtain http response");
+        }
+        #if ($status == 401 && $this->_re_auth()) {
+        #    return $this->delete_container($container);
+        #}
+        if ($return_code == 409) {
+            throw new NonEmptyContainerException(
+                "Container must be empty prior to removing it.");
+        }
+        if ($return_code == 404) {
+            throw new NoSuchContainerException(
+                "Specified container did not exist to delete.");
+        }
+        if ($return_code != 204) {
+            throw new InvalidResponseException(
+                "Invalid response (".$return_code."): "
+                . $this->cfs_http->get_error());
+        }
+        return True;
+    }
+
+    /**
+     * Return a Container instance
+     *
+     * For the given name, return a Container instance if the remote Container
+     * exists, otherwise throw a Not Found exception.
+     *
+     * Example:
+     * <code>
+     * # ... authentication code excluded (see previous examples) ...
+     * #
+     * $conn = new CF_Authentication($auth);
+     *
+     * $images = $conn->get_container("my photos");
+     * print "Number of Objects: " . $images->count . "\n";
+     * print "Bytes stored in container: " . $images->bytes . "\n";
+     * </code>
+     *
+     * @param string $container_name name of the remote Container
+     * @return container CF_Container instance
+     * @throws NoSuchContainerException thrown if no remote Container
+     * @throws InvalidResponseException unexpected response
+     */
+    function get_container($container_name=NULL)
+    {
+        list($status, $reason, $count, $bytes) =
+                $this->cfs_http->head_container($container_name);
+        #if ($status == 401 && $this->_re_auth()) {
+        #    return $this->get_container($container_name);
+        #}
+        if ($status == 404) {
+            throw new NoSuchContainerException("Container not found.");
+        }
+        if ($status < 200 || $status > 299) {
+            throw new InvalidResponseException(
+                "Invalid response: ".$this->cfs_http->get_error());
+        }
+        return new CF_Container($this->cfs_auth, $this->cfs_http,
+            $container_name, $count, $bytes);
+    }
+
+    /**
+     * Return array of Container instances
+     *
+     * Return an array of CF_Container instances on the account.  The instances
+     * will be fully populated with Container attributes (bytes stored and
+     * Object count)
+     *
+     * Example:
+     * <code>
+     * # ... authentication code excluded (see previous examples) ...
+     * #
+     * $conn = new CF_Authentication($auth);
+     *
+     * $clist = $conn->get_containers();
+     * foreach ($clist as $cont) {
+     *     print "Container name: " . $cont->name . "\n";
+     *     print "Number of Objects: " . $cont->count . "\n";
+     *     print "Bytes stored in container: " . $cont->bytes . "\n";
+     * }
+     * </code>
+     *
+     * @return array An array of CF_Container instances
+     * @throws InvalidResponseException unexpected response
+     */
+    function get_containers($limit=0, $marker=NULL)
+    {
+        list($status, $reason, $container_info) =
+                $this->cfs_http->list_containers_info($limit, $marker);
+        #if ($status == 401 && $this->_re_auth()) {
+        #    return $this->get_containers();
+        #}
+        if ($status < 200 || $status > 299) {
+            throw new InvalidResponseException(
+                "Invalid response: ".$this->cfs_http->get_error());
+        }
+        $containers = array();
+        foreach ($container_info as $name => $info) {
+            $containers[] = new CF_Container($this->cfs_auth, $this->cfs_http,
+                $info['name'], $info["count"], $info["bytes"], False);
+        }
+        return $containers;
+    }
+
+    /**
+     * Return list of remote Containers
+     *
+     * Return an array of strings containing the names of all remote Containers.
+     *
+     * Example:
+     * <code>
+     * # ... authentication code excluded (see previous examples) ...
+     * #
+     * $conn = new CF_Authentication($auth);
+     *
+     * $container_list = $conn->list_containers();
+     * print_r($container_list);
+     * Array
+     * (
+     *     [0] => "my photos",
+     *     [1] => "my docs"
+     * )
+     * </code>
+     *
+     * @param integer $limit restrict results to $limit Containers
+     * @param string $marker return results greater than $marker
+     * @return array list of remote Containers
+     * @throws InvalidResponseException unexpected response
+     */
+    function list_containers($limit=0, $marker=NULL)
+    {
+        list($status, $reason, $containers) =
+            $this->cfs_http->list_containers($limit, $marker);
+        #if ($status == 401 && $this->_re_auth()) {
+        #    return $this->list_containers($limit, $marker);
+        #}
+        if ($status < 200 || $status > 299) {
+            throw new InvalidResponseException(
+                "Invalid response (".$status."): ".$this->cfs_http->get_error());
+        }
+        return $containers;
+    }
+
+    /**
+     * Return array of information about remote Containers
+     *
+     * Return a nested array structure of Container info.
+     *
+     * Example:
+     * <code>
+     * # ... authentication code excluded (see previous examples) ...
+     * #
+     *
+     * $container_info = $conn->list_containers_info();
+     * print_r($container_info);
+     * Array
+     * (
+     *     ["my photos"] =>
+     *         Array
+     *         (
+     *             ["bytes"] => 78,
+     *             ["count"] => 2
+     *         )
+     *     ["docs"] =>
+     *         Array
+     *         (
+     *             ["bytes"] => 37323,
+     *             ["count"] => 12
+     *         )
+     * )
+     * </code>
+     *
+     * @param integer $limit restrict results to $limit Containers
+     * @param string $marker return results greater than $marker
+     * @return array nested array structure of Container info
+     * @throws InvalidResponseException unexpected response
+     */
+    function list_containers_info($limit=0, $marker=NULL)
+    {
+        list($status, $reason, $container_info) = 
+                $this->cfs_http->list_containers_info($limit, $marker);
+        #if ($status == 401 && $this->_re_auth()) {
+        #    return $this->list_containers_info($limit, $marker);
+        #}
+        if ($status < 200 || $status > 299) {
+            throw new InvalidResponseException(
+                "Invalid response (".$status."): ".$this->cfs_http->get_error());
+        }
+        return $container_info;
+    }
+
+    /**
+     * Return list of Containers that have been published to the CDN.
+     *
+     * Return an array of strings containing the names of published Containers.
+     * Note that this function returns the list of any Container that has
+     * ever been CDN-enabled regardless of it's existence in the storage
+     * system.
+     *
+     * Example:
+     * <code>
+     * # ... authentication code excluded (see previous examples) ...
+     * #
+     * $conn = new CF_Authentication($auth);
+     *
+     * $public_containers = $conn->list_public_containers();
+     * print_r($public_containers);
+     * Array
+     * (
+     *     [0] => "images",
+     *     [1] => "css",
+     *     [2] => "javascript"
+     * )
+     * </code>
+     *
+     * @param bool $enabled_only Will list all containers ever CDN enabled if     * set to false or only currently enabled CDN containers if set to true.      * Defaults to false.
+     * @return array list of published Container names
+     * @throws InvalidResponseException unexpected response
+     */
+    function list_public_containers($enabled_only=False)
+    {
+        list($status, $reason, $containers) =
+                $this->cfs_http->list_cdn_containers($enabled_only);
+        #if ($status == 401 && $this->_re_auth()) {
+        #    return $this->list_public_containers();
+        #}
+        if ($status < 200 || $status > 299) {
+            throw new InvalidResponseException(
+                "Invalid response (".$status."): ".$this->cfs_http->get_error());
+        }
+        return $containers;
+    }
+
+    /**
+     * Set a user-supplied callback function to report download progress
+     *
+     * The callback function is used to report incremental progress of a data
+     * download functions (e.g. $container->list_objects(), $obj->read(), etc).
+     * The specified function will be periodically called with the number of
+     * bytes transferred until the entire download is complete.  This callback
+     * function can be useful for implementing "progress bars" for large
+     * downloads.
+     *
+     * The specified callback function should take a single integer parameter.
+     *
+     * <code>
+     * function read_callback($bytes_transferred) {
+     *     print ">> downloaded " . $bytes_transferred . " bytes.\n";
+     *     # ... do other things ...
+     *     return;
+     * }
+     *
+     * $conn = new CF_Connection($auth_obj);
+     * $conn->set_read_progress_function("read_callback");
+     * print_r($conn->list_containers());
+     *
+     * # output would look like this:
+     * #
+     * >> downloaded 10 bytes.
+     * >> downloaded 11 bytes.
+     * Array
+     * (
+     *      [0] => fuzzy.txt
+     *      [1] => space name
+     * )
+     * </code>
+     *
+     * @param string $func_name the name of the user callback function
+     */
+    function set_read_progress_function($func_name)
+    {
+        $this->cfs_http->setReadProgressFunc($func_name);
+    }
+
+    /**
+     * Set a user-supplied callback function to report upload progress
+     *
+     * The callback function is used to report incremental progress of a data
+     * upload functions (e.g. $obj->write() call).  The specified function will
+     * be periodically called with the number of bytes transferred until the
+     * entire upload is complete.  This callback function can be useful
+     * for implementing "progress bars" for large uploads/downloads.
+     *
+     * The specified callback function should take a single integer parameter.
+     *
+     * <code>
+     * function write_callback($bytes_transferred) {
+     *     print ">> uploaded " . $bytes_transferred . " bytes.\n";
+     *     # ... do other things ...
+     *     return;
+     * }
+     *
+     * $conn = new CF_Connection($auth_obj);
+     * $conn->set_write_progress_function("write_callback");
+     * $container = $conn->create_container("stuff");
+     * $obj = $container->create_object("foo");
+     * $obj->write("The callback function will be called during upload.");
+     *
+     * # output would look like this:
+     * # >> uploaded 51 bytes.
+     * #
+     * </code>
+     *
+     * @param string $func_name the name of the user callback function
+     */
+    function set_write_progress_function($func_name)
+    {
+        $this->cfs_http->setWriteProgressFunc($func_name);
+    }
+
+    /**
+     * Use the Certificate Authority bundle included with this API
+     *
+     * Most versions of PHP with cURL support include an outdated Certificate
+     * Authority (CA) bundle (the file that lists all valid certificate
+     * signing authorities).  The SSL certificates used by the Cloud Files
+     * storage system are perfectly valid but have been created/signed by
+     * a CA not listed in these outdated cURL distributions.
+     *
+     * As a work-around, we've included an updated CA bundle obtained
+     * directly from cURL's web site (http://curl.haxx.se).  You can direct
+     * the API to use this CA bundle by calling this method prior to making
+     * any remote calls.  The best place to use this method is right after
+     * the CF_Authentication instance has been instantiated.
+     *
+     * You can specify your own CA bundle by passing in the full pathname
+     * to the bundle.  You can use the included CA bundle by leaving the
+     * argument blank.
+     *
+     * @param string $path Specify path to CA bundle (default to included)
+     */
+    function ssl_use_cabundle($path=NULL)
+    {
+        $this->cfs_http->ssl_use_cabundle($path);
+    }
+
+    #private function _re_auth()
+    #{
+    #    $new_auth = new CF_Authentication(
+    #        $this->cfs_auth->username,
+    #        $this->cfs_auth->api_key,
+    #        $this->cfs_auth->auth_host,
+    #        $this->cfs_auth->account);
+    #    $new_auth->authenticate();
+    #    $this->cfs_auth = $new_auth;
+    #    $this->cfs_http->setCFAuth($this->cfs_auth);
+    #    return True;
+    #}
+}
+
+/**
+ * Container operations
+ *
+ * Containers are storage compartments where you put your data (objects).
+ * A container is similar to a directory or folder on a conventional filesystem
+ * with the exception that they exist in a flat namespace, you can not create
+ * containers inside of containers.
+ *
+ * You also have the option of marking a Container as "public" so that the
+ * Objects stored in the Container are publicly available via the CDN.
+ *
+ * @package php-cloudfiles
+ */
+class CF_Container
+{
+    public $cfs_auth;
+    public $cfs_http;
+    public $name;
+    public $object_count;
+    public $bytes_used;
+
+    public $cdn_enabled;
+    public $cdn_streaming_uri;
+    public $cdn_ssl_uri;
+    public $cdn_uri;
+    public $cdn_ttl;
+    public $cdn_log_retention;
+    public $cdn_acl_user_agent;
+    public $cdn_acl_referrer;
+
+    /**
+     * Class constructor
+     *
+     * Constructor for Container
+     *
+     * @param obj $cfs_auth CF_Authentication instance
+     * @param obj $cfs_http HTTP connection manager
+     * @param string $name name of Container
+     * @param int $count number of Objects stored in this Container
+     * @param int $bytes number of bytes stored in this Container
+     * @throws SyntaxException invalid Container name
+     */
+    function __construct(&$cfs_auth, &$cfs_http, $name, $count=0,
+        $bytes=0, $docdn=True)
+    {
+        if (strlen($name) > MAX_CONTAINER_NAME_LEN) {
+            throw new SyntaxException("Container name exceeds "
+                . "maximum allowed length.");
+        }
+        if (strpos($name, "/") !== False) {
+            throw new SyntaxException(
+                "Container names cannot contain a '/' character.");
+        }
+        $this->cfs_auth = $cfs_auth;
+        $this->cfs_http = $cfs_http;
+        $this->name = $name;
+        $this->object_count = $count;
+        $this->bytes_used = $bytes;
+        $this->cdn_enabled = NULL;
+        $this->cdn_uri = NULL;
+        $this->cdn_ssl_uri = NULL;
+        $this->cdn_streaming_uri = NULL;
+        $this->cdn_ttl = NULL;
+        $this->cdn_log_retention = NULL;
+        $this->cdn_acl_user_agent = NULL;
+        $this->cdn_acl_referrer = NULL;
+        if ($this->cfs_http->getCDNMUrl() != NULL && $docdn) {
+            $this->_cdn_initialize();
+        }
+    }
+
+    /**
+     * String representation of Container
+     *
+     * Pretty print the Container instance.
+     *
+     * @return string Container details
+     */
+    function __toString()
+    {
+        $me = sprintf("name: %s, count: %.0f, bytes: %.0f",
+            $this->name, $this->object_count, $this->bytes_used);
+        if ($this->cfs_http->getCDNMUrl() != NULL) {
+            $me .= sprintf(", cdn: %s, cdn uri: %s, cdn ttl: %.0f, logs retention: %s",
+                $this->is_public() ? "Yes" : "No",
+                $this->cdn_uri, $this->cdn_ttl,
+                $this->cdn_log_retention ? "Yes" : "No"
+                );
+
+            if ($this->cdn_acl_user_agent != NULL) {
+                $me .= ", cdn acl user agent: " . $this->cdn_acl_user_agent;
+            }
+
+            if ($this->cdn_acl_referrer != NULL) {
+                $me .= ", cdn acl referrer: " . $this->cdn_acl_referrer;
+            }
+            
+            
+        }
+        return $me;
+    }
+
+    /**
+     * Enable Container content to be served via CDN or modify CDN attributes
+     *
+     * Either enable this Container's content to be served via CDN or
+     * adjust its CDN attributes.  This Container will always return the
+     * same CDN-enabled URI each time it is toggled public/private/public.
+     *
+     * Example:
+     * <code>
+     * # ... authentication code excluded (see previous examples) ...
+     * #
+     * $conn = new CF_Authentication($auth);
+     *
+     * $public_container = $conn->create_container("public");
+     *
+     * # CDN-enable the container and set it's TTL for a month
+     * #
+     * $public_container->make_public(86400/2); # 12 hours (86400 seconds/day)
+     * </code>
+     *
+     * @param int $ttl the time in seconds content will be cached in the CDN
+     * @returns string the CDN enabled Container's URI
+     * @throws CDNNotEnabledException CDN functionality not returned during auth
+     * @throws AuthenticationException if auth token is not valid/expired
+     * @throws InvalidResponseException unexpected response
+     */
+    function make_public($ttl=86400)
+    {
+        if ($this->cfs_http->getCDNMUrl() == NULL) {
+            throw new CDNNotEnabledException(
+                "Authentication response did not indicate CDN availability");
+        }
+        if ($this->cdn_uri != NULL) {
+            # previously published, assume we're setting new attributes
+            list($status, $reason, $cdn_uri, $cdn_ssl_uri) =
+                $this->cfs_http->update_cdn_container($this->name,$ttl,
+                                                      $this->cdn_log_retention,
+                                                      $this->cdn_acl_user_agent,
+                                                      $this->cdn_acl_referrer);
+            #if ($status == 401 && $this->_re_auth()) {
+            #    return $this->make_public($ttl);
+            #}
+            if ($status == 404) {
+                # this instance _thinks_ the container was published, but the
+                # cdn management system thinks otherwise - try again with a PUT
+                list($status, $reason, $cdn_uri, $cdn_ssl_uri) =
+                    $this->cfs_http->add_cdn_container($this->name,$ttl);
+
+            }
+        } else {
+            # publish it for first time
+            list($status, $reason, $cdn_uri, $cdn_ssl_uri) =
+                $this->cfs_http->add_cdn_container($this->name,$ttl);
+        }
+        #if ($status == 401 && $this->_re_auth()) {
+        #    return $this->make_public($ttl);
+        #}
+        if (!in_array($status, array(201,202))) {
+            throw new InvalidResponseException(
+                "Invalid response (".$status."): ".$this->cfs_http->get_error());
+        }
+        $this->cdn_enabled = True;
+        $this->cdn_ttl = $ttl;
+        $this->cdn_ssl_uri = $cdn_ssl_uri;
+        $this->cdn_uri = $cdn_uri;
+        $this->cdn_log_retention = False;
+        $this->cdn_acl_user_agent = "";
+        $this->cdn_acl_referrer = "";
+        return $this->cdn_uri;
+    }
+    /**
+     * Purge Containers objects from CDN Cache.
+     * Example:
+     * <code>
+     * # ... authentication code excluded (see previous examples) ...
+     * #
+     * $conn = new CF_Authentication($auth);
+     * $container = $conn->get_container("cdn_enabled");
+     * $container->purge_from_cdn("user@domain.com");
+     * # or
+     * $container->purge_from_cdn();
+     * # or 
+     * $container->purge_from_cdn("user1@domain.com,user2@domain.com");
+     * @returns boolean True if successful
+     * @throws CDNNotEnabledException if CDN Is not enabled on this connection
+     * @throws InvalidResponseException if the response expected is not returned
+     */
+    function purge_from_cdn($email=null)
+    {
+        if (!$this->cfs_http->getCDNMUrl()) 
+        {
+            throw new CDNNotEnabledException(
+                "Authentication response did not indicate CDN availability");
+        }
+        $status = $this->cfs_http->purge_from_cdn($this->name, $email);
+        if ($status < 199 or $status > 299) {
+            throw new InvalidResponseException(
+                "Invalid response (".$status."): ".$this->cfs_http->get_error());
+        } 
+        return True;
+    }
+    /**
+     * Enable ACL restriction by User Agent for this container.
+     *
+     * Example:
+     * <code>
+     * # ... authentication code excluded (see previous examples) ...
+     * #
+     * $conn = new CF_Authentication($auth);
+     *
+     * $public_container = $conn->get_container("public");
+     *
+     * # Enable ACL by Referrer
+     * $public_container->acl_referrer("Mozilla");
+     * </code>
+     *
+     * @returns boolean True if successful
+     * @throws CDNNotEnabledException CDN functionality not returned during auth
+     * @throws AuthenticationException if auth token is not valid/expired
+     * @throws InvalidResponseException unexpected response
+     */
+    function acl_user_agent($cdn_acl_user_agent="") {
+        if ($this->cfs_http->getCDNMUrl() == NULL) {
+            throw new CDNNotEnabledException(
+                "Authentication response did not indicate CDN availability");
+        }
+        list($status,$reason) =
+            $this->cfs_http->update_cdn_container($this->name,
+                                                  $this->cdn_ttl,
+                                                  $this->cdn_log_retention,
+                                                  $cdn_acl_user_agent,
+                                                  $this->cdn_acl_referrer
+                );
+        if (!in_array($status, array(202,404))) {
+            throw new InvalidResponseException(
+                "Invalid response (".$status."): ".$this->cfs_http->get_error());
+        }
+        $this->cdn_acl_user_agent = $cdn_acl_user_agent;
+        return True;
+    }
+
+    /**
+     * Enable ACL restriction by referer for this container.
+     *
+     * Example:
+     * <code>
+     * # ... authentication code excluded (see previous examples) ...
+     * #
+     * $conn = new CF_Authentication($auth);
+     *
+     * $public_container = $conn->get_container("public");
+     *
+     * # Enable Referrer
+     * $public_container->acl_referrer("http://www.example.com/gallery.php");
+     * </code>
+     *
+     * @returns boolean True if successful
+     * @throws CDNNotEnabledException CDN functionality not returned during auth
+     * @throws AuthenticationException if auth token is not valid/expired
+     * @throws InvalidResponseException unexpected response
+     */
+    function acl_referrer($cdn_acl_referrer="") {
+        if ($this->cfs_http->getCDNMUrl() == NULL) {
+            throw new CDNNotEnabledException(
+                "Authentication response did not indicate CDN availability");
+        }
+        list($status,$reason) =
+            $this->cfs_http->update_cdn_container($this->name,
+                                                  $this->cdn_ttl,
+                                                  $this->cdn_log_retention,
+                                                  $this->cdn_acl_user_agent,
+                                                  $cdn_acl_referrer
+                );
+        if (!in_array($status, array(202,404))) {
+            throw new InvalidResponseException(
+                "Invalid response (".$status."): ".$this->cfs_http->get_error());
+        }
+        $this->cdn_acl_referrer = $cdn_acl_referrer;
+        return True;
+    }
+    
+    /**
+     * Enable log retention for this CDN container.
+     *
+     * Enable CDN log retention on the container. If enabled logs will
+     * be periodically (at unpredictable intervals) compressed and
+     * uploaded to a ".CDN_ACCESS_LOGS" container in the form of
+     * "container_name.YYYYMMDDHH-XXXX.gz". Requires CDN be enabled on
+     * the account.
+     * 
+     * Example:
+     * <code>
+     * # ... authentication code excluded (see previous examples) ...
+     * #
+     * $conn = new CF_Authentication($auth);
+     *
+     * $public_container = $conn->get_container("public");
+     *
+     * # Enable logs retention.
+     * $public_container->log_retention(True);
+     * </code>
+     *
+     * @returns boolean True if successful
+     * @throws CDNNotEnabledException CDN functionality not returned during auth
+     * @throws AuthenticationException if auth token is not valid/expired
+     * @throws InvalidResponseException unexpected response
+     */
+    function log_retention($cdn_log_retention=False) {
+        if ($this->cfs_http->getCDNMUrl() == NULL) {
+            throw new CDNNotEnabledException(
+                "Authentication response did not indicate CDN availability");
+        }
+        list($status,$reason) =
+            $this->cfs_http->update_cdn_container($this->name,
+                                                  $this->cdn_ttl,
+                                                  $cdn_log_retention,
+                                                  $this->cdn_acl_user_agent,
+                                                  $this->cdn_acl_referrer
+                );
+        if (!in_array($status, array(202,404))) {
+            throw new InvalidResponseException(
+                "Invalid response (".$status."): ".$this->cfs_http->get_error());
+        }
+        $this->cdn_log_retention = $cdn_log_retention;
+        return True;
+    }
+    
+    /**
+     * Disable the CDN sharing for this container
+     *
+     * Use this method to disallow distribution into the CDN of this Container's
+     * content.
+     *
+     * NOTE: Any content already cached in the CDN will continue to be served
+     *       from its cache until the TTL expiration transpires.  The default
+     *       TTL is typically one day, so "privatizing" the Container will take
+     *       up to 24 hours before the content is purged from the CDN cache.
+     *
+     * Example:
+     * <code>
+     * # ... authentication code excluded (see previous examples) ...
+     * #
+     * $conn = new CF_Authentication($auth);
+     *
+     * $public_container = $conn->get_container("public");
+     *
+     * # Disable CDN accessability
+     * # ... still cached up to a month based on previous example
+     * #
+     * $public_container->make_private();
+     * </code>
+     *
+     * @returns boolean True if successful
+     * @throws CDNNotEnabledException CDN functionality not returned during auth
+     * @throws AuthenticationException if auth token is not valid/expired
+     * @throws InvalidResponseException unexpected response
+     */
+    function make_private()
+    {
+        if ($this->cfs_http->getCDNMUrl() == NULL) {
+            throw new CDNNotEnabledException(
+                "Authentication response did not indicate CDN availability");
+        }
+        list($status,$reason) = $this->cfs_http->remove_cdn_container($this->name);
+        #if ($status == 401 && $this->_re_auth()) {
+        #    return $this->make_private();
+        #}
+        if (!in_array($status, array(202,404))) {
+            throw new InvalidResponseException(
+                "Invalid response (".$status."): ".$this->cfs_http->get_error());
+        }
+        $this->cdn_enabled = False;
+        $this->cdn_ttl = NULL;
+        $this->cdn_uri = NULL;
+        $this->cdn_ssl_uri = NULL;
+        $this->cdn_streaming_uri - NULL;
+        $this->cdn_log_retention = NULL;
+        $this->cdn_acl_user_agent = NULL;
+        $this->cdn_acl_referrer = NULL;
+        return True;
+    }
+
+    /**
+     * Check if this Container is being publicly served via CDN
+     *
+     * Use this method to determine if the Container's content is currently
+     * available through the CDN.
+     *
+     * Example:
+     * <code>
+     * # ... authentication code excluded (see previous examples) ...
+     * #
+     * $conn = new CF_Authentication($auth);
+     *
+     * $public_container = $conn->get_container("public");
+     *
+     * # Display CDN accessability
+     * #
+     * $public_container->is_public() ? print "Yes" : print "No";
+     * </code>
+     *
+     * @returns boolean True if enabled, False otherwise
+     */
+    function is_public()
+    {
+        return $this->cdn_enabled == True ? True : False;
+    }
+
+    /**
+     * Create a new remote storage Object
+     *
+     * Return a new Object instance.  If the remote storage Object exists,
+     * the instance's attributes are populated.
+     *
+     * Example:
+     * <code>
+     * # ... authentication code excluded (see previous examples) ...
+     * #
+     * $conn = new CF_Authentication($auth);
+     *
+     * $public_container = $conn->get_container("public");
+     *
+     * # This creates a local instance of a storage object but only creates
+     * # it in the storage system when the object's write() method is called.
+     * #
+     * $pic = $public_container->create_object("baby.jpg");
+     * </code>
+     *
+     * @param string $obj_name name of storage Object
+     * @return obj CF_Object instance
+     */
+    function create_object($obj_name=NULL)
+    {
+        return new CF_Object($this, $obj_name);
+    }
+
+    /**
+     * Return an Object instance for the remote storage Object
+     *
+     * Given a name, return a Object instance representing the
+     * remote storage object.
+     *
+     * Example:
+     * <code>
+     * # ... authentication code excluded (see previous examples) ...
+     * #
+     * $conn = new CF_Authentication($auth);
+     *
+     * $public_container = $conn->get_container("public");
+     *
+     * # This call only fetches header information and not the content of
+     * # the storage object.  Use the Object's read() or stream() methods
+     * # to obtain the object's data.
+     * #
+     * $pic = $public_container->get_object("baby.jpg");
+     * </code>
+     *
+     * @param string $obj_name name of storage Object
+     * @return obj CF_Object instance
+     */
+    function get_object($obj_name=NULL)
+    {
+        return new CF_Object($this, $obj_name, True);
+    }
+
+    /**
+     * Return a list of Objects
+     *
+     * Return an array of strings listing the Object names in this Container.
+     *
+     * Example:
+     * <code>
+     * # ... authentication code excluded (see previous examples) ...
+     * #
+     * $images = $conn->get_container("my photos");
+     *
+     * # Grab the list of all storage objects
+     * #
+     * $all_objects = $images->list_objects();
+     *
+     * # Grab subsets of all storage objects
+     * #
+     * $first_ten = $images->list_objects(10);
+     * 
+     * # Note the use of the previous result's last object name being
+     * # used as the 'marker' parameter to fetch the next 10 objects
+     * #
+     * $next_ten = $images->list_objects(10, $first_ten[count($first_ten)-1]);
+     *
+     * # Grab images starting with "birthday_party" and default limit/marker
+     * # to match all photos with that prefix
+     * #
+     * $prefixed = $images->list_objects(0, NULL, "birthday");
+     *
+     * # Assuming you have created the appropriate directory marker Objects,
+     * # you can traverse your pseudo-hierarchical containers
+     * # with the "path" argument.
+     * #
+     * $animals = $images->list_objects(0,NULL,NULL,"pictures/animals");
+     * $dogs = $images->list_objects(0,NULL,NULL,"pictures/animals/dogs");
+     * </code>
+     *
+     * @param int $limit <i>optional</i> only return $limit names
+     * @param int $marker <i>optional</i> subset of names starting at $marker
+     * @param string $prefix <i>optional</i> Objects whose names begin with $prefix
+     * @param string $path <i>optional</i> only return results under "pathname"
+     * @return array array of strings
+     * @throws InvalidResponseException unexpected response
+     */
+    function list_objects($limit=0, $marker=NULL, $prefix=NULL, $path=NULL)
+    {
+        list($status, $reason, $obj_list) =
+            $this->cfs_http->list_objects($this->name, $limit,
+                $marker, $prefix, $path);
+        #if ($status == 401 && $this->_re_auth()) {
+        #    return $this->list_objects($limit, $marker, $prefix, $path);
+        #}
+        if ($status < 200 || $status > 299) {
+            throw new InvalidResponseException(
+                "Invalid response (".$status."): ".$this->cfs_http->get_error());
+        }
+        return $obj_list;
+    }
+
+    /**
+     * Return an array of Objects
+     *
+     * Return an array of Object instances in this Container.
+     *
+     * Example:
+     * <code>
+     * # ... authentication code excluded (see previous examples) ...
+     * #
+     * $images = $conn->get_container("my photos");
+     *
+     * # Grab the list of all storage objects
+     * #
+     * $all_objects = $images->get_objects();
+     *
+     * # Grab subsets of all storage objects
+     * #
+     * $first_ten = $images->get_objects(10);
+     *
+     * # Note the use of the previous result's last object name being
+     * # used as the 'marker' parameter to fetch the next 10 objects
+     * #
+     * $next_ten = $images->list_objects(10, $first_ten[count($first_ten)-1]);
+     *
+     * # Grab images starting with "birthday_party" and default limit/marker
+     * # to match all photos with that prefix
+     * #
+     * $prefixed = $images->get_objects(0, NULL, "birthday");
+     *
+     * # Assuming you have created the appropriate directory marker Objects,
+     * # you can traverse your pseudo-hierarchical containers
+     * # with the "path" argument.
+     * #
+     * $animals = $images->get_objects(0,NULL,NULL,"pictures/animals");
+     * $dogs = $images->get_objects(0,NULL,NULL,"pictures/animals/dogs");
+     * </code>
+     *
+     * @param int $limit <i>optional</i> only return $limit names
+     * @param int $marker <i>optional</i> subset of names starting at $marker
+     * @param string $prefix <i>optional</i> Objects whose names begin with $prefix
+     * @param string $path <i>optional</i> only return results under "pathname"
+     * @return array array of strings
+     * @throws InvalidResponseException unexpected response
+     */
+    function get_objects($limit=0, $marker=NULL, $prefix=NULL, $path=NULL)
+    {
+        list($status, $reason, $obj_array) =
+            $this->cfs_http->get_objects($this->name, $limit,
+                $marker, $prefix, $path);
+        #if ($status == 401 && $this->_re_auth()) {
+        #    return $this->get_objects($limit, $marker, $prefix, $path);
+        #}
+        if ($status < 200 || $status > 299) {
+            throw new InvalidResponseException(
+                "Invalid response (".$status."): ".$this->cfs_http->get_error());
+        }
+        $objects = array();
+        foreach ($obj_array as $obj) {
+            $tmp = new CF_Object($this, $obj["name"], False, False);
+            $tmp->content_type = $obj["content_type"];
+            $tmp->content_length = (float) $obj["bytes"];
+            $tmp->set_etag($obj["hash"]);
+            $tmp->last_modified = $obj["last_modified"];
+            $objects[] = $tmp;
+        }
+        return $objects;
+    }
+
+    /**
+     * Copy a remote storage Object to a target Container
+     *
+     * Given an Object instance or name and a target Container instance or name, copy copies the remote Object
+     * and all associated metadata.
+     *
+     * Example:
+     * <code>
+     * # ... authentication code excluded (see previous examples) ...
+     * #
+     * $conn = new CF_Authentication($auth);
+     *
+     * $images = $conn->get_container("my photos");
+     *
+     * # Copy specific object
+     * #
+     * $images->copy_object_to("disco_dancing.jpg","container_target");
+     * </code>
+     *
+     * @param obj $obj name or instance of Object to copy
+     * @param obj $container_target name or instance of target Container
+     * @param string $dest_obj_name name of target object (optional - uses source name if omitted)
+     * @param array $metadata metadata array for new object (optional)
+     * @param array $headers header fields array for the new object (optional)
+     * @return boolean <kbd>true</kbd> if successfully copied
+     * @throws SyntaxException invalid Object/Container name
+     * @throws NoSuchObjectException remote Object does not exist
+     * @throws InvalidResponseException unexpected response
+     */
+    function copy_object_to($obj,$container_target,$dest_obj_name=NULL,$metadata=NULL,$headers=NULL)
+    {
+        $obj_name = NULL;
+        if (is_object($obj)) {
+            if (get_class($obj) == "CF_Object") {
+                $obj_name = $obj->name;
+            }
+        }
+        if (is_string($obj)) {
+            $obj_name = $obj;
+        }
+        if (!$obj_name) {
+            throw new SyntaxException("Object name not set.");
+        }
+
+				if ($dest_obj_name === NULL) {
+            $dest_obj_name = $obj_name;
+				}
+
+        $container_name_target = NULL;
+        if (is_object($container_target)) {
+            if (get_class($container_target) == "CF_Container") {
+                $container_name_target = $container_target->name;
+            }
+        }
+        if (is_string($container_target)) {
+            $container_name_target = $container_target;
+        }
+        if (!$container_name_target) {
+            throw new SyntaxException("Container name target not set.");
+        }
+
+        $status = $this->cfs_http->copy_object($obj_name,$dest_obj_name,$this->name,$container_name_target,$metadata,$headers);
+        if ($status == 404) {
+            $m = "Specified object '".$this->name."/".$obj_name;
+            $m.= "' did not exist as source to copy from or '".$container_name_target."' did not exist as target to copy to.";
+            throw new NoSuchObjectException($m);
+        }
+        if ($status < 200 || $status > 299) {
+            throw new InvalidResponseException(
+                "Invalid response (".$status."): ".$this->cfs_http->get_error());
+        }
+        return true;
+    }
+
+    /**
+     * Copy a remote storage Object from a source Container
+     *
+     * Given an Object instance or name and a source Container instance or name, copy copies the remote Object
+     * and all associated metadata.
+     *
+     * Example:
+     * <code>
+     * # ... authentication code excluded (see previous examples) ...
+     * #
+     * $conn = new CF_Authentication($auth);
+     *
+     * $images = $conn->get_container("my photos");
+     *
+     * # Copy specific object
+     * #
+     * $images->copy_object_from("disco_dancing.jpg","container_source");
+     * </code>
+     *
+     * @param obj $obj name or instance of Object to copy
+     * @param obj $container_source name or instance of source Container
+     * @param string $dest_obj_name name of target object (optional - uses source name if omitted)
+     * @param array $metadata metadata array for new object (optional)
+     * @param array $headers header fields array for the new object (optional)
+     * @return boolean <kbd>true</kbd> if successfully copied
+     * @throws SyntaxException invalid Object/Container name
+     * @throws NoSuchObjectException remote Object does not exist
+     * @throws InvalidResponseException unexpected response
+     */
+    function copy_object_from($obj,$container_source,$dest_obj_name=NULL,$metadata=NULL,$headers=NULL)
+    {
+        $obj_name = NULL;
+        if (is_object($obj)) {
+            if (get_class($obj) == "CF_Object") {
+                $obj_name = $obj->name;
+            }
+        }
+        if (is_string($obj)) {
+            $obj_name = $obj;
+        }
+        if (!$obj_name) {
+            throw new SyntaxException("Object name not set.");
+        }
+
+				if ($dest_obj_name === NULL) {
+            $dest_obj_name = $obj_name;
+				}
+
+        $container_name_source = NULL;
+        if (is_object($container_source)) {
+            if (get_class($container_source) == "CF_Container") {
+                $container_name_source = $container_source->name;
+            }
+        }
+        if (is_string($container_source)) {
+            $container_name_source = $container_source;
+        }
+        if (!$container_name_source) {
+            throw new SyntaxException("Container name source not set.");
+        }
+
+        $status = $this->cfs_http->copy_object($obj_name,$dest_obj_name,$container_name_source,$this->name,$metadata,$headers);
+        if ($status == 404) {
+            $m = "Specified object '".$container_name_source."/".$obj_name;
+            $m.= "' did not exist as source to copy from or '".$this->name."/".$obj_name."' did not exist as target to copy to.";
+            throw new NoSuchObjectException($m);
+        }
+        if ($status < 200 || $status > 299) {
+            throw new InvalidResponseException(
+                "Invalid response (".$status."): ".$this->cfs_http->get_error());
+        }
+        
+        return true;
+    }
+
+    /**
+     * Move a remote storage Object to a target Container
+     *
+     * Given an Object instance or name and a target Container instance or name, move copies the remote Object
+     * and all associated metadata and deletes the source Object afterwards
+     *
+     * Example:
+     * <code>
+     * # ... authentication code excluded (see previous examples) ...
+     * #
+     * $conn = new CF_Authentication($auth);
+     *
+     * $images = $conn->get_container("my photos");
+     *
+     * # Move specific object
+     * #
+     * $images->move_object_to("disco_dancing.jpg","container_target");
+     * </code>
+     *
+     * @param obj $obj name or instance of Object to move
+     * @param obj $container_target name or instance of target Container
+     * @param string $dest_obj_name name of target object (optional - uses source name if omitted)
+     * @param array $metadata metadata array for new object (optional)
+     * @param array $headers header fields array for the new object (optional)
+     * @return boolean <kbd>true</kbd> if successfully moved
+     * @throws SyntaxException invalid Object/Container name
+     * @throws NoSuchObjectException remote Object does not exist
+     * @throws InvalidResponseException unexpected response
+     */
+    function move_object_to($obj,$container_target,$dest_obj_name=NULL,$metadata=NULL,$headers=NULL)
+    {
+    	$retVal = false;
+
+        if(self::copy_object_to($obj,$container_target,$dest_obj_name,$metadata,$headers)) {
+        	$retVal = self::delete_object($obj,$this->name);
+        }
+
+        return $retVal;
+    }
+
+    /**
+     * Move a remote storage Object from a source Container
+     *
+     * Given an Object instance or name and a source Container instance or name, move copies the remote Object
+     * and all associated metadata and deletes the source Object afterwards
+     *
+     * Example:
+     * <code>
+     * # ... authentication code excluded (see previous examples) ...
+     * #
+     * $conn = new CF_Authentication($auth);
+     *
+     * $images = $conn->get_container("my photos");
+     *
+     * # Move specific object
+     * #
+     * $images->move_object_from("disco_dancing.jpg","container_target");
+     * </code>
+     *
+     * @param obj $obj name or instance of Object to move
+     * @param obj $container_source name or instance of target Container
+     * @param string $dest_obj_name name of target object (optional - uses source name if omitted)
+     * @param array $metadata metadata array for new object (optional)
+     * @param array $headers header fields array for the new object (optional)
+     * @return boolean <kbd>true</kbd> if successfully moved
+     * @throws SyntaxException invalid Object/Container name
+     * @throws NoSuchObjectException remote Object does not exist
+     * @throws InvalidResponseException unexpected response
+     */
+    function move_object_from($obj,$container_source,$dest_obj_name=NULL,$metadata=NULL,$headers=NULL)
+    {
+    	$retVal = false;
+
+        if(self::copy_object_from($obj,$container_source,$dest_obj_name,$metadata,$headers)) {
+        	$retVal = self::delete_object($obj,$container_source);
+        } 	
+
+        return $retVal;
+    }
+
+    /**
+     * Delete a remote storage Object
+     *
+     * Given an Object instance or name, permanently remove the remote Object
+     * and all associated metadata.
+     *
+     * Example:
+     * <code>
+     * # ... authentication code excluded (see previous examples) ...
+     * #
+     * $conn = new CF_Authentication($auth);
+     *
+     * $images = $conn->get_container("my photos");
+     *
+     * # Delete specific object
+     * #
+     * $images->delete_object("disco_dancing.jpg");
+     * </code>
+     *
+     * @param obj $obj name or instance of Object to delete
+     * @param obj $container name or instance of Container in which the object resides (optional)
+     * @return boolean <kbd>True</kbd> if successfully removed
+     * @throws SyntaxException invalid Object name
+     * @throws NoSuchObjectException remote Object does not exist
+     * @throws InvalidResponseException unexpected response
+     */
+    function delete_object($obj,$container=NULL)
+    {
+        $obj_name = NULL;
+        if (is_object($obj)) {
+            if (get_class($obj) == "CF_Object") {
+                $obj_name = $obj->name;
+            }
+        }
+        if (is_string($obj)) {
+            $obj_name = $obj;
+        }
+        if (!$obj_name) {
+            throw new SyntaxException("Object name not set.");
+        }
+
+        $container_name = NULL;
+
+        if($container === NULL) {
+        	$container_name = $this->name;
+        }
+        else {
+	        if (is_object($container)) {
+	            if (get_class($container) == "CF_Container") {
+	                $container_name = $container->name;
+	            }
+	        }
+	        if (is_string($container)) {
+	            $container_name = $container;
+	        }
+	        if (!$container_name) {
+	            throw new SyntaxException("Container name source not set.");
+	        }
+        }
+
+        $status = $this->cfs_http->delete_object($container_name, $obj_name);
+        #if ($status == 401 && $this->_re_auth()) {
+        #    return $this->delete_object($obj);
+        #}
+        if ($status == 404) {
+            $m = "Specified object '".$container_name."/".$obj_name;
+            $m.= "' did not exist to delete.";
+            throw new NoSuchObjectException($m);
+        }
+        if ($status != 204) {
+            throw new InvalidResponseException(
+                "Invalid response (".$status."): ".$this->cfs_http->get_error());
+        }
+        return True;
+    }
+
+    /**
+     * Helper function to create "path" elements for a given Object name
+     *
+     * Given an Object whos name contains '/' path separators, this function
+     * will create the "directory marker" Objects of one byte with the
+     * Content-Type of "application/directory".
+     *
+     * It assumes the last element of the full path is the "real" Object
+     * and does NOT create a remote storage Object for that last element.
+     */
+    function create_paths($path_name)
+    {
+        if ($path_name[0] == '/') {
+            $path_name = mb_substr($path_name, 0, 1);
+        }
+        $elements = explode('/', $path_name, -1);
+        $build_path = "";
+        foreach ($elements as $idx => $val) {
+            if (!$build_path) {
+                $build_path = $val;
+            } else {
+                $build_path .= "/" . $val;
+            }
+            $obj = new CF_Object($this, $build_path);
+            $obj->content_type = "application/directory";
+            $obj->write(".", 1);
+        }
+    }
+
+    /**
+     * Internal method to grab CDN/Container info if appropriate to do so
+     *
+     * @throws InvalidResponseException unexpected response
+     */
+    private function _cdn_initialize()
+    {
+        list($status, $reason, $cdn_enabled, $cdn_ssl_uri, $cdn_streaming_uri, $cdn_uri, $cdn_ttl,
+             $cdn_log_retention, $cdn_acl_user_agent, $cdn_acl_referrer) =
+            $this->cfs_http->head_cdn_container($this->name);
+        #if ($status == 401 && $this->_re_auth()) {
+        #    return $this->_cdn_initialize();
+        #}
+        if (!in_array($status, array(204,404))) {
+            throw new InvalidResponseException(
+                "Invalid response (".$status."): ".$this->cfs_http->get_error());
+        }
+        $this->cdn_enabled = $cdn_enabled;
+        $this->cdn_streaming_uri = $cdn_streaming_uri;
+        $this->cdn_ssl_uri = $cdn_ssl_uri;
+        $this->cdn_uri = $cdn_uri;
+        $this->cdn_ttl = $cdn_ttl;
+        $this->cdn_log_retention = $cdn_log_retention;
+        $this->cdn_acl_user_agent = $cdn_acl_user_agent;
+        $this->cdn_acl_referrer = $cdn_acl_referrer;
+    }
+
+    #private function _re_auth()
+    #{
+    #    $new_auth = new CF_Authentication(
+    #        $this->cfs_auth->username,
+    #        $this->cfs_auth->api_key,
+    #        $this->cfs_auth->auth_host,
+    #        $this->cfs_auth->account);
+    #    $new_auth->authenticate();
+    #    $this->cfs_auth = $new_auth;
+    #    $this->cfs_http->setCFAuth($this->cfs_auth);
+    #    return True;
+    #}
+}
+
+
+/**
+ * Object operations
+ *
+ * An Object is analogous to a file on a conventional filesystem. You can
+ * read data from, or write data to your Objects. You can also associate 
+ * arbitrary metadata with them.
+ *
+ * @package php-cloudfiles
+ */
+class CF_Object
+{
+    public $container;
+    public $name;
+    public $last_modified;
+    public $content_type;
+    public $content_length;
+    public $metadata;
+    public $headers;
+    public $manifest;
+    private $etag;
+
+    /**
+     * Class constructor
+     *
+     * @param obj $container CF_Container instance
+     * @param string $name name of Object
+     * @param boolean $force_exists if set, throw an error if Object doesn't exist
+     */
+    function __construct(&$container, $name, $force_exists=False, $dohead=True)
+    {
+        if ($name[0] == "/") {
+            $r = "Object name '".$name;
+            $r .= "' cannot contain begin with a '/' character.";
+            throw new SyntaxException($r);
+        }
+        if (strlen($name) > MAX_OBJECT_NAME_LEN) {
+            throw new SyntaxException("Object name exceeds "
+                . "maximum allowed length.");
+        }
+        $this->container = $container;
+        $this->name = $name;
+        $this->etag = NULL;
+        $this->_etag_override = False;
+        $this->last_modified = NULL;
+        $this->content_type = NULL;
+        $this->content_length = 0;
+        $this->metadata = array();
+        $this->headers = array();
+        $this->manifest = NULL;
+        if ($dohead) {
+            if (!$this->_initialize() && $force_exists) {
+                throw new NoSuchObjectException("No such object '".$name."'");
+            }
+        }
+    }
+
+    /**
+     * String representation of Object
+     *
+     * Pretty print the Object's location and name
+     *
+     * @return string Object information
+     */
+    function __toString()
+    {
+        return $this->container->name . "/" . $this->name;
+    }
+
+    /**
+     * Internal check to get the proper mimetype.
+     *
+     * This function would go over the available PHP methods to get
+     * the MIME type.
+     *
+     * By default it will try to use the PHP fileinfo library which is
+     * available from PHP 5.3 or as an PECL extension
+     * (http://pecl.php.net/package/Fileinfo).
+     *
+     * It will get the magic file by default from the system wide file
+     * which is usually available in /usr/share/magic on Unix or try
+     * to use the file specified in the source directory of the API
+     * (share directory).
+     *
+     * if fileinfo is not available it will try to use the internal
+     * mime_content_type function.
+     * 
+     * @param string $handle name of file or buffer to guess the type from
+     * @return boolean <kbd>True</kbd> if successful
+     * @throws BadContentTypeException
+     */
+    function _guess_content_type($handle) {
+        if ($this->content_type)
+            return;
+            
+//         if (function_exists("finfo_open")) {
+//             $local_magic = dirname(__FILE__) . "/share/magic";
+//             $finfo = @finfo_open(FILEINFO_MIME, $local_magic);
+// 
+//             if (!$finfo) 
+//                 $finfo = @finfo_open(FILEINFO_MIME);
+//                 
+//             if ($finfo) {
+// 
+//                 if (is_file((string)$handle))
+//                     $ct = @finfo_file($finfo, $handle);
+//                 else 
+//                     $ct = @finfo_buffer($finfo, $handle);
+// 
+//                 /* PHP 5.3 fileinfo display extra information like
+//                    charset so we remove everything after the ; since
+//                    we are not into that stuff */
+//                 if ($ct) {
+//                     $extra_content_type_info = strpos($ct, "; ");
+//                     if ($extra_content_type_info)
+//                         $ct = substr($ct, 0, $extra_content_type_info);
+//                 }
+// 
+//                 if ($ct && $ct != 'application/octet-stream')
+//                     $this->content_type = $ct;
+// 
+//                 @finfo_close($finfo);
+//             }
+//         }
+// 
+//         if (!$this->content_type && (string)is_file($handle) && function_exists("mime_content_type")) {
+//             $this->content_type = @mime_content_type($handle);
+//         }
+
+		//use OC's mimetype detection for files
+		if(is_file($handle)){
+			$this->content_type=OC_Helper::getMimeType($handle);
+		}else{
+			$this->content_type=OC_Helper::getStringMimeType($handle);
+		}
+
+        if (!$this->content_type) {
+            throw new BadContentTypeException("Required Content-Type not set");
+        }
+        return True;
+    }
+    
+    /**
+     * String representation of the Object's public URI
+     *
+     * A string representing the Object's public URI assuming that it's
+     * parent Container is CDN-enabled.
+     *
+     * Example:
+     * <code>
+     * # ... authentication/connection/container code excluded
+     * # ... see previous examples
+     *
+     * # Print out the Object's CDN URI (if it has one) in an HTML img-tag
+     * #
+     * print "<img src='$pic->public_uri()' />\n";
+     * </code>
+     *
+     * @return string Object's public URI or NULL
+     */
+    function public_uri()
+    {
+        if ($this->container->cdn_enabled) {
+            return $this->container->cdn_uri . "/" . $this->name;
+        }
+        return NULL;
+    }
+
+       /**
+     * String representation of the Object's public SSL URI
+     *
+     * A string representing the Object's public SSL URI assuming that it's
+     * parent Container is CDN-enabled.
+     *
+     * Example:
+     * <code>
+     * # ... authentication/connection/container code excluded
+     * # ... see previous examples
+     *
+     * # Print out the Object's CDN SSL URI (if it has one) in an HTML img-tag
+     * #
+     * print "<img src='$pic->public_ssl_uri()' />\n";
+     * </code>
+     *
+     * @return string Object's public SSL URI or NULL
+     */
+    function public_ssl_uri()
+    {
+        if ($this->container->cdn_enabled) {
+            return $this->container->cdn_ssl_uri . "/" . $this->name;
+        }
+        return NULL;
+    }
+    /**
+     * String representation of the Object's public Streaming URI
+     *
+     * A string representing the Object's public Streaming URI assuming that it's
+     * parent Container is CDN-enabled.
+     *
+     * Example:
+     * <code>
+     * # ... authentication/connection/container code excluded
+     * # ... see previous examples
+     *
+     * # Print out the Object's CDN Streaming URI (if it has one) in an HTML img-tag
+     * #
+     * print "<img src='$pic->public_streaming_uri()' />\n";
+     * </code>
+     *
+     * @return string Object's public Streaming URI or NULL
+     */
+    function public_streaming_uri()
+    {
+        if ($this->container->cdn_enabled) {
+            return $this->container->cdn_streaming_uri . "/" . $this->name;
+        }
+        return NULL;
+    }
+
+    /**
+     * Read the remote Object's data
+     *
+     * Returns the Object's data.  This is useful for smaller Objects such
+     * as images or office documents.  Object's with larger content should use
+     * the stream() method below.
+     *
+     * Pass in $hdrs array to set specific custom HTTP headers such as
+     * If-Match, If-None-Match, If-Modified-Since, Range, etc.
+     *
+     * Example:
+     * <code>
+     * # ... authentication/connection/container code excluded
+     * # ... see previous examples
+     *
+     * $my_docs = $conn->get_container("documents");
+     * $doc = $my_docs->get_object("README");
+     * $data = $doc->read(); # read image content into a string variable
+     * print $data;
+     *
+     * # Or see stream() below for a different example.
+     * #
+     * </code>
+     *
+     * @param array $hdrs user-defined headers (Range, If-Match, etc.)
+     * @return string Object's data
+     * @throws InvalidResponseException unexpected response
+     */
+    function read($hdrs=array())
+    {
+        list($status, $reason, $data) =
+            $this->container->cfs_http->get_object_to_string($this, $hdrs);
+        #if ($status == 401 && $this->_re_auth()) {
+        #    return $this->read($hdrs);
+        #}
+        if (($status < 200) || ($status > 299
+                && $status != 412 && $status != 304)) {
+            throw new InvalidResponseException("Invalid response (".$status."): "
+                . $this->container->cfs_http->get_error());
+        }
+        return $data;
+    }
+
+    /**
+     * Streaming read of Object's data
+     *
+     * Given an open PHP resource (see PHP's fopen() method), fetch the Object's
+     * data and write it to the open resource handle.  This is useful for
+     * streaming an Object's content to the browser (videos, images) or for
+     * fetching content to a local file.
+     *
+     * Pass in $hdrs array to set specific custom HTTP headers such as
+     * If-Match, If-None-Match, If-Modified-Since, Range, etc.
+     *
+     * Example:
+     * <code>
+     * # ... authentication/connection/container code excluded
+     * # ... see previous examples
+     *
+     * # Assuming this is a web script to display the README to the
+     * # user's browser:
+     * #
+     * <?php
+     * // grab README from storage system
+     * //
+     * $my_docs = $conn->get_container("documents");
+     * $doc = $my_docs->get_object("README");
+     *
+     * // Hand it back to user's browser with appropriate content-type
+     * //
+     * header("Content-Type: " . $doc->content_type);
+     * $output = fopen("php://output", "w");
+     * $doc->stream($output); # stream object content to PHP's output buffer
+     * fclose($output);
+     * ?>
+     *
+     * # See read() above for a more simple example.
+     * #
+     * </code>
+     *
+     * @param resource $fp open resource for writing data to
+     * @param array $hdrs user-defined headers (Range, If-Match, etc.)
+     * @return string Object's data
+     * @throws InvalidResponseException unexpected response
+     */
+    function stream(&$fp, $hdrs=array())
+    {
+        list($status, $reason) = 
+                $this->container->cfs_http->get_object_to_stream($this,$fp,$hdrs);
+        #if ($status == 401 && $this->_re_auth()) {
+        #    return $this->stream($fp, $hdrs);
+        #}
+        if (($status < 200) || ($status > 299
+                && $status != 412 && $status != 304)) {
+            throw new InvalidResponseException("Invalid response (".$status."): "
+                .$reason);
+        }
+        return True;
+    }
+
+    /**
+     * Store new Object metadata
+     *
+     * Write's an Object's metadata to the remote Object.  This will overwrite
+     * an prior Object metadata.
+     *
+     * Example:
+     * <code>
+     * # ... authentication/connection/container code excluded
+     * # ... see previous examples
+     *
+     * $my_docs = $conn->get_container("documents");
+     * $doc = $my_docs->get_object("README");
+     *
+     * # Define new metadata for the object
+     * #
+     * $doc->metadata = array(
+     *     "Author" => "EJ",
+     *     "Subject" => "How to use the PHP tests",
+     *     "Version" => "1.2.2"
+     * );
+     *
+     * # Define additional headers for the object
+     * #
+     * $doc->headers = array(
+     *     "Content-Disposition" => "attachment",
+     * );
+     *
+     * # Push the new metadata up to the storage system
+     * #
+     * $doc->sync_metadata();
+     * </code>
+     *
+     * @return boolean <kbd>True</kbd> if successful, <kbd>False</kbd> otherwise
+     * @throws InvalidResponseException unexpected response
+     */
+    function sync_metadata()
+    {
+        if (!empty($this->metadata) || !empty($this->headers) || $this->manifest) {
+            $status = $this->container->cfs_http->update_object($this);
+            #if ($status == 401 && $this->_re_auth()) {
+            #    return $this->sync_metadata();
+            #}
+            if ($status != 202) {
+                throw new InvalidResponseException("Invalid response ("
+                    .$status."): ".$this->container->cfs_http->get_error());
+            }
+            return True;
+        }
+        return False;
+    }
+    /**
+     * Store new Object manifest
+     *
+     * Write's an Object's manifest to the remote Object.  This will overwrite
+     * an prior Object manifest.
+     *
+     * Example:
+     * <code>
+     * # ... authentication/connection/container code excluded
+     * # ... see previous examples
+     *
+     * $my_docs = $conn->get_container("documents");
+     * $doc = $my_docs->get_object("README");
+     *
+     * # Define new manifest for the object
+     * #
+     * $doc->manifest = "container/prefix";
+     *
+     * # Push the new manifest up to the storage system
+     * #
+     * $doc->sync_manifest();
+     * </code>
+     *
+     * @return boolean <kbd>True</kbd> if successful, <kbd>False</kbd> otherwise
+     * @throws InvalidResponseException unexpected response
+     */
+
+    function sync_manifest()
+    {
+        return $this->sync_metadata();
+    }
+    /**
+     * Upload Object's data to Cloud Files
+     *
+     * Write data to the remote Object.  The $data argument can either be a
+     * PHP resource open for reading (see PHP's fopen() method) or an in-memory
+     * variable.  If passing in a PHP resource, you must also include the $bytes
+     * parameter.
+     *
+     * Example:
+     * <code>
+     * # ... authentication/connection/container code excluded
+     * # ... see previous examples
+     *
+     * $my_docs = $conn->get_container("documents");
+     * $doc = $my_docs->get_object("README");
+     *
+     * # Upload placeholder text in my README
+     * #
+     * $doc->write("This is just placeholder text for now...");
+     * </code>
+     *
+     * @param string|resource $data string or open resource
+     * @param float $bytes amount of data to upload (required for resources)
+     * @param boolean $verify generate, send, and compare MD5 checksums
+     * @return boolean <kbd>True</kbd> when data uploaded successfully
+     * @throws SyntaxException missing required parameters
+     * @throws BadContentTypeException if no Content-Type was/could be set
+     * @throws MisMatchedChecksumException $verify is set and checksums unequal
+     * @throws InvalidResponseException unexpected response
+     */
+    function write($data=NULL, $bytes=0, $verify=True)
+    {
+        if (!$data && !is_string($data)) {
+            throw new SyntaxException("Missing data source.");
+        }
+        if ($bytes > MAX_OBJECT_SIZE) {
+            throw new SyntaxException("Bytes exceeds maximum object size.");
+        }
+        if ($verify) {
+            if (!$this->_etag_override) {
+                $this->etag = $this->compute_md5sum($data);
+            }
+        } else {
+            $this->etag = NULL;
+        }
+
+        $close_fh = False;
+        if (!is_resource($data)) {
+            # A hack to treat string data as a file handle.  php://memory feels
+            # like a better option, but it seems to break on Windows so use
+            # a temporary file instead.
+            #
+            $fp = fopen("php://temp", "wb+");
+            #$fp = fopen("php://memory", "wb+");
+            fwrite($fp, $data, strlen($data));
+            rewind($fp);
+            $close_fh = True;
+            $this->content_length = (float) strlen($data);
+            if ($this->content_length > MAX_OBJECT_SIZE) {
+                throw new SyntaxException("Data exceeds maximum object size");
+            }
+            $ct_data = substr($data, 0, 64);
+        } else {
+            $this->content_length = $bytes;
+            $fp = $data;
+            $ct_data = fread($data, 64);
+            rewind($data);
+        }
+
+        $this->_guess_content_type($ct_data);
+
+        list($status, $reason, $etag) =
+                $this->container->cfs_http->put_object($this, $fp);
+        #if ($status == 401 && $this->_re_auth()) {
+        #    return $this->write($data, $bytes, $verify);
+        #}
+        if ($status == 412) {
+            if ($close_fh) { fclose($fp); }
+            throw new SyntaxException("Missing Content-Type header");
+        }
+        if ($status == 422) {
+            if ($close_fh) { fclose($fp); }
+            throw new MisMatchedChecksumException(
+                "Supplied and computed checksums do not match.");
+        }
+        if ($status != 201) {
+            if ($close_fh) { fclose($fp); }
+            throw new InvalidResponseException("Invalid response (".$status."): "
+                . $this->container->cfs_http->get_error());
+        }
+        if (!$verify) {
+            $this->etag = $etag;
+        }
+        if ($close_fh) { fclose($fp); }
+        return True;
+    }
+
+    /**
+     * Upload Object data from local filename
+     *
+     * This is a convenience function to upload the data from a local file.  A
+     * True value for $verify will cause the method to compute the Object's MD5
+     * checksum prior to uploading.
+     *
+     * Example:
+     * <code>
+     * # ... authentication/connection/container code excluded
+     * # ... see previous examples
+     *
+     * $my_docs = $conn->get_container("documents");
+     * $doc = $my_docs->get_object("README");
+     *
+     * # Upload my local README's content
+     * #
+     * $doc->load_from_filename("/home/ej/cloudfiles/readme");
+     * </code>
+     *
+     * @param string $filename full path to local file
+     * @param boolean $verify enable local/remote MD5 checksum validation
+     * @return boolean <kbd>True</kbd> if data uploaded successfully
+     * @throws SyntaxException missing required parameters
+     * @throws BadContentTypeException if no Content-Type was/could be set
+     * @throws MisMatchedChecksumException $verify is set and checksums unequal
+     * @throws InvalidResponseException unexpected response
+     * @throws IOException error opening file
+     */
+    function load_from_filename($filename, $verify=True)
+    {
+        $fp = @fopen($filename, "r");
+        if (!$fp) {
+            throw new IOException("Could not open file for reading: ".$filename);
+        }
+
+        clearstatcache();
+        
+        $size = (float) sprintf("%u", filesize($filename));
+        if ($size > MAX_OBJECT_SIZE) {
+            throw new SyntaxException("File size exceeds maximum object size.");
+        }
+
+        $this->_guess_content_type($filename);
+        
+        $this->write($fp, $size, $verify);
+        fclose($fp);
+        return True;
+    }
+
+    /**
+     * Save Object's data to local filename
+     *
+     * Given a local filename, the Object's data will be written to the newly
+     * created file.
+     *
+     * Example:
+     * <code>
+     * # ... authentication/connection/container code excluded
+     * # ... see previous examples
+     *
+     * # Whoops!  I deleted my local README, let me download/save it
+     * #
+     * $my_docs = $conn->get_container("documents");
+     * $doc = $my_docs->get_object("README");
+     *
+     * $doc->save_to_filename("/home/ej/cloudfiles/readme.restored");
+     * </code>
+     *
+     * @param string $filename name of local file to write data to
+     * @return boolean <kbd>True</kbd> if successful
+     * @throws IOException error opening file
+     * @throws InvalidResponseException unexpected response
+     */
+    function save_to_filename($filename)
+    {
+        $fp = @fopen($filename, "wb");
+        if (!$fp) {
+            throw new IOException("Could not open file for writing: ".$filename);
+        }
+        $result = $this->stream($fp);
+        fclose($fp);
+        return $result;
+    }
+       /**
+     * Purge this Object from CDN Cache.
+     * Example:
+     * <code>
+     * # ... authentication code excluded (see previous examples) ...
+     * #
+     * $conn = new CF_Authentication($auth);
+     * $container = $conn->get_container("cdn_enabled");
+     * $obj = $container->get_object("object");
+     * $obj->purge_from_cdn("user@domain.com");
+     * # or
+     * $obj->purge_from_cdn();
+     * # or 
+     * $obj->purge_from_cdn("user1@domain.com,user2@domain.com");
+     * @returns boolean True if successful
+     * @throws CDNNotEnabledException if CDN Is not enabled on this connection
+     * @throws InvalidResponseException if the response expected is not returned
+     */
+    function purge_from_cdn($email=null)
+    {
+        if (!$this->container->cfs_http->getCDNMUrl())
+        {
+            throw new CDNNotEnabledException(
+                "Authentication response did not indicate CDN availability");
+        }
+        $status = $this->container->cfs_http->purge_from_cdn($this->container->name . "/" . $this->name, $email);
+        if ($status < 199 or $status > 299) {
+            throw new InvalidResponseException(
+                "Invalid response (".$status."): ".$this->container->cfs_http->get_error());
+        }
+        return True;
+    }
+
+    /**
+     * Set Object's MD5 checksum
+     *
+     * Manually set the Object's ETag.  Including the ETag is mandatory for
+     * Cloud Files to perform end-to-end verification.  Omitting the ETag forces
+     * the user to handle any data integrity checks.
+     *
+     * @param string $etag MD5 checksum hexidecimal string
+     */
+    function set_etag($etag)
+    {
+        $this->etag = $etag;
+        $this->_etag_override = True;
+    }
+
+    /**
+     * Object's MD5 checksum
+     *
+     * Accessor method for reading Object's private ETag attribute.
+     *
+     * @return string MD5 checksum hexidecimal string
+     */
+    function getETag()
+    {
+        return $this->etag;
+    }
+
+    /**
+     * Compute the MD5 checksum
+     *
+     * Calculate the MD5 checksum on either a PHP resource or data.  The argument
+     * may either be a local filename, open resource for reading, or a string.
+     *
+     * <b>WARNING:</b> if you are uploading a big file over a stream
+     * it could get very slow to compute the md5 you probably want to
+     * set the $verify parameter to False in the write() method and
+     * compute yourself the md5 before if you have it.
+     *
+     * @param filename|obj|string $data filename, open resource, or string
+     * @return string MD5 checksum hexidecimal string
+     */
+    function compute_md5sum(&$data)
+    {
+
+        if (function_exists("hash_init") && is_resource($data)) {
+            $ctx = hash_init('md5');
+            while (!feof($data)) {
+                $buffer = fgets($data, 65536);
+                hash_update($ctx, $buffer);
+            }
+            $md5 = hash_final($ctx, false);
+            rewind($data);
+        } elseif ((string)is_file($data)) {
+            $md5 = md5_file($data);
+        } else {
+            $md5 = md5($data);
+        }
+        return $md5;
+    }
+
+    /**
+     * PRIVATE: fetch information about the remote Object if it exists
+     */
+    private function _initialize()
+    {
+        list($status, $reason, $etag, $last_modified, $content_type,
+            $content_length, $metadata, $manifest, $headers) =
+                $this->container->cfs_http->head_object($this);
+        #if ($status == 401 && $this->_re_auth()) {
+        #    return $this->_initialize();
+        #}
+        if ($status == 404) {
+            return False;
+        }
+        if ($status < 200 || $status > 299) {
+            throw new InvalidResponseException("Invalid response (".$status."): "
+                . $this->container->cfs_http->get_error());
+        }
+        $this->etag = $etag;
+        $this->last_modified = $last_modified;
+        $this->content_type = $content_type;
+        $this->content_length = $content_length;
+        $this->metadata = $metadata;
+        $this->headers = $headers;
+        $this->manifest = $manifest;
+        return True;
+    }
+
+    #private function _re_auth()
+    #{
+    #    $new_auth = new CF_Authentication(
+    #        $this->cfs_auth->username,
+    #        $this->cfs_auth->api_key,
+    #        $this->cfs_auth->auth_host,
+    #        $this->cfs_auth->account);
+    #    $new_auth->authenticate();
+    #    $this->container->cfs_auth = $new_auth;
+    #    $this->container->cfs_http->setCFAuth($this->cfs_auth);
+    #    return True;
+    #}
+}
+
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * c-hanging-comment-ender-p: nil
+ * End:
+ */
+?>
diff --git a/3rdparty/php-cloudfiles/cloudfiles_exceptions.php b/3rdparty/php-cloudfiles/cloudfiles_exceptions.php
new file mode 100644
index 0000000000000000000000000000000000000000..5624d6b86342a5b2e8f5292596c87d0ff40624a1
--- /dev/null
+++ b/3rdparty/php-cloudfiles/cloudfiles_exceptions.php
@@ -0,0 +1,41 @@
+<?php
+/**
+ * Custom Exceptions for the CloudFiles API
+ *
+ * Requres PHP 5.x (for Exceptions and OO syntax)
+ *
+ * See COPYING for license information.
+ *
+ * @author Eric "EJ" Johnson <ej@racklabs.com>
+ * @copyright Copyright (c) 2008, Rackspace US, Inc.
+ * @package php-cloudfiles-exceptions
+ */
+
+/**
+ * Custom Exceptions for the CloudFiles API
+ * @package php-cloudfiles-exceptions
+ */
+class SyntaxException extends Exception { }
+class AuthenticationException extends Exception { }
+class InvalidResponseException extends Exception { }
+class NonEmptyContainerException extends Exception { }
+class NoSuchObjectException extends Exception { }
+class NoSuchContainerException extends Exception { }
+class NoSuchAccountException extends Exception { }
+class MisMatchedChecksumException extends Exception { }
+class IOException extends Exception { }
+class CDNNotEnabledException extends Exception { }
+class BadContentTypeException extends Exception { }
+class InvalidUTF8Exception extends Exception { }
+class ConnectionNotOpenException extends Exception { }
+
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * c-hanging-comment-ender-p: nil
+ * End:
+ */
+?>
diff --git a/3rdparty/php-cloudfiles/cloudfiles_http.php b/3rdparty/php-cloudfiles/cloudfiles_http.php
new file mode 100644
index 0000000000000000000000000000000000000000..0e5d9717e813496b033e2ec59026dba65535bc36
--- /dev/null
+++ b/3rdparty/php-cloudfiles/cloudfiles_http.php
@@ -0,0 +1,1488 @@
+<?php
+/**
+ * This is an HTTP client class for Cloud Files.  It uses PHP's cURL module
+ * to handle the actual HTTP request/response.  This is NOT a generic HTTP
+ * client class and is only used to abstract out the HTTP communication for
+ * the PHP Cloud Files API.
+ *
+ * This module was designed to re-use existing HTTP(S) connections between
+ * subsequent operations.  For example, performing multiple PUT operations
+ * will re-use the same connection.
+ *
+ * This modules also provides support for streaming content into and out
+ * of Cloud Files.  The majority (all?) of the PHP HTTP client modules expect
+ * to read the server's response into a string variable.  This will not work
+ * with large files without killing your server.  Methods like,
+ * get_object_to_stream() and put_object() take an open filehandle
+ * argument for streaming data out of or into Cloud Files.
+ *
+ * Requres PHP 5.x (for Exceptions and OO syntax)
+ *
+ * See COPYING for license information.
+ *
+ * @author Eric "EJ" Johnson <ej@racklabs.com>
+ * @copyright Copyright (c) 2008, Rackspace US, Inc.
+ * @package php-cloudfiles-http
+ */
+
+/**
+ */
+require_once("cloudfiles_exceptions.php");
+
+define("PHP_CF_VERSION", "1.7.10");
+define("USER_AGENT", sprintf("PHP-CloudFiles/%s", PHP_CF_VERSION));
+define("MAX_HEADER_NAME_LEN", 128);
+define("MAX_HEADER_VALUE_LEN", 256);
+define("ACCOUNT_CONTAINER_COUNT", "X-Account-Container-Count");
+define("ACCOUNT_BYTES_USED", "X-Account-Bytes-Used");
+define("CONTAINER_OBJ_COUNT", "X-Container-Object-Count");
+define("CONTAINER_BYTES_USED", "X-Container-Bytes-Used");
+define("MANIFEST_HEADER", "X-Object-Manifest");
+define("METADATA_HEADER_PREFIX", "X-Object-Meta-");
+define("CONTENT_HEADER_PREFIX", "Content-");
+define("ACCESS_CONTROL_HEADER_PREFIX", "Access-Control-");
+define("ORIGIN_HEADER", "Origin");
+define("CDN_URI", "X-CDN-URI");
+define("CDN_SSL_URI", "X-CDN-SSL-URI");
+define("CDN_STREAMING_URI", "X-CDN-Streaming-URI");
+define("CDN_ENABLED", "X-CDN-Enabled");
+define("CDN_LOG_RETENTION", "X-Log-Retention");
+define("CDN_ACL_USER_AGENT", "X-User-Agent-ACL");
+define("CDN_ACL_REFERRER", "X-Referrer-ACL");
+define("CDN_TTL", "X-TTL");
+define("CDNM_URL", "X-CDN-Management-Url");
+define("STORAGE_URL", "X-Storage-Url");
+define("AUTH_TOKEN", "X-Auth-Token");
+define("AUTH_USER_HEADER", "X-Auth-User");
+define("AUTH_KEY_HEADER", "X-Auth-Key");
+define("AUTH_USER_HEADER_LEGACY", "X-Storage-User");
+define("AUTH_KEY_HEADER_LEGACY", "X-Storage-Pass");
+define("AUTH_TOKEN_LEGACY", "X-Storage-Token");
+define("CDN_EMAIL", "X-Purge-Email");
+define("DESTINATION", "Destination");
+define("ETAG_HEADER", "ETag");
+define("LAST_MODIFIED_HEADER", "Last-Modified");
+define("CONTENT_TYPE_HEADER", "Content-Type");
+define("CONTENT_LENGTH_HEADER", "Content-Length");
+define("USER_AGENT_HEADER", "User-Agent");
+
+/**
+ * HTTP/cURL wrapper for Cloud Files
+ *
+ * This class should not be used directly.  It's only purpose is to abstract
+ * out the HTTP communication from the main API.
+ *
+ * @package php-cloudfiles-http
+ */
+class CF_Http
+{
+    private $error_str;
+    private $dbug;
+    private $cabundle_path;
+    private $api_version;
+
+    # Authentication instance variables
+    #
+    private $storage_url;
+    private $cdnm_url;
+    private $auth_token;
+
+    # Request/response variables
+    #
+    private $response_status;
+    private $response_reason;
+    private $connections;
+
+    # Variables used for content/header callbacks
+    #
+    private $_user_read_progress_callback_func;
+    private $_user_write_progress_callback_func;
+    private $_write_callback_type;
+    private $_text_list;
+    private $_account_container_count;
+    private $_account_bytes_used;
+    private $_container_object_count;
+    private $_container_bytes_used;
+    private $_obj_etag;
+    private $_obj_last_modified;
+    private $_obj_content_type;
+    private $_obj_content_length;
+    private $_obj_metadata;
+    private $_obj_headers;
+    private $_obj_manifest;
+    private $_obj_write_resource;
+    private $_obj_write_string;
+    private $_cdn_enabled;
+    private $_cdn_ssl_uri;
+    private $_cdn_streaming_uri;
+    private $_cdn_uri;
+    private $_cdn_ttl;
+    private $_cdn_log_retention;
+    private $_cdn_acl_user_agent;
+    private $_cdn_acl_referrer;
+
+    function __construct($api_version)
+    {
+        $this->dbug = False;
+        $this->cabundle_path = NULL;
+        $this->api_version = $api_version;
+        $this->error_str = NULL;
+
+        $this->storage_url = NULL;
+        $this->cdnm_url = NULL;
+        $this->auth_token = NULL;
+
+        $this->response_status = NULL;
+        $this->response_reason = NULL;
+
+        # Curl connections array - since there is no way to "re-set" the
+        # connection paramaters for a cURL handle, we keep an array of
+        # the unique use-cases and funnel all of those same type
+        # requests through the appropriate curl connection.
+        #
+        $this->connections = array(
+            "GET_CALL"  => NULL, # GET objects/containers/lists
+            "PUT_OBJ"   => NULL, # PUT object
+            "HEAD"      => NULL, # HEAD requests
+            "PUT_CONT"  => NULL, # PUT container
+            "DEL_POST"  => NULL, # DELETE containers/objects, POST objects
+            "COPY"      => null, # COPY objects
+        );
+
+        $this->_user_read_progress_callback_func = NULL;
+        $this->_user_write_progress_callback_func = NULL;
+        $this->_write_callback_type = NULL;
+        $this->_text_list = array();
+	$this->_return_list = NULL;
+        $this->_account_container_count = 0;
+        $this->_account_bytes_used = 0;
+        $this->_container_object_count = 0;
+        $this->_container_bytes_used = 0;
+        $this->_obj_write_resource = NULL;
+        $this->_obj_write_string = "";
+        $this->_obj_etag = NULL;
+        $this->_obj_last_modified = NULL;
+        $this->_obj_content_type = NULL;
+        $this->_obj_content_length = NULL;
+        $this->_obj_metadata = array();
+        $this->_obj_manifest = NULL;
+        $this->_obj_headers = NULL;
+        $this->_cdn_enabled = NULL;
+        $this->_cdn_ssl_uri = NULL;
+        $this->_cdn_streaming_uri = NULL;
+        $this->_cdn_uri = NULL;
+        $this->_cdn_ttl = NULL;
+        $this->_cdn_log_retention = NULL;
+        $this->_cdn_acl_user_agent = NULL;
+        $this->_cdn_acl_referrer = NULL;
+
+        # The OS list with a PHP without an updated CA File for CURL to
+        # connect to SSL Websites. It is the first 3 letters of the PHP_OS
+        # variable.
+        $OS_CAFILE_NONUPDATED=array(
+            "win","dar"
+        ); 
+
+        if (in_array((strtolower (substr(PHP_OS, 0,3))), $OS_CAFILE_NONUPDATED))
+            $this->ssl_use_cabundle();
+        
+    }
+
+    function ssl_use_cabundle($path=NULL)
+    {
+        if ($path) {
+            $this->cabundle_path = $path;
+        } else {
+            $this->cabundle_path = dirname(__FILE__) . "/share/cacert.pem";
+        }
+        if (!file_exists($this->cabundle_path)) {
+            throw new IOException("Could not use CA bundle: "
+                . $this->cabundle_path);
+        }
+        return;
+    }
+
+    # Uses separate cURL connection to authenticate
+    #
+    function authenticate($user, $pass, $acct=NULL, $host=NULL)
+    {
+        $path = array();
+        if (isset($acct)){
+            $headers = array(
+                sprintf("%s: %s", AUTH_USER_HEADER_LEGACY, $user),
+                sprintf("%s: %s", AUTH_KEY_HEADER_LEGACY, $pass),
+                );
+            $path[] = $host;
+            $path[] = rawurlencode(sprintf("v%d",$this->api_version));
+            $path[] = rawurlencode($acct);
+        } else {
+            $headers = array(
+                sprintf("%s: %s", AUTH_USER_HEADER, $user),
+                sprintf("%s: %s", AUTH_KEY_HEADER, $pass),
+                );
+	    $path[] = $host;
+        }
+	$path[] = "v1.0";
+        $url = implode("/", $path);
+
+        $curl_ch = curl_init();
+        if (!is_null($this->cabundle_path)) {
+            curl_setopt($curl_ch, CURLOPT_SSL_VERIFYPEER, True);
+            curl_setopt($curl_ch, CURLOPT_CAINFO, $this->cabundle_path);
+        }
+        curl_setopt($curl_ch, CURLOPT_VERBOSE, $this->dbug);
+        curl_setopt($curl_ch, CURLOPT_FOLLOWLOCATION, 1);
+        curl_setopt($curl_ch, CURLOPT_MAXREDIRS, 4);
+        curl_setopt($curl_ch, CURLOPT_HEADER, 0);
+        curl_setopt($curl_ch, CURLOPT_HTTPHEADER, $headers);
+        curl_setopt($curl_ch, CURLOPT_USERAGENT, USER_AGENT);
+        curl_setopt($curl_ch, CURLOPT_RETURNTRANSFER, TRUE);
+        curl_setopt($curl_ch, CURLOPT_HEADERFUNCTION,array(&$this,'_auth_hdr_cb'));
+        curl_setopt($curl_ch, CURLOPT_CONNECTTIMEOUT, 10);
+        curl_setopt($curl_ch, CURLOPT_URL, $url);
+        curl_exec($curl_ch);
+        curl_close($curl_ch);
+
+        return array($this->response_status, $this->response_reason,
+            $this->storage_url, $this->cdnm_url, $this->auth_token);
+    }
+
+    # (CDN) GET /v1/Account
+    #
+    function list_cdn_containers($enabled_only)
+    {
+        $conn_type = "GET_CALL";
+        $url_path = $this->_make_path("CDN");
+
+        $this->_write_callback_type = "TEXT_LIST";
+        if ($enabled_only)
+        {
+            $return_code = $this->_send_request($conn_type, $url_path . 
+            '/?enabled_only=true');
+        }
+        else
+        {
+            $return_code = $this->_send_request($conn_type, $url_path);
+        }
+        if (!$return_code) {
+            $this->error_str .= ": Failed to obtain valid HTTP response.";
+            return array(0,$this->error_str,array());
+        }
+        if ($return_code == 401) {
+            return array($return_code,"Unauthorized",array());
+        }
+        if ($return_code == 404) {
+            return array($return_code,"Account not found.",array());
+        }
+        if ($return_code == 204) {
+            return array($return_code,"Account has no CDN enabled Containers.",
+                array());
+        }
+        if ($return_code == 200) {
+	    $this->create_array();
+            return array($return_code,$this->response_reason,$this->_text_list);
+        }
+        $this->error_str = "Unexpected HTTP response: ".$this->response_reason;
+        return array($return_code,$this->error_str,array());
+    }
+
+    # (CDN) DELETE /v1/Account/Container or /v1/Account/Container/Object
+    #
+    function purge_from_cdn($path, $email=null)
+    {
+        if(!$path)
+            throw new SyntaxException("Path not set");
+        $url_path = $this->_make_path("CDN", NULL, $path);
+        if($email)
+        {
+            $hdrs = array(CDN_EMAIL => $email);
+            $return_code = $this->_send_request("DEL_POST",$url_path,$hdrs,"DELETE");
+        }
+        else
+            $return_code = $this->_send_request("DEL_POST",$url_path,null,"DELETE");
+        return $return_code;
+    }
+
+    # (CDN) POST /v1/Account/Container
+    function update_cdn_container($container_name, $ttl=86400, $cdn_log_retention=False,
+                                  $cdn_acl_user_agent="", $cdn_acl_referrer)
+    {
+        if ($container_name == "")
+            throw new SyntaxException("Container name not set.");
+
+        if ($container_name != "0" and !isset($container_name))
+            throw new SyntaxException("Container name not set.");
+
+        $url_path = $this->_make_path("CDN", $container_name);
+        $hdrs = array(
+            CDN_ENABLED => "True",
+            CDN_TTL => $ttl,
+            CDN_LOG_RETENTION => $cdn_log_retention ?  "True" : "False",
+            CDN_ACL_USER_AGENT => $cdn_acl_user_agent,
+            CDN_ACL_REFERRER => $cdn_acl_referrer,
+            );
+        $return_code = $this->_send_request("DEL_POST",$url_path,$hdrs,"POST");
+        if ($return_code == 401) {
+            $this->error_str = "Unauthorized";
+            return array($return_code, $this->error_str, NULL);
+        }
+        if ($return_code == 404) {
+            $this->error_str = "Container not found.";
+            return array($return_code, $this->error_str, NULL);
+        }
+        if ($return_code != 202) {
+            $this->error_str="Unexpected HTTP response: ".$this->response_reason;
+            return array($return_code, $this->error_str, NULL);
+        }
+        return array($return_code, "Accepted", $this->_cdn_uri, $this->_cdn_ssl_uri);
+
+    }
+
+    # (CDN) PUT /v1/Account/Container
+    #
+    function add_cdn_container($container_name, $ttl=86400)
+    {
+        if ($container_name == "")
+            throw new SyntaxException("Container name not set.");
+
+        if ($container_name != "0" and !isset($container_name))
+            throw new SyntaxException("Container name not set.");
+        
+        $url_path = $this->_make_path("CDN", $container_name);
+        $hdrs = array(
+            CDN_ENABLED => "True",
+            CDN_TTL => $ttl,
+            );
+        $return_code = $this->_send_request("PUT_CONT", $url_path, $hdrs);
+        if ($return_code == 401) {
+            $this->error_str = "Unauthorized";
+            return array($return_code,$this->response_reason,False);
+        }
+        if (!in_array($return_code, array(201,202))) {
+            $this->error_str="Unexpected HTTP response: ".$this->response_reason;
+            return array($return_code,$this->response_reason,False);
+        }
+        return array($return_code,$this->response_reason,$this->_cdn_uri,
+                     $this->_cdn_ssl_uri);
+    }
+
+    # (CDN) POST /v1/Account/Container
+    #
+    function remove_cdn_container($container_name)
+    {
+        if ($container_name == "")
+            throw new SyntaxException("Container name not set.");
+
+        if ($container_name != "0" and !isset($container_name))
+            throw new SyntaxException("Container name not set.");
+        
+        $url_path = $this->_make_path("CDN", $container_name);
+        $hdrs = array(CDN_ENABLED => "False");
+        $return_code = $this->_send_request("DEL_POST",$url_path,$hdrs,"POST");
+        if ($return_code == 401) {
+            $this->error_str = "Unauthorized";
+            return array($return_code, $this->error_str);
+        }
+        if ($return_code == 404) {
+            $this->error_str = "Container not found.";
+            return array($return_code, $this->error_str);
+        }
+        if ($return_code != 202) {
+            $this->error_str="Unexpected HTTP response: ".$this->response_reason;
+            return array($return_code, $this->error_str);
+        }
+        return array($return_code, "Accepted");
+    }
+
+    # (CDN) HEAD /v1/Account
+    #
+    function head_cdn_container($container_name)
+    {
+        if ($container_name == "")
+            throw new SyntaxException("Container name not set.");
+
+        if ($container_name != "0" and !isset($container_name))
+            throw new SyntaxException("Container name not set.");
+        
+        $conn_type = "HEAD";
+        $url_path = $this->_make_path("CDN", $container_name);
+        $return_code = $this->_send_request($conn_type, $url_path, NULL, "GET", True);
+
+        if (!$return_code) {
+            $this->error_str .= ": Failed to obtain valid HTTP response.";
+            return array(0,$this->error_str,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL);
+        }
+        if ($return_code == 401) {
+            return array($return_code,"Unauthorized",NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL);
+        }
+        if ($return_code == 404) {
+            return array($return_code,"Account not found.",NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL);
+        }
+        if ($return_code == 204) {
+            return array($return_code,$this->response_reason,
+                $this->_cdn_enabled, $this->_cdn_ssl_uri,
+                $this->_cdn_streaming_uri,
+                $this->_cdn_uri, $this->_cdn_ttl,
+                $this->_cdn_log_retention,
+                $this->_cdn_acl_user_agent,
+                $this->_cdn_acl_referrer
+                );
+        }
+        return array($return_code,$this->response_reason,
+                     NULL,NULL,NULL,NULL,
+                     $this->_cdn_log_retention,
+                     $this->_cdn_acl_user_agent,
+                     $this->_cdn_acl_referrer,
+                     NULL
+            );
+    }
+
+    # GET /v1/Account
+    #
+    function list_containers($limit=0, $marker=NULL)
+    {
+        $conn_type = "GET_CALL";
+        $url_path = $this->_make_path();
+
+        $limit = intval($limit);
+        $params = array();
+        if ($limit > 0) {
+            $params[] = "limit=$limit";
+        }
+        if ($marker) {
+            $params[] = "marker=".rawurlencode($marker);
+        }
+        if (!empty($params)) {
+            $url_path .= "?" . implode("&", $params);
+        }
+
+        $this->_write_callback_type = "TEXT_LIST";
+        $return_code = $this->_send_request($conn_type, $url_path);
+
+        if (!$return_code) {
+            $this->error_str .= ": Failed to obtain valid HTTP response.";
+            return array(0,$this->error_str,array());
+        }
+        if ($return_code == 204) {
+            return array($return_code, "Account has no containers.", array());
+        }
+        if ($return_code == 404) {
+            $this->error_str = "Invalid account name for authentication token.";
+            return array($return_code,$this->error_str,array());
+        }
+        if ($return_code == 200) {
+	    $this->create_array();
+            return array($return_code, $this->response_reason, $this->_text_list);
+        }
+        $this->error_str = "Unexpected HTTP response: ".$this->response_reason;
+        return array($return_code,$this->error_str,array());
+    }
+
+    # GET /v1/Account?format=json
+    #
+    function list_containers_info($limit=0, $marker=NULL)
+    {
+        $conn_type = "GET_CALL";
+        $url_path = $this->_make_path() . "?format=json";
+
+        $limit = intval($limit);
+        $params = array();
+        if ($limit > 0) {
+            $params[] = "limit=$limit";
+        }
+        if ($marker) {
+            $params[] = "marker=".rawurlencode($marker);
+        }
+        if (!empty($params)) {
+            $url_path .= "&" . implode("&", $params);
+        }
+
+        $this->_write_callback_type = "OBJECT_STRING";
+        $return_code = $this->_send_request($conn_type, $url_path);
+
+        if (!$return_code) {
+            $this->error_str .= ": Failed to obtain valid HTTP response.";
+            return array(0,$this->error_str,array());
+        }
+        if ($return_code == 204) {
+            return array($return_code, "Account has no containers.", array());
+        }
+        if ($return_code == 404) {
+            $this->error_str = "Invalid account name for authentication token.";
+            return array($return_code,$this->error_str,array());
+        }
+        if ($return_code == 200) {
+            $json_body = json_decode($this->_obj_write_string, True);
+            return array($return_code, $this->response_reason, $json_body);
+        }
+        $this->error_str = "Unexpected HTTP response: ".$this->response_reason;
+        return array($return_code,$this->error_str,array());
+    }
+
+    # HEAD /v1/Account
+    #
+    function head_account()
+    {
+        $conn_type = "HEAD";
+
+        $url_path = $this->_make_path();
+        $return_code = $this->_send_request($conn_type,$url_path);
+
+        if (!$return_code) {
+            $this->error_str .= ": Failed to obtain valid HTTP response.";
+            return array(0,$this->error_str,0,0);
+        }
+        if ($return_code == 404) {
+            return array($return_code,"Account not found.",0,0);
+        }
+        if ($return_code == 204) {
+            return array($return_code,$this->response_reason,
+                $this->_account_container_count, $this->_account_bytes_used);
+        }
+        return array($return_code,$this->response_reason,0,0);
+    }
+
+    # PUT /v1/Account/Container
+    #
+    function create_container($container_name)
+    {
+        if ($container_name == "")
+            throw new SyntaxException("Container name not set.");
+
+        if ($container_name != "0" and !isset($container_name))
+            throw new SyntaxException("Container name not set.");
+
+        $url_path = $this->_make_path("STORAGE", $container_name);
+        $return_code = $this->_send_request("PUT_CONT",$url_path);
+
+        if (!$return_code) {
+            $this->error_str .= ": Failed to obtain valid HTTP response.";
+            return False;
+        }
+        return $return_code;
+    }
+
+    # DELETE /v1/Account/Container
+    #
+    function delete_container($container_name)
+    {
+        if ($container_name == "")
+            throw new SyntaxException("Container name not set.");
+
+        if ($container_name != "0" and !isset($container_name))
+            throw new SyntaxException("Container name not set.");
+
+        $url_path = $this->_make_path("STORAGE", $container_name);
+        $return_code = $this->_send_request("DEL_POST",$url_path,array(),"DELETE");
+
+        switch ($return_code) {
+        case 204:
+            break;
+        case 0:
+            $this->error_str .= ": Failed to obtain valid HTTP response.";;
+            break;
+        case 409:
+            $this->error_str = "Container must be empty prior to removing it.";
+            break;
+        case 404:
+            $this->error_str = "Specified container did not exist to delete.";
+            break;
+        default:
+            $this->error_str = "Unexpected HTTP return code: $return_code.";
+        }
+        return $return_code;
+    }
+
+    # GET /v1/Account/Container
+    #
+    function list_objects($cname,$limit=0,$marker=NULL,$prefix=NULL,$path=NULL)
+    {
+        if (!$cname) {
+            $this->error_str = "Container name not set.";
+            return array(0, $this->error_str, array());
+        }
+
+        $url_path = $this->_make_path("STORAGE", $cname);
+
+        $limit = intval($limit);
+        $params = array();
+        if ($limit > 0) {
+            $params[] = "limit=$limit";
+        }
+        if ($marker) {
+            $params[] = "marker=".rawurlencode($marker);
+        }
+        if ($prefix) {
+            $params[] = "prefix=".rawurlencode($prefix);
+        }
+        if ($path) {
+            $params[] = "path=".rawurlencode($path);
+        }
+        if (!empty($params)) {
+            $url_path .= "?" . implode("&", $params);
+        }
+ 
+        $conn_type = "GET_CALL";
+        $this->_write_callback_type = "TEXT_LIST";
+        $return_code = $this->_send_request($conn_type,$url_path);
+
+        if (!$return_code) {
+            $this->error_str .= ": Failed to obtain valid HTTP response.";
+            return array(0,$this->error_str,array());
+        }
+        if ($return_code == 204) {
+            $this->error_str = "Container has no Objects.";
+            return array($return_code,$this->error_str,array());
+        }
+        if ($return_code == 404) {
+            $this->error_str = "Container has no Objects.";
+            return array($return_code,$this->error_str,array());
+        }
+        if ($return_code == 200) {
+	    $this->create_array();	
+            return array($return_code,$this->response_reason, $this->_text_list);
+        }
+        $this->error_str = "Unexpected HTTP response code: $return_code";
+        return array(0,$this->error_str,array());
+    }
+
+    # GET /v1/Account/Container?format=json
+    #
+    function get_objects($cname,$limit=0,$marker=NULL,$prefix=NULL,$path=NULL)
+    {
+        if (!$cname) {
+            $this->error_str = "Container name not set.";
+            return array(0, $this->error_str, array());
+        }
+
+        $url_path = $this->_make_path("STORAGE", $cname);
+
+        $limit = intval($limit);
+        $params = array();
+        $params[] = "format=json";
+        if ($limit > 0) {
+            $params[] = "limit=$limit";
+        }
+        if ($marker) {
+            $params[] = "marker=".rawurlencode($marker);
+        }
+        if ($prefix) {
+            $params[] = "prefix=".rawurlencode($prefix);
+        }
+        if ($path) {
+            $params[] = "path=".rawurlencode($path);
+        }
+        if (!empty($params)) {
+            $url_path .= "?" . implode("&", $params);
+        }
+ 
+        $conn_type = "GET_CALL";
+        $this->_write_callback_type = "OBJECT_STRING";
+        $return_code = $this->_send_request($conn_type,$url_path);
+
+        if (!$return_code) {
+            $this->error_str .= ": Failed to obtain valid HTTP response.";
+            return array(0,$this->error_str,array());
+        }
+        if ($return_code == 204) {
+            $this->error_str = "Container has no Objects.";
+            return array($return_code,$this->error_str,array());
+        }
+        if ($return_code == 404) {
+            $this->error_str = "Container has no Objects.";
+            return array($return_code,$this->error_str,array());
+        }
+        if ($return_code == 200) {
+            $json_body = json_decode($this->_obj_write_string, True);
+            return array($return_code,$this->response_reason, $json_body);
+        }
+        $this->error_str = "Unexpected HTTP response code: $return_code";
+        return array(0,$this->error_str,array());
+    }
+
+
+    # HEAD /v1/Account/Container
+    #
+    function head_container($container_name)
+    {
+
+        if ($container_name == "") {
+            $this->error_str = "Container name not set.";
+            return False;
+        }
+        
+        if ($container_name != "0" and !isset($container_name)) {
+            $this->error_str = "Container name not set.";
+            return False;
+        }
+    
+        $conn_type = "HEAD";
+
+        $url_path = $this->_make_path("STORAGE", $container_name);
+        $return_code = $this->_send_request($conn_type,$url_path);
+
+        if (!$return_code) {
+            $this->error_str .= ": Failed to obtain valid HTTP response.";
+            return array(0,$this->error_str,0,0);
+        }
+        if ($return_code == 404) {
+            return array($return_code,"Container not found.",0,0);
+        }
+        if ($return_code == 204 || $return_code == 200) {
+            return array($return_code,$this->response_reason,
+                $this->_container_object_count, $this->_container_bytes_used);
+        }
+        return array($return_code,$this->response_reason,0,0);
+    }
+
+    # GET /v1/Account/Container/Object
+    #
+    function get_object_to_string(&$obj, $hdrs=array())
+    {
+        if (!is_object($obj) || get_class($obj) != "CF_Object") {
+            throw new SyntaxException(
+                "Method argument is not a valid CF_Object.");
+        }
+
+        $conn_type = "GET_CALL";
+
+        $url_path = $this->_make_path("STORAGE", $obj->container->name,$obj->name);
+        $this->_write_callback_type = "OBJECT_STRING";
+        $return_code = $this->_send_request($conn_type,$url_path,$hdrs);
+
+        if (!$return_code) {
+            $this->error_str .= ": Failed to obtain valid HTTP response.";
+            return array($return_code0,$this->error_str,NULL);
+        }
+        if ($return_code == 404) {
+            $this->error_str = "Object not found.";
+            return array($return_code0,$this->error_str,NULL);
+        }
+        if (($return_code < 200) || ($return_code > 299
+                && $return_code != 412 && $return_code != 304)) {
+            $this->error_str = "Unexpected HTTP return code: $return_code";
+            return array($return_code,$this->error_str,NULL);
+        }
+        return array($return_code,$this->response_reason, $this->_obj_write_string);
+    }
+
+    # GET /v1/Account/Container/Object
+    #
+    function get_object_to_stream(&$obj, &$resource=NULL, $hdrs=array())
+    {
+        if (!is_object($obj) || get_class($obj) != "CF_Object") {
+            throw new SyntaxException(
+                "Method argument is not a valid CF_Object.");
+        }
+        if (!is_resource($resource)) {
+            throw new SyntaxException(
+                "Resource argument not a valid PHP resource.");
+        }
+
+        $conn_type = "GET_CALL";
+
+        $url_path = $this->_make_path("STORAGE", $obj->container->name,$obj->name);
+        $this->_obj_write_resource = $resource;
+        $this->_write_callback_type = "OBJECT_STREAM";
+        $return_code = $this->_send_request($conn_type,$url_path,$hdrs);
+
+        if (!$return_code) {
+            $this->error_str .= ": Failed to obtain valid HTTP response.";
+            return array($return_code,$this->error_str);
+        }
+        if ($return_code == 404) {
+            $this->error_str = "Object not found.";
+            return array($return_code,$this->error_str);
+        }
+        if (($return_code < 200) || ($return_code > 299
+                && $return_code != 412 && $return_code != 304)) {
+            $this->error_str = "Unexpected HTTP return code: $return_code";
+            return array($return_code,$this->error_str);
+        }
+        return array($return_code,$this->response_reason);
+    }
+
+    # PUT /v1/Account/Container/Object
+    #
+    function put_object(&$obj, &$fp)
+    {
+        if (!is_object($obj) || get_class($obj) != "CF_Object") {
+            throw new SyntaxException(
+                "Method argument is not a valid CF_Object.");
+        }
+        if (!is_resource($fp)) {
+            throw new SyntaxException(
+                "File pointer argument is not a valid resource.");
+        }
+
+        $conn_type = "PUT_OBJ";
+        $url_path = $this->_make_path("STORAGE", $obj->container->name,$obj->name);
+
+        $hdrs = $this->_headers($obj);
+
+        $etag = $obj->getETag();
+        if (isset($etag)) {
+            $hdrs[] = "ETag: " . $etag;
+        }
+        if (!$obj->content_type) {
+            $hdrs[] = "Content-Type: application/octet-stream";
+        } else {
+            $hdrs[] = "Content-Type: " . $obj->content_type;
+        }
+
+        $this->_init($conn_type);
+        curl_setopt($this->connections[$conn_type],
+                CURLOPT_INFILE, $fp);
+        if (!$obj->content_length) {
+            # We don''t know the Content-Length, so assumed "chunked" PUT
+            #
+            curl_setopt($this->connections[$conn_type], CURLOPT_UPLOAD, True);
+            $hdrs[] = 'Transfer-Encoding: chunked';
+        } else {
+            # We know the Content-Length, so use regular transfer
+            #
+            curl_setopt($this->connections[$conn_type],
+                    CURLOPT_INFILESIZE, $obj->content_length);
+        }
+        $return_code = $this->_send_request($conn_type,$url_path,$hdrs);
+
+        if (!$return_code) {
+            $this->error_str .= ": Failed to obtain valid HTTP response.";
+            return array(0,$this->error_str,NULL);
+        }
+        if ($return_code == 412) {
+            $this->error_str = "Missing Content-Type header";
+            return array($return_code,$this->error_str,NULL);
+        }
+        if ($return_code == 422) {
+            $this->error_str = "Derived and computed checksums do not match.";
+            return array($return_code,$this->error_str,NULL);
+        }
+        if ($return_code != 201) {
+            $this->error_str = "Unexpected HTTP return code: $return_code";
+            return array($return_code,$this->error_str,NULL);
+        }
+        return array($return_code,$this->response_reason,$this->_obj_etag);
+    }
+
+    # POST /v1/Account/Container/Object
+    #
+    function update_object(&$obj)
+    {
+        if (!is_object($obj) || get_class($obj) != "CF_Object") {
+            throw new SyntaxException(
+                "Method argument is not a valid CF_Object.");
+        }
+
+        # TODO: The is_array check isn't in sync with the error message
+        if (!$obj->manifest && !(is_array($obj->metadata) || is_array($obj->headers))) {
+            $this->error_str = "Metadata and headers arrays are empty.";
+            return 0;
+        }
+
+        $url_path = $this->_make_path("STORAGE", $obj->container->name,$obj->name);
+
+        $hdrs = $this->_headers($obj);
+        $return_code = $this->_send_request("DEL_POST",$url_path,$hdrs,"POST");
+        switch ($return_code) {
+        case 202:
+            break;
+        case 0:
+            $this->error_str .= ": Failed to obtain valid HTTP response.";
+            $return_code = 0;
+            break;
+        case 404:
+            $this->error_str = "Account, Container, or Object not found.";
+            break;
+        default:
+            $this->error_str = "Unexpected HTTP return code: $return_code";
+            break;
+        }
+        return $return_code;
+    }
+
+    # HEAD /v1/Account/Container/Object
+    #
+    function head_object(&$obj)
+    {
+        if (!is_object($obj) || get_class($obj) != "CF_Object") {
+            throw new SyntaxException(
+                "Method argument is not a valid CF_Object.");
+        }
+
+        $conn_type = "HEAD";
+
+        $url_path = $this->_make_path("STORAGE", $obj->container->name,$obj->name);
+        $return_code = $this->_send_request($conn_type,$url_path);
+
+        if (!$return_code) {
+            $this->error_str .= ": Failed to obtain valid HTTP response.";
+            return array(0, $this->error_str." ".$this->response_reason,
+                NULL, NULL, NULL, NULL, array(), NULL, array());
+        }
+
+        if ($return_code == 404) {
+            return array($return_code, $this->response_reason,
+                NULL, NULL, NULL, NULL, array(), NULL, array());
+        }
+        if ($return_code == 204 || $return_code == 200) {
+            return array($return_code,$this->response_reason,
+                $this->_obj_etag,
+                $this->_obj_last_modified,
+                $this->_obj_content_type,
+                $this->_obj_content_length,
+                $this->_obj_metadata,
+                $this->_obj_manifest,
+                $this->_obj_headers);
+        }
+        $this->error_str = "Unexpected HTTP return code: $return_code";
+        return array($return_code, $this->error_str." ".$this->response_reason,
+                NULL, NULL, NULL, NULL, array(), NULL, array());
+    }
+
+    # COPY /v1/Account/Container/Object
+    #
+    function copy_object($src_obj_name, $dest_obj_name, $container_name_source, $container_name_target, $metadata=NULL, $headers=NULL)
+    {
+        if (!$src_obj_name) {
+            $this->error_str = "Object name not set.";
+            return 0;
+        }
+
+        if ($container_name_source == "") {
+            $this->error_str = "Container name source not set.";
+            return 0;
+        }
+
+        if ($container_name_source != "0" and !isset($container_name_source)) {
+            $this->error_str = "Container name source not set.";
+            return 0;
+        }
+
+        if ($container_name_target == "") {
+            $this->error_str = "Container name target not set.";
+            return 0;
+        }
+
+        if ($container_name_target != "0" and !isset($container_name_target)) {
+            $this->error_str = "Container name target not set.";
+            return 0;
+        }
+
+        $conn_type = "COPY";
+
+        $url_path = $this->_make_path("STORAGE", $container_name_source, rawurlencode($src_obj_name));
+        $destination = rawurlencode($container_name_target."/".$dest_obj_name);
+
+        $hdrs = self::_process_headers($metadata, $headers);
+        $hdrs[DESTINATION] = $destination;
+
+        $return_code = $this->_send_request($conn_type,$url_path,$hdrs,"COPY");
+        switch ($return_code) {
+        case 201:
+            break;
+        case 0:
+            $this->error_str .= ": Failed to obtain valid HTTP response.";
+            $return_code = 0;
+            break;
+        case 404:
+            $this->error_str = "Specified container/object did not exist.";
+            break;
+        default:
+            $this->error_str = "Unexpected HTTP return code: $return_code.";
+        }
+        return $return_code;
+    }
+
+    # DELETE /v1/Account/Container/Object
+    #
+    function delete_object($container_name, $object_name)
+    {
+        if ($container_name == "") {
+            $this->error_str = "Container name not set.";
+            return 0;
+        }
+        
+        if ($container_name != "0" and !isset($container_name)) {
+            $this->error_str = "Container name not set.";
+            return 0;
+        }
+        
+        if (!$object_name) {
+            $this->error_str = "Object name not set.";
+            return 0;
+        }
+
+        $url_path = $this->_make_path("STORAGE", $container_name,$object_name);
+        $return_code = $this->_send_request("DEL_POST",$url_path,NULL,"DELETE");
+        switch ($return_code) {
+        case 204:
+            break;
+        case 0:
+            $this->error_str .= ": Failed to obtain valid HTTP response.";
+            $return_code = 0;
+            break;
+        case 404:
+            $this->error_str = "Specified container did not exist to delete.";
+            break;
+        default:
+            $this->error_str = "Unexpected HTTP return code: $return_code.";
+        }
+        return $return_code;
+    }
+
+    function get_error()
+    {
+        return $this->error_str;
+    }
+
+    function setDebug($bool)
+    {
+        $this->dbug = $bool;
+        foreach ($this->connections as $k => $v) {
+            if (!is_null($v)) {
+                curl_setopt($this->connections[$k], CURLOPT_VERBOSE, $this->dbug);
+            }
+        }
+    }
+
+    function getCDNMUrl()
+    {
+        return $this->cdnm_url;
+    }
+
+    function getStorageUrl()
+    {
+        return $this->storage_url;
+    }
+
+    function getAuthToken()
+    {
+        return $this->auth_token;
+    }
+
+    function setCFAuth($cfs_auth, $servicenet=False)
+    {
+        if ($servicenet) {
+            $this->storage_url = "https://snet-" . substr($cfs_auth->storage_url, 8);
+        } else {
+            $this->storage_url = $cfs_auth->storage_url;
+        }
+        $this->auth_token = $cfs_auth->auth_token;
+        $this->cdnm_url = $cfs_auth->cdnm_url;
+    }
+
+    function setReadProgressFunc($func_name)
+    {
+        $this->_user_read_progress_callback_func = $func_name;
+    }
+
+    function setWriteProgressFunc($func_name)
+    {
+        $this->_user_write_progress_callback_func = $func_name;
+    }
+
+    private function _header_cb($ch, $header)
+    {
+        $header_len = strlen($header);
+
+        if (preg_match("/^(HTTP\/1\.[01]) (\d{3}) (.*)/", $header, $matches)) {
+            $this->response_status = $matches[2];
+            $this->response_reason = $matches[3];
+            return $header_len;
+        }
+
+        if (strpos($header, ":") === False)
+            return $header_len;
+        list($name, $value) = explode(":", $header, 2);
+        $value = trim($value);
+
+        switch (strtolower($name)) {
+        case strtolower(CDN_ENABLED):
+            $this->_cdn_enabled = strtolower($value) == "true";
+            break;
+        case strtolower(CDN_URI):
+            $this->_cdn_uri = $value;
+            break;
+        case strtolower(CDN_SSL_URI):
+            $this->_cdn_ssl_uri = $value;
+            break;
+        case strtolower(CDN_STREAMING_URI):
+            $this->_cdn_streaming_uri = $value;
+            break;
+        case strtolower(CDN_TTL):
+            $this->_cdn_ttl = $value;
+            break;
+        case strtolower(MANIFEST_HEADER):
+            $this->_obj_manifest = $value;
+            break;
+        case strtolower(CDN_LOG_RETENTION):
+            $this->_cdn_log_retention = strtolower($value) == "true";
+            break;
+        case strtolower(CDN_ACL_USER_AGENT):
+            $this->_cdn_acl_user_agent = $value;
+            break;
+        case strtolower(CDN_ACL_REFERRER):
+            $this->_cdn_acl_referrer = $value;
+            break;
+        case strtolower(ACCOUNT_CONTAINER_COUNT):
+            $this->_account_container_count = (float)$value+0;
+            break;
+        case strtolower(ACCOUNT_BYTES_USED):
+            $this->_account_bytes_used = (float)$value+0;
+            break;
+        case strtolower(CONTAINER_OBJ_COUNT):
+            $this->_container_object_count = (float)$value+0;
+            break;
+        case strtolower(CONTAINER_BYTES_USED):
+            $this->_container_bytes_used = (float)$value+0;
+            break;
+        case strtolower(ETAG_HEADER):
+            $this->_obj_etag = $value;
+            break;
+        case strtolower(LAST_MODIFIED_HEADER):
+            $this->_obj_last_modified = $value;
+            break;
+        case strtolower(CONTENT_TYPE_HEADER):
+            $this->_obj_content_type = $value;
+            break;
+        case strtolower(CONTENT_LENGTH_HEADER):
+            $this->_obj_content_length = (float)$value+0;
+            break;
+        case strtolower(ORIGIN_HEADER):
+            $this->_obj_headers[ORIGIN_HEADER] = $value;
+            break;
+        default:
+            if (strncasecmp($name, METADATA_HEADER_PREFIX, strlen(METADATA_HEADER_PREFIX)) == 0) {
+                $name = substr($name, strlen(METADATA_HEADER_PREFIX));
+                $this->_obj_metadata[$name] = $value;
+            }
+            elseif ((strncasecmp($name, CONTENT_HEADER_PREFIX, strlen(CONTENT_HEADER_PREFIX)) == 0) ||
+                    (strncasecmp($name, ACCESS_CONTROL_HEADER_PREFIX, strlen(ACCESS_CONTROL_HEADER_PREFIX)) == 0)) {
+                $this->_obj_headers[$name] = $value;
+            }
+        }
+        return $header_len;
+    }
+
+    private function _read_cb($ch, $fd, $length)
+    {
+        $data = fread($fd, $length);
+        $len = strlen($data);
+        if (isset($this->_user_write_progress_callback_func)) {
+            call_user_func($this->_user_write_progress_callback_func, $len);
+        }
+        return $data;
+    }
+
+    private function _write_cb($ch, $data)
+    {
+        $dlen = strlen($data);
+        switch ($this->_write_callback_type) {
+        case "TEXT_LIST":
+	     $this->_return_list = $this->_return_list . $data;
+	     //= explode("\n",$data); # keep tab,space
+	     //his->_text_list[] = rtrim($data,"\n\r\x0B"); # keep tab,space
+            break;
+        case "OBJECT_STREAM":
+            fwrite($this->_obj_write_resource, $data, $dlen);
+            break;
+        case "OBJECT_STRING":
+            $this->_obj_write_string .= $data;
+            break;
+        }
+        if (isset($this->_user_read_progress_callback_func)) {
+            call_user_func($this->_user_read_progress_callback_func, $dlen);
+        }
+        return $dlen;
+    }
+
+    private function _auth_hdr_cb($ch, $header)
+    {
+        preg_match("/^HTTP\/1\.[01] (\d{3}) (.*)/", $header, $matches);
+        if (isset($matches[1])) {
+            $this->response_status = $matches[1];
+        }
+        if (isset($matches[2])) {
+            $this->response_reason = $matches[2];
+        }
+        if (stripos($header, STORAGE_URL) === 0) {
+            $this->storage_url = trim(substr($header, strlen(STORAGE_URL)+1));
+        }
+        if (stripos($header, CDNM_URL) === 0) {
+            $this->cdnm_url = trim(substr($header, strlen(CDNM_URL)+1));
+        }
+        if (stripos($header, AUTH_TOKEN) === 0) {
+            $this->auth_token = trim(substr($header, strlen(AUTH_TOKEN)+1));
+        }
+        if (stripos($header, AUTH_TOKEN_LEGACY) === 0) {
+            $this->auth_token = trim(substr($header,strlen(AUTH_TOKEN_LEGACY)+1));
+        }
+        return strlen($header);
+    }
+
+    private function _make_headers($hdrs=NULL)
+    {
+        $new_headers = array();
+        $has_stoken = False;
+        $has_uagent = False;
+        if (is_array($hdrs)) {
+            foreach ($hdrs as $h => $v) {
+                if (is_int($h)) {
+                    list($h, $v) = explode(":", $v, 2);
+                }
+
+                if (strncasecmp($h, AUTH_TOKEN, strlen(AUTH_TOKEN)) === 0) {
+                    $has_stoken = True;
+                }
+                if (strncasecmp($h, USER_AGENT_HEADER, strlen(USER_AGENT_HEADER)) === 0) {
+                    $has_uagent = True;
+                }
+                $new_headers[] = $h . ": " . trim($v);
+            }
+        }
+        if (!$has_stoken) {
+            $new_headers[] = AUTH_TOKEN . ": " . $this->auth_token;
+        }
+        if (!$has_uagent) {
+            $new_headers[] = USER_AGENT_HEADER . ": " . USER_AGENT;
+        }
+        return $new_headers;
+    }
+
+    private function _init($conn_type, $force_new=False)
+    {
+        if (!array_key_exists($conn_type, $this->connections)) {
+            $this->error_str = "Invalid CURL_XXX connection type";
+            return False;
+        }
+
+        if (is_null($this->connections[$conn_type]) || $force_new) {
+            $ch = curl_init();
+        } else {
+            return;
+        }
+
+        if ($this->dbug) { curl_setopt($ch, CURLOPT_VERBOSE, 1); }
+
+        if (!is_null($this->cabundle_path)) {
+            curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, True);
+            curl_setopt($ch, CURLOPT_CAINFO, $this->cabundle_path);
+        }
+	curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, True);
+        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
+        curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
+        curl_setopt($ch, CURLOPT_MAXREDIRS, 4);
+        curl_setopt($ch, CURLOPT_HEADER, 0);
+        curl_setopt($ch, CURLOPT_HEADERFUNCTION, array(&$this, '_header_cb'));
+
+        if ($conn_type == "GET_CALL") {
+            curl_setopt($ch, CURLOPT_WRITEFUNCTION, array(&$this, '_write_cb'));
+        }
+
+        if ($conn_type == "PUT_OBJ") {
+            curl_setopt($ch, CURLOPT_PUT, 1);
+            curl_setopt($ch, CURLOPT_READFUNCTION, array(&$this, '_read_cb'));
+	    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
+        }
+        if ($conn_type == "HEAD") {
+            curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "HEAD");
+            curl_setopt($ch, CURLOPT_NOBODY, 1);
+        }
+        if ($conn_type == "PUT_CONT") {
+            curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "PUT");
+            curl_setopt($ch, CURLOPT_INFILESIZE, 0);
+	    curl_setopt($ch, CURLOPT_NOBODY, 1);
+        }
+        if ($conn_type == "DEL_POST") {
+        	curl_setopt($ch, CURLOPT_NOBODY, 1);
+	}
+        if ($conn_type == "COPY") {
+            curl_setopt($ch, CURLOPT_NOBODY, 1);
+        }
+        $this->connections[$conn_type] = $ch;
+        return;
+    }
+
+    private function _reset_callback_vars()
+    {
+        $this->_text_list = array();
+	$this->_return_list = NULL;
+        $this->_account_container_count = 0;
+        $this->_account_bytes_used = 0;
+        $this->_container_object_count = 0;
+        $this->_container_bytes_used = 0;
+        $this->_obj_etag = NULL;
+        $this->_obj_last_modified = NULL;
+        $this->_obj_content_type = NULL;
+        $this->_obj_content_length = NULL;
+        $this->_obj_metadata = array();
+        $this->_obj_manifest = NULL;
+        $this->_obj_headers = NULL;
+        $this->_obj_write_string = "";
+        $this->_cdn_streaming_uri = NULL;
+        $this->_cdn_enabled = NULL;
+        $this->_cdn_ssl_uri = NULL;
+        $this->_cdn_uri = NULL;
+        $this->_cdn_ttl = NULL;
+        $this->response_status = 0;
+        $this->response_reason = "";
+    }
+
+    private function _make_path($t="STORAGE",$c=NULL,$o=NULL)
+    {
+        $path = array();
+        switch ($t) {
+        case "STORAGE":
+            $path[] = $this->storage_url; break;
+        case "CDN":
+            $path[] = $this->cdnm_url; break;
+        }
+        if ($c == "0")
+            $path[] = rawurlencode($c);
+
+        if ($c) {
+            $path[] = rawurlencode($c);
+        }
+        if ($o) {
+            # mimic Python''s urllib.quote() feature of a "safe" '/' character
+            #
+            $path[] = str_replace("%2F","/",rawurlencode($o));
+        }
+        return implode("/",$path);
+    }
+
+    private function _headers(&$obj)
+    {
+        $hdrs = self::_process_headers($obj->metadata, $obj->headers);
+        if ($obj->manifest)
+            $hdrs[MANIFEST_HEADER] = $obj->manifest;
+
+        return $hdrs;
+    }
+
+    private function _process_headers($metadata=null, $headers=null)
+    {
+        $rules = array(
+            array(
+                'prefix' => METADATA_HEADER_PREFIX,
+            ),
+            array(
+                'prefix' => '',
+                'filter' => array( # key order is important, first match decides
+                    CONTENT_TYPE_HEADER          => false,
+                    CONTENT_LENGTH_HEADER        => false,
+                    CONTENT_HEADER_PREFIX        => true,
+                    ACCESS_CONTROL_HEADER_PREFIX => true,
+                    ORIGIN_HEADER                => true,
+                ),
+            ),
+        );
+
+        $hdrs = array();
+        $argc = func_num_args();
+        $argv = func_get_args();
+        for ($argi = 0; $argi < $argc; $argi++) {
+            if(!is_array($argv[$argi])) continue;
+
+            $rule = $rules[$argi];
+            foreach ($argv[$argi] as $k => $v) {
+                $k = trim($k);
+                $v = trim($v);
+                if (strpos($k, ":") !== False) throw new SyntaxException(
+                    "Header names cannot contain a ':' character.");
+
+                if (array_key_exists('filter', $rule)) {
+                    $result = null;
+                    foreach ($rule['filter'] as $p => $f) {
+                        if (strncasecmp($k, $p, strlen($p)) == 0) {
+                            $result = $f;
+                            break;
+                        }
+                    }
+                    if (!$result) throw new SyntaxException(sprintf(
+                        "Header name %s is not allowed", $k));
+                }
+
+                $k = $rule['prefix'] . $k;
+                if (strlen($k) > MAX_HEADER_NAME_LEN || strlen($v) > MAX_HEADER_VALUE_LEN)
+                    throw new SyntaxException(sprintf(
+                        "Header %s exceeds maximum length: %d/%d",
+                            $k, strlen($k), strlen($v)));
+
+                $hdrs[$k] = $v;
+            }
+        }
+
+        return $hdrs;
+    }
+    
+    private function _send_request($conn_type, $url_path, $hdrs=NULL, $method="GET", $force_new=False)
+    {
+        $this->_init($conn_type, $force_new);
+        $this->_reset_callback_vars();
+        $headers = $this->_make_headers($hdrs);
+
+        if (gettype($this->connections[$conn_type]) == "unknown type")
+            throw new ConnectionNotOpenException (
+                "Connection is not open."
+                );
+        
+        switch ($method) {
+        case "COPY":
+            curl_setopt($this->connections[$conn_type],
+                CURLOPT_CUSTOMREQUEST, "COPY");
+            break;
+        case "DELETE":
+            curl_setopt($this->connections[$conn_type],
+                CURLOPT_CUSTOMREQUEST, "DELETE");
+            break;
+        case "POST":
+            curl_setopt($this->connections[$conn_type],
+                CURLOPT_CUSTOMREQUEST, "POST");
+        default:
+            break;
+        }        
+
+        curl_setopt($this->connections[$conn_type],
+                    CURLOPT_HTTPHEADER, $headers);
+
+        curl_setopt($this->connections[$conn_type],
+            CURLOPT_URL, $url_path);
+
+        if (!curl_exec($this->connections[$conn_type]) && curl_errno($this->connections[$conn_type]) !== 0) {
+            $this->error_str = "(curl error: "
+                . curl_errno($this->connections[$conn_type]) . ") ";
+            $this->error_str .= curl_error($this->connections[$conn_type]);
+            return False;
+        }
+        return curl_getinfo($this->connections[$conn_type], CURLINFO_HTTP_CODE);
+    }
+    
+    function close()
+    {
+        foreach ($this->connections as $cnx) {
+            if (isset($cnx)) {
+                curl_close($cnx);
+                $this->connections[$cnx] = NULL;
+            }
+        }
+    }
+    private function create_array()
+    {
+	$this->_text_list = explode("\n",rtrim($this->_return_list,"\n\x0B"));
+	return True;
+    }
+
+}
+
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * c-hanging-comment-ender-p: nil
+ * End:
+ */
+?>
diff --git a/3rdparty/simpletest/HELP_MY_TESTS_DONT_WORK_ANYMORE b/3rdparty/simpletest/HELP_MY_TESTS_DONT_WORK_ANYMORE
old mode 100755
new mode 100644
diff --git a/3rdparty/simpletest/LICENSE b/3rdparty/simpletest/LICENSE
old mode 100755
new mode 100644
diff --git a/3rdparty/simpletest/README b/3rdparty/simpletest/README
old mode 100755
new mode 100644
diff --git a/3rdparty/simpletest/VERSION b/3rdparty/simpletest/VERSION
old mode 100755
new mode 100644
diff --git a/3rdparty/simpletest/arguments.php b/3rdparty/simpletest/arguments.php
old mode 100755
new mode 100644
diff --git a/3rdparty/simpletest/compatibility.php b/3rdparty/simpletest/compatibility.php
old mode 100755
new mode 100644
diff --git a/3rdparty/simpletest/detached.php b/3rdparty/simpletest/detached.php
old mode 100755
new mode 100644
diff --git a/3rdparty/simpletest/docs/en/docs.css b/3rdparty/simpletest/docs/en/docs.css
old mode 100755
new mode 100644
diff --git a/3rdparty/simpletest/docs/fr/docs.css b/3rdparty/simpletest/docs/fr/docs.css
old mode 100755
new mode 100644
diff --git a/3rdparty/simpletest/dumper.php b/3rdparty/simpletest/dumper.php
old mode 100755
new mode 100644
diff --git a/3rdparty/simpletest/exceptions.php b/3rdparty/simpletest/exceptions.php
old mode 100755
new mode 100644
diff --git a/3rdparty/simpletest/expectation.php b/3rdparty/simpletest/expectation.php
old mode 100755
new mode 100644
diff --git a/3rdparty/simpletest/extensions/pear_test_case.php b/3rdparty/simpletest/extensions/pear_test_case.php
old mode 100755
new mode 100644
diff --git a/3rdparty/simpletest/extensions/testdox.php b/3rdparty/simpletest/extensions/testdox.php
old mode 100755
new mode 100644
diff --git a/3rdparty/simpletest/extensions/testdox/test.php b/3rdparty/simpletest/extensions/testdox/test.php
old mode 100755
new mode 100644
diff --git a/3rdparty/simpletest/frames.php b/3rdparty/simpletest/frames.php
old mode 100755
new mode 100644
diff --git a/3rdparty/simpletest/invoker.php b/3rdparty/simpletest/invoker.php
old mode 100755
new mode 100644
diff --git a/3rdparty/simpletest/mock_objects.php b/3rdparty/simpletest/mock_objects.php
old mode 100755
new mode 100644
diff --git a/3rdparty/simpletest/page.php b/3rdparty/simpletest/page.php
old mode 100755
new mode 100644
diff --git a/3rdparty/simpletest/php_parser.php b/3rdparty/simpletest/php_parser.php
old mode 100755
new mode 100644
diff --git a/3rdparty/simpletest/reporter.php b/3rdparty/simpletest/reporter.php
old mode 100755
new mode 100644
diff --git a/3rdparty/simpletest/selector.php b/3rdparty/simpletest/selector.php
old mode 100755
new mode 100644
diff --git a/3rdparty/simpletest/socket.php b/3rdparty/simpletest/socket.php
old mode 100755
new mode 100644
diff --git a/3rdparty/simpletest/test/adapter_test.php b/3rdparty/simpletest/test/adapter_test.php
old mode 100755
new mode 100644
diff --git a/3rdparty/simpletest/test/all_tests.php b/3rdparty/simpletest/test/all_tests.php
old mode 100755
new mode 100644
diff --git a/3rdparty/simpletest/test/arguments_test.php b/3rdparty/simpletest/test/arguments_test.php
old mode 100755
new mode 100644
diff --git a/3rdparty/simpletest/test/authentication_test.php b/3rdparty/simpletest/test/authentication_test.php
old mode 100755
new mode 100644
diff --git a/3rdparty/simpletest/test/autorun_test.php b/3rdparty/simpletest/test/autorun_test.php
old mode 100755
new mode 100644
diff --git a/3rdparty/simpletest/test/bad_test_suite.php b/3rdparty/simpletest/test/bad_test_suite.php
old mode 100755
new mode 100644
diff --git a/3rdparty/simpletest/test/browser_test.php b/3rdparty/simpletest/test/browser_test.php
old mode 100755
new mode 100644
diff --git a/3rdparty/simpletest/test/collector_test.php b/3rdparty/simpletest/test/collector_test.php
old mode 100755
new mode 100644
diff --git a/3rdparty/simpletest/test/command_line_test.php b/3rdparty/simpletest/test/command_line_test.php
old mode 100755
new mode 100644
diff --git a/3rdparty/simpletest/test/compatibility_test.php b/3rdparty/simpletest/test/compatibility_test.php
old mode 100755
new mode 100644
diff --git a/3rdparty/simpletest/test/cookies_test.php b/3rdparty/simpletest/test/cookies_test.php
old mode 100755
new mode 100644
diff --git a/3rdparty/simpletest/test/detached_test.php b/3rdparty/simpletest/test/detached_test.php
old mode 100755
new mode 100644
diff --git a/3rdparty/simpletest/test/dumper_test.php b/3rdparty/simpletest/test/dumper_test.php
old mode 100755
new mode 100644
diff --git a/3rdparty/simpletest/test/eclipse_test.php b/3rdparty/simpletest/test/eclipse_test.php
old mode 100755
new mode 100644
diff --git a/3rdparty/simpletest/test/encoding_test.php b/3rdparty/simpletest/test/encoding_test.php
old mode 100755
new mode 100644
diff --git a/3rdparty/simpletest/test/errors_test.php b/3rdparty/simpletest/test/errors_test.php
old mode 100755
new mode 100644
diff --git a/3rdparty/simpletest/test/exceptions_test.php b/3rdparty/simpletest/test/exceptions_test.php
old mode 100755
new mode 100644
diff --git a/3rdparty/simpletest/test/expectation_test.php b/3rdparty/simpletest/test/expectation_test.php
old mode 100755
new mode 100644
diff --git a/3rdparty/simpletest/test/form_test.php b/3rdparty/simpletest/test/form_test.php
old mode 100755
new mode 100644
diff --git a/3rdparty/simpletest/test/frames_test.php b/3rdparty/simpletest/test/frames_test.php
old mode 100755
new mode 100644
diff --git a/3rdparty/simpletest/test/http_test.php b/3rdparty/simpletest/test/http_test.php
old mode 100755
new mode 100644
diff --git a/3rdparty/simpletest/test/interfaces_test.php b/3rdparty/simpletest/test/interfaces_test.php
old mode 100755
new mode 100644
diff --git a/3rdparty/simpletest/test/interfaces_test_php5_1.php b/3rdparty/simpletest/test/interfaces_test_php5_1.php
old mode 100755
new mode 100644
diff --git a/3rdparty/simpletest/test/live_test.php b/3rdparty/simpletest/test/live_test.php
old mode 100755
new mode 100644
diff --git a/3rdparty/simpletest/test/mock_objects_test.php b/3rdparty/simpletest/test/mock_objects_test.php
old mode 100755
new mode 100644
diff --git a/3rdparty/simpletest/test/page_test.php b/3rdparty/simpletest/test/page_test.php
old mode 100755
new mode 100644
diff --git a/3rdparty/simpletest/test/parse_error_test.php b/3rdparty/simpletest/test/parse_error_test.php
old mode 100755
new mode 100644
diff --git a/3rdparty/simpletest/test/parsing_test.php b/3rdparty/simpletest/test/parsing_test.php
old mode 100755
new mode 100644
diff --git a/3rdparty/simpletest/test/php_parser_test.php b/3rdparty/simpletest/test/php_parser_test.php
old mode 100755
new mode 100644
diff --git a/3rdparty/simpletest/test/recorder_test.php b/3rdparty/simpletest/test/recorder_test.php
old mode 100755
new mode 100644
diff --git a/3rdparty/simpletest/test/reflection_php5_test.php b/3rdparty/simpletest/test/reflection_php5_test.php
old mode 100755
new mode 100644
diff --git a/3rdparty/simpletest/test/remote_test.php b/3rdparty/simpletest/test/remote_test.php
old mode 100755
new mode 100644
diff --git a/3rdparty/simpletest/test/shell_test.php b/3rdparty/simpletest/test/shell_test.php
old mode 100755
new mode 100644
diff --git a/3rdparty/simpletest/test/shell_tester_test.php b/3rdparty/simpletest/test/shell_tester_test.php
old mode 100755
new mode 100644
diff --git a/3rdparty/simpletest/test/simpletest_test.php b/3rdparty/simpletest/test/simpletest_test.php
old mode 100755
new mode 100644
diff --git a/3rdparty/simpletest/test/site/file.html b/3rdparty/simpletest/test/site/file.html
old mode 100755
new mode 100644
diff --git a/3rdparty/simpletest/test/socket_test.php b/3rdparty/simpletest/test/socket_test.php
old mode 100755
new mode 100644
diff --git a/3rdparty/simpletest/test/support/collector/collectable.1 b/3rdparty/simpletest/test/support/collector/collectable.1
old mode 100755
new mode 100644
diff --git a/3rdparty/simpletest/test/support/collector/collectable.2 b/3rdparty/simpletest/test/support/collector/collectable.2
old mode 100755
new mode 100644
diff --git a/3rdparty/simpletest/test/support/empty_test_file.php b/3rdparty/simpletest/test/support/empty_test_file.php
old mode 100755
new mode 100644
diff --git a/3rdparty/simpletest/test/support/failing_test.php b/3rdparty/simpletest/test/support/failing_test.php
old mode 100755
new mode 100644
diff --git a/3rdparty/simpletest/test/support/latin1_sample b/3rdparty/simpletest/test/support/latin1_sample
old mode 100755
new mode 100644
diff --git a/3rdparty/simpletest/test/support/passing_test.php b/3rdparty/simpletest/test/support/passing_test.php
old mode 100755
new mode 100644
diff --git a/3rdparty/simpletest/test/support/recorder_sample.php b/3rdparty/simpletest/test/support/recorder_sample.php
old mode 100755
new mode 100644
diff --git a/3rdparty/simpletest/test/support/spl_examples.php b/3rdparty/simpletest/test/support/spl_examples.php
old mode 100755
new mode 100644
diff --git a/3rdparty/simpletest/test/support/supplementary_upload_sample.txt b/3rdparty/simpletest/test/support/supplementary_upload_sample.txt
old mode 100755
new mode 100644
diff --git a/3rdparty/simpletest/test/support/test1.php b/3rdparty/simpletest/test/support/test1.php
old mode 100755
new mode 100644
diff --git a/3rdparty/simpletest/test/support/upload_sample.txt b/3rdparty/simpletest/test/support/upload_sample.txt
old mode 100755
new mode 100644
diff --git a/3rdparty/simpletest/test/tag_test.php b/3rdparty/simpletest/test/tag_test.php
old mode 100755
new mode 100644
diff --git a/3rdparty/simpletest/test/test_with_parse_error.php b/3rdparty/simpletest/test/test_with_parse_error.php
old mode 100755
new mode 100644
diff --git a/3rdparty/simpletest/test/unit_tester_test.php b/3rdparty/simpletest/test/unit_tester_test.php
old mode 100755
new mode 100644
diff --git a/3rdparty/simpletest/test/unit_tests.php b/3rdparty/simpletest/test/unit_tests.php
old mode 100755
new mode 100644
diff --git a/3rdparty/simpletest/test/url_test.php b/3rdparty/simpletest/test/url_test.php
old mode 100755
new mode 100644
diff --git a/3rdparty/simpletest/test/user_agent_test.php b/3rdparty/simpletest/test/user_agent_test.php
old mode 100755
new mode 100644
diff --git a/3rdparty/simpletest/test/visual_test.php b/3rdparty/simpletest/test/visual_test.php
old mode 100755
new mode 100644
diff --git a/3rdparty/simpletest/test/web_tester_test.php b/3rdparty/simpletest/test/web_tester_test.php
old mode 100755
new mode 100644
diff --git a/3rdparty/simpletest/test/xml_test.php b/3rdparty/simpletest/test/xml_test.php
old mode 100755
new mode 100644
diff --git a/3rdparty/simpletest/tidy_parser.php b/3rdparty/simpletest/tidy_parser.php
old mode 100755
new mode 100644
diff --git a/3rdparty/simpletest/unit_tester.php b/3rdparty/simpletest/unit_tester.php
old mode 100755
new mode 100644
diff --git a/3rdparty/simpletest/xml.php b/3rdparty/simpletest/xml.php
old mode 100755
new mode 100644
diff --git a/3rdparty/when/When.php b/3rdparty/when/When.php
old mode 100755
new mode 100644
diff --git a/apps/admin_dependencies_chk/appinfo/app.php b/apps/admin_dependencies_chk/appinfo/app.php
old mode 100644
new mode 100755
index e2169b5dd7711e352c788d5bbde144b8421566ac..72d368a085efa3d7b252b206e80300b2071dac31
--- a/apps/admin_dependencies_chk/appinfo/app.php
+++ b/apps/admin_dependencies_chk/appinfo/app.php
@@ -1,9 +1,9 @@
 <?php
-$l=new OC_L10N('admin_dependencies_chk');
+$l=OC_L10N::get('admin_dependencies_chk');
 
-OC_App::register( array( 
+OCP\App::register( array( 
   'order' => 14,
   'id' => 'admin_dependencies_chk',
   'name' => 'Owncloud Install Info' ));
 
-OC_APP::registerAdmin('admin_dependencies_chk','settings');
+OCP\App::registerAdmin('admin_dependencies_chk','settings');
diff --git a/apps/admin_dependencies_chk/appinfo/info.xml b/apps/admin_dependencies_chk/appinfo/info.xml
index a9c1c68c5d4b7ad8fe441d6e51759590088fe68d..d5f8bd3783da51d59f45ae6e0c413d03e82ff2be 100644
--- a/apps/admin_dependencies_chk/appinfo/info.xml
+++ b/apps/admin_dependencies_chk/appinfo/info.xml
@@ -2,7 +2,6 @@
 <info>
 	<id>admin_dependencies_chk</id>
 	<name>Owncloud dependencies info</name>
-	<version>0.01</version>
 	<licence>AGPL</licence>
 	<author>Brice Maron (eMerzh)</author>
 	<require>2</require>
diff --git a/apps/admin_dependencies_chk/appinfo/version b/apps/admin_dependencies_chk/appinfo/version
new file mode 100644
index 0000000000000000000000000000000000000000..d1c6331b3109accd73f01907062e6c174e28200a
--- /dev/null
+++ b/apps/admin_dependencies_chk/appinfo/version
@@ -0,0 +1 @@
+0.01
\ No newline at end of file
diff --git a/apps/admin_dependencies_chk/settings.php b/apps/admin_dependencies_chk/settings.php
old mode 100644
new mode 100755
index ce90dd604ca46d549dbbcab54a2f921e7ed89f81..f4915c3d2fe7c7871c4d8e047a06723796d638f5
--- a/apps/admin_dependencies_chk/settings.php
+++ b/apps/admin_dependencies_chk/settings.php
@@ -20,7 +20,7 @@
  * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
  *
  */
-$l=new OC_L10N('admin_dependencies_chk');
+$l=OC_L10N::get('admin_dependencies_chk');
 $tmpl = new OC_Template( 'admin_dependencies_chk', 'settings');
 
 $modules = array();
@@ -77,14 +77,14 @@ $modules[] =array(
 foreach($modules as $key => $module) {
 	$enabled = false ;
 	foreach($module['modules'] as $app) {
-		if(OC_App::isEnabled($app) || $app=='core'){
+		if(OCP\App::isEnabled($app) || $app=='core'){
 				$enabled = true;
 		}
 	}
 	if($enabled == false) unset($modules[$key]);
 }
 
-OC_UTIL::addStyle('admin_dependencies_chk', 'style');
+OCP\UTIL::addStyle('admin_dependencies_chk', 'style');
 $tmpl->assign( 'items', $modules );
 
 return $tmpl->fetchPage();
diff --git a/apps/admin_migrate/appinfo/app.php b/apps/admin_migrate/appinfo/app.php
old mode 100644
new mode 100755
index e45d3f6a529252b271d54a985da9d71b560018c9..7a12a32856dbdb59f33c379abd6610ab06b134e1
--- a/apps/admin_migrate/appinfo/app.php
+++ b/apps/admin_migrate/appinfo/app.php
@@ -22,12 +22,12 @@
 */
 
 
-OC_APP::registerAdmin('admin_migrate','settings');
+OCP\App::registerAdmin('admin_migrate','settings');
 
 // add settings page to navigation
 $entry = array(
 	'id' => "admin_migrate_settings",
 	'order'=>1,
-	'href' => OC_Helper::linkTo( "admin_migrate", "settings.php" ),
+	'href' => OCP\Util::linkTo( "admin_migrate", "settings.php" ),
 	'name' => 'Export'
 );
diff --git a/apps/admin_migrate/appinfo/info.xml b/apps/admin_migrate/appinfo/info.xml
index 67fc3f9c5a091b5c8a6074b773316a720778da62..51721579002ca10525ff8842f850d1af181ef8dc 100644
--- a/apps/admin_migrate/appinfo/info.xml
+++ b/apps/admin_migrate/appinfo/info.xml
@@ -3,7 +3,6 @@
 	<id>admin_migrate</id>
 	<name>ownCloud Instance Migration</name>
 	<description>Import/Export your owncloud instance</description>
-	<version>0.1</version>
 	<licence>AGPL</licence>
 	<author>Thomas Schmidt and Tom Needham</author>
 	<require>2</require>
diff --git a/apps/admin_migrate/appinfo/version b/apps/admin_migrate/appinfo/version
new file mode 100644
index 0000000000000000000000000000000000000000..ceab6e11ece0bcec917c12e11d350946f085d549
--- /dev/null
+++ b/apps/admin_migrate/appinfo/version
@@ -0,0 +1 @@
+0.1
\ No newline at end of file
diff --git a/apps/admin_migrate/settings.php b/apps/admin_migrate/settings.php
old mode 100644
new mode 100755
index 94bf6052a6b6017a9adbb7b2559b67d2acc2669b..7d3fd0417986c30bcf1a2ebaa0d82c8c272162f4
--- a/apps/admin_migrate/settings.php
+++ b/apps/admin_migrate/settings.php
@@ -22,8 +22,8 @@
  * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
  *
  */
-OC_Util::checkAdminUser();
-OC_Util::checkAppEnabled('admin_migrate');
+OCP\User::checkAdminUser();
+OCP\App::checkAppEnabled('admin_migrate');
 
 // Export?
 if (isset($_POST['admin_export'])) {
diff --git a/apps/admin_migrate/templates/settings.php b/apps/admin_migrate/templates/settings.php
index 91e305074e40e5a23b477f84275ae3df44349acb..f81c9199ecee6d67b9a64e860e75b228f15bfaae 100644
--- a/apps/admin_migrate/templates/settings.php
+++ b/apps/admin_migrate/templates/settings.php
@@ -6,9 +6,9 @@
         </p>
         <h3>What would you like to export?</h3>
         <p>
-        <input type="radio" name="export_type" value="instance" /> ownCloud instance (suitable for import )<br />
-		<input type="radio" name="export_type" value="system" /> ownCloud system files<br />
-		<input type="radio" name="export_type" value="userfiles" /> Just user files<br />
+        <input type="radio" name="export_type" value="instance" style="width:20px;" /> ownCloud instance (suitable for import )<br />
+	<input type="radio" name="export_type" value="system" style="width:20px;" /> ownCloud system files<br />
+	<input type="radio" name="export_type" value="userfiles" style="width:20px;" /> Just user files<br />
         <input type="submit" name="admin_export" value="<?php echo $l->t('Export'); ?>" />
     </fieldset>
 </form>
diff --git a/apps/bookmarks/addBm.php b/apps/bookmarks/addBm.php
old mode 100644
new mode 100755
index 861b677222d2232f5ba7d4f12f49d11363c4b2b1..313489d22fbf822f03162625973945b60c2c7fb6
--- a/apps/bookmarks/addBm.php
+++ b/apps/bookmarks/addBm.php
@@ -21,11 +21,11 @@
 * 
 */
 
-require_once('../../lib/base.php');
+
 
 // Check if we are a user
-OC_Util::checkLoggedIn();
-OC_Util::checkAppEnabled('bookmarks');
+OCP\User::checkLoggedIn();
+OCP\App::checkAppEnabled('bookmarks');
 
 require_once('bookmarksHelper.php');
 addBookmark($_GET['url'], '', 'Read-Later');
diff --git a/apps/bookmarks/ajax/addBookmark.php b/apps/bookmarks/ajax/addBookmark.php
old mode 100644
new mode 100755
index 8cda7f0f060dc4d03495cfe5fe89af405ef646e4..9241dc8ddf6c3f0a22fbf83df8ee178270f5a2a5
--- a/apps/bookmarks/ajax/addBookmark.php
+++ b/apps/bookmarks/ajax/addBookmark.php
@@ -24,12 +24,12 @@
 //no apps or filesystem
 $RUNTIME_NOSETUPFS=true;
 
-require_once('../../../lib/base.php');
+ 
 
 // Check if we are a user
-OC_JSON::checkLoggedIn();
-OC_JSON::checkAppEnabled('bookmarks');
+OCP\JSON::checkLoggedIn();
+OCP\JSON::checkAppEnabled('bookmarks');
 
-require_once('../bookmarksHelper.php');
+require_once(OC::$APPSROOT . '/apps/bookmarks/bookmarksHelper.php');
 $id = addBookmark($_GET['url'], $_GET['title'], $_GET['tags']);
-OC_JSON::success(array('data' => $id));
\ No newline at end of file
+OCP\JSON::success(array('data' => $id));
\ No newline at end of file
diff --git a/apps/bookmarks/ajax/delBookmark.php b/apps/bookmarks/ajax/delBookmark.php
old mode 100644
new mode 100755
index 4aef86e771b4b125b71fe56bc3bc1ef7fe1fc7fd..0b5689811aeebaffd774557a3dbe289e39718c54
--- a/apps/bookmarks/ajax/delBookmark.php
+++ b/apps/bookmarks/ajax/delBookmark.php
@@ -24,39 +24,16 @@
 //no apps or filesystem
 $RUNTIME_NOSETUPFS=true;
 
-require_once('../../../lib/base.php');
+ 
 
 // Check if we are a user
-OC_JSON::checkLoggedIn();
-OC_JSON::checkAppEnabled('bookmarks');
+OCP\JSON::checkLoggedIn();
+OCP\JSON::checkAppEnabled('bookmarks');
 
-$params=array(
-	htmlspecialchars_decode($_GET["url"]),
-	OC_User::getUser()
-	);
+$id = $_GET['id'];
+if (!OC_Bookmarks_Bookmarks::deleteUrl($id)){
+	OC_JSON::error();
+	exit();
+}
 
-$query = OC_DB::prepare("
-	SELECT id FROM *PREFIX*bookmarks 
-	WHERE url LIKE ?
-		AND user_id = ?
-	");
-
-$id = $query->execute($params)->fetchOne();
-
-$query = OC_DB::prepare("
-	DELETE FROM *PREFIX*bookmarks
-	WHERE id = $id
-	");
-	
-$result = $query->execute();
-
-
-$query = OC_DB::prepare("
-	DELETE FROM *PREFIX*bookmarks_tags
-	WHERE bookmark_id = $id
-	");
-	
-$result = $query->execute();
-// var_dump($params);
-
-OC_JSON::success(array('data' => array()));
+OCP\JSON::success();
diff --git a/apps/bookmarks/ajax/editBookmark.php b/apps/bookmarks/ajax/editBookmark.php
old mode 100644
new mode 100755
index 35f30ebcb7a9e7b8fb3d7e8b1d9b413e0271d225..db349af35c13f0d08a45316aa707b1a06e6800f3
--- a/apps/bookmarks/ajax/editBookmark.php
+++ b/apps/bookmarks/ajax/editBookmark.php
@@ -24,13 +24,13 @@
 //no apps or filesystem
 $RUNTIME_NOSETUPFS=true;
 
-require_once('../../../lib/base.php');
+ 
 
 // Check if we are a user
-OC_JSON::checkLoggedIn();
-OC_JSON::checkAppEnabled('bookmarks');
+OCP\JSON::checkLoggedIn();
+OCP\JSON::checkAppEnabled('bookmarks');
 
-$CONFIG_DBTYPE = OC_Config::getValue( "dbtype", "sqlite" );
+$CONFIG_DBTYPE = OCP\Config::getSystemValue( "dbtype", "sqlite" );
 if( $CONFIG_DBTYPE == 'sqlite' or $CONFIG_DBTYPE == 'sqlite3' ){
 	$_ut = "strftime('%s','now')";
 } elseif($CONFIG_DBTYPE == 'pgsql') {
@@ -41,7 +41,7 @@ if( $CONFIG_DBTYPE == 'sqlite' or $CONFIG_DBTYPE == 'sqlite3' ){
 
 $bookmark_id = (int)$_GET["id"];
 
-$query = OC_DB::prepare("
+$query = OCP\DB::prepare("
 	UPDATE *PREFIX*bookmarks
 	SET url = ?, title =?, lastmodified = $_ut
 	WHERE id = $bookmark_id
@@ -54,14 +54,14 @@ $params=array(
 $query->execute($params);
 
 # Remove old tags and insert new ones.
-$query = OC_DB::prepare("
+$query = OCP\DB::prepare("
 	DELETE FROM *PREFIX*bookmarks_tags
 	WHERE bookmark_id = $bookmark_id
 	");
 
 $query->execute();
 
-$query = OC_DB::prepare("
+$query = OCP\DB::prepare("
 	INSERT INTO *PREFIX*bookmarks_tags
 	(bookmark_id, tag)
 	VALUES (?, ?)
diff --git a/apps/bookmarks/ajax/recordClick.php b/apps/bookmarks/ajax/recordClick.php
old mode 100644
new mode 100755
index e6fdfe043e1dcd6691e4c55f87da376dbc2f6933..2bd91f232a4801162e7d9b06c3ec3a39ed2296bc
--- a/apps/bookmarks/ajax/recordClick.php
+++ b/apps/bookmarks/ajax/recordClick.php
@@ -24,20 +24,20 @@
 //no apps or filesystem
 $RUNTIME_NOSETUPFS=true;
 
-require_once('../../../lib/base.php');
+ 
 
 // Check if we are a user
-OC_JSON::checkLoggedIn();
-OC_JSON::checkAppEnabled('bookmarks');
+OCP\JSON::checkLoggedIn();
+OCP\JSON::checkAppEnabled('bookmarks');
 
-$query = OC_DB::prepare("
+$query = OCP\DB::prepare("
 	UPDATE *PREFIX*bookmarks
 	SET clickcount = clickcount + 1
 	WHERE user_id = ?
 		AND url LIKE ?
 	");
 	
-$params=array(OC_User::getUser(), htmlspecialchars_decode($_GET["url"]));
+$params=array(OCP\USER::getUser(), htmlspecialchars_decode($_GET["url"]));
 $bookmarks = $query->execute($params);
 
 header( "HTTP/1.1 204 No Content" );
diff --git a/apps/bookmarks/ajax/updateList.php b/apps/bookmarks/ajax/updateList.php
old mode 100644
new mode 100755
index 487e0d290e3d664097d018fd86c90644e6e84285..c919a5fc4392d17f586edef3ab8d10c8abf41ad3
--- a/apps/bookmarks/ajax/updateList.php
+++ b/apps/bookmarks/ajax/updateList.php
@@ -25,11 +25,11 @@
 //no apps or filesystem
 $RUNTIME_NOSETUPFS=true;
 
-require_once('../../../lib/base.php');
+ 
 
 // Check if we are a user
-OC_JSON::checkLoggedIn();
-OC_JSON::checkAppEnabled('bookmarks');
+OCP\JSON::checkLoggedIn();
+OCP\JSON::checkAppEnabled('bookmarks');
 
 
 //Filter for tag?
@@ -47,4 +47,4 @@ if($sort == 'bookmarks_sorting_clicks') {
 
 $bookmarks = OC_Bookmarks_Bookmarks::findBookmarks($offset, $sqlSortColumn, $filterTag, true);
 
-OC_JSON::success(array('data' => $bookmarks));
+OCP\JSON::success(array('data' => $bookmarks));
diff --git a/apps/bookmarks/appinfo/app.php b/apps/bookmarks/appinfo/app.php
old mode 100644
new mode 100755
index b9c308ca05378f7eb2251c91ffd9cf7e3966ed20..8a8f443891c11fb0407d11b746978ec279fab795
--- a/apps/bookmarks/appinfo/app.php
+++ b/apps/bookmarks/appinfo/app.php
@@ -10,12 +10,12 @@
 OC::$CLASSPATH['OC_Bookmarks_Bookmarks'] = 'apps/bookmarks/lib/bookmarks.php';
 OC::$CLASSPATH['OC_Search_Provider_Bookmarks'] = 'apps/bookmarks/lib/search.php';
 
-OC_App::register( array( 'order' => 70, 'id' => 'bookmark', 'name' => 'Bookmarks' ));
+OCP\App::register( array( 'order' => 70, 'id' => 'bookmark', 'name' => 'Bookmarks' ));
 
 $l = new OC_l10n('bookmarks');
-OC_App::addNavigationEntry( array( 'id' => 'bookmarks_index', 'order' => 70, 'href' => OC_Helper::linkTo( 'bookmarks', 'index.php' ), 'icon' => OC_Helper::imagePath( 'bookmarks', 'bookmarks.png' ), 'name' => $l->t('Bookmarks')));
+OCP\App::addNavigationEntry( array( 'id' => 'bookmarks_index', 'order' => 70, 'href' => OCP\Util::linkTo( 'bookmarks', 'index.php' ), 'icon' => OCP\Util::imagePath( 'bookmarks', 'bookmarks.png' ), 'name' => $l->t('Bookmarks')));
 
-OC_App::registerPersonal('bookmarks', 'settings');
-OC_Util::addScript('bookmarks','bookmarksearch');
+OCP\App::registerPersonal('bookmarks', 'settings');
+OCP\Util::addscript('bookmarks','bookmarksearch');
 
 OC_Search::registerProvider('OC_Search_Provider_Bookmarks');
diff --git a/apps/bookmarks/appinfo/info.xml b/apps/bookmarks/appinfo/info.xml
index 862ab805a60f2eafd29afa57e02bcac9c75113ea..39779483d8504fec3df563b78e541450e4cdcf79 100644
--- a/apps/bookmarks/appinfo/info.xml
+++ b/apps/bookmarks/appinfo/info.xml
@@ -3,7 +3,6 @@
 	<id>bookmarks</id>
 	<name>Bookmarks</name>
 	<description>Bookmark manager for ownCloud</description>
-	<version>0.2</version>
 	<licence>AGPL</licence>
 	<author>Arthur Schiwon, Marvin Thomas Rabe</author>
 	<require>2</require>
diff --git a/apps/bookmarks/appinfo/migrate.php b/apps/bookmarks/appinfo/migrate.php
old mode 100644
new mode 100755
index c1251e816ecb45c8f22ca8742ec4a5350bea74eb..e7e572f52dc881c89782b4883bf1e4cfc766370a
--- a/apps/bookmarks/appinfo/migrate.php
+++ b/apps/bookmarks/appinfo/migrate.php
@@ -40,10 +40,10 @@ class OC_Migration_Provider_Bookmarks extends OC_Migration_Provider{
 				$idmap = array();
 				while( $row = $results->fetchRow() ){
 					// Import each bookmark, saving its id into the map	
-					$query = OC_DB::prepare( "INSERT INTO *PREFIX*bookmarks(url, title, user_id, public, added, lastmodified) VALUES (?, ?, ?, ?, ?, ?)" );
+					$query = OCP\DB::prepare( "INSERT INTO *PREFIX*bookmarks(url, title, user_id, public, added, lastmodified) VALUES (?, ?, ?, ?, ?, ?)" );
 					$query->execute( array( $row['url'], $row['title'], $this->uid, $row['public'], $row['added'], $row['lastmodified'] ) );
 					// Map the id
-					$idmap[$row['id']] = OC_DB::insertid();
+					$idmap[$row['id']] = OCP\DB::insertid();
 				}
 				// Now tags
 				foreach($idmap as $oldid => $newid){
@@ -51,7 +51,7 @@ class OC_Migration_Provider_Bookmarks extends OC_Migration_Provider{
 					$results = $query->execute( array( $oldid ) );
 					while( $row = $results->fetchRow() ){
 						// Import the tags for this bookmark, using the new bookmark id
-						$query = OC_DB::prepare( "INSERT INTO *PREFIX*bookmarks_tags(bookmark_id, tag) VALUES (?, ?)" );
+						$query = OCP\DB::prepare( "INSERT INTO *PREFIX*bookmarks_tags(bookmark_id, tag) VALUES (?, ?)" );
 						$query->execute( array( $newid, $row['tag'] ) );	
 					}		
 				}
diff --git a/apps/bookmarks/appinfo/version b/apps/bookmarks/appinfo/version
new file mode 100644
index 0000000000000000000000000000000000000000..2f4536184bcac31936bd15a5f9cf931dd526c022
--- /dev/null
+++ b/apps/bookmarks/appinfo/version
@@ -0,0 +1 @@
+0.2
\ No newline at end of file
diff --git a/apps/bookmarks/bookmarksHelper.php b/apps/bookmarks/bookmarksHelper.php
old mode 100644
new mode 100755
index 7ada69014fbb8ecaa8d529e70a1ad4ecec74d9fb..01b551111e0b8e5a50f6101b4908e0e7286ce607
--- a/apps/bookmarks/bookmarksHelper.php
+++ b/apps/bookmarks/bookmarksHelper.php
@@ -72,7 +72,7 @@ function getURLMetadata($url) {
 }
 
 function addBookmark($url, $title, $tags='') {
-	$CONFIG_DBTYPE = OC_Config::getValue( "dbtype", "sqlite" );
+	$CONFIG_DBTYPE = OCP\Config::getSystemValue( "dbtype", "sqlite" );
 	if( $CONFIG_DBTYPE == 'sqlite' or $CONFIG_DBTYPE == 'sqlite3' ){
 		$_ut = "strftime('%s','now')";
 	} elseif($CONFIG_DBTYPE == 'pgsql') {
@@ -82,7 +82,7 @@ function addBookmark($url, $title, $tags='') {
 	}
 	
 	//FIXME: Detect when user adds a known URL
-	$query = OC_DB::prepare("
+	$query = OCP\DB::prepare("
 		INSERT INTO *PREFIX*bookmarks
 		(url, title, user_id, public, added, lastmodified)
 		VALUES (?, ?, ?, 0, $_ut, $_ut)
@@ -94,21 +94,21 @@ function addBookmark($url, $title, $tags='') {
 	}
 	
 	if(empty($title)) {
-		$l = new OC_L10N('bookmarks');
+		$l = OC_L10N::get('bookmarks');
 		$title = $l->t('unnamed');
 	}
 	
 	$params=array(
 	htmlspecialchars_decode($url),
 	htmlspecialchars_decode($title),
-	OC_User::getUser()
+	OCP\USER::getUser()
 	);
 	$query->execute($params);
 	
-	$b_id = OC_DB::insertid('*PREFIX*bookmarks');
+	$b_id = OCP\DB::insertid('*PREFIX*bookmarks');
 	
 	if($b_id !== false) {
-		$query = OC_DB::prepare("
+		$query = OCP\DB::prepare("
 			INSERT INTO *PREFIX*bookmarks_tags
 			(bookmark_id, tag)
 			VALUES (?, ?)
diff --git a/apps/bookmarks/index.php b/apps/bookmarks/index.php
old mode 100644
new mode 100755
index 50fea3fddbd68b4966838690799a434c730530b9..f545d79da61cea2355fdbeb332e65cbf0d880dd3
--- a/apps/bookmarks/index.php
+++ b/apps/bookmarks/index.php
@@ -21,16 +21,16 @@
 * 
 */
 
-require_once('../../lib/base.php');
+
 
 // Check if we are a user
-OC_Util::checkLoggedIn();
-OC_Util::checkAppEnabled('bookmarks');
+OCP\User::checkLoggedIn();
+OCP\App::checkAppEnabled('bookmarks');
 
-OC_App::setActiveNavigationEntry( 'bookmarks_index' );
+OCP\App::setActiveNavigationEntry( 'bookmarks_index' );
 
-OC_Util::addScript('bookmarks','bookmarks');
-OC_Util::addStyle('bookmarks', 'bookmarks');
+OCP\Util::addscript('bookmarks','bookmarks');
+OCP\Util::addStyle('bookmarks', 'bookmarks');
 
 $tmpl = new OC_Template( 'bookmarks', 'list', 'user' );
 
diff --git a/apps/bookmarks/js/bookmarks.js b/apps/bookmarks/js/bookmarks.js
index 9502af0a00d12ca2379e67d01878e214ddf14a30..b1eebaa551540b1dc218c93d402f6d7a79facd97 100644
--- a/apps/bookmarks/js/bookmarks.js
+++ b/apps/bookmarks/js/bookmarks.js
@@ -3,7 +3,7 @@ var bookmarks_loading = false;
 
 var bookmarks_sorting = 'bookmarks_sorting_recent';
 
-$(document).ready(function() {	
+$(document).ready(function() {
 	$('#bookmark_add_submit').click(addOrEditBookmark);
 	$(window).resize(function () {
 		fillWindow($('.bookmarks_list'));
@@ -18,10 +18,10 @@ function getBookmarks() {
 		//have patience :)
 		return;
 	}
-	
+
 	$.ajax({
-		url: 'ajax/updateList.php',
-		data: 'tag=' + encodeURI($('#bookmarkFilterTag').val()) + '&page=' + bookmarks_page + '&sort=' + bookmarks_sorting,
+		url: OC.filePath('bookmarks', 'ajax', 'updateList.php'),
+		data: 'tag=' + encodeURIComponent($('#bookmarkFilterTag').val()) + '&page=' + bookmarks_page + '&sort=' + bookmarks_sorting,
 		success: function(bookmarks){
 			if (bookmarks.data.length) {
 				bookmarks_page += 1;
@@ -29,7 +29,7 @@ function getBookmarks() {
 			$('.bookmark_link').unbind('click', recordClick);
 			$('.bookmark_delete').unbind('click', delBookmark);
 			$('.bookmark_edit').unbind('click', showBookmark);
-	
+
 			for(var i in bookmarks.data) {
 				updateBookmarksList(bookmarks.data[i]);
 				$("#firstrun").hide();
@@ -41,13 +41,13 @@ function getBookmarks() {
 			$('.bookmark_link').click(recordClick);
 			$('.bookmark_delete').click(delBookmark);
 			$('.bookmark_edit').click(showBookmark);
-			
+
 			bookmarks_loading = false;
 			if (bookmarks.data.length) {
 				updateOnBottom()
 			}
 		}
-	});	
+	});
 }
 
 // function addBookmark() {
@@ -60,13 +60,13 @@ function addOrEditBookmark(event) {
 	var title = encodeEntities($('#bookmark_add_title').val());
 	var tags = encodeEntities($('#bookmark_add_tags').val());
 	$("#firstrun").hide();
-	
+
 	if (id == 0) {
 		$.ajax({
-			url: 'ajax/addBookmark.php',
-			data: 'url=' + encodeURI(url) + '&title=' + encodeURI(title) + '&tags=' + encodeURI(tags),
-			success: function(response){ 
-				$('.bookmarks_input').val(''); 
+			url: OC.filePath('bookmarks', 'ajax', 'addBookmark.php'),
+			data: 'url=' + encodeURIComponent(url) + '&title=' + encodeURIComponent(title) + '&tags=' + encodeURIComponent(tags),
+			success: function(response){
+				$('.bookmarks_input').val('');
 				$('.bookmarks_list').empty();
 				bookmarks_page = 0;
 				getBookmarks();
@@ -75,9 +75,9 @@ function addOrEditBookmark(event) {
 	}
 	else {
 		$.ajax({
-			url: 'ajax/editBookmark.php',
-			data: 'id=' + id + '&url=' + encodeURI(url) + '&title=' + encodeURI(title) + '&tags=' + encodeURI(tags),
-			success: function(){ 
+			url: OC.filePath('bookmarks', 'ajax', 'editBookmark.php'),
+			data: 'id=' + id + '&url=' + encodeURIComponent(url) + '&title=' + encodeURIComponent(title) + '&tags=' + encodeURIComponent(tags),
+			success: function(){
 				$('.bookmarks_input').val('');
 				$('#bookmark_add_id').val('0');
 				$('.bookmarks_list').empty();
@@ -86,18 +86,20 @@ function addOrEditBookmark(event) {
 			}
 		});
 	}
-	
+
 }
 
 function delBookmark(event) {
 	var record = $(this).parent().parent();
 	$.ajax({
-		url: 'ajax/delBookmark.php',
-		data: 'url=' + encodeURI($(this).parent().parent().children('.bookmark_url:first').text()),
+		url: OC.filePath('bookmarks', 'ajax', 'delBookmark.php'),
+		data: 'id=' + record.data('id'),
 		success: function(data){
-			record.remove();
-			if($('.bookmarks_list').is(':empty')) {
-				$("#firstrun").show();
+			if (data.status == 'success') {
+				record.remove();
+				if($('.bookmarks_list').is(':empty')) {
+					$("#firstrun").show();
+				}
 			}
 		}
 	});
@@ -109,7 +111,7 @@ function showBookmark(event) {
 	$('#bookmark_add_url').val(record.children('.bookmark_url:first').text());
 	$('#bookmark_add_title').val(record.children('.bookmark_title:first').text());
 	$('#bookmark_add_tags').val(record.children('.bookmark_tags:first').text());
-	
+
 	if ($('.bookmarks_add').css('display') == 'none') {
 		$('.bookmarks_add').slideToggle();
 	}
@@ -124,7 +126,7 @@ function updateBookmarksList(bookmark) {
 	var taglist = '';
 	for ( var i=0, len=tags.length; i<len; ++i ){
 		if(tags[i] != '')
-			taglist = taglist + '<a class="bookmark_tag" href="?tag=' + encodeURI(tags[i]) + '">' + tags[i] + '</a> ';
+			taglist = taglist + '<a class="bookmark_tag" href="?tag=' + encodeURIComponent(tags[i]) + '">' + tags[i] + '</a> ';
 	}
 	if(!hasProtocol(bookmark.url)) {
 		bookmark.url = 'http://' + bookmark.url;
@@ -164,9 +166,9 @@ function updateOnBottom() {
 
 function recordClick(event) {
 	$.ajax({
-		url: 'ajax/recordClick.php',
-		data: 'url=' + encodeURI($(this).attr('href')),
-	});	
+		url: OC.filePath('bookmarks', 'ajax', 'recordClick.php'),
+		data: 'url=' + encodeURIComponent($(this).attr('href')),
+	});
 }
 
 function encodeEntities(s){
diff --git a/apps/bookmarks/lib/bookmarks.php b/apps/bookmarks/lib/bookmarks.php
old mode 100644
new mode 100755
index 81c1b03981aed56a3ad4a80a4ce6251fd36d1b52..e0005968f31525d0c2e326979fadade63cb6ebe1
--- a/apps/bookmarks/lib/bookmarks.php
+++ b/apps/bookmarks/lib/bookmarks.php
@@ -34,10 +34,10 @@ class OC_Bookmarks_Bookmarks{
 	 * @return void
 	 */
 	public static function findBookmarks($offset, $sqlSortColumn, $filter, $filterTagOnly){
-		//OC_Log::write('bookmarks', 'findBookmarks ' .$offset. ' '.$sqlSortColumn.' '. $filter.' '. $filterTagOnly ,OC_Log::DEBUG);
-		$CONFIG_DBTYPE = OC_Config::getValue( 'dbtype', 'sqlite' );
+		//OCP\Util::writeLog('bookmarks', 'findBookmarks ' .$offset. ' '.$sqlSortColumn.' '. $filter.' '. $filterTagOnly ,OCP\Util::DEBUG);
+		$CONFIG_DBTYPE = OCP\Config::getSystemValue( 'dbtype', 'sqlite' );
 	
-		$params=array(OC_User::getUser());
+		$params=array(OCP\USER::getUser());
 	
 		if( $CONFIG_DBTYPE == 'sqlite' or $CONFIG_DBTYPE == 'sqlite3' ){
 			$_gc_separator = ', \' \'';
@@ -70,7 +70,7 @@ class OC_Bookmarks_Bookmarks{
 		}
 
 		if($CONFIG_DBTYPE == 'pgsql' ){
-			$query = OC_DB::prepare('
+			$query = OCP\DB::prepare('
 				SELECT id, url, title, '.($filterTagOnly?'':'url || title ||').' array_to_string(array_agg(tag), \' \') as tags
 				FROM *PREFIX*bookmarks
 				LEFT JOIN *PREFIX*bookmarks_tags ON *PREFIX*bookmarks.id = *PREFIX*bookmarks_tags.bookmark_id 
@@ -87,7 +87,7 @@ class OC_Bookmarks_Bookmarks{
 			else
 				$concatFunction = 'Concat(Concat( url, title), ';
 		
-			$query = OC_DB::prepare('
+			$query = OCP\DB::prepare('
 				SELECT id, url, title, '
 				.($filterTagOnly?'':$concatFunction).
 				'CASE WHEN *PREFIX*bookmarks.id = *PREFIX*bookmarks_tags.bookmark_id
@@ -113,5 +113,37 @@ class OC_Bookmarks_Bookmarks{
 		$bookmarks = $query->execute($params)->fetchAll();
 		return $bookmarks;
 	}
+
+	public static function deleteUrl($id)
+	{
+		$user = OCP\USER::getUser();
+
+		$query = OCP\DB::prepare("
+				SELECT id FROM *PREFIX*bookmarks
+				WHERE id = ?
+				AND user_id = ?
+				");
+
+		$result = $query->execute(array($id, $user));
+		$id = $result->fetchOne();
+		if ($id === false) {
+			return false;
+		}
+
+		$query = OCP\DB::prepare("
+			DELETE FROM *PREFIX*bookmarks
+			WHERE id = $id
+			");
+
+		$result = $query->execute();
+
+		$query = OCP\DB::prepare("
+			DELETE FROM *PREFIX*bookmarks_tags
+			WHERE bookmark_id = $id
+			");
+
+		$result = $query->execute();
+		return true;
+	}
 }
 ?>
diff --git a/apps/bookmarks/lib/search.php b/apps/bookmarks/lib/search.php
old mode 100644
new mode 100755
index d7e32558617198ce1b1abedc6fdbf76a967db45d..1e6a3ce910b9517f543ed8222119bcc4b8b2f322
--- a/apps/bookmarks/lib/search.php
+++ b/apps/bookmarks/lib/search.php
@@ -34,9 +34,9 @@ class OC_Search_Provider_Bookmarks extends OC_Search_Provider{
 			$searchquery = $query;
 		}
 		
-//		OC_Log::write('bookmarks', 'search ' .$query ,OC_Log::DEBUG);
+//		OCP\Util::writeLog('bookmarks', 'search ' .$query ,OCP\Util::DEBUG);
 		$bookmarks = OC_Bookmarks_Bookmarks::findBookmarks($offset, $sqlSortColumn, $searchquery, false);
-//		OC_Log::write('bookmarks', 'found ' .count($bookmarks) ,OC_Log::DEBUG);
+//		OCP\Util::writeLog('bookmarks', 'found ' .count($bookmarks) ,OCP\Util::DEBUG);
 		//$l = new OC_l10n('bookmarks'); //resulttype can't be localized, javascript relies on that type
 		foreach($bookmarks as $bookmark){
 			$results[]=new OC_Search_Result($bookmark['title'],'', $bookmark['url'],'Bookm.');
diff --git a/apps/bookmarks/templates/bookmarklet.php b/apps/bookmarks/templates/bookmarklet.php
old mode 100644
new mode 100755
index 5ea67f04df2d32f6943e8c8e0b3b60fb6302164a..1802814d4bbd22f1443d0e9e3d668c5a5910eb4e
--- a/apps/bookmarks/templates/bookmarklet.php
+++ b/apps/bookmarks/templates/bookmarklet.php
@@ -1,8 +1,8 @@
 <?php
 
 function createBookmarklet() {
-	$l = new OC_L10N('bookmarks');
+	$l = OC_L10N::get('bookmarks');
 	echo '<small>' . $l->t('Drag this to your browser bookmarks and click it, when you want to bookmark a webpage quickly:') . '</small>'
-	. '<a class="bookmarklet" href="javascript:(function(){var a=window,b=document,c=encodeURIComponent,d=a.open(\'' . OC_Helper::linkToAbsolute('bookmarks', 'addBm.php') . '?output=popup&url=\'+c(b.location),\'bkmk_popup\',\'left=\'+((a.screenX||a.screenLeft)+10)+\',top=\'+((a.screenY||a.screenTop)+10)+\',height=230px,width=230px,resizable=1,alwaysRaised=1\');a.setTimeout(function(){d.focus()},300);})();">'
+	. '<a class="button bookmarklet" href="javascript:(function(){var a=window,b=document,c=encodeURIComponent,d=a.open(\'' . OCP\Util::linkToAbsolute('bookmarks', 'addBm.php') . '?output=popup&url=\'+c(b.location),\'bkmk_popup\',\'left=\'+((a.screenX||a.screenLeft)+10)+\',top=\'+((a.screenY||a.screenTop)+10)+\',height=230px,width=230px,resizable=1,alwaysRaised=1\');a.setTimeout(function(){d.focus()},300);})();">'
 	. $l->t('Read later') . '</a>';
 } 
diff --git a/apps/bookmarks/templates/list.php b/apps/bookmarks/templates/list.php
index 1abdbb7f838af48d94d062e395f3463a58eca76d..9fe9ee7a9a9bfdc81e7a770441e35d0543f2d6c6 100644
--- a/apps/bookmarks/templates/list.php
+++ b/apps/bookmarks/templates/list.php
@@ -20,7 +20,7 @@
 <div id="firstrun" style="display: none;">
 	<?php
 		echo $l->t('You have no bookmarks');
-		require_once('bookmarklet.php');
+		require_once(OC::$APPSROOT . '/apps/bookmarks/templates/bookmarklet.php');
 		createBookmarklet(); 
 	?>
 </div>
diff --git a/apps/calendar/ajax/calendar/activation.php b/apps/calendar/ajax/calendar/activation.php
old mode 100644
new mode 100755
index 7677d85aff30d67c1318aee177f4fbb4c83cbfa1..3523590aa27df0180aaec803f183385eb3fb7f01
--- a/apps/calendar/ajax/calendar/activation.php
+++ b/apps/calendar/ajax/calendar/activation.php
@@ -6,14 +6,14 @@
  * See the COPYING-README file.
  */
 
-require_once('../../../../lib/base.php');
-OC_JSON::checkLoggedIn();
-OC_JSON::checkAppEnabled('calendar');
+ 
+OCP\JSON::checkLoggedIn();
+OCP\JSON::checkAppEnabled('calendar');
 $calendarid = $_POST['calendarid'];
 $calendar = OC_Calendar_App::getCalendar($calendarid);//access check
 OC_Calendar_Calendar::setCalendarActive($calendarid, $_POST['active']);
 $calendar = OC_Calendar_App::getCalendar($calendarid);
-OC_JSON::success(array(
+OCP\JSON::success(array(
 	'active' => $calendar['active'],
 	'eventSource' => OC_Calendar_Calendar::getEventSourceInfo($calendar),
 ));
diff --git a/apps/calendar/ajax/calendar/delete.php b/apps/calendar/ajax/calendar/delete.php
old mode 100644
new mode 100755
index a2f5311731c5edb0b137a8e0876639109dca3fd9..a36a05346500c436b64892fb19e3257451c6548b
--- a/apps/calendar/ajax/calendar/delete.php
+++ b/apps/calendar/ajax/calendar/delete.php
@@ -5,17 +5,17 @@
  * later.
  * See the COPYING-README file.
  */
-require_once('../../../../lib/base.php');
+ 
 
-OC_JSON::checkLoggedIn();
-OC_JSON::checkAppEnabled('calendar');
+OCP\JSON::checkLoggedIn();
+OCP\JSON::checkAppEnabled('calendar');
 
 $cal = $_POST["calendarid"];
 $calendar = OC_Calendar_App::getCalendar($cal);
 $del = OC_Calendar_Calendar::deleteCalendar($cal);
 if($del == true){
-	OC_JSON::success();
+	OCP\JSON::success();
 }else{
-	OC_JSON::error(array('error'=>'dberror'));
+	OCP\JSON::error(array('error'=>'dberror'));
 }
 ?> 
diff --git a/apps/calendar/ajax/calendar/edit.form.php b/apps/calendar/ajax/calendar/edit.form.php
old mode 100644
new mode 100755
index 8922b3eba4ed5e05ae174d95ff357c3b6bb71806..17118c5165f5987f64e28d2dc2fcfc1e3eedd838
--- a/apps/calendar/ajax/calendar/edit.form.php
+++ b/apps/calendar/ajax/calendar/edit.form.php
@@ -6,9 +6,9 @@
  * See the COPYING-README file.
  */
 
-require_once('../../../../lib/base.php');
-OC_JSON::checkLoggedIn();
-OC_JSON::checkAppEnabled('calendar');
+ 
+OCP\JSON::checkLoggedIn();
+OCP\JSON::checkAppEnabled('calendar');
 
 $calendarcolor_options = OC_Calendar_Calendar::getCalendarColorOptions();
 $calendar = OC_Calendar_App::getCalendar($_GET['calendarid']);
diff --git a/apps/calendar/ajax/calendar/edit.php b/apps/calendar/ajax/calendar/edit.php
old mode 100644
new mode 100755
index 8922b3eba4ed5e05ae174d95ff357c3b6bb71806..17118c5165f5987f64e28d2dc2fcfc1e3eedd838
--- a/apps/calendar/ajax/calendar/edit.php
+++ b/apps/calendar/ajax/calendar/edit.php
@@ -6,9 +6,9 @@
  * See the COPYING-README file.
  */
 
-require_once('../../../../lib/base.php');
-OC_JSON::checkLoggedIn();
-OC_JSON::checkAppEnabled('calendar');
+ 
+OCP\JSON::checkLoggedIn();
+OCP\JSON::checkAppEnabled('calendar');
 
 $calendarcolor_options = OC_Calendar_Calendar::getCalendarColorOptions();
 $calendar = OC_Calendar_App::getCalendar($_GET['calendarid']);
diff --git a/apps/calendar/ajax/calendar/new.form.php b/apps/calendar/ajax/calendar/new.form.php
old mode 100644
new mode 100755
index 6e7423cbe922ff6909f29ba32207a43c2019f5ab..fa30b871e42611a35aa581fcecfaf932449dc4b8
--- a/apps/calendar/ajax/calendar/new.form.php
+++ b/apps/calendar/ajax/calendar/new.form.php
@@ -6,10 +6,9 @@
  * See the COPYING-README file.
  */
 
-require_once('../../../../lib/base.php');
-$l10n = new OC_L10N('calendar');
-OC_JSON::checkLoggedIn();
-OC_JSON::checkAppEnabled('calendar');
+ 
+OCP\JSON::checkLoggedIn();
+OCP\JSON::checkAppEnabled('calendar');
 $calendarcolor_options = OC_Calendar_Calendar::getCalendarColorOptions();
 $calendar = array(
 	'id' => 'new',
diff --git a/apps/calendar/ajax/calendar/new.php b/apps/calendar/ajax/calendar/new.php
old mode 100644
new mode 100755
index 228e6247724dfbf0dcfc32235ca2294b86c6a5a4..4b8688e3d1d2dd792bd4db78e29e9c6c45ca6210
--- a/apps/calendar/ajax/calendar/new.php
+++ b/apps/calendar/ajax/calendar/new.php
@@ -6,32 +6,32 @@
  * See the COPYING-README file.
  */
 
-require_once('../../../../lib/base.php');
+ 
 
 // Check if we are a user
-OC_JSON::checkLoggedIn();
-OC_JSON::checkAppEnabled('calendar');
+OCP\JSON::checkLoggedIn();
+OCP\JSON::checkAppEnabled('calendar');
 
 if(trim($_POST['name']) == ''){
-	OC_JSON::error(array('message'=>'empty'));
+	OCP\JSON::error(array('message'=>'empty'));
 	exit;
 }
-$calendars = OC_Calendar_Calendar::allCalendars(OC_User::getUser());
+$calendars = OC_Calendar_Calendar::allCalendars(OCP\USER::getUser());
 foreach($calendars as $cal){
 	if($cal['displayname'] == $_POST['name']){
-		OC_JSON::error(array('message'=>'namenotavailable'));
+		OCP\JSON::error(array('message'=>'namenotavailable'));
 		exit;
 	}
 }
 
-$userid = OC_User::getUser();
+$userid = OCP\USER::getUser();
 $calendarid = OC_Calendar_Calendar::addCalendar($userid, strip_tags($_POST['name']), 'VEVENT,VTODO,VJOURNAL', null, 0, $_POST['color']);
 OC_Calendar_Calendar::setCalendarActive($calendarid, 1);
 
 $calendar = OC_Calendar_Calendar::find($calendarid);
 $tmpl = new OC_Template('calendar', 'part.choosecalendar.rowfields');
 $tmpl->assign('calendar', $calendar);
-OC_JSON::success(array(
+OCP\JSON::success(array(
 	'page' => $tmpl->fetchPage(),
 	'eventSource' => OC_Calendar_Calendar::getEventSourceInfo($calendar),
 ));
diff --git a/apps/calendar/ajax/calendar/overview.php b/apps/calendar/ajax/calendar/overview.php
old mode 100644
new mode 100755
index 2f73f5d07101deea02075aeccd90b7e2bfd27ee8..586bf3db814681c34ae58f976ec798d0fdb5c9e5
--- a/apps/calendar/ajax/calendar/overview.php
+++ b/apps/calendar/ajax/calendar/overview.php
@@ -6,10 +6,10 @@
  * See the COPYING-README file.
  */
 
-require_once('../../../../lib/base.php');
-$l10n = new OC_L10N('calendar');
-OC_JSON::checkLoggedIn();
-OC_JSON::checkAppEnabled('calendar');
+ 
+$l10n = OC_L10N::get('calendar');
+OCP\JSON::checkLoggedIn();
+OCP\JSON::checkAppEnabled('calendar');
 $output = new OC_TEMPLATE("calendar", "part.choosecalendar");
 $output -> printpage();
 ?>
diff --git a/apps/calendar/ajax/calendar/update.php b/apps/calendar/ajax/calendar/update.php
old mode 100644
new mode 100755
index f400c8c14b43018fdf12efb541b9f422430d5ba0..408ac9009127e946f6514b0e2c75e4f6333b12ab
--- a/apps/calendar/ajax/calendar/update.php
+++ b/apps/calendar/ajax/calendar/update.php
@@ -6,20 +6,20 @@
  * See the COPYING-README file.
  */
 
-require_once('../../../../lib/base.php');
+ 
 
 // Check if we are a user
-OC_JSON::checkLoggedIn();
-OC_JSON::checkAppEnabled('calendar');
+OCP\JSON::checkLoggedIn();
+OCP\JSON::checkAppEnabled('calendar');
 
 if(trim($_POST['name']) == ''){
-	OC_JSON::error(array('message'=>'empty'));
+	OCP\JSON::error(array('message'=>'empty'));
 	exit;
 }
-$calendars = OC_Calendar_Calendar::allCalendars(OC_User::getUser());
+$calendars = OC_Calendar_Calendar::allCalendars(OCP\USER::getUser());
 foreach($calendars as $cal){
 	if($cal['displayname'] == $_POST['name'] && $cal['id'] != $_POST['id']){
-		OC_JSON::error(array('message'=>'namenotavailable'));
+		OCP\JSON::error(array('message'=>'namenotavailable'));
 		exit;
 	}
 }
@@ -32,7 +32,7 @@ OC_Calendar_Calendar::setCalendarActive($calendarid, $_POST['active']);
 $calendar = OC_Calendar_App::getCalendar($calendarid);
 $tmpl = new OC_Template('calendar', 'part.choosecalendar.rowfields');
 $tmpl->assign('calendar', $calendar);
-OC_JSON::success(array(
+OCP\JSON::success(array(
 	'page' => $tmpl->fetchPage(),
 	'eventSource' => OC_Calendar_Calendar::getEventSourceInfo($calendar),
 ));
diff --git a/apps/calendar/ajax/categories/rescan.php b/apps/calendar/ajax/categories/rescan.php
old mode 100644
new mode 100755
index 0fd878ed8f93cbc9a6497449be80c57f9a24a54b..93e8c50954a2733fbc37ebc5347a0cf738367504
--- a/apps/calendar/ajax/categories/rescan.php
+++ b/apps/calendar/ajax/categories/rescan.php
@@ -6,24 +6,24 @@
  * See the COPYING-README file.
  */
 
-require_once('../../../../lib/base.php');
-OC_JSON::checkLoggedIn();
-OC_JSON::checkAppEnabled('calendar');
+ 
+OCP\JSON::checkLoggedIn();
+OCP\JSON::checkAppEnabled('calendar');
 
 foreach ($_POST as $key=>$element) {
 	debug('_POST: '.$key.'=>'.print_r($element, true));
 }
 
 function bailOut($msg) {
-	OC_JSON::error(array('data' => array('message' => $msg)));
-	OC_Log::write('calendar','ajax/categories/rescan.php: '.$msg, OC_Log::DEBUG);
+	OCP\JSON::error(array('data' => array('message' => $msg)));
+	OCP\Util::writeLog('calendar','ajax/categories/rescan.php: '.$msg, OCP\Util::DEBUG);
 	exit();
 }
 function debug($msg) {
-	OC_Log::write('calendar','ajax/categories/rescan.php: '.$msg, OC_Log::DEBUG);
+	OCP\Util::writeLog('calendar','ajax/categories/rescan.php: '.$msg, OCP\Util::DEBUG);
 }
 
-$calendars = OC_Calendar_Calendar::allCalendars(OC_User::getUser());
+$calendars = OC_Calendar_Calendar::allCalendars(OCP\USER::getUser());
 if(count($calendars) == 0) {
 	bailOut(OC_Calendar_App::$l10n->t('No calendars found.'));
 }
@@ -39,4 +39,4 @@ if(count($events) == 0) {
 OC_Calendar_App::scanCategories($events);
 $categories = OC_Calendar_App::getCategoryOptions();
 
-OC_JSON::success(array('data' => array('categories'=>$categories)));
+OCP\JSON::success(array('data' => array('categories'=>$categories)));
diff --git a/apps/calendar/ajax/changeview.php b/apps/calendar/ajax/changeview.php
old mode 100644
new mode 100755
index ae48b229b164f6be44dbed1664fe37958fc4ed87..2c2d09ccb1294b2e5445538e7b16b67acfcfc1fe
--- a/apps/calendar/ajax/changeview.php
+++ b/apps/calendar/ajax/changeview.php
@@ -1,14 +1,12 @@
 <?php
 /**
- * Copyright (c) 2011 Georg Ehrke <ownclouddev at georgswebsite dot de>
+ * Copyright (c) 2012 Georg Ehrke <ownclouddev at georgswebsite dot de>
  * This file is licensed under the Affero General Public License version 3 or
  * later.
  * See the COPYING-README file.
  */
-
-require_once ("../../../lib/base.php");
-OC_JSON::checkLoggedIn();
-OC_JSON::checkAppEnabled('calendar');
+OCP\JSON::checkLoggedIn();
+OCP\JSON::checkAppEnabled('calendar');
 $view = $_GET['v'];
 switch($view){
 	case 'agendaWeek':
@@ -16,9 +14,9 @@ switch($view){
 	case 'list':
 		break;
 	default:
-		OC_JSON::error(array('message'=>'unexspected parameter: ' . $view));
+		OCP\JSON::error(array('message'=>'unexspected parameter: ' . $view));
 		exit;
 }
-OC_Preferences::setValue(OC_USER::getUser(), 'calendar', 'currentview', $view);
-OC_JSON::success();
+OCP\Config::setUserValue(OCP\USER::getUser(), 'calendar', 'currentview', $view);
+OCP\JSON::success();
 ?>
diff --git a/apps/calendar/ajax/event/delete.php b/apps/calendar/ajax/event/delete.php
old mode 100644
new mode 100755
index 862dec6bf5b2ce92b96dfa936f854be1c9dd18cc..cb30621af4d4c2d3defb8c7564ef25b161125dd1
--- a/apps/calendar/ajax/event/delete.php
+++ b/apps/calendar/ajax/event/delete.php
@@ -5,15 +5,16 @@
  * later.
  * See the COPYING-README file.
  */
-require_once('../../../../lib/base.php');
+ 
 
-$l10n = new OC_L10N('calendar');
-
-OC_JSON::checkLoggedIn();
-OC_JSON::checkAppEnabled('calendar');
+OCP\JSON::checkLoggedIn();
+OCP\JSON::checkAppEnabled('calendar');
 
 $id = $_POST['id'];
-$event_object = OC_Calendar_App::getEventObject($id);
+$access = OC_Calendar_App::getaccess($id, OC_Calendar_App::EVENT);
+if($access != 'owner' && $access != 'rw'){
+	OCP\JSON::error(array('message'=>'permission denied'));
+	exit;
+}
 $result = OC_Calendar_Object::delete($id);
-OC_JSON::success();
-?> 
+OCP\JSON::success();
diff --git a/apps/calendar/ajax/event/edit.form.php b/apps/calendar/ajax/event/edit.form.php
old mode 100644
new mode 100755
index 98c22eb0206c8f5772750d34d7e0eec08349b602..91d07d3897a11f1b809a8aab8d8bad6879dfc79d
--- a/apps/calendar/ajax/event/edit.form.php
+++ b/apps/calendar/ajax/event/edit.form.php
@@ -6,30 +6,36 @@
  * See the COPYING-README file.
  */
 
-require_once('../../../../lib/base.php');
+ 
 
-if(!OC_USER::isLoggedIn()) {
+if(!OCP\User::isLoggedIn()) {
 	die('<script type="text/javascript">document.location = oc_webroot;</script>');
 }
-OC_JSON::checkAppEnabled('calendar');
+OCP\JSON::checkAppEnabled('calendar');
 
 $id = $_GET['id'];
-$data = OC_Calendar_App::getEventObject($id);
+$data = OC_Calendar_App::getEventObject($id, true, true);
+
+if(!$data){
+	OCP\JSON::error(array('data' => array('message' => self::$l10n->t('Wrong calendar'))));
+	exit;
+}
+$access = OC_Calendar_App::getaccess($id, OC_Calendar_Share::EVENT);
 $object = OC_VObject::parse($data['calendardata']);
 $vevent = $object->VEVENT;
 
 $dtstart = $vevent->DTSTART;
 $dtend = OC_Calendar_Object::getDTEndFromVEvent($vevent);
 switch($dtstart->getDateType()) {
-	case Sabre_VObject_Element_DateTime::LOCALTZ:
-	case Sabre_VObject_Element_DateTime::LOCAL:
+	case Sabre_VObject_Property_DateTime::LOCALTZ:
+	case Sabre_VObject_Property_DateTime::LOCAL:
 		$startdate = $dtstart->getDateTime()->format('d-m-Y');
 		$starttime = $dtstart->getDateTime()->format('H:i');
 		$enddate = $dtend->getDateTime()->format('d-m-Y');
 		$endtime = $dtend->getDateTime()->format('H:i');
 		$allday = false;
 		break;
-	case Sabre_VObject_Element_DateTime::DATE:
+	case Sabre_VObject_Property_DateTime::DATE:
 		$startdate = $dtstart->getDateTime()->format('d-m-Y');
 		$starttime = '';
 		$dtend->getDateTime()->modify('-1 day');
@@ -182,8 +188,12 @@ if($data['repeating'] == 1){
 }else{
 	$repeat['repeat'] = 'doesnotrepeat';
 }
-
-$calendar_options = OC_Calendar_Calendar::allCalendars(OC_User::getUser());
+if($access == 'owner'){
+	$calendar_options = OC_Calendar_Calendar::allCalendars(OCP\USER::getUser());
+}else{
+	$calendar_options = array(OC_Calendar_App::getCalendar($data['calendarid'], false));
+}
+$category_options = OC_Calendar_App::getCategoryOptions();
 $repeat_options = OC_Calendar_App::getRepeatOptions();
 $repeat_end_options = OC_Calendar_App::getEndOptions();
 $repeat_month_options = OC_Calendar_App::getMonthOptions();
@@ -195,8 +205,14 @@ $repeat_bymonth_options = OC_Calendar_App::getByMonthOptions();
 $repeat_byweekno_options = OC_Calendar_App::getByWeekNoOptions();
 $repeat_bymonthday_options = OC_Calendar_App::getByMonthDayOptions();
 
-$tmpl = new OC_Template('calendar', 'part.editevent');
-$tmpl->assign('id', $id);
+if($access == 'owner' || $access == 'rw'){
+	$tmpl = new OC_Template('calendar', 'part.editevent');
+}elseif($access == 'r'){
+	$tmpl = new OC_Template('calendar', 'part.showevent');
+}
+
+$tmpl->assign('eventid', $id);
+$tmpl->assign('access', $access);
 $tmpl->assign('lastmodified', $lastmodified);
 $tmpl->assign('calendar_options', $calendar_options);
 $tmpl->assign('repeat_options', $repeat_options);
diff --git a/apps/calendar/ajax/event/edit.php b/apps/calendar/ajax/event/edit.php
old mode 100644
new mode 100755
index 64daffddef01b6aad9a7755af270681b65976368..e615fb093de018035cbf12b2c603c034a6de856c
--- a/apps/calendar/ajax/event/edit.php
+++ b/apps/calendar/ajax/event/edit.php
@@ -6,28 +6,41 @@
  * See the COPYING-README file.
  */
 
-require_once('../../../../lib/base.php');
-OC_JSON::checkLoggedIn();
-OC_JSON::checkAppEnabled('calendar');
+ 
+OCP\JSON::checkLoggedIn();
+OCP\JSON::checkAppEnabled('calendar');
+
+$id = $_POST['id'];
+
+if(!array_key_exists('calendar', $_POST)){
+	$cal = OC_Calendar_Object::getCalendarid($id);
+	$_POST['calendar'] = $cal;
+}else{
+	$cal = $_POST['calendar'];
+}
+
+$access = OC_Calendar_App::getaccess($id, OC_Calendar_App::EVENT);
+if($access != 'owner' && $access != 'rw'){
+	OCP\JSON::error(array('message'=>'permission denied'));
+	exit;
+}
 
 $errarr = OC_Calendar_Object::validateRequest($_POST);
 if($errarr){
 	//show validate errors
-	OC_JSON::error($errarr);
+	OCP\JSON::error($errarr);
 	exit;
 }else{
-	$id = $_POST['id'];
-	$cal = $_POST['calendar'];
-	$data = OC_Calendar_App::getEventObject($id);
+	$data = OC_Calendar_App::getEventObject($id, false, false);
 	$vcalendar = OC_VObject::parse($data['calendardata']);
 
 	OC_Calendar_App::isNotModified($vcalendar->VEVENT, $_POST['lastmodified']);
 	OC_Calendar_Object::updateVCalendarFromRequest($_POST, $vcalendar);
 
-	$result = OC_Calendar_Object::edit($id, $vcalendar->serialize());
+	OC_Calendar_Object::edit($id, $vcalendar->serialize());
 	if ($data['calendarid'] != $cal) {
 		OC_Calendar_Object::moveToCalendar($id, $cal);
 	}
-	OC_JSON::success();
+	OCP\JSON::success();
 }
 ?>
diff --git a/apps/calendar/ajax/event/move.php b/apps/calendar/ajax/event/move.php
old mode 100644
new mode 100755
index 8150fdbaa3207fcee344fe15c201476fbea12d52..8added69143b6a85c1064e2f862f074f074c29b5
--- a/apps/calendar/ajax/event/move.php
+++ b/apps/calendar/ajax/event/move.php
@@ -5,39 +5,42 @@
  * later.
  * See the COPYING-README file.
  */
-require_once('../../../../lib/base.php');
-OC_JSON::checkLoggedIn();
+ 
+OCP\JSON::checkLoggedIn();
 
 $id = $_POST['id'];
-
-$vcalendar = OC_Calendar_App::getVCalendar($id);
+$access = OC_Calendar_App::getaccess($id, OC_Calendar_App::EVENT);
+if($access != 'owner' && $access != 'rw'){
+	OCP\JSON::error(array('message'=>'permission denied'));
+	exit;
+}
+$vcalendar = OC_Calendar_App::getVCalendar($id, false, false);
 $vevent = $vcalendar->VEVENT;
 
 $allday = $_POST['allDay'];
 $delta = new DateInterval('P0D');
 $delta->d = $_POST['dayDelta'];
 $delta->i = $_POST['minuteDelta'];
-
 OC_Calendar_App::isNotModified($vevent, $_POST['lastmodified']);
 
 $dtstart = $vevent->DTSTART;
 $dtend = OC_Calendar_Object::getDTEndFromVEvent($vevent);
 $start_type = $dtstart->getDateType();
 $end_type = $dtend->getDateType();
-if ($allday && $start_type != Sabre_VObject_Element_DateTime::DATE){
-	$start_type = $end_type = Sabre_VObject_Element_DateTime::DATE;
+if ($allday && $start_type != Sabre_VObject_Property_DateTime::DATE){
+	$start_type = $end_type = Sabre_VObject_Property_DateTime::DATE;
 	$dtend->setDateTime($dtend->getDateTime()->modify('+1 day'), $end_type);
 }
-if (!$allday && $start_type == Sabre_VObject_Element_DateTime::DATE){
-	$start_type = $end_type = Sabre_VObject_Element_DateTime::LOCALTZ;
+if (!$allday && $start_type == Sabre_VObject_Property_DateTime::DATE){
+	$start_type = $end_type = Sabre_VObject_Property_DateTime::LOCALTZ;
 }
 $dtstart->setDateTime($dtstart->getDateTime()->add($delta), $start_type);
 $dtend->setDateTime($dtend->getDateTime()->add($delta), $end_type);
 unset($vevent->DURATION);
 
-$vevent->setDateTime('LAST-MODIFIED', 'now', Sabre_VObject_Element_DateTime::UTC);
-$vevent->setDateTime('DTSTAMP', 'now', Sabre_VObject_Element_DateTime::UTC);
+$vevent->setDateTime('LAST-MODIFIED', 'now', Sabre_VObject_Property_DateTime::UTC);
+$vevent->setDateTime('DTSTAMP', 'now', Sabre_VObject_Property_DateTime::UTC);
 
 $result = OC_Calendar_Object::edit($id, $vcalendar->serialize());
 $lastmodified = $vevent->__get('LAST-MODIFIED')->getDateTime();
-OC_JSON::success(array('lastmodified'=>(int)$lastmodified->format('U')));
+OCP\JSON::success(array('lastmodified'=>(int)$lastmodified->format('U')));
diff --git a/apps/calendar/ajax/event/new.form.php b/apps/calendar/ajax/event/new.form.php
old mode 100644
new mode 100755
index 838002a3a09e62edec9a4e2c8021db9e2efcec5e..42cdb81642e298925013594a61d74384381fabf9
--- a/apps/calendar/ajax/event/new.form.php
+++ b/apps/calendar/ajax/event/new.form.php
@@ -6,15 +6,15 @@
  * See the COPYING-README file.
  */
 
-require_once('../../../../lib/base.php');
+ 
 
-if(!OC_USER::isLoggedIn()) {
+if(!OCP\User::isLoggedIn()) {
 	die('<script type="text/javascript">document.location = oc_webroot;</script>');
 }
-OC_JSON::checkAppEnabled('calendar');
+OCP\JSON::checkAppEnabled('calendar');
 
 if (!isset($_POST['start'])){
-	OC_JSON::error();
+	OCP\JSON::error();
 	die;
 }
 $start = $_POST['start'];
@@ -22,16 +22,16 @@ $end = $_POST['end'];
 $allday = $_POST['allday'];
 
 if (!$end){
-	$duration = OC_Preferences::getValue( OC_User::getUser(), 'calendar', 'duration', '60');
+	$duration = OCP\Config::getUserValue( OCP\USER::getUser(), 'calendar', 'duration', '60');
 	$end = $start + ($duration * 60);
 }
 $start = new DateTime('@'.$start);
 $end = new DateTime('@'.$end);
-$timezone = OC_Preferences::getValue(OC_USER::getUser(), 'calendar', 'timezone', date_default_timezone_get());
+$timezone = OCP\Config::getUserValue(OCP\USER::getUser(), 'calendar', 'timezone', date_default_timezone_get());
 $start->setTimezone(new DateTimeZone($timezone));
 $end->setTimezone(new DateTimeZone($timezone));
 
-$calendar_options = OC_Calendar_Calendar::allCalendars(OC_User::getUser());
+$calendar_options = OC_Calendar_Calendar::allCalendars(OCP\USER::getUser());
 $repeat_options = OC_Calendar_App::getRepeatOptions();
 $repeat_end_options = OC_Calendar_App::getEndOptions();
 $repeat_month_options = OC_Calendar_App::getMonthOptions();
@@ -44,6 +44,7 @@ $repeat_byweekno_options = OC_Calendar_App::getByWeekNoOptions();
 $repeat_bymonthday_options = OC_Calendar_App::getByMonthDayOptions();
 
 $tmpl = new OC_Template('calendar', 'part.newevent');
+$tmpl->assign('access', 'owner');
 $tmpl->assign('calendar_options', $calendar_options);
 $tmpl->assign('repeat_options', $repeat_options);
 $tmpl->assign('repeat_month_options', $repeat_month_options);
diff --git a/apps/calendar/ajax/event/new.php b/apps/calendar/ajax/event/new.php
old mode 100644
new mode 100755
index 59fda79da731c7be2847406e4fe2f687649e26b7..72d57be03bfb204a7d8b912b25dea94467d01192
--- a/apps/calendar/ajax/event/new.php
+++ b/apps/calendar/ajax/event/new.php
@@ -6,22 +6,20 @@
  * See the COPYING-README file.
  */
 
-require_once('../../../../lib/base.php');
+ 
 
-$l10n = new OC_L10N('calendar');
-
-OC_JSON::checkLoggedIn();
-OC_JSON::checkAppEnabled('calendar');
+OCP\JSON::checkLoggedIn();
+OCP\JSON::checkAppEnabled('calendar');
 
 $errarr = OC_Calendar_Object::validateRequest($_POST);
 if($errarr){
 	//show validate errors
-	OC_JSON::error($errarr);
+	OCP\JSON::error($errarr);
 	exit;
 }else{
 	$cal = $_POST['calendar'];
 	$vcalendar = OC_Calendar_Object::createVCalendarFromRequest($_POST);
 	$result = OC_Calendar_Object::add($cal, $vcalendar->serialize());
-	OC_JSON::success();
+	OCP\JSON::success();
 }
 ?>
diff --git a/apps/calendar/ajax/event/resize.php b/apps/calendar/ajax/event/resize.php
old mode 100644
new mode 100755
index aa2d420e77d595d5b8ade1288f79b1576ccfb3d2..0dc0a5fca7f800d7aca138fedb55a814921d2473
--- a/apps/calendar/ajax/event/resize.php
+++ b/apps/calendar/ajax/event/resize.php
@@ -5,12 +5,18 @@
  * later.
  * See the COPYING-README file.
  */
-require_once('../../../../lib/base.php');
-OC_JSON::checkLoggedIn();
+ 
+OCP\JSON::checkLoggedIn();
 
 $id = $_POST['id'];
 
-$vcalendar = OC_Calendar_App::getVCalendar($id);
+$access = OC_Calendar_App::getaccess($id, OC_Calendar_App::EVENT);
+if($access != 'owner' && $access != 'rw'){
+	OCP\JSON::error(array('message'=>'permission denied'));
+	exit;
+}
+
+$vcalendar = OC_Calendar_App::getVCalendar($id, false, false);
 $vevent = $vcalendar->VEVENT;
 
 $delta = new DateInterval('P0D');
@@ -24,9 +30,9 @@ $end_type = $dtend->getDateType();
 $dtend->setDateTime($dtend->getDateTime()->add($delta), $end_type);
 unset($vevent->DURATION);
 
-$vevent->setDateTime('LAST-MODIFIED', 'now', Sabre_VObject_Element_DateTime::UTC);
-$vevent->setDateTime('DTSTAMP', 'now', Sabre_VObject_Element_DateTime::UTC);
+$vevent->setDateTime('LAST-MODIFIED', 'now', Sabre_VObject_Property_DateTime::UTC);
+$vevent->setDateTime('DTSTAMP', 'now', Sabre_VObject_Property_DateTime::UTC);
 
-$result = OC_Calendar_Object::edit($id, $vcalendar->serialize());
+OC_Calendar_Object::edit($id, $vcalendar->serialize());
 $lastmodified = $vevent->__get('LAST-MODIFIED')->getDateTime();
-OC_JSON::success(array('lastmodified'=>(int)$lastmodified->format('U')));
+OCP\JSON::success(array('lastmodified'=>(int)$lastmodified->format('U')));
diff --git a/apps/calendar/ajax/events.php b/apps/calendar/ajax/events.php
index c62f93c540eb484253ec39c5e564b72e0fb9a4a3..b86620329e3e6d73e76cf6097b7f62a29f96a0c9 100755
--- a/apps/calendar/ajax/events.php
+++ b/apps/calendar/ajax/events.php
@@ -1,109 +1,24 @@
 <?php
 /**
- * Copyright (c) 2011 Georg Ehrke <ownclouddev at georgswebsite dot de>
+ * Copyright (c) 2011, 2012 Georg Ehrke <ownclouddev at georgswebsite dot de>
  * This file is licensed under the Affero General Public License version 3 or
  * later.
  * See the COPYING-README file.
  */
 
-require_once ('../../../lib/base.php');
+ 
 require_once('when/When.php');
-$l = new OC_L10N('calendar');
-$unnamed = $l->t('unnamed');
-function create_return_event($event, $vevent){
-	$return_event = array();
-	global $unnamed;
-	$return_event['id'] = (int)$event['id'];
-	$return_event['title'] = htmlspecialchars(($event['summary']!=NULL || $event['summary'] != '')?$event['summary']: $unnamed);
-	$return_event['description'] = isset($vevent->DESCRIPTION)?htmlspecialchars($vevent->DESCRIPTION->value):'';
-	$last_modified = $vevent->__get('LAST-MODIFIED');
-	if ($last_modified){
-		$lastmodified = $last_modified->getDateTime()->format('U');
-	}else{
-		$lastmodified = 0;
-	}
-	$return_event['lastmodified'] = (int)$lastmodified;
-	return $return_event;
-}
 
-OC_JSON::checkLoggedIn();
-OC_JSON::checkAppEnabled('calendar');
+OCP\JSON::checkLoggedIn();
+OCP\JSON::checkAppEnabled('calendar');
 
-if(version_compare(PHP_VERSION, '5.3.0', '>=')){
-	$start = DateTime::createFromFormat('U', $_GET['start']);
-	$end = DateTime::createFromFormat('U', $_GET['end']);
-}else{
-	$start = new DateTime('@' . $_GET['start']);
-	$end = new DateTime('@' . $_GET['end']);
-}
+$start = (version_compare(PHP_VERSION, '5.3.0', '>='))?DateTime::createFromFormat('U', $_GET['start']):new DateTime('@' . $_GET['start']);
+$end = (version_compare(PHP_VERSION, '5.3.0', '>='))?DateTime::createFromFormat('U', $_GET['end']):new DateTime('@' . $_GET['end']);
 
-$calendar_id = $_GET['calendar_id'];
-if (is_numeric($calendar_id)) {
-	$calendar = OC_Calendar_App::getCalendar($calendar_id);
-	OC_Response::enableCaching(0);
-	OC_Response::setETagHeader($calendar['ctag']);
-	$events = OC_Calendar_Object::allInPeriod($calendar_id, $start, $end);
-} else {
-	$events = array();
-	OC_Hook::emit('OC_Calendar', 'getEvents', array('calendar_id' => $calendar_id, 'events' => &$events));
-}
+$events = OC_Calendar_App::getrequestedEvents($_GET['calendar_id'], $start, $end);
 
-$user_timezone = OC_Preferences::getValue(OC_USER::getUser(), 'calendar', 'timezone', date_default_timezone_get());
-$return = array();
+$output = array();
 foreach($events as $event){
-	if (isset($event['calendardata'])) {
-		$object = OC_VObject::parse($event['calendardata']);
-		$vevent = $object->VEVENT;
-	} else {
-		$vevent = $event['vevent'];
-	}
-
-	$return_event = create_return_event($event, $vevent);
-
-	$dtstart = $vevent->DTSTART;
-	$start_dt = $dtstart->getDateTime();
-	$dtend = OC_Calendar_Object::getDTEndFromVEvent($vevent);
-	$end_dt = $dtend->getDateTime();
-	if ($dtstart->getDateType() == Sabre_VObject_Element_DateTime::DATE){
-		$return_event['allDay'] = true;
-	}else{
-		$return_event['allDay'] = false;
-		$start_dt->setTimezone(new DateTimeZone($user_timezone));
-		$end_dt->setTimezone(new DateTimeZone($user_timezone));
-	}
-
-	//Repeating Events
-	if($event['repeating'] == 1){
-		$duration = (double) $end_dt->format('U') - (double) $start_dt->format('U');
-		$r = new When();
-		$r->recur($start_dt)->rrule((string) $vevent->RRULE);
-		while($result = $r->next()){
-			if($result < $start){
-				continue;
-			}
-			if($result > $end){
-				break;
-			}
-			if($return_event['allDay'] == true){
-				$return_event['start'] = $result->format('Y-m-d');
-				$return_event['end'] = date('Y-m-d', $result->format('U') + --$duration);
-			}else{
-				$return_event['start'] = $result->format('Y-m-d H:i:s');
-				$return_event['end'] = date('Y-m-d H:i:s', $result->format('U') + $duration);
-			}
-			$return[] = $return_event;
-		}
-	}else{
-		if($return_event['allDay'] == true){
-			$return_event['start'] = $start_dt->format('Y-m-d');
-			$end_dt->modify('-1 sec');
-			$return_event['end'] = $end_dt->format('Y-m-d');
-		}else{
-			$return_event['start'] = $start_dt->format('Y-m-d H:i:s');
-			$return_event['end'] = $end_dt->format('Y-m-d H:i:s');
-		}
-		$return[] = $return_event;
-	}
+	$output = $output + OC_Calendar_App::generateEventOutput($event, $start, $end);
 }
-OC_JSON::encodedPrint($return);
-?>
+OCP\JSON::encodedPrint($output);
diff --git a/apps/calendar/ajax/import/dialog.php b/apps/calendar/ajax/import/dialog.php
old mode 100644
new mode 100755
index 2e0020921505d3f72539eaee56e15d7d4ef9c1ea..e686066a993a852b884366dba56c1823a8d0105f
--- a/apps/calendar/ajax/import/dialog.php
+++ b/apps/calendar/ajax/import/dialog.php
@@ -6,10 +6,9 @@
  * See the COPYING-README file.
  */
 
-require_once('../../../../lib/base.php');
-OC_JSON::checkLoggedIn();
-OC_Util::checkAppEnabled('calendar');
-$l10n = new OC_L10N('calendar');
+ 
+OCP\JSON::checkLoggedIn();
+OCP\App::checkAppEnabled('calendar');
 $tmpl = new OC_Template('calendar', 'part.import');
 $tmpl->assign('path', $_POST['path']);
 $tmpl->assign('filename', $_POST['filename']);
diff --git a/apps/calendar/ajax/import/import.php b/apps/calendar/ajax/import/import.php
old mode 100644
new mode 100755
index d0bdab4f0d508a13cb219c4cacd9e50032bdb8ee..202af1eb46e02e3026eb8b929876ebf1d75a9cc5
--- a/apps/calendar/ajax/import/import.php
+++ b/apps/calendar/ajax/import/import.php
@@ -7,11 +7,11 @@
  */
 //check for calendar rights or create new one
 ob_start();
-require_once('../../../../lib/base.php');
-OC_JSON::checkLoggedIn();
-OC_Util::checkAppEnabled('calendar');
-$nl = "\n\r";
-$progressfile = OC::$APPSROOT . '/apps/calendar/import_tmp/' . md5(session_id()) . '.txt';
+OCP\JSON::checkLoggedIn();
+OCP\App::checkAppEnabled('calendar');
+$nl="\r\n";
+$comps = array('VEVENT'=>true, 'VTODO'=>true, 'VJOURNAL'=>true);
+$progressfile = 'import_tmp/' . md5(session_id()) . '.txt';
 if(is_writable('import_tmp/')){
 	$progressfopen = fopen($progressfile, 'w');
 	fwrite($progressfopen, '10');
@@ -19,95 +19,104 @@ if(is_writable('import_tmp/')){
 }
 $file = OC_Filesystem::file_get_contents($_POST['path'] . '/' . $_POST['file']);
 if($_POST['method'] == 'new'){
-	$id = OC_Calendar_Calendar::addCalendar(OC_User::getUser(), $_POST['calname']);
+	$id = OC_Calendar_Calendar::addCalendar(OCP\USER::getUser(), $_POST['calname']);
 	OC_Calendar_Calendar::setCalendarActive($id, 1);
 }else{
 	$calendar = OC_Calendar_App::getCalendar($_POST['id']);
-	if($calendar['userid'] != OC_USER::getUser()){
-		OC_JSON::error();
+	if($calendar['userid'] != OCP\USER::getUser()){
+		OCP\JSON::error();
 		exit();
 	}
 	$id = $_POST['id'];
 }
-//analyse the calendar file
 if(is_writable('import_tmp/')){
 	$progressfopen = fopen($progressfile, 'w');
 	fwrite($progressfopen, '20');
 	fclose($progressfopen);
 }
-$searchfor = array('VEVENT', 'VTODO', 'VJOURNAL');
-$parts = $searchfor;
-$filearr = explode($nl, $file);
-$inelement = false;
-$parts = array();
+// normalize the newlines
+$file = str_replace(array("\r","\n\n"), array("\n","\n"), $file);
+$lines = explode("\n", $file);
+unset($file);
+if(is_writable('import_tmp/')){
+	$progressfopen = fopen($progressfile, 'w');
+	fwrite($progressfopen, '30');
+	fclose($progressfopen);
+}
+// analyze the file, group components by uid, and keep refs to originating calendar object
+// $cals is array calendar objects, keys are 1st line# $cal, ie array( $cal => $caldata )
+//   $caldata is array( 'first' => 1st component line#, 'last' => last comp line#, 'end' => end line# )
+//   $caldata is used to create prefix/suffix strings when building import text
+// $uids is array of component arrays, keys are $uid, ie array( $uid => array( $beginlineno => $component ) )
+//   $component is array( 'end' => end line#, 'cal'=> $cal )
+$comp=$uid=$cal=false;
+$cals=$uids=array();
 $i = 0;
-foreach($filearr as $line){
-	foreach($searchfor as $search){
-		if(substr_count($line, $search) == 1){
-			list($attr, $val) = explode(':', $line);
-			if($attr == 'BEGIN'){
-				$parts[]['begin'] = $i;
-				$inelement = true;
+foreach($lines as $line) {
+
+	if(strpos($line, ':')!==false) {
+		list($attr, $val) = explode(':', strtoupper($line));
+		if ($attr == 'BEGIN' && $val == 'VCALENDAR') {
+			$cal = $i;
+			$cals[$cal] = array('first'=>$i,'last'=>$i,'end'=>$i);
+		} elseif ($attr =='BEGIN' && $cal!==false && isset($comps[$val])) {
+			$comp = $val;
+			$beginNo = $i;
+		} elseif ($attr == 'END' && $cal!==false && $val == 'VCALENDAR') {
+			if($comp!==false) {
+				unset($cals[$cal]); // corrupt calendar, unset it
+			} else {
+				$cals[$cal]['end'] = $i;
+			}
+			$comp=$uid=$cal=false; // reset calendar
+		} elseif ($attr == 'END' && $comp!==false && $val == $comp) {
+			if(! $uid) {
+				$uid = OC_Calendar_Object::createUID();
 			}
-			if($attr == 'END'){
-				$parts[count($parts) - 1]['end'] = $i;
-				$inelement = false;
+			$uids[$uid][$beginNo] = array('end'=>$i, 'cal'=>$cal);
+			if ($cals[$cal]['first'] == $cal) {
+				$cals[$cal]['first'] = $beginNo;
 			}
+			$cals[$cal]['last'] = $i;
+			$comp=$uid=false; // reset component
+		} elseif ($attr =="UID" && $comp!==false) {
+			list($attr, $uid) = explode(':', $line);
 		}
 	}
 	$i++;
 }
-//import the calendar
+// import the calendar
 if(is_writable('import_tmp/')){
 	$progressfopen = fopen($progressfile, 'w');
-	fwrite($progressfopen, '40');
+	fwrite($progressfopen, '60');
 	fclose($progressfopen);
 }
-$start = '';
-for ($i = 0; $i < $parts[0]['begin']; $i++) { 
-	if($i == 0){
-		$start = $filearr[0];
-	}else{
-		$start .= $nl . $filearr[$i];
-	}
-}
-$end = '';
-for($i = $parts[count($parts) - 1]['end'] + 1;$i <= count($filearr) - 1; $i++){
-	if($i == $parts[count($parts) - 1]['end'] + 1){
-		$end = $filearr[$parts[count($parts) - 1]['end'] + 1];
-	}else{
-		$end .= $nl . $filearr[$i];
-	}
-}
-if(is_writable('import_tmp/')){
-	$progressfopen = fopen($progressfile, 'w');
-	fwrite($progressfopen, '50');
-	fclose($progressfopen);
-}
-$importready = array();
-foreach($parts as $part){
-	for($i = $part['begin']; $i <= $part['end'];$i++){
-		if($i == $part['begin']){
-			$content = $filearr[$i];
-		}else{
-			$content .= $nl . $filearr[$i];
+foreach($uids as $uid) {
+	
+	$prefix=$suffix=$content=array();
+	foreach($uid as $begin=>$details) {
+		
+		$cal = $details['cal'];
+		if(!isset($cals[$cal])) {
+			continue; // from corrupt/incomplete calendar
+		}
+		$cdata = $cals[$cal];
+		// if we have multiple components from different calendar objects,
+		// we should really merge their elements (enhancement?) -- 1st one wins for now.
+		if(! count($prefix)) {
+			$prefix = array_slice($lines, $cal, $cdata['first'] - $cal);
 		}
+		if(! count($suffix)) {
+			$suffix = array_slice($lines, $cdata['last']+1, $cdata['end'] - $cdata['last']);
+		}
+		$content = array_merge($content, array_slice($lines, $begin, $details['end'] - $begin + 1));
 	}
-	$importready[] = $start . $nl . $content . $nl . $end;
-}
-if(is_writable('import_tmp/')){
-	$progressfopen = fopen($progressfile, 'w');
-	fwrite($progressfopen, '70');
-	fclose($progressfopen);
-}
-if(count($parts) == 1){
-	OC_Calendar_Object::add($id, $file);
-}else{
-	foreach($importready as $import){
+	if(count($content)) {
+		$import = join($nl, array_merge($prefix, $content, $suffix)) . $nl;
 		OC_Calendar_Object::add($id, $import);
 	}
 }
-//done the import
+// finished import
 if(is_writable('import_tmp/')){
 	$progressfopen = fopen($progressfile, 'w');
 	fwrite($progressfopen, '100');
@@ -117,4 +126,4 @@ sleep(3);
 if(is_writable('import_tmp/')){
 	unlink($progressfile);
 }
-OC_JSON::success();
+OCP\JSON::success();
diff --git a/apps/calendar/ajax/settings/getfirstday.php b/apps/calendar/ajax/settings/getfirstday.php
old mode 100644
new mode 100755
index cab5870509a3718c598beee612987dfc7a8665c1..23b71bba043b3b150fdd4acfb6eed31247aa7b46
--- a/apps/calendar/ajax/settings/getfirstday.php
+++ b/apps/calendar/ajax/settings/getfirstday.php
@@ -5,8 +5,8 @@
  * later.
  * See the COPYING-README file.
  */
-require_once('../../../../lib/base.php');
-OC_JSON::checkLoggedIn();
-$firstday = OC_Preferences::getValue( OC_User::getUser(), 'calendar', 'firstday', 'mo');
-OC_JSON::encodedPrint(array('firstday' => $firstday));
+ 
+OCP\JSON::checkLoggedIn();
+$firstday = OCP\Config::getUserValue( OCP\USER::getUser(), 'calendar', 'firstday', 'mo');
+OCP\JSON::encodedPrint(array('firstday' => $firstday));
 ?> 
diff --git a/apps/calendar/ajax/settings/gettimezonedetection.php b/apps/calendar/ajax/settings/gettimezonedetection.php
old mode 100644
new mode 100755
index 11255fe8ef386739105d36fe99838ba729032bfe..6bc9a07a1e97a5f6cd3aa66ef1384e0c3aaf492d
--- a/apps/calendar/ajax/settings/gettimezonedetection.php
+++ b/apps/calendar/ajax/settings/gettimezonedetection.php
@@ -5,7 +5,7 @@
  * later.
  * See the COPYING-README file.
  */
-require_once('../../../../lib/base.php');
-OC_JSON::checkLoggedIn();
-OC_JSON::checkAppEnabled('calendar');
-OC_JSON::success(array('detection' => OC_Preferences::getValue(OC_USER::getUser(), 'calendar', 'timezonedetection')));
\ No newline at end of file
+ 
+OCP\JSON::checkLoggedIn();
+OCP\JSON::checkAppEnabled('calendar');
+OCP\JSON::success(array('detection' => OCP\Config::getUserValue(OCP\USER::getUser(), 'calendar', 'timezonedetection')));
\ No newline at end of file
diff --git a/apps/calendar/ajax/settings/guesstimezone.php b/apps/calendar/ajax/settings/guesstimezone.php
index d45a70e1ce304d16375e1d7d7e8ed1e05cc6c870..13092777b78bdf54c9dc92850dfbb4a4b6dd7b2a 100755
--- a/apps/calendar/ajax/settings/guesstimezone.php
+++ b/apps/calendar/ajax/settings/guesstimezone.php
@@ -5,23 +5,23 @@
  * later.
  * See the COPYING-README file.
  */
-require_once('../../../../lib/base.php');
+ 
 
-OC_JSON::checkLoggedIn();
-OC_JSON::checkAppEnabled('calendar');
+OCP\JSON::checkLoggedIn();
+OCP\JSON::checkAppEnabled('calendar');
 
-$l = new OC_L10N('calendar');
+$l = OC_L10N::get('calendar');
 
 $lat = $_GET['lat'];
 $lng = $_GET['long'];
 
 $timezone =  OC_Geo::timezone($lat, $lng);
 
-if($timezone == OC_Preferences::getValue(OC_USER::getUser(), 'calendar', 'timezone')){
-	OC_JSON::success();
+if($timezone == OCP\Config::getUserValue(OCP\USER::getUser(), 'calendar', 'timezone')){
+	OCP\JSON::success();
 	exit;
 }
-OC_Preferences::setValue(OC_USER::getUser(), 'calendar', 'timezone', $timezone);
+OCP\Config::setUserValue(OCP\USER::getUser(), 'calendar', 'timezone', $timezone);
 $message = array('message'=> $l->t('New Timezone:') . $timezone);
-OC_JSON::success($message);
+OCP\JSON::success($message);
 ?>
\ No newline at end of file
diff --git a/apps/calendar/ajax/settings/setfirstday.php b/apps/calendar/ajax/settings/setfirstday.php
old mode 100644
new mode 100755
index 3b6522122059598ac64f545e75e92fec9888e684..373eeee796838ad8f1cebba4de35461d67dd737d
--- a/apps/calendar/ajax/settings/setfirstday.php
+++ b/apps/calendar/ajax/settings/setfirstday.php
@@ -5,13 +5,13 @@
  * later.
  * See the COPYING-README file.
  */
-require_once('../../../../lib/base.php');
-OC_JSON::checkLoggedIn();
+ 
+OCP\JSON::checkLoggedIn();
 if(isset($_POST["firstday"])){
-	OC_Preferences::setValue(OC_User::getUser(), 'calendar', 'firstday', $_POST["firstday"]);
-	OC_JSON::success();
+	OCP\Config::setUserValue(OCP\USER::getUser(), 'calendar', 'firstday', $_POST["firstday"]);
+	OCP\JSON::success();
 }else{
-	OC_JSON::error();
+	OCP\JSON::error();
 }
 ?> 
  
diff --git a/apps/calendar/ajax/settings/settimeformat.php b/apps/calendar/ajax/settings/settimeformat.php
old mode 100644
new mode 100755
index 8f65447065c1deb22908bcf23b68d23a5bb0a358..eae7be54e80ed2740b3b044f26bb866061fbd27e
--- a/apps/calendar/ajax/settings/settimeformat.php
+++ b/apps/calendar/ajax/settings/settimeformat.php
@@ -5,13 +5,13 @@
  * later.
  * See the COPYING-README file.
  */
-require_once('../../../../lib/base.php');
-OC_JSON::checkLoggedIn();
+ 
+OCP\JSON::checkLoggedIn();
 if(isset($_POST["timeformat"])){
-	OC_Preferences::setValue(OC_User::getUser(), 'calendar', 'timeformat', $_POST["timeformat"]);
-	OC_JSON::success();
+	OCP\Config::setUserValue(OCP\USER::getUser(), 'calendar', 'timeformat', $_POST["timeformat"]);
+	OCP\JSON::success();
 }else{
-	OC_JSON::error();
+	OCP\JSON::error();
 }
 ?> 
  
diff --git a/apps/calendar/ajax/settings/settimezone.php b/apps/calendar/ajax/settings/settimezone.php
old mode 100644
new mode 100755
index c639753fe2fe14f34ba59e67babf37ecb6212d64..d2797a08aae6525769183050982926dcfec939f3
--- a/apps/calendar/ajax/settings/settimezone.php
+++ b/apps/calendar/ajax/settings/settimezone.php
@@ -7,21 +7,21 @@
  */
 
 // Init owncloud
-require_once('../../../../lib/base.php');
+ 
 
-$l=new OC_L10N('calendar');
+$l=OC_L10N::get('calendar');
 
 // Check if we are a user
-OC_JSON::checkLoggedIn();
-OC_JSON::checkAppEnabled('calendar');
+OCP\JSON::checkLoggedIn();
+OCP\JSON::checkAppEnabled('calendar');
 
 // Get data
 if( isset( $_POST['timezone'] ) ){
 	$timezone=$_POST['timezone'];
-	OC_Preferences::setValue( OC_User::getUser(), 'calendar', 'timezone', $timezone );
-	OC_JSON::success(array('data' => array( 'message' => $l->t('Timezone changed') )));
+	OCP\Config::setUserValue( OCP\USER::getUser(), 'calendar', 'timezone', $timezone );
+	OCP\JSON::success(array('data' => array( 'message' => $l->t('Timezone changed') )));
 }else{
-	OC_JSON::error(array('data' => array( 'message' => $l->t('Invalid request') )));
+	OCP\JSON::error(array('data' => array( 'message' => $l->t('Invalid request') )));
 }
 
 ?>
diff --git a/apps/calendar/ajax/settings/timeformat.php b/apps/calendar/ajax/settings/timeformat.php
old mode 100644
new mode 100755
index e0dbe8d3cd7b8631d6780434eb532e0fd7afaf5f..809164e870a50b5788fd9bbbf4a2c02eece349f2
--- a/apps/calendar/ajax/settings/timeformat.php
+++ b/apps/calendar/ajax/settings/timeformat.php
@@ -5,8 +5,8 @@
  * later.
  * See the COPYING-README file.
  */
-require_once('../../../../lib/base.php');
-OC_JSON::checkLoggedIn();
-$timeformat = OC_Preferences::getValue( OC_User::getUser(), 'calendar', 'timeformat', "24");
-OC_JSON::encodedPrint(array("timeformat" => $timeformat));
+ 
+OCP\JSON::checkLoggedIn();
+$timeformat = OCP\Config::getUserValue( OCP\USER::getUser(), 'calendar', 'timeformat', "24");
+OCP\JSON::encodedPrint(array("timeformat" => $timeformat));
 ?> 
diff --git a/apps/calendar/ajax/settings/timezonedetection.php b/apps/calendar/ajax/settings/timezonedetection.php
old mode 100644
new mode 100755
index f67bab901e7e6197f30360a8f32d6ed17cf2f955..ba5f2af5fd98d1aabb52c1f8934103c88dd7f09a
--- a/apps/calendar/ajax/settings/timezonedetection.php
+++ b/apps/calendar/ajax/settings/timezonedetection.php
@@ -5,13 +5,16 @@
  * later.
  * See the COPYING-README file.
  */
-require_once('../../../../lib/base.php');
-OC_JSON::checkLoggedIn();
-OC_JSON::checkAppEnabled('calendar');
-if($_POST['timezonedetection'] == 'on'){
-	OC_Preferences::setValue(OC_USER::getUser(), 'calendar', 'timezonedetection', 'true');
+ 
+OCP\JSON::checkLoggedIn();
+OCP\JSON::checkAppEnabled('calendar');
+if(array_key_exists('timezonedetection', $_POST)){
+	if($_POST['timezonedetection'] == 'on'){
+		OCP\Config::setUserValue(OCP\USER::getUser(), 'calendar', 'timezonedetection', 'true');
+	}else{
+		OCP\Config::setUserValue(OCP\USER::getUser(), 'calendar', 'timezonedetection', 'false');
+	}
+	OCP\JSON::success();
 }else{
-	OC_Preferences::setValue(OC_USER::getUser(), 'calendar', 'timezonedetection', 'false');
-}
-OC_JSON::success();
-
+	OCP\JSON::error();
+}
\ No newline at end of file
diff --git a/apps/calendar/ajax/share/activation.php b/apps/calendar/ajax/share/activation.php
new file mode 100755
index 0000000000000000000000000000000000000000..5526e5230f49ff487b58b8275ce37ec4a31b4628
--- /dev/null
+++ b/apps/calendar/ajax/share/activation.php
@@ -0,0 +1,12 @@
+<?php
+/**
+ * Copyright (c) 2012 Georg Ehrke <ownclouddev@georgswebsite.de>
+ * This file is licensed under the Affero General Public License version 3 or
+ * later.
+ * See the COPYING-README file.
+ */
+require_once('../../../../lib/base.php');
+$id = strip_tags($_GET['id']);
+$activation = strip_tags($_GET['activation']);
+OC_Calendar_Share::set_active(OCP\USER::getUser(), $id, $activation);
+OCP\JSON::success();
\ No newline at end of file
diff --git a/apps/calendar/ajax/share/changepermission.php b/apps/calendar/ajax/share/changepermission.php
old mode 100644
new mode 100755
index d91f87b613f617487c76dcc5a2a84debd919690d..e4a4f186ab06548457eecb15467e7fd6802b1959
--- a/apps/calendar/ajax/share/changepermission.php
+++ b/apps/calendar/ajax/share/changepermission.php
@@ -5,7 +5,7 @@
  * later.
  * See the COPYING-README file.
  */
-require_once('../../../../lib/base.php');
+ 
 $id = strip_tags($_GET['id']);
 $idtype = strip_tags($_GET['idtype']);
 $permission = (int) strip_tags($_GET['permission']);
@@ -14,7 +14,7 @@ switch($idtype){
 	case 'event':
 		break;
 	default:
-		OC_JSON::error(array('message'=>'unexspected parameter'));
+		OCP\JSON::error(array('message'=>'unexspected parameter'));
 		exit;
 }
 $sharewith = $_GET['sharewith'];
@@ -25,16 +25,16 @@ switch($sharetype){
 	case 'public':
 		break;
 	default:
-		OC_JSON::error(array('message'=>'unexspected parameter'));
+		OCP\JSON::error(array('message'=>'unexspected parameter'));
 		exit;
 }
-if($sharetype == 'user' && !OC_User::userExists($sharewith)){
-	OC_JSON::error(array('message'=>'user not found'));
+if($sharetype == 'user' && !OCP\User::userExists($sharewith)){
+	OCP\JSON::error(array('message'=>'user not found'));
 	exit;
 }
 if($sharetype == 'group' && !OC_Group::groupExists($sharewith)){
-	OC_JSON::error(array('message'=>'group not found'));
+	OCP\JSON::error(array('message'=>'group not found'));
 	exit;
 }
-$success = OC_Calendar_Share::changepermission($sharewith, $sharetype, $id, $permission, (($idtype=='calendar') ? OC_Calendar_Share::CALENDAR : OC_Calendar_Share::Event));
-OC_JSON::success();
\ No newline at end of file
+$success = OC_Calendar_Share::changepermission($sharewith, $sharetype, $id, $permission, (($idtype=='calendar') ? OC_Calendar_Share::CALENDAR : OC_Calendar_Share::EVENT));
+OCP\JSON::success();
\ No newline at end of file
diff --git a/apps/calendar/ajax/share/dropdown.php b/apps/calendar/ajax/share/dropdown.php
old mode 100644
new mode 100755
index eb396d38fd9f067c562b8e449c659852bfc28499..bac487f0d0bf6c267d4cad9e11276476feb8a7d3
--- a/apps/calendar/ajax/share/dropdown.php
+++ b/apps/calendar/ajax/share/dropdown.php
@@ -5,12 +5,12 @@
  * later.
  * See the COPYING-README file.
  */
-require_once('../../../../lib/base.php');
-$user = OC_USER::getUser();
+ 
+$user = OCP\USER::getUser();
 $calid = $_GET['calid'];
 $calendar = OC_Calendar_Calendar::find($calid);
 if($calendar['userid'] != $user){
-	OC_JSON::error();
+	OCP\JSON::error();
 	exit;
 }
 $tmpl = new OC_Template('calendar', 'share.dropdown');
diff --git a/apps/calendar/ajax/share/share.php b/apps/calendar/ajax/share/share.php
old mode 100644
new mode 100755
index d892727701a9c5cb7ebc2f2add41af2bacbaef76..3ce2bf1e21756a142d5e07c6bcb9b795577a2cdf
--- a/apps/calendar/ajax/share/share.php
+++ b/apps/calendar/ajax/share/share.php
@@ -5,7 +5,7 @@
  * later.
  * See the COPYING-README file.
  */
-require_once('../../../../lib/base.php');
+ 
 $id = strip_tags($_GET['id']);
 $idtype = strip_tags($_GET['idtype']);
 switch($idtype){
@@ -13,9 +13,17 @@ switch($idtype){
 	case 'event':
 		break;
 	default:
-		OC_JSON::error(array('message'=>'unexspected parameter'));
+		OCP\JSON::error(array('message'=>'unexspected parameter'));
 		exit;
 }
+if($idtype == 'calendar' && !OC_Calendar_App::getCalendar($id)){
+	OCP\JSON::error(array('message'=>'permission denied'));
+	exit;
+}
+if($idtype == 'event' && !OC_Calendar_App::getEventObject($id)){
+	OCP\JSON::error(array('message'=>'permission denied'));
+	exit;
+}
 $sharewith = $_GET['sharewith'];
 $sharetype = strip_tags($_GET['sharetype']);
 switch($sharetype){
@@ -24,28 +32,28 @@ switch($sharetype){
 	case 'public':
 		break;
 	default:
-		OC_JSON::error(array('message'=>'unexspected parameter'));
+		OCP\JSON::error(array('message'=>'unexspected parameter'));
 		exit;
 }
-if($sharetype == 'user' && !OC_User::userExists($sharewith)){
-	OC_JSON::error(array('message'=>'user not found'));
+if($sharetype == 'user' && !OCP\User::userExists($sharewith)){
+	OCP\JSON::error(array('message'=>'user not found'));
 	exit;
 }
 if($sharetype == 'group' && !OC_Group::groupExists($sharewith)){
-	OC_JSON::error(array('message'=>'group not found'));
+	OCP\JSON::error(array('message'=>'group not found'));
 	exit;
 }
-if($sharetype == 'user' && OC_User::getUser() == $sharewith){
-	OC_JSON::error(array('meesage'=>'you can not share with yourself'));
+if($sharetype == 'user' && OCP\USER::getUser() == $sharewith){
+	OCP\JSON::error(array('meesage'=>'you can not share with yourself'));
 }
-$success = OC_Calendar_Share::share(OC_User::getUser(), $sharewith, $sharetype, $id, (($idtype=='calendar') ? OC_Calendar_Share::CALENDAR : OC_Calendar_Share::Event));
+$success = OC_Calendar_Share::share(OCP\USER::getUser(), $sharewith, $sharetype, $id, (($idtype=='calendar') ? OC_Calendar_Share::CALENDAR : OC_Calendar_Share::EVENT));
 if($success){
 	if($sharetype == 'public'){
-		OC_JSON::success(array('message'=>$success));
+		OCP\JSON::success(array('message'=>$success));
 	}else{
-		OC_JSON::success(array('message'=>'shared'));
+		OCP\JSON::success(array('message'=>'shared'));
 	}
 }else{
-	OC_JSON::error(array('message'=>'can not share'));
+	OCP\JSON::error(array('message'=>'can not share'));
 	exit;
 }
\ No newline at end of file
diff --git a/apps/calendar/ajax/share/unshare.php b/apps/calendar/ajax/share/unshare.php
old mode 100644
new mode 100755
index ec3150a89aa882040f2a9ad5a5bbdcde4d49ba1e..cbd5ed8e505bbe8c511e919578316be2c8a2c49d
--- a/apps/calendar/ajax/share/unshare.php
+++ b/apps/calendar/ajax/share/unshare.php
@@ -5,7 +5,7 @@
  * later.
  * See the COPYING-README file.
  */
-require_once('../../../../lib/base.php');
+ 
 $id = strip_tags($_GET['id']);
 $idtype = strip_tags($_GET['idtype']);
 switch($idtype){
@@ -13,7 +13,7 @@ switch($idtype){
 	case 'event':
 		break;
 	default:
-		OC_JSON::error(array('message'=>'unexspected parameter'));
+		OCP\JSON::error(array('message'=>'unexspected parameter'));
 		exit;
 }
 $sharewith = $_GET['sharewith'];
@@ -24,21 +24,20 @@ switch($sharetype){
 	case 'public':
 		break;
 	default:
-		OC_JSON::error(array('message'=>'unexspected parameter'));
+		OCP\JSON::error(array('message'=>'unexspected parameter'));
 		exit;
 }
-if($sharetype == 'user' && !OC_User::userExists($sharewith)){
-	OC_JSON::error(array('message'=>'user not found'));
+if($sharetype == 'user' && !OCP\User::userExists($sharewith)){
+	OCP\JSON::error(array('message'=>'user not found'));
 	exit;
-}
-if($sharetype == 'group' && !OC_Group::groupExists($sharewith)){
-	OC_JSON::error(array('message'=>'group not found'));
+}elseif($sharetype == 'group' && !OC_Group::groupExists($sharewith)){
+	OCP\JSON::error(array('message'=>'group not found'));
 	exit;
 }
-$success = OC_Calendar_Share::unshare(OC_User::getUser(), $sharewith, $sharetype, $id, (($idtype=='calendar') ? OC_Calendar_Share::CALENDAR : OC_Calendar_Share::Event));
+$success = OC_Calendar_Share::unshare(OCP\USER::getUser(), $sharewith, $sharetype, $id, (($idtype=='calendar') ? OC_Calendar_Share::CALENDAR : OC_Calendar_Share::EVENT));
 if($success){
-	OC_JSON::success();
+	OCP\JSON::success();
 }else{
-	OC_JSON::error(array('message'=>'can not unshare'));
+	OCP\JSON::error(array('message'=>'can not unshare'));
 	exit;
 }
\ No newline at end of file
diff --git a/apps/calendar/appinfo/app.php b/apps/calendar/appinfo/app.php
old mode 100644
new mode 100755
index f297c4d16d4eac5dfa705cef089b4f12f6f83b7f..7b5db834fb5838ca4bd050b8a2510b6fa13edc8a
--- a/apps/calendar/appinfo/app.php
+++ b/apps/calendar/appinfo/app.php
@@ -1,23 +1,25 @@
 <?php
-$l=new OC_L10N('calendar');
+$l=OC_L10N::get('calendar');
 OC::$CLASSPATH['OC_Calendar_App'] = 'apps/calendar/lib/app.php';
 OC::$CLASSPATH['OC_Calendar_Calendar'] = 'apps/calendar/lib/calendar.php';
 OC::$CLASSPATH['OC_Calendar_Object'] = 'apps/calendar/lib/object.php';
 OC::$CLASSPATH['OC_Calendar_Hooks'] = 'apps/calendar/lib/hooks.php';
 OC::$CLASSPATH['OC_Connector_Sabre_CalDAV'] = 'apps/calendar/lib/connector_sabre.php';
+OC::$CLASSPATH['OC_Calendar_Share'] = 'apps/calendar/lib/share.php';
 OC::$CLASSPATH['OC_Search_Provider_Calendar'] = 'apps/calendar/lib/search.php';
 OC_HOOK::connect('OC_User', 'post_deleteUser', 'OC_Calendar_Hooks', 'deleteUser');
-OC_Hook::connect('OC_DAV', 'initialize', 'OC_Calendar_Hooks', 'initializeCalDAV');
-OC_Util::addScript('calendar','loader');
-OC_App::register( array(
+OCP\Util::addscript('calendar','loader');
+OCP\Util::addscript("3rdparty", "chosen/chosen.jquery.min");
+OCP\Util::addStyle("3rdparty", "chosen/chosen");
+OCP\App::register( array(
   'order' => 10,
   'id' => 'calendar',
   'name' => 'Calendar' ));
-OC_App::addNavigationEntry( array(
+OCP\App::addNavigationEntry( array(
   'id' => 'calendar_index',
   'order' => 10,
-  'href' => OC_Helper::linkTo( 'calendar', 'index.php' ),
-  'icon' => OC_Helper::imagePath( 'calendar', 'icon.svg' ),
+  'href' => OCP\Util::linkTo( 'calendar', 'index.php' ),
+  'icon' => OCP\Util::imagePath( 'calendar', 'icon.svg' ),
   'name' => $l->t('Calendar')));
-OC_App::registerPersonal('calendar', 'settings');
-OC_Search::registerProvider('OC_Search_Provider_Calendar');
\ No newline at end of file
+OCP\App::registerPersonal('calendar', 'settings');
+OC_Search::registerProvider('OC_Search_Provider_Calendar');
diff --git a/apps/calendar/appinfo/database.xml b/apps/calendar/appinfo/database.xml
index 7f7b6457559c207e779a7c3d70c5084231e25989..b065ab3f94ac49da841a388de98ba3ac15fa0121 100644
--- a/apps/calendar/appinfo/database.xml
+++ b/apps/calendar/appinfo/database.xml
@@ -187,5 +187,107 @@
   </declaration>
 
  </table>
+ 
+ <table>
+
+  <name>*dbprefix*calendar_share_event</name>
+
+  <declaration>
+  
+   <field>
+    <name>owner</name>
+    <type>text</type>
+    <notnull>true</notnull>
+    <length>255</length>
+   </field>
+  
+   <field>
+    <name>share</name>
+    <type>text</type>
+    <notnull>true</notnull>
+    <length>255</length>
+   </field>
+  
+   <field>
+    <name>sharetype</name>
+    <type>text</type>
+    <notnull>true</notnull>
+    <length>6</length>
+   </field>
+
+   <field>
+    <name>eventid</name>
+    <type>integer</type>
+    <default></default>
+    <notnull>true</notnull>
+    <unsigned>true</unsigned>
+    <length>11</length>
+   </field>
+
+   <field>
+    <name>permissions</name>
+    <type>integer</type>
+    <notnull>true</notnull>
+    <length>1</length>
+   </field>
+
+  </declaration>
+
+ </table>
+ 
+ <table>
+
+  <name>*dbprefix*calendar_share_calendar</name>
+
+  <declaration>
+  
+   <field>
+    <name>owner</name>
+    <type>text</type>
+    <notnull>true</notnull>
+    <length>255</length>
+   </field>
+  
+   <field>
+    <name>share</name>
+    <type>text</type>
+    <notnull>true</notnull>
+    <length>255</length>
+   </field>
+  
+   <field>
+    <name>sharetype</name>
+    <type>text</type>
+    <notnull>true</notnull>
+    <length>6</length>
+   </field>
+
+   <field>
+    <name>calendarid</name>
+    <type>integer</type>
+    <default></default>
+    <notnull>true</notnull>
+    <unsigned>true</unsigned>
+    <length>11</length>
+   </field>
+
+   <field>
+    <name>permissions</name>
+    <type>integer</type>
+    <notnull>true</notnull>
+    <length>1</length>
+   </field>
 
+   <field>
+    <name>active</name>
+    <type>integer</type>
+    <default>1</default>
+    <notnull>true</notnull>
+    <length>4</length>
+   </field>
+
+  </declaration>
+
+ </table>
+ 
 </database>
diff --git a/apps/calendar/appinfo/info.xml b/apps/calendar/appinfo/info.xml
index 4ac3c5bf0996db97a1dc307e710fd4341535c5d1..101840aa1fa86f6b30316dc5019e43a7efdf4f15 100644
--- a/apps/calendar/appinfo/info.xml
+++ b/apps/calendar/appinfo/info.xml
@@ -2,7 +2,6 @@
 <info>
 	<id>calendar</id>
 	<name>Calendar</name>
-	<version>0.2.1</version>
 	<licence>AGPL</licence>
 	<author>Georg Ehrke, Bart Visscher, Jakob Sack</author>
 	<require>2</require>
diff --git a/apps/calendar/appinfo/install.php b/apps/calendar/appinfo/install.php
new file mode 100644
index 0000000000000000000000000000000000000000..fc5cd892394e68804ad6391eeee8abd5d95987d6
--- /dev/null
+++ b/apps/calendar/appinfo/install.php
@@ -0,0 +1,4 @@
+<?php
+if(!file_exists(OC::$WEBROOT.'/remote/caldav.php')){
+	file_put_contents(OC::$WEBROOT.'/remote/caldav.php', file_get_contents(OC::$APPSROOT . '/apps/calendar/appinfo/remote.php'));
+}
diff --git a/apps/calendar/caldav.php b/apps/calendar/appinfo/remote.php
old mode 100644
new mode 100755
similarity index 86%
rename from apps/calendar/caldav.php
rename to apps/calendar/appinfo/remote.php
index b710b99ea43bf069cc8cf989e35a1b120b080dd3..32b454ee90ca27e2c2a1187338a65b41d248199a
--- a/apps/calendar/caldav.php
+++ b/apps/calendar/appinfo/remote.php
@@ -5,12 +5,11 @@
  * later.
  * See the COPYING-README file.
  */
-
 // Do not load FS ...
 $RUNTIME_NOSETUPFS = true;
+require_once('../lib/base.php');
 
-require_once('../../lib/base.php');
-OC_Util::checkAppEnabled('calendar');
+OCP\App::checkAppEnabled('calendar');
 
 // Backends
 $authBackend = new OC_Connector_Sabre_Auth();
@@ -25,7 +24,7 @@ $nodes = array(
 
 // Fire up server
 $server = new Sabre_DAV_Server($nodes);
-$server->setBaseUri(OC::$APPSWEBROOT.'/apps/calendar/caldav.php');
+$server->setBaseUri(OC::$WEBROOT.'/remote/caldav.php');
 // Add plugins
 $server->addPlugin(new Sabre_DAV_Auth_Plugin($authBackend,'ownCloud'));
 $server->addPlugin(new Sabre_CalDAV_Plugin());
diff --git a/apps/calendar/appinfo/update.php b/apps/calendar/appinfo/update.php
old mode 100644
new mode 100755
index 375816a403ebc4ce6537fd7d14143b89f7a1bed6..1c0424280891cb2cf5e0c71e4395761eed9ccb48
--- a/apps/calendar/appinfo/update.php
+++ b/apps/calendar/appinfo/update.php
@@ -1,8 +1,8 @@
 <?php
 
-$installedVersion=OC_Appconfig::getValue('calendar', 'installed_version');
+$installedVersion=OCP\Config::getAppValue('calendar', 'installed_version');
 if (version_compare($installedVersion, '0.2.1', '<')) {
-	$stmt = OC_DB::prepare( 'SELECT id, calendarcolor FROM *PREFIX*calendar_calendars WHERE calendarcolor IS NOT NULL' );
+	$stmt = OCP\DB::prepare( 'SELECT id, calendarcolor FROM *PREFIX*calendar_calendars WHERE calendarcolor IS NOT NULL' );
 	$result = $stmt->execute();
 	while( $row = $result->fetchRow()) {
 		$id = $row['id'];
@@ -11,7 +11,10 @@ if (version_compare($installedVersion, '0.2.1', '<')) {
 			continue;
 		}
 		$color = '#' .$color;
-		$stmt = OC_DB::prepare( 'UPDATE *PREFIX*calendar_calendars SET calendarcolor=? WHERE id=?' );
+		$stmt = OCP\DB::prepare( 'UPDATE *PREFIX*calendar_calendars SET calendarcolor=? WHERE id=?' );
 		$r = $stmt->execute(array($color,$id));
 	}
 }
+if(!file_exists(OC::$WEBROOT.'/remote/caldav.php')){
+	file_put_contents(OC::$WEBROOT.'/remote/caldav.php', file_get_contents(OC::$APPROOT . '/apps/calendar/appinfo/remote.php'));
+}
\ No newline at end of file
diff --git a/apps/calendar/appinfo/version b/apps/calendar/appinfo/version
new file mode 100644
index 0000000000000000000000000000000000000000..1d71ef97443918d538e8188167c94d7bbafaf753
--- /dev/null
+++ b/apps/calendar/appinfo/version
@@ -0,0 +1 @@
+0.3
\ No newline at end of file
diff --git a/apps/calendar/css/style.css b/apps/calendar/css/style.css
index cffaf356402d7c43f8b8811c0133e50a8c49777b..373a456563876608810127e9c2c41a25ecb1ad9d 100644
--- a/apps/calendar/css/style.css
+++ b/apps/calendar/css/style.css
@@ -56,6 +56,12 @@ button.category{margin:0 3px;}
 .calendar-colorpicker-color{display:inline-block;width:20px;height:20px;margin-right:2px;cursor:pointer;border:2px solid transparent;}
 .calendar-colorpicker-color.active{border:2px solid black;}
 
+#event {padding: 0;margin: 0;margin-top:-5px}
+
+.calendar_share_dropdown{ display:block;  position:absolute; z-index:100; width:16em; right:0; margin-right:7em; background:#F8F8F8; padding:1em;
+-moz-box-shadow:0 1px 1px #777; -webkit-box-shadow:0 1px 1px #777; box-shadow:0 1px 1px #777;
+-moz-border-radius:0 0 1em 1em; -webkit-border-radius:0 0 1em 1em; border-radius:0 0 1em 1em;}
+
 .fc-list-table
 {
     margin: 10px;
diff --git a/apps/calendar/export.php b/apps/calendar/export.php
old mode 100644
new mode 100755
index 2736eec96c2124e0d9363b30f0aaad6b6bd10fe3..0756e1df20e3cda05b31ff760e28d8c124b1f329
--- a/apps/calendar/export.php
+++ b/apps/calendar/export.php
@@ -6,14 +6,14 @@
  * See the COPYING-README file.
  */
 
-require_once ('../../lib/base.php');
-OC_Util::checkLoggedIn();
-OC_Util::checkAppEnabled('calendar');
+ 
+OCP\User::checkLoggedIn();
+OCP\App::checkAppEnabled('calendar');
 $cal = isset($_GET['calid']) ? $_GET['calid'] : NULL;
 $event = isset($_GET['eventid']) ? $_GET['eventid'] : NULL;
-$nl = "\n\r";
+$nl = "\r\n";
 if(isset($cal)){
-	$calendar = OC_Calendar_App::getCalendar($cal);
+	$calendar = OC_Calendar_App::getCalendar($cal, true);
 	$calobjects = OC_Calendar_Object::all($cal);
 	header('Content-Type: text/Calendar');
 	header('Content-Disposition: inline; filename=' . $calendar['displayname'] . '.ics'); 
@@ -21,7 +21,7 @@ if(isset($cal)){
 		echo $calobject['calendardata'] . $nl;
 	}
 }elseif(isset($event)){
-	$data = OC_Calendar_App::getEventObject($_GET['eventid']);
+	$data = OC_Calendar_App::getEventObject($_GET['eventid'], true);
 	$calendarid = $data['calendarid'];
 	$calendar = OC_Calendar_App::getCalendar($calendarid);
 	header('Content-Type: text/Calendar');
diff --git a/apps/calendar/img/icon.svg b/apps/calendar/img/icon.svg
old mode 100755
new mode 100644
diff --git a/apps/calendar/import.php b/apps/calendar/import.php
deleted file mode 100644
index b1c6f91df8479ea6c15759aaa1367a1fa3923ffc..0000000000000000000000000000000000000000
--- a/apps/calendar/import.php
+++ /dev/null
@@ -1,120 +0,0 @@
-<?php
-/**
- * Copyright (c) 2012 Georg Ehrke <ownclouddev at georgswebsite dot de>
- * This file is licensed under the Affero General Public License version 3 or
- * later.
- * See the COPYING-README file.
- */
-//check for calendar rights or create new one
-ob_start();
-require_once ('../../lib/base.php');
-OC_JSON::checkLoggedIn();
-OC_Util::checkAppEnabled('calendar');
-$nl = "\n";
-$progressfile = 'import_tmp/' . md5(session_id()) . '.txt';
-if(is_writable('import_tmp/')){
-	$progressfopen = fopen($progressfile, 'w');
-	fwrite($progressfopen, '10');
-	fclose($progressfopen);
-}
-$file = OC_Filesystem::file_get_contents($_POST['path'] . '/' . $_POST['file']);
-if($_POST['method'] == 'new'){
-	$id = OC_Calendar_Calendar::addCalendar(OC_User::getUser(), $_POST['calname']);
-	OC_Calendar_Calendar::setCalendarActive($id, 1);
-}else{
-	$calendar = OC_Calendar_App::getCalendar($_POST['id']);
-	if($calendar['userid'] != OC_USER::getUser()){
-		OC_JSON::error();
-		exit();
-	}
-	$id = $_POST['id'];
-}
-//analyse the calendar file
-if(is_writable('import_tmp/')){
-	$progressfopen = fopen($progressfile, 'w');
-	fwrite($progressfopen, '20');
-	fclose($progressfopen);
-}
-$searchfor = array('VEVENT', 'VTODO', 'VJOURNAL');
-$parts = $searchfor;
-$filearr = explode($nl, $file);
-$inelement = false;
-$parts = array();
-$i = 0;
-foreach($filearr as $line){
-	foreach($searchfor as $search){
-		if(substr_count($line, $search) == 1){
-			list($attr, $val) = explode(':', $line);
-			if($attr == 'BEGIN'){
-				$parts[]['begin'] = $i;
-				$inelement = true;
-			}
-			if($attr == 'END'){
-				$parts[count($parts) - 1]['end'] = $i;
-				$inelement = false;
-			}
-		}
-	}
-	$i++;
-}
-//import the calendar
-if(is_writable('import_tmp/')){
-	$progressfopen = fopen($progressfile, 'w');
-	fwrite($progressfopen, '40');
-	fclose($progressfopen);
-}
-$start = '';
-for ($i = 0; $i < $parts[0]['begin']; $i++) { 
-	if($i == 0){
-		$start = $filearr[0];
-	}else{
-		$start .= $nl . $filearr[$i];
-	}
-}
-$end = '';
-for($i = $parts[count($parts) - 1]['end'] + 1;$i <= count($filearr) - 1; $i++){
-	if($i == $parts[count($parts) - 1]['end'] + 1){
-		$end = $filearr[$parts[count($parts) - 1]['end'] + 1];
-	}else{
-		$end .= $nl . $filearr[$i];
-	}
-}
-if(is_writable('import_tmp/')){
-	$progressfopen = fopen($progressfile, 'w');
-	fwrite($progressfopen, '50');
-	fclose($progressfopen);
-}
-$importready = array();
-foreach($parts as $part){
-	for($i = $part['begin']; $i <= $part['end'];$i++){
-		if($i == $part['begin']){
-			$content = $filearr[$i];
-		}else{
-			$content .= $nl . $filearr[$i];
-		}
-	}
-	$importready[] = $start . $nl . $content . $nl . $end;
-}
-if(is_writable('import_tmp/')){
-	$progressfopen = fopen($progressfile, 'w');
-	fwrite($progressfopen, '70');
-	fclose($progressfopen);
-}
-if(count($parts) == 1){
-	OC_Calendar_Object::add($id, $file);
-}else{
-	foreach($importready as $import){
-		OC_Calendar_Object::add($id, $import);
-	}
-}
-//done the import
-if(is_writable('import_tmp/')){
-	$progressfopen = fopen($progressfile, 'w');
-	fwrite($progressfopen, '100');
-	fclose($progressfopen);
-}
-sleep(3);
-if(is_writable('import_tmp/')){
-	unlink($progressfile);
-}
-OC_JSON::success();
\ No newline at end of file
diff --git a/apps/calendar/index.php b/apps/calendar/index.php
old mode 100644
new mode 100755
index f964a13ef790339a50f03b9a736d856f20a2928a..3a3915b96697cb6b6f20029db4d2b71fcf29f7c3
--- a/apps/calendar/index.php
+++ b/apps/calendar/index.php
@@ -6,49 +6,53 @@
  * See the COPYING-README file.
  */
 
-require_once ('../../lib/base.php');
-OC_Util::checkLoggedIn();
-OC_Util::checkAppEnabled('calendar');
+ 
+OCP\User::checkLoggedIn();
+OCP\App::checkAppEnabled('calendar');
 
 // Create default calendar ...
-$calendars = OC_Calendar_Calendar::allCalendars(OC_User::getUser(), 1);
+$calendars = OC_Calendar_Calendar::allCalendars(OCP\USER::getUser(), 1);
 if( count($calendars) == 0){
-	OC_Calendar_Calendar::addCalendar(OC_User::getUser(),'Default calendar');
-	$calendars = OC_Calendar_Calendar::allCalendars(OC_User::getUser(), 1);
+	OC_Calendar_Calendar::addCalendar(OCP\USER::getUser(),'Default calendar');
+	$calendars = OC_Calendar_Calendar::allCalendars(OCP\USER::getUser(), 1);
 }
 
 $eventSources = array();
 foreach($calendars as $calendar){
 	$eventSources[] = OC_Calendar_Calendar::getEventSourceInfo($calendar);
 }
+
+$eventSources[] = array('url' => '?app=calendar&getfile=ajax/events.php?calendar_id=shared_rw', 'backgroundColor' => '#1D2D44', 'borderColor' => '#888', 'textColor' => 'white', 'editable'=>'true');
+$eventSources[] = array('url' => '?app=calendar&getfile=ajax/events.php?calendar_id=shared_r', 'backgroundColor' => '#1D2D44', 'borderColor' => '#888', 'textColor' => 'white', 'editable' => 'false');
+
 OC_Hook::emit('OC_Calendar', 'getSources', array('sources' => &$eventSources));
 $categories = OC_Calendar_App::getCategoryOptions();
 
 //Fix currentview for fullcalendar
-if(OC_Preferences::getValue(OC_USER::getUser(), 'calendar', 'currentview', 'month') == "oneweekview"){
-	OC_Preferences::setValue(OC_USER::getUser(), "calendar", "currentview", "agendaWeek");
+if(OCP\Config::getUserValue(OCP\USER::getUser(), 'calendar', 'currentview', 'month') == "oneweekview"){
+	OCP\Config::setUserValue(OCP\USER::getUser(), "calendar", "currentview", "agendaWeek");
 }
-if(OC_Preferences::getValue(OC_USER::getUser(), 'calendar', 'currentview', 'month') == "onemonthview"){
-	OC_Preferences::setValue(OC_USER::getUser(), "calendar", "currentview", "month");
+if(OCP\Config::getUserValue(OCP\USER::getUser(), 'calendar', 'currentview', 'month') == "onemonthview"){
+	OCP\Config::setUserValue(OCP\USER::getUser(), "calendar", "currentview", "month");
 }
-if(OC_Preferences::getValue(OC_USER::getUser(), 'calendar', 'currentview', 'month') == "listview"){
-	OC_Preferences::setValue(OC_USER::getUser(), "calendar", "currentview", "list");
+if(OCP\Config::getUserValue(OCP\USER::getUser(), 'calendar', 'currentview', 'month') == "listview"){
+	OCP\Config::setUserValue(OCP\USER::getUser(), "calendar", "currentview", "list");
 }
 
-OC_Util::addScript('3rdparty/fullcalendar', 'fullcalendar');
-OC_Util::addStyle('3rdparty/fullcalendar', 'fullcalendar');
-OC_Util::addScript('3rdparty/timepicker', 'jquery.ui.timepicker');
-OC_Util::addStyle('3rdparty/timepicker', 'jquery.ui.timepicker');
-if(OC_Preferences::getValue(OC_USER::getUser(), "calendar", "timezone") == null || OC_Preferences::getValue(OC_USER::getUser(), 'calendar', 'timezonedetection') == 'true'){
-	OC_UTIL::addScript('calendar', 'geo');
+OCP\Util::addscript('3rdparty/fullcalendar', 'fullcalendar');
+OCP\Util::addStyle('3rdparty/fullcalendar', 'fullcalendar');
+OCP\Util::addscript('3rdparty/timepicker', 'jquery.ui.timepicker');
+OCP\Util::addStyle('3rdparty/timepicker', 'jquery.ui.timepicker');
+if(OCP\Config::getUserValue(OCP\USER::getUser(), "calendar", "timezone") == null || OCP\Config::getUserValue(OCP\USER::getUser(), 'calendar', 'timezonedetection') == 'true'){
+	OCP\Util::addscript('calendar', 'geo');
 }
-OC_Util::addScript('calendar', 'calendar');
-OC_Util::addStyle('calendar', 'style');
-OC_Util::addScript('', 'jquery.multiselect');
-OC_Util::addStyle('', 'jquery.multiselect');
-OC_Util::addScript('contacts','jquery.multi-autocomplete');
-OC_Util::addScript('','oc-vcategories');
-OC_App::setActiveNavigationEntry('calendar_index');
+OCP\Util::addscript('calendar', 'calendar');
+OCP\Util::addStyle('calendar', 'style');
+OCP\Util::addscript('', 'jquery.multiselect');
+OCP\Util::addStyle('', 'jquery.multiselect');
+OCP\Util::addscript('contacts','jquery.multi-autocomplete');
+OCP\Util::addscript('','oc-vcategories');
+OCP\App::setActiveNavigationEntry('calendar_index');
 $tmpl = new OC_Template('calendar', 'calendar', 'user');
 $tmpl->assign('eventSources', $eventSources);
 $tmpl->assign('categories', $categories);
diff --git a/apps/calendar/js/calendar.js b/apps/calendar/js/calendar.js
index 858990fb89d6663fd8ff0f4a4cbcb7a1e49ddb4d..a16856938ce0b43cb893491e907a24d5fe1702dc 100644
--- a/apps/calendar/js/calendar.js
+++ b/apps/calendar/js/calendar.js
@@ -46,6 +46,7 @@ Calendar={
 			$('#advanced_month').change(function(){
 				Calendar.UI.repeat('month');
 			});
+			$( "#event" ).tabs({ selected: 0});
 			$('#event').dialog({
 				width : 500,
 				close : function(event, ui) {
@@ -455,7 +456,7 @@ Calendar={
 							$('#calendar_holder').fullCalendar('removeEventSource', data.eventSource.url);
 							$('#calendar_holder').fullCalendar('addEventSource', data.eventSource);
 							if (calendarid == 'new'){
-								$('#choosecalendar_dialog > table').append('<tr><td colspan="6"><a href="#" onclick="Calendar.UI.Calendar.newCalendar(this);"><input type="button" value="' + newcalendar + '"></a></td></tr>');
+								$('#choosecalendar_dialog > table:first').append('<tr><td colspan="6"><a href="#" onclick="Calendar.UI.Calendar.newCalendar(this);"><input type="button" value="' + newcalendar + '"></a></td></tr>');
 							}
 						}else{
 							$("#displayname_"+calendarid).css('background-color', '#FF2626');
@@ -494,6 +495,109 @@ Calendar={
 					left: -10000
 				});
 			}
+		},
+		Share:{
+			currentid: 'false',
+			idtype: '',
+			activation:function(object,owner,id){
+				$.getJSON(OC.filePath('calendar', 'ajax/share', 'activation.php'),{id:id, idtype:'calendar', activation:object.checked?1:0});
+				$('#calendar_holder').fullCalendar('refetchEvents');
+			},
+			dropdown:function(userid, calid){
+				$('.calendar_share_dropdown').remove();
+				$('<div class="calendar_share_dropdown"></div>').appendTo('#'+userid+'_'+calid);
+				$.get(OC.filePath('calendar', 'ajax/share', 'dropdown.php') + '?calid=' + calid, function(data){
+					$('#'+userid+'_'+calid+' > .calendar_share_dropdown').html(data);
+					$('#'+userid+'_'+calid+' > .calendar_share_dropdown').show('blind');
+					$('#share_user').chosen();
+					$('#share_group').chosen();
+				});
+				Calendar.UI.Share.currentid = calid;
+				Calendar.UI.Share.idtype = 'calendar';
+			},
+			share:function(id, idtype, sharewith, sharetype){
+				$.getJSON(OC.filePath('calendar', 'ajax/share', 'share.php'),{id:id, idtype:idtype, sharewith:sharewith, sharetype:sharetype}, function(data){
+
+				});
+			},
+			unshare:function(id, idtype, sharewith, sharetype){
+				$.getJSON(OC.filePath('calendar', 'ajax/share', 'unshare.php'),{id:id, idtype:idtype, sharewith:sharewith, sharetype:sharetype}, function(){
+					if(sharetype == 'public'){
+						$('#public_token').val('');
+						$('#public_token').css('display', 'none');
+					}
+				});
+			},
+			changepermission:function(id, idtype, sharewith, sharetype, permission){
+				$.getJSON(OC.filePath('calendar', 'ajax/share', 'changepermission.php'),{id:id, idtype:idtype, sharewith: sharewith, sharetype:sharetype, permission: (permission?1:0)});
+			},
+			init:function(){
+				$('.calendar_share_dropdown').live('mouseleave', function(){
+					$('.calendar_share_dropdown').hide('blind', function(){
+						$('.calendar_share_dropdown').remove();
+					});
+				});
+				$('#share_user').live('change', function(){
+					if($('#sharewithuser_' + $('#share_user option:selected').text()).length == 0){
+						Calendar.UI.Share.share(Calendar.UI.Share.currentid, Calendar.UI.Share.idtype, $('#share_user option:selected').text(), 'user');
+						var newitem = '<li id="sharewithuser_' + $('#share_user option:selected').text() +'"><input type="checkbox" width="12px" style="visibility:hidden;" title="' + $('#share_user option:selected').text() + '">' + $('#share_user option:selected').text() + '<img src="/owncloud/core/img/actions/delete.svg" class="svg action" style="display:none;float:right;"></li>';
+						$('#sharewithuser_list').append(newitem);
+						$('#sharewithuser_' + $('#share_user option:selected').text() + ' > img').click(function(){
+							$('#share_user option[value="' + $(this).parent().text() + '"]').removeAttr('disabled');
+							Calendar.UI.Share.unshare(Calendar.UI.Share.currentid, Calendar.UI.Share.idtype, $(this).parent().text(), 'user' );
+							$("#share_user").trigger("liszt:updated");
+							$(this).parent().remove();
+						});
+						$('#share_user option:selected').attr('disabled', 'disabled');
+						$("#share_user").trigger("liszt:updated");
+					}
+				});
+				$('#share_group').live('change', function(){
+					if($('#sharewithgroup_' + $('#share_group option:selected').text()).length == 0){
+						Calendar.UI.Share.share(Calendar.UI.Share.currentid, Calendar.UI.Share.idtype, $('#share_group option:selected').text(), 'group');
+						var newitem = '<li id="sharewithgroup_' + $('#share_group option:selected').text() +'"><input type="checkbox" width="12px" style="visibility:hidden;" title="' + $('#share_group option:selected').text() + '">' + $('#share_group option:selected').text() + '<img src="/owncloud/core/img/actions/delete.svg" class="svg action" style="display:none;float:right;"></li>';
+						$('#sharewithgroup_list').append(newitem);
+						$('#sharewithgroup_' + $('#share_group option:selected').text() + ' > img').click(function(){
+							$('#share_group option[value="' + $(this).parent().text() + '"]').removeAttr('disabled');
+							Calendar.UI.Share.unshare(Calendar.UI.Share.currentid, Calendar.UI.Share.idtype, $(this).parent().text(), 'group');
+							$("#share_group").trigger("liszt:updated");
+							$(this).parent().remove();
+						});
+						$('#share_group option:selected').attr('disabled', 'disabled');
+						$("#share_group").trigger("liszt:updated");
+					}
+				});
+				$('#sharewithuser_list > li > input:checkbox').live('change', function(){
+					Calendar.UI.Share.changepermission(Calendar.UI.Share.currentid, Calendar.UI.Share.idtype, $(this).parent().text(), 'user', this.checked);
+				});
+				$('#sharewithgroup_list > li > input:checkbox').live('change', function(){
+					Calendar.UI.Share.changepermission(Calendar.UI.Share.currentid, Calendar.UI.Share.idtype, $(this).parent().text(), 'group', this.checked);
+				});
+				$('#publish').live('change', function(){
+					if(this.checked == 1){
+						Calendar.UI.Share.share(Calendar.UI.Share.currentid, Calendar.UI.Share.idtype, '', 'public');
+					}else{
+						Calendar.UI.Share.unshare(Calendar.UI.Share.currentid, Calendar.UI.Share.idtype, '', 'public');
+					}
+				});
+				$('#sharewithuser_list').live('mouseenter', function(){
+					$('#sharewithuser_list > li > img').css('display', 'block');
+					$('#sharewithuser_list > li > input').css('visibility', 'visible');
+				});
+				$('#sharewithuser_list').live('mouseleave', function(){
+					$('#sharewithuser_list > li > img').css('display', 'none');
+					$('#sharewithuser_list > li > input').css('visibility', 'hidden');
+				});
+				$('#sharewithgroup_list').live('mouseenter', function(){
+					$('#sharewithgroup_list > li > img').css('display', 'block');
+					$('#sharewithgroup_list > li > input').css('visibility', 'visible');
+				});
+				$('#sharewithgroup_list').live('mouseleave', function(){
+					$('#sharewithgroup_list > li > img').css('display', 'none');
+					$('#sharewithgroup_list > li > input').css('visibility', 'hidden');
+				});
+				/*var permissions = (this.checked) ? 1 : 0;*/
+			}
 		}
 	}
 }
@@ -749,4 +853,5 @@ $(document).ready(function(){
 	$('#datecontrol_right').click(function(){
 		$('#calendar_holder').fullCalendar('next');
 	});
+	Calendar.UI.Share.init();
 });
diff --git a/apps/calendar/js/geo.js b/apps/calendar/js/geo.js
old mode 100755
new mode 100644
index 7018c6298a20c46cb8c21b2206537780341554d1..092d8547469ac32caea9f26df70435a8772e15ca
--- a/apps/calendar/js/geo.js
+++ b/apps/calendar/js/geo.js
@@ -6,7 +6,7 @@
  */
 if (navigator.geolocation) { 
 	navigator.geolocation.getCurrentPosition(function(position) {
-		$.getJSON(OC.filePath('calendar', 'ajax/settings', 'guesstimezone.php?lat=' + position.coords.latitude + '&long=' + position.coords.longitude + ''),
+		$.getJSON(OC.filePath('calendar', 'ajax/settings', 'guesstimezone.php') + '?lat=' + position.coords.latitude + '&long=' + position.coords.longitude,
 		function(data){
 			if (data.status == 'success' && typeof(data.message) != 'undefined'){
 				$('#notification').html(data.message);
diff --git a/apps/calendar/js/loader.js b/apps/calendar/js/loader.js
index 54003879759d15b2d37b277e84b352697720bb1c..60d92f448eee33fb1cb99689876bdd865615301f 100644
--- a/apps/calendar/js/loader.js
+++ b/apps/calendar/js/loader.js
@@ -44,7 +44,7 @@ Calendar_Import={
 			$('#newcalendar').attr('readonly', 'readonly');
 			$('#calendar').attr('disabled', 'disabled');
 			var progressfile = $('#progressfile').val();
-			$.post(OC.filePath('calendar', '', 'import.php'), {method: String (method), calname: String (calname), path: String (path), file: String (filename), id: String (calid)}, function(data){
+			$.post(OC.filePath('calendar', 'ajax/import', 'import.php'), {method: String (method), calname: String (calname), path: String (path), file: String (filename), id: String (calid)}, function(data){
 				if(data.status == 'success'){
 					$('#progressbar').progressbar('option', 'value', 100);
 					$('#import_done').css('display', 'block');
diff --git a/apps/calendar/lib/alarm.php b/apps/calendar/lib/alarm.php
new file mode 100644
index 0000000000000000000000000000000000000000..a71cc086827039c3a79ebc0735fb0fdfac90f7dc
--- /dev/null
+++ b/apps/calendar/lib/alarm.php
@@ -0,0 +1,13 @@
+<?php
+/**
+ * Copyright (c) 2012 Georg Ehrke <ownclouddev@georgswebsite.de>
+ * This file is licensed under the Affero General Public License version 3 or
+ * later.
+ * See the COPYING-README file.
+ */
+/*
+ * This class manages reminders for calendars
+ */
+class OC_Calendar_Alarm{
+	
+}
\ No newline at end of file
diff --git a/apps/calendar/lib/app.php b/apps/calendar/lib/app.php
old mode 100644
new mode 100755
index 660aa928a76db83a56ef70bd2608e69c470308c3..98e430b88636651c4fbdc62be1e4e452b5d9a4bb
--- a/apps/calendar/lib/app.php
+++ b/apps/calendar/lib/app.php
@@ -1,60 +1,121 @@
 <?php
 /**
  * Copyright (c) 2011 Bart Visscher <bartv@thisnet.nl>
+ * Copyright (c) 2012 Georg Ehrke <georg@owncloud.com>
  * This file is licensed under the Affero General Public License version 3 or
  * later.
  * See the COPYING-README file.
- */
-
-/**
+ * 
  * This class manages our app actions
  */
 OC_Calendar_App::$l10n = new OC_L10N('calendar');
+OC_Calendar_App::$tz = OCP\Config::getUserValue(OCP\USER::getUser(), 'calendar', 'timezone', date_default_timezone_get());
 class OC_Calendar_App{
+	const CALENDAR = 'calendar';
+	const EVENT = 'event';
+	/*
+	 * @brief language object for calendar app
+	 */
 	public static $l10n;
+	
+	/*
+	 * @brief categories of the user
+	 */
 	protected static $categories = null;
 
-	public static function getCalendar($id){
-		$calendar = OC_Calendar_Calendar::find( $id );
-		if( $calendar === false || $calendar['userid'] != OC_User::getUser()){
-			OC_JSON::error(array('data' => array('message' => self::$l10n->t('Wrong calendar'))));
-			exit();
+	/*
+	 * @brief timezone of the user
+	 */
+	public static $tz;
+	
+	/*
+	 * @brief returns informations about a calendar
+	 * @param int $id - id of the calendar
+	 * @param bool $security - check access rights or not
+	 * @param bool $shared - check if the user got access via sharing
+	 * @return mixed - bool / array
+	 */
+	public static function getCalendar($id, $security = true, $shared = false){
+		$calendar = OC_Calendar_Calendar::find($id);
+		if($shared === true){
+			if(OC_Calendar_Share::check_access(OCP\USER::getUser(), $id, OC_Calendar_Share::CALENDAR)){
+				return $calendar;
+			}
+		}
+		if($security === true){
+			if($calendar['userid'] != OCP\USER::getUser()){
+				return false;
+			}
 		}
-		return $calendar;
+		if($calendar === false){
+			return false;
+		}
+		return OC_Calendar_Calendar::find($id);
 	}
-
-	public static function getEventObject($id){
-		$event_object = OC_Calendar_Object::find( $id );
-		if( $event_object === false ){
-			OC_JSON::error();
-			exit();
+	
+	/*
+	 * @brief returns informations about an event
+	 * @param int $id - id of the event
+	 * @param bool $security - check access rights or not
+	 * @param bool $shared - check if the user got access via sharing
+	 * @return mixed - bool / array
+	 */
+	public static function getEventObject($id, $security = true, $shared = false){
+		$event = OC_Calendar_Object::find($id);
+		if($shared === true){
+			if(OC_Calendar_Share::check_access(OCP\USER::getUser(), $id, OC_Calendar_Share::EVENT)){
+				return $event;
+			}
 		}
-
-		self::getCalendar( $event_object['calendarid'] );//access check
-		return $event_object;
+		if($security === true){
+			$calendar = self::getCalendar($event['calendarid'], false);
+			if($calendar['userid'] != OCP\USER::getUser()){
+				return false;
+			}
+		}
+		if($event === false){
+			return false;
+		}
+		return $event;
 	}
-
-	public static function getVCalendar($id){
-		$event_object = self::getEventObject( $id );
-
-		$vcalendar = OC_VObject::parse($event_object['calendardata']);
-		// Check if the vcalendar is valid
-		if(is_null($vcalendar)){
-			OC_JSON::error();
-			exit();
+	
+	/*
+	 * @brief returns the parsed calendar data
+	 * @param int $id - id of the event
+	 * @param bool $security - check access rights or not
+	 * @return mixed - bool / object
+	 */
+	public static function getVCalendar($id, $security = true, $shared = false){
+		$event_object = self::getEventObject($id, $security, $shared);
+		if($event_object === false){
+			return false;
+		}
+		$vobject = OC_VObject::parse($event_object['calendardata']);
+		if(is_null($vobject)){
+			return false;
 		}
-		return $vcalendar;
+		return $vobject;
 	}
-
-	public static function isNotModified($vevent, $lastmodified)
-	{
+	
+	/*
+	 * @brief checks if an event was edited and dies if it was
+	 * @param (object) $vevent - vevent object of the event
+	 * @param (int) $lastmodified - time of last modification as unix timestamp
+	 * @return (bool)
+	 */
+	public static function isNotModified($vevent, $lastmodified){
 		$last_modified = $vevent->__get('LAST-MODIFIED');
 		if($last_modified && $lastmodified != $last_modified->getDateTime()->format('U')){
-			OC_JSON::error(array('modified'=>true));
+			OCP\JSON::error(array('modified'=>true));
 			exit;
 		}
+		return true;
 	}
-
+	
+	/*
+	 * @brief returns the default categories of ownCloud
+	 * @return (array) $categories
+	 */
 	protected static function getDefaultCategories()
 	{
 		return array(
@@ -75,14 +136,22 @@ class OC_Calendar_App{
 			self::$l10n->t('Work'),
 		);
 	}
-
+	
+	/*
+	 * @brief returns the vcategories object of the user
+	 * @return (object) $vcategories
+	 */
 	protected static function getVCategories() {
 		if (is_null(self::$categories)) {
 			self::$categories = new OC_VCategories('calendar', null, self::getDefaultCategories());
 		}
 		return self::$categories;
 	}
-
+	
+	/*
+	 * @brief returns the categories of the vcategories object
+	 * @return (array) $categories
+	 */
 	public static function getCategoryOptions()
 	{
 		$categories = self::getVCategories()->categories();
@@ -95,7 +164,7 @@ class OC_Calendar_App{
 	 */
 	public static function scanCategories($events = null) {
 		if (is_null($events)) {
-			$calendars = OC_Calendar_Calendar::allCalendars(OC_User::getUser());
+			$calendars = OC_Calendar_Calendar::allCalendars(OCP\USER::getUser());
 			if(count($calendars) > 0) {
 				$events = array();
 				foreach($calendars as $calendar) {
@@ -136,40 +205,246 @@ class OC_Calendar_App{
 	public static function getRepeatOptions(){
 		return OC_Calendar_Object::getRepeatOptions(self::$l10n);
 	}
-
+	
+	/*
+	 * @brief returns the options for the end of an repeating event
+	 * @return array - valid inputs for the end of an repeating events
+	 */
 	public static function getEndOptions(){
 		return OC_Calendar_Object::getEndOptions(self::$l10n);
 	}
-
+	
+	/*
+	 * @brief returns the options for an monthly repeating event
+	 * @return array - valid inputs for monthly repeating events
+	 */
 	public static function getMonthOptions(){
 		return OC_Calendar_Object::getMonthOptions(self::$l10n);
 	}
-
+	
+	/*
+	 * @brief returns the options for an weekly repeating event
+	 * @return array - valid inputs for weekly repeating events
+	 */
 	public static function getWeeklyOptions(){
 		return OC_Calendar_Object::getWeeklyOptions(self::$l10n);
 	}
-
+	
+	/*
+	 * @brief returns the options for an yearly repeating event
+	 * @return array - valid inputs for yearly repeating events
+	 */
 	public static function getYearOptions(){
 		return OC_Calendar_Object::getYearOptions(self::$l10n);
 	}
-
+	
+	/*
+	 * @brief returns the options for an yearly repeating event which occurs on specific days of the year
+	 * @return array - valid inputs for yearly repeating events
+	 */
 	public static function getByYearDayOptions(){
 		return OC_Calendar_Object::getByYearDayOptions();
 	}
-
+	
+	/*
+	 * @brief returns the options for an yearly repeating event which occurs on specific month of the year
+	 * @return array - valid inputs for yearly repeating events
+	 */
 	public static function getByMonthOptions(){
 		return OC_Calendar_Object::getByMonthOptions(self::$l10n);
 	}
 	
+	/*
+	 * @brief returns the options for an yearly repeating event which occurs on specific week numbers of the year
+	 * @return array - valid inputs for yearly repeating events
+	 */
 	public static function getByWeekNoOptions(){
 		return OC_Calendar_Object::getByWeekNoOptions();
 	}
-
+	
+	/*
+	 * @brief returns the options for an yearly or monthly repeating event which occurs on specific days of the month
+	 * @return array - valid inputs for yearly or monthly repeating events
+	 */
 	public static function getByMonthDayOptions(){
 		return OC_Calendar_Object::getByMonthDayOptions();
 	}
 	
+	/*
+	 * @brief returns the options for an monthly repeating event which occurs on specific weeks of the month
+	 * @return array - valid inputs for monthly repeating events
+	 */
 	public static function getWeekofMonth(){
 		return OC_Calendar_Object::getWeekofMonth(self::$l10n);
 	}
+	
+	/*
+	 * @brief checks the access for a calendar / an event
+	 * @param (int) $id - id of the calendar / event
+	 * @param (string) $type - type of the id (calendar/event)
+	 * @return (string) $access - level of access
+	 */
+	public static function getaccess($id, $type){
+		if($type == self::CALENDAR){
+			$calendar = self::getCalendar($id, false, false);
+			if($calendar['userid'] == OCP\USER::getUser()){
+				return 'owner';
+			}
+			$isshared = OC_Calendar_Share::check_access(OCP\USER::getUser(), $id, OC_Calendar_Share::CALENDAR);
+			if($isshared){
+				$writeaccess = OC_Calendar_Share::is_editing_allowed(OCP\USER::getUser(), $id, OC_Calendar_Share::CALENDAR);
+				if($writeaccess){
+					return 'rw';
+				}else{
+					return 'r';
+				}
+			}else{
+				return false;
+			}
+		}elseif($type == self::EVENT){
+			if(OC_Calendar_Object::getowner($id) == OCP\USER::getUser()){
+				return 'owner';
+			}
+			$isshared = OC_Calendar_Share::check_access(OCP\USER::getUser(), $id, OC_Calendar_Share::EVENT);
+			if($isshared){
+				$writeaccess = OC_Calendar_Share::is_editing_allowed(OCP\USER::getUser(), $id, OC_Calendar_Share::EVENT);
+				if($writeaccess){
+					return 'rw';
+				}else{
+					return 'r';
+				}
+			}else{
+				return false;
+			}
+		}
+	}
+	
+	/*
+	 * @brief analyses the parameter for calendar parameter and returns the objects
+	 * @param (string) $calendarid - calendarid
+	 * @param (int) $start - unixtimestamp of start
+	 * @param (int) $end - unixtimestamp of end
+	 * @return (array) $events 
+	 */
+	public static function getrequestedEvents($calendarid, $start, $end){
+		$events = array();
+		if($calendarid == 'shared_rw' || $_GET['calendar_id'] == 'shared_r'){
+			$calendars = OC_Calendar_Share::allSharedwithuser(OCP\USER::getUser(), OC_Calendar_Share::CALENDAR, 1, ($_GET['calendar_id'] == 'shared_rw')?'rw':'r');
+			foreach($calendars as $calendar){
+				$calendarevents = OC_Calendar_Object::allInPeriod($calendar['calendarid'], $start, $end);
+				$events = array_merge($events, $calendarevents);
+			}
+			$singleevents = OC_Calendar_Share::allSharedwithuser(OCP\USER::getUser(), OC_Calendar_Share::EVENT, 1, ($_GET['calendar_id'] == 'shared_rw')?'rw':'r');
+			foreach($singleevents as $singleevent){
+				$event = OC_Calendar_Object::find($singleevent['eventid']);
+				$events[] =  $event;
+			}
+		}else{
+			$calendar_id = $_GET['calendar_id'];
+			if (is_numeric($calendar_id)) {
+				$calendar = self::getCalendar($calendar_id);
+				OCP\Response::enableCaching(0);
+				OCP\Response::setETagHeader($calendar['ctag']);
+				$events = OC_Calendar_Object::allInPeriod($calendar_id, $start, $end);
+			} else {
+				OC_Hook::emit('OC_Calendar', 'getEvents', array('calendar_id' => $calendar_id, 'events' => &$events));
+			}
+		}
+		return $events;
+	}
+	
+	/*
+	 * @brief generates the output for an event which will be readable for our js
+	 * @param (mixed) $event - event object / array
+	 * @param (int) $start - unixtimestamp of start
+	 * @param (int) $end - unixtimestamp of end
+	 * @return (array) $output - readable output
+	 */
+	public static function generateEventOutput($event, $start, $end){
+		$output = array();
+		
+		if(isset($event['calendardata'])){
+			$object = OC_VObject::parse($event['calendardata']);
+			$vevent = $object->VEVENT;
+		}else{
+			$vevent = $event['vevent'];
+		}
+		
+		$last_modified = @$vevent->__get('LAST-MODIFIED');
+		$lastmodified = ($last_modified)?$last_modified->getDateTime()->format('U'):0;
+		
+		$output = array('id'=>(int)$event['id'],
+						'title' => htmlspecialchars(($event['summary']!=NULL || $event['summary'] != '')?$event['summary']: self::$l10n->t('unnamed')),
+						'description' => isset($vevent->DESCRIPTION)?htmlspecialchars($vevent->DESCRIPTION->value):'',
+						'lastmodified'=>$lastmodified);
+		
+		$dtstart = $vevent->DTSTART;
+		$start_dt = $dtstart->getDateTime();
+		$dtend = OC_Calendar_Object::getDTEndFromVEvent($vevent);
+		$end_dt = $dtend->getDateTime();
+		
+		if ($dtstart->getDateType() == Sabre_VObject_Element_DateTime::DATE){
+			$output['allDay'] = true;
+		}else{
+			$output['allDay'] = false;
+			$start_dt->setTimezone(new DateTimeZone(self::$tz));
+			$end_dt->setTimezone(new DateTimeZone(self::$tz));
+		}
+
+		// Handle exceptions to recurring events
+		$exceptionDateObjects = $vevent->select('EXDATE');
+		$exceptionDateMap = Array();
+		foreach ($exceptionDateObjects as $exceptionObject) {
+			foreach($exceptionObject->getDateTimes() as $datetime) {
+				$ts = $datetime->getTimestamp();
+				$exceptionDateMap[idate('Y',$ts)][idate('m', $ts)][idate('d', $ts)] = true;
+			}
+		}
+
+		$return = array();
+		if($event['repeating'] == 1){
+			$duration = (double) $end_dt->format('U') - (double) $start_dt->format('U');
+			$r = new When();
+			$r->recur($start_dt)->rrule((string) $vevent->RRULE);
+			/*$r = new iCal_Repeat_Generator(array('RECUR'  => $start_dt,
+			 *									   'RRULE'  => (string)$vevent->RRULE
+			 *									   'RDATE'  => (string)$vevent->RDATE						
+			 *									   'EXRULE' => (string)$vevent->EXRULE
+			 *									   'EXDATE' => (string)$vevent->EXDATE));*/
+			while($result = $r->next()){
+				if($result < $start){
+					continue;
+				}
+				if($result > $end){
+					break;
+				}
+				// Check for exceptions to recurring events
+				$ts = $result->getTimestamp();
+				if (isset($exceptionDateMap[idate('Y',$ts)][idate('m', $ts)][idate('d', $ts)])) {
+					continue;
+				}
+				unset($ts);
+
+				if($output['allDay'] == true){
+					$output['start'] = $result->format('Y-m-d');
+					$output['end'] = date('Y-m-d', $result->format('U') + --$duration);
+				}else{
+					$output['start'] = $result->format('Y-m-d H:i:s');
+					$output['end'] = date('Y-m-d H:i:s', $result->format('U') + $duration);
+				}
+				$return[] = $output;
+			}
+		}else{
+			if($output['allDay'] == true){
+				$output['start'] = $start_dt->format('Y-m-d');
+				$end_dt->modify('-1 sec');
+				$output['end'] = $end_dt->format('Y-m-d');
+			}else{
+				$output['start'] = $start_dt->format('Y-m-d H:i:s');
+				$output['end'] = $end_dt->format('Y-m-d H:i:s');
+			}
+			$return[] = $output;
+		}
+		return $return;
+	}
 }
diff --git a/apps/calendar/lib/attendees.php b/apps/calendar/lib/attendees.php
new file mode 100644
index 0000000000000000000000000000000000000000..ac30e11b3be3f57d12a2b2d89f496bec1881b373
--- /dev/null
+++ b/apps/calendar/lib/attendees.php
@@ -0,0 +1,13 @@
+<?php
+/**
+ * Copyright (c) 2012 Georg Ehrke <ownclouddev@georgswebsite.de>
+ * This file is licensed under the Affero General Public License version 3 or
+ * later.
+ * See the COPYING-README file.
+ */
+/*
+ * This class manages Attendees for calendars
+ */
+class OC_Calendar_Attendees{
+	
+}
\ No newline at end of file
diff --git a/apps/calendar/lib/calendar.php b/apps/calendar/lib/calendar.php
old mode 100644
new mode 100755
index 321f4c73ba069541a435d7d1c9abbab44816bad6..1d0085080409cfebc13b4e072642c67c55979d1f
--- a/apps/calendar/lib/calendar.php
+++ b/apps/calendar/lib/calendar.php
@@ -54,7 +54,7 @@ class OC_Calendar_Calendar{
 			$active_where = ' AND active = ?';
 			$values[] = $active;
 		}
-		$stmt = OC_DB::prepare( 'SELECT * FROM *PREFIX*calendar_calendars WHERE userid = ?' . $active_where );
+		$stmt = OCP\DB::prepare( 'SELECT * FROM *PREFIX*calendar_calendars WHERE userid = ?' . $active_where );
 		$result = $stmt->execute($values);
 
 		$calendars = array();
@@ -81,7 +81,7 @@ class OC_Calendar_Calendar{
 	 * @return associative array
 	 */
 	public static function find($id){
-		$stmt = OC_DB::prepare( 'SELECT * FROM *PREFIX*calendar_calendars WHERE id = ?' );
+		$stmt = OCP\DB::prepare( 'SELECT * FROM *PREFIX*calendar_calendars WHERE id = ?' );
 		$result = $stmt->execute(array($id));
 
 		return $result->fetchRow();
@@ -106,10 +106,10 @@ class OC_Calendar_Calendar{
 
 		$uri = self::createURI($name, $uris );
 
-		$stmt = OC_DB::prepare( 'INSERT INTO *PREFIX*calendar_calendars (userid,displayname,uri,ctag,calendarorder,calendarcolor,timezone,components) VALUES(?,?,?,?,?,?,?,?)' );
+		$stmt = OCP\DB::prepare( 'INSERT INTO *PREFIX*calendar_calendars (userid,displayname,uri,ctag,calendarorder,calendarcolor,timezone,components) VALUES(?,?,?,?,?,?,?,?)' );
 		$result = $stmt->execute(array($userid,$name,$uri,1,$order,$color,$timezone,$components));
 
-		return OC_DB::insertid('*PREFIX*calendar_calendar');
+		return OCP\DB::insertid('*PREFIX*calendar_calendar');
 	}
 
 	/**
@@ -126,10 +126,10 @@ class OC_Calendar_Calendar{
 	public static function addCalendarFromDAVData($principaluri,$uri,$name,$components,$timezone,$order,$color){
 		$userid = self::extractUserID($principaluri);
 
-		$stmt = OC_DB::prepare( 'INSERT INTO *PREFIX*calendar_calendars (userid,displayname,uri,ctag,calendarorder,calendarcolor,timezone,components) VALUES(?,?,?,?,?,?,?,?)' );
+		$stmt = OCP\DB::prepare( 'INSERT INTO *PREFIX*calendar_calendars (userid,displayname,uri,ctag,calendarorder,calendarcolor,timezone,components) VALUES(?,?,?,?,?,?,?,?)' );
 		$result = $stmt->execute(array($userid,$name,$uri,1,$order,$color,$timezone,$components));
 
-		return OC_DB::insertid('*PREFIX*calendar_calendars');
+		return OCP\DB::insertid('*PREFIX*calendar_calendars');
 	}
 
 	/**
@@ -155,7 +155,7 @@ class OC_Calendar_Calendar{
 		if(is_null($order)) $order = $calendar['calendarorder'];
 		if(is_null($color)) $color = $calendar['calendarcolor'];
 
-		$stmt = OC_DB::prepare( 'UPDATE *PREFIX*calendar_calendars SET displayname=?,calendarorder=?,calendarcolor=?,timezone=?,components=?,ctag=ctag+1 WHERE id=?' );
+		$stmt = OCP\DB::prepare( 'UPDATE *PREFIX*calendar_calendars SET displayname=?,calendarorder=?,calendarcolor=?,timezone=?,components=?,ctag=ctag+1 WHERE id=?' );
 		$result = $stmt->execute(array($name,$order,$color,$timezone,$components,$id));
 
 		return true;
@@ -168,7 +168,7 @@ class OC_Calendar_Calendar{
 	 * @return boolean
 	 */
 	public static function setCalendarActive($id,$active){
-		$stmt = OC_DB::prepare( 'UPDATE *PREFIX*calendar_calendars SET active = ? WHERE id = ?' );
+		$stmt = OCP\DB::prepare( 'UPDATE *PREFIX*calendar_calendars SET active = ? WHERE id = ?' );
 		$stmt->execute(array($active, $id));
 
 		return true;
@@ -180,7 +180,7 @@ class OC_Calendar_Calendar{
 	 * @return boolean
 	 */
 	public static function touchCalendar($id){
-		$stmt = OC_DB::prepare( 'UPDATE *PREFIX*calendar_calendars SET ctag = ctag + 1 WHERE id = ?' );
+		$stmt = OCP\DB::prepare( 'UPDATE *PREFIX*calendar_calendars SET ctag = ctag + 1 WHERE id = ?' );
 		$stmt->execute(array($id));
 
 		return true;
@@ -192,10 +192,10 @@ class OC_Calendar_Calendar{
 	 * @return boolean
 	 */
 	public static function deleteCalendar($id){
-		$stmt = OC_DB::prepare( 'DELETE FROM *PREFIX*calendar_calendars WHERE id = ?' );
+		$stmt = OCP\DB::prepare( 'DELETE FROM *PREFIX*calendar_calendars WHERE id = ?' );
 		$stmt->execute(array($id));
 
-		$stmt = OC_DB::prepare( 'DELETE FROM *PREFIX*calendar_objects WHERE calendarid = ?' );
+		$stmt = OCP\DB::prepare( 'DELETE FROM *PREFIX*calendar_objects WHERE calendarid = ?' );
 		$stmt->execute(array($id));
 
 		return true;
@@ -241,7 +241,7 @@ class OC_Calendar_Calendar{
 
 	public static function getEventSourceInfo($calendar){
 		return array(
-			'url' => OC_Helper::linkTo('calendar', 'ajax/events.php').'?calendar_id='.$calendar['id'],
+			'url' => OCP\Util::linkTo('calendar', 'ajax/events.php').'?calendar_id='.$calendar['id'],
 			'backgroundColor' => $calendar['calendarcolor'],
 			'borderColor' => '#888',
 			'textColor' => 'black',
diff --git a/apps/calendar/lib/hooks.php b/apps/calendar/lib/hooks.php
index 54f1680a36e55d4a68427902ca3ce2816cc8b1d5..22e8d8e20f28257bc1c6e7c31401546b2a9d693a 100644
--- a/apps/calendar/lib/hooks.php
+++ b/apps/calendar/lib/hooks.php
@@ -24,17 +24,4 @@ class OC_Calendar_Hooks{
 
 		return true;
 	}
-
-	/**
-	 * @brief Adds the CardDAV resource to the DAV server
-	 * @param paramters parameters from initialize-Hook
-	 * @return array
-	 */
-	public static function initializeCalDAV($parameters){
-		// We need a backend, the root node and the caldav plugin
-		$parameters['backends']['caldav'] = new OC_Connector_Sabre_CalDAV();
-		$parameters['nodes'][] = new Sabre_CalDAV_CalendarRootNode($parameters['backends']['principal'], $parameters['backends']['caldav']);
-		$parameters['plugins'][] = new Sabre_CalDAV_Plugin();
-		return true;
-	}
 }
diff --git a/apps/calendar/lib/object.php b/apps/calendar/lib/object.php
old mode 100644
new mode 100755
index d5622f6251fb0d78db07d79dd130e2e9176fded8..3d4174a57be18e1e7db14d52afc0a4f016d85af8
--- a/apps/calendar/lib/object.php
+++ b/apps/calendar/lib/object.php
@@ -19,7 +19,7 @@ class OC_Calendar_Object{
 	 * ['calendardata']
 	 */
 	public static function all($id){
-		$stmt = OC_DB::prepare( 'SELECT * FROM *PREFIX*calendar_objects WHERE calendarid = ?' );
+		$stmt = OCP\DB::prepare( 'SELECT * FROM *PREFIX*calendar_objects WHERE calendarid = ?' );
 		$result = $stmt->execute(array($id));
 
 		$calendarobjects = array();
@@ -41,7 +41,7 @@ class OC_Calendar_Object{
 	 * in ['calendardata']
 	 */
 	public static function allInPeriod($id, $start, $end){
-		$stmt = OC_DB::prepare( 'SELECT * FROM *PREFIX*calendar_objects WHERE calendarid = ?'
+		$stmt = OCP\DB::prepare( 'SELECT * FROM *PREFIX*calendar_objects WHERE calendarid = ?'
 		.' AND ((startdate >= ? AND startdate <= ? AND repeating = 0)'
 		.' OR (enddate >= ? AND enddate <= ? AND repeating = 0)'
 		.' OR (startdate <= ? AND repeating = 1))' );
@@ -66,7 +66,7 @@ class OC_Calendar_Object{
 	 * @return associative array
 	 */
 	public static function find($id){
-		$stmt = OC_DB::prepare( 'SELECT * FROM *PREFIX*calendar_objects WHERE id = ?' );
+		$stmt = OCP\DB::prepare( 'SELECT * FROM *PREFIX*calendar_objects WHERE id = ?' );
 		$result = $stmt->execute(array($id));
 
 		return $result->fetchRow();
@@ -79,7 +79,7 @@ class OC_Calendar_Object{
 	 * @return associative array
 	 */
 	public static function findWhereDAVDataIs($cid,$uri){
-		$stmt = OC_DB::prepare( 'SELECT * FROM *PREFIX*calendar_objects WHERE calendarid = ? AND uri = ?' );
+		$stmt = OCP\DB::prepare( 'SELECT * FROM *PREFIX*calendar_objects WHERE calendarid = ? AND uri = ?' );
 		$result = $stmt->execute(array($cid,$uri));
 
 		return $result->fetchRow();
@@ -103,12 +103,12 @@ class OC_Calendar_Object{
 
 		$uri = 'owncloud-'.md5($data.rand().time()).'.ics';
 
-		$stmt = OC_DB::prepare( 'INSERT INTO *PREFIX*calendar_objects (calendarid,objecttype,startdate,enddate,repeating,summary,calendardata,uri,lastmodified) VALUES(?,?,?,?,?,?,?,?,?)' );
-		$result = $stmt->execute(array($id,$type,$startdate,$enddate,$repeating,$summary,$data,$uri,time()));
+		$stmt = OCP\DB::prepare( 'INSERT INTO *PREFIX*calendar_objects (calendarid,objecttype,startdate,enddate,repeating,summary,calendardata,uri,lastmodified) VALUES(?,?,?,?,?,?,?,?,?)' );
+		$stmt->execute(array($id,$type,$startdate,$enddate,$repeating,$summary,$data,$uri,time()));
 
 		OC_Calendar_Calendar::touchCalendar($id);
 
-		return OC_DB::insertid('*PREFIX*calendar_objects');
+		return OCP\DB::insertid('*PREFIX*calendar_objects');
 	}
 
 	/**
@@ -122,12 +122,12 @@ class OC_Calendar_Object{
 		$object = OC_VObject::parse($data);
 		list($type,$startdate,$enddate,$summary,$repeating,$uid) = self::extractData($object);
 
-		$stmt = OC_DB::prepare( 'INSERT INTO *PREFIX*calendar_objects (calendarid,objecttype,startdate,enddate,repeating,summary,calendardata,uri,lastmodified) VALUES(?,?,?,?,?,?,?,?,?)' );
-		$result = $stmt->execute(array($id,$type,$startdate,$enddate,$repeating,$summary,$data,$uri,time()));
+		$stmt = OCP\DB::prepare( 'INSERT INTO *PREFIX*calendar_objects (calendarid,objecttype,startdate,enddate,repeating,summary,calendardata,uri,lastmodified) VALUES(?,?,?,?,?,?,?,?,?)' );
+		$stmt->execute(array($id,$type,$startdate,$enddate,$repeating,$summary,$data,$uri,time()));
 
 		OC_Calendar_Calendar::touchCalendar($id);
 
-		return OC_DB::insertid('*PREFIX*calendar_objects');
+		return OCP\DB::insertid('*PREFIX*calendar_objects');
 	}
 
 	/**
@@ -143,8 +143,8 @@ class OC_Calendar_Object{
 		OC_Calendar_App::loadCategoriesFromVCalendar($object);
 		list($type,$startdate,$enddate,$summary,$repeating,$uid) = self::extractData($object);
 
-		$stmt = OC_DB::prepare( 'UPDATE *PREFIX*calendar_objects SET objecttype=?,startdate=?,enddate=?,repeating=?,summary=?,calendardata=?, lastmodified = ? WHERE id = ?' );
-		$result = $stmt->execute(array($type,$startdate,$enddate,$repeating,$summary,$data,time(),$id));
+		$stmt = OCP\DB::prepare( 'UPDATE *PREFIX*calendar_objects SET objecttype=?,startdate=?,enddate=?,repeating=?,summary=?,calendardata=?, lastmodified = ? WHERE id = ?' );
+		$stmt->execute(array($type,$startdate,$enddate,$repeating,$summary,$data,time(),$id));
 
 		OC_Calendar_Calendar::touchCalendar($oldobject['calendarid']);
 
@@ -164,8 +164,8 @@ class OC_Calendar_Object{
 		$object = OC_VObject::parse($data);
 		list($type,$startdate,$enddate,$summary,$repeating,$uid) = self::extractData($object);
 
-		$stmt = OC_DB::prepare( 'UPDATE *PREFIX*calendar_objects SET objecttype=?,startdate=?,enddate=?,repeating=?,summary=?,calendardata=?, lastmodified = ? WHERE id = ?' );
-		$result = $stmt->execute(array($type,$startdate,$enddate,$repeating,$summary,$data,time(),$oldobject['id']));
+		$stmt = OCP\DB::prepare( 'UPDATE *PREFIX*calendar_objects SET objecttype=?,startdate=?,enddate=?,repeating=?,summary=?,calendardata=?, lastmodified = ? WHERE id = ?' );
+		$stmt->execute(array($type,$startdate,$enddate,$repeating,$summary,$data,time(),$oldobject['id']));
 
 		OC_Calendar_Calendar::touchCalendar($oldobject['calendarid']);
 
@@ -179,7 +179,7 @@ class OC_Calendar_Object{
 	 */
 	public static function delete($id){
 		$oldobject = self::find($id);
-		$stmt = OC_DB::prepare( 'DELETE FROM *PREFIX*calendar_objects WHERE id = ?' );
+		$stmt = OCP\DB::prepare( 'DELETE FROM *PREFIX*calendar_objects WHERE id = ?' );
 		$stmt->execute(array($id));
 		OC_Calendar_Calendar::touchCalendar($oldobject['calendarid']);
 
@@ -193,7 +193,7 @@ class OC_Calendar_Object{
 	 * @return boolean
 	 */
 	public static function deleteFromDAVData($cid,$uri){
-		$stmt = OC_DB::prepare( 'DELETE FROM *PREFIX*calendar_objects WHERE calendarid = ? AND uri=?' );
+		$stmt = OCP\DB::prepare( 'DELETE FROM *PREFIX*calendar_objects WHERE calendarid = ? AND uri=?' );
 		$stmt->execute(array($cid,$uri));
 		OC_Calendar_Calendar::touchCalendar($cid);
 
@@ -201,8 +201,8 @@ class OC_Calendar_Object{
 	}
 
 	public static function moveToCalendar($id, $calendarid){
-		$stmt = OC_DB::prepare( 'UPDATE *PREFIX*calendar_objects SET calendarid=? WHERE id = ?' );
-		$result = $stmt->execute(array($calendarid,$id));
+		$stmt = OCP\DB::prepare( 'UPDATE *PREFIX*calendar_objects SET calendarid=? WHERE id = ?' );
+		$stmt->execute(array($calendarid,$id));
 
 		OC_Calendar_Calendar::touchCalendar($id);
 
@@ -432,11 +432,6 @@ class OC_Calendar_Object{
 			$errarr['title'] = 'true';
 			$errnum++;
 		}
-		$calendar = OC_Calendar_Calendar::find($request['calendar']);
-		if($calendar['userid'] != OC_User::getUser()){
-			$errarr['cal'] = 'true';
-			$errnum++;
-		}
 
 		$fromday = substr($request['from'], 0, 2);
 		$frommonth = substr($request['from'], 3, 2);
@@ -461,11 +456,11 @@ class OC_Calendar_Object{
 		if($request['repeat'] != 'doesnotrepeat'){
 			if(is_nan($request['interval']) && $request['interval'] != ''){
 				$errarr['interval'] = 'true';
-				$ernum++;
+				$errnum++;
 			}
 			if(array_key_exists('repeat', $request) && !array_key_exists($request['repeat'], self::getRepeatOptions(OC_Calendar_App::$l10n))){
 				$errarr['repeat'] = 'true';
-				$ernum++;
+				$errnum++;
 			}
 			if(array_key_exists('advanced_month_select', $request) && !array_key_exists($request['advanced_month_select'], self::getMonthOptions(OC_Calendar_App::$l10n))){
 				$errarr['advanced_month_select'] = 'true';
@@ -595,7 +590,7 @@ class OC_Calendar_Object{
 		$vevent = new OC_VObject('VEVENT');
 		$vcalendar->add($vevent);
 
-		$vevent->setDateTime('CREATED', 'now', Sabre_VObject_Element_DateTime::UTC);
+		$vevent->setDateTime('CREATED', 'now', Sabre_VObject_Property_DateTime::UTC);
 
 		$vevent->setUID();
 		return self::updateVCalendarFromRequest($request, $vcalendar);
@@ -756,24 +751,22 @@ class OC_Calendar_Object{
 		}
 
 
-		$vevent->setDateTime('LAST-MODIFIED', 'now', Sabre_VObject_Element_DateTime::UTC);
-		$vevent->setDateTime('DTSTAMP', 'now', Sabre_VObject_Element_DateTime::UTC);
+		$vevent->setDateTime('LAST-MODIFIED', 'now', Sabre_VObject_Property_DateTime::UTC);
+		$vevent->setDateTime('DTSTAMP', 'now', Sabre_VObject_Property_DateTime::UTC);
 		$vevent->setString('SUMMARY', $title);
 
-		$dtstart = new Sabre_VObject_Element_DateTime('DTSTART');
-		$dtend = new Sabre_VObject_Element_DateTime('DTEND');
 		if($allday){
 			$start = new DateTime($from);
 			$end = new DateTime($to.' +1 day');
-			$vevent->setDateTime('DTSTART', $start, Sabre_VObject_Element_DateTime::DATE);
-			$vevent->setDateTime('DTEND', $end, Sabre_VObject_Element_DateTime::DATE);
+			$vevent->setDateTime('DTSTART', $start, Sabre_VObject_Property_DateTime::DATE);
+			$vevent->setDateTime('DTEND', $end, Sabre_VObject_Property_DateTime::DATE);
 		}else{
-			$timezone = OC_Preferences::getValue(OC_USER::getUser(), 'calendar', 'timezone', date_default_timezone_get());
+			$timezone = OCP\Config::getUserValue(OCP\USER::getUser(), 'calendar', 'timezone', date_default_timezone_get());
 			$timezone = new DateTimeZone($timezone);
 			$start = new DateTime($from.' '.$fromtime, $timezone);
 			$end = new DateTime($to.' '.$totime, $timezone);
-			$vevent->setDateTime('DTSTART', $start, Sabre_VObject_Element_DateTime::LOCALTZ);
-			$vevent->setDateTime('DTEND', $end, Sabre_VObject_Element_DateTime::LOCALTZ);
+			$vevent->setDateTime('DTSTART', $start, Sabre_VObject_Property_DateTime::LOCALTZ);
+			$vevent->setDateTime('DTEND', $end, Sabre_VObject_Property_DateTime::LOCALTZ);
 		}
 		unset($vevent->DURATION);
 
@@ -787,4 +780,15 @@ class OC_Calendar_Object{
 
 		return $vcalendar;
 	}
+
+	public static function getowner($id){
+		$event = self::find($id);
+		$cal = OC_Calendar_Calendar::find($event['calendarid']);
+		return $cal['userid'];
+	}
+	
+	public static function getCalendarid($id){
+		$event = self::find($id);
+		return $event['calendarid'];
+	}
 }
diff --git a/apps/calendar/lib/search.php b/apps/calendar/lib/search.php
old mode 100644
new mode 100755
index da5fa35bc21caa6830b91a39b45d78458fc0b46e..03516b3b70c31007987fc70cb1a1f8cddfa7f300
--- a/apps/calendar/lib/search.php
+++ b/apps/calendar/lib/search.php
@@ -1,8 +1,8 @@
 <?php
 class OC_Search_Provider_Calendar extends OC_Search_Provider{
 	function search($query){
-		$calendars = OC_Calendar_Calendar::allCalendars(OC_User::getUser(), 1);
-		if(count($calendars)==0 || !OC_App::isEnabled('calendar')){
+		$calendars = OC_Calendar_Calendar::allCalendars(OCP\USER::getUser(), 1);
+		if(count($calendars)==0 || !OCP\App::isEnabled('calendar')){
 			//return false;
 		}
 		$results=array();
@@ -12,7 +12,7 @@ class OC_Search_Provider_Calendar extends OC_Search_Provider{
 		}else{
 			$searchquery[] = $query;
 		}
-		$user_timezone = OC_Preferences::getValue(OC_USER::getUser(), 'calendar', 'timezone', date_default_timezone_get());
+		$user_timezone = OCP\Config::getUserValue(OCP\USER::getUser(), 'calendar', 'timezone', date_default_timezone_get());
 		$l = new OC_l10n('calendar');
 		foreach($calendars as $calendar){
 			$objects = OC_Calendar_Object::all($calendar['id']);
@@ -26,7 +26,7 @@ class OC_Search_Provider_Calendar extends OC_Search_Provider{
 					$start_dt->setTimezone(new DateTimeZone($user_timezone));
 					$end_dt = $dtend->getDateTime();
 					$end_dt->setTimezone(new DateTimeZone($user_timezone));
-					if ($dtstart->getDateType() == Sabre_VObject_Element_DateTime::DATE){
+					if ($dtstart->getDateType() == Sabre_VObject_Property_DateTime::DATE){
 						$end_dt->modify('-1 sec');
 						if($start_dt->format('d.m.Y') != $end_dt->format('d.m.Y')){
 							$info = $l->t('Date') . ': ' . $start_dt->format('d.m.Y') . ' - ' . $end_dt->format('d.m.Y');
@@ -36,7 +36,7 @@ class OC_Search_Provider_Calendar extends OC_Search_Provider{
 					}else{
 						$info = $l->t('Date') . ': ' . $start_dt->format('d.m.y H:i') . ' - ' . $end_dt->format('d.m.y H:i');
 					}
-					$link = OC_Helper::linkTo('calendar', 'index.php').'?showevent='.urlencode($object['id']);
+					$link = OCP\Util::linkTo('calendar', 'index.php').'?showevent='.urlencode($object['id']);
 					$results[]=new OC_Search_Result($object['summary'],$info, $link,$l->t('Cal.'));//$name,$text,$link,$type
 				}
 			}
diff --git a/apps/calendar/lib/share.php b/apps/calendar/lib/share.php
new file mode 100755
index 0000000000000000000000000000000000000000..a53bf763324f1de3a91ff1539bce467207cdb3d2
--- /dev/null
+++ b/apps/calendar/lib/share.php
@@ -0,0 +1,259 @@
+<?php
+/**
+ * Copyright (c) 2012 Georg Ehrke <ownclouddev@georgswebsite.de>
+ * This file is licensed under the Affero General Public License version 3 or
+ * later.
+ * See the COPYING-README file.
+ */
+/*
+ * This class manages shared calendars
+ */
+class OC_Calendar_Share{
+	const CALENDAR = 'calendar';
+	const EVENT = 'event';
+	/*
+	 * @brief: returns informations about all calendar or events which users are sharing with the user - userid
+	 * @param: (string) $userid - id of the user
+	 * @param: (string) $type - use const self::CALENDAR or self::EVENT
+	 * @return: (array) $return - information about calendars
+	 */
+	public static function allSharedwithuser($userid, $type, $active=null, $permission=null){
+		$group_where = self::group_sql(OC_Group::getUserGroups($userid));
+		$permission_where = self::permission_sql($permission);
+		if($type == self::CALENDAR){
+			$active_where = self::active_sql($active);
+		}else{
+			$active_where = '';
+		}
+		$stmt = OCP\DB::prepare('SELECT * FROM *PREFIX*calendar_share_' . $type . ' WHERE ((share = ? AND sharetype = "user") ' . $group_where . ') AND owner <> ? ' . $permission_where . ' ' . $active_where);
+		$result = $stmt->execute(array($userid, $userid));
+		$return = array();
+		while( $row = $result->fetchRow()){
+			$return[] = $row;
+		}
+		return $return;
+	}
+	/*
+	 * @brief: returns all users a calendar / event is shared with
+	 * @param: (int) id - id of the calendar / event
+	 * @param: (string) $type - use const self::CALENDAR or self::EVENT
+	 * @return: (array) $users - information about users a calendar / event is shared with
+	 */
+	public static function allUsersSharedwith($id, $type){
+		$stmt = OCP\DB::prepare('SELECT * FROM *PREFIX*calendar_share_' . $type . ' WHERE ' . $type . 'id = ? ORDER BY share');
+		$result = $stmt->execute(array($id));
+		$users = array();
+		while( $row = $result->fetchRow()){
+			$users[] = $row;
+		}
+		return $users;
+	}
+	/*
+	 * @brief: shares a calendar / event
+	 * @param: (string) $owner - userid of the owner
+	 * @param: (string) $share - userid (if $sharetype == user) / groupid (if $sharetype == group) / token (if $sharetype == public)
+	 * @param: (string) $sharetype - type of sharing (can be: user/group/public)
+	 * @param: (string) $id - id of the calendar / event
+	 * @param: (string) $type - use const self::CALENDAR or self::EVENT
+	 * @return (mixed) - token (if $sharetype == public) / bool (if $sharetype != public)
+	 */
+	public static function share($owner, $share, $sharetype, $id, $type){
+		if(self::is_already_shared($owner, $share, $sharetype, $id, $type)){
+			return false;
+		}
+		switch($sharetype){
+			case 'user':
+			case 'group':
+			case 'public':
+				break;
+			default:
+				return false;
+		}
+		if($sharetype == 'public'){
+			$share = self::generate_token($id, $type);
+		}
+		$stmt = OCP\DB::prepare('INSERT INTO *PREFIX*calendar_share_' . $type . ' (owner,share,sharetype,' . $type . 'id,permissions' . (($type == self::CALENDAR)?', active':'') . ') VALUES(?,?,?,?,0' . (($type == self::CALENDAR)?', 1':'') . ')' );
+		$result = $stmt->execute(array($owner,$share,$sharetype,$id));
+		if($sharetype == 'public'){
+			return $share;
+		}else{
+			return true;
+		}
+	}
+	/*
+	 * @brief: stops sharing a calendar / event
+	 * @param: (string) $owner - userid of the owner
+	 * @param: (string) $share - userid (if $sharetype == user) / groupid (if $sharetype == group) / token (if $sharetype == public)
+	 * @param: (string) $sharetype - type of sharing (can be: user/group/public)
+	 * @param: (string) $id - id of the calendar / event
+	 * @param: (string) $type - use const self::CALENDAR or self::EVENT
+	 * @return (bool)
+	 */
+	public static function unshare($owner, $share, $sharetype, $id, $type){
+		$stmt = OCP\DB::prepare('DELETE FROM *PREFIX*calendar_share_' . $type . ' WHERE owner = ? ' . (($sharetype != 'public')?'AND share = ?':'') . ' AND sharetype = ? AND ' . $type . 'id = ?');
+		if($sharetype != 'public'){
+			$stmt->execute(array($owner,$share,$sharetype,$id));
+		}else{
+			$stmt->execute(array($owner,$sharetype,$id));
+		}
+		return true;
+	}
+	/*
+	 * @brief: changes the permission for a calendar / event
+	 * @param: (string) $share - userid (if $sharetype == user) / groupid (if $sharetype == group) / token (if $sharetype == public)
+	 * @param: (string) $sharetype - type of sharing (can be: user/group/public)
+	 * @param: (string) $id - id of the calendar / event
+	 * @param: (int) $permission - permission of user the calendar / event is shared with (if $sharetype == public then $permission = 0)
+	 * @param: (string) $type - use const self::CALENDAR or self::EVENT
+	 * @return (bool)
+	 */
+	public static function changepermission($share, $sharetype, $id, $permission, $type){
+		if($sharetype == 'public' && $permission == 1){
+			$permission = 0;
+		}
+		$stmt = OCP\DB::prepare('UPDATE *PREFIX*calendar_share_' . $type . ' SET permissions = ? WHERE share = ? AND sharetype = ? AND ' . $type . 'id = ?');
+		$stmt->execute(array($permission, $share, $sharetype, $id));
+		return true;
+	}
+	/*
+	 * @brief: generates a token for public calendars / events
+	 * @return: (string) $token
+	 */
+	private static function generate_token($id, $type){
+		$uniqid = uniqid();
+		if($type == self::CALENDAR){
+			$events = OC_Calendar_Object::all($id);
+			$string = '';
+			foreach($events as $event){
+				$string .= $event['calendardata'];
+			}
+		}else{
+			$string = OC_Calendar_Object::find($id);
+		}
+		$string = sha1($string['calendardata']);
+		$id = sha1($id);
+		$array = array($uniqid,$string,$id);
+		shuffle($array);
+		$string = implode('', $array);
+		$token = md5($string);
+		return substr($token, rand(0,16), 15);
+	}
+	/*
+	 * @brief: checks if it is already shared
+	 * @param: (string) $owner - userid of the owner
+	 * @param: (string) $share - userid (if $sharetype == user) / groupid (if $sharetype == group) / token (if $sharetype == public)
+	 * @param: (string) $sharetype - type of sharing (can be: user/group/public)
+	 * @param: (string) $id - id of the calendar / event
+	 * @param: (string) $type - use const self::CALENDAR or self::EVENT
+	 * @return (bool)
+	 */
+	public static function is_already_shared($owner, $share, $sharetype, $id, $type){
+		$stmt = OCP\DB::prepare('SELECT * FROM *PREFIX*calendar_share_' . $type . ' WHERE owner = ? AND share = ? AND sharetype = ? AND ' . $type . 'id = ?');
+		$result = $stmt->execute(array($owner, $share, $sharetype, $id));
+		if($result->numRows() > 0){
+			return true;
+		}
+		return false;
+	}
+	private static function group_sql($groups){
+		$group_where = '';
+		$i = 0;
+		foreach($groups as $group){
+			$group_where .= ' OR ';
+			$group_where .= ' (share = "' . $group . '" AND sharetype = "group") ';
+			$i++;
+		}
+		return $group_where;
+	}
+	private static function permission_sql($permission = null){
+		$permission_where = '';
+		if(!is_null($permission)){
+			$permission_where = ' AND permissions = ';
+			$permission_where .= ($permission=='rw')?'"1"':'"0"';
+		}
+		return $permission_where;
+	}
+	private static function active_sql($active = null){
+		$active_where = '';
+		if(!is_null($active)){
+			$active_where = 'AND active = ';
+			$active_where .= (!is_null($active) && $active)?'1':'0';
+		}
+		return $active_where;
+	}
+	/*
+	 * @brief: checks the permission for editing an event
+	 * @param: (string) $share - userid (if $sharetype == user) / groupid (if $sharetype == group) / token (if $sharetype == public)
+	 * @param: (string) $id - id of the calendar / event
+	 * @param: (string) $type - use const self::CALENDAR or self::EVENT
+	 * @return (bool)
+	 */
+	public static function is_editing_allowed($share, $id, $type){
+		$group_where = self::group_sql(OC_Group::getUserGroups($share));
+		$permission_where = self::permission_sql('rw');
+		$stmt = OCP\DB::prepare('SELECT * FROM *PREFIX*calendar_share_' . $type . ' WHERE ((share = ? AND sharetype = "user") ' . $group_where . ') ' . $permission_where);
+		$result = $stmt->execute(array($share));
+		if($result->numRows() == 1){
+			return true;
+		}
+		if($type == self::EVENT){
+			$event = OC_Calendar_App::getEventObject($id, false, false);
+			return self::is_editing_allowed($share, $event['calendarid'], self::CALENDAR);
+		}
+		return false;
+	}
+	/*
+	 * @brief: checks the access of 
+	 * @param: (string) $share - userid (if $sharetype == user) / groupid (if $sharetype == group) / token (if $sharetype == public)
+	 * @param: (string) $id - id of the calendar / event
+	 * @param: (string) $type - use const self::CALENDAR or self::EVENT
+	 * @return (bool)
+	 */
+	public static function check_access($share, $id, $type){
+		$group_where = self::group_sql(OC_Group::getUserGroups($share));
+		$stmt = OCP\DB::prepare('SELECT * FROM *PREFIX*calendar_share_' . $type . ' WHERE (' . $type . 'id = ? AND (share = ? AND sharetype = "user") ' . $group_where . ')');
+		$result = $stmt->execute(array($id,$share));
+		$rows =  $result->numRows();
+		if($rows > 0){
+			return true;
+		}elseif($type == self::EVENT){
+			$event = OC_Calendar_App::getEventObject($id, false, false);
+			return self::check_access($share, $event['calendarid'], self::CALENDAR);
+		}else{
+			return false;
+		}
+	}
+        /*
+         * @brief: returns the calendardata of an event or a calendar
+         * @param: (string) $token - token which should be searched
+         * @return: mixed - bool if false, array with type and id if true
+         */
+        public static function getElementByToken($token){
+            $stmt_calendar = OCP\DB::prepare('SELECT * FROM *PREFIX*calendar_share_' . OC_Calendar_Share::CALENDAR . ' WHERE sharetype = "public" AND share = ?');
+            $result_calendar = $stmt_calendar->execute(array($token));
+            $stmt_event = OCP\DB::prepare('SELECT * FROM *PREFIX*calendar_share_' . OC_Calendar_Share::EVENT . ' WHERE sharetype = "public" AND share = ?');
+            $result_event = $stmt_event->execute(array($token));
+            $return = array();
+            if($result_calendar->numRows() == 0 && $result_event->numRows() == 0){
+                return false;
+            }elseif($result_calendar->numRows() != 0){
+                $return ['type'] = 'calendar';
+                $calendar = $result_calendar->fetchRow();
+                $return ['id'] = $calendar['calendarid'];
+            }else{
+                $return ['type'] = 'event';
+                $event = $result_event->fetchRow();
+                $return ['id'] = $event['eventid'];
+            }
+			return $return;
+        }
+		
+		/*
+		 * @brief sets the active status of the calendar
+		 * @param (string) $
+		 */
+		public static function set_active($share, $id, $active){
+			$stmt = OCP\DB::prepare('UPDATE *PREFIX*calendar_share_calendar SET active = ? WHERE share = ? AND sharetype = "user" AND calendarid = ?');
+			$stmt->execute(array($active, $share, $id));
+		}
+}
\ No newline at end of file
diff --git a/apps/calendar/resettimezone.php b/apps/calendar/resettimezone.php
deleted file mode 100644
index 1ef9591ae39d8f01f8bdc836b67ae20e3dab482e..0000000000000000000000000000000000000000
--- a/apps/calendar/resettimezone.php
+++ /dev/null
@@ -1,4 +0,0 @@
-<?php
-require_once ("../../lib/base.php"); 
-OC_Preferences::deleteKey(OC_USER::getUser(), 'calendar', 'timezone');
-?>
\ No newline at end of file
diff --git a/apps/calendar/settings.php b/apps/calendar/settings.php
old mode 100644
new mode 100755
index b592280271685c676b5521cd3f30d64763f66ef5..981df9ffafdd58e0af6324c08e9a98ae9937f216
--- a/apps/calendar/settings.php
+++ b/apps/calendar/settings.php
@@ -7,10 +7,10 @@
  */
 
 $tmpl = new OC_Template( 'calendar', 'settings');
-$timezone=OC_Preferences::getValue(OC_User::getUser(),'calendar','timezone','');
+$timezone=OCP\Config::getUserValue(OCP\USER::getUser(),'calendar','timezone','');
 $tmpl->assign('timezone',$timezone);
 $tmpl->assign('timezones',DateTimeZone::listIdentifiers());
 
-OC_Util::addScript('calendar','settings');
+OCP\Util::addscript('calendar','settings');
 
 return $tmpl->fetchPage();
diff --git a/apps/calendar/share.php b/apps/calendar/share.php
new file mode 100644
index 0000000000000000000000000000000000000000..1cc8a2ef15edd9708cc73f9ba3edc5fff45e3dd8
--- /dev/null
+++ b/apps/calendar/share.php
@@ -0,0 +1,23 @@
+<?php
+require_once('../../lib/base.php');
+$token = strip_tags($_GET['t']);
+$shared = OC_Calendar_Share::getElementByToken($token);
+$nl = "\n\r";
+if($shared['type'] == OC_Calendar_Share::CALENDAR){
+	$calendar = OC_Calendar_App::getCalendar($shared['id'], false);
+	$calobjects = OC_Calendar_Object::all($shared['id']);
+	header('Content-Type: text/Calendar');
+	header('Content-Disposition: inline; filename=' . $calendar['displayname'] . '.ics'); 
+	foreach($calobjects as $calobject){
+		echo $calobject['calendardata'] . $nl;
+	}
+}elseif($shared['type'] == OC_Calendar_Share::EVENT){
+	$data = OC_Calendar_App::getEventObject($shared['id'], false);
+	$calendarid = $data['calendarid'];
+	$calendar = OC_Calendar_App::getCalendar($calendarid);
+	header('Content-Type: text/Calendar');
+	header('Content-Disposition: inline; filename=' . $data['summary'] . '.ics'); 
+	echo $data['calendardata'];
+}else{
+	header('Error 404: Not Found');
+}
\ No newline at end of file
diff --git a/apps/calendar/templates/calendar.php b/apps/calendar/templates/calendar.php
index ba9423a66f19604e895848a79e244b2ebbdbd8df..7e767e367324ef006152cc0d85e384a6c2f1e117 100755
--- a/apps/calendar/templates/calendar.php
+++ b/apps/calendar/templates/calendar.php
@@ -1,13 +1,13 @@
 				<script type='text/javascript'>
-				var defaultView = '<?php echo OC_Preferences::getValue(OC_USER::getUser(), 'calendar', 'currentview', 'month') ?>';
+				var defaultView = '<?php echo OCP\Config::getUserValue(OCP\USER::getUser(), 'calendar', 'currentview', 'month') ?>';
 				var eventSources = <?php echo json_encode($_['eventSources']) ?>;
 				var categories = <?php echo json_encode($_['categories']); ?>;
 				var dayNames = <?php echo json_encode($l->tA(array('Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'))) ?>;
 				var dayNamesShort = <?php echo json_encode($l->tA(array('Sun.', 'Mon.', 'Tue.', 'Wed.', 'Thu.', 'Fri.', 'Sat.'))) ?>;
 				var monthNames = <?php echo json_encode($l->tA(array('January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'))) ?>;
 				var monthNamesShort = <?php echo json_encode($l->tA(array('Jan.', 'Feb.', 'Mar.', 'Apr.', 'May.', 'Jun.', 'Jul.', 'Aug.', 'Sep.', 'Oct.', 'Nov.', 'Dec.'))) ?>;
-				var agendatime = '<?php echo ((int) OC_Preferences::getValue(OC_USER::getUser(), 'calendar', 'timeformat', '24') == 24 ? 'HH:mm' : 'hh:mm tt'); ?>{ - <?php echo ((int) OC_Preferences::getValue(OC_USER::getUser(), 'calendar', 'timeformat', '24') == 24 ? 'HH:mm' : 'hh:mm tt'); ?>}';
-				var defaulttime = '<?php echo ((int) OC_Preferences::getValue(OC_USER::getUser(), 'calendar', 'timeformat', '24') == 24 ? 'HH:mm' : 'hh:mm tt'); ?>';
+				var agendatime = '<?php echo ((int) OCP\Config::getUserValue(OCP\USER::getUser(), 'calendar', 'timeformat', '24') == 24 ? 'HH:mm' : 'hh:mm tt'); ?>{ - <?php echo ((int) OCP\Config::getUserValue(OCP\USER::getUser(), 'calendar', 'timeformat', '24') == 24 ? 'HH:mm' : 'hh:mm tt'); ?>}';
+				var defaulttime = '<?php echo ((int) OCP\Config::getUserValue(OCP\USER::getUser(), 'calendar', 'timeformat', '24') == 24 ? 'HH:mm' : 'hh:mm tt'); ?>';
 				var allDayText = '<?php echo addslashes($l->t('All day')) ?>';
 				var newcalendar = '<?php echo addslashes($l->t('New Calendar')) ?>';
 				var missing_field = '<?php echo addslashes($l->t('Missing fields')) ?>';
@@ -19,8 +19,8 @@
 				var missing_field_totime = '<?php echo addslashes($l->t('To Time')) ?>';
 				var missing_field_startsbeforeends = '<?php echo addslashes($l->t('The event ends before it starts')) ?>';
 				var missing_field_dberror = '<?php echo addslashes($l->t('There was a database fail')) ?>';
-				var totalurl = '<?php echo OC_Helper::linkToAbsolute('calendar', 'caldav.php'); ?>/calendars';
-				var firstDay = '<?php echo (OC_Preferences::getValue(OC_USER::getUser(), 'calendar', 'firstday', 'mo') == 'mo' ? '1' : '0'); ?>';
+				var totalurl = '<?php echo OCP\Util::linkToAbsolute('calendar', 'caldav.php'); ?>/calendars';
+				var firstDay = '<?php echo (OCP\Config::getUserValue(OCP\USER::getUser(), 'calendar', 'firstday', 'mo') == 'mo' ? '1' : '0'); ?>';
 				$(document).ready(function() {
 				<?php
 				if(array_key_exists('showevent', $_)){
@@ -40,7 +40,7 @@
 								<input type="button" value="<?php echo $l->t('Week');?>" id="oneweekview_radio"/>
 								<input type="button" value="<?php echo $l->t('Month');?>" id="onemonthview_radio"/>
 								<input type="button" value="<?php echo $l->t('List');?>" id="listview_radio"/>&nbsp;&nbsp;
-								<img id="loading" src="<?php echo OC_Helper::imagePath('core', 'loading.gif'); ?>" />
+								<img id="loading" src="<?php echo OCP\Util::imagePath('core', 'loading.gif'); ?>" />
 							</div>
 						</form>
 						<form>
diff --git a/apps/calendar/templates/part.choosecalendar.php b/apps/calendar/templates/part.choosecalendar.php
old mode 100644
new mode 100755
index 86f09d6207603752e7918f3c93a8d46da9793a91..af3b82a48fc553d44a83439b623b2cafb86c36a9
--- a/apps/calendar/templates/part.choosecalendar.php
+++ b/apps/calendar/templates/part.choosecalendar.php
@@ -1,11 +1,18 @@
 <div id="choosecalendar_dialog" title="<?php echo $l->t("Choose active calendars"); ?>">
+<p><b><?php echo $l->t('Your calendars'); ?>:</b></p>
 <table width="100%" style="border: 0;">
 <?php
-$option_calendars = OC_Calendar_Calendar::allCalendars(OC_User::getUser());
+$option_calendars = OC_Calendar_Calendar::allCalendars(OCP\USER::getUser());
 for($i = 0; $i < count($option_calendars); $i++){
 	echo "<tr>";
 	$tmpl = new OC_Template('calendar', 'part.choosecalendar.rowfields');
 	$tmpl->assign('calendar', $option_calendars[$i]);
+	if(OC_Calendar_Share::allUsersSharedwith($option_calendars[$i]['id'], OC_Calendar_Share::CALENDAR) == array()){
+		$shared = false;
+	}else{
+		$shared = true;
+	}
+	$tmpl->assign('shared', $shared);
 	$tmpl->printpage();
 	echo "</tr>";
 }
@@ -20,4 +27,25 @@ for($i = 0; $i < count($option_calendars); $i++){
 		<p style="margin: 0 auto;width: 90%;"><input style="display:none;width: 90%;float: left;" type="text" id="caldav_url" onmouseover="$('#caldav_url').select();" title="<?php echo $l->t("CalDav Link"); ?>"><img id="caldav_url_close" style="height: 20px;vertical-align: middle;display: none;" src="../../core/img/actions/delete.svg" alt="close" onclick="$('#caldav_url').hide();$('#caldav_url_close').hide();"/></p>
 	</td>
 </tr>
+</table><br>
+<p><b><?php echo $l->t('Shared calendars'); ?>: </b></p>
+<table width="100%" style="border: 0;">
+<?php
+$share = OC_Calendar_Share::allSharedwithuser(OCP\USER::getUser(), OC_Calendar_Share::CALENDAR);
+$count = count($share);
+for($i = 0; $i < $count; $i++){
+	$share[$i]['calendar'] = OC_Calendar_App::getCalendar($share[$i]['calendarid'], false, false);
+	echo '<tr>';
+	$tmpl = new OC_Template('calendar', 'part.choosecalendar.rowfields.shared');
+	$tmpl->assign('share', $share[$i]);
+	$tmpl->printpage();
+	echo '</tr>';
+}
+?>
 </table>
+<?php
+if($count == 0){
+	echo '<p style="text-align:center;"><b>' . $l->t('No shared calendars') . '</b></p>';
+}
+?>
+</div>
\ No newline at end of file
diff --git a/apps/calendar/templates/part.choosecalendar.rowfields.php b/apps/calendar/templates/part.choosecalendar.rowfields.php
old mode 100644
new mode 100755
index a789be45a43d50bfa86968081d9b1eaa76048272..8848d22805404b640a558445bbbadac26c140724
--- a/apps/calendar/templates/part.choosecalendar.rowfields.php
+++ b/apps/calendar/templates/part.choosecalendar.rowfields.php
@@ -1,4 +1,8 @@
 <?php
-	echo "<td width=\"20px\"><input id=\"active_" . $_['calendar']["id"] . "\" type=\"checkbox\" onClick=\"Calendar.UI.Calendar.activation(this, " . $_['calendar']["id"] . ")\"" . ($_['calendar']["active"] ? ' checked="checked"' : '') . "></td>";
-	echo "<td><label for=\"active_" . $_['calendar']["id"] . "\">" . $_['calendar']["displayname"] . "</label></td>";
-	echo "<td width=\"20px\"><a href=\"#\" onclick=\"Calendar.UI.showCalDAVUrl('" . OC_User::getUser() . "', '" . $_['calendar']["uri"] . "');\" title=\"" . $l->t("CalDav Link") . "\" class=\"action\"><img  class=\"svg action\" src=\"../../core/img/actions/public.svg\"></a></td><td width=\"20px\"><a href=\"export.php?calid=" . $_['calendar']["id"] . "\" title=\"" . $l->t("Download") . "\" class=\"action\"><img  class=\"svg action\" src=\"../../core/img/actions/download.svg\"></a></td><td width=\"20px\"><a  href=\"#\" title=\"" . $l->t("Edit") . "\" class=\"action\" onclick=\"Calendar.UI.Calendar.edit(this, " . $_['calendar']["id"] . ");\"><img class=\"svg action\" src=\"../../core/img/actions/rename.svg\"></a></td><td width=\"20px\"><a href=\"#\" onclick=\"Calendar.UI.Calendar.deleteCalendar('" . $_['calendar']["id"] . "');\" title=\"" . $l->t("Delete") . "\" class=\"action\"><img  class=\"svg action\" src=\"../../core/img/actions/delete.svg\"></a></td>";
+echo '<td width="20px"><input id="active_' . $_['calendar']['id'] . '" type="checkbox" onClick="Calendar.UI.Calendar.activation(this,' . $_['calendar']['id'] . ')"' . ($_['calendar']['active'] ? ' checked="checked"' : '') . '></td>';
+echo '<td  id="' . OCP\USER::getUser() . '_' . $_['calendar']['id'] . '"><label for="active_' . $_['calendar']['id'] . '">' . $_['calendar']['displayname'] . '</label></td>';
+echo '<td width="20px"><a href="#" onclick="Calendar.UI.Share.dropdown(\'' . OCP\USER::getUser() . '\', \'' . $_['calendar']['id'] . '\');" title="' . $l->t("Share Calendar") . '" class="action"><img  class="svg action" src="' . ((!$_['shared']) ? '../../core/img/actions/share.svg' : '../../core/img/actions/shared.svg') . '"></a></td>';
+echo '<td width="20px"><a href="#" onclick="Calendar.UI.showCalDAVUrl(\'' . OCP\USER::getUser() . '\', \'' . $_['calendar']['uri'] . '\');" title="' . $l->t("CalDav Link") . '" class="action"><img  class="svg action" src="../../core/img/actions/public.svg"></a></td>';
+echo '<td width="20px"><a href="export.php?calid=' . $_['calendar']['id'] . '" title="' . $l->t('Download') . '" class="action"><img class="svg action" src="../../core/img/actions/download.svg"></a></td>';
+echo '<td width="20px"><a  href="#" title="' . $l->t('Edit') . '" class="action" onclick="Calendar.UI.Calendar.edit(this, ' . $_['calendar']['id'] . ');"><img class="svg action" src="../../core/img/actions/rename.svg"></a></td>';
+echo '<td width="20px"><a href="#" onclick="Calendar.UI.Calendar.deleteCalendar(\'' . $_['calendar']['id'] . '\');" title="' . $l->t('Delete') . '" class="action"><img  class="svg action" src="../../core/img/actions/delete.svg"></a></td>';
\ No newline at end of file
diff --git a/apps/calendar/templates/part.choosecalendar.rowfields.shared.php b/apps/calendar/templates/part.choosecalendar.rowfields.shared.php
new file mode 100644
index 0000000000000000000000000000000000000000..a23266da0c39a908d7c2e830b97d63111a36a161
--- /dev/null
+++ b/apps/calendar/templates/part.choosecalendar.rowfields.shared.php
@@ -0,0 +1,4 @@
+<?php
+echo '<td width="20px"><input id="active_' . $_['share']['owner'] . '_' . $_['share']['calendar']['id'] . '" type="checkbox" onClick="Calendar.UI.Share.activation(this,\'' . $_['share']['owner'] . '\',' . $_['share']['calendar']['id'] . ')"' . ($_['share']['active'] ? ' checked="checked"' : '') . '></td>';
+echo '<td><label for="active_' . $_['share']['owner'] . '_' . $_['share']['calendar']['id'] . '">' . $_['share']['calendar']['displayname'] . '</label></td>';
+echo '<td style="font-style: italic;">' .  $l->t('shared with you by') . ' ' . $_['share']['owner'] . '</td>';
\ No newline at end of file
diff --git a/apps/calendar/templates/part.editevent.php b/apps/calendar/templates/part.editevent.php
index 6e319e1b4e0fe7b67607ef735f0219c8a39e63ea..102366f8f08f67fe4204d084260461dea18155bc 100644
--- a/apps/calendar/templates/part.editevent.php
+++ b/apps/calendar/templates/part.editevent.php
@@ -1,13 +1,13 @@
 <div id="event" title="<?php echo $l->t("Edit an event");?>">
 	<form id="event_form">
-		<input type="hidden" name="id" value="<?php echo $_['id'] ?>">
+		<input type="hidden" name="id" value="<?php echo $_['eventid'] ?>">
 		<input type="hidden" name="lastmodified" value="<?php echo $_['lastmodified'] ?>">
 <?php echo $this->inc("part.eventform"); ?>
 	<div style="width: 100%;text-align: center;color: #FF1D1D;" id="errorbox"></div>
 	<span id="actions">
-		<input type="button" class="submit" style="float: left;" value="<?php echo $l->t("Submit");?>" onclick="Calendar.UI.validateEventForm('ajax/event/edit.php');">
-		<input type="button" class="submit" style="float: left;" name="delete" value="<?php echo $l->t("Delete");?>" onclick="Calendar.UI.submitDeleteEventForm('ajax/event/delete.php');">
-		<input type="button" class="submit" style="float: right;" name="export" value="<?php echo $l->t("Export");?>" onclick="window.location='export.php?eventid=<?php echo $_['id'] ?>';">
+		<input type="button" class="submit" style="float: left;" value="<?php echo $l->t("Submit");?>" onclick="Calendar.UI.validateEventForm('?app=calendar&getfile=ajax/event/edit.php');">
+		<input type="button" class="submit" style="float: left;" name="delete" value="<?php echo $l->t("Delete");?>" onclick="Calendar.UI.submitDeleteEventForm('?app=calendar&getfile=ajax/event/delete.php');">
+		<input type="button" class="submit" style="float: right;" name="export" value="<?php echo $l->t("Export");?>" onclick="window.location='?app=calendar&getfile=export.php?eventid=<?php echo $_['eventid'] ?>';">
 	</span>
 	</form>
 </div>
diff --git a/apps/calendar/templates/part.eventform.php b/apps/calendar/templates/part.eventform.php
index 3830c273a730156ac5814a413b2c0f6bdc41a6b2..1eee099d0d19e41be81770e0b5fdbd1229fa5b88 100644
--- a/apps/calendar/templates/part.eventform.php
+++ b/apps/calendar/templates/part.eventform.php
@@ -1,3 +1,19 @@
+<script type="text/javascript">
+<?php
+echo 'Calendar.UI.Share.idtype = "event";' . "\n" . 'Calendar.UI.Share.currentid = "' . $_['eventid'] . '";';
+?>
+</script>
+
+<ul>
+	<li><a href="#tabs-1"><?php echo $l->t('Eventinfo'); ?></a></li>
+	<li><a href="#tabs-2"><?php echo $l->t('Repeating'); ?></a></li>
+	<!--<li><a href="#tabs-3"><?php echo $l->t('Alarm'); ?></a></li>
+	<li><a href="#tabs-4"><?php echo $l->t('Attendees'); ?></a></li>-->
+	<?php if($_['access'] == 'owner') { ?>
+	<li><a href="#tabs-5"><?php echo $l->t('Share'); ?></a></li>
+	<?php } ?>
+</ul>
+<div id="tabs-1">
 	<table width="100%">
 		<tr>
 			<th width="75px"><?php echo $l->t("Title");?>:</th>
@@ -26,7 +42,7 @@
 			<?php } else { ?>
 			<th width="75px">&nbsp;</th>
 			<td>
-				<input type="hidden" name="calendar" value="<?php echo $_['calendar_options'][0]['id'] ?>">
+				<input type="hidden" name="calendar" value="<?php echo $_['calendar_options'][0]['id']; ?>">
 			</td>
 			<?php } ?>
 		</tr>
@@ -59,7 +75,27 @@
 	</table>
 	<input type="button" class="submit" value="<?php echo $l->t("Advanced options"); ?>" onclick="Calendar.UI.showadvancedoptions();" id="advanced_options_button">
 	<div id="advanced_options" style="display: none;">
-		<table style="width:100%">
+		<hr>
+		<table>
+			<tr>
+				<th width="85px"><?php echo $l->t("Location");?>:</th>
+				<td>
+					<input type="text" style="width:350px;" size="100" placeholder="<?php echo $l->t("Location of the Event");?>" value="<?php echo isset($_['location']) ? htmlspecialchars($_['location']) : '' ?>" maxlength="100"  name="location" />
+				</td>
+			</tr>
+		</table>
+		<table>
+			<tr>
+				<th width="85px" style="vertical-align: top;"><?php echo $l->t("Description");?>:</th>
+				<td>
+					<textarea style="width:350px;height: 150px;" placeholder="<?php echo $l->t("Description of the Event");?>" name="description"><?php echo isset($_['description']) ? htmlspecialchars($_['description']) : '' ?></textarea>
+				</td>
+			</tr>
+		</table>
+	</div>
+	</div>
+<div id="tabs-2">
+	<table style="width:100%">
 			<tr>
 				<th width="75px"><?php echo $l->t("Repeat");?>:</th>
 				<td>
@@ -112,7 +148,7 @@
 				<tr id="advanced_weekday" style="display:none;">
 					<th width="75px"></th>
 					<td id="weeklycheckbox">
-						<select id="weeklyoptions" name="weeklyoptions[]" multiple="multiple" title="<?php echo $l->t("Select weekdays") ?>">
+						<select id="weeklyoptions" name="weeklyoptions[]" multiple="multiple" style="width: 150px;" title="<?php echo $l->t("Select weekdays") ?>">
 							<?php
 							if (!isset($_['weekdays'])) {$_['weekdays'] = array();}
 							echo html_select_options($_['repeat_weekly_options'], $_['repeat_weekdays'], array('combine'=>true));
@@ -185,6 +221,7 @@
 					<td>
 						<select id="end" name="end">
 							<?php
+							if($_['repeat_end'] == '') $_['repeat_end'] = 'never';
 							echo html_select_options($_['repeat_end_options'], $_['repeat_end']); 
 							?>
 						</select>
@@ -203,23 +240,13 @@
 					</td>
 				</tr>
 			</table>
+			<?php echo $l->t('Summary'); ?>:<span id="repeatsummary"></span>
 		</div>
-		<hr>
-		<!-- support for attendees will be added in following versions --> 
-		<table>
-			<tr>
-				<th width="85px"><?php echo $l->t("Location");?>:</th>
-				<td>
-					<input type="text" style="width:350px;" size="100" placeholder="<?php echo $l->t("Location of the Event");?>" value="<?php echo isset($_['location']) ? htmlspecialchars($_['location']) : '' ?>" maxlength="100"  name="location" />
-				</td>
-			</tr>
-		</table>
-		<table>
-			<tr>
-				<th width="85px" style="vertical-align: top;"><?php echo $l->t("Description");?>:</th>
-				<td>
-					<textarea style="width:350px;height: 150px;" placeholder="<?php echo $l->t("Description of the Event");?>" name="description"><?php echo isset($_['description']) ? htmlspecialchars($_['description']) : '' ?></textarea>
-				</td>
-			</tr>
-		</table>
-	</div>
+</div>
+<!--<div id="tabs-3">//Alarm</div>
+<div id="tabs-4">//Attendees</div>-->
+<?php if($_['access'] == 'owner') { ?>
+<div id="tabs-5">
+	<?php echo $this->inc('share.dropdown'); ?>
+</div>
+<?php } ?>
diff --git a/apps/calendar/templates/part.import.php b/apps/calendar/templates/part.import.php
old mode 100644
new mode 100755
index 8f46484b42b67fa38f2ab0f052cab0238b291cc3..80375c3ef785ec0650cfbe011b88f1f6e4ff1616
--- a/apps/calendar/templates/part.import.php
+++ b/apps/calendar/templates/part.import.php
@@ -3,10 +3,10 @@
 <input type="hidden" id="filename" value="<?php echo $_['filename'];?>">
 <input type="hidden" id="path" value="<?php echo $_['path'];?>">
 <input type="hidden" id="progressfile" value="<?php echo md5(session_id()) . '.txt';?>">
-<p style="text-align:center;"><b><?php echo $l->t('Please choose the calendar'); ?></b>
+<p style="text-align:center;"><b><?php echo $l->t('Please choose the calendar'); ?></b></p>
 <select style="width:100%;" id="calendar" name="calendar">
 <?php
-$calendar_options = OC_Calendar_Calendar::allCalendars(OC_User::getUser());
+$calendar_options = OC_Calendar_Calendar::allCalendars(OCP\USER::getUser());
 $calendar_options[] = array('id'=>'newcal', 'displayname'=>$l->t('create a new calendar'));
 echo html_select_options($calendar_options, $calendar_options[0]['id'], array('value'=>'id', 'label'=>'displayname'));
 ?>
@@ -17,7 +17,7 @@ echo html_select_options($calendar_options, $calendar_options[0]['id'], array('v
 <input type="button" value="<?php echo $l->t("Import");?>!" id="startimport">
 </div>
 <div id="progressbar_container" style="display: none">
-<p style="text-align:center;"><b><?php echo $l->t('Importing calendar'); ?></b>
+<p style="text-align:center;"><b><?php echo $l->t('Importing calendar'); ?></b></p>
 <div id="progressbar"></div>
 <div id="import_done" style="display: none;">
 <p style="text-align:center;"><b><?php echo $l->t('Calendar imported successfully'); ?></b></p>
diff --git a/apps/calendar/templates/part.newevent.php b/apps/calendar/templates/part.newevent.php
index 11416260344b07c4a1f9dde7e33e9b9d9cc08b17..f4bb867b180a652f12e2909ca8e3a12f0e4f4b04 100644
--- a/apps/calendar/templates/part.newevent.php
+++ b/apps/calendar/templates/part.newevent.php
@@ -3,7 +3,7 @@
 <?php echo $this->inc("part.eventform"); ?>
 	<div style="width: 100%;text-align: center;color: #FF1D1D;" id="errorbox"></div>
 	<span id="actions">
-		<input type="button" class="submit" style="float: left;" value="<?php echo $l->t("Submit");?>" onclick="Calendar.UI.validateEventForm('ajax/event/new.php');">
+		<input type="button" class="submit" style="float: left;" value="<?php echo $l->t("Submit");?>" onclick="Calendar.UI.validateEventForm('?app=calendar&getfile=ajax/event/new.php');">
 	</span>
 	</form>
 </div>
diff --git a/apps/calendar/templates/part.showevent.php b/apps/calendar/templates/part.showevent.php
new file mode 100644
index 0000000000000000000000000000000000000000..6baf0415d5429eb7380079203e4051ad3389a2a4
--- /dev/null
+++ b/apps/calendar/templates/part.showevent.php
@@ -0,0 +1,247 @@
+<div id="event" title="<?php echo $l->t("View an event");?>">
+<ul>
+	<li><a href="#tabs-1"><?php echo $l->t('Eventinfo'); ?></a></li>
+	<li><a href="#tabs-2"><?php echo $l->t('Repeating'); ?></a></li>
+	<!--<li><a href="#tabs-3"><?php echo $l->t('Alarm'); ?></a></li>
+	<li><a href="#tabs-4"><?php echo $l->t('Attendees'); ?></a></li>-->
+</ul>
+<div id="tabs-1">
+	<table width="100%">
+		<tr>
+			<th width="75px"><?php echo $l->t("Title");?>:</th>
+			<td>
+				<?php echo isset($_['title']) ? htmlspecialchars($_['title']) : '' ?>
+			</td>
+		</tr>
+	</table>
+	<table width="100%">
+		<tr>
+			<th width="75px"><?php echo $l->t("Category");?>:</th>
+			<td>
+				<?php
+				if(count($_['categories']) == 0){
+					echo $l->t('No categories selected');
+				}else{
+					echo '<select id="category" name="categories[]" multiple="multiple" title="' .  $l->t("Select category") . '">';
+					echo html_select_options($_['categories'], $_['categories'], array('combine'=>true));
+					echo '</select>';
+				}
+				?>
+			</td>
+			<th width="75px">&nbsp;&nbsp;&nbsp;<?php echo $l->t("Calendar");?>:</th>
+			<td>
+				<select name="calendar" disabled="disabled">
+					<option>
+					<?php
+					$calendar = OC_Calendar_App::getCalendar($_['calendar']);
+					echo $calendar['displayname'] . ' ' . $l->t('of') . ' ' . $calendar['userid'];
+					?>
+					</option>
+					
+				</select>
+			</td>
+			<th width="75px">&nbsp;</th>
+			<td>
+				<input type="hidden" name="calendar" value="<?php echo $_['calendar_options'][0]['id'] ?>">
+			</td>
+		</tr>
+	</table>
+	<hr>
+	<table width="100%">
+		<tr>
+			<th width="75px"></th>
+			<td>
+				<input onclick="Calendar.UI.lockTime();" type="checkbox"<?php if($_['allday']){echo 'checked="checked"';} ?> id="allday_checkbox" name="allday" disabled="disabled">
+				<?php echo $l->t("All Day Event");?>
+			</td>
+		</tr>
+		<tr>
+			<th width="75px"><?php echo $l->t("From");?>:</th>
+			<td>
+				<?php echo $_['startdate'];?>
+				&nbsp;&nbsp; <?php echo (!$_['allday'])?$l->t('at'):''; ?> &nbsp;&nbsp;
+				<?php echo $_['starttime'];?>
+			</td>
+		</tr>
+		<tr>
+			<th width="75px"><?php echo $l->t("To");?>:</th>
+			<td>
+				<?php echo $_['enddate'];?>
+				&nbsp;&nbsp; <?php echo (!$_['allday'])?$l->t('at'):''; ?> &nbsp;&nbsp;
+				<?php echo $_['endtime'];?>
+			</td>
+		</tr>
+	</table>
+	<input type="button" class="submit" value="<?php echo $l->t("Advanced options"); ?>" onclick="Calendar.UI.showadvancedoptions();" id="advanced_options_button">
+	<div id="advanced_options" style="display: none;">
+		<hr>
+		<table>
+			<tr>
+				<th width="85px"><?php echo $l->t("Location");?>:</th>
+				<td>
+					<?php echo isset($_['location']) ? htmlspecialchars($_['location']) : '' ?>
+				</td>
+			</tr>
+		</table>
+		<table>
+			<tr>
+				<th width="85px" style="vertical-align: top;"><?php echo $l->t("Description");?>:</th>
+				<td>
+					<?php echo isset($_['description']) ? htmlspecialchars($_['description']) : '' ?></textarea>
+			</tr>
+		</table>
+	</div>
+	</div>
+<div id="tabs-2">
+	<table style="width:100%">
+			<tr>
+				<th width="75px"><?php echo $l->t("Repeat");?>:</th>
+				<td>
+				<select id="repeat" name="repeat">
+					<?php
+					echo html_select_options(array($_['repeat_options'][$_['repeat']]), $_['repeat']);
+					?>
+				</select></td>
+				<td><input type="button" style="float:right;" class="submit" value="<?php echo $l->t("Advanced"); ?>" onclick="Calendar.UI.showadvancedoptionsforrepeating();" id="advanced_options_button"></td>
+			</tr>
+		</table>
+		<div id="advanced_options_repeating" style="display:none;">
+			<table style="width:100%">
+				<tr id="advanced_month" style="display:none;">
+					<th width="75px"></th>
+					<td>
+						<select id="advanced_month_select" name="advanced_month_select">
+							<?php
+							echo html_select_options(array($_['repeat_month_options'][$_['repeat_month']]), $_['repeat_month']);
+							?>
+						</select>
+					</td>
+				</tr>
+			</table>
+			<table style="width:100%">
+				<tr id="advanced_year" style="display:none;">
+					<th width="75px"></th>
+					<td>
+						<select id="advanced_year_select" name="advanced_year_select">
+							<?php
+							echo html_select_options(array($_['repeat_year_options'][$_['repeat_year']]), $_['repeat_year']);
+							?>
+						</select>
+					</td>
+				</tr>
+			</table>
+			<table style="width:100%">
+				<tr id="advanced_weekofmonth" style="display:none;">
+					<th width="75px"></th>
+					<td id="weekofmonthcheckbox">
+						<select id="weekofmonthoptions" name="weekofmonthoptions">
+							<?php
+							echo html_select_options(array($_['repeat_weekofmonth_options'][$_['repeat_weekofmonth']]), $_['repeat_weekofmonth']);
+							?>
+						</select>
+					</td>
+				</tr>
+			</table>
+			<table style="width:100%">
+				<tr id="advanced_weekday" style="display:none;">
+					<th width="75px"></th>
+					<td id="weeklycheckbox">
+						<select id="weeklyoptions" name="weeklyoptions[]" multiple="multiple" style="width: 150px;" title="<?php echo $l->t("Select weekdays") ?>">
+							<?php
+							if (!isset($_['weekdays'])) {$_['weekdays'] = array();}
+							echo html_select_options(array($_['repeat_weekly_options'][$_['repeat_weekdays']]), $_['repeat_weekdays'], array('combine'=>true));
+							?>
+						</select>
+					</td>
+				</tr>
+			</table>
+			<table style="width:100%">
+				<tr id="advanced_byyearday" style="display:none;">
+					<th width="75px"></th>
+					<td id="byyeardaycheckbox">
+						<select id="byyearday" name="byyearday[]" multiple="multiple" title="<?php echo $l->t("Select days") ?>">
+							<?php
+							if (!isset($_['repeat_byyearday'])) {$_['repeat_byyearday'] = array();}
+							echo html_select_options(array($_['repeat_byyearday_options'][$_['repeat_byyearday']]), $_['repeat_byyearday'], array('combine'=>true));
+							?>
+						</select><?php echo $l->t('and the events day of year.'); ?>
+					</td>
+				</tr>
+			</table>
+			<table style="width:100%">
+				<tr id="advanced_bymonthday" style="display:none;">
+					<th width="75px"></th>
+					<td id="bymonthdaycheckbox">
+						<select id="bymonthday" name="bymonthday[]" multiple="multiple" title="<?php echo $l->t("Select days") ?>">
+							<?php
+							if (!isset($_['repeat_bymonthday'])) {$_['repeat_bymonthday'] = array();}
+							echo html_select_options(array($_['repeat_bymonthday_options'][$_['repeat_bymonthday']]), $_['repeat_bymonthday'], array('combine'=>true));
+							?>
+						</select><?php echo $l->t('and the events day of month.'); ?>
+					</td>
+				</tr>
+			</table>
+			<table style="width:100%">
+				<tr id="advanced_bymonth" style="display:none;">
+					<th width="75px"></th>
+					<td id="bymonthcheckbox">
+						<select id="bymonth" name="bymonth[]" multiple="multiple" title="<?php echo $l->t("Select months") ?>">
+							<?php
+							if (!isset($_['repeat_bymonth'])) {$_['repeat_bymonth'] = array();}
+							echo html_select_options(array($_['repeat_bymonth_options'][$_['repeat_bymonth']]), $_['repeat_bymonth'], array('combine'=>true));
+							?>
+						</select>
+					</td>
+				</tr>
+			</table>
+			<table style="width:100%">
+				<tr id="advanced_byweekno" style="display:none;">
+					<th width="75px"></th>
+					<td id="bymonthcheckbox">
+						<select id="byweekno" name="byweekno[]" multiple="multiple" title="<?php echo $l->t("Select weeks") ?>">
+							<?php
+							if (!isset($_['repeat_byweekno'])) {$_['repeat_byweekno'] = array();}
+							echo html_select_options(array($_['repeat_byweekno_options'][$_['repeat_byweekno']]), $_['repeat_byweekno'], array('combine'=>true));
+							?>
+						</select><?php echo $l->t('and the events week of year.'); ?>
+					</td>
+				</tr>
+			</table>
+			<table style="width:100%">
+				<tr>
+					<th width="75px"><?php echo $l->t('Interval'); ?>:</th>
+					<td>
+						<?php echo isset($_['repeat_interval']) ? $_['repeat_interval'] : '1'; ?>
+					</td>
+				</tr>
+				<tr>
+					<th width="75px"><?php echo $l->t('End'); ?>:</th>
+					<td>
+						<select id="end" name="end">
+							<?php
+							if($_['repeat_end'] == '') $_['repeat_end'] = 'never';
+							echo html_select_options(array($_['repeat_end_options'][$_['repeat_end']]), $_['repeat_end']); 
+							?>
+						</select>
+					</td>
+				</tr>
+				<tr>
+					<th></th>
+					<td id="byoccurrences" style="display:none;">
+						<?php echo $_['repeat_count'] . ' ' . $l->t('occurrences'); ?>
+					</td>
+				</tr>
+				<tr>
+					<th></th>
+					<td id="bydate" style="display:none;">
+						<?php echo $_['repeat_date']; ?>
+					</td>
+				</tr>
+			</table>
+			<?php echo $l->t('Summary'); ?>:<span id="repeatsummary"></span>
+		</div>
+</div>
+<!--<div id="tabs-3">//Alarm</div>
+<div id="tabs-4">//Attendees</div>-->
+
+</div>
\ No newline at end of file
diff --git a/apps/calendar/templates/settings.php b/apps/calendar/templates/settings.php
old mode 100644
new mode 100755
index fb2a04a64988c7ea62a06acdf46a04bd09d5fd94..ac32b79215f46a486835d908c2c0412072139631
--- a/apps/calendar/templates/settings.php
+++ b/apps/calendar/templates/settings.php
@@ -9,7 +9,7 @@
 ?>
 <form id="calendar">
         <fieldset class="personalblock">
-	<strong><?php echo $l->t('Calendar'); ?></strong>
+	<legend><?php echo $l->t('Calendar'); ?></legend>
         <table class="nostyle">
             <tr><td><label for="timezone" class="bold"><?php echo $l->t('Timezone');?></label></td><td><select style="display: none;" id="timezone" name="timezone">
                 <?php
@@ -47,6 +47,6 @@
         </table>
 
         <?php echo $l->t('Calendar CalDAV syncing address:');?>
-        <?php echo OC_Helper::linkToAbsolute('calendar', 'caldav.php'); ?><br />
+        <code><?php echo OCP\Util::linkToAbsolute('calendar', 'caldav.php'); ?></code><br />
         </fieldset>
 </form>
diff --git a/apps/calendar/templates/share.dropdown.php b/apps/calendar/templates/share.dropdown.php
new file mode 100755
index 0000000000000000000000000000000000000000..b11a4ef94cf98628c1bc3e9630b825c474bbb263
--- /dev/null
+++ b/apps/calendar/templates/share.dropdown.php
@@ -0,0 +1,77 @@
+<?php
+if(array_key_exists('calid', $_)){
+	$id = $_['calid'];
+	$sharedelements = OC_Calendar_Share::allUsersSharedwith($_['calid'], OC_Calendar_Share::CALENDAR);
+}else{
+	$sharedelements = OC_Calendar_Share::allUsersSharedwith($_['eventid'], OC_Calendar_Share::EVENT);
+	$id = $_['eventid'];
+}
+$users = array();$groups = array();$public = array();
+foreach($sharedelements as $sharedelement){
+	if($sharedelement['sharetype'] == 'user'){
+		$users[] = $sharedelement;
+	}elseif($sharedelement['sharetype'] == 'group'){
+		$groups[] = $sharedelement;
+	}elseif($sharedelement['sharetype'] == 'public'){
+		$public = $sharedelement;
+	}
+}
+?>
+<strong><?php echo $l->t('Users');?>:</strong><br>
+<select id="share_user" title="<?php echo $l->t('select users');?>" data-placeholder="<?php echo $l->t('select users'); ?>">
+<option value=""></option>
+<?php
+$allocusers = OCP\USER::getUsers();
+$allusers = array();
+foreach($allocusers as $ocuser){
+	$allusers[$ocuser] = $ocuser;
+}
+unset($allusers[OCP\USER::getUser()]);
+$allusers = array_flip($allusers);
+echo html_select_options($allusers, array());
+?>
+</select><br>
+<ul id="sharewithuser_list">
+<?php foreach($users as $user): ?>
+	<li id="sharewithuser_<?php echo $user['share']; ?>"><input type="checkbox" width="12px" <?php echo ($user['permissions']?'checked="checked"':'')?> style="visibility:hidden;" title="<?php echo $l->t('Editable'); ?>"><?php echo $user['share']; ?><img src="<?php echo  OC::$WEBROOT; ?>/core/img/actions/delete.svg" class="svg action" style="display:none;float:right;"></li>
+	<script>
+		$('#sharewithuser_<?php echo $user['share']; ?> > img').click(function(){
+			$('#share_user option[value="<?php echo $user['share']; ?>"]').removeAttr('disabled');
+			Calendar.UI.Share.unshare(<?php echo $id; ?>, '<?php echo (array_key_exists('calid', $_)?'calendar':'event');?>', '<?php echo $user['share']; ?>', 'user');
+			$('#sharewithuser_<?php echo $user['share']; ?>').remove();
+			$("#share_user").trigger("liszt:updated");
+		});
+		$('#share_user option[value="<?php echo $user['share']; ?>"]').attr('disabled', 'disabled');
+	</script>
+<?php endforeach; ?>
+</ul>
+<strong><?php echo $l->t('Groups');?>:</strong><br>
+<select id="share_group" title="<?php echo $l->t('select groups');?>" data-placeholder="<?php echo $l->t('select groups'); ?>">
+<option value=""></option> 
+<?php
+$allocgroups = OC_Group::getGroups();
+$allgroups = array();
+foreach($allocgroups as $ocgroup){
+	$allgroups[$ocgroup] = $ocgroup;
+}
+echo html_select_options($allgroups, array());
+?>
+</select><br>
+<ul id="sharewithgroup_list">
+<?php foreach($groups as $group): ?>
+	<li id="sharewithgroup_<?php echo $group['share']; ?>"><input type="checkbox" width="12px" <?php echo ($group['permissions']?'checked="checked"':'')?> style="visibility:hidden;" title="<?php echo $l->t('Editable'); ?>"><?php echo $group['share']; ?><img src="<?php echo  OC::$WEBROOT; ?>/core/img/actions/delete.svg" class="svg action" style="display:none;float:right;"></li>
+	<script>
+		$('#sharewithgroup_<?php echo $group['share']; ?> > img').click(function(){
+			$('#share_group option[value="<?php echo $group['share']; ?>"]').removeAttr('disabled');
+			Calendar.UI.Share.unshare(<?php echo $id; ?>, '<?php echo (array_key_exists('calid', $_)?'calendar':'event');?>, '<?php echo $group['share']; ?>', 'group'); ?>
+			$('#sharewithgroup_<?php echo $group['share']; ?>').remove();
+			$("#share_group").trigger("liszt:updated");
+		});
+		$('#share_group option[value="<?php echo $group['share']; ?>"]').attr('disabled', 'disabled');
+	</script>
+<?php endforeach; ?>
+</ul>
+<div id="public">
+	<input type="checkbox" id="publish" <?php echo ($public['share'])?'checked="checked"':'' ?>><label for="publish"><?php echo $l->t('make public'); ?></label><br>
+	<input type="text" id="public_token" value="<?php echo OCP\Util::linkToAbsolute('apps/calendar', 'share.php?t=' . $public['share'], null, true) ; ?>" onmouseover="$('#public_token').select();" style="<?php echo (!$public['share'])?'display:none':'' ?>">
+</div>
\ No newline at end of file
diff --git a/apps/contacts/ajax/activation.php b/apps/contacts/ajax/activation.php
old mode 100644
new mode 100755
index d69e3dba3f8ce2c7a1259fa226ef6920c2cb3e24..388a3b5438c6d35fc8e8148bddd37764f62a01df
--- a/apps/contacts/ajax/activation.php
+++ b/apps/contacts/ajax/activation.php
@@ -7,20 +7,20 @@
  * See the COPYING-README file.
  */
 
-require_once ("../../../lib/base.php");
-OC_JSON::checkLoggedIn();
-OC_JSON::checkAppEnabled('contacts');
+ 
+OCP\JSON::checkLoggedIn();
+OCP\JSON::checkAppEnabled('contacts');
 
 $bookid = $_POST['bookid'];
 $book = OC_Contacts_App::getAddressbook($bookid);// is owner access check
 
 if(!OC_Contacts_Addressbook::setActive($bookid, $_POST['active'])) {
-	OC_Log::write('contacts','ajax/activation.php: Error activating addressbook: '.$bookid, OC_Log::ERROR);
-	OC_JSON::error(array('data' => array('message' => OC_Contacts_App::$l10n->t('Error (de)activating addressbook.'))));
+	OCP\Util::writeLog('contacts','ajax/activation.php: Error activating addressbook: '.$bookid, OCP\Util::ERROR);
+	OCP\JSON::error(array('data' => array('message' => OC_Contacts_App::$l10n->t('Error (de)activating addressbook.'))));
 	exit();
 }
 
-OC_JSON::success(array(
+OCP\JSON::success(array(
 	'active' => OC_Contacts_Addressbook::isActive($bookid),
 	'bookid' => $bookid,
 	'book'   => $book,
diff --git a/apps/contacts/ajax/addbook.php b/apps/contacts/ajax/addbook.php
old mode 100644
new mode 100755
index f5852183cc340b380204c0a8ab7e705d3faeb2b0..254af1c3f50fef55158bc23b110672351bb696eb
--- a/apps/contacts/ajax/addbook.php
+++ b/apps/contacts/ajax/addbook.php
@@ -6,9 +6,9 @@
  * See the COPYING-README file.
  */
 
-require_once('../../../lib/base.php');
-OC_JSON::checkLoggedIn();
-OC_JSON::checkAppEnabled('contacts');
+ 
+OCP\JSON::checkLoggedIn();
+OCP\JSON::checkAppEnabled('contacts');
 $book = array(
 	'id' => 'new',
 	'displayname' => '',
diff --git a/apps/contacts/ajax/addcontact.php b/apps/contacts/ajax/addcontact.php
old mode 100644
new mode 100755
index 68da54655aea760a8521fe8f40e5cd575124a8e5..dc083df1fa54563768256b34ee1f15cfe8284a86
--- a/apps/contacts/ajax/addcontact.php
+++ b/apps/contacts/ajax/addcontact.php
@@ -21,19 +21,19 @@
  */
 
 // Init owncloud
-require_once('../../../lib/base.php');
+ 
 function bailOut($msg) {
-	OC_JSON::error(array('data' => array('message' => $msg)));
-	OC_Log::write('contacts','ajax/addcontact.php: '.$msg, OC_Log::DEBUG);
+	OCP\JSON::error(array('data' => array('message' => $msg)));
+	OCP\Util::writeLog('contacts','ajax/addcontact.php: '.$msg, OCP\Util::DEBUG);
 	exit();
 }
 function debug($msg) {
-	OC_Log::write('contacts','ajax/addcontact.php: '.$msg, OC_Log::DEBUG);
+	OCP\Util::writeLog('contacts','ajax/addcontact.php: '.$msg, OCP\Util::DEBUG);
 }
 
 // Check if we are a user
-OC_JSON::checkLoggedIn();
-OC_JSON::checkAppEnabled('contacts');
+OCP\JSON::checkLoggedIn();
+OCP\JSON::checkAppEnabled('contacts');
 
 foreach ($_POST as $key=>$element) {
 	debug('_POST: '.$key.'=>'.$element);
@@ -55,9 +55,9 @@ $vcard->setString('N',$n);
 
 $id = OC_Contacts_VCard::add($aid,$vcard);
 if(!$id) {
-	OC_JSON::error(array('data' => array('message' => OC_Contacts_App::$l10n->t('There was an error adding the contact.'))));
-	OC_Log::write('contacts','ajax/addcontact.php: Recieved non-positive ID on adding card: '.$id, OC_Log::ERROR);
+	OCP\JSON::error(array('data' => array('message' => OC_Contacts_App::$l10n->t('There was an error adding the contact.'))));
+	OCP\Util::writeLog('contacts','ajax/addcontact.php: Recieved non-positive ID on adding card: '.$id, OCP\Util::ERROR);
 	exit();
 }
 
-OC_JSON::success(array('data' => array( 'id' => $id )));
+OCP\JSON::success(array('data' => array( 'id' => $id )));
diff --git a/apps/contacts/ajax/addproperty.php b/apps/contacts/ajax/addproperty.php
old mode 100644
new mode 100755
index d2c0291e8c62fcf3d5230835963fbc5ec06029a5..bf23df6758509d688f1c434dd5009212824adda2
--- a/apps/contacts/ajax/addproperty.php
+++ b/apps/contacts/ajax/addproperty.php
@@ -21,11 +21,11 @@
  */
 
 // Init owncloud
-require_once('../../../lib/base.php');
+ 
 
 // Check if we are a user
-OC_JSON::checkLoggedIn();
-OC_JSON::checkAppEnabled('contacts');
+OCP\JSON::checkLoggedIn();
+OCP\JSON::checkAppEnabled('contacts');
 
 $id = isset($_POST['id'])?$_POST['id']:null;
 $name = isset($_POST['name'])?$_POST['name']:null;
@@ -37,7 +37,7 @@ $vcard = OC_Contacts_App::getContactVCard($id);
 if(!is_array($value)){
 	$value = trim($value);
 	if(!$value && in_array($name, array('TEL', 'EMAIL', 'ORG', 'BDAY', 'NICKNAME', 'NOTE'))) {
-		OC_JSON::error(array('data' => array('message' => OC_Contacts_App::$l10n->t('Cannot add empty property.'))));
+		OCP\JSON::error(array('data' => array('message' => OC_Contacts_App::$l10n->t('Cannot add empty property.'))));
 		exit();
 	}
 } elseif($name === 'ADR') { // only add if non-empty elements.
@@ -49,7 +49,7 @@ if(!is_array($value)){
 		}
 	}
 	if($empty) {
-		OC_JSON::error(array('data' => array('message' => OC_Contacts_App::$l10n->t('At least one of the address fields has to be filled out.'))));
+		OCP\JSON::error(array('data' => array('message' => OC_Contacts_App::$l10n->t('At least one of the address fields has to be filled out.'))));
 		exit();
 	}
 }
@@ -59,8 +59,8 @@ $current = $vcard->select($name);
 foreach($current as $item) {
 	$tmpvalue = (is_array($value)?implode(';', $value):$value);
 	if($tmpvalue == $item->value) {
-		OC_JSON::error(array('data' => array('message' => OC_Contacts_App::$l10n->t('Trying to add duplicate property: ').$name.': '.$tmpvalue)));
-		OC_Log::write('contacts','ajax/addproperty.php: Trying to add duplicate property: '.$name.': '.$tmpvalue, OC_Log::DEBUG);
+		OCP\JSON::error(array('data' => array('message' => OC_Contacts_App::$l10n->t('Trying to add duplicate property: ').$name.': '.$tmpvalue)));
+		OCP\Util::writeLog('contacts','ajax/addproperty.php: Trying to add duplicate property: '.$name.': '.$tmpvalue, OCP\Util::DEBUG);
 		exit();
 	}
 }
@@ -117,9 +117,9 @@ foreach ($parameters as $key=>$element) {
 $checksum = md5($vcard->children[$line]->serialize());
 
 if(!OC_Contacts_VCard::edit($id,$vcard)) {
-	OC_JSON::error(array('data' => array('message' => OC_Contacts_App::$l10n->t('Error adding contact property.'))));
-	OC_Log::write('contacts','ajax/addproperty.php: Error updating contact property: '.$name, OC_Log::ERROR);
+	OCP\JSON::error(array('data' => array('message' => OC_Contacts_App::$l10n->t('Error adding contact property.'))));
+	OCP\Util::writeLog('contacts','ajax/addproperty.php: Error updating contact property: '.$name, OCP\Util::ERROR);
 	exit();
 }
 
-OC_JSON::success(array('data' => array( 'checksum' => $checksum )));
+OCP\JSON::success(array('data' => array( 'checksum' => $checksum )));
diff --git a/apps/contacts/ajax/categories/categoriesfor.php b/apps/contacts/ajax/categories/categoriesfor.php
old mode 100644
new mode 100755
index c02c37914a22f97a379f575e94e4e52f8caf6fcd..846af300de8008d2aa8cca1f5ff30e94000070e3
--- a/apps/contacts/ajax/categories/categoriesfor.php
+++ b/apps/contacts/ajax/categories/categoriesfor.php
@@ -6,23 +6,23 @@
  * See the COPYING-README file.
  */
 
-require_once('../../../../lib/base.php');
-OC_JSON::checkLoggedIn();
-OC_JSON::checkAppEnabled('contacts');
+ 
+OCP\JSON::checkLoggedIn();
+OCP\JSON::checkAppEnabled('contacts');
 
 $id = isset($_GET['id'])?$_GET['id']:null;
 if(is_null($id)) {
-	OC_JSON::error(array('data' => array('message' => OC_Contacts_App::$l10n->t('No ID provided'))));
+	OCP\JSON::error(array('data' => array('message' => OC_Contacts_App::$l10n->t('No ID provided'))));
 	exit();
 }
 $vcard = OC_Contacts_App::getContactVCard( $id );
 foreach($vcard->children as $property){
-	//OC_Log::write('contacts','ajax/categories/checksumfor.php: '.$property->name, OC_Log::DEBUG);
+	//OCP\Util::writeLog('contacts','ajax/categories/checksumfor.php: '.$property->name, OCP\Util::DEBUG);
 	if($property->name == 'CATEGORIES') {
 		$checksum = md5($property->serialize());
-		OC_JSON::success(array('data' => array('value'=>$property->value, 'checksum'=>$checksum)));
+		OCP\JSON::success(array('data' => array('value'=>$property->value, 'checksum'=>$checksum)));
 		exit();
 	}
 }
-OC_JSON::error(array('data' => array('message' => OC_Contacts_App::$l10n->t('Error setting checksum.'))));
+OCP\JSON::error(array('data' => array('message' => OC_Contacts_App::$l10n->t('Error setting checksum.'))));
 ?>
diff --git a/apps/contacts/ajax/categories/delete.php b/apps/contacts/ajax/categories/delete.php
old mode 100644
new mode 100755
index 3ba5aa16068eced43d40eec07c245b5ba84bd898..bee2dbe3f6b7411d96fafd22e8b163e4ad8fd819
--- a/apps/contacts/ajax/categories/delete.php
+++ b/apps/contacts/ajax/categories/delete.php
@@ -6,21 +6,21 @@
  * See the COPYING-README file.
  */
 
-require_once('../../../../lib/base.php');
-OC_JSON::checkLoggedIn();
-OC_JSON::checkAppEnabled('contacts');
+ 
+OCP\JSON::checkLoggedIn();
+OCP\JSON::checkAppEnabled('contacts');
 
 foreach ($_POST as $key=>$element) {
 	debug('_POST: '.$key.'=>'.print_r($element, true));
 }
 
 function bailOut($msg) {
-	OC_JSON::error(array('data' => array('message' => $msg)));
-	OC_Log::write('contacts','ajax/categories/delete.php: '.$msg, OC_Log::DEBUG);
+	OCP\JSON::error(array('data' => array('message' => $msg)));
+	OCP\Util::writeLog('contacts','ajax/categories/delete.php: '.$msg, OCP\Util::DEBUG);
 	exit();
 }
 function debug($msg) {
-	OC_Log::write('contacts','ajax/categories/delete.php: '.$msg, OC_Log::DEBUG);
+	OCP\Util::writeLog('contacts','ajax/categories/delete.php: '.$msg, OCP\Util::DEBUG);
 }
 
 $categories = isset($_POST['categories'])?$_POST['categories']:null;
@@ -31,7 +31,7 @@ if(is_null($categories)) {
 
 debug(print_r($categories, true));
 
-$addressbooks = OC_Contacts_Addressbook::all(OC_User::getUser());
+$addressbooks = OC_Contacts_Addressbook::all(OCP\USER::getUser());
 if(count($addressbooks) == 0) {
 	bailOut(OC_Contacts_App::$l10n->t('No address books found.'));
 }
@@ -55,6 +55,6 @@ $catman = new OC_VCategories('contacts');
 $catman->delete($categories, $cards);
 debug('After delete: '.print_r($catman->categories(), true));
 OC_Contacts_VCard::updateDataByID($cards);
-OC_JSON::success(array('data' => array('categories'=>$catman->categories())));
+OCP\JSON::success(array('data' => array('categories'=>$catman->categories())));
 
 ?>
diff --git a/apps/contacts/ajax/categories/list.php b/apps/contacts/ajax/categories/list.php
old mode 100644
new mode 100755
index 64d74c82e69d3e34315fc5f3aaed658f8870b5f2..3ae7635390c8be9277c53b4e42e05f4ce9273a58
--- a/apps/contacts/ajax/categories/list.php
+++ b/apps/contacts/ajax/categories/list.php
@@ -6,12 +6,12 @@
  * See the COPYING-README file.
  */
 
-require_once('../../../../lib/base.php');
-OC_JSON::checkLoggedIn();
-OC_JSON::checkAppEnabled('contacts');
+ 
+OCP\JSON::checkLoggedIn();
+OCP\JSON::checkAppEnabled('contacts');
 
 $categories = OC_Contacts_App::getCategories();
 
-OC_JSON::success(array('data' => array('categories'=>$categories)));
+OCP\JSON::success(array('data' => array('categories'=>$categories)));
 
 ?>
diff --git a/apps/contacts/ajax/categories/rescan.php b/apps/contacts/ajax/categories/rescan.php
old mode 100644
new mode 100755
index 5f1057bab44e5a04f0eadaf6a0c252a8398f681c..84a67dec0b1832da19e4c2b83a59abe7719f2790
--- a/apps/contacts/ajax/categories/rescan.php
+++ b/apps/contacts/ajax/categories/rescan.php
@@ -6,24 +6,24 @@
  * See the COPYING-README file.
  */
 
-require_once('../../../../lib/base.php');
-OC_JSON::checkLoggedIn();
-OC_JSON::checkAppEnabled('contacts');
+ 
+OCP\JSON::checkLoggedIn();
+OCP\JSON::checkAppEnabled('contacts');
 
 foreach ($_POST as $key=>$element) {
 	debug('_POST: '.$key.'=>'.print_r($element, true));
 }
 
 function bailOut($msg) {
-	OC_JSON::error(array('data' => array('message' => $msg)));
-	OC_Log::write('contacts','ajax/categories/rescan.php: '.$msg, OC_Log::DEBUG);
+	OCP\JSON::error(array('data' => array('message' => $msg)));
+	OCP\Util::writeLog('contacts','ajax/categories/rescan.php: '.$msg, OCP\Util::DEBUG);
 	exit();
 }
 function debug($msg) {
-	OC_Log::write('contacts','ajax/categories/rescan.php: '.$msg, OC_Log::DEBUG);
+	OCP\Util::writeLog('contacts','ajax/categories/rescan.php: '.$msg, OCP\Util::DEBUG);
 }
 
-$addressbooks = OC_Contacts_Addressbook::all(OC_User::getUser());
+$addressbooks = OC_Contacts_Addressbook::all(OCP\USER::getUser());
 if(count($addressbooks) == 0) {
 	bailOut(OC_Contacts_App::$l10n->t('No address books found.'));
 }
@@ -39,6 +39,6 @@ if(count($contacts) == 0) {
 OC_Contacts_App::scanCategories($contacts);
 $categories = OC_Contacts_App::getCategories();
 
-OC_JSON::success(array('data' => array('categories'=>$categories)));
+OCP\JSON::success(array('data' => array('categories'=>$categories)));
 
 ?>
diff --git a/apps/contacts/ajax/chooseaddressbook.php b/apps/contacts/ajax/chooseaddressbook.php
old mode 100644
new mode 100755
index 8298c16b041a059cd9cbd2e3bf70ea51c28fd71a..2fe55606d1d8df714a6c618ea69dbd800e727d5b
--- a/apps/contacts/ajax/chooseaddressbook.php
+++ b/apps/contacts/ajax/chooseaddressbook.php
@@ -6,10 +6,9 @@
  * See the COPYING-README file.
  */
 
-require_once('../../../lib/base.php');
-OC_JSON::checkLoggedIn();
-OC_JSON::checkAppEnabled('contacts');
+ 
+OCP\JSON::checkLoggedIn();
+OCP\JSON::checkAppEnabled('contacts');
 
 $output = new OC_TEMPLATE("contacts", "part.chooseaddressbook");
 $output -> printpage();
-?>
diff --git a/apps/contacts/ajax/contactdetails.php b/apps/contacts/ajax/contactdetails.php
old mode 100644
new mode 100755
index 03895c862aab3ed195a885a962e6b54506e96737..0cbd55258de657434fa932eecf7738701e13514f
--- a/apps/contacts/ajax/contactdetails.php
+++ b/apps/contacts/ajax/contactdetails.php
@@ -21,19 +21,16 @@
  */
 
 // Init owncloud
-require_once('../../../lib/base.php');
+ 
 function bailOut($msg) {
-	OC_JSON::error(array('data' => array('message' => $msg)));
-	OC_Log::write('contacts','ajax/contactdetails.php: '.$msg, OC_Log::DEBUG);
+	OCP\JSON::error(array('data' => array('message' => $msg)));
+	OCP\Util::writeLog('contacts','ajax/contactdetails.php: '.$msg, OCP\Util::DEBUG);
 	exit();
 }
-function debug($msg) {
-	OC_Log::write('contacts','ajax/contactdetails.php: '.$msg, OC_Log::DEBUG);
-}
 
 // Check if we are a user
-OC_JSON::checkLoggedIn();
-OC_JSON::checkAppEnabled('contacts');
+OCP\JSON::checkLoggedIn();
+OCP\JSON::checkAppEnabled('contacts');
 
 $id = isset($_GET['id'])?$_GET['id']:null;
 if(is_null($id)) {
@@ -72,4 +69,4 @@ if(isset($details['PHOTO'])) {
 }
 $details['id'] = $id;
 OC_Contacts_App::setLastModifiedHeader($vcard);
-OC_JSON::success(array('data' => $details));
+OCP\JSON::success(array('data' => $details));
diff --git a/apps/contacts/ajax/contacts.php b/apps/contacts/ajax/contacts.php
old mode 100644
new mode 100755
index cf86764105f1a5bcadb50a0f0bf3f915dd2350a4..93e618a08007cd1626522c9183310810fede50e1
--- a/apps/contacts/ajax/contacts.php
+++ b/apps/contacts/ajax/contacts.php
@@ -6,15 +6,15 @@
  * See the COPYING-README file.
  */
 
-require_once('../../../lib/base.php');
-OC_JSON::checkLoggedIn();
-OC_JSON::checkAppEnabled('contacts');
+ 
+OCP\JSON::checkLoggedIn();
+OCP\JSON::checkAppEnabled('contacts');
 
-$ids = OC_Contacts_Addressbook::activeIds(OC_User::getUser());
+$ids = OC_Contacts_Addressbook::activeIds(OCP\USER::getUser());
 $contacts = OC_Contacts_VCard::all($ids);
 $tmpl = new OC_TEMPLATE("contacts", "part.contacts");
 $tmpl->assign('contacts', $contacts);
 $page = $tmpl->fetchPage();
 
-OC_JSON::success(array('data' => array( 'page' => $page )));
+OCP\JSON::success(array('data' => array( 'page' => $page )));
 ?>
diff --git a/apps/contacts/ajax/createaddressbook.php b/apps/contacts/ajax/createaddressbook.php
old mode 100644
new mode 100755
index 28944fe864c8de48a602f2c92cb921869adcdbb6..772232b67d7382f9a6ca25c4d8b0316f5950acc6
--- a/apps/contacts/ajax/createaddressbook.php
+++ b/apps/contacts/ajax/createaddressbook.php
@@ -6,35 +6,35 @@
  * later.
  * See the COPYING-README file.
  */
-require_once('../../../lib/base.php');
+ 
 
 // Check if we are a user
-OC_JSON::checkLoggedIn();
-OC_JSON::checkAppEnabled('contacts');
+OCP\JSON::checkLoggedIn();
+OCP\JSON::checkAppEnabled('contacts');
 
-$userid = OC_User::getUser();
+$userid = OCP\USER::getUser();
 $name = trim(strip_tags($_POST['name']));
 if(!$name) {
-	OC_JSON::error(array('data' => array('message' => OC_Contacts_App::$l10n->t('Cannot add addressbook with an empty name.'))));
-	OC_Log::write('contacts','ajax/createaddressbook.php: Cannot add addressbook with an empty name: '.strip_tags($_POST['name']), OC_Log::ERROR);
+	OCP\JSON::error(array('data' => array('message' => OC_Contacts_App::$l10n->t('Cannot add addressbook with an empty name.'))));
+	OCP\Util::writeLog('contacts','ajax/createaddressbook.php: Cannot add addressbook with an empty name: '.strip_tags($_POST['name']), OCP\Util::ERROR);
 	exit();
 }
 $bookid = OC_Contacts_Addressbook::add($userid, $name, null);
 if(!$bookid) {
-	OC_JSON::error(array('data' => array('message' => OC_Contacts_App::$l10n->t('Error adding addressbook.'))));
-	OC_Log::write('contacts','ajax/createaddressbook.php: Error adding addressbook: '.$_POST['name'], OC_Log::ERROR);
+	OCP\JSON::error(array('data' => array('message' => OC_Contacts_App::$l10n->t('Error adding addressbook.'))));
+	OCP\Util::writeLog('contacts','ajax/createaddressbook.php: Error adding addressbook: '.$_POST['name'], OCP\Util::ERROR);
 	exit();
 }
 
 if(!OC_Contacts_Addressbook::setActive($bookid, 1)) {
-	OC_JSON::error(array('data' => array('message' => OC_Contacts_App::$l10n->t('Error activating addressbook.'))));
-	OC_Log::write('contacts','ajax/createaddressbook.php: Error activating addressbook: '.$bookid, OC_Log::ERROR);
+	OCP\JSON::error(array('data' => array('message' => OC_Contacts_App::$l10n->t('Error activating addressbook.'))));
+	OCP\Util::writeLog('contacts','ajax/createaddressbook.php: Error activating addressbook: '.$bookid, OCP\Util::ERROR);
 	//exit();
 }
 $addressbook = OC_Contacts_App::getAddressbook($bookid);
 $tmpl = new OC_Template('contacts', 'part.chooseaddressbook.rowfields');
 $tmpl->assign('addressbook', $addressbook);
-OC_JSON::success(array(
+OCP\JSON::success(array(
 	'page' => $tmpl->fetchPage(),
 	'addressbook' => $addressbook,
 ));
diff --git a/apps/contacts/ajax/cropphoto.php b/apps/contacts/ajax/cropphoto.php
old mode 100644
new mode 100755
index 878fb5610c611d2a81e4a4a64804d9c2c12b98a1..125dd1076022643b752e79c4e97dd5d262305f38
--- a/apps/contacts/ajax/cropphoto.php
+++ b/apps/contacts/ajax/cropphoto.php
@@ -21,18 +21,18 @@
  */
 
 // Init owncloud
-require_once('../../../lib/base.php');
+ 
 
 // Check if we are a user
-OC_JSON::checkLoggedIn();
-OC_JSON::checkAppEnabled('contacts');
+OCP\JSON::checkLoggedIn();
+OCP\JSON::checkAppEnabled('contacts');
 
 $tmp_path = $_GET['tmp_path'];
 $id = $_GET['id'];
-OC_Log::write('contacts','ajax/cropphoto.php: tmp_path: '.$tmp_path.', exists: '.file_exists($tmp_path), OC_Log::DEBUG);
+OCP\Util::writeLog('contacts','ajax/cropphoto.php: tmp_path: '.$tmp_path.', exists: '.file_exists($tmp_path), OCP\Util::DEBUG);
 $tmpl = new OC_TEMPLATE("contacts", "part.cropphoto");
 $tmpl->assign('tmp_path', $tmp_path);
 $tmpl->assign('id', $id);
 $page = $tmpl->fetchPage();
 
-OC_JSON::success(array('data' => array( 'page' => $page )));
+OCP\JSON::success(array('data' => array( 'page' => $page )));
diff --git a/apps/contacts/ajax/currentphoto.php b/apps/contacts/ajax/currentphoto.php
new file mode 100755
index 0000000000000000000000000000000000000000..d8afa060b1eaab4326e585feab450abd352320b3
--- /dev/null
+++ b/apps/contacts/ajax/currentphoto.php
@@ -0,0 +1,68 @@
+<?php
+/**
+ * ownCloud - Addressbook
+ *
+ * @author Thomas Tanghus
+ * @copyright 2012 Thomas Tanghus <thomas@tanghus.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or any later version.
+ *
+ * This library 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 AFFERO GENERAL PUBLIC LICENSE for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public
+ * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+// Init owncloud
+//require_once('../../../lib/base.php');
+
+// Check if we are a user
+// Firefox and Konqueror tries to download application/json for me.  --Arthur
+OCP\JSON::setContentTypeHeader('text/plain');
+OCP\JSON::checkLoggedIn();
+OCP\JSON::checkAppEnabled('contacts');
+function bailOut($msg) {
+	OCP\JSON::error(array('data' => array('message' => $msg)));
+	OCP\Util::writeLog('contacts','ajax/currentphoto.php: '.$msg, OCP\Util::ERROR);
+	exit();
+}
+function debug($msg) {
+	OCP\Util::writeLog('contacts','ajax/currentphoto.php: '.$msg, OCP\Util::DEBUG);
+}
+
+if (!isset($_GET['id'])) {
+	bailOut(OC_Contacts_App::$l10n->t('No contact ID was submitted.'));
+}
+
+$tmpfname = tempnam("/tmp", "occOrig");
+$contact = OC_Contacts_App::getContactVCard($_GET['id']);
+$image = new OC_Image();
+if(!$image) {
+	bailOut(OC_Contacts_App::$l10n->t('Error loading image.'));
+}
+// invalid vcard
+if( is_null($contact)) {
+	bailOut(OC_Contacts_App::$l10n->t('Error reading contact photo.'));
+} else {
+	if(!$image->loadFromBase64($contact->getAsString('PHOTO'))) {
+		$image->loadFromBase64($contact->getAsString('LOGO'));
+	}
+	if($image->valid()) {
+		if($image->save($tmpfname)) {
+			OCP\JSON::success(array('data' => array('id'=>$_GET['id'], 'tmp'=>$tmpfname)));
+			exit();
+		} else {
+			bailOut(OC_Contacts_App::$l10n->t('Error saving temporary file.'));
+		}
+	} else {
+		bailOut(OC_Contacts_App::$l10n->t('The loading photo is not valid.'));
+	}
+}
+
+?>
diff --git a/apps/contacts/ajax/deletebook.php b/apps/contacts/ajax/deletebook.php
old mode 100644
new mode 100755
index 46d8deb48687c44f01d133bba2bf496cfc272fd5..bcf6aa4432967f78135fe16a033cc42be8000ace
--- a/apps/contacts/ajax/deletebook.php
+++ b/apps/contacts/ajax/deletebook.php
@@ -21,15 +21,15 @@
  */
 
 // Init owncloud
-require_once('../../../lib/base.php');
+ 
 
 // Check if we are a user
-OC_JSON::checkLoggedIn();
-OC_JSON::checkAppEnabled('contacts');
+OCP\JSON::checkLoggedIn();
+OCP\JSON::checkAppEnabled('contacts');
 
 //$id = $_GET['id'];
 $id = $_POST['id'];
 OC_Contacts_App::getAddressbook( $id ); // is owner access check
 
 OC_Contacts_Addressbook::delete($id);
-OC_JSON::success(array('data' => array( 'id' => $id )));
+OCP\JSON::success(array('data' => array( 'id' => $id )));
diff --git a/apps/contacts/ajax/deletecard.php b/apps/contacts/ajax/deletecard.php
old mode 100644
new mode 100755
index 5675aef5f15143d1ca5ade32a2a6b161a644d426..46fd8252d472d296267b00748e3a1d176b68152d
--- a/apps/contacts/ajax/deletecard.php
+++ b/apps/contacts/ajax/deletecard.php
@@ -20,17 +20,17 @@
  *
  */
 function bailOut($msg) {
-	OC_JSON::error(array('data' => array('message' => $msg)));
-	OC_Log::write('contacts','ajax/saveproperty.php: '.$msg, OC_Log::DEBUG);
+	OCP\JSON::error(array('data' => array('message' => $msg)));
+	OCP\Util::writeLog('contacts','ajax/saveproperty.php: '.$msg, OCP\Util::DEBUG);
 	exit();
 }
 
 // Init owncloud
-require_once('../../../lib/base.php');
+ 
 
 // Check if we are a user
-OC_JSON::checkLoggedIn();
-OC_JSON::checkAppEnabled('contacts');
+OCP\JSON::checkLoggedIn();
+OCP\JSON::checkAppEnabled('contacts');
 
 $id = isset($_GET['id'])?$_GET['id']:null;
 if(!$id) {
@@ -39,4 +39,4 @@ if(!$id) {
 $card = OC_Contacts_App::getContactObject( $id );
 
 OC_Contacts_VCard::delete($id);
-OC_JSON::success(array('data' => array( 'id' => $id )));
+OCP\JSON::success(array('data' => array( 'id' => $id )));
diff --git a/apps/contacts/ajax/deleteproperty.php b/apps/contacts/ajax/deleteproperty.php
old mode 100644
new mode 100755
index ab0958cac58ab0a6cdb5c9ff3d2da78871c9845b..9bb1208cdd1bc574311d457bee4702f38cbfab1c
--- a/apps/contacts/ajax/deleteproperty.php
+++ b/apps/contacts/ajax/deleteproperty.php
@@ -21,11 +21,11 @@
  */
 
 // Init owncloud
-require_once('../../../lib/base.php');
+ 
 
 // Check if we are a user
-OC_JSON::checkLoggedIn();
-OC_JSON::checkAppEnabled('contacts');
+OCP\JSON::checkLoggedIn();
+OCP\JSON::checkAppEnabled('contacts');
 
 $id = $_GET['id'];
 $checksum = $_GET['checksum'];
@@ -33,16 +33,16 @@ $checksum = $_GET['checksum'];
 $vcard = OC_Contacts_App::getContactVCard( $id );
 $line = OC_Contacts_App::getPropertyLineByChecksum($vcard, $checksum);
 if(is_null($line)){
-	OC_JSON::error(array('data' => array( 'message' => OC_Contacts_App::$l10n->t('Information about vCard is incorrect. Please reload the page.'))));
+	OCP\JSON::error(array('data' => array( 'message' => OC_Contacts_App::$l10n->t('Information about vCard is incorrect. Please reload the page.'))));
 	exit();
 }
 
 unset($vcard->children[$line]);
 
 if(!OC_Contacts_VCard::edit($id,$vcard)) {
-	OC_JSON::error(array('data' => array('message' => OC_Contacts_App::$l10n->t('Error deleting contact property.'))));
-	OC_Log::write('contacts','ajax/deleteproperty.php: Error deleting contact property', OC_Log::ERROR);
+	OCP\JSON::error(array('data' => array('message' => OC_Contacts_App::$l10n->t('Error deleting contact property.'))));
+	OCP\Util::writeLog('contacts','ajax/deleteproperty.php: Error deleting contact property', OCP\Util::ERROR);
 	exit();
 }
 
-OC_JSON::success(array('data' => array( 'id' => $id )));
+OCP\JSON::success(array('data' => array( 'id' => $id )));
diff --git a/apps/contacts/ajax/editaddress.php b/apps/contacts/ajax/editaddress.php
old mode 100644
new mode 100755
index 4e6456f6045d42644b5c5b1e3a76e463395355d9..4044eb5a359ffb1e4a5b28bab729a3059ea13706
--- a/apps/contacts/ajax/editaddress.php
+++ b/apps/contacts/ajax/editaddress.php
@@ -6,9 +6,9 @@
  * See the COPYING-README file.
  */
 
-require_once('../../../lib/base.php');
-OC_JSON::checkLoggedIn();
-OC_JSON::checkAppEnabled('contacts');
+ 
+OCP\JSON::checkLoggedIn();
+OCP\JSON::checkAppEnabled('contacts');
 
 $id = $_GET['id'];
 $checksum = isset($_GET['checksum'])?$_GET['checksum']:'';
diff --git a/apps/contacts/ajax/editaddressbook.php b/apps/contacts/ajax/editaddressbook.php
old mode 100644
new mode 100755
index a6262f39b23e244ea7e5b2119cc48c630e86228a..fe1806a7b8a6be532cff50fa68b3867c042d2148
--- a/apps/contacts/ajax/editaddressbook.php
+++ b/apps/contacts/ajax/editaddressbook.php
@@ -6,9 +6,9 @@
  * See the COPYING-README file.
  */
 
-require_once('../../../lib/base.php');
-OC_JSON::checkLoggedIn();
-OC_JSON::checkAppEnabled('contacts');
+ 
+OCP\JSON::checkLoggedIn();
+OCP\JSON::checkAppEnabled('contacts');
 $addressbook = OC_Contacts_App::getAddressbook($_GET['bookid']);
 $tmpl = new OC_Template("contacts", "part.editaddressbook");
 $tmpl->assign('new', false);
diff --git a/apps/contacts/ajax/editname.php b/apps/contacts/ajax/editname.php
old mode 100644
new mode 100755
index 31bdd125675445f1c173b5cb14bebb1d4224fff7..155bee70a7f2e5aa0ef91cc5dc12fe6622acb2e4
--- a/apps/contacts/ajax/editname.php
+++ b/apps/contacts/ajax/editname.php
@@ -6,21 +6,22 @@
  * See the COPYING-README file.
  */
 
-require_once('../../../lib/base.php');
-OC_JSON::checkLoggedIn();
-OC_JSON::checkAppEnabled('contacts');
+ 
+OCP\JSON::checkLoggedIn();
+OCP\JSON::checkAppEnabled('contacts');
 function bailOut($msg) {
-	OC_JSON::error(array('data' => array('message' => $msg)));
-	OC_Log::write('contacts','ajax/editname.php: '.$msg, OC_Log::DEBUG);
+	OCP\JSON::error(array('data' => array('message' => $msg)));
+	OCP\Util::writeLog('contacts','ajax/editname.php: '.$msg, OCP\Util::DEBUG);
 	exit();
 }
 function debug($msg) {
-	OC_Log::write('contacts','ajax/editname.php: '.$msg, OC_Log::DEBUG);
+	OCP\Util::writeLog('contacts','ajax/editname.php: '.$msg, OCP\Util::DEBUG);
 }
 
 $tmpl = new OC_TEMPLATE("contacts", "part.edit_name_dialog");
 
 $id = isset($_GET['id'])?$_GET['id']:'';
+debug('id: '.$id);
 if($id) {
 	$vcard = OC_Contacts_App::getContactVCard($id);
 	$name = array('', '', '', '', '');
@@ -33,8 +34,9 @@ if($id) {
 	$tmpl->assign('name',$name);
 	$tmpl->assign('id',$id);
 } else {
-	$addressbooks = OC_Contacts_Addressbook::active(OC_User::getUser());
-	$tmpl->assign('addressbooks', $addressbooks);
+	bailOut(OC_Contacts_App::$l10n->t('Contact ID is missing.'));
+	//$addressbooks = OC_Contacts_Addressbook::active(OCP\USER::getUser());
+	//$tmpl->assign('addressbooks', $addressbooks);
 }
 $tmpl->printpage();
 
diff --git a/apps/contacts/ajax/getdetails.php b/apps/contacts/ajax/getdetails.php
deleted file mode 100644
index 4819916f4c301ae8d9ab088599f55b9b3aacc53d..0000000000000000000000000000000000000000
--- a/apps/contacts/ajax/getdetails.php
+++ /dev/null
@@ -1,34 +0,0 @@
-<?php
-/**
- * ownCloud - Addressbook
- *
- * @author Jakob Sack
- * @copyright 2011 Jakob Sack mail@jakobsack.de
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or any later version.
- *
- * This library 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 AFFERO GENERAL PUBLIC LICENSE for more details.
- *
- * You should have received a copy of the GNU Affero General Public
- * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-// Init owncloud
-require_once('../../../lib/base.php');
-
-// Check if we are a user
-OC_JSON::checkLoggedIn();
-OC_JSON::checkAppEnabled('contacts');
-
-$id = $_GET['id'];
-$new = isset($_GET['new']) ? true : false;
-$vcard = OC_Contacts_App::getContactVCard( $id );
-
-OC_Contacts_App::renderDetails($id, $vcard, $new);
diff --git a/apps/contacts/ajax/importaddressbook.php b/apps/contacts/ajax/importaddressbook.php
new file mode 100755
index 0000000000000000000000000000000000000000..66cfa4f8af4362b7a1acc794999024da3a43143c
--- /dev/null
+++ b/apps/contacts/ajax/importaddressbook.php
@@ -0,0 +1,23 @@
+<?php
+/**
+ * Copyright (c) 2012 Georg Ehrke <ownclouddev at georgswebsite dot de>
+ * This file is licensed under the Affero General Public License version 3 or
+ * later.
+ * See the COPYING-README file.
+ */
+
+OCP\JSON::checkLoggedIn();
+OCP\App::checkAppEnabled('contacts');
+$upload_max_filesize = OCP\Util::computerFileSize(ini_get('upload_max_filesize'));
+$post_max_size = OCP\Util::computerFileSize(ini_get('post_max_size'));
+$maxUploadFilesize = min($upload_max_filesize, $post_max_size);
+
+$freeSpace=OC_Filesystem::free_space('/');
+$freeSpace=max($freeSpace,0);
+$maxUploadFilesize = min($maxUploadFilesize ,$freeSpace);
+
+$tmpl = new OC_Template('contacts', 'part.importaddressbook');
+$tmpl->assign('uploadMaxFilesize', $maxUploadFilesize);
+$tmpl->assign('uploadMaxHumanFilesize', OCP\Util::humanFileSize($maxUploadFilesize));
+$tmpl->printpage();
+?>
diff --git a/apps/contacts/ajax/importdialog.php b/apps/contacts/ajax/importdialog.php
old mode 100644
new mode 100755
index 280e462f662307b3ee1c4635e53ea81ef6fc6513..7a564ccec8339e3ea3e70dcf8cf9b13a0c7689e5
--- a/apps/contacts/ajax/importdialog.php
+++ b/apps/contacts/ajax/importdialog.php
@@ -6,9 +6,9 @@
  * See the COPYING-README file.
  */
 
-require_once('../../../lib/base.php');
-OC_JSON::checkLoggedIn();
-OC_Util::checkAppEnabled('contacts');
+ 
+OCP\JSON::checkLoggedIn();
+OCP\App::checkAppEnabled('contacts');
 $tmpl = new OC_Template('contacts', 'part.import');
 $tmpl->assign('path', $_POST['path']);
 $tmpl->assign('filename', $_POST['filename']);
diff --git a/apps/contacts/ajax/loadcard.php b/apps/contacts/ajax/loadcard.php
old mode 100644
new mode 100755
index 037fe2a6df279adba220b14a5484bc9baaab9740..047db4d940c7f26a0ac101dffb9c389a52f3c291
--- a/apps/contacts/ajax/loadcard.php
+++ b/apps/contacts/ajax/loadcard.php
@@ -21,25 +21,25 @@
  */
 
 // Init owncloud
-require_once('../../../lib/base.php');
+ 
 function bailOut($msg) {
-	OC_JSON::error(array('data' => array('message' => $msg)));
-	OC_Log::write('contacts','ajax/loadcard.php: '.$msg, OC_Log::DEBUG);
+	OCP\JSON::error(array('data' => array('message' => $msg)));
+	OCP\Util::writeLog('contacts','ajax/loadcard.php: '.$msg, OCP\Util::DEBUG);
 	exit();
 }
 function debug($msg) {
-	OC_Log::write('contacts','ajax/loadcard.php: '.$msg, OC_Log::DEBUG);
+	OCP\Util::writeLog('contacts','ajax/loadcard.php: '.$msg, OCP\Util::DEBUG);
 }
 // foreach ($_POST as $key=>$element) {
 // 	debug('_POST: '.$key.'=>'.$element);
 // }
 
 // Check if we are a user
-OC_JSON::checkLoggedIn();
-OC_JSON::checkAppEnabled('contacts');
+OCP\JSON::checkLoggedIn();
+OCP\JSON::checkAppEnabled('contacts');
 
-$upload_max_filesize = OC_Helper::computerFileSize(ini_get('upload_max_filesize'));
-$post_max_size = OC_Helper::computerFileSize(ini_get('post_max_size'));
+$upload_max_filesize = OCP\Util::computerFileSize(ini_get('upload_max_filesize'));
+$post_max_size = OCP\Util::computerFileSize(ini_get('post_max_size'));
 $maxUploadFilesize = min($upload_max_filesize, $post_max_size);
 
 $freeSpace=OC_Filesystem::free_space('/');
@@ -47,13 +47,15 @@ $freeSpace=max($freeSpace,0);
 $maxUploadFilesize = min($maxUploadFilesize ,$freeSpace);
 $adr_types = OC_Contacts_App::getTypesOfProperty('ADR');
 $phone_types = OC_Contacts_App::getTypesOfProperty('TEL');
+$email_types = OC_Contacts_App::getTypesOfProperty('EMAIL');
 
 $tmpl = new OC_Template('contacts','part.contact');
 $tmpl->assign('uploadMaxFilesize', $maxUploadFilesize);
-$tmpl->assign('uploadMaxHumanFilesize', OC_Helper::humanFileSize($maxUploadFilesize));
+$tmpl->assign('uploadMaxHumanFilesize', OCP\Util::humanFileSize($maxUploadFilesize));
 $tmpl->assign('adr_types',$adr_types);
 $tmpl->assign('phone_types',$phone_types);
+$tmpl->assign('email_types',$email_types);
 $tmpl->assign('id','');
 $page = $tmpl->fetchPage();
 
-OC_JSON::success(array('data' => array( 'page' => $page )));
+OCP\JSON::success(array('data' => array( 'page' => $page )));
diff --git a/apps/contacts/ajax/loadintro.php b/apps/contacts/ajax/loadintro.php
old mode 100644
new mode 100755
index 8e5673655a17541e9d1f513ba6439ef610eb98bc..8ad828ebba34ebbea7abc45241e95c5ff71f17a6
--- a/apps/contacts/ajax/loadintro.php
+++ b/apps/contacts/ajax/loadintro.php
@@ -20,43 +20,12 @@
  *
  */
 
-// Init owncloud
-require_once('../../../lib/base.php');
-function bailOut($msg) {
-	OC_JSON::error(array('data' => array('message' => $msg)));
-	OC_Log::write('contacts','ajax/loadintro.php: '.$msg, OC_Log::DEBUG);
-	exit();
-}
-function debug($msg) {
-	OC_Log::write('contacts','ajax/loadintro.php: '.$msg, OC_Log::DEBUG);
-}
-// foreach ($_POST as $key=>$element) {
-// 	debug('_POST: '.$key.'=>'.$element);
-// }
-
 // Check if we are a user
-OC_JSON::checkLoggedIn();
-OC_JSON::checkAppEnabled('contacts');
+OCP\JSON::checkLoggedIn();
+OCP\JSON::checkAppEnabled('contacts');
 
-// $addressbooks = OC_Contacts_Addressbook::all(OC_USER::getUser());
-// 
-// $upload_max_filesize = OC_Helper::computerFileSize(ini_get('upload_max_filesize'));
-// $post_max_size = OC_Helper::computerFileSize(ini_get('post_max_size'));
-// $maxUploadFilesize = min($upload_max_filesize, $post_max_size);
-// 
-// $freeSpace=OC_Filesystem::free_space('/');
-// $freeSpace=max($freeSpace,0);
-// $maxUploadFilesize = min($maxUploadFilesize ,$freeSpace);
-// $adr_types = OC_Contacts_App::getTypesOfProperty('ADR');
-// $phone_types = OC_Contacts_App::getTypesOfProperty('TEL');
 
 $tmpl = new OC_Template('contacts','part.no_contacts');
-// $tmpl->assign('uploadMaxFilesize', $maxUploadFilesize);
-// $tmpl->assign('uploadMaxHumanFilesize', OC_Helper::humanFileSize($maxUploadFilesize));
-// $tmpl->assign('adr_types',$adr_types);
-// $tmpl->assign('phone_types',$phone_types);
-// $tmpl->assign('addressbooks',$addressbooks);
-// $tmpl->assign('id','');
 $page = $tmpl->fetchPage();
 
-OC_JSON::success(array('data' => array( 'page' => $page )));
+OCP\JSON::success(array('data' => array( 'page' => $page )));
diff --git a/apps/contacts/ajax/loadphoto.php b/apps/contacts/ajax/loadphoto.php
old mode 100644
new mode 100755
index 2c8bb7bf1ed80e1097d1ba70446fea3248605b44..9913fe13e11fa8eeaa80d667e3731a271daf3658
--- a/apps/contacts/ajax/loadphoto.php
+++ b/apps/contacts/ajax/loadphoto.php
@@ -20,24 +20,25 @@
  *
  */
 // Init owncloud
-require_once('../../../lib/base.php');
+ 
 // Check if we are a user
-OC_JSON::checkLoggedIn();
-OC_JSON::checkAppEnabled('contacts');
+OCP\JSON::checkLoggedIn();
+OCP\JSON::checkAppEnabled('contacts');
 
 // foreach ($_POST as $key=>$element) {
-// 	OC_Log::write('contacts','ajax/savecrop.php: '.$key.'=>'.$element, OC_Log::DEBUG);
+// 	OCP\Util::writeLog('contacts','ajax/savecrop.php: '.$key.'=>'.$element, OCP\Util::DEBUG);
 // }
 
 function bailOut($msg) {
-	OC_JSON::error(array('data' => array('message' => $msg)));
-	OC_Log::write('contacts','ajax/loadphoto.php: '.$msg, OC_Log::DEBUG);
+	OCP\JSON::error(array('data' => array('message' => $msg)));
+	OCP\Util::writeLog('contacts','ajax/loadphoto.php: '.$msg, OCP\Util::DEBUG);
 	exit();
 }
 
 $image = null;
 
 $id = isset($_GET['id']) ? $_GET['id'] : '';
+$refresh = isset($_GET['refresh']) ? true : false;
 
 if($id == '') {
 	bailOut(OC_Contacts_App::$l10n->t('Missing contact id.'));
@@ -54,6 +55,9 @@ foreach($vcard->children as $property){
 
 $tmpl = new OC_TEMPLATE("contacts", "part.contactphoto");
 $tmpl->assign('id', $id);
+if($refresh) {
+	$tmpl->assign('refresh', 1);
+}
 $page = $tmpl->fetchPage();
-OC_JSON::success(array('data' => array('page'=>$page, 'checksum'=>$checksum)));
+OCP\JSON::success(array('data' => array('page'=>$page, 'checksum'=>$checksum)));
 ?>
diff --git a/apps/contacts/ajax/newcontact.php b/apps/contacts/ajax/newcontact.php
deleted file mode 100644
index fcfd12ca80d7600ffce43dbbd9e7afa4fda94497..0000000000000000000000000000000000000000
--- a/apps/contacts/ajax/newcontact.php
+++ /dev/null
@@ -1,62 +0,0 @@
-<?php
-/**
- * ownCloud - Addressbook
- *
- * @author Thomas Tanghus
- * @copyright 2012 Thomas Tanghus <thomas@tanghus.net>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or any later version.
- *
- * This library 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 AFFERO GENERAL PUBLIC LICENSE for more details.
- *
- * You should have received a copy of the GNU Affero General Public
- * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-// Init owncloud
-require_once('../../../lib/base.php');
-function bailOut($msg) {
-	OC_JSON::error(array('data' => array('message' => $msg)));
-	OC_Log::write('contacts','ajax/newcontact.php: '.$msg, OC_Log::DEBUG);
-	exit();
-}
-function debug($msg) {
-	OC_Log::write('contacts','ajax/newcontact.php: '.$msg, OC_Log::DEBUG);
-}
-foreach ($_POST as $key=>$element) {
-	debug('_POST: '.$key.'=>'.$element);
-}
-
-// Check if we are a user
-OC_JSON::checkLoggedIn();
-OC_JSON::checkAppEnabled('contacts');
-
-$addressbooks = OC_Contacts_Addressbook::all(OC_USER::getUser());
-
-$upload_max_filesize = OC_Helper::computerFileSize(ini_get('upload_max_filesize'));
-$post_max_size = OC_Helper::computerFileSize(ini_get('post_max_size'));
-$maxUploadFilesize = min($upload_max_filesize, $post_max_size);
-
-$freeSpace=OC_Filesystem::free_space('/');
-$freeSpace=max($freeSpace,0);
-$maxUploadFilesize = min($maxUploadFilesize ,$freeSpace);
-$adr_types = OC_Contacts_App::getTypesOfProperty('ADR');
-$phone_types = OC_Contacts_App::getTypesOfProperty('TEL');
-
-$tmpl = new OC_Template('contacts','part.contact');
-$tmpl->assign('uploadMaxFilesize', $maxUploadFilesize);
-$tmpl->assign('uploadMaxHumanFilesize', OC_Helper::humanFileSize($maxUploadFilesize));
-$tmpl->assign('adr_types',$adr_types);
-$tmpl->assign('phone_types',$phone_types);
-$tmpl->assign('addressbooks',$addressbooks);
-$tmpl->assign('id','');
-$page = $tmpl->fetchPage();
-
-OC_JSON::success(array('data' => array( 'page' => $page )));
diff --git a/apps/contacts/ajax/oc_photo.php b/apps/contacts/ajax/oc_photo.php
new file mode 100755
index 0000000000000000000000000000000000000000..0fd978e325a420f81f00860c19629d1d1e7c5e72
--- /dev/null
+++ b/apps/contacts/ajax/oc_photo.php
@@ -0,0 +1,75 @@
+<?php
+/**
+ * ownCloud - Addressbook
+ *
+ * @author Thomas Tanghus
+ * @copyright 2012 Thomas Tanghus <thomas@tanghus.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or any later version.
+ *
+ * This library 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 AFFERO GENERAL PUBLIC LICENSE for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public
+ * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+// Init owncloud
+require_once('lib/base.php');
+
+// Check if we are a user
+// Firefox and Konqueror tries to download application/json for me.  --Arthur
+OCP\JSON::setContentTypeHeader('text/plain');
+OCP\JSON::checkLoggedIn();
+OCP\JSON::checkAppEnabled('contacts');
+function bailOut($msg) {
+	OCP\JSON::error(array('data' => array('message' => $msg)));
+	OCP\Util::writeLog('contacts','ajax/oc_photo.php: '.$msg, OCP\Util::ERROR);
+	exit();
+}
+function debug($msg) {
+	OCP\Util::writeLog('contacts','ajax/oc_photo.php: '.$msg, OCP\Util::DEBUG);
+}
+
+if(!isset($_GET['id'])) {
+	bailOut(OC_Contacts_App::$l10n->t('No contact ID was submitted.'));
+}
+
+if(!isset($_GET['path'])) {
+	bailOut(OC_Contacts_App::$l10n->t('No photo path was submitted.'));
+}
+
+$localpath = OC_Filesystem::getLocalFile($_GET['path']);
+$tmpfname = tempnam("/tmp", "occOrig");
+
+if(!file_exists($localpath)) {
+	bailOut(OC_Contacts_App::$l10n->t('File doesn\'t exist:').$localpath);
+}
+file_put_contents($tmpfname, file_get_contents($localpath));
+
+$image = new OC_Image();
+if(!$image) {
+	bailOut(OC_Contacts_App::$l10n->t('Error loading image.'));
+}
+if(!$image->loadFromFile($tmpfname)) {
+	bailOut(OC_Contacts_App::$l10n->t('Error loading image.'));
+}
+if($image->width() > 400 || $image->height() > 400) {
+	$image->resize(400); // Prettier resizing than with browser and saves bandwidth.
+}
+if(!$image->fixOrientation()) { // No fatal error so we don't bail out.
+	debug('Couldn\'t save correct image orientation: '.$tmpfname);
+}
+if($image->save($tmpfname)) {
+	OCP\JSON::success(array('data' => array('id'=>$_GET['id'], 'tmp'=>$tmpfname)));
+	exit();
+} else {
+	bailOut('Couldn\'t save temporary image: '.$tmpfname);
+}
+
+?>
diff --git a/apps/contacts/ajax/savecrop.php b/apps/contacts/ajax/savecrop.php
old mode 100644
new mode 100755
index 0df4e1998cba0630765198c0b08745ee76df990f..5418e26cd1048311ea431a676f78ec8f7b003c5d
--- a/apps/contacts/ajax/savecrop.php
+++ b/apps/contacts/ajax/savecrop.php
@@ -22,41 +22,37 @@
  *       Remember to delete tmp file at some point.
  */
 // Init owncloud
-require_once('../../../lib/base.php');
-OC_Log::write('contacts','ajax/savecrop.php: Huzzah!!!', OC_Log::DEBUG);
+ 
+OCP\Util::writeLog('contacts','ajax/savecrop.php: Huzzah!!!', OCP\Util::DEBUG);
 
 // Check if we are a user
-OC_JSON::checkLoggedIn();
-OC_JSON::checkAppEnabled('contacts');
+OCP\JSON::checkLoggedIn();
+OCP\JSON::checkAppEnabled('contacts');
 
 // foreach ($_POST as $key=>$element) {
-// 	OC_Log::write('contacts','ajax/savecrop.php: '.$key.'=>'.$element, OC_Log::DEBUG);
+// 	OCP\Util::writeLog('contacts','ajax/savecrop.php: '.$key.'=>'.$element, OCP\Util::DEBUG);
 // }
 
 // Firefox and Konqueror tries to download application/json for me.  --Arthur
-OC_JSON::setContentTypeHeader('text/plain');
+OCP\JSON::setContentTypeHeader('text/plain');
 
 function bailOut($msg) {
-	OC_JSON::error(array('data' => array('message' => $msg)));
-	OC_Log::write('contacts','ajax/savecrop.php: '.$msg, OC_Log::DEBUG);
+	OCP\JSON::error(array('data' => array('message' => $msg)));
+	OCP\Util::writeLog('contacts','ajax/savecrop.php: '.$msg, OCP\Util::DEBUG);
 	exit();
 }
 
 $image = null;
 
-$x1 = (isset($_POST['x1']) && $_POST['x1']) ? $_POST['x1'] : -1;
+$x1 = (isset($_POST['x1']) && $_POST['x1']) ? $_POST['x1'] : 0;
 //$x2 = isset($_POST['x2']) ? $_POST['x2'] : -1;
-$y1 = (isset($_POST['y1']) && $_POST['y1']) ? $_POST['y1'] : -1;
+$y1 = (isset($_POST['y1']) && $_POST['y1']) ? $_POST['y1'] : 0;
 //$y2 = isset($_POST['y2']) ? $_POST['y2'] : -1;
 $w = (isset($_POST['w']) && $_POST['w']) ? $_POST['w'] : -1;
 $h = (isset($_POST['h']) && $_POST['h']) ? $_POST['h'] : -1;
 $tmp_path = isset($_POST['tmp_path']) ? $_POST['tmp_path'] : '';
 $id = isset($_POST['id']) ? $_POST['id'] : '';
 
-if(in_array(-1, array($x1, $y1, $w, $h))) {
-	bailOut('Wrong crop dimensions: '.implode(', ', array($x1, $y1, $w, $h)));
-}
-
 if($tmp_path == '') {
 	bailOut('Missing path to temporary file.');
 }
@@ -65,13 +61,16 @@ if($id == '') {
 	bailOut('Missing contact id.');
 }
 
-OC_Log::write('contacts','savecrop.php: files: '.$tmp_path.'  exists: '.file_exists($tmp_path), OC_Log::DEBUG);
+OCP\Util::writeLog('contacts','savecrop.php: files: '.$tmp_path.'  exists: '.file_exists($tmp_path), OCP\Util::DEBUG);
 
 if(file_exists($tmp_path)) {
 	$image = new OC_Image();
 	if($image->loadFromFile($tmp_path)) {
+		$w = ($w != -1 ? $w : $image->width());
+		$h = ($h != -1 ? $h : $image->height());
+		OCP\Util::writeLog('contacts','savecrop.php, x: '.$x1.' y: '.$y1.' w: '.$w.' h: '.$h, OCP\Util::DEBUG);
 		if($image->crop($x1, $y1, $w, $h)) {
-			if($image->resize(200)) {
+			if(($image->width() <= 200 && $image->height() <= 200) || $image->resize(200)) {
 				$tmpfname = tempnam("/tmp", "occCropped"); // create a new file because of caching issues.
 				if($image->save($tmpfname)) {
 					unlink($tmp_path);
@@ -81,7 +80,7 @@ if(file_exists($tmp_path)) {
 						bailOut('Error getting contact object.');
 					}
 					if($card->__isset('PHOTO')) {
-						OC_Log::write('contacts','savecrop.php: files: PHOTO property exists.', OC_Log::DEBUG);
+						OCP\Util::writeLog('contacts','savecrop.php: PHOTO property exists.', OCP\Util::DEBUG);
 						$property = $card->__get('PHOTO');
 						if(!$property) {
 							unlink($tmpfname);
@@ -92,9 +91,11 @@ if(file_exists($tmp_path)) {
 						$property->parameters[] = new Sabre_VObject_Parameter('TYPE', $image->mimeType());
 						$card->__set('PHOTO', $property);
 					} else {
-						OC_Log::write('contacts','savecrop.php: files: Adding PHOTO property.', OC_Log::DEBUG);
+						OCP\Util::writeLog('contacts','savecrop.php: files: Adding PHOTO property.', OCP\Util::DEBUG);
 						$card->addProperty('PHOTO', $image->__toString(), array('ENCODING' => 'b', 'TYPE' => $image->mimeType()));
 					}
+					$now = new DateTime;
+					$card->setString('REV', $now->format(DateTime::W3C));
 					if(!OC_Contacts_VCard::edit($id,$card)) {
 						bailOut('Error saving contact.');
 					}
@@ -108,7 +109,7 @@ if(file_exists($tmp_path)) {
 					$tmpl->assign('width', $image->width());
 					$tmpl->assign('height', $image->height());
 					$page = $tmpl->fetchPage();
-					OC_JSON::success(array('data' => array('page'=>$page, 'tmp'=>$tmpfname)));
+					OCP\JSON::success(array('data' => array('page'=>$page, 'tmp'=>$tmpfname)));
 					exit();
 				} else {
 					if(file_exists($tmpfname)) {
diff --git a/apps/contacts/ajax/saveproperty.php b/apps/contacts/ajax/saveproperty.php
old mode 100644
new mode 100755
index 99d55e7927acc7fc5115bd69c2cdbde41c9e28a1..0cd6d5b36fb74a602aad90f7bdd0582099a8e29f
--- a/apps/contacts/ajax/saveproperty.php
+++ b/apps/contacts/ajax/saveproperty.php
@@ -21,19 +21,19 @@
  */
 
 // Init owncloud
-require_once('../../../lib/base.php');
+ 
 
 // Check if we are a user
-OC_JSON::checkLoggedIn();
-OC_JSON::checkAppEnabled('contacts');
+OCP\JSON::checkLoggedIn();
+OCP\JSON::checkAppEnabled('contacts');
 
 function bailOut($msg) {
-	OC_JSON::error(array('data' => array('message' => $msg)));
-	OC_Log::write('contacts','ajax/saveproperty.php: '.$msg, OC_Log::DEBUG);
+	OCP\JSON::error(array('data' => array('message' => $msg)));
+	OCP\Util::writeLog('contacts','ajax/saveproperty.php: '.$msg, OCP\Util::DEBUG);
 	exit();
 }
 function debug($msg) {
-	OC_Log::write('contacts','ajax/saveproperty.php: '.$msg, OC_Log::DEBUG);
+	OCP\Util::writeLog('contacts','ajax/saveproperty.php: '.$msg, OCP\Util::DEBUG);
 }
 // foreach ($_POST as $key=>$element) {
 // 	debug('_POST: '.$key.'=>'.print_r($element, true));
@@ -154,4 +154,4 @@ if(!OC_Contacts_VCard::edit($id,$vcard)) {
 	exit();
 }
 
-OC_JSON::success(array('data' => array( 'line' => $line, 'checksum' => $checksum, 'oldchecksum' => $_POST['checksum'] )));
+OCP\JSON::success(array('data' => array( 'line' => $line, 'checksum' => $checksum, 'oldchecksum' => $_POST['checksum'] )));
diff --git a/apps/contacts/ajax/updateaddressbook.php b/apps/contacts/ajax/updateaddressbook.php
old mode 100644
new mode 100755
index 211df84b1d18811964964475fb76c4898e496464..13f1c15ac2333fc144fed1ed06b31b07039863e1
--- a/apps/contacts/ajax/updateaddressbook.php
+++ b/apps/contacts/ajax/updateaddressbook.php
@@ -6,38 +6,38 @@
  * See the COPYING-README file.
  */
 
-require_once('../../../lib/base.php');
+ 
 
 // Check if we are a user
-OC_JSON::checkLoggedIn();
-OC_JSON::checkAppEnabled('contacts');
+OCP\JSON::checkLoggedIn();
+OCP\JSON::checkAppEnabled('contacts');
 
 $bookid = $_POST['id'];
 OC_Contacts_App::getAddressbook($bookid); // is owner access check
 
 $name = trim(strip_tags($_POST['name']));
 if(!$name) {
-	OC_JSON::error(array('data' => array('message' => OC_Contacts_App::$l10n->t('Cannot update addressbook with an empty name.'))));
-	OC_Log::write('contacts','ajax/updateaddressbook.php: Cannot update addressbook with an empty name: '.strip_tags($_POST['name']), OC_Log::ERROR);
+	OCP\JSON::error(array('data' => array('message' => OC_Contacts_App::$l10n->t('Cannot update addressbook with an empty name.'))));
+	OCP\Util::writeLog('contacts','ajax/updateaddressbook.php: Cannot update addressbook with an empty name: '.strip_tags($_POST['name']), OCP\Util::ERROR);
 	exit();
 }
 
 if(!OC_Contacts_Addressbook::edit($bookid, $name, null)) {
-	OC_JSON::error(array('data' => array('message' => $l->t('Error updating addressbook.'))));
-	OC_Log::write('contacts','ajax/updateaddressbook.php: Error adding addressbook: ', OC_Log::ERROR);
+	OCP\JSON::error(array('data' => array('message' => $l->t('Error updating addressbook.'))));
+	OCP\Util::writeLog('contacts','ajax/updateaddressbook.php: Error adding addressbook: ', OCP\Util::ERROR);
 	//exit();
 }
 
 if(!OC_Contacts_Addressbook::setActive($bookid, $_POST['active'])) {
-	OC_JSON::error(array('data' => array('message' => $l->t('Error (de)activating addressbook.'))));
-	OC_Log::write('contacts','ajax/updateaddressbook.php: Error (de)activating addressbook: '.$bookid, OC_Log::ERROR);
+	OCP\JSON::error(array('data' => array('message' => $l->t('Error (de)activating addressbook.'))));
+	OCP\Util::writeLog('contacts','ajax/updateaddressbook.php: Error (de)activating addressbook: '.$bookid, OCP\Util::ERROR);
 	//exit();
 }
 
 $addressbook = OC_Contacts_App::getAddressbook($bookid);
 $tmpl = new OC_Template('contacts', 'part.chooseaddressbook.rowfields');
 $tmpl->assign('addressbook', $addressbook);
-OC_JSON::success(array(
+OCP\JSON::success(array(
 	'page' => $tmpl->fetchPage(),
 	'addressbook' => $addressbook,
 ));
diff --git a/apps/contacts/ajax/uploadimport.php b/apps/contacts/ajax/uploadimport.php
new file mode 100755
index 0000000000000000000000000000000000000000..99386516f5083c56281de69a99ea4685962c0ae6
--- /dev/null
+++ b/apps/contacts/ajax/uploadimport.php
@@ -0,0 +1,83 @@
+<?php
+/**
+ * ownCloud - Addressbook
+ *
+ * @author Thomas Tanghus
+ * @copyright 2012 Thomas Tanghus <thomas@tanghus.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or any later version.
+ *
+ * This library 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 AFFERO GENERAL PUBLIC LICENSE for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public
+ * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+// Check if we are a user
+OCP\JSON::checkLoggedIn();
+OCP\JSON::checkAppEnabled('contacts');
+function bailOut($msg) {
+	OCP\JSON::error(array('data' => array('message' => $msg)));
+	OCP\Util::writeLog('contacts','ajax/uploadimport.php: '.$msg, OCP\Util::ERROR);
+	exit();
+}
+function debug($msg) {
+	OCP\Util::writeLog('contacts','ajax/uploadimport.php: '.$msg, OCP\Util::DEBUG);
+}
+
+$view = OCP\App::getStorage('contacts');
+$tmpfile = md5(rand());
+
+// If it is a Drag'n'Drop transfer it's handled here.
+$fn = (isset($_SERVER['HTTP_X_FILE_NAME']) ? $_SERVER['HTTP_X_FILE_NAME'] : false);
+if($fn) {
+	if($view->file_put_contents('/'.$tmpfile, file_get_contents('php://input'))) {
+		debug($fn.' uploaded');
+		OCP\JSON::success(array('data' => array('path'=>'', 'file'=>$tmpfile)));
+		exit();
+	} else {
+		bailOut(OC_Contacts_App::$l10n->t('Error uploading contacts to storage.'));
+	}
+}
+
+// File input transfers are handled here
+if (!isset($_FILES['importfile'])) {
+	OCP\Util::writeLog('contacts','ajax/uploadphoto.php: No file was uploaded. Unknown error.', OCP\Util::DEBUG);
+	OCP\JSON::error(array('data' => array( 'message' => 'No file was uploaded. Unknown error' )));
+	exit();
+}
+$error = $_FILES['importfile']['error'];
+if($error !== UPLOAD_ERR_OK) {
+	$errors = array(
+		0=>OC_Contacts_App::$l10n->t("There is no error, the file uploaded with success"),
+		1=>OC_Contacts_App::$l10n->t("The uploaded file exceeds the upload_max_filesize directive in php.ini").ini_get('upload_max_filesize'),
+		2=>OC_Contacts_App::$l10n->t("The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form"),
+		3=>OC_Contacts_App::$l10n->t("The uploaded file was only partially uploaded"),
+		4=>OC_Contacts_App::$l10n->t("No file was uploaded"),
+		6=>OC_Contacts_App::$l10n->t("Missing a temporary folder")
+	);
+	bailOut($errors[$error]);
+}
+$file=$_FILES['importfile'];
+
+$tmpfname = tempnam("/tmp", "occOrig");
+if(file_exists($file['tmp_name'])) {
+	if($view->file_put_contents('/'.$tmpfile, file_get_contents($file['tmp_name']))) {
+		debug($fn.' uploaded');
+		OCP\JSON::success(array('data' => array('path'=>'', 'file'=>$tmpfile)));
+	} else {
+		bailOut(OC_Contacts_App::$l10n->t('Error uploading contacts to storage.'));
+	}
+} else {
+	bailOut('Temporary file: \''.$file['tmp_name'].'\' has gone AWOL?');
+}
+
+
+?>
diff --git a/apps/contacts/ajax/uploadphoto.php b/apps/contacts/ajax/uploadphoto.php
old mode 100644
new mode 100755
index 9780df464767a1cfb2a5b238f3ffb2cacc8eb1e7..99015e2d50241f46f5761008d5b4df4375805984
--- a/apps/contacts/ajax/uploadphoto.php
+++ b/apps/contacts/ajax/uploadphoto.php
@@ -20,42 +20,29 @@
  *
  */
 // Init owncloud
-require_once('../../../lib/base.php');
+ 
 
 // Check if we are a user
 // Firefox and Konqueror tries to download application/json for me.  --Arthur
-OC_JSON::setContentTypeHeader('text/plain');
-OC_JSON::checkLoggedIn();
-OC_JSON::checkAppEnabled('contacts');
+OCP\JSON::setContentTypeHeader('text/plain');
+OCP\JSON::checkLoggedIn();
+OCP\JSON::checkAppEnabled('contacts');
 function bailOut($msg) {
-	OC_JSON::error(array('data' => array('message' => $msg)));
-	OC_Log::write('contacts','ajax/uploadphoto.php: '.$msg, OC_Log::DEBUG);
+	OCP\JSON::error(array('data' => array('message' => $msg)));
+	OCP\Util::writeLog('contacts','ajax/uploadphoto.php: '.$msg, OCP\Util::DEBUG);
 	exit();
 }
 function debug($msg) {
-	OC_Log::write('contacts','ajax/uploadphoto.php: '.$msg, OC_Log::DEBUG);
+	OCP\Util::writeLog('contacts','ajax/uploadphoto.php: '.$msg, OCP\Util::DEBUG);
 }
 
-// foreach ($_SERVER as $key=>$element) {
-// 	debug('$_SERVER: '.$key.'=>'.$element);
-// }
-// foreach ($_GET as $key=>$element) {
-// 	debug('_GET: '.$key.'=>'.$element);
-// }
-// foreach ($_POST as $key=>$element) {
-// 	debug('_POST: '.$key.'=>'.$element);
-// }
-// foreach ($_FILES as $key=>$element) {
-// 	debug('_FILES: '.$key.'=>'.$element);
-// }
-
 // If it is a Drag'n'Drop transfer it's handled here.
 $fn = (isset($_SERVER['HTTP_X_FILE_NAME']) ? $_SERVER['HTTP_X_FILE_NAME'] : false);
 if ($fn) {
 	// AJAX call
 	if (!isset($_GET['id'])) {
-		OC_Log::write('contacts','ajax/uploadphoto.php: No contact ID was submitted.', OC_Log::DEBUG);
-		OC_JSON::error(array('data' => array( 'message' => 'No contact ID was submitted.' )));
+		OCP\Util::writeLog('contacts','ajax/uploadphoto.php: No contact ID was submitted.', OCP\Util::DEBUG);
+		OCP\JSON::error(array('data' => array( 'message' => 'No contact ID was submitted.' )));
 		exit();
 	}
 	$id = $_GET['id'];
@@ -71,7 +58,7 @@ if ($fn) {
 			debug('Couldn\'t save correct image orientation: '.$tmpfname);
 		}
 		if($image->save($tmpfname)) {
-			OC_JSON::success(array('data' => array('mime'=>$_SERVER['CONTENT_TYPE'], 'name'=>$fn, 'id'=>$id, 'tmp'=>$tmpfname)));
+			OCP\JSON::success(array('data' => array('mime'=>$_SERVER['CONTENT_TYPE'], 'name'=>$fn, 'id'=>$id, 'tmp'=>$tmpfname)));
 			exit();
 		} else {
 			bailOut('Couldn\'t save temporary image: '.$tmpfname);
@@ -83,13 +70,13 @@ if ($fn) {
 
 
 if (!isset($_POST['id'])) {
-	OC_Log::write('contacts','ajax/uploadphoto.php: No contact ID was submitted.', OC_Log::DEBUG);
-	OC_JSON::error(array('data' => array( 'message' => 'No contact ID was submitted.' )));
+	OCP\Util::writeLog('contacts','ajax/uploadphoto.php: No contact ID was submitted.', OCP\Util::DEBUG);
+	OCP\JSON::error(array('data' => array( 'message' => 'No contact ID was submitted.' )));
 	exit();
 }
 if (!isset($_FILES['imagefile'])) {
-	OC_Log::write('contacts','ajax/uploadphoto.php: No file was uploaded. Unknown error.', OC_Log::DEBUG);
-	OC_JSON::error(array('data' => array( 'message' => 'No file was uploaded. Unknown error' )));
+	OCP\Util::writeLog('contacts','ajax/uploadphoto.php: No file was uploaded. Unknown error.', OCP\Util::DEBUG);
+	OCP\JSON::error(array('data' => array( 'message' => 'No file was uploaded. Unknown error' )));
 	exit();
 }
 $error = $_FILES['imagefile']['error'];
@@ -117,7 +104,7 @@ if(file_exists($file['tmp_name'])) {
 			debug('Couldn\'t save correct image orientation: '.$tmpfname);
 		}
 		if($image->save($tmpfname)) {
-			OC_JSON::success(array('data' => array('mime'=>$file['type'],'size'=>$file['size'],'name'=>$file['name'], 'id'=>$_POST['id'], 'tmp'=>$tmpfname)));
+			OCP\JSON::success(array('data' => array('mime'=>$file['type'],'size'=>$file['size'],'name'=>$file['name'], 'id'=>$_POST['id'], 'tmp'=>$tmpfname)));
 			exit();
 		} else {
 			bailOut('Couldn\'t save temporary image: '.$tmpfname);
diff --git a/apps/contacts/appinfo/app.php b/apps/contacts/appinfo/app.php
old mode 100644
new mode 100755
index 85c383c4c3224a88cf54e7da546272a67e1cd406..4808ea5fa835d872ba44b98d92b418f7bca49dd1
--- a/apps/contacts/appinfo/app.php
+++ b/apps/contacts/appinfo/app.php
@@ -8,21 +8,20 @@ OC::$CLASSPATH['OC_Search_Provider_Contacts'] = 'apps/contacts/lib/search.php';
 OC_HOOK::connect('OC_User', 'post_deleteUser', 'OC_Contacts_Hooks', 'deleteUser');
 OC_HOOK::connect('OC_Calendar', 'getEvents', 'OC_Contacts_Hooks', 'getBirthdayEvents');
 OC_HOOK::connect('OC_Calendar', 'getSources', 'OC_Contacts_Hooks', 'getCalenderSources');
-OC_Hook::connect('OC_DAV', 'initialize', 'OC_Contacts_Hooks', 'initializeCardDAV');
 
-OC_App::register( array(
+OCP\App::register( array(
   'order' => 10,
   'id' => 'contacts',
   'name' => 'Contacts' ));
 
-OC_App::addNavigationEntry( array(
+OCP\App::addNavigationEntry( array(
   'id' => 'contacts_index',
   'order' => 10,
-  'href' => OC_Helper::linkTo( 'contacts', 'index.php' ),
-  'icon' => OC_Helper::imagePath( 'settings', 'users.svg' ),
-  'name' => OC_Contacts_App::$l10n->t('Contacts') ));
+  'href' => OCP\Util::linkTo( 'contacts', 'index.php' ),
+  'icon' => OCP\Util::imagePath( 'settings', 'users.svg' ),
+  'name' => OC_L10N::get('contact')->t('Contacts') ));
 
 
-OC_APP::registerPersonal('contacts','settings');
-OC_UTIL::addScript('contacts', 'loader');
+OCP\App::registerPersonal('contacts','settings');
+OCP\Util::addscript('contacts', 'loader');
 OC_Search::registerProvider('OC_Search_Provider_Contacts');
diff --git a/apps/contacts/appinfo/info.xml b/apps/contacts/appinfo/info.xml
index 0e2b13360069fd3810cdb8b770d7fdac3e74e200..55ddf42ccc1ad6b3eec09e3aa6597b8695a966b7 100644
--- a/apps/contacts/appinfo/info.xml
+++ b/apps/contacts/appinfo/info.xml
@@ -2,7 +2,6 @@
 <info>
 	<id>contacts</id>
 	<name>Contacts</name>
-	<version>0.1</version>
 	<licence>AGPL</licence>
 	<author>Jakob Sack</author>
 	<require>2</require>
diff --git a/apps/contacts/appinfo/install.php b/apps/contacts/appinfo/install.php
new file mode 100644
index 0000000000000000000000000000000000000000..172ace5b1a69a3e2c696ea872bc6bfb92bdea065
--- /dev/null
+++ b/apps/contacts/appinfo/install.php
@@ -0,0 +1,4 @@
+<?php
+if(!file_exists(OC::$WEBROOT.'/remote/carddav.php')){
+	file_put_contents(OC::$WEBROOT.'/remote/carddav.php', file_get_contents(OC::$APPSROOT . '/apps/contacts/appinfo/remote.php'));
+}
diff --git a/apps/contacts/appinfo/migrate.php b/apps/contacts/appinfo/migrate.php
old mode 100644
new mode 100755
index a6c6bc20fa4dd5f4098c5fc3e681a319bf2325cd..1400cdf79d4707d4b76da70674b430ee1c8993aa
--- a/apps/contacts/appinfo/migrate.php
+++ b/apps/contacts/appinfo/migrate.php
@@ -40,10 +40,10 @@ class OC_Migration_Provider_Contacts extends OC_Migration_Provider{
 				$idmap = array();
 				while( $row = $results->fetchRow() ){
 					// Import each bookmark, saving its id into the map	
-					$query = OC_DB::prepare( "INSERT INTO *PREFIX*contacts_addressbooks (`userid`, `displayname`, `uri`, `description`, `ctag`) VALUES (?, ?, ?, ?, ?)" );
+					$query = OCP\DB::prepare( "INSERT INTO *PREFIX*contacts_addressbooks (`userid`, `displayname`, `uri`, `description`, `ctag`) VALUES (?, ?, ?, ?, ?)" );
 					$query->execute( array( $this->uid, $row['displayname'], $row['uri'], $row['description'], $row['ctag'] ) );
 					// Map the id
-					$idmap[$row['id']] = OC_DB::insertid();
+					$idmap[$row['id']] = OCP\DB::insertid();
 				}
 				// Now tags
 				foreach($idmap as $oldid => $newid){
@@ -51,7 +51,7 @@ class OC_Migration_Provider_Contacts extends OC_Migration_Provider{
 					$results = $query->execute( array( $oldid ) );
 					while( $row = $results->fetchRow() ){
 						// Import the tags for this bookmark, using the new bookmark id
-						$query = OC_DB::prepare( "INSERT INTO *PREFIX*contacts_cards (`addressbookid`, `fullname`, `carddata`, `uri`, `lastmodified`) VALUES (?, ?, ?, ?, ?)" );
+						$query = OCP\DB::prepare( "INSERT INTO *PREFIX*contacts_cards (`addressbookid`, `fullname`, `carddata`, `uri`, `lastmodified`) VALUES (?, ?, ?, ?, ?)" );
 						$query->execute( array( $newid, $row['fullname'], $row['carddata'], $row['uri'], $row['lastmodified'] ) );	
 					}		
 				}
diff --git a/apps/contacts/carddav.php b/apps/contacts/appinfo/remote.php
old mode 100644
new mode 100755
similarity index 91%
rename from apps/contacts/carddav.php
rename to apps/contacts/appinfo/remote.php
index 654aeb66a72174ec9d73c60c76c4b3f13f6ab896..804c560e3d0414c15d067cba22ad61754b100505
--- a/apps/contacts/carddav.php
+++ b/apps/contacts/appinfo/remote.php
@@ -19,12 +19,11 @@
  * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
  *
  */
-
 // Do not load FS ...
 $RUNTIME_NOSETUPFS = true;
+require_once('../lib/base.php');
 
-require_once('../../lib/base.php');
-OC_Util::checkAppEnabled('contacts');
+OCP\App::checkAppEnabled('contacts');
 
 // Backends
 $authBackend = new OC_Connector_Sabre_Auth();
@@ -39,7 +38,7 @@ $nodes = array(
 
 // Fire up server
 $server = new Sabre_DAV_Server($nodes);
-$server->setBaseUri(OC::$APPSWEBROOT.'/apps/contacts/carddav.php');
+$server->setBaseUri(OC::$WEBROOT.'/remote/carddav.php');
 // Add plugins
 $server->addPlugin(new Sabre_DAV_Auth_Plugin($authBackend,'ownCloud'));
 $server->addPlugin(new Sabre_CardDAV_Plugin());
diff --git a/apps/contacts/appinfo/update.php b/apps/contacts/appinfo/update.php
new file mode 100644
index 0000000000000000000000000000000000000000..b87241b2db1345c6073737f449064cba14de1b82
--- /dev/null
+++ b/apps/contacts/appinfo/update.php
@@ -0,0 +1,4 @@
+<?php
+if(!file_exists(OC::$WEBROOT.'/remote/carddav.php')){
+	file_put_contents(OC::$WEBROOT.'/remote/carddav.php', file_get_contents(OC::$APPROOT . '/apps/contacts/appinfo/remote.php'));
+}
\ No newline at end of file
diff --git a/apps/contacts/appinfo/version b/apps/contacts/appinfo/version
new file mode 100644
index 0000000000000000000000000000000000000000..ceab6e11ece0bcec917c12e11d350946f085d549
--- /dev/null
+++ b/apps/contacts/appinfo/version
@@ -0,0 +1 @@
+0.1
\ No newline at end of file
diff --git a/apps/contacts/css/contacts.css b/apps/contacts/css/contacts.css
index 2d207943841cd22c05cad9d0ded891b77c8bd9d2..4b09e810bb618ca5640e44e38bcff0f81a08b988 100644
--- a/apps/contacts/css/contacts.css
+++ b/apps/contacts/css/contacts.css
@@ -1,27 +1,31 @@
 /*dl > dt {
 	font-weight: bold;
 }*/
-
-#contacts { padding-left:2px; padding-top: 5px; background: #fff; }
+#leftcontent { top: 3.5em !important; }
+#rightcontent { top: 3.5em !important; padding-top: 5px; }
+#contacts { background: #fff; width: 20em; top: 3.7em; bottom:3em; position: fixed; overflow: auto; }
+#bottomcontrols { padding: 0; bottom:0px; height:2.8em; width: 20em; margin:0; background:#eee; border-top:1px solid #ccc; position:fixed; -moz-box-shadow: 0 0 0 #000, -3px 0 7px #000; -webkit-box-shadow: 0 0 0 #000, -3px 0 7px #000; box-shadow: 0 0 0 #000, -3px 0 7px #000;}
+#contacts_newcontact { float: left; margin: 0.2em 0 0 1em; }
+#chooseaddressbook { float: right; margin: 0.2em 1em 0 0; }
 #leftcontent a { height: 23px; display: block; margin: 0 0 0 0; padding: 0 0 0 25px; }
-#chooseaddressbook {margin-right: 170px; float: right;}
-#contacts_deletecard {position:absolute;top:15px;right:25px;}
-#contacts_downloadcard {position:absolute;top:15px;right:50px;}
-#contacts_propertymenu_button { position:absolute;top:15px;right:150px; background:url('../../../core/img/actions/add.svg') no-repeat center;	 }
+#actionbar { height: 30px; width: 60px; position: fixed; right: 0px; top: 4em; margin: 0 0 0 0; padding: 0 0 0 0; z-index: 1000; }
+#contacts_deletecard {position:absolute;top:15px;right:25px; background:url('%webroot%/core/img/actions/delete.svg') no-repeat center; }
+#contacts_downloadcard {position:absolute;top:15px;right:50px; background:url('%webroot%/core/img/actions/download.svg') no-repeat center; }
+#contacts_propertymenu_button { position:absolute;top:15px;right:150px; background:url('%webroot%/core/img/actions/add.svg') no-repeat center; }
 #contacts_propertymenu { background-color: #fff; position:absolute;top:40px;right:150px; overflow:hidden; text-overflow:ellipsis; /*border: thin solid #1d2d44;*/  -moz-box-shadow:0 0 10px #000; -webkit-box-shadow:0 0 10px #000; box-shadow:0 0 10px #000; -moz-border-radius:0.5em; -webkit-border-radius:0.5em; border-radius:0.5em; -moz-border-radius:0.5em; -webkit-border-radius:0.5em; border-radius:0.5em; }
 #contacts_propertymenu li { display: block; font-weight: bold; height: 20px; width: 100px; }
 #contacts_propertymenu li a { padding: 3px; display: block }
 #contacts_propertymenu li:hover { background-color: #1d2d44; }
 #contacts_propertymenu li a:hover { color: #fff }
-#actionbar { height: 30px; width: 200px; position: fixed; right: 0px; top: 75px; margin: 0 0 0 0; padding: 0 0 0 0; z-index: 1000; }
 #card { width: auto;/*max-width: 70em; border: thin solid lightgray; display: block;*/ }
 #firstrun { width: 100%; position: absolute; top: 5em; left: 0; text-align: center; font-weight:bold; font-size:1.5em; color:#777; }
 #firstrun #selections { font-size:0.8em; margin: 2em auto auto auto; clear: both; }
 
-#card input[type="text"].contacts_property,input[type="email"].contacts_property { width: 14em; float: left; }
+#card input[type="text"].contacts_property,input[type="email"].contacts_property { width: 14em; float: left; font-weight: bold; }
 .categories { float: left; width: 16em; }
 #card input[type="text"],input[type="email"],input[type="tel"],input[type="date"], select, textarea { background-color: #fefefe; border: 0 !important; -webkit-appearance:none !important; -moz-appearance:none  !important; -webkit-box-sizing:none !important; -moz-box-sizing:none !important; box-sizing:none !important; -moz-box-shadow: none; -webkit-box-shadow: none; box-shadow: none; -moz-border-radius: 0px; -webkit-border-radius: 0px; border-radius: 0px; float: left; }
-#card input[type="text"]:hover, input[type="text"]:focus, input[type="text"]:active,input[type="email"]:hover,input[type="tel"]:hover,input[type="date"]:hover,input[type="date"],input[type="date"]:hover,input[type="date"]:active,input[type="date"]:active,input[type="date"]:active,input[type="email"]:active,input[type="tel"]:active, select:hover, select:focus, select:active, textarea:focus, textarea:hover { border: 0 !important; -webkit-appearance:textfield; -moz-appearance:textfield; -webkit-box-sizing:content-box; -moz-box-sizing:content-box; box-sizing:content-box; background:#fff; color:#333; border:1px solid #ddd; -moz-box-shadow:0 1px 1px #fff, 0 2px 0 #bbb inset; -webkit-box-shadow:0 1px 1px #fff, 0 1px 0 #bbb inset; box-shadow:0 1px 1px #fff, 0 1px 0 #bbb inset; -moz-border-radius:.5em; -webkit-border-radius:.5em; border-radius:.5em; outline:none; float: left; }
+#card input[type="text"]:hover, input[type="text"]:focus, input[type="text"]:active,input[type="email"]:hover,input[type="tel"]:hover,input[type="date"]:hover,input[type="date"],input[type="date"]:hover,input[type="date"]:active,input[type="date"]:active,input[type="date"]:active,input[type="email"]:active,input[type="tel"]:active, select:hover, select:focus, select:active { border: 0 !important; -webkit-appearance:textfield; -moz-appearance:textfield; -webkit-box-sizing:content-box; -moz-box-sizing:content-box; box-sizing:content-box; background:#fff; color:#333; border:1px solid #ddd; -moz-box-shadow:0 1px 1px #fff, 0 2px 0 #bbb inset; -webkit-box-shadow:0 1px 1px #fff, 0 1px 0 #bbb inset; box-shadow:0 1px 1px #fff, 0 1px 0 #bbb inset; -moz-border-radius:.5em; -webkit-border-radius:.5em; border-radius:.5em; outline:none; float: left; }
+textarea:focus, textarea:hover { background:#fff; color:#333; border:1px solid #ddd; -moz-box-shadow:0 1px 1px #fff, 0 2px 0 #bbb inset; -webkit-box-shadow:0 1px 1px #fff, 0 1px 0 #bbb inset; box-shadow:0 1px 1px #fff, 0 1px 0 #bbb inset; -moz-border-radius:.5em; -webkit-border-radius:.5em; border-radius:.5em; outline:none; float: left; }
 input[type="text"]:invalid,input[type="email"]:invalid,input[type="tel"]:invalid,input[type="date"]:invalid, textarea:invalid { color: #bbb !important; }
 textarea { min-height: 4em; }
 dl.form { width: 100%; float: left; clear: right; margin: 0; padding: 0; }
@@ -29,19 +33,25 @@ dl.form { width: 100%; float: left; clear: right; margin: 0; padding: 0; }
 .form dd { display: table-cell; clear: right; float: left; margin: 0; padding: 0px; white-space: nowrap; vertical-align: text-bottom; }
 #address.form dt { min-width: 5em; }
 #address.form dl { min-width: 10em; }
-
-.loading { background: url('../../../core/img/loading.gif') no-repeat center !important; /*cursor: progress; */ cursor: wait; }
-.ui-autocomplete-loading { background: url('../../../core/img/loading.gif') right center no-repeat; }
+.droptarget { margin: 0.5em; padding: 0.5em; border: thin solid #ccc; -moz-border-radius:.3em; -webkit-border-radius:.3em; border-radius:.3em; }
+.droppable { margin: 0.5em; padding: 0.5em; border: thin dashed #333; -moz-border-radius:.3em; -webkit-border-radius:.3em; border-radius:.3em; }
+.loading { background: url('%webroot%/core/img/loading.gif') no-repeat center !important; /*cursor: progress; */ cursor: wait; }
+.ui-autocomplete-loading { background: url('%webroot%/core/img/loading.gif') right center no-repeat; }
 .float { float: left; }
+.svg { border: inherit; background: inherit; }
 .listactions { height: 1em; width:60px; float: left; clear: right; }
-.add,.edit,.delete,.mail, .globe { cursor: pointer; width: 20px; height: 20px; margin: 0; float: left; position:relative; display: none; }
-.add { background:url('../../../core/img/actions/add.svg') no-repeat center; clear: both; }
-.delete { background:url('../../../core/img/actions/delete.svg') no-repeat center; }
-.edit { background:url('../../../core/img/actions/rename.svg') no-repeat center; }
-.mail { background:url('../../../core/img/actions/mail.svg') no-repeat center; }
+.add,.edit,.delete,.mail, .globe, .upload, .download, .cloud { cursor: pointer; width: 20px; height: 20px; margin: 0; float: left; position:relative; opacity: 0.1; }
+.add:hover,.edit:hover,.delete:hover,.mail:hover, .globe:hover, .upload:hover, .download:hover .cloud:hover { opacity: 1.0 }
+.add { background:url('%webroot%/core/img/actions/add.svg') no-repeat center; clear: both; }
+.delete { background:url('%webroot%/core/img/actions/delete.svg') no-repeat center; }
+.edit { background:url('%webroot%/core/img/actions/rename.svg') no-repeat center; }
+.mail { background:url('%webroot%/core/img/actions/mail.svg') no-repeat center; }
+.upload { background:url('%webroot%/core/img/actions/upload.svg') no-repeat center; }
+.download { background:url('%webroot%/core/img/actions/download.svg') no-repeat center; }
+.cloud { background:url('%webroot%/core/img/places/picture.svg') no-repeat center; }
 /*.globe { background:url('../img/globe.svg') no-repeat center; }*/
-.globe { background:url('../../../core/img/actions/public.svg') no-repeat center; }
-
+.globe { background:url('%webroot%/core/img/actions/public.svg') no-repeat center; }
+.transparent{ opacity: 0.6; }
 #edit_name_dialog { padding:0; }
 #edit_name_dialog > input { width: 15em; }
 #edit_address_dialog { /*width: 30em;*/ }
@@ -52,19 +62,26 @@ dl.form { width: 100%; float: left; clear: right; margin: 0; padding: 0; }
 #identityprops { /*position: absolute; top: 2.5em; left: 0px;*/ }
 /*#contact_photo { max-width: 250px; }*/
 #contact_identity { min-width: 30em; }
+#note { min-width: 200px; }
 .contactsection { position: relative; float: left; /*max-width: 40em;*/ padding: 0.5em; height: auto: border: thin solid lightgray;/* -webkit-border-radius: 0.5em; -moz-border-radius: 0.5em; border-radius: 0.5em; background-color: #f8f8f8;*/ }
 
-.contactpart legend { width:auto; padding:.3em; border:1px solid #ddd; font-weight:bold; cursor:pointer; background:#f8f8f8; color:#555; text-shadow:#fff 0 1px 0; -moz-box-shadow:0 1px 1px #fff, 0 1px 1px #fff inset; -webkit-box-shadow:0 1px 1px #fff, 0 1px 1px #fff inset; -moz-border-radius:.5em; -webkit-border-radius:.5em; border-radius:.5em; }
+/*.contactpart legend { width:auto; padding:.3em; border:1px solid #ddd; font-weight:bold; cursor:pointer; background:#f8f8f8; color:#555; text-shadow:#fff 0 1px 0; -moz-box-shadow:0 1px 1px #fff, 0 1px 1px #fff inset; -webkit-box-shadow:0 1px 1px #fff, 0 1px 1px #fff inset; -moz-border-radius:.5em; -webkit-border-radius:.5em; border-radius:.5em; } */
 #cropbox { margin: auto; }
-#contacts_details_photo { border-radius: 0.5em; border: thin solid #bbb; margin: 0.3em; cursor: pointer; background: url(../../../core/img/loading.gif) no-repeat center center; display: block; /* clear: right;*/ }
-#contacts_details_photo:hover { background: #fff; }
-/*#contacts_details_photo_progress { margin: 0.3em 0.3em 0.3em 7em; clear: left; }*/
+#contacts_details_photo { border-radius: 0.5em; border: thin solid #bbb; margin: 0.3em; background: url('%webroot%/core/img/loading.gif') no-repeat center center; -moz-box-shadow: 0 1px 3px #777; -webkit-box-shadow: 0 1px 3px #777; box-shadow: 0 1px 3px #777; }
+#contacts_details_photo:hover { background: #fff; cursor: default; }
+#phototools { position:absolute; margin: 5px 0 0 10px; width:auto; height:22px; padding:0px; background-color:#fff; list-style-type:none; border-radius: 0.5em; -moz-box-shadow: 0 1px 3px #777; -webkit-box-shadow: 0 1px 3px #777; box-shadow: 0 1px 3px #777; }
+#phototools li { display: inline; }
+#phototools li a { float:left; cursor:pointer; width:22px; height:22px; opacity: 0.6; }
+#phototools li a:hover { opacity: 0.8; }
+
 /* Address editor */
 #addressdisplay { padding: 0.5em; }
-dl.addresscard { background-color: #fff; float: left; width: 45%; margin: 0 0.3em 0.3em 0.3em; padding: 0; border: thin solid lightgray; }
+dl.addresscard { background-color: #fff; float: left; width: auto; margin: 0 0.3em 0.3em 0.3em; padding: 0; border: 0; }
 dl.addresscard dd {}
-dl.addresscard dt { padding: 0.3em; border-bottom: thin solid lightgray; font-weight: bold; clear: both;}
+dl.addresscard dt { padding: 0.3em; /*border-bottom: thin solid lightgray;*/ font-weight: bold; clear: both; color: #bbb;}
+dl.addresscard dt:hover { color:#777; }
 dl.addresscard dd > ul { margin: 0.3em; padding: 0.3em; }
+dl.addresscard .action { float: right; }
 #adr_type {} /* Select */
 #adr_pobox {}
 #adr_extended {}
@@ -74,18 +91,17 @@ dl.addresscard dd > ul { margin: 0.3em; padding: 0.3em; }
 #adr_zipcode {}
 #adr_country {}
 
-#file_upload_target, #crop_target { display:none; }
+#file_upload_target, #import_upload_target, #crop_target { display:none; }
 
-#file_upload_start { opacity:0; filter:alpha(opacity=0); z-index:1; /*position:absolute; left:0; top:0;*/ cursor:pointer; width:0; height:0;}
+#file_upload_start, #import_upload_start { opacity:0; filter:alpha(opacity=0); z-index:1; /*position:absolute; left:0; top:0;*/ width:0; height:0;}
 input[type="checkbox"] { width: 20px; height: 20px; vertical-align: bottom; }
 .big { font-weight:bold; font-size:1.2em; }
 .huge { font-weight:bold; font-size:1.5em; }
 .propertycontainer dd { float: left; width: 25em; }
 .propertylist { clear: none; max-width: 28em; }
-.propertylist li { /*background-color: cyan; */ min-width: 25em; /*max-width: 30em;*/ display: block; clear: right; }
+.propertylist li.propertycontainer { white-space: nowrap; min-width: 35em; /*max-width: 30em;*/ display: block; clear: right; }
 .propertylist li > input[type="text"],input[type="email"],input[type="tel"] { float: left; max-width: 15em; }
 .propertylist li > input[type="checkbox"],input[type="radio"] { float: left; clear: left; width: 20px; height: 20px; vertical-align: middle; }
 .propertylist li > select { float: left; max-width: 8em; }
-.typelist { float: left; max-width: 10em; } /* for multiselect */
-.addresslist { clear: both; }
-
+.typelist { float: left; max-width: 10em; border: 0; background-color: #fff; } /* for multiselect */
+.addresslist { clear: both; font-weight: bold; }
diff --git a/apps/contacts/css/jquery.Jcrop.css b/apps/contacts/css/jquery.Jcrop.css
index 554f013fd777da4c52cd3040cdbb9df94a8170d7..c9b24a5ebe9e0c6871a488aeda82a3ac9592c941 100644
--- a/apps/contacts/css/jquery.Jcrop.css
+++ b/apps/contacts/css/jquery.Jcrop.css
@@ -14,7 +14,7 @@
 }
 
 .jcrop-vline, .jcrop-hline {
-	background: white url('Jcrop.gif') top left repeat;
+	background: white url('%webroot%/apps/contacts/img/Jcrop.gif') top left repeat;
 	font-size: 0px;
 	position: absolute;
 }
diff --git a/apps/contacts/dynphoto.php b/apps/contacts/dynphoto.php
old mode 100644
new mode 100755
index 2beac15e1437db469517b6089e3b42acd5a28b77..ea6cef227e1d16a79657abeabe29dd329b5c2ede
--- a/apps/contacts/dynphoto.php
+++ b/apps/contacts/dynphoto.php
@@ -21,12 +21,12 @@
  */
 
 // Init owncloud
-require_once('../../lib/base.php');
+
 $tmp_path = $_GET['tmp_path'];
 $maxsize = isset($_GET['maxsize']) ? $_GET['maxsize'] : -1;
 header("Cache-Control: no-cache, no-store, must-revalidate");
 
-OC_Log::write('contacts','dynphoto.php: tmp_path: '.$tmp_path.', exists: '.file_exists($tmp_path), OC_Log::DEBUG);
+OCP\Util::writeLog('contacts','dynphoto.php: tmp_path: '.$tmp_path.', exists: '.file_exists($tmp_path), OCP\Util::DEBUG);
 
 $image = new OC_Image($tmp_path);
 if($maxsize != -1) {
diff --git a/apps/contacts/export.php b/apps/contacts/export.php
old mode 100644
new mode 100755
index fb3e0a41ae7bc9eafe37c8718c6db2a3cbc424b2..4e4ade2f2ba6c015cf38c5a3bb84dfdd6e89c2a8
--- a/apps/contacts/export.php
+++ b/apps/contacts/export.php
@@ -6,9 +6,9 @@
  * See the COPYING-README file.
  */
 
-require_once ("../../lib/base.php");
-OC_Util::checkLoggedIn();
-OC_Util::checkAppEnabled('contacts');
+ 
+OCP\User::checkLoggedIn();
+OCP\App::checkAppEnabled('contacts');
 $bookid = isset($_GET['bookid']) ? $_GET['bookid'] : NULL;
 $contactid = isset($_GET['contactid']) ? $_GET['contactid'] : NULL;
 $nl = "\n";
diff --git a/apps/contacts/css/Jcrop.gif b/apps/contacts/img/Jcrop.gif
similarity index 100%
rename from apps/contacts/css/Jcrop.gif
rename to apps/contacts/img/Jcrop.gif
diff --git a/apps/contacts/img/contact-new.png b/apps/contacts/img/contact-new.png
new file mode 100644
index 0000000000000000000000000000000000000000..437e4e223f4bb02fd19c3dc1ab0fed2abf4e3151
Binary files /dev/null and b/apps/contacts/img/contact-new.png differ
diff --git a/apps/contacts/img/contact-new.svg b/apps/contacts/img/contact-new.svg
new file mode 100644
index 0000000000000000000000000000000000000000..3c824dd10c910e7809dd7acae20ea8080605aae3
--- /dev/null
+++ b/apps/contacts/img/contact-new.svg
@@ -0,0 +1,449 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:xlink="http://www.w3.org/1999/xlink"
+   version="1.0"
+   width="22"
+   height="22"
+   id="svg2">
+  <defs
+     id="defs4">
+    <linearGradient
+       id="linearGradient2804">
+      <stop
+         id="stop2806"
+         style="stop-color:#000000;stop-opacity:0"
+         offset="0" />
+      <stop
+         id="stop2812"
+         style="stop-color:#000000;stop-opacity:1"
+         offset="0.5" />
+      <stop
+         id="stop2808"
+         style="stop-color:#000000;stop-opacity:0"
+         offset="1" />
+    </linearGradient>
+    <linearGradient
+       x1="21.875"
+       y1="48.000977"
+       x2="21.875"
+       y2="40"
+       id="linearGradient7875"
+       xlink:href="#linearGradient2804"
+       gradientUnits="userSpaceOnUse" />
+    <radialGradient
+       cx="1"
+       cy="44"
+       r="5"
+       fx="1"
+       fy="44"
+       id="radialGradient7873"
+       xlink:href="#linearGradient2781"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(2,0,0,0.8,36,8.8)" />
+    <linearGradient
+       id="linearGradient2781">
+      <stop
+         id="stop2783"
+         style="stop-color:#000000;stop-opacity:1"
+         offset="0" />
+      <stop
+         id="stop2785"
+         style="stop-color:#000000;stop-opacity:0"
+         offset="1" />
+    </linearGradient>
+    <radialGradient
+       cx="1"
+       cy="44"
+       r="5"
+       fx="1"
+       fy="44"
+       id="radialGradient7871"
+       xlink:href="#linearGradient2781"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(2,0,0,0.8,-13,-79.2)" />
+    <linearGradient
+       x1="9.117774"
+       y1="18.345161"
+       x2="8.4885712"
+       y2="34.608616"
+       id="linearGradient7883"
+       xlink:href="#linearGradient4585"
+       gradientUnits="userSpaceOnUse" />
+    <linearGradient
+       x1="11.511479"
+       y1="0.75951481"
+       x2="31.5"
+       y2="36.625"
+       id="linearGradient7881"
+       xlink:href="#linearGradient6732"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.858045,0,0,0.8,-0.932219,9.3)" />
+    <linearGradient
+       id="linearGradient6732">
+      <stop
+         id="stop6734"
+         style="stop-color:#ffffff;stop-opacity:1"
+         offset="0" />
+      <stop
+         id="stop6736"
+         style="stop-color:#dddddd;stop-opacity:1"
+         offset="1" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient4585">
+      <stop
+         id="stop4587"
+         style="stop-color:#9e9e9e;stop-opacity:1"
+         offset="0" />
+      <stop
+         id="stop4589"
+         style="stop-color:#dddddd;stop-opacity:0"
+         offset="1" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient4222">
+      <stop
+         id="stop4224"
+         style="stop-color:#ffffff;stop-opacity:1"
+         offset="0" />
+      <stop
+         id="stop4226"
+         style="stop-color:#ffffff;stop-opacity:0"
+         offset="1" />
+    </linearGradient>
+    <linearGradient
+       x1="24.138529"
+       y1="7.0774679"
+       x2="24.138529"
+       y2="47.272728"
+       id="linearGradient7449"
+       xlink:href="#linearGradient4222"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.2817955,0,0,0.2800956,8.7966501,33.376211)" />
+    <linearGradient
+       id="linearGradient2264">
+      <stop
+         id="stop2266"
+         style="stop-color:#d7e866;stop-opacity:1"
+         offset="0" />
+      <stop
+         id="stop2268"
+         style="stop-color:#8cab2a;stop-opacity:1"
+         offset="1" />
+    </linearGradient>
+    <linearGradient
+       x1="24.103895"
+       y1="15.168831"
+       x2="24.103895"
+       y2="32.485161"
+       id="linearGradient7447"
+       xlink:href="#linearGradient2264"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.4691323,0,0,0.4663025,4.3005671,29.169788)" />
+    <linearGradient
+       x1="9.117774"
+       y1="18.345161"
+       x2="8.4885712"
+       y2="34.608616"
+       id="linearGradient2905"
+       xlink:href="#linearGradient4585"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.6013587,0,0,0.5980624,-1.0380127,-5.8062214)" />
+    <linearGradient
+       x1="11.511479"
+       y1="0.75951481"
+       x2="31.5"
+       y2="36.625"
+       id="linearGradient2918"
+       xlink:href="#linearGradient6732"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.4797481,0,0,0.4329733,-1.4240221,0.5982379)" />
+  </defs>
+  <g
+     transform="matrix(0.5106383,0,0,0.625,-2.5106384,-10)"
+     id="g2822"
+     style="opacity:0.2;display:inline">
+    <rect
+       width="10"
+       height="8"
+       x="-11"
+       y="-48"
+       transform="scale(-1,-1)"
+       id="rect1892"
+       style="fill:url(#radialGradient7871);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible" />
+    <rect
+       width="10"
+       height="8"
+       x="38"
+       y="40"
+       id="rect2789"
+       style="fill:url(#radialGradient7873);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible" />
+    <rect
+       width="27"
+       height="8"
+       x="11"
+       y="40"
+       id="rect2793"
+       style="fill:url(#linearGradient7875);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible" />
+  </g>
+  <g
+     transform="matrix(0.514569,0,0,0.5204006,-0.3058992,-3.571213)"
+     id="g1962"
+     style="stroke-width:1.91310632;stroke-miterlimit:4;stroke-dasharray:none;display:inline">
+    <rect
+       width="34.000015"
+       height="24"
+       rx="2.7500012"
+       ry="2.7499983"
+       x="2.5000017"
+       y="16.499996"
+       id="rect5857"
+       style="fill:url(#linearGradient7881);fill-opacity:1;fill-rule:evenodd;stroke:#939393;stroke-width:1.91310632;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible" />
+    <path
+       d="m 18.395099,22.588796 c 0,0.294138 -0.06929,0.519713 -0.207851,0.676725 -0.138572,0.155966 -0.327526,0.233949 -0.566874,0.233949 -0.09763,0 -0.191057,-0.01832 -0.280291,-0.05495 l 0,-0.417654 c 0.07874,0.05967 0.165868,0.0895 0.261393,0.0895 0.117576,0 0.205753,-0.04344 0.264545,-0.130321 0.05983,-0.08793 0.08975,-0.219293 0.08975,-0.394102 l 0,-1.392703 0.439328,0 0,1.389563 m 1.226649,-0.803906 c 0.24564,2e-6 0.441423,0.07537 0.587344,0.226098 0.145913,0.150734 0.218869,0.353281 0.218869,0.60764 0,0.276344 -0.07821,0.491974 -0.234622,0.646893 -0.156414,0.153873 -0.366362,0.230809 -0.629851,0.230809 -0.242502,0 -0.439851,-0.07589 -0.592071,-0.227669 -0.151163,-0.151778 -0.226749,-0.350661 -0.226749,-0.596648 0,-0.276342 0.07926,-0.49302 0.237775,-0.650033 0.158512,-0.158058 0.371613,-0.237088 0.639305,-0.23709 m -0.03622,1.373863 c 0.128071,0 0.231992,-0.04553 0.31178,-0.136602 0.08083,-0.09211 0.121247,-0.2172 0.121247,-0.37526 0,-0.160152 -0.03989,-0.286286 -0.119674,-0.378401 -0.07979,-0.09316 -0.182137,-0.139741 -0.307054,-0.139742 -0.123876,10e-7 -0.228854,0.04867 -0.314933,0.146022 -0.08608,0.0963 -0.12912,0.223483 -0.12912,0.381541 0,0.155967 0.04199,0.278961 0.125974,0.36898 0.08503,0.08898 0.188952,0.133462 0.31178,0.133462 m 2.675322,0.292043 -0.422011,0 0,-0.880842 c 0,-0.147591 -0.02257,-0.254359 -0.06771,-0.320306 -0.04515,-0.06699 -0.122304,-0.100487 -0.231476,-0.100488 -0.09553,1e-6 -0.174788,0.03611 -0.237767,0.108339 -0.06299,0.07223 -0.09448,0.164341 -0.09448,0.276342 l 0,0.916955 -0.426728,0 0,-2.380314 0.426728,0 0,0.997031 c 0.05774,-0.09421 0.129643,-0.164862 0.215731,-0.211967 0.08713,-0.0471 0.188428,-0.07065 0.3039,-0.07066 0.177409,2e-6 0.310731,0.05496 0.399964,0.164864 0.08923,0.10991 0.133838,0.274774 0.133848,0.49459 l 0,1.006452 m 1.93366,0 -0.42201,0 0,-0.880842 c 0,-0.147591 -0.02257,-0.254359 -0.06771,-0.320306 -0.04514,-0.06699 -0.12229,-0.100487 -0.23147,-0.100488 -0.09553,10e-7 -0.17478,0.03611 -0.23777,0.108339 -0.06299,0.07223 -0.09448,0.164341 -0.09448,0.276342 l 0,0.916955 -0.42673,0 0,-1.607811 0.42673,0 0,0.224528 c 0.05774,-0.09421 0.12965,-0.164862 0.21573,-0.211967 0.08712,-0.0471 0.18842,-0.07065 0.3039,-0.07066 0.17741,2e-6 0.31073,0.05496 0.39996,0.164864 0.08923,0.10991 0.13385,0.274774 0.13385,0.49459 l 0,1.006452 m 1.38096,-2.251563 0.79047,0 c 0.38211,2e-6 0.6687,0.09159 0.85976,0.274772 0.1921,0.183183 0.28815,0.457432 0.28815,0.822747 0,0.352756 -0.10812,0.633285 -0.32437,0.841589 -0.21521,0.208303 -0.50704,0.312455 -0.87551,0.312455 l -0.7385,0 0,-2.251563 m 0.43932,1.904565 0.28974,0 c 0.23724,0 0.42358,-0.07066 0.559,-0.211967 0.13647,-0.141311 0.20469,-0.334437 0.2047,-0.579378 -10e-6,-0.237611 -0.06614,-0.422362 -0.1984,-0.554255 -0.13228,-0.131889 -0.31651,-0.197835 -0.5527,-0.197836 l -0.30234,0 0,1.543436 m 2.62651,-1.318908 c 0.24564,2e-6 0.44142,0.07537 0.58734,0.226098 0.14591,0.150734 0.21888,0.353281 0.21888,0.60764 0,0.276344 -0.07821,0.491974 -0.23462,0.646893 -0.15642,0.153873 -0.36637,0.230809 -0.62986,0.230809 -0.2425,0 -0.43985,-0.07589 -0.59207,-0.227669 -0.15117,-0.151778 -0.22675,-0.350661 -0.22675,-0.596648 0,-0.276342 0.07926,-0.49302 0.23777,-0.650033 0.15851,-0.158058 0.37162,-0.237088 0.63931,-0.23709 m -0.03622,1.373863 c 0.12807,0 0.232,-0.04553 0.31178,-0.136602 0.08083,-0.09211 0.12125,-0.2172 0.12125,-0.37526 0,-0.160152 -0.0399,-0.286286 -0.11968,-0.378401 -0.07978,-0.09316 -0.18213,-0.139741 -0.30705,-0.139742 -0.12388,1e-6 -0.22885,0.04867 -0.31493,0.146022 -0.08608,0.0963 -0.12912,0.223483 -0.12912,0.381541 0,0.155967 0.04199,0.278961 0.12597,0.36898 0.08503,0.08898 0.18896,0.133462 0.31178,0.133462 m 2.58242,-0.419225 -1.07391,0 c 0,0.131892 0.04041,0.234473 0.12125,0.307745 0.08188,0.07223 0.19525,0.10834 0.34012,0.108339 0.15956,1e-6 0.31336,-0.04763 0.46137,-0.142882 l 0,0.348569 c -0.16586,0.08583 -0.35167,0.128751 -0.55742,0.128751 -0.2488,0 -0.44352,-0.07275 -0.58419,-0.218249 -0.13962,-0.145498 -0.20944,-0.34438 -0.20944,-0.596648 0,-0.272155 0.07454,-0.488832 0.22361,-0.650034 0.15011,-0.162244 0.34747,-0.243367 0.59206,-0.243369 0.2152,2e-6 0.38316,0.06699 0.50389,0.200976 0.12177,0.132939 0.18266,0.318737 0.18266,0.557396 l 0,0.199406 m -0.39367,-0.282623 c 0,-0.112002 -0.02834,-0.199405 -0.08503,-0.262211 -0.05563,-0.0628 -0.13489,-0.09421 -0.23777,-0.09421 -0.09342,2e-6 -0.17426,0.03245 -0.24249,0.09735 -0.06824,0.06385 -0.10655,0.15021 -0.11495,0.259071 l 0.68024,0"
+       id="text6970"
+       style="font-size:4.12102222px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:120.00000477%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Segoe" />
+    <rect
+       width="15"
+       height="2"
+       rx="1"
+       ry="1"
+       x="17"
+       y="25"
+       id="rect6978"
+       style="opacity:0.3976608;fill:#8d8d8d;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.91310632;marker:none;visibility:visible;display:inline;overflow:visible" />
+    <rect
+       width="10.955575"
+       height="2"
+       rx="1"
+       ry="1"
+       x="17.089211"
+       y="28"
+       id="rect6980"
+       style="opacity:0.3976608;fill:#8d8d8d;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.91310632;marker:none;visibility:visible;display:inline;overflow:visible" />
+    <g
+       transform="matrix(0.782541,0,0,0.650248,0.39068,14.55146)"
+       id="g7033"
+       style="opacity:0.48538011;stroke-width:2.68192148;stroke-miterlimit:4;stroke-dasharray:none">
+      <rect
+         width="1"
+         height="6"
+         rx="0"
+         ry="0"
+         x="6"
+         y="30"
+         id="rect7003"
+         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.68192148;marker:none;visibility:visible;display:inline;overflow:visible" />
+      <rect
+         width="1.9375"
+         height="2.9851687"
+         rx="0"
+         ry="0"
+         x="8.0846453"
+         y="30"
+         id="rect7005"
+         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.68192148;marker:none;visibility:visible;display:inline;overflow:visible" />
+      <rect
+         width="1"
+         height="2.9851687"
+         x="11"
+         y="30"
+         id="rect7007"
+         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.68192148;marker:none;visibility:visible;display:inline;overflow:visible" />
+      <rect
+         width="2"
+         height="2.9851687"
+         x="13"
+         y="30"
+         id="rect7009"
+         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.68192148;marker:none;visibility:visible;display:inline;overflow:visible" />
+      <rect
+         width="1"
+         height="2.9851687"
+         x="16"
+         y="30"
+         id="rect7011"
+         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.68192148;marker:none;visibility:visible;display:inline;overflow:visible" />
+      <rect
+         width="1"
+         height="2.9851687"
+         x="18"
+         y="30"
+         id="rect7013"
+         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.68192148;marker:none;visibility:visible;display:inline;overflow:visible" />
+      <rect
+         width="1"
+         height="2.9851687"
+         x="21"
+         y="30"
+         id="rect7015"
+         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.68192148;marker:none;visibility:visible;display:inline;overflow:visible" />
+      <rect
+         width="2"
+         height="2.9851687"
+         x="23"
+         y="30"
+         id="rect7017"
+         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.68192148;marker:none;visibility:visible;display:inline;overflow:visible" />
+      <rect
+         width="2"
+         height="2.9851687"
+         x="26"
+         y="30"
+         id="rect7019"
+         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.68192148;marker:none;visibility:visible;display:inline;overflow:visible" />
+      <rect
+         width="1"
+         height="2.9851687"
+         x="29"
+         y="30"
+         id="rect7021"
+         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.68192148;marker:none;visibility:visible;display:inline;overflow:visible" />
+      <rect
+         width="1"
+         height="2.9851687"
+         x="31"
+         y="30"
+         id="rect7023"
+         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.68192148;marker:none;visibility:visible;display:inline;overflow:visible" />
+      <rect
+         width="1"
+         height="2.9851687"
+         x="33"
+         y="30"
+         id="rect7025"
+         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.68192148;marker:none;visibility:visible;display:inline;overflow:visible" />
+      <rect
+         width="2"
+         height="2.9851687"
+         x="35"
+         y="30"
+         id="rect7027"
+         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.68192148;marker:none;visibility:visible;display:inline;overflow:visible" />
+      <rect
+         width="2"
+         height="2.9851687"
+         x="39"
+         y="30"
+         id="rect7029"
+         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.68192148;marker:none;visibility:visible;display:inline;overflow:visible" />
+      <rect
+         width="1"
+         height="6"
+         x="42"
+         y="30"
+         id="rect7031"
+         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.68192148;marker:none;visibility:visible;display:inline;overflow:visible" />
+    </g>
+    <path
+       d="m 7.4730264,37.137227 c 0.058659,0.01251 0.104375,0.03852 0.13714,0.07805 0.033172,0.03953 0.049762,0.08834 0.049762,0.14643 0,0.08915 -0.030746,0.158128 -0.092238,0.206938 -0.061492,0.04881 -0.148871,0.07322 -0.262144,0.07322 -0.038031,0 -0.077276,-0.0038 -0.117725,-0.0115 -0.040051,-0.0073 -0.081517,-0.01835 -0.124401,-0.03328 l 0,-0.117991 c 0.033986,0.01977 0.071204,0.03469 0.111653,0.04478 0.040458,0.01009 0.082731,0.01513 0.126827,0.01513 0.076869,0 0.135325,-0.01513 0.175375,-0.04538 0.04045,-0.03025 0.060678,-0.07422 0.060678,-0.131908 0,-0.05325 -0.018812,-0.0948 -0.056429,-0.124647 -0.037225,-0.03025 -0.089209,-0.04538 -0.155952,-0.04538 l -0.105589,0 0,-0.100444 0.11044,0 c 0.06028,10e-7 0.106395,-0.0119 0.138354,-0.0357 0.031959,-0.0242 0.047938,-0.05889 0.047938,-0.104074 0,-0.04639 -0.016582,-0.08189 -0.049754,-0.106494 -0.032773,-0.02501 -0.079905,-0.03752 -0.141389,-0.03752 -0.033579,0 -0.069584,0.0036 -0.108015,0.01089 -0.038438,0.0073 -0.080711,0.01856 -0.126826,0.03388 l 0,-0.108914 c 0.046522,-0.01291 0.090008,-0.02259 0.130465,-0.02904 0.040857,-0.0065 0.079287,-0.0097 0.115292,-0.0097 0.093052,2e-6 0.166674,0.02118 0.220888,0.06353 0.054207,0.04195 0.081314,0.09883 0.081314,0.170633 0,0.05002 -0.014368,0.09238 -0.043087,0.127066 -0.028719,0.03429 -0.069583,0.05809 -0.122577,0.0714 m 0.525507,0.384227 0.427808,0 0,0.102863 -0.57527,0 0,-0.102863 c 0.04653,-0.048 0.109838,-0.112343 0.189939,-0.193021 0.080508,-0.08108 0.131075,-0.13332 0.151703,-0.156716 0.039245,-0.04397 0.066548,-0.08108 0.081924,-0.111335 0.015776,-0.03066 0.023665,-0.06071 0.023665,-0.09016 0,-0.048 -0.016989,-0.08713 -0.050975,-0.117386 -0.033579,-0.03025 -0.077472,-0.04538 -0.131678,-0.04538 -0.038431,0 -0.079092,0.0067 -0.121967,0.01997 -0.042484,0.01331 -0.087989,0.03348 -0.136538,0.06051 l 0,-0.123437 c 0.049355,-0.01976 0.09547,-0.03469 0.138353,-0.04478 0.042883,-0.01008 0.082128,-0.01513 0.117726,-0.01513 0.09385,2e-6 0.168692,0.0234 0.224526,0.07019 0.055827,0.04679 0.08374,0.109319 0.08374,0.187575 0,0.03711 -0.00708,0.07241 -0.021238,0.10589 -0.013757,0.03308 -0.039041,0.07221 -0.075852,0.117385 -0.010118,0.0117 -0.04228,0.04558 -0.096487,0.101654 -0.054207,0.05567 -0.130669,0.133723 -0.229379,0.234167 m 1.022492,-0.694029 -0.309479,0.48225 0.309479,0 0,-0.48225 m -0.032162,-0.106494 0.154137,0 0,0.588744 0.129252,0 0,0.101654 -0.129252,0 0,0.212988 -0.121975,0 0,-0.212988 -0.408995,0 0,-0.117991 0.376833,-0.572407 m 0.487891,0 0.4812083,0 0,0.102864 -0.3689533,0 0,0.22146 c 0.017803,-0.0061 0.035606,-0.01049 0.053401,-0.01331 0.017803,-0.0032 0.035605,-0.0048 0.0534,-0.0048 0.101136,10e-7 0.181237,0.02763 0.2403033,0.0829 0.059066,0.05527 0.088599,0.130093 0.088599,0.224486 0,0.09722 -0.030347,0.172851 -0.091025,0.226905 -0.060686,0.05365 -0.1462413,0.08048 -0.2566893,0.08048 -0.038024,0 -0.076861,-0.0032 -0.116505,-0.0097 -0.039244,-0.0065 -0.079897,-0.01614 -0.121974,-0.02905 l 0,-0.122831 c 0.036411,0.01977 0.074036,0.03449 0.112873,0.04417 0.03883,0.0097 0.079898,0.01452 0.12318,0.01452 0.069991,0 0.12541,-0.01835 0.166274,-0.05506 0.040857,-0.03671 0.061289,-0.08653 0.061289,-0.149455 0,-0.06293 -0.020432,-0.112747 -0.061289,-0.149455 -0.040864,-0.03671 -0.096283,-0.05506 -0.166274,-0.05506 -0.032765,0 -0.065538,0.0036 -0.098303,0.01089 -0.032366,0.0073 -0.065537,0.01856 -0.099515,0.03388 l 0,-0.453811 m 1.4478736,0.08047 c -0.06311,10e-7 -0.110644,0.03106 -0.142603,0.09318 -0.03156,0.06172 -0.04734,0.154699 -0.04734,0.278942 0,0.12384 0.01578,0.216821 0.04734,0.278942 0.03196,0.06172 0.07949,0.09258 0.142603,0.09258 0.06351,0 0.11105,-0.03086 0.142602,-0.09258 0.03196,-0.06212 0.04794,-0.155102 0.04794,-0.278942 0,-0.124243 -0.01598,-0.217224 -0.04794,-0.278942 -0.03155,-0.06212 -0.07909,-0.09318 -0.142602,-0.09318 m 0,-0.09681 c 0.101542,2e-6 0.179014,0.04014 0.232414,0.120412 0.0538,0.07987 0.0807,0.196047 0.0807,0.348527 0,0.152077 -0.0269,0.268253 -0.0807,0.348527 -0.0534,0.07987 -0.130872,0.119806 -0.232414,0.119806 -0.101543,0 -0.179218,-0.03993 -0.233017,-0.119806 -0.0534,-0.08027 -0.0801,-0.19645 -0.0801,-0.348527 0,-0.15248 0.0267,-0.268656 0.0801,-0.348527 0.0538,-0.08027 0.131474,-0.12041 0.233017,-0.120412 m 0.530359,0.01634 0.481208,0 0,0.102864 -0.368945,0 0,0.22146 c 0.0178,-0.0061 0.0356,-0.01049 0.0534,-0.01331 0.0178,-0.0032 0.0356,-0.0048 0.0534,-0.0048 0.101135,1e-6 0.181236,0.02763 0.240302,0.0829 0.05906,0.05527 0.08859,0.130093 0.08859,0.224486 0,0.09722 -0.03034,0.172851 -0.09102,0.226905 -0.06069,0.05365 -0.14625,0.08048 -0.25669,0.08048 -0.03802,0 -0.07686,-0.0032 -0.116512,-0.0097 -0.03924,-0.0065 -0.0799,-0.01614 -0.121967,-0.02905 l 0,-0.122831 c 0.03641,0.01977 0.07403,0.03449 0.112866,0.04417 0.03884,0.0097 0.0799,0.01452 0.123188,0.01452 0.06998,0 0.12541,-0.01835 0.166266,-0.05506 0.04086,-0.03671 0.06129,-0.08653 0.06129,-0.149455 0,-0.06293 -0.02043,-0.112747 -0.06129,-0.149455 -0.04086,-0.03671 -0.09628,-0.05506 -0.166266,-0.05506 -0.03277,0 -0.06554,0.0036 -0.0983,0.01089 -0.03237,0.0073 -0.06554,0.01856 -0.09952,0.03388 l 0,-0.453811 m 0.791298,0 0.481208,0 0,0.102864 -0.368945,0 0,0.22146 c 0.01779,-0.0061 0.0356,-0.01049 0.0534,-0.01331 0.01779,-0.0032 0.0356,-0.0048 0.0534,-0.0048 0.101136,1e-6 0.181237,0.02763 0.240295,0.0829 0.05907,0.05527 0.0886,0.130093 0.0886,0.224486 0,0.09722 -0.03034,0.172851 -0.09103,0.226905 -0.06068,0.05365 -0.146241,0.08048 -0.256681,0.08048 -0.03803,0 -0.07687,-0.0032 -0.116512,-0.0097 -0.03924,-0.0065 -0.0799,-0.01614 -0.121967,-0.02905 l 0,-0.122831 c 0.0364,0.01977 0.07403,0.03449 0.112866,0.04417 0.03884,0.0097 0.0799,0.01452 0.123187,0.01452 0.06998,0 0.125402,-0.01835 0.166267,-0.05506 0.04086,-0.03671 0.06129,-0.08653 0.06129,-0.149455 0,-0.06293 -0.02043,-0.112747 -0.06129,-0.149455 -0.04087,-0.03671 -0.09628,-0.05506 -0.166267,-0.05506 -0.03277,0 -0.06554,0.0036 -0.09831,0.01089 -0.03237,0.0073 -0.06554,0.01856 -0.09952,0.03388 l 0,-0.453811 m 0.759135,0 0.582547,0 0,0.05204 -0.328902,0.851349 -0.128039,0 0.309479,-0.800522 -0.435085,0 0,-0.102864 m 1.219105,0 0.481208,0 0,0.102864 -0.368952,0 0,0.22146 c 0.0178,-0.0061 0.03561,-0.01049 0.0534,-0.01331 0.0178,-0.0032 0.03561,-0.0048 0.0534,-0.0048 0.101136,10e-7 0.181236,0.02763 0.240303,0.0829 0.05907,0.05527 0.0886,0.130093 0.0886,0.224486 0,0.09722 -0.03035,0.172851 -0.09103,0.226905 -0.06069,0.05365 -0.146249,0.08048 -0.256689,0.08048 -0.03802,0 -0.07686,-0.0032 -0.116505,-0.0097 -0.03924,-0.0065 -0.0799,-0.01614 -0.121975,-0.02905 l 0,-0.122831 c 0.03641,0.01977 0.07404,0.03449 0.112874,0.04417 0.03883,0.0097 0.0799,0.01452 0.12318,0.01452 0.06999,0 0.12541,-0.01835 0.166266,-0.05506 0.04087,-0.03671 0.06129,-0.08653 0.0613,-0.149455 -8e-6,-0.06293 -0.02043,-0.112747 -0.0613,-0.149455 -0.04086,-0.03671 -0.09628,-0.05506 -0.166266,-0.05506 -0.03277,0 -0.06554,0.0036 -0.0983,0.01089 -0.03237,0.0073 -0.06554,0.01856 -0.09952,0.03388 l 0,-0.453811 m 0.811315,0.800523 0.200253,0 0,-0.689188 -0.217852,0.04357 0,-0.111335 0.216639,-0.04357 0.122577,0 0,0.800523 0.200252,0 0,0.102863 -0.521869,0 0,-0.102863 m 1.032203,-0.720048 c -0.06311,1e-6 -0.110643,0.03106 -0.142602,0.09318 -0.03155,0.06172 -0.04733,0.154699 -0.04733,0.278942 0,0.12384 0.01578,0.216821 0.04733,0.278942 0.03196,0.06172 0.07949,0.09258 0.142602,0.09258 0.06351,0 0.111051,-0.03086 0.142603,-0.09258 0.03196,-0.06212 0.04794,-0.155102 0.04794,-0.278942 0,-0.124243 -0.01598,-0.217224 -0.04794,-0.278942 -0.03155,-0.06212 -0.07909,-0.09318 -0.142603,-0.09318 m 0,-0.09681 c 0.101543,2e-6 0.179014,0.04014 0.232415,0.120412 0.0538,0.07987 0.0807,0.196047 0.0807,0.348527 0,0.152077 -0.0269,0.268253 -0.0807,0.348527 -0.0534,0.07987 -0.130872,0.119806 -0.232415,0.119806 -0.101542,0 -0.179209,-0.03993 -0.233017,-0.119806 -0.0534,-0.08027 -0.0801,-0.19645 -0.0801,-0.348527 0,-0.15248 0.0267,-0.268656 0.0801,-0.348527 0.05381,-0.08027 0.131475,-0.12041 0.233017,-0.120412 m 0.806464,0.419322 c -0.05501,10e-7 -0.09871,0.01876 -0.131068,0.05627 -0.03196,0.03751 -0.04794,0.08895 -0.04794,0.154296 0,0.06494 0.01598,0.116377 0.04794,0.154295 0.03236,0.03751 0.07606,0.05627 0.131068,0.05627 0.05502,0 0.09851,-0.01876 0.130473,-0.05627 0.03236,-0.03792 0.04854,-0.08935 0.04854,-0.154295 0,-0.06535 -0.01618,-0.116781 -0.04854,-0.154296 -0.03196,-0.03751 -0.07545,-0.05627 -0.130473,-0.05627 m 0.243339,-0.383017 0,0.111335 c -0.03075,-0.01452 -0.0619,-0.02561 -0.09345,-0.03328 -0.03115,-0.0077 -0.06209,-0.0115 -0.09284,-0.0115 -0.08091,0 -0.142806,0.02723 -0.185689,0.08169 -0.04248,0.05446 -0.06675,0.136749 -0.07282,0.246873 0.02387,-0.03509 0.0538,-0.06192 0.08981,-0.08048 0.036,-0.01896 0.07565,-0.02844 0.118938,-0.02844 0.09102,1e-6 0.162831,0.02763 0.215418,0.0829 0.053,0.05486 0.0795,0.12969 0.0795,0.224486 0,0.09278 -0.02751,0.167204 -0.08253,0.223275 -0.05502,0.05607 -0.128243,0.08411 -0.219675,0.08411 -0.104775,0 -0.184876,-0.03993 -0.240295,-0.119806 -0.05543,-0.08027 -0.08314,-0.19645 -0.08314,-0.348527 0,-0.142799 0.03398,-0.256554 0.101949,-0.341266 0.06796,-0.08511 0.159185,-0.127671 0.27367,-0.127673 0.03075,2e-6 0.0617,0.003 0.09285,0.0091 0.03155,0.0061 0.06432,0.01513 0.0983,0.02723 m 0.667499,-0.01997 0.481214,0 0,0.102864 -0.368953,0 0,0.22146 c 0.0178,-0.0061 0.03561,-0.01049 0.0534,-0.01331 0.0178,-0.0032 0.03561,-0.0048 0.0534,-0.0048 0.101135,1e-6 0.181236,0.02763 0.240302,0.0829 0.05907,0.05527 0.0886,0.130093 0.0886,0.224486 0,0.09722 -0.03035,0.172851 -0.09103,0.226905 -0.06069,0.05365 -0.146249,0.08048 -0.256689,0.08048 -0.03802,0 -0.07686,-0.0032 -0.116504,-0.0097 -0.03925,-0.0065 -0.0799,-0.01614 -0.121973,-0.02905 l 0,-0.122831 c 0.03641,0.01977 0.07403,0.03449 0.112872,0.04417 0.03883,0.0097 0.0799,0.01452 0.123179,0.01452 0.06999,0 0.12541,-0.01835 0.166267,-0.05506 0.04086,-0.03671 0.06129,-0.08653 0.0613,-0.149455 -7e-6,-0.06293 -0.02043,-0.112747 -0.0613,-0.149455 -0.04086,-0.03671 -0.09628,-0.05506 -0.166267,-0.05506 -0.03277,0 -0.06554,0.0036 -0.0983,0.01089 -0.03237,0.0073 -0.06554,0.01856 -0.09952,0.03388 l 0,-0.453811 m 1.126873,0.106494 -0.309479,0.48225 0.309479,0 0,-0.48225 m -0.03216,-0.106494 0.15413,0 0,0.588744 0.129252,0 0,0.101654 -0.129252,0 0,0.212988 -0.121967,0 0,-0.212988 -0.409003,0 0,-0.117991 0.37684,-0.572407 m 0.748814,0.08047 c -0.06311,1e-6 -0.110643,0.03106 -0.142602,0.09318 -0.03155,0.06172 -0.04733,0.154699 -0.04733,0.278942 0,0.12384 0.01578,0.216821 0.04733,0.278942 0.03196,0.06172 0.07949,0.09258 0.142602,0.09258 0.06351,0 0.11105,-0.03086 0.142602,-0.09258 0.03196,-0.06212 0.04794,-0.155102 0.04794,-0.278942 0,-0.124243 -0.01598,-0.217224 -0.04794,-0.278942 -0.03155,-0.06212 -0.07909,-0.09318 -0.142602,-0.09318 m 0,-0.09681 c 0.101543,2e-6 0.179014,0.04014 0.232415,0.120412 0.0538,0.07987 0.0807,0.196047 0.0807,0.348527 0,0.152077 -0.0269,0.268253 -0.0807,0.348527 -0.0534,0.07987 -0.130872,0.119806 -0.232415,0.119806 -0.101543,0 -0.179218,-0.03993 -0.233017,-0.119806 -0.0534,-0.08027 -0.0801,-0.19645 -0.0801,-0.348527 0,-0.15248 0.0267,-0.268656 0.0801,-0.348527 0.0538,-0.08027 0.131474,-0.12041 0.233017,-0.120412 m 0.806463,0.419322 c -0.05501,10e-7 -0.09871,0.01876 -0.131067,0.05627 -0.03196,0.03751 -0.04794,0.08895 -0.04794,0.154296 0,0.06494 0.01598,0.116377 0.04794,0.154295 0.03236,0.03751 0.07606,0.05627 0.131067,0.05627 0.05502,0 0.09851,-0.01876 0.130466,-0.05627 0.03237,-0.03792 0.04855,-0.08935 0.04855,-0.154295 0,-0.06535 -0.01618,-0.116781 -0.04855,-0.154296 -0.03196,-0.03751 -0.07545,-0.05627 -0.130466,-0.05627 m 0.243339,-0.383017 0,0.111335 c -0.03075,-0.01452 -0.0619,-0.02561 -0.09345,-0.03328 -0.03115,-0.0077 -0.0621,-0.0115 -0.09284,-0.0115 -0.08092,0 -0.142806,0.02723 -0.18569,0.08169 -0.04248,0.05446 -0.06675,0.136749 -0.07282,0.246873 0.02387,-0.03509 0.05381,-0.06192 0.08981,-0.08048 0.03601,-0.01896 0.07565,-0.02844 0.118939,-0.02844 0.09103,1e-6 0.162831,0.02763 0.215418,0.0829 0.053,0.05486 0.0795,0.12969 0.0795,0.224486 0,0.09278 -0.02751,0.167204 -0.08253,0.223275 -0.05502,0.05607 -0.128243,0.08411 -0.219675,0.08411 -0.104774,0 -0.184875,-0.03993 -0.240295,-0.119806 -0.05543,-0.08027 -0.08314,-0.19645 -0.08314,-0.348527 0,-0.142799 0.03398,-0.256554 0.101942,-0.341266 0.06796,-0.08511 0.159192,-0.127671 0.273678,-0.127673 0.03075,2e-6 0.0617,0.003 0.09285,0.0091 0.03155,0.0061 0.06432,0.01513 0.0983,0.02723 m 0.6675,-0.01997 0.481216,0 0,0.102864 -0.368953,0 0,0.22146 c 0.0178,-0.0061 0.03561,-0.01049 0.0534,-0.01331 0.0178,-0.0032 0.0356,-0.0048 0.0534,-0.0048 0.101135,1e-6 0.181236,0.02763 0.240302,0.0829 0.05907,0.05527 0.08859,0.130093 0.0886,0.224486 -8e-6,0.09722 -0.03035,0.172851 -0.09103,0.226905 -0.06069,0.05365 -0.146249,0.08048 -0.256689,0.08048 -0.03802,0 -0.07686,-0.0032 -0.116504,-0.0097 -0.03925,-0.0065 -0.0799,-0.01614 -0.121975,-0.02905 l 0,-0.122831 c 0.03641,0.01977 0.07404,0.03449 0.112866,0.04417 0.03884,0.0097 0.07991,0.01452 0.123187,0.01452 0.06999,0 0.12541,-0.01835 0.166267,-0.05506 0.04086,-0.03671 0.06129,-0.08653 0.06129,-0.149455 0,-0.06293 -0.02042,-0.112747 -0.06129,-0.149455 -0.04086,-0.03671 -0.09628,-0.05506 -0.166267,-0.05506 -0.03277,0 -0.06554,0.0036 -0.0983,0.01089 -0.03237,0.0073 -0.06554,0.01856 -0.09952,0.03388 l 0,-0.453811 m 1.126867,0.106494 -0.30947,0.48225 0.30947,0 0,-0.48225 m -0.03215,-0.106494 0.15412,0 0,0.588744 0.12926,0 0,0.101654 -0.12926,0 0,0.212988 -0.12197,0 0,-0.212988 -0.409,0 0,-0.117991 0.37685,-0.572407 m 0.76398,0.402984 c -0.05502,10e-7 -0.09871,0.01876 -0.13107,0.05627 -0.03196,0.03751 -0.04794,0.08895 -0.04794,0.154296 0,0.06494 0.01598,0.116377 0.04794,0.154295 0.03236,0.03751 0.07605,0.05627 0.13107,0.05627 0.05502,0 0.09851,-0.01876 0.13047,-0.05627 0.03236,-0.03792 0.04854,-0.08935 0.04855,-0.154295 -10e-6,-0.06535 -0.01619,-0.116781 -0.04855,-0.154296 -0.03196,-0.03751 -0.07545,-0.05627 -0.13047,-0.05627 m 0.24333,-0.383017 0,0.111335 c -0.03074,-0.01452 -0.06189,-0.02561 -0.09345,-0.03328 -0.03114,-0.0077 -0.06209,-0.0115 -0.09284,-0.0115 -0.08091,0 -0.1428,0.02723 -0.18569,0.08169 -0.04247,0.05446 -0.06675,0.136749 -0.07281,0.246873 0.02386,-0.03509 0.0538,-0.06192 0.0898,-0.08048 0.03601,-0.01896 0.07566,-0.02844 0.11894,-0.02844 0.09103,1e-6 0.16283,0.02763 0.21543,0.0829 0.05299,0.05486 0.07949,0.12969 0.07949,0.224486 0,0.09278 -0.02751,0.167204 -0.08253,0.223275 -0.05502,0.05607 -0.12824,0.08411 -0.21967,0.08411 -0.10478,0 -0.18488,-0.03993 -0.2403,-0.119806 -0.05543,-0.08027 -0.08314,-0.19645 -0.08314,-0.348527 0,-0.142799 0.03399,-0.256554 0.10195,-0.341266 0.06797,-0.08511 0.15919,-0.127671 0.27368,-0.127673 0.03074,2e-6 0.06169,0.003 0.09284,0.0091 0.03155,0.0061 0.06433,0.01513 0.0983,0.02723 m 0.27186,-0.01997 0.48121,0 0,0.102864 -0.36895,0 0,0.22146 c 0.0178,-0.0061 0.03561,-0.01049 0.0534,-0.01331 0.01781,-0.0032 0.0356,-0.0048 0.0534,-0.0048 0.10114,10e-7 0.18124,0.02763 0.24031,0.0829 0.05906,0.05527 0.08859,0.130093 0.08859,0.224486 0,0.09722 -0.03034,0.172851 -0.09102,0.226905 -0.06069,0.05365 -0.14625,0.08048 -0.25669,0.08048 -0.03802,0 -0.07686,-0.0032 -0.1165,-0.0097 -0.03925,-0.0065 -0.0799,-0.01614 -0.12198,-0.02905 l 0,-0.122831 c 0.03641,0.01977 0.07404,0.03449 0.11287,0.04417 0.03883,0.0097 0.0799,0.01452 0.12318,0.01452 0.07,0 0.12541,-0.01835 0.16627,-0.05506 0.04087,-0.03671 0.06129,-0.08653 0.06129,-0.149455 0,-0.06293 -0.02042,-0.112747 -0.06129,-0.149455 -0.04086,-0.03671 -0.09627,-0.05506 -0.16627,-0.05506 -0.03276,0 -0.06553,0.0036 -0.0983,0.01089 -0.03236,0.0073 -0.06554,0.01856 -0.09952,0.03388 l 0,-0.453811 m 1.15478,0 0.58255,0 0,0.05204 -0.3289,0.851349 -0.12804,0 0.30948,-0.800522 -0.43509,0 0,-0.102864 m 1.0844,0.08047 c -0.06311,1e-6 -0.11065,0.03106 -0.14261,0.09318 -0.03156,0.06172 -0.04733,0.154699 -0.04733,0.278942 0,0.12384 0.01577,0.216821 0.04733,0.278942 0.03196,0.06172 0.0795,0.09258 0.14261,0.09258 0.06351,0 0.11104,-0.03086 0.1426,-0.09258 0.03196,-0.06212 0.04794,-0.155102 0.04794,-0.278942 0,-0.124243 -0.01598,-0.217224 -0.04794,-0.278942 -0.03156,-0.06212 -0.07909,-0.09318 -0.1426,-0.09318 m 0,-0.09681 c 0.10153,2e-6 0.179,0.04014 0.2324,0.120412 0.05381,0.07987 0.08072,0.196047 0.08072,0.348527 0,0.152077 -0.02691,0.268253 -0.08072,0.348527 -0.0534,0.07987 -0.13087,0.119806 -0.2324,0.119806 -0.10155,0 -0.17922,-0.03993 -0.23303,-0.119806 -0.0534,-0.08027 -0.0801,-0.19645 -0.0801,-0.348527 0,-0.15248 0.0267,-0.268656 0.0801,-0.348527 0.05381,-0.08027 0.13148,-0.12041 0.23303,-0.120412 m 0.80646,0.419322 c -0.05502,10e-7 -0.09871,0.01876 -0.13108,0.05627 -0.03195,0.03751 -0.04793,0.08895 -0.04793,0.154296 0,0.06494 0.01598,0.116377 0.04793,0.154295 0.03237,0.03751 0.07606,0.05627 0.13108,0.05627 0.05501,0 0.09851,-0.01876 0.13047,-0.05627 0.03235,-0.03792 0.04854,-0.08935 0.04854,-0.154295 0,-0.06535 -0.01619,-0.116781 -0.04854,-0.154296 -0.03196,-0.03751 -0.07546,-0.05627 -0.13047,-0.05627 m 0.24333,-0.383017 0,0.111335 c -0.03074,-0.01452 -0.0619,-0.02561 -0.09345,-0.03328 -0.03114,-0.0077 -0.06209,-0.0115 -0.09284,-0.0115 -0.08091,0 -0.14281,0.02723 -0.18569,0.08169 -0.04248,0.05446 -0.06675,0.136749 -0.07281,0.246873 0.02386,-0.03509 0.05379,-0.06192 0.0898,-0.08048 0.036,-0.01896 0.07566,-0.02844 0.11894,-0.02844 0.09102,1e-6 0.16283,0.02763 0.21542,0.0829 0.053,0.05486 0.07949,0.12969 0.07949,0.224486 0,0.09278 -0.0275,0.167204 -0.08252,0.223275 -0.05502,0.05607 -0.12825,0.08411 -0.21967,0.08411 -0.10478,0 -0.18488,-0.03993 -0.2403,-0.119806 -0.05543,-0.08027 -0.08314,-0.19645 -0.08314,-0.348527 0,-0.142799 0.03399,-0.256554 0.10195,-0.341266 0.06796,-0.08511 0.15918,-0.127671 0.27367,-0.127673 0.03075,2e-6 0.0617,0.003 0.09285,0.0091 0.03155,0.0061 0.06432,0.01513 0.0983,0.02723 m 0.27186,-0.01997 0.48121,0 0,0.102864 -0.36895,0 0,0.22146 c 0.0178,-0.0061 0.03561,-0.01049 0.0534,-0.01331 0.0178,-0.0032 0.03561,-0.0048 0.0534,-0.0048 0.10114,1e-6 0.18124,0.02763 0.2403,0.0829 0.05907,0.05527 0.0886,0.130093 0.0886,0.224486 0,0.09722 -0.03034,0.172851 -0.09102,0.226905 -0.06069,0.05365 -0.14625,0.08048 -0.25669,0.08048 -0.03803,0 -0.07686,-0.0032 -0.11651,-0.0097 -0.03924,-0.0065 -0.07989,-0.01614 -0.12197,-0.02905 l 0,-0.122831 c 0.03641,0.01977 0.07404,0.03449 0.11287,0.04417 0.03883,0.0097 0.0799,0.01452 0.12318,0.01452 0.06999,0 0.12541,-0.01835 0.16627,-0.05506 0.04086,-0.03671 0.06129,-0.08653 0.0613,-0.149455 -10e-6,-0.06293 -0.02044,-0.112747 -0.0613,-0.149455 -0.04086,-0.03671 -0.09628,-0.05506 -0.16627,-0.05506 -0.03276,0 -0.06554,0.0036 -0.0983,0.01089 -0.03237,0.0073 -0.06554,0.01856 -0.09952,0.03388 l 0,-0.453811 m 1.15478,0 0.58255,0 0,0.05204 -0.3289,0.851349 -0.12804,0 0.30948,-0.800522 -0.43509,0 0,-0.102864 m 1.09956,0.402984 c -0.05502,1e-6 -0.09871,0.01876 -0.13107,0.05627 -0.03196,0.03751 -0.04794,0.08895 -0.04794,0.154296 0,0.06494 0.01598,0.116377 0.04794,0.154295 0.03236,0.03751 0.07605,0.05627 0.13107,0.05627 0.05502,0 0.09851,-0.01876 0.13047,-0.05627 0.03236,-0.03792 0.04854,-0.08935 0.04854,-0.154295 0,-0.06535 -0.01618,-0.116781 -0.04854,-0.154296 -0.03196,-0.03751 -0.07545,-0.05627 -0.13047,-0.05627 m 0.24334,-0.383017 0,0.111335 c -0.03075,-0.01452 -0.0619,-0.02561 -0.09345,-0.03328 -0.03115,-0.0077 -0.0621,-0.0115 -0.09285,-0.0115 -0.08091,0 -0.14281,0.02723 -0.18569,0.08169 -0.04248,0.05446 -0.06675,0.136749 -0.07281,0.246873 0.02386,-0.03509 0.0538,-0.06192 0.08981,-0.08048 0.036,-0.01896 0.07565,-0.02844 0.11894,-0.02844 0.09101,10e-7 0.16282,0.02763 0.21541,0.0829 0.053,0.05486 0.07949,0.12969 0.07949,0.224486 0,0.09278 -0.0275,0.167204 -0.08252,0.223275 -0.05502,0.05607 -0.12824,0.08411 -0.21967,0.08411 -0.10477,0 -0.18487,-0.03993 -0.2403,-0.119806 -0.05542,-0.08027 -0.08313,-0.19645 -0.08313,-0.348527 0,-0.142799 0.03398,-0.256554 0.10194,-0.341266 0.06796,-0.08511 0.15919,-0.127671 0.27368,-0.127673 0.03074,2e-6 0.06169,0.003 0.09284,0.0091 0.03156,0.0061 0.06432,0.01513 0.09831,0.02723 m 0.23969,-0.01997 0.58255,0 0,0.05204 -0.3289,0.851349 -0.12803,0 0.30947,-0.800522 -0.43509,0 0,-0.102864 m 0.82589,0.884629 0,-0.111335 c 0.03074,0.01452 0.06189,0.02562 0.09344,0.03328 0.03156,0.0077 0.06251,0.0115 0.09285,0.0115 0.08091,0 0.1426,-0.02703 0.18508,-0.08108 0.04288,-0.05446 0.06735,-0.13695 0.07342,-0.247479 -0.02346,0.03469 -0.05319,0.06132 -0.0892,0.07987 -0.036,0.01856 -0.07585,0.02783 -0.11954,0.02783 -0.09062,0 -0.16243,-0.02723 -0.21542,-0.08169 -0.0526,-0.05486 -0.07889,-0.129688 -0.07889,-0.224485 0,-0.09278 0.02751,-0.167204 0.08252,-0.223275 0.05503,-0.05607 0.12825,-0.08411 0.21968,-0.08411 0.10477,2e-6 0.18467,0.04014 0.23969,0.120412 0.05542,0.07987 0.08313,0.196047 0.08314,0.348527 -10e-6,0.142396 -0.03399,0.256151 -0.10195,0.341266 -0.06756,0.08471 -0.15858,0.127067 -0.27307,0.127067 -0.03074,0 -0.0619,-0.003 -0.09345,-0.0091 -0.03156,-0.0061 -0.06432,-0.01513 -0.0983,-0.02723 m 0.24394,-0.383016 c 0.05501,0 0.09851,-0.01876 0.13046,-0.05627 0.03236,-0.03751 0.04855,-0.08895 0.04855,-0.154296 0,-0.06495 -0.01619,-0.116174 -0.04855,-0.15369 -0.03195,-0.03792 -0.07545,-0.05688 -0.13046,-0.05688 -0.05502,10e-7 -0.09871,0.01896 -0.13108,0.05688 -0.03195,0.03752 -0.04793,0.08874 -0.04793,0.15369 0,0.06535 0.01598,0.116781 0.04793,0.154296 0.03237,0.03751 0.07606,0.05627 0.13108,0.05627 m 0.54735,0.383016 0,-0.111335 c 0.03074,0.01452 0.0619,0.02562 0.09345,0.03328 0.03155,0.0077 0.0625,0.0115 0.09285,0.0115 0.0809,0 0.1426,-0.02703 0.18508,-0.08108 0.04288,-0.05446 0.06735,-0.13695 0.07342,-0.247479 -0.02347,0.03469 -0.0532,0.06132 -0.0892,0.07987 -0.036,0.01856 -0.07586,0.02783 -0.11955,0.02783 -0.09062,0 -0.16242,-0.02723 -0.21542,-0.08169 -0.05259,-0.05486 -0.07888,-0.129688 -0.07888,-0.224485 0,-0.09278 0.0275,-0.167204 0.08252,-0.223275 0.05502,-0.05607 0.12825,-0.08411 0.21967,-0.08411 0.10478,2e-6 0.18468,0.04014 0.2397,0.120412 0.05542,0.07987 0.08313,0.196047 0.08313,0.348527 0,0.142396 -0.03398,0.256151 -0.10194,0.341266 -0.06757,0.08471 -0.15858,0.127067 -0.27308,0.127067 -0.03074,0 -0.06189,-0.003 -0.09345,-0.0091 -0.03155,-0.0061 -0.06432,-0.01513 -0.0983,-0.02723 m 0.24394,-0.383016 c 0.05502,0 0.09851,-0.01876 0.13046,-0.05627 0.03237,-0.03751 0.04855,-0.08895 0.04855,-0.154296 0,-0.06495 -0.01618,-0.116174 -0.04855,-0.15369 -0.03195,-0.03792 -0.07544,-0.05688 -0.13046,-0.05688 -0.05501,10e-7 -0.09871,0.01896 -0.13107,0.05688 -0.03196,0.03752 -0.04794,0.08874 -0.04794,0.15369 0,0.06535 0.01598,0.116781 0.04794,0.154296 0.03236,0.03751 0.07606,0.05627 0.13107,0.05627"
+       id="text7050"
+       style="font-size:1.58812129px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:120.00000477%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans" />
+    <rect
+       width="9.9773989"
+       height="11.70446"
+       rx="0.31249964"
+       ry="0.31249976"
+       x="5.0519104"
+       y="19.740776"
+       id="rect6553"
+       style="fill:url(#linearGradient7883);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.91310632;marker:none;visibility:visible;display:inline;overflow:visible" />
+    <g
+       transform="matrix(0.300427,0,0,0.299566,-1.239336,19.26775)"
+       id="g6935"
+       style="fill:#939393;fill-opacity:1;stroke:none">
+      <path
+         d="m 50.301157,40.747425 c 1.035639,-2.982476 0.176777,-8.892289 -6.540737,-13.488483 l -12.551146,0 c -6.717514,4.24264 -7.556991,10.044831 -6.010407,13.435028 0,0 25.10229,0.05345 25.10229,0.05345 z"
+         id="path2329"
+         style="fill:#939393;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:6.3771019;marker:none;visibility:visible;display:inline;overflow:visible" />
+      <path
+         d="m 39.774755,19.008621 a 8.6620579,8.6620579 0 1 1 -17.324115,0 8.6620579,8.6620579 0 1 1 17.324115,0 z"
+         transform="translate(6.407083,1.742408)"
+         id="path2327"
+         style="fill:#939393;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:6.3771019;marker:none;visibility:visible;display:inline;overflow:visible" />
+    </g>
+    <rect
+       width="32.000011"
+       height="22.000008"
+       rx="1.7777265"
+       ry="1.7777265"
+       x="3.500001"
+       y="17.499992"
+       id="rect6555"
+       style="fill:none;stroke:#ffffff;stroke-width:1.91310632;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible" />
+  </g>
+  <rect
+     width="19.010012"
+     height="12.989197"
+     rx="0.9554745"
+     ry="0.9554745"
+     x="0.49499393"
+     y="4.4949956"
+     id="rect2373"
+     style="fill:url(#linearGradient2918);fill-opacity:1;fill-rule:evenodd;stroke:#939393;stroke-width:0.98998767;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible" />
+  <path
+     d="M 9.573176,7.5087174 C 9.590116,7.7680994 9.459654,8.110498 9.152277,8.098906 8.958476,8.135 9.00126,7.9554092 8.999999,7.8327116 c 0.01424,-0.046426 0.295053,0.099821 0.30707,-0.1145656 0.05248,-0.2799917 0.01703,-0.5689122 0.02743,-0.8530236 0.01861,-0.077288 -0.03848,-0.2302757 0.03074,-0.2569546 0.07626,0.018668 0.244681,-0.054816 0.207937,0.076861 0,0.274563 0,0.549126 0,0.823689 z m 0.666423,-0.520996 c 0.327668,-0.014597 0.482629,0.3578734 0.433525,0.636919 0.0068,0.3228281 -0.345852,0.5791316 -0.644403,0.4353456 C 9.704875,7.8929322 9.691675,7.4076643 9.892273,7.1413744 9.975553,7.0377977 10.108341,6.9850262 10.239599,6.9877214 z m -0.01968,0.890375 c 0.304692,-0.030483 0.316983,-0.5638347 0.05202,-0.661867 -0.36198,-0.062264 -0.396644,0.6507089 -0.05203,0.661867 z M 11.67338,8.067362 c -0.07409,-0.02283 -0.249813,0.05597 -0.229273,-0.06149 -0.0078,-0.2265064 0.01884,-0.4563068 -0.02069,-0.6799369 -0.133462,-0.2597947 -0.394183,0.039327 -0.322354,0.2393985 0,0.1673424 0,0.3346849 0,0.5020274 -0.06841,-0.02424 -0.238002,0.0527 -0.231836,-0.04612 0,-0.4988398 0,-0.9976796 0,-1.4965193 0.06841,0.024237 0.238002,-0.052701 0.231836,0.046116 0,0.2000137 0,0.4000275 0,0.6000412 0.09467,-0.2631603 0.52995,-0.2338573 0.554136,0.057239 0.03479,0.2770226 0.01132,0.5601297 0.01819,0.8392391 z m 1.050542,0 c -0.07409,-0.02283 -0.249812,0.05597 -0.229272,-0.06149 -0.0078,-0.2265063 0.01885,-0.4563082 -0.02069,-0.6799369 -0.133464,-0.2597948 -0.394189,0.039325 -0.322359,0.2393985 0,0.1673424 0,0.3346849 0,0.5020274 -0.06841,-0.02424 -0.238002,0.0527 -0.231836,-0.04612 0,-0.3319583 0,-0.6639165 0,-0.9958747 0.06841,0.024238 0.238002,-0.052701 0.231836,0.046116 -0.03571,0.2312441 0.209359,-0.2396496 0.380638,-0.06874 0.240483,0.1084785 0.183823,0.4097303 0.191684,0.6275647 0,0.1456834 0,0.2913669 0,0.43705 z m 0.750256,-1.4591942 c 0.287395,0.017381 0.614129,-0.064527 0.855192,0.136339 0.241518,0.2432184 0.239005,0.6444255 0.129069,0.9487409 -0.101991,0.2707825 -0.399103,0.4051683 -0.675276,0.3741143 -0.102995,0 -0.20599,0 -0.308985,0 0,-0.4863978 0,-0.972796 0,-1.4591942 z m 0.238677,1.2343116 c 0.191729,0.012265 0.423493,-0.0084 0.509764,-0.2123525 0.125197,-0.2621459 0.08546,-0.7123857 -0.25456,-0.7799037 -0.08731,0.013084 -0.301155,-0.074906 -0.255204,0.084219 0,0.3026791 0,0.6053583 0,0.9080374 z m 1.42695,-0.854758 c 0.327666,-0.014597 0.482632,0.3578735 0.433529,0.636919 0.0068,0.3228301 -0.345854,0.5791316 -0.644405,0.4353456 -0.323851,-0.1670528 -0.337044,-0.6523186 -0.136452,-0.9186116 0.08327,-0.1035815 0.216071,-0.1563463 0.347328,-0.153653 z m -0.01968,0.890375 c 0.304693,-0.030481 0.316984,-0.5638342 0.05202,-0.661867 -0.361983,-0.062264 -0.396638,0.6507079 -0.05202,0.661867 z m 1.402995,-0.271693 c -0.194481,0 -0.388962,0 -0.583443,0 -0.0552,0.3638961 0.428733,0.2312211 0.50132,0.2231744 0.0509,0.1786152 -0.08967,0.2676342 -0.26143,0.2619212 -0.326493,0.04945 -0.51851,-0.3067037 -0.470681,-0.5912713 -0.01895,-0.3067557 0.287558,-0.6268862 0.59737,-0.4819783 0.217779,0.1086926 0.22174,0.3767488 0.216872,0.588154 z m -0.213867,-0.183162 c 0.06051,-0.3207056 -0.437363,-0.2580341 -0.354198,0 0.118065,0 0.236131,0 0.354196,0 z"
+     id="path2375"
+     style="font-size:4.12102222px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:120.00000477%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;display:inline;font-family:Segoe" />
+  <rect
+     width="7.499999"
+     height="1.0494535"
+     rx="0.49999997"
+     ry="0.52472675"
+     x="8.999999"
+     y="9.148365"
+     id="rect2377"
+     style="opacity:0.3976608;fill:#8d8d8d;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible" />
+  <rect
+     width="5.9999995"
+     height="1.0494535"
+     rx="0.49999997"
+     ry="0.52472675"
+     x="8.999999"
+     y="10.722544"
+     id="rect2379"
+     style="opacity:0.3976608;fill:#8d8d8d;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible" />
+  <path
+     d="M 2,13.875 2,16 l 0.5,0 0,-2.125 -0.5,0 z m 1,0 0,1.03125 1,0 0,-1.03125 -1,0 z m 1.5,0 0,1.03125 0.5,0 0,-1.03125 -0.5,0 z m 1,0 0,1.03125 1,0 0,-1.03125 -1,0 z m 2,0 0,1.03125 0.5,0 0,-1.03125 -0.5,0 z m 1,0 0,1.03125 1,0 0,-1.03125 -1,0 z m 1.5,0 0,1.03125 1,0 0,-1.03125 -1,0 z"
+     id="rect2383"
+     style="opacity:0.48538011;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible" />
+  <rect
+     width="6"
+     height="7"
+     rx="0.1879245"
+     ry="0.18689443"
+     x="2"
+     y="6.0000019"
+     id="rect2415"
+     style="fill:url(#linearGradient2905);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible" />
+  <path
+     d="M 4.875,7.78125 C 3.8870611,7.793019 3.080052,8.859894 3.4154196,9.806677 c 0.017081,0.268718 0.4174298,0.608587 0.4479609,0.724573 -0.1722069,0.02911 -0.306249,0.185322 -0.4511408,0.280441 -0.5465131,0.430888 -0.9751065,1.121725 -0.8550737,1.839996 0.037643,0.13003 0.038179,0.371169 0.2276924,0.317063 1.5300472,0 3.0600944,0 4.5901416,0 C 7.5889424,12.308501 7.2812244,11.590921 6.8329971,11.102488 6.6295102,10.884377 6.3989205,10.677674 6.1419602,10.53125 5.8980366,10.567057 6.224519,10.402258 6.2603926,10.309569 6.971785,9.545478 6.5651174,8.193913 5.5882976,7.8835708 5.3616343,7.798463 5.1163878,7.7635579 4.875,7.78125 z"
+     id="path2419"
+     style="fill:#939393;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:5.84023809;marker:none;visibility:visible;display:inline;overflow:visible" />
+  <rect
+     width="17.001713"
+     height="10.948627"
+     rx="0.14346921"
+     ry="0.14346921"
+     x="1.4788659"
+     y="5.5054727"
+     id="rect2423"
+     style="fill:none;stroke:#ffffff;stroke-width:0.98998767;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible" />
+  <g
+     transform="translate(1.389377,-23.361317)"
+     id="g7443"
+     style="display:inline">
+    <path
+       d="m 13.100088,37.861326 0,-3 4,0 0,3 3,0 0,4 -3,0 0,2.999991 -4,0 0,-2.999991 -2.989465,0 0,-4 2.989465,0 z"
+       id="path5596"
+       style="fill:url(#linearGradient7447);fill-opacity:1;fill-rule:evenodd;stroke:#699536;stroke-width:1;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline" />
+    <path
+       d="m 14.100088,38.861326 0,-3 2,0 0,3 3,0 0,2 -3,0 0,3 -2,0 0,-3 -3,0 0,-2 3,0 z"
+       id="path5598"
+       style="opacity:0.4;fill:none;stroke:url(#linearGradient7449);stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline" />
+  </g>
+</svg>
diff --git a/apps/contacts/import.php b/apps/contacts/import.php
old mode 100644
new mode 100755
index 04cfc397d56a7322dadbaae7ad90f8e551092f3b..2386a1cff980d6f7bf579dfe7c5a15cce1a19dd5
--- a/apps/contacts/import.php
+++ b/apps/contacts/import.php
@@ -7,9 +7,9 @@
  */
 //check for addressbooks rights or create new one
 ob_start();
-require_once ('../../lib/base.php');
-OC_JSON::checkLoggedIn();
-OC_Util::checkAppEnabled('calendar');
+ 
+OCP\JSON::checkLoggedIn();
+OCP\App::checkAppEnabled('contacts');
 $nl = "\n";
 $progressfile = 'import_tmp/' . md5(session_id()) . '.txt';
 if(is_writable('import_tmp/')){
@@ -17,9 +17,20 @@ if(is_writable('import_tmp/')){
 	fwrite($progressfopen, '10');
 	fclose($progressfopen);
 }
-$file = OC_Filesystem::file_get_contents($_POST['path'] . '/' . $_POST['file']);
-if($_POST['method'] == 'new'){
-	$id = OC_Contacts_Addressbook::add(OC_User::getUser(), $_POST['addressbookname']);
+$view = $file = null;
+if(isset($_POST['fstype']) && $_POST['fstype'] == 'OC_FilesystemView') {
+	$view = OCP\App::getStorage('contacts');
+	$file = $view->file_get_contents('/' . $_POST['file']);
+} else {
+	$file = OC_Filesystem::file_get_contents($_POST['path'] . '/' . $_POST['file']);
+}
+if(!$file) {
+	OCP\JSON::error(array('message' => 'Import file was empty.'));
+	exit();
+}
+
+if(isset($_POST['method']) && $_POST['method'] == 'new'){
+	$id = OC_Contacts_Addressbook::add(OCP\USER::getUser(), $_POST['addressbookname']);
 	OC_Contacts_Addressbook::setActive($id, 1);
 }else{
 	$id = $_POST['id'];
@@ -99,12 +110,16 @@ if(is_writable('import_tmp/')){
 if(count($parts) == 1){
 	$importready = array($file);
 }
+$imported = 0;
+$failed = 0;
 foreach($importready as $import){
 	$card = OC_VObject::parse($import);
 	if (!$card) {
-		OC_Log::write('contacts','Import: skipping card. Error parsing VCard: '.$import, OC_Log::ERROR);
+		$failed += 1;
+		OCP\Util::writeLog('contacts','Import: skipping card. Error parsing VCard: '.$import, OCP\Util::ERROR);
 		continue; // Ditch cards that can't be parsed by Sabre.
 	}
+	$imported += 1;
 	OC_Contacts_VCard::add($id, $card);
 }
 //done the import
@@ -117,4 +132,9 @@ sleep(3);
 if(is_writable('import_tmp/')){
 	unlink($progressfile);
 }
-OC_JSON::success();
+if(isset($_POST['fstype']) && $_POST['fstype'] == 'OC_FilesystemView') {
+	if(!$view->unlink('/' . $_POST['file'])) {
+		OCP\Util::writeLog('contacts','Import: Error unlinking OC_FilesystemView ' . '/' . $_POST['file'], OCP\Util::ERROR);
+	}
+}
+OCP\JSON::success(array('data' => array('imported'=>$imported, 'failed'=>$failed)));
diff --git a/apps/contacts/index.php b/apps/contacts/index.php
old mode 100644
new mode 100755
index 4039b8afd3d9479813ca31a0dc3fe6a8f6daca06..814a8927f321a85496e35ad9d4e24b2dd947b01e
--- a/apps/contacts/index.php
+++ b/apps/contacts/index.php
@@ -6,20 +6,20 @@
  * later.
  * See the COPYING-README file.
  */
-require_once('../../lib/base.php');
+
 
 // Check if we are a user
-OC_Util::checkLoggedIn();
-OC_Util::checkAppEnabled('contacts');
+OCP\User::checkLoggedIn();
+OCP\App::checkAppEnabled('contacts');
 
 // Get active address books. This creates a default one if none exists.
-$ids = OC_Contacts_Addressbook::activeIds(OC_User::getUser());
+$ids = OC_Contacts_Addressbook::activeIds(OCP\USER::getUser());
 $contacts = OC_Contacts_VCard::all($ids);
 
-$addressbooks = OC_Contacts_Addressbook::active(OC_User::getUser());
+$addressbooks = OC_Contacts_Addressbook::active(OCP\USER::getUser());
 
 // Load the files we need
-OC_App::setActiveNavigationEntry( 'contacts_index' );
+OCP\App::setActiveNavigationEntry( 'contacts_index' );
 
 // Load a specific user?
 $id = isset( $_GET['id'] ) ? $_GET['id'] : null;
@@ -34,33 +34,35 @@ if(!is_null($id)) {
 }
 $property_types = OC_Contacts_App::getAddPropertyOptions();
 $phone_types = OC_Contacts_App::getTypesOfProperty('TEL');
+$email_types = OC_Contacts_App::getTypesOfProperty('EMAIL');
 $categories = OC_Contacts_App::getCategories();
 
-$upload_max_filesize = OC_Helper::computerFileSize(ini_get('upload_max_filesize'));
-$post_max_size = OC_Helper::computerFileSize(ini_get('post_max_size'));
+$upload_max_filesize = OCP\Util::computerFileSize(ini_get('upload_max_filesize'));
+$post_max_size = OCP\Util::computerFileSize(ini_get('post_max_size'));
 $maxUploadFilesize = min($upload_max_filesize, $post_max_size);
 
 $freeSpace=OC_Filesystem::free_space('/');
 $freeSpace=max($freeSpace,0);
 $maxUploadFilesize = min($maxUploadFilesize ,$freeSpace);
 
-OC_Util::addScript('','jquery.multiselect');
-OC_Util::addScript('','oc-vcategories');
-OC_Util::addScript('contacts','contacts');
-OC_Util::addScript('contacts','jquery.combobox');
-OC_Util::addScript('contacts','jquery.inview');
-OC_Util::addScript('contacts','jquery.Jcrop');
-OC_Util::addScript('contacts','jquery.multi-autocomplete');
-OC_Util::addStyle('','jquery.multiselect');
-OC_Util::addStyle('contacts','jquery.combobox');
-OC_Util::addStyle('contacts','jquery.Jcrop');
-OC_Util::addStyle('contacts','contacts');
+OCP\Util::addscript('','jquery.multiselect');
+OCP\Util::addscript('','oc-vcategories');
+OCP\Util::addscript('contacts','contacts');
+OCP\Util::addscript('contacts','jquery.combobox');
+OCP\Util::addscript('contacts','jquery.inview');
+OCP\Util::addscript('contacts','jquery.Jcrop');
+OCP\Util::addscript('contacts','jquery.multi-autocomplete');
+OCP\Util::addStyle('','jquery.multiselect');
+OCP\Util::addStyle('contacts','jquery.combobox');
+OCP\Util::addStyle('contacts','jquery.Jcrop');
+OCP\Util::addStyle('contacts','contacts');
 
 $tmpl = new OC_Template( "contacts", "index", "user" );
 $tmpl->assign('uploadMaxFilesize', $maxUploadFilesize);
-$tmpl->assign('uploadMaxHumanFilesize', OC_Helper::humanFileSize($maxUploadFilesize));
+$tmpl->assign('uploadMaxHumanFilesize', OCP\Util::humanFileSize($maxUploadFilesize));
 $tmpl->assign('property_types', $property_types);
 $tmpl->assign('phone_types', $phone_types);
+$tmpl->assign('email_types', $email_types);
 $tmpl->assign('categories', $categories);
 $tmpl->assign('addressbooks', $addressbooks);
 $tmpl->assign('contacts', $contacts);
diff --git a/apps/contacts/js/contacts.js b/apps/contacts/js/contacts.js
index 5f2bd6e9df9bbd0dccfdb40b9bdb4e69cb69baea..bb8b6b89e57c53d771cca51fb6d6b3e3f3540fa1 100644
--- a/apps/contacts/js/contacts.js
+++ b/apps/contacts/js/contacts.js
@@ -12,12 +12,19 @@ String.prototype.strip_tags = function(){
 
 Contacts={
 	UI:{
+		notification:function(msg, ndata) {
+			$('#notification').text(msg);
+			if(data) {
+				$('#notification').data(ndata[0],ndata[1]);
+			}
+			$('#notification').fadeIn();
+			setTimeout($('#notification').fadeOut(), 10000);
+		},
 		notImplemented:function() {
 			OC.dialogs.alert(t('contacts', 'Sorry, this functionality has not been implemented yet'), t('contacts', 'Not implemented'));
 		},
 		searchOSM:function(obj) {
 			var adr = Contacts.UI.propertyContainerFor(obj).find('.adr').val();
-			console.log('adr 1: ' + adr);
 			if(adr == undefined) {
 				OC.dialogs.alert(t('contacts', 'Couldn\'t get a valid address.'), t('contacts', 'Error'));
 				return;
@@ -40,11 +47,8 @@ Contacts={
 			if(adrarr[6].trim() != '') {
 				adrstr = adrstr + adrarr[6].trim();
 			}
-			console.log('adrstr: "' + adrstr + '"');
 			adrstr = encodeURIComponent(adrstr);
-			console.log('adrstr 2: ' + adrstr);
 			var uri = 'http://open.mapquestapi.com/nominatim/v1/search.php?q=' + adrstr + '&limit=10&addressdetails=1&zoom=';
-			console.log('uri: ' + uri);
 			var newWindow = window.open(uri,'_blank');
 			newWindow.focus();
 		},
@@ -65,43 +69,6 @@ Contacts={
 		propertyTypeFor:function(obj) {
 			return $(obj).parents('.propertycontainer').first().data('element');
 		},
-		/*showHideContactInfo:function() {
-			var show = ($('#emaillist li.propertycontainer').length > 0 || $('#phonelist li.propertycontainer').length > 0 || $('#addressdisplay dl.propertycontainer').length > 0);
-			console.log('showHideContactInfo: ' + show);
-			if(show) {
-				$('#contact_communication').show();
-			} else {
-				$('#contact_communication').hide();
-			}
-		},*/
-		/*checkListFor:function(obj) {
-			var type = $(obj).parents('.propertycontainer').first().data('element');
-			console.log('checkListFor: ' + type);
-			switch (type) {
-				case 'EMAIL':
-					console.log('emails: '+$('#emaillist>li').length);
-					if($('#emaillist li.propertycontainer').length == 0) {
-						$('#emails').hide();
-					}
-					break;
-				case 'TEL':
-					console.log('phones: '+$('#phonelist>li').length);
-					if($('#phonelist li.propertycontainer').length == 0) {
-						$('#phones').hide();
-					}
-					break;
-				case 'ADR':
-					console.log('addresses: '+$('#addressdisplay>dl').length);
-					if($('#addressdisplay dl.propertycontainer').length == 0) {
-						$('#addresses').hide();
-					}
-					break;
-				case 'NICKNAME':
-				case 'ORG':
-				case 'BDAY':
-					break;
-			}
-		},*/
 		loading:function(obj, state) {
 			if(state) {
 				$(obj).addClass('loading');
@@ -115,45 +82,48 @@ Contacts={
 			$('#carddav_url_close').show();
 		},
 		loadListHandlers:function() {
-			//$('.add,.delete').hide();
+			$('.propertylist li a.delete').unbind('click');
+			$('.propertylist li a.delete').unbind('keydown');
 			$('.globe,.mail,.delete,.edit,.tip').tipsy();
+			var deleteItem = function(obj) {
+				obj.tipsy('hide');
+				Contacts.UI.Card.deleteProperty(obj, 'list');
+			}
+			$('.propertylist li a.delete, .addresscard .delete').click(function() { deleteItem($(this)) });
+			$('.propertylist li a.delete, .addresscard .delete').keydown(function() { deleteItem($(this)) });
+			$('.propertylist li a.mail').click(function() { Contacts.UI.mailTo(this) });
+			$('.propertylist li a.mail').keydown(function() { Contacts.UI.mailTo(this) });
+			$('.addresscard .globe').click(function() { $(this).tipsy('hide');Contacts.UI.searchOSM(this); });
+			$('.addresscard .globe').keydown(function() { $(this).tipsy('hide');Contacts.UI.searchOSM(this); });
+			$('.addresscard .edit').click(function() { $(this).tipsy('hide');Contacts.UI.Card.editAddress(this, false); });
+			$('.addresscard .edit').keydown(function() { $(this).tipsy('hide');Contacts.UI.Card.editAddress(this, false); });
 			$('.addresscard,.propertylist li,.propertycontainer').hover(
 				function () {
-					$(this).find('.globe,.mail,.delete,.edit').fadeIn(100);
+					$(this).find('.globe,.mail,.delete,.edit').animate({ opacity: 1.0 }, 200, function() {});
 				}, 
 				function () {
-					$(this).find('.globe,.mail,.delete,.edit').fadeOut(100);
+					$(this).find('.globe,.mail,.delete,.edit').animate({ opacity: 0.1 }, 200, function() {});
 				}
 			);
 		},
 		loadHandlers:function() {
-			//console.log('loadHandlers');
-			/*
-			$('.formfloat').hover(
-				function () {
-					$(this).find('.add').fadeIn(500);
-				}, 
-				function () {
-					$(this).find('.add').fadeOut(500);
-				}
-			);*/
-			//$('#fn').jec();
+			var deleteItem = function(obj) {
+				obj.tipsy('hide');
+				Contacts.UI.Card.deleteProperty(obj, 'single');
+			}
+			$('#identityprops a.delete').click( function() { deleteItem($(this)) });
+			$('#identityprops a.delete').keydown( function() { deleteItem($(this)) });
+			$('#categories_value a.edit').click( function() { $(this).tipsy('hide');OCCategories.edit(); } );
+			$('#categories_value a.edit').keydown( function() { $(this).tipsy('hide');OCCategories.edit(); } );
 			$('#fn_select').combobox({
 				'id': 'fn',
 				'name': 'value',
 				'classes': ['contacts_property', 'huge', 'tip', 'float'],
 				'attributes': {'placeholder': t('contacts', 'Enter name')},
 				'title': t('contacts', 'Format custom, Short name, Full name, Reverse or Reverse with comma')});
-			//$('.jecEditableOption').attr('title', t('contacts','Custom'));
 			$('#bday').datepicker({
 						dateFormat : 'dd-mm-yy'
 			});
-			/*$('#categories_value').find('select').multiselect({
-										noneSelectedText: t('contacts', 'Select categories'),
-										header: false,
-										selectedList: 6,
-										classes: 'categories'
-									});*/
 			// Style phone types
 			$('#phonelist').find('select.contacts_property').multiselect({
 													noneSelectedText: t('contacts', 'Select type'),
@@ -161,20 +131,8 @@ Contacts={
 													selectedList: 4,
 													classes: 'typelist'
 												});
-			$('#add_email').click(function(){
-				Contacts.UI.Card.addMail();
-			});
-			$('#add_phone').click(function(){
-				Contacts.UI.Card.addPhone();
-			});
-// 			$('#add_address').click(function(){
-// 				Contacts.UI.Card.editAddress();
-// 				return false;
-// 			});
-			$('#edit_name').click(function(){
-				Contacts.UI.Card.editName();
-				return false;
-			});
+			$('#edit_name').click(function(){Contacts.UI.Card.editName()});
+			$('#edit_name').keydown(function(){Contacts.UI.Card.editName()});
 			
 			/* Initialize the photo edit dialog */
 			$('#edit_photo_dialog').dialog({ autoOpen: false, modal: true, height: 'auto', width: 'auto' });
@@ -192,10 +150,10 @@ Contacts={
 				}
 			] );
 			$('#categories').multiple_autocomplete({source: categories});
-			$('.button,.action,.tip').tipsy();
 			$('#contacts_deletecard').tipsy({gravity: 'ne'});
 			$('#contacts_downloadcard').tipsy({gravity: 'ne'});
-			Contacts.UI.loadListHandlers();
+			$('#contacts_propertymenu_button').tipsy();
+			$('#contacts_newcontact, #chooseaddressbook').tipsy({gravity: 'sw'});
 		},
 		Card:{
 			id:'',
@@ -211,37 +169,32 @@ Contacts={
 			update:function(id) {
 				// Make sure proper DOM is loaded.
 				var newid;
-				console.log('Card.update(), id: ' + id);
-				console.log('Card.update(), #contacts: ' + $('#contacts li').length);
 				if(id == undefined) {
 					newid = $('#contacts li:first-child').data('id');
 				} else {
 					newid = id;
 				}
-				if($('#contacts li').length > 0) {
+				if(!$('n')) {
 					$.getJSON(OC.filePath('contacts', 'ajax', 'loadcard.php'),{},function(jsondata){
 						if(jsondata.status == 'success'){
 							$('#rightcontent').html(jsondata.data.page);
-							Contacts.UI.loadHandlers();
-							if($('#contacts li').length > 0) {
-								//var newid = $('#contacts li:first-child').data('id');
-								//$('#contacts li:first-child').addClass('active');
-								$('#leftcontent li[data-id="'+newid+'"]').addClass('active');
-								console.log('trying to load: ' + newid);
-								$.getJSON(OC.filePath('contacts', 'ajax', 'contactdetails.php'),{'id':newid},function(jsondata){
-									if(jsondata.status == 'success'){
-										Contacts.UI.Card.loadContact(jsondata.data);
-									} else{
-										OC.dialogs.alert(jsondata.data.message, t('contacts', 'Error'));
-									}
-								});
-							}
-						} else{
+						} else {
 							OC.dialogs.alert(jsondata.data.message, t('contacts', 'Error'));
 						}
 					});
 				}
-				if($('#contacts li').length == 0) {
+				if($('#contacts li').length > 0) {
+					//var newid = $('#contacts li:first-child').data('id');
+					//$('#contacts li:first-child').addClass('active');
+					$('#leftcontent li[data-id="'+newid+'"]').addClass('active');
+					$.getJSON(OC.filePath('contacts', 'ajax', 'contactdetails.php'),{'id':newid},function(jsondata){
+						if(jsondata.status == 'success'){
+							Contacts.UI.Card.loadContact(jsondata.data);
+						} else {
+							OC.dialogs.alert(jsondata.data.message, t('contacts', 'Error'));
+						}
+					});
+				} else if($('#contacts li').length == 0) {
 					// load intro page
 					$.getJSON(OC.filePath('contacts', 'ajax', 'loadintro.php'),{},function(jsondata){
 						if(jsondata.status == 'success'){
@@ -263,10 +216,8 @@ Contacts={
 				Contacts.UI.notImplemented();
 			},
 			add:function(n, fn, aid, isnew){ // add a new contact
-				console.log('Add contact: ' + n + ', ' + fn + ' ' + aid);
 				var card = $('#card')[0];
 				if(!card) {
-					console.log('Loading proper card DOM');
 					$.getJSON(OC.filePath('contacts', 'ajax', 'loadcard.php'),{},function(jsondata){
 						if(jsondata.status == 'success'){
 							$('#rightcontent').html(jsondata.data.page);
@@ -281,12 +232,12 @@ Contacts={
 					if (jsondata.status == 'success'){
 						$('#rightcontent').data('id',jsondata.data.id);
 						var id = jsondata.data.id;
-						$.getJSON('ajax/contactdetails.php',{'id':id},function(jsondata){
+						$.getJSON(OC.filePath('contacts', 'ajax', 'contactdetails.php'),{'id':id},function(jsondata){
 							if(jsondata.status == 'success'){
 								Contacts.UI.loadHandlers();
 								Contacts.UI.Card.loadContact(jsondata.data);
 								$('#leftcontent .active').removeClass('active');
-								var item = '<li data-id="'+jsondata.data.id+'" class="active"><a href="index.php?id='+jsondata.data.id+'"  style="background: url(thumbnail.php?id='+jsondata.data.id+') no-repeat scroll 0% 0% transparent;">'+Contacts.UI.Card.fn+'</a></li>';
+								var item = '<li data-id="'+jsondata.data.id+'" class="active"><a href="index.php?id='+jsondata.data.id+'"  style="background: url('+OC.filePath('contacts', '', 'thumbnail.php')+'?id='+jsondata.data.id+') no-repeat scroll 0% 0% transparent;">'+Contacts.UI.Card.fn+'</a></li>';
 								var added = false;
 								$('#leftcontent ul li').each(function(){
 									if ($(this).text().toLowerCase() > Contacts.UI.Card.fn.toLowerCase()) {
@@ -327,12 +278,11 @@ Contacts={
 				$('#contacts_deletecard').tipsy('hide');
 				OC.dialogs.confirm(t('contacts', 'Are you sure you want to delete this contact?'), t('contacts', 'Warning'), function(answer) {
 					if(answer == true) {
-						$.getJSON('ajax/deletecard.php',{'id':Contacts.UI.Card.id},function(jsondata){
+						$.getJSON(OC.filePath('contacts', 'ajax', 'deletecard.php'),{'id':Contacts.UI.Card.id},function(jsondata){
 							if(jsondata.status == 'success'){
 								var newid = '';
 								var curlistitem = $('#leftcontent [data-id="'+jsondata.data.id+'"]');
 								var newlistitem = curlistitem.prev();
-								console.log('Previous: ' + newlistitem);
 								if(newlistitem == undefined) {
 									newlistitem = curlistitem.next();
 								}
@@ -349,7 +299,7 @@ Contacts={
 									Contacts.UI.Card.update(newid);
 								} else {
 									// load intro page
-									$.getJSON('ajax/loadintro.php',{},function(jsondata){
+									$.getJSON(OC.filePath('contacts', 'ajax', 'loadintro.php'),{},function(jsondata){
 										if(jsondata.status == 'success'){
 											id = '';
 											$('#rightcontent').data('id','');
@@ -375,22 +325,22 @@ Contacts={
 				this.data = jsondata;
 				this.id = this.data.id;
 				$('#rightcontent').data('id',this.id);
-				console.log('loaded: ' + this.data.FN[0]['value']);
 				this.populateNameFields();
-				//this.loadCategories();
 				this.loadPhoto();
 				this.loadMails();
 				this.loadPhones();
 				this.loadAddresses();
 				this.loadSingleProperties();
+				Contacts.UI.loadListHandlers();
 				if(this.data.NOTE) {
 					$('#note').data('checksum', this.data.NOTE[0]['checksum']);
 					$('#note').find('textarea').val(this.data.NOTE[0]['value']);
 					$('#note').show();
+					$('#contacts_propertymenu a[data-type="NOTE"]').parent().hide();
 				} else {
 					$('#note').data('checksum', '');
 					$('#note').find('textarea').val('');
-					//$('#note').hide();
+					$('#note').hide();
 				}
 			},
 			loadSingleProperties:function() {
@@ -494,9 +444,7 @@ Contacts={
 					var categories = this.data.CATEGORIES[0]['value'].split(/,\s*/);
 					for(var c in categories) {
 						var cat = this.data.CATEGORIES[0]['value'][c];
-						console.log('hasCategory: ' + cat + ' === ' + category + '?');
 						if(typeof cat === 'string' && (cat.toUpperCase() === category.toUpperCase())) {
-							console.log('Yes');
 							return true;
 						}
 					}
@@ -505,12 +453,10 @@ Contacts={
 			},
 			categoriesChanged:function(newcategories) { // Categories added/deleted.
 				categories = $.map(newcategories, function(v) {return v;});
-				console.log('categoriesChanged for ' + Contacts.UI.Card.id + ' : ' + categories);
 				$('#categories').multiple_autocomplete('option', 'source', categories);
 				var categorylist = $('#categories_value').find('input');
 				$.getJSON(OC.filePath('contacts', 'ajax', 'categories/categoriesfor.php'),{'id':Contacts.UI.Card.id},function(jsondata){
 					if(jsondata.status == 'success'){
-						console.log('Setting checksum: ' + jsondata.data.checksum + ', value: ' + jsondata.data.value);
 						$('#categories_value').data('checksum', jsondata.data.checksum);
 						categorylist.val(jsondata.data.value);
 					} else {
@@ -518,41 +464,15 @@ Contacts={
 					}
 				});
 			},
-			/*loadCategories:function(){ // On loading contact.
-				var categories = $('#categories_value').find('select');
-				if(this.data.CATEGORIES) {
-					$('#categories_value').data('checksum', this.data.CATEGORIES[0]['checksum']);
-				} else {
-					$('#categories_value').data('checksum', '');
-				}
-				categories.find('option').each(function(){ 
-					if(Contacts.UI.Card.hasCategory($(this).val())) {
-						$(this).attr('selected', 'selected');
-					} else {
-						$(this).removeAttr('selected');
-					}
-				});
-				categories.multiselect('refresh');
-			},*/
 			editNew:function(){ // add a new contact
 				this.id = ''; this.fn = ''; this.fullname = ''; this.givname = ''; this.famname = ''; this.addname = ''; this.honpre = ''; this.honsuf = '';
-				Contacts.UI.Card.add(';;;;', '', '', true);
-				/*$.getJSON(OC.filePath('contacts', 'ajax', 'newcontact.php'),{},function(jsondata){
-					if(jsondata.status == 'success'){
-						id = '';
-						$('#rightcontent').data('id','');
-						$('#rightcontent').html(jsondata.data.page);
-						//Contacts.UI.Card.editName();
-					} else {
-						OC.dialogs.alert(jsondata.data.message, t('contacts', 'Error'));
-						//alert(jsondata.data.message);
-					}
-				});*/
+				Contacts.UI.Card.add(t('contacts', 'Contact')+';'+t('contacts', 'New')+';;;', t('contacts', 'New Contact'), '', true);
+				return false;
 			},
 			savePropertyInternal:function(name, fields, oldchecksum, checksum){
 				// TODO: Add functionality for new fields.
-				console.log('savePropertyInternal: ' + name + ', fields: ' + fields + 'checksum: ' + checksum);
-				console.log('savePropertyInternal: ' + this.data[name]);
+				//console.log('savePropertyInternal: ' + name + ', fields: ' + fields + 'checksum: ' + checksum);
+				//console.log('savePropertyInternal: ' + this.data[name]);
 				var multivalue = ['CATEGORIES'];
 				var params = {};
 				var value = multivalue.indexOf(name) != -1 ? new Array() : undefined;
@@ -583,7 +503,6 @@ Contacts={
 			saveProperty:function(obj){
 				// I couldn't get the selector to filter on 'contacts_property' so I filter by hand here :-/
 				if(!$(obj).hasClass('contacts_property')) {
-					console.log('Filtering out object.' + obj);
 					return false;
 				}
 				if($(obj).hasClass('nonempty') && $(obj).val().trim() == '') {
@@ -594,11 +513,10 @@ Contacts={
 				Contacts.UI.loading(container, true);
 				var checksum = container.data('checksum');
 				var name = container.data('element');
-				console.log('saveProperty: ' + name);
 				var fields = container.find('input.contacts_property,select.contacts_property').serializeArray();
 				var q = container.find('input.contacts_property,select.contacts_property,textarea.contacts_property').serialize();
 				if(q == '' || q == undefined) {
-					console.log('Couldn\'t serialize elements.');
+					OC.dialogs.alert(t('contacts', 'Couldn\'t serialize elements.'), t('contacts', 'Error'));
 					Contacts.UI.loading(container, false);
 					return false;
 				}
@@ -607,7 +525,7 @@ Contacts={
 					q = q + '&checksum=' + checksum;
 					console.log('Saving: ' + q);
 					$(obj).attr('disabled', 'disabled');
-					$.post('ajax/saveproperty.php',q,function(jsondata){
+					$.post(OC.filePath('contacts', 'ajax', 'saveproperty.php'),q,function(jsondata){
 						if(jsondata.status == 'success'){
 							container.data('checksum', jsondata.data.checksum);
 							Contacts.UI.Card.savePropertyInternal(name, fields, checksum, jsondata.data.checksum);
@@ -625,7 +543,7 @@ Contacts={
 				} else { // add
 					console.log('Adding: ' + q);
 					$(obj).attr('disabled', 'disabled');
-					$.post('ajax/addproperty.php',q,function(jsondata){
+					$.post(OC.filePath('contacts', 'ajax', 'addproperty.php'),q,function(jsondata){
 						if(jsondata.status == 'success'){
 							container.data('checksum', jsondata.data.checksum);
 							// TODO: savePropertyInternal doesn't know about new fields
@@ -644,8 +562,7 @@ Contacts={
 				}
 			},
 			addProperty:function(type){
-				//var type = $(obj).data('type');
-				console.log('addProperty:' + type);
+				//console.log('addProperty:' + type);
 				switch (type) {
 					case 'PHOTO':
 						this.loadPhoto(true);
@@ -663,21 +580,21 @@ Contacts={
 							$('#emails').show();
 						}
 						Contacts.UI.Card.addMail();
-						//Contacts.UI.showHideContactInfo();
+						Contacts.UI.loadListHandlers();
 						break;
 					case 'TEL':
 						if($('#phonelist>li').length == 1) {
 							$('#phones').show();
 						}
 						Contacts.UI.Card.addPhone();
-						//Contacts.UI.showHideContactInfo();
+						Contacts.UI.loadListHandlers();
 						break;
 					case 'ADR':
 						if($('#addressdisplay>dl').length == 1) {
 							$('#addresses').show();
 						}
 						Contacts.UI.Card.editAddress('new', true);
-						//Contacts.UI.showHideContactInfo();
+						Contacts.UI.loadListHandlers();
 						break;
 					case 'NICKNAME':
 					case 'ORG':
@@ -690,29 +607,26 @@ Contacts={
 				}
 			},
 			deleteProperty:function(obj, type){
-				//console.log('deleteProperty, id: ' + this.id);
 				Contacts.UI.loading(obj, true);
 				var checksum = Contacts.UI.checksumFor(obj);
-				if(checksum != undefined) {
-					$.getJSON('ajax/deleteproperty.php',{'id': this.id, 'checksum': checksum },function(jsondata){
+				//console.log('deleteProperty, id: ' + this.id + ', checksum: ' + checksum);
+				if(checksum) {
+					$.getJSON(OC.filePath('contacts', 'ajax', 'deleteproperty.php'),{'id': this.id, 'checksum': checksum },function(jsondata){
 						if(jsondata.status == 'success'){
 							if(type == 'list') {
 								Contacts.UI.propertyContainerFor(obj).remove();
-								//Contacts.UI.showHideContactInfo();
-								//Contacts.UI.checkListFor(obj);
 							} else if(type == 'single') {
 								var proptype = Contacts.UI.propertyTypeFor(obj);
-								console.log('deleteProperty, hiding: ' + proptype);
+								Contacts.UI.Card.data[proptype] = null;
 								var othertypes = ['NOTE', 'PHOTO'];
 								if(othertypes.indexOf(proptype) != -1) {
-									console.log('NOTE or PHOTO');
-									Contacts.UI.propertyContainerFor(obj).hide();
 									Contacts.UI.propertyContainerFor(obj).data('checksum', '');
 									if(proptype == 'PHOTO') {
-										console.log('Delete PHOTO');
 										Contacts.UI.Contacts.refreshThumbnail(Contacts.UI.Card.id);
+										Contacts.UI.Card.loadPhoto(true);
 									} else if(proptype == 'NOTE') {
 										$('#note').find('textarea').val('');
+										Contacts.UI.propertyContainerFor(obj).hide();
 									}
 								} else {
 									$('dl dt[data-element="'+proptype+'"],dd[data-element="'+proptype+'"]').hide();
@@ -734,11 +648,8 @@ Contacts={
 				} else { // Property hasn't been saved so there's nothing to delete.
 					if(type == 'list') {
 						Contacts.UI.propertyContainerFor(obj).remove();
-						//Contacts.UI.showHideContactInfo();
-						//Contacts.UI.checkListFor(obj);
 					} else if(type == 'single') {
 						var proptype = Contacts.UI.propertyTypeFor(obj);
-						console.log('deleteProperty, hiding: ' + proptype);
 						$('dl dt[data-element="'+proptype+'"],dd[data-element="'+proptype+'"]').hide();
 						$('#contacts_propertymenu a[data-type="'+proptype+'"]').parent().show();
 						Contacts.UI.loading(obj, false);
@@ -752,7 +663,7 @@ Contacts={
 				/* Initialize the name edit dialog */
 				if($('#edit_name_dialog').dialog('isOpen') == true){
 					$('#edit_name_dialog').dialog('moveToTop');
-				}else{ // TODO: If id=='' call addcontact.php (or whatever name) instead and reload view with id.
+				}else{
 					$('#dialog_holder').load(OC.filePath('contacts', 'ajax', 'editname.php')+'?id='+this.id, function(jsondata){
 						if(jsondata.status != 'error'){
 							$('#edit_name_dialog' ).dialog({
@@ -767,13 +678,13 @@ Contacts={
 									},
 									'Cancel':function() { $(this).dialog('destroy').remove(); }
 								},
-								close : function(event, ui) {
+								close: function(event, ui) {
 									$(this).dialog('destroy').remove();
 									//return event;
-								}/*,
-								open : function(event, ui) {
+								},
+								open: function(event, ui) {
 									// load 'N' property - maybe :-P
-								}*/
+								}
 							});
 						} else {
 							OC.dialogs.alert(jsondata.data.message, t('contacts', 'Error'));
@@ -782,7 +693,7 @@ Contacts={
 				}
 			},
 			saveName:function(dlg){
-				console.log('saveName, id: ' + this.id);
+				//console.log('saveName, id: ' + this.id);
 				var n = new Array($(dlg).find('#fam').val().strip_tags(),$(dlg).find('#giv').val().strip_tags(),$(dlg).find('#add').val().strip_tags(),$(dlg).find('#pre').val().strip_tags(),$(dlg).find('#suf').val().strip_tags());
 				this.famname = n[0];
 				this.givname = n[1];
@@ -805,7 +716,6 @@ Contacts={
 				var tmp = [this.fullname, this.givname + ' ' + this.famname, this.famname + ' ' + this.givname, this.famname + ', ' + this.givname];
 				var names = new Array();
 				for(var name in tmp) {
-					console.log('idx: ' + names.indexOf(tmp[name]));
 					if(names.indexOf(tmp[name]) == -1) {
 						names.push(tmp[name]);
 					}
@@ -868,11 +778,9 @@ Contacts={
 					$('#addresses').show();
 					$('#contact_communication').show();
 				}
-				Contacts.UI.loadListHandlers();
 				return false;
 			},
 			editAddress:function(obj, isnew){
-				console.log('editAddress');
 				var container = undefined;
 				var q = q = '?id=' + this.id;
 				if(obj === 'new') {
@@ -880,7 +788,6 @@ Contacts={
 					$('#addressdisplay dl').first().clone().insertAfter($('#addressdisplay dl').last()).show();
 					container = $('#addressdisplay dl').last();
 					container.removeClass('template').addClass('propertycontainer');
-					Contacts.UI.loadListHandlers();
 				} else {
 					q = q + '&checksum='+Contacts.UI.checksumFor(obj);
 				}
@@ -977,9 +884,9 @@ Contacts={
 												},
 												success: function( data ) {
 													response( $.map( data.geonames, function( item ) {
-														for(var key in item) {
-															console.log(key + ': ' + item[key]);
-														}
+														//for(var key in item) {
+														//	console.log(key + ': ' + item[key]);
+														//}
 														return {
 															label: item.name,
 															value: item.name
@@ -1051,7 +958,6 @@ Contacts={
 					OC.dialogs.alert(t('contacts','No files selected for upload.'), t('contacts', 'Error'));
 					return;
 				}
-				//var file = filelist.item(0);
 				var file = filelist[0];
 				var target = $('#file_upload_target');
 				var form = $('#file_upload_form');
@@ -1072,29 +978,91 @@ Contacts={
 					form.submit();
 				}
 			},
-			loadPhoto:function(force){
-				//if(this.data.PHOTO||force==true) {
-					$.getJSON('ajax/loadphoto.php',{'id':this.id},function(jsondata){
-						if(jsondata.status == 'success'){
-							//alert(jsondata.data.page);
-							$('#file_upload_form').data('checksum', jsondata.data.checksum);
-							$('#contacts_details_photo_wrapper').html(jsondata.data.page);
-						}
-						else{
-							OC.dialogs.alert(jsondata.data.message, t('contacts', 'Error'));
-						}
+			loadPhotoHandlers:function(){
+				$('#phototools li a').tipsy('hide');
+				$('#phototools li a').tipsy();
+				$('#phototools li a').click(function() {
+					$(this).tipsy('hide');
+				});
+				$('#contacts_details_photo_wrapper').hover(
+					function () {
+						$('#phototools').slideDown(200);
+					},
+					function () {
+						$('#phototools').slideUp(200);
+					}
+				);
+				$('#phototools').hover(
+					function () {
+						$(this).removeClass('transparent');
+					},
+					function () {
+						$(this).addClass('transparent');
+					}
+				);
+				if(this.data.PHOTO) {
+					$('#phototools .delete').click(function() {
+						$(this).tipsy('hide');
+						Contacts.UI.Card.deleteProperty($('#contacts_details_photo'), 'single');
+						$(this).hide();
 					});
-					$('#file_upload_form').show();
-					$('#contacts_propertymenu a[data-type="PHOTO"]').parent().hide();
-				/*} else {
-					$('#contacts_details_photo_wrapper').empty();
-					$('#file_upload_form').hide();
-					$('#contacts_propertymenu a[data-type="PHOTO"]').parent().show();
-				}*/
+					$('#phototools .edit').click(function() {
+						$(this).tipsy('hide');
+						Contacts.UI.Card.editCurrentPhoto();
+					});
+				} else {
+					$('#phototools .delete').hide();
+					$('#phototools .edit').hide();
+				}
+				$('#phototools .upload').click(function() {
+					$('#file_upload_start').trigger('click');
+				});
+				$('#phototools .cloud').click(function() {
+					OC.dialogs.filepicker(t('contacts', 'Select photo'), Contacts.UI.Card.cloudPhotoSelected, false, 'image', true);
+				});
+			},
+			cloudPhotoSelected:function(path){
+				$.getJSON(OC.filePath('contacts', 'ajax', 'oc_photo.php'),{'path':path,'id':Contacts.UI.Card.id},function(jsondata){
+					if(jsondata.status == 'success'){
+						//alert(jsondata.data.page);
+						Contacts.UI.Card.editPhoto(jsondata.data.id, jsondata.data.tmp)
+						$('#edit_photo_dialog_img').html(jsondata.data.page);
+					}
+					else{
+						OC.dialogs.alert(jsondata.data.message, t('contacts', 'Error'));
+					}
+				});
+			},
+			loadPhoto:function(refresh){
+				$('#phototools li a').tipsy('hide');
+				$.getJSON(OC.filePath('contacts', 'ajax', 'loadphoto.php'),{'id':this.id, 'refresh': refresh},function(jsondata){
+					if(jsondata.status == 'success'){
+						$('#contacts_details_photo_wrapper').data('checksum', jsondata.data.checksum);
+						$('#contacts_details_photo_wrapper').html(jsondata.data.page);
+						Contacts.UI.Card.loadPhotoHandlers();
+					}
+					else{
+						OC.dialogs.alert(jsondata.data.message, t('contacts', 'Error'));
+					}
+				});
+				$('#file_upload_form').show();
+				$('#contacts_propertymenu a[data-type="PHOTO"]').parent().hide();
+			},
+			editCurrentPhoto:function(){
+				$.getJSON(OC.filePath('contacts', 'ajax', 'currentphoto.php'),{'id':this.id},function(jsondata){
+					if(jsondata.status == 'success'){
+						//alert(jsondata.data.page);
+						Contacts.UI.Card.editPhoto(jsondata.data.id, jsondata.data.tmp)
+						$('#edit_photo_dialog_img').html(jsondata.data.page);
+					}
+					else{
+						OC.dialogs.alert(jsondata.data.message, t('contacts', 'Error'));
+					}
+				});
 			},
 			editPhoto:function(id, tmp_path){
 				//alert('editPhoto: ' + tmp_path);
-				$.getJSON('ajax/cropphoto.php',{'tmp_path':tmp_path,'id':this.id},function(jsondata){
+				$.getJSON(OC.filePath('contacts', 'ajax', 'cropphoto.php'),{'tmp_path':tmp_path,'id':this.id},function(jsondata){
 					if(jsondata.status == 'success'){
 						//alert(jsondata.data.page);
 						$('#edit_photo_dialog_img').html(jsondata.data.page);
@@ -1118,6 +1086,8 @@ Contacts={
 					if(response != undefined && response.status == 'success'){
 						// load cropped photo.
 						$('#contacts_details_photo_wrapper').html(response.data.page);
+						Contacts.UI.Card.data.PHOTO = true;
+						Contacts.UI.Card.loadPhotoHandlers();
 					}else{
 						OC.dialogs.alert(response.data.message, t('contacts', 'Error'));
 					}
@@ -1127,9 +1097,9 @@ Contacts={
 			addMail:function() {
 				//alert('addMail');
 				$('#emaillist li.template:first-child').clone().appendTo($('#emaillist')).show();
+				$('#emaillist li.template:last-child').find('select').addClass('contacts_property');
 				$('#emaillist li.template:last-child').removeClass('template').addClass('propertycontainer');
 				$('#emaillist li:last-child').find('input[type="email"]').focus();
-				Contacts.UI.loadListHandlers();
 				return false;
 			},
 			loadMails:function() {
@@ -1144,6 +1114,16 @@ Contacts={
 						if(param.toUpperCase() == 'PREF') {
 							$('#emaillist li:last-child').find('input[type="checkbox"]').attr('checked', 'checked')
 						}
+						else if(param.toUpperCase() == 'TYPE') {
+							for(etype in this.data.EMAIL[mail]['parameters'][param]) {
+								var et = this.data.EMAIL[mail]['parameters'][param][etype];
+								$('#emaillist li:last-child').find('select option').each(function(){
+									if($.inArray($(this).val().toUpperCase(), et.toUpperCase().split(',')) > -1) {
+										$(this).attr('selected', 'selected');
+									}
+								});
+							}
+						}
 					}
 				}
 				if($('#emaillist li').length > 1) {
@@ -1152,7 +1132,6 @@ Contacts={
 				}
 
 				$('#emaillist li:last-child').find('input[type="text"]').focus();
-				Contacts.UI.loadListHandlers();
 				return false;
 			},
 			addPhone:function() {
@@ -1160,7 +1139,6 @@ Contacts={
 				$('#phonelist li.template:last-child').find('select').addClass('contacts_property');
 				$('#phonelist li.template:last-child').removeClass('template').addClass('propertycontainer');
 				$('#phonelist li:last-child').find('input[type="text"]').focus();
-				Contacts.UI.loadListHandlers();
 				$('#phonelist li:last-child').find('select').multiselect({
 														noneSelectedText: t('contacts', 'Select type'),
 														header: false,
@@ -1186,7 +1164,8 @@ Contacts={
 							for(ptype in this.data.TEL[phone]['parameters'][param]) {
 								var pt = this.data.TEL[phone]['parameters'][param][ptype];
 								$('#phonelist li:last-child').find('select option').each(function(){
-									if ($(this).val().toUpperCase() == pt.toUpperCase()) {
+									//if ($(this).val().toUpperCase() == pt.toUpperCase()) {
+									if ($.inArray($(this).val().toUpperCase(), pt.toUpperCase().split(',')) > -1) {
 										$(this).attr('selected', 'selected');
 									}
 								});
@@ -1208,6 +1187,8 @@ Contacts={
 			},
 		},
 		Addressbooks:{
+			droptarget:undefined,
+			droptext:t('contacts', 'Drop a VCF file to import contacts.'),
 			overview:function(){
 				if($('#chooseaddressbook_dialog').dialog('isOpen') == true){
 					$('#chooseaddressbook_dialog').dialog('moveToTop');
@@ -1225,6 +1206,7 @@ Contacts={
 						}
 					});
 				}
+				return false;
 			},
 			activation:function(checkbox, bookid)
 			{
@@ -1240,14 +1222,13 @@ Contacts={
 				var tr = $(document.createElement('tr'))
 					.load(OC.filePath('contacts', 'ajax', 'addbook.php'));
 				$(object).closest('tr').after(tr).hide();
-				/* TODO: Shouldn't there be some kinda error checking here? */
 			},
 			editAddressbook:function(object, bookid){
 				var tr = $(document.createElement('tr'))
 					.load(OC.filePath('contacts', 'ajax', 'editaddressbook.php') + "?bookid="+bookid);
 				$(object).closest('tr').after(tr).hide();
 			},
-			deleteAddressbook:function(bookid){
+			deleteAddressbook:function(obj, bookid){
 				var check = confirm("Do you really want to delete this address book?");
 				if(check == false){
 					return false;
@@ -1255,9 +1236,10 @@ Contacts={
 					$.post(OC.filePath('contacts', 'ajax', 'deletebook.php'), { id: bookid},
 					  function(jsondata) {
 						if (jsondata.status == 'success'){
-							$('#chooseaddressbook_dialog').dialog('destroy').remove();
+							$(obj).closest('tr').remove();
+							//$('#chooseaddressbook_dialog').dialog('destroy').remove();
 							Contacts.UI.Contacts.update();
-							Contacts.UI.Addressbooks.overview();
+							//Contacts.UI.Addressbooks.overview();
 						} else {
 							OC.dialogs.alert(jsondata.data.message, t('contacts', 'Error'));
 							//alert('Error: ' + data.message);
@@ -1265,8 +1247,128 @@ Contacts={
 					  });
 				}
 			},
-			doImport:function(){
-				Contacts.UI.notImplemented();
+			loadImportHandlers:function() {
+				$('#import_upload_start').change(function(){
+					Contacts.UI.Addressbooks.uploadImport(this.files);
+				});
+				$('#importaddressbook_dialog').find('.upload').click(function() {
+					Contacts.UI.Addressbooks.droptarget.html(t('contacts', 'Uploading...'));
+					Contacts.UI.loading(Contacts.UI.Addressbooks.droptarget, true);
+					$('#import_upload_start').trigger('click');
+				});
+				$('#importaddressbook_dialog').find('.upload').tipsy();
+				this.droptarget = $('#import_drop_target');
+				$(this.droptarget).bind('dragover',function(event){
+					$(event.target).addClass('droppable');
+					event.stopPropagation();
+					event.preventDefault();  
+				});
+				$(this.droptarget).bind('dragleave',function(event){
+					$(event.target).removeClass('droppable');
+				});
+				$(this.droptarget).bind('drop',function(event){
+					event.stopPropagation();
+					event.preventDefault();
+					$(event.target).removeClass('droppable');
+					$(event.target).html(t('contacts', 'Uploading...'));
+					Contacts.UI.loading(event.target, true);
+					$.fileUpload(event.originalEvent.dataTransfer.files);
+				});
+
+				$.fileUpload = function(files){
+					var file = files[0];
+					if(file.size > $('#max_upload').val()){
+						OC.dialogs.alert(t('contacts','The file you are trying to upload exceed the maximum size for file uploads on this server.'), t('contacts','Upload too large'));
+						$(Contacts.UI.Addressbooks.droptarget).html(Contacts.UI.Addressbooks.droptext);
+						Contacts.UI.loading(Contacts.UI.Addressbooks.droptarget, false);
+						return;
+					}
+					if(file.type.indexOf('text') != 0) {
+						OC.dialogs.alert(t('contacts','You have dropped a file type that cannot be imported: ') + file.type, t('contacts','Wrong file type'));
+						$(Contacts.UI.Addressbooks.droptarget).html(Contacts.UI.Addressbooks.droptext);
+						Contacts.UI.loading(Contacts.UI.Addressbooks.droptarget, false);
+						return;
+					}
+					var xhr = new XMLHttpRequest();
+
+					if (!xhr.upload) {
+						OC.dialogs.alert(t('contacts', 'Your browser doesn\'t support AJAX upload. Please upload the contacts file to ownCloud and import that way.'), t('contacts', 'Error'))
+					}
+					fileUpload = xhr.upload,
+					xhr.onreadystatechange = function() {
+						if (xhr.readyState == 4){
+							response = $.parseJSON(xhr.responseText);
+							if(response.status == 'success') {
+								if(xhr.status == 200) {
+									Contacts.UI.Addressbooks.doImport(response.data.path, response.data.file);
+								} else {
+									$(Contacts.UI.Addressbooks.droptarget).html(Contacts.UI.Addressbooks.droptext);
+									Contacts.UI.loading(Contacts.UI.Addressbooks.droptarget, false);
+									OC.dialogs.alert(xhr.status + ': ' + xhr.responseText, t('contacts', 'Error'));
+								}
+							} else {
+								OC.dialogs.alert(response.data.message, t('contacts', 'Error'));
+							}
+						}
+					};
+					xhr.open('POST', OC.filePath('contacts', 'ajax', 'uploadimport.php') + '?file='+encodeURIComponent(file.name), true);
+					xhr.setRequestHeader('Cache-Control', 'no-cache');
+					xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
+					xhr.setRequestHeader('X_FILE_NAME', encodeURIComponent(file.name));
+					xhr.setRequestHeader('X-File-Size', file.size);
+					xhr.setRequestHeader('Content-Type', file.type);
+					xhr.send(file);
+				}
+			},
+			uploadImport:function(filelist) {
+				if(!filelist) {
+					OC.dialogs.alert(t('contacts','No files selected for upload.'), t('contacts', 'Error'));
+					return;
+				}
+				//var file = filelist.item(0);
+				var file = filelist[0];
+				var target = $('#import_upload_target');
+				var form = $('#import_upload_form');
+				var totalSize=0;
+				if(file.size > $('#max_upload').val()){
+					OC.dialogs.alert(t('contacts','The file you are trying to upload exceed the maximum size for file uploads on this server.'), t('contacts', 'Error'));
+					return;
+				} else {
+					target.load(function(){
+						var response=jQuery.parseJSON(target.contents().text());
+						if(response != undefined && response.status == 'success'){
+							Contacts.UI.Addressbooks.doImport(response.data.path, response.data.file);
+						}else{
+							OC.dialogs.alert(response.data.message, t('contacts', 'Error'));
+						}
+					});
+					form.submit();
+				}
+			},
+			importAddressbook:function(object){
+				var tr = $(document.createElement('tr'))
+					.load(OC.filePath('contacts', 'ajax', 'importaddressbook.php'));
+				$(object).closest('tr').after(tr).hide();
+			},
+			doImport:function(path, file){
+				$(Contacts.UI.Addressbooks.droptarget).html(t('contacts', 'Importing...'));
+				Contacts.UI.loading(Contacts.UI.Addressbooks.droptarget, true);
+				var id = $('#importaddressbook_dialog').find('#book').val();
+				$.post(OC.filePath('contacts', '', 'import.php'), { id: id, path: path, file: file, fstype: 'OC_FilesystemView' },
+					function(jsondata){
+						if(jsondata.status == 'success'){
+							Contacts.UI.Addressbooks.droptarget.html(t('contacts', 'Import done. Success/Failure: ')+jsondata.data.imported+'/'+jsondata.data.failed);
+							$('#chooseaddressbook_dialog').find('#close_button').val(t('contacts', 'OK'));
+							Contacts.UI.Contacts.update();
+							setTimeout(
+									function() {
+										$(Contacts.UI.Addressbooks.droptarget).html(Contacts.UI.Addressbooks.droptext);
+									}, 5000);
+						} else {
+							OC.dialogs.alert(jsondata.data.message, t('contacts', 'Error'));
+						}
+				});
+				Contacts.UI.loading(Contacts.UI.Addressbooks.droptarget, false);
 			},
 			submit:function(button, bookid){
 				var displayname = $("#displayname_"+bookid).val().trim();
@@ -1291,7 +1393,7 @@ Contacts={
 						} else {
 							OC.dialogs.alert(jsondata.data.message, t('contacts', 'Error'));
 						}
-					});
+				});
 			},
 			cancel:function(button, bookid){
 				$(button).closest('tr').prev().show().next().remove();
@@ -1300,15 +1402,13 @@ Contacts={
 		Contacts:{
 			// Reload the contacts list.
 			update:function(){
-				console.log('Contacts.update, start');
-				$.getJSON('ajax/contacts.php',{},function(jsondata){
+				$.getJSON(OC.filePath('contacts', 'ajax', 'contacts.php'),{},function(jsondata){
 					if(jsondata.status == 'success'){
 						$('#contacts').html(jsondata.data.page);
 						Contacts.UI.Card.update();
 					}
 					else{
 						OC.dialogs.alert(jsondata.data.message, t('contacts', 'Error'));
-						//alert(jsondata.data.message);
 					}
 				});
 				setTimeout(Contacts.UI.Contacts.lazyupdate, 500);
@@ -1317,12 +1417,12 @@ Contacts={
 			lazyupdate:function(){
 				$('#contacts li').live('inview', function(){
 					if (!$(this).find('a').attr('style')) {
-						$(this).find('a').css('background','url(thumbnail.php?id='+$(this).data('id')+') no-repeat');
+						$(this).find('a').css('background','url('+OC.filePath('contacts', '', 'thumbnail.php')+'?id='+$(this).data('id')+') no-repeat');
 					}
 				});
 			},
 			refreshThumbnail:function(id){
-				$('#contacts [data-id="'+id+'"]').find('a').css('background','url(thumbnail.php?id='+id+'&refresh=1'+Math.random()+') no-repeat');
+				$('#contacts [data-id="'+id+'"]').find('a').css('background','url('+OC.filePath('contacts', '', 'thumbnail.php')+'?id='+id+'&refresh=1'+Math.random()+') no-repeat');
 			}
 		}
 	}
@@ -1333,26 +1433,41 @@ $(document).ready(function(){
 	OCCategories.changed = Contacts.UI.Card.categoriesChanged;
 	OCCategories.app = 'contacts';
 
-	$('#chooseaddressbook').click(function(){
-		Contacts.UI.Addressbooks.overview();
+	$('#notification').click(function(){
+		$('#notification').fadeOut();
+	});
+	
+	$('#chooseaddressbook').click(Contacts.UI.Addressbooks.overview);
+	$('#chooseaddressbook').keydown(Contacts.UI.Addressbooks.overview);
+
+	$('#contacts_newcontact').click(Contacts.UI.Card.editNew);
+	$('#contacts_newcontact').keydown(Contacts.UI.Card.editNew);
+	
+	$('#contacts_deletecard').click( function() { Contacts.UI.Card.doDelete();return false;} );
+	$('#contacts_deletecard').keydown( function(event) { 
+		if(event.which == 13) {
+			Contacts.UI.Card.doDelete();
+		}
 		return false;
 	});
 
-	$('#contacts_newcontact').click(function(){
-		Contacts.UI.Card.editNew();
+	$('#contacts_downloadcard').click( function() { Contacts.UI.Card.doExport();return false;} );
+	$('#contacts_downloadcard').keydown( function(event) { 
+		if(event.which == 13) {
+			Contacts.UI.Card.doExport();
+		}
+		return false;
 	});
-	
-	/**
-	 * Load the details view for a contact.
-	 */
-	$('#leftcontent li').live('click',function(){
+
+	// Load a contact.
+	$('#leftcontent li').click(function(){
 		var id = $(this).data('id');
 		$(this).addClass('active');
 		var oldid = $('#rightcontent').data('id');
 		if(oldid != 0){
 			$('#leftcontent li[data-id="'+oldid+'"]').removeClass('active');
 		}
-		$.getJSON('ajax/contactdetails.php',{'id':id},function(jsondata){
+		$.getJSON(OC.filePath('contacts', 'ajax', 'contactdetails.php'),{'id':id},function(jsondata){
 			if(jsondata.status == 'success'){
 				Contacts.UI.Card.loadContact(jsondata.data);
 			}
@@ -1364,10 +1479,6 @@ $(document).ready(function(){
 		return false;
 	});
 
-	$('#contacts_deletecard').live('click',function(){
-		Contacts.UI.Card.doDelete();
-	});
-
 	$('#contacts li').bind('inview', function(event, isInView, visiblePartX, visiblePartY) {
 		if (isInView) { //NOTE: I've kept all conditions for future reference ;-)
 			// element is now visible in the viewport
@@ -1379,7 +1490,7 @@ $(document).ready(function(){
 				// whole part of element is visible
 				if (!$(this).find('a').attr('style')) {
 					//alert($(this).data('id') + ' has background: ' + $(this).attr('style'));
-					$(this).find('a').css('background','url(thumbnail.php?id='+$(this).data('id')+') no-repeat');
+					$(this).find('a').css('background','url('+OC.filePath('contacts', '', 'thumbnail.php')+'?id='+$(this).data('id')+') no-repeat');
 				}/* else {
 					alert($(this).data('id') + ' has style ' + $(this).attr('style').match('url'));
 				}*/
@@ -1389,13 +1500,6 @@ $(document).ready(function(){
 		}
 	});
 	
-	$('.button').tipsy();
-	// Triggers invisible file input
-	$('#contacts_details_photo').live('click', function() {
-		$('#file_upload_start').trigger('click');
-		return false;
-	});
-	
 	// NOTE: For some reason the selector doesn't work when I select by '.contacts_property' too...
 	// I do the filtering in the event handler instead.
 	//$('input[type="text"],input[type="checkbox"],input[type="email"],input[type="tel"],input[type="date"], select').live('change', function(){
@@ -1403,6 +1507,14 @@ $(document).ready(function(){
 		Contacts.UI.Card.saveProperty(this);
 	});
 
+	$('#fn').blur(function(){
+		if($('#fn').val() == '') {
+			OC.dialogs.alert(t('contacts','The name field cannot be empty. Please enter a name for this contact.'), t('contacts','Name is empty'), function() { $('#fn').focus(); });
+			$('#fn').focus();
+			return false;
+		}
+	});
+	
 	// Name has changed. Update it and reorder.
 	$('#fn').live('change',function(){
 		var name = $('#fn').val();
@@ -1426,26 +1538,23 @@ $(document).ready(function(){
 	 * Profile picture upload handling
 	 */
 	// New profile picture selected
-	$('#file_upload_start').live('change',function(){
+	$('#file_upload_start').change(function(){
 		Contacts.UI.Card.uploadPhoto(this.files);
 	});
-	$('#contacts_details_photo').bind('dragover',function(event){
-		console.log('dragover');
-		$(event.target).css('background-color','red');
+	$('#contacts_details_photo_wrapper').bind('dragover',function(event){
+		$(event.target).addClass('droppable');
 		event.stopPropagation();
 		event.preventDefault();  
 	});
-	$('#contacts_details_photo').bind('dragleave',function(event){
-		console.log('dragleave');
-		$(event.target).css('background-color','white');
+	$('#contacts_details_photo_wrapper').bind('dragleave',function(event){
+		$(event.target).removeClass('droppable');
 		//event.stopPropagation();
 		//event.preventDefault();  
 	});
-	$('#contacts_details_photo').bind('drop',function(event){
+	$('#contacts_details_photo_wrapper').bind('drop',function(event){
 		event.stopPropagation();
 		event.preventDefault();
-		console.log('drop');
-		$(event.target).css('background-color','white')
+		$(event.target).removeClass('droppable');
 		$.fileUpload(event.originalEvent.dataTransfer.files);
 	});
 
@@ -1454,7 +1563,6 @@ $(document).ready(function(){
 	 */
 	$.fileUpload = function(files){
 		var file = files[0];
-		console.log('size: '+file.size);
 		if(file.size > $('#max_upload').val()){
 			OC.dialogs.alert(t('contacts','The file you are trying to upload exceed the maximum size for file uploads on this server.'), t('contacts','Upload too large'));
 			return;
@@ -1491,14 +1599,14 @@ $(document).ready(function(){
 			if (e.lengthComputable){
 				var _progress = Math.round((e.loaded * 100) / e.total);
 				if (_progress != 100){
-					$('#contacts_details_photo_progress').text(_progress + '%');
-					$('#contacts_details_photo_progress').val(_progress);
+					//$('#contacts_details_photo_progress').text(_progress + '%');
+					//$('#contacts_details_photo_progress').val(_progress);
 				}
 			}
 		};
 		// Start loading indicator.
 		//$('#contacts_details_photo_progress').show()();
-		xhr.open("POST", 'ajax/uploadphoto.php?id='+Contacts.UI.Card.id+'&imagefile='+encodeURIComponent(file.name), true);
+		xhr.open('POST', OC.filePath('contacts', 'ajax', 'uploadphoto.php')+'?id='+Contacts.UI.Card.id+'&imagefile='+encodeURIComponent(file.name), true);
 		xhr.setRequestHeader('Cache-Control', 'no-cache');
 		xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
 		xhr.setRequestHeader('X_FILE_NAME', encodeURIComponent(file.name));
@@ -1508,23 +1616,27 @@ $(document).ready(function(){
 		xhr.send(file);
 	}
 
-	$('body').live('click',function(e){
+	$('body').click(function(e){
 		if(!$(e.target).is('#contacts_propertymenu_button')) {
 			$('#contacts_propertymenu').hide();
 		}
 	});
-	$('#contacts_propertymenu_button').live('click',function(){
+	function propertyMenu(){
 		var menu = $('#contacts_propertymenu');
 		if(menu.is(':hidden')) {
 			menu.show();
-			menu.find('ul').focus();
+			menu.find('li').first().focus();
 		} else {
 			menu.hide();
 		}
-	});
-	$('#contacts_propertymenu a').live('click',function(){
+	}
+	$('#contacts_propertymenu_button').click(propertyMenu);
+	$('#contacts_propertymenu_button').keydown(propertyMenu);
+	function propertyMenuItem(){
 		var type = $(this).data('type');
 		Contacts.UI.Card.addProperty(type);
 		$('#contacts_propertymenu').hide();
-	});
+	}
+	$('#contacts_propertymenu a').click(propertyMenuItem);
+	$('#contacts_propertymenu a').keydown(propertyMenuItem);
 });
diff --git a/apps/contacts/js/jquery.combobox.js b/apps/contacts/js/jquery.combobox.js
index f46d7c14c183b7eb0bfc9efcf3bd16d795120cbc..f12d1d7dd20ef3934bd054950f79e7dee94f8615 100644
--- a/apps/contacts/js/jquery.combobox.js
+++ b/apps/contacts/js/jquery.combobox.js
@@ -4,8 +4,13 @@
 
 (function( $ ) {
 	$.widget('ui.combobox', {
+		options: { 
+			id: null,
+			name: null,
+			showButton: false,
+			editable: true
+		},
 		_create: function() {
-			//console.log('_create: ' + this.options['id']);
 			var self = this,
 				select = this.element.hide(),
 				selected = select.children(':selected'),
@@ -53,13 +58,13 @@
 									return false;
 								}
 							});
-							/*if ( !valid ) {
+							if ( !self.options['editable'] && !valid ) {
 								// remove invalid value, as it didn't match anything
 								$( this ).val( "" );
 								select.val( "" );
 								input.data( "autocomplete" ).term = "";
 								return false;
-							}*/
+							}
 						}
 					}
 				})
@@ -71,40 +76,41 @@
 					.append( "<a>" + item.label + "</a>" )
 					.appendTo( ul );
 			};
-
-			/*this.button = $( "<button type='button'>&nbsp;</button>" )
-				.attr( "tabIndex", -1 )
-				.attr( "title", "Show All Items" )
-				.insertAfter( input )
-				.addClass('svg')
-				.addClass('action')
-				.addClass('combo-button')
-				.click(function() {
-					// close if already visible
-					if ( input.autocomplete( "widget" ).is( ":visible" ) ) {
-						input.autocomplete( "close" );
-						return;
-					}
-
-					// work around a bug (likely same cause as #5265)
-					$( this ).blur();
-
-					// pass empty string as value to search for, displaying all results
-					input.autocomplete( "search", "" );
-					input.focus();
-				});*/
 			$.each(this.options, function(key, value) {
 				self._setOption(key, value);
 			});
+
+			if(this.options['showButton']) {
+				this.button = $( "<button type='button'>&nbsp;</button>" )
+					.attr( "tabIndex", -1 )
+					.attr( "title", "Show All Items" )
+					.insertAfter( input )
+					.addClass('svg')
+					.addClass('action')
+					.addClass('combo-button')
+					.click(function() {
+						// close if already visible
+						if ( input.autocomplete( "widget" ).is( ":visible" ) ) {
+							input.autocomplete( "close" );
+							return;
+						}
+
+						// work around a bug (likely same cause as #5265)
+						$( this ).blur();
+
+						// pass empty string as value to search for, displaying all results
+						input.autocomplete( "search", "" );
+						input.focus();
+					});
+			}
 		},
 		destroy: function() {
 			this.input.remove();
-			this.button.remove();
+			//this.button.remove();
 			this.element.show();
 			$.Widget.prototype.destroy.call( this );
 		},
 		value: function(val) {
-			console.log('combobox.value: ' + val);
 			if(val != undefined) {
 				this.input.val(val);
 			} else {
@@ -113,35 +119,35 @@
 		},
 		_setOption: function( key, value ) {
 			switch( key ) {
-				case "id":
+				case 'id':
 					this.options['id'] = value;
 					this.input.attr('id', value);
 					break;
-				case "name":
+				case 'name':
 					this.options['name'] = value;
 					this.input.attr('name', value);
 					break;
-				case "attributes":
+				case 'attributes':
 					var input = this.input;
 					$.each(this.options['attributes'], function(key, value) {
 						input.attr(key, value);
 					});
 					break;
-				case "classes":
+				case 'classes':
 					var input = this.input;
 					$.each(this.options['classes'], function(key, value) {
 						input.addClass(value);
 					});
 					break;
+				case 'editable':
+				case 'showButton':
+					this.options[key] = value;
+					break;
 			}
 			// In jQuery UI 1.8, you have to manually invoke the _setOption method from the base widget
 			$.Widget.prototype._setOption.apply( this, arguments );
 			// In jQuery UI 1.9 and above, you use the _super method instead
 			//this._super( "_setOption", key, value );
-		},
-		options: { 
-			id: null,
-			name: null
-		},
+		}
 	});
 })( jQuery );
diff --git a/apps/contacts/js/jquery.multi-autocomplete.js b/apps/contacts/js/jquery.multi-autocomplete.js
index e1c5d63dc5f2c73aaace35857ff3e28baeda5768..5516a74b03918b25bede5bd750356104e6b932cd 100644
--- a/apps/contacts/js/jquery.multi-autocomplete.js
+++ b/apps/contacts/js/jquery.multi-autocomplete.js
@@ -31,7 +31,9 @@
 				} else {
 					self.element.val(tmp);
 				}
-				self.element.trigger('change'); // Changes wasn't saved when only using the dropdown.
+				if(self.element.val().trim() != '') {
+					self.element.trigger('change'); // Changes wasn't saved when only using the dropdown.
+				}
 			});
 			this.element.bind( "keydown", function( event ) {
 				if ( event.keyCode === $.ui.keyCode.TAB &&
diff --git a/apps/contacts/l10n/xgettextfiles b/apps/contacts/l10n/xgettextfiles
index e2492431ff8de2d2b153b31af194965b1b816d5e..e291074fba90fe9672a4d2397772dad65fc08869 100644
--- a/apps/contacts/l10n/xgettextfiles
+++ b/apps/contacts/l10n/xgettextfiles
@@ -5,7 +5,7 @@
 ../ajax/createaddressbook.php
 ../ajax/deletebook.php
 ../ajax/deleteproperty.php
-../ajax/getdetails.php
+../ajax/contactdetails.php
 ../ajax/saveproperty.php
 ../ajax/updateaddressbook.php
 ../lib/app.php
diff --git a/apps/contacts/lib/addressbook.php b/apps/contacts/lib/addressbook.php
old mode 100644
new mode 100755
index 9061fa1914042dff24874f31f80f50227d6a6861..78e94762f2e90dd8b54e849683c8b9494b25b30d
--- a/apps/contacts/lib/addressbook.php
+++ b/apps/contacts/lib/addressbook.php
@@ -44,7 +44,7 @@ class OC_Contacts_Addressbook{
 	 * @return array
 	 */
 	public static function all($uid){
-		$stmt = OC_DB::prepare( 'SELECT * FROM *PREFIX*contacts_addressbooks WHERE userid = ? ORDER BY displayname' );
+		$stmt = OCP\DB::prepare( 'SELECT * FROM *PREFIX*contacts_addressbooks WHERE userid = ? ORDER BY displayname' );
 		$result = $stmt->execute(array($uid));
 
 		$addressbooks = array();
@@ -71,7 +71,7 @@ class OC_Contacts_Addressbook{
 	 * @return associative array
 	 */
 	public static function find($id){
-		$stmt = OC_DB::prepare( 'SELECT * FROM *PREFIX*contacts_addressbooks WHERE id = ?' );
+		$stmt = OCP\DB::prepare( 'SELECT * FROM *PREFIX*contacts_addressbooks WHERE id = ?' );
 		$result = $stmt->execute(array($id));
 
 		return $result->fetchRow();
@@ -93,10 +93,10 @@ class OC_Contacts_Addressbook{
 
 		$uri = self::createURI($name, $uris );
 
-		$stmt = OC_DB::prepare( 'INSERT INTO *PREFIX*contacts_addressbooks (userid,displayname,uri,description,ctag) VALUES(?,?,?,?,?)' );
+		$stmt = OCP\DB::prepare( 'INSERT INTO *PREFIX*contacts_addressbooks (userid,displayname,uri,description,ctag) VALUES(?,?,?,?,?)' );
 		$result = $stmt->execute(array($userid,$name,$uri,$description,1));
 
-		return OC_DB::insertid('*PREFIX*contacts_addressbooks');
+		return OCP\DB::insertid('*PREFIX*contacts_addressbooks');
 	}
 
 	/**
@@ -110,10 +110,10 @@ class OC_Contacts_Addressbook{
 	public static function addFromDAVData($principaluri,$uri,$name,$description){
 		$userid = self::extractUserID($principaluri);
 
-		$stmt = OC_DB::prepare( 'INSERT INTO *PREFIX*contacts_addressbooks (userid,displayname,uri,description,ctag) VALUES(?,?,?,?,?)' );
+		$stmt = OCP\DB::prepare( 'INSERT INTO *PREFIX*contacts_addressbooks (userid,displayname,uri,description,ctag) VALUES(?,?,?,?,?)' );
 		$result = $stmt->execute(array($userid,$name,$uri,$description,1));
 
-		return OC_DB::insertid('*PREFIX*contacts_addressbooks');
+		return OCP\DB::insertid('*PREFIX*contacts_addressbooks');
 	}
 
 	/**
@@ -134,7 +134,7 @@ class OC_Contacts_Addressbook{
 			$description = $addressbook['description'];
 		}
 
-		$stmt = OC_DB::prepare( 'UPDATE *PREFIX*contacts_addressbooks SET displayname=?,description=?, ctag=ctag+1 WHERE id=?' );
+		$stmt = OCP\DB::prepare( 'UPDATE *PREFIX*contacts_addressbooks SET displayname=?,description=?, ctag=ctag+1 WHERE id=?' );
 		$result = $stmt->execute(array($name,$description,$id));
 
 		return true;
@@ -166,9 +166,9 @@ class OC_Contacts_Addressbook{
 	 */
 	public static function activeIds($uid = null){
 		if(is_null($uid)){
-			$uid = OC_User::getUser();
+			$uid = OCP\USER::getUser();
 		}
-		$prefbooks = OC_Preferences::getValue($uid,'contacts','openaddressbooks',null);
+		$prefbooks = OCP\Config::getUserValue($uid,'contacts','openaddressbooks',null);
 		if(!$prefbooks){
 			$addressbooks = OC_Contacts_Addressbook::all($uid);
 			if(count($addressbooks) == 0){
@@ -176,7 +176,7 @@ class OC_Contacts_Addressbook{
 				$addressbooks = OC_Contacts_Addressbook::all($uid);
 			}
 			$prefbooks = $addressbooks[0]['id'];
-			OC_Preferences::setValue($uid,'contacts','openaddressbooks',$prefbooks);
+			OCP\Config::setUserValue($uid,'contacts','openaddressbooks',$prefbooks);
 		}
 		return explode(';',$prefbooks);
 	}
@@ -192,12 +192,12 @@ class OC_Contacts_Addressbook{
 		$ids_sql = join(',', array_fill(0, count($active), '?'));
 		$prep = 'SELECT * FROM *PREFIX*contacts_addressbooks WHERE id IN ('.$ids_sql.') ORDER BY displayname';
 		try {
-			$stmt = OC_DB::prepare( $prep );
+			$stmt = OCP\DB::prepare( $prep );
 			$result = $stmt->execute($active);
 		} catch(Exception $e) {
-			OC_Log::write('contacts','OC_Contacts_Addressbook:active:, exception: '.$e->getMessage(),OC_Log::DEBUG);
-			OC_Log::write('contacts','OC_Contacts_Addressbook:active, ids: '.join(',', $active),OC_Log::DEBUG);
-			OC_Log::write('contacts','OC_Contacts_Addressbook::active, SQL:'.$prep,OC_Log::DEBUG);
+			OCP\Util::writeLog('contacts','OC_Contacts_Addressbook:active:, exception: '.$e->getMessage(),OCP\Util::DEBUG);
+			OCP\Util::writeLog('contacts','OC_Contacts_Addressbook:active, ids: '.join(',', $active),OCP\Util::DEBUG);
+			OCP\Util::writeLog('contacts','OC_Contacts_Addressbook::active, SQL:'.$prep,OCP\Util::DEBUG);
 		}
 
 		while( $row = $result->fetchRow()){
@@ -235,7 +235,7 @@ class OC_Contacts_Addressbook{
 		$openaddressbooks = self::cleanArray($openaddressbooks, false);
 		sort($openaddressbooks, SORT_NUMERIC);
 		// FIXME: I alway end up with a ';' prepending when imploding the array..?
-		OC_Preferences::setValue(OC_User::getUser(),'contacts','openaddressbooks',implode(';', $openaddressbooks));
+		OCP\Config::setUserValue(OCP\USER::getUser(),'contacts','openaddressbooks',implode(';', $openaddressbooks));
 
 		return true;
 	}
@@ -246,7 +246,7 @@ class OC_Contacts_Addressbook{
 	 * @return boolean
 	 */
 	public static function isActive($id){
-		//OC_Log::write('contacts','OC_Contacts_Addressbook::isActive('.$id.'):'.in_array($id, self::activeIds()), OC_Log::DEBUG);
+		//OCP\Util::writeLog('contacts','OC_Contacts_Addressbook::isActive('.$id.'):'.in_array($id, self::activeIds()), OCP\Util::DEBUG);
 		return in_array($id, self::activeIds());
 	}
 
@@ -258,7 +258,7 @@ class OC_Contacts_Addressbook{
 	public static function delete($id){
 		// FIXME: There's no error checking at all.
 		self::setActive($id, false);
-		$stmt = OC_DB::prepare( 'DELETE FROM *PREFIX*contacts_addressbooks WHERE id = ?' );
+		$stmt = OCP\DB::prepare( 'DELETE FROM *PREFIX*contacts_addressbooks WHERE id = ?' );
 		$stmt->execute(array($id));
 
 		$cards = OC_Contacts_VCard::all($id);
@@ -275,7 +275,7 @@ class OC_Contacts_Addressbook{
 	 * @return boolean
 	 */
 	public static function touch($id){
-		$stmt = OC_DB::prepare( 'UPDATE *PREFIX*contacts_addressbooks SET ctag = ctag + 1 WHERE id = ?' );
+		$stmt = OCP\DB::prepare( 'UPDATE *PREFIX*contacts_addressbooks SET ctag = ctag + 1 WHERE id = ?' );
 		$stmt->execute(array($id));
 
 		return true;
diff --git a/apps/contacts/lib/app.php b/apps/contacts/lib/app.php
old mode 100644
new mode 100755
index 78fdfe6a10a2fe08be11cb4f3ae9ffdc917480e8..58cc7f034620353b6650d1af9888f656fe25d704
--- a/apps/contacts/lib/app.php
+++ b/apps/contacts/lib/app.php
@@ -9,55 +9,22 @@
 /**
  * This class manages our app actions
  */
-OC_Contacts_App::$l10n = new OC_L10N('contacts');
+OC_Contacts_App::$l10n = OC_L10N::get('contacts');
 OC_Contacts_App::$categories = new OC_VCategories('contacts');
 class OC_Contacts_App {
 	public static $l10n;
 	public static $categories;
 
-	/**
-	* Render templates/part.details to json output
-	* @param int $id of contact
-	* @param Sabre_VObject_Component $vcard to render
-	*/
-	public static function renderDetails($id, $vcard, $new=false) {
-		$property_types = self::getAddPropertyOptions();
-		$adr_types = self::getTypesOfProperty('ADR');
-		$phone_types = self::getTypesOfProperty('TEL');
-		$upload_max_filesize = OC_Helper::computerFileSize(ini_get('upload_max_filesize'));
-		$post_max_size = OC_Helper::computerFileSize(ini_get('post_max_size'));
-		$maxUploadFilesize = min($upload_max_filesize, $post_max_size);
-
-		$freeSpace=OC_Filesystem::free_space('/');
-		$freeSpace=max($freeSpace,0);
-		$maxUploadFilesize = min($maxUploadFilesize ,$freeSpace);
-
-		$details = OC_Contacts_VCard::structureContact($vcard);
-		$name = $details['FN'][0]['value'];
-		$t = $new ? 'part.contact' : 'part.details';
-		$tmpl = new OC_Template('contacts',$t);
-		$tmpl->assign('details',$details);
-		$tmpl->assign('id',$id);
-		$tmpl->assign( 'uploadMaxFilesize', $maxUploadFilesize);
-		$tmpl->assign( 'uploadMaxHumanFilesize', OC_Helper::humanFileSize($maxUploadFilesize));
-		$tmpl->assign('property_types',$property_types);
-		$tmpl->assign('adr_types',$adr_types);
-		$tmpl->assign('phone_types',$phone_types);
-		$page = $tmpl->fetchPage();
-
-		OC_JSON::success(array('data' => array( 'id' => $id, 'name' => $name, 'page' => $page )));
-	}
-
 	public static function getAddressbook($id) {
 		$addressbook = OC_Contacts_Addressbook::find( $id );
-		if( $addressbook === false || $addressbook['userid'] != OC_User::getUser()) {
+		if( $addressbook === false || $addressbook['userid'] != OCP\USER::getUser()) {
 			if ($addressbook === false) {
-				OC_Log::write('contacts', 'Addressbook not found: '. $id, OC_Log::ERROR);
-				OC_JSON::error(array('data' => array( 'message' => self::$l10n->t('Addressbook not found.'))));
+				OCP\Util::writeLog('contacts', 'Addressbook not found: '. $id, OCP\Util::ERROR);
+				OCP\JSON::error(array('data' => array( 'message' => self::$l10n->t('Addressbook not found.'))));
 			}
 			else {
-				OC_Log::write('contacts', 'Addressbook('.$id.') is not from '.OC_User::getUser(), OC_Log::ERROR);
-				OC_JSON::error(array('data' => array( 'message' => self::$l10n->t('This is not your addressbook.'))));
+				OCP\Util::writeLog('contacts', 'Addressbook('.$id.') is not from '.OCP\USER::getUser(), OCP\Util::ERROR);
+				OCP\JSON::error(array('data' => array( 'message' => self::$l10n->t('This is not your addressbook.'))));
 			}
 			exit();
 		}
@@ -67,8 +34,8 @@ class OC_Contacts_App {
 	public static function getContactObject($id) {
 		$card = OC_Contacts_VCard::find( $id );
 		if( $card === false ) {
-			OC_Log::write('contacts', 'Contact could not be found: '.$id, OC_Log::ERROR);
-			OC_JSON::error(array('data' => array( 'message' => self::$l10n->t('Contact could not be found.').' '.$id)));
+			OCP\Util::writeLog('contacts', 'Contact could not be found: '.$id, OCP\Util::ERROR);
+			OCP\JSON::error(array('data' => array( 'message' => self::$l10n->t('Contact could not be found.').' '.$id)));
 			exit();
 		}
 
@@ -86,13 +53,13 @@ class OC_Contacts_App {
 		$vcard = OC_VObject::parse($card['carddata']);
 		// Try to fix cards with missing 'N' field from pre ownCloud 4. Hot damn, this is ugly...
 		if(!is_null($vcard) && !$vcard->__isset('N')) {
-			$appinfo = OC_App::getAppInfo('contacts');
+			$appinfo = OCP\App::getAppInfo('contacts');
 			if($appinfo['version'] >= 5) {
-				OC_Log::write('contacts','OC_Contacts_App::getContactVCard. Deprecated check for missing N field', OC_Log::DEBUG);
+				OCP\Util::writeLog('contacts','OC_Contacts_App::getContactVCard. Deprecated check for missing N field', OCP\Util::DEBUG);
 			}
-			OC_Log::write('contacts','getContactVCard, Missing N field', OC_Log::DEBUG);
+			OCP\Util::writeLog('contacts','getContactVCard, Missing N field', OCP\Util::DEBUG);
 			if($vcard->__isset('FN')) {
-				OC_Log::write('contacts','getContactVCard, found FN field: '.$vcard->__get('FN'), OC_Log::DEBUG);
+				OCP\Util::writeLog('contacts','getContactVCard, found FN field: '.$vcard->__get('FN'), OCP\Util::DEBUG);
 				$n = implode(';', array_reverse(array_slice(explode(' ', $vcard->__get('FN')), 0, 2))).';;;';
 				$vcard->setString('N', $n);
 				OC_Contacts_VCard::edit( $id, $vcard);
@@ -149,10 +116,17 @@ class OC_Contacts_App {
 				'WORK'  =>  $l->t('Work'),
 				'TEXT'  =>  $l->t('Text'),
 				'VOICE' =>  $l->t('Voice'),
+				'MSG'   =>  $l->t('Message'),
 				'FAX'   =>  $l->t('Fax'),
 				'VIDEO' =>  $l->t('Video'),
 				'PAGER' =>  $l->t('Pager'),
 			);
+		case 'EMAIL':
+			return array(
+				'WORK' => $l->t('Work'),
+				'HOME' => $l->t('Home'),
+				'INTERNET' => $l->t('Internet'),
+			);
 		}
 	}
 
@@ -171,7 +145,7 @@ class OC_Contacts_App {
 	 */
 	public static function scanCategories($vccontacts = null) {
 		if (is_null($vccontacts)) {
-			$vcaddressbooks = OC_Contacts_Addressbook::all(OC_User::getUser());
+			$vcaddressbooks = OC_Contacts_Addressbook::all(OCP\USER::getUser());
 			if(count($vcaddressbooks) > 0) {
 				$vcaddressbookids = array();
 				foreach($vcaddressbooks as $vcaddressbook) {
@@ -202,7 +176,7 @@ class OC_Contacts_App {
 		$rev = $contact->getAsString('REV');
 		if ($rev) {
 			$rev = DateTime::createFromFormat(DateTime::W3C, $rev);
-			OC_Response::setLastModifiedHeader($rev);
+			OCP\Response::setLastModifiedHeader($rev);
 		}
 	}
 }
diff --git a/apps/contacts/lib/hooks.php b/apps/contacts/lib/hooks.php
old mode 100644
new mode 100755
index e09da20be8633ac651e66d26e01ed34daea6a00d..e3d5df3d51fd227c8ce65a3256367f651df0bffb
--- a/apps/contacts/lib/hooks.php
+++ b/apps/contacts/lib/hooks.php
@@ -39,22 +39,9 @@ class OC_Contacts_Hooks{
 		return true;
 	}
 
-	/**
-	 * @brief Adds the CardDAV resource to the DAV server
-	 * @param paramters parameters from initialize-Hook
-	 * @return array
-	 */
-	static public function initializeCardDAV($parameters){
-		// We need a backend, the root node and the carddav plugin
-		$parameters['backends']['carddav'] = new OC_Connector_Sabre_CardDAV();
-		$parameters['nodes'][] = new Sabre_CardDAV_AddressBookRoot($parameters['backends']['principal'], $parameters['backends']['carddav']);
-		$parameters['plugins'][] = new Sabre_CardDAV_Plugin();
-		return true;
-	}
-
 	static public function getCalenderSources($parameters) {
-		$base_url = OC_Helper::linkTo('calendar', 'ajax/events.php').'?calendar_id=';
-		foreach(OC_Contacts_Addressbook::all(OC_User::getUser()) as $addressbook) {
+		$base_url = OCP\Util::linkTo('calendar', 'ajax/events.php').'?calendar_id=';
+		foreach(OC_Contacts_Addressbook::all(OCP\USER::getUser()) as $addressbook) {
 			$parameters['sources'][] =
 				array(
 					'url' => $base_url.'birthday_'. $addressbook['id'],
@@ -77,6 +64,9 @@ class OC_Contacts_Hooks{
 		OC_Contacts_App::getAddressbook($aid);
 		foreach(OC_Contacts_VCard::all($aid) as $card){
 			$vcard = OC_VObject::parse($card['carddata']);
+			if (!$vcard) {
+				continue;
+			}
 			$birthday = $vcard->BDAY;
 			if ($birthday) {
 				$date = new DateTime($birthday);
diff --git a/apps/contacts/lib/search.php b/apps/contacts/lib/search.php
old mode 100644
new mode 100755
index 31d8542091e8a4a787e48c78f886df345ea528cd..144138a7c2c4e44f732f6c3b6f3254cdd50b815b
--- a/apps/contacts/lib/search.php
+++ b/apps/contacts/lib/search.php
@@ -1,8 +1,8 @@
 <?php
 class OC_Search_Provider_Contacts extends OC_Search_Provider{
 	function search($query){
-		$addressbooks = OC_Contacts_Addressbook::all(OC_User::getUser(), 1);
-// 		if(count($calendars)==0 || !OC_App::isEnabled('contacts')){
+		$addressbooks = OC_Contacts_Addressbook::all(OCP\USER::getUser(), 1);
+// 		if(count($calendars)==0 || !OCP\App::isEnabled('contacts')){
 // 			//return false;
 // 		}
 		// NOTE: Does the following do anything
@@ -18,7 +18,7 @@ class OC_Search_Provider_Contacts extends OC_Search_Provider{
 			$vcards = OC_Contacts_VCard::all($addressbook['id']);
 			foreach($vcards as $vcard){
 				if(substr_count(strtolower($vcard['fullname']), strtolower($query)) > 0){
-					$link = OC_Helper::linkTo('contacts', 'index.php').'?id='.urlencode($vcard['id']);
+					$link = OCP\Util::linkTo('contacts', 'index.php').'?id='.urlencode($vcard['id']);
 					$results[]=new OC_Search_Result($vcard['fullname'],'', $link,$l->t('Contact'));//$name,$text,$link,$type
 				}
 			}
diff --git a/apps/contacts/lib/vcard.php b/apps/contacts/lib/vcard.php
old mode 100644
new mode 100755
index 90b037f76ee161dc29b80bc5be52ee23b8038cf7..4be6819054b8d31fd93d8f2e1bb110ae443fc4d9
--- a/apps/contacts/lib/vcard.php
+++ b/apps/contacts/lib/vcard.php
@@ -53,20 +53,20 @@ class OC_Contacts_VCard{
 			$id_sql = join(',', array_fill(0, count($id), '?'));
 			$prep = 'SELECT * FROM *PREFIX*contacts_cards WHERE addressbookid IN ('.$id_sql.') ORDER BY fullname';
 			try {
-				$stmt = OC_DB::prepare( $prep );
+				$stmt = OCP\DB::prepare( $prep );
 				$result = $stmt->execute($id);
 			} catch(Exception $e) {
-				OC_Log::write('contacts','OC_Contacts_VCard:all:, exception: '.$e->getMessage(),OC_Log::DEBUG);
-				OC_Log::write('contacts','OC_Contacts_VCard:all, ids: '.join(',', $id),OC_Log::DEBUG);
-				OC_Log::write('contacts','SQL:'.$prep,OC_Log::DEBUG);
+				OCP\Util::writeLog('contacts','OC_Contacts_VCard:all:, exception: '.$e->getMessage(),OCP\Util::DEBUG);
+				OCP\Util::writeLog('contacts','OC_Contacts_VCard:all, ids: '.join(',', $id),OCP\Util::DEBUG);
+				OCP\Util::writeLog('contacts','SQL:'.$prep,OCP\Util::DEBUG);
 			}
 		} elseif($id) {
 			try {
-				$stmt = OC_DB::prepare( 'SELECT * FROM *PREFIX*contacts_cards WHERE addressbookid = ? ORDER BY fullname' );
+				$stmt = OCP\DB::prepare( 'SELECT * FROM *PREFIX*contacts_cards WHERE addressbookid = ? ORDER BY fullname' );
 				$result = $stmt->execute(array($id));
 			} catch(Exception $e) {
-				OC_Log::write('contacts','OC_Contacts_VCard:all:, exception: '.$e->getMessage(),OC_Log::DEBUG);
-				OC_Log::write('contacts','OC_Contacts_VCard:all, ids: '. $id,OC_Log::DEBUG);
+				OCP\Util::writeLog('contacts','OC_Contacts_VCard:all:, exception: '.$e->getMessage(),OCP\Util::DEBUG);
+				OCP\Util::writeLog('contacts','OC_Contacts_VCard:all, ids: '. $id,OCP\Util::DEBUG);
 			}
 		}
 		$cards = array();
@@ -85,7 +85,7 @@ class OC_Contacts_VCard{
 	 * @return associative array
 	 */
 	public static function find($id){
-		$stmt = OC_DB::prepare( 'SELECT * FROM *PREFIX*contacts_cards WHERE id = ?' );
+		$stmt = OCP\DB::prepare( 'SELECT * FROM *PREFIX*contacts_cards WHERE id = ?' );
 		$result = $stmt->execute(array($id));
 
 		return $result->fetchRow();
@@ -98,7 +98,7 @@ class OC_Contacts_VCard{
 	 * @return associative array
 	 */
 	public static function findWhereDAVDataIs($aid,$uri){
-		$stmt = OC_DB::prepare( 'SELECT * FROM *PREFIX*contacts_cards WHERE addressbookid = ? AND uri = ?' );
+		$stmt = OCP\DB::prepare( 'SELECT * FROM *PREFIX*contacts_cards WHERE addressbookid = ? AND uri = ?' );
 		$result = $stmt->execute(array($aid,$uri));
 
 		return $result->fetchRow();
@@ -141,10 +141,38 @@ class OC_Contacts_VCard{
 	}
 
 	/**
-	* @brief Tries to update imported VCards to adhere to rfc2426 (VERSION: 3.0)
+	* @brief Checks if a contact with the same UID already exist in the address book.
+	* @param $aid Address book ID.
+	* @param $uid UID (passed by reference).
+	* @returns true if the UID has been changed.
+	*/
+	protected static function trueUID($aid, &$uid) {
+		$stmt = OCP\DB::prepare( 'SELECT * FROM *PREFIX*contacts_cards WHERE addressbookid = ? AND uri = ?' );
+		$uri = $uid.'.vcf';
+		$result = $stmt->execute(array($aid,$uri));
+		if($result->numRows() > 0){
+			while(true) {
+				$tmpuid = substr(md5(rand().time()),0,10);
+				$uri = $tmpuid.'.vcf';
+				$result = $stmt->execute(array($aid,$uri));
+				if($result->numRows() > 0){
+					continue;
+				} else {
+					$uid = $tmpuid;
+					return true;
+				}
+			}
+		} else {
+			return false;
+		}
+	}
+
+	/**
+	* @brief Tries to update imported VCards to adhere to rfc2426 (VERSION: 3.0) and add mandatory fields if missing.
+	* @param aid Address book id.
 	* @param vcard An OC_VObject of type VCARD (passed by reference).
 	*/
-	protected static function updateValuesFromAdd(&$vcard) { // any suggestions for a better method name? ;-)
+	protected static function updateValuesFromAdd($aid, &$vcard) { // any suggestions for a better method name? ;-)
 		$stringprops = array('N', 'FN', 'ORG', 'NICK', 'ADR', 'NOTE');
 		$typeprops = array('ADR', 'TEL', 'EMAIL');
 		$upgrade = false;
@@ -153,7 +181,7 @@ class OC_Contacts_VCard{
 		// Add version if needed
 		if($version && $version < '3.0') {
 			$upgrade = true;
-			OC_Log::write('contacts','OC_Contacts_VCard::updateValuesFromAdd. Updating from version: '.$version,OC_Log::DEBUG);
+			OCP\Util::writeLog('contacts','OC_Contacts_VCard::updateValuesFromAdd. Updating from version: '.$version,OCP\Util::DEBUG);
 		}
 		foreach($vcard->children as &$property){
 			// Decode string properties and remove obsolete properties.
@@ -162,9 +190,9 @@ class OC_Contacts_VCard{
 			}
 			// Fix format of type parameters.
 			if($upgrade && in_array($property->name, $typeprops)) {
-				OC_Log::write('contacts','OC_Contacts_VCard::updateValuesFromAdd. before: '.$property->serialize(),OC_Log::DEBUG);
+				OCP\Util::writeLog('contacts','OC_Contacts_VCard::updateValuesFromAdd. before: '.$property->serialize(),OCP\Util::DEBUG);
 				self::formatPropertyTypes($property);
-				OC_Log::write('contacts','OC_Contacts_VCard::updateValuesFromAdd. after: '.$property->serialize(),OC_Log::DEBUG);
+				OCP\Util::writeLog('contacts','OC_Contacts_VCard::updateValuesFromAdd. after: '.$property->serialize(),OCP\Util::DEBUG);
 			}
 			if($property->name == 'FN'){
 				$fn = $property->value;
@@ -194,7 +222,7 @@ class OC_Contacts_VCard{
 				$fn = 'Unknown Name';
 			}
 			$vcard->setString('FN', $fn);
-			OC_Log::write('contacts','OC_Contacts_VCard::updateValuesFromAdd. Added missing \'FN\' field: '.$fn,OC_Log::DEBUG);
+			OCP\Util::writeLog('contacts','OC_Contacts_VCard::updateValuesFromAdd. Added missing \'FN\' field: '.$fn,OCP\Util::DEBUG);
 		}
 		if(!$n || $n = ';;;;'){ // Fix missing 'N' field. Ugly hack ahead ;-)
 			$slice = array_reverse(array_slice(explode(' ', $fn), 0, 2)); // Take 2 first name parts of 'FN' and reverse.
@@ -203,18 +231,23 @@ class OC_Contacts_VCard{
 			}
 			$n = implode(';', $slice).';;;';
 			$vcard->setString('N', $n);
-			OC_Log::write('contacts','OC_Contacts_VCard::updateValuesFromAdd. Added missing \'N\' field: '.$n,OC_Log::DEBUG);
+			OCP\Util::writeLog('contacts','OC_Contacts_VCard::updateValuesFromAdd. Added missing \'N\' field: '.$n,OCP\Util::DEBUG);
 		}
 		if(!$uid) {
 			$vcard->setUID();
-			OC_Log::write('contacts','OC_Contacts_VCard::updateValuesFromAdd. Added missing \'UID\' field: '.$uid,OC_Log::DEBUG);
+			$uid = $vcard->getAsString('UID');
+			OCP\Util::writeLog('contacts','OC_Contacts_VCard::updateValuesFromAdd. Added missing \'UID\' field: '.$uid,OCP\Util::DEBUG);
+		}
+		if(self::trueUID($aid, $uid)) {
+			$vcard->setString('UID', $uid);
 		}
 		$vcard->setString('VERSION','3.0');
 		// Add product ID is missing.
 		$prodid = trim($vcard->getAsString('PRODID'));
 		if(!$prodid) {
-			$appinfo = OC_App::getAppInfo('contacts');
-			$prodid = '-//ownCloud//NONSGML '.$appinfo['name'].' '.$appinfo['version'].'//EN';
+			$appinfo = OCP\App::getAppInfo('contacts');
+			$appversion = OCP\App::getAppVersion('contacts');
+			$prodid = '-//ownCloud//NONSGML '.$appinfo['name'].' '.$appversion.'//EN';
 			$vcard->setString('PRODID', $prodid);
 		}
 		$now = new DateTime;
@@ -230,13 +263,13 @@ class OC_Contacts_VCard{
 	 */
 	public static function add($aid, OC_VObject $card, $uri=null){
 		if(is_null($card)){
-			OC_Log::write('contacts','OC_Contacts_VCard::add. No vCard supplied', OC_Log::ERROR);
+			OCP\Util::writeLog('contacts','OC_Contacts_VCard::add. No vCard supplied', OCP\Util::ERROR);
 			return null;
 		};
 
 		OC_Contacts_App::loadCategoriesFromVCard($card);
 
-		self::updateValuesFromAdd($card);
+		self::updateValuesFromAdd($aid, $card);
 
 		$fn = $card->getAsString('FN');
 		if (empty($fn)) {
@@ -249,9 +282,9 @@ class OC_Contacts_VCard{
 		}
 
 		$data = $card->serialize();
-		$stmt = OC_DB::prepare( 'INSERT INTO *PREFIX*contacts_cards (addressbookid,fullname,carddata,uri,lastmodified) VALUES(?,?,?,?,?)' );
+		$stmt = OCP\DB::prepare( 'INSERT INTO *PREFIX*contacts_cards (addressbookid,fullname,carddata,uri,lastmodified) VALUES(?,?,?,?,?)' );
 		$result = $stmt->execute(array($aid,$fn,$data,$uri,time()));
-		$newid = OC_DB::insertid('*PREFIX*contacts_cards');
+		$newid = OCP\DB::insertid('*PREFIX*contacts_cards');
 
 		OC_Contacts_Addressbook::touch($aid);
 
@@ -275,7 +308,7 @@ class OC_Contacts_VCard{
 	 * @param array $objects  An array of [id, carddata].
 	 */
 	public static function updateDataByID($objects){
-		$stmt = OC_DB::prepare( 'UPDATE *PREFIX*contacts_cards SET carddata = ?, lastmodified = ? WHERE id = ?' );
+		$stmt = OCP\DB::prepare( 'UPDATE *PREFIX*contacts_cards SET carddata = ?, lastmodified = ? WHERE id = ?' );
 		$now = new DateTime;
 		foreach($objects as $object) {
 			$vcard = OC_VObject::parse($object[1]);
@@ -284,10 +317,10 @@ class OC_Contacts_VCard{
 				$data = $vcard->serialize();
 				try {
 					$result = $stmt->execute(array($data,time(),$object[0]));
-					//OC_Log::write('contacts','OC_Contacts_VCard::updateDataByID, id: '.$object[0].': '.$object[1],OC_Log::DEBUG);
+					//OCP\Util::writeLog('contacts','OC_Contacts_VCard::updateDataByID, id: '.$object[0].': '.$object[1],OCP\Util::DEBUG);
 				} catch(Exception $e) {
-					OC_Log::write('contacts','OC_Contacts_VCard::updateDataByID:, exception: '.$e->getMessage(),OC_Log::DEBUG);
-					OC_Log::write('contacts','OC_Contacts_VCard::updateDataByID, id: '.$object[0],OC_Log::DEBUG);
+					OCP\Util::writeLog('contacts','OC_Contacts_VCard::updateDataByID:, exception: '.$e->getMessage(),OCP\Util::DEBUG);
+					OCP\Util::writeLog('contacts','OC_Contacts_VCard::updateDataByID, id: '.$object[0],OCP\Util::DEBUG);
 				}
 			}
 		}
@@ -317,7 +350,7 @@ class OC_Contacts_VCard{
 		$card->setString('REV', $now->format(DateTime::W3C));
 
 		$data = $card->serialize();
-		$stmt = OC_DB::prepare( 'UPDATE *PREFIX*contacts_cards SET fullname = ?,carddata = ?, lastmodified = ? WHERE id = ?' );
+		$stmt = OCP\DB::prepare( 'UPDATE *PREFIX*contacts_cards SET fullname = ?,carddata = ?, lastmodified = ? WHERE id = ?' );
 		$result = $stmt->execute(array($fn,$data,time(),$id));
 
 		OC_Contacts_Addressbook::touch($oldcard['addressbookid']);
@@ -345,7 +378,7 @@ class OC_Contacts_VCard{
 	 */
 	public static function delete($id){
 		// FIXME: Add error checking.
-		$stmt = OC_DB::prepare( 'DELETE FROM *PREFIX*contacts_cards WHERE id = ?' );
+		$stmt = OCP\DB::prepare( 'DELETE FROM *PREFIX*contacts_cards WHERE id = ?' );
 		$stmt->execute(array($id));
 
 		return true;
@@ -359,7 +392,7 @@ class OC_Contacts_VCard{
 	 */
 	public static function deleteFromDAVData($aid,$uri){
 		// FIXME: Add error checking. Deleting a card gives an Kontact/Akonadi error.
-		$stmt = OC_DB::prepare( 'DELETE FROM *PREFIX*contacts_cards WHERE addressbookid = ? AND uri=?' );
+		$stmt = OCP\DB::prepare( 'DELETE FROM *PREFIX*contacts_cards WHERE addressbookid = ? AND uri=?' );
 		$stmt->execute(array($aid,$uri));
 		OC_Contacts_Addressbook::touch($aid);
 
@@ -460,7 +493,7 @@ class OC_Contacts_VCard{
 			}
 			// NOTE: Apparently Sabre_VObject_Reader can't always deal with value list parameters
 			// like TYPE=HOME,CELL,VOICE. Tanghus.
-			if ($property->name == 'TEL' && $parameter->name == 'TYPE'){
+			if (in_array($property->name, array('TEL', 'EMAIL')) && $parameter->name == 'TYPE'){
 				if (isset($temp['parameters'][$parameter->name])){
 					$temp['parameters'][$parameter->name][] = $parameter->value;
 				}
@@ -488,23 +521,23 @@ class OC_Contacts_VCard{
 			$id_sql = join(',', array_fill(0, count($id), '?'));
 			$prep = 'UPDATE *PREFIX*contacts_cards SET addressbookid = ? WHERE id IN ('.$id_sql.')';
 			try {
-				$stmt = OC_DB::prepare( $prep );
+				$stmt = OCP\DB::prepare( $prep );
 				//$aid = array($aid);
 				$vals = array_merge((array)$aid, $id);
 				$result = $stmt->execute($vals);
 			} catch(Exception $e) {
-				OC_Log::write('contacts','OC_Contacts_VCard::moveToAddressBook:, exception: '.$e->getMessage(),OC_Log::DEBUG);
-				OC_Log::write('contacts','OC_Contacts_VCard::moveToAddressBook, ids: '.join(',', $vals),OC_Log::DEBUG);
-				OC_Log::write('contacts','SQL:'.$prep,OC_Log::DEBUG);
+				OCP\Util::writeLog('contacts','OC_Contacts_VCard::moveToAddressBook:, exception: '.$e->getMessage(),OCP\Util::DEBUG);
+				OCP\Util::writeLog('contacts','OC_Contacts_VCard::moveToAddressBook, ids: '.join(',', $vals),OCP\Util::DEBUG);
+				OCP\Util::writeLog('contacts','SQL:'.$prep,OCP\Util::DEBUG);
 				return false;
 			}
 		} else {
 			try {
-				$stmt = OC_DB::prepare( 'UPDATE *PREFIX*contacts_cards SET addressbookid = ? WHERE id = ?' );
+				$stmt = OCP\DB::prepare( 'UPDATE *PREFIX*contacts_cards SET addressbookid = ? WHERE id = ?' );
 				$result = $stmt->execute(array($aid, $id));
 			} catch(Exception $e) {
-				OC_Log::write('contacts','OC_Contacts_VCard::moveToAddressBook:, exception: '.$e->getMessage(),OC_Log::DEBUG);
-				OC_Log::write('contacts','OC_Contacts_VCard::moveToAddressBook, id: '.$id,OC_Log::DEBUG);
+				OCP\Util::writeLog('contacts','OC_Contacts_VCard::moveToAddressBook:, exception: '.$e->getMessage(),OCP\Util::DEBUG);
+				OCP\Util::writeLog('contacts','OC_Contacts_VCard::moveToAddressBook, id: '.$id,OCP\Util::DEBUG);
 				return false;
 			}
 		}
diff --git a/apps/contacts/photo.php b/apps/contacts/photo.php
old mode 100644
new mode 100755
index 298f1215e3c467685b629cdd37d832093ba28a57..6fe68cefb6d0ce4dd5894160ac2b4f1e6e05adef
--- a/apps/contacts/photo.php
+++ b/apps/contacts/photo.php
@@ -9,17 +9,22 @@
  */
 
 // Init owncloud
-require_once('../../lib/base.php');
-OC_Util::checkLoggedIn();
-OC_Util::checkAppEnabled('contacts');
+
+OCP\User::checkLoggedIn();
+OCP\App::checkAppEnabled('contacts');
 
 function getStandardImage(){
-	OC_Response::setExpiresHeader('P10D');
-	OC_Response::enableCaching();
-	OC_Response::redirect(OC_Helper::imagePath('contacts', 'person_large.png'));
+	OCP\Response::setExpiresHeader('P10D');
+	OCP\Response::enableCaching();
+	OCP\Response::redirect(OCP\Util::imagePath('contacts', 'person_large.png'));
 }
 
-$id = $_GET['id'];
+$id = isset($_GET['id']) ? $_GET['id'] : null;
+$caching = isset($_GET['refresh']) ? 0 : null;
+
+if(is_null($id)) {
+	getStandardImage();
+}
 
 $contact = OC_Contacts_App::getContactVCard($id);
 $image = new OC_Image();
@@ -28,21 +33,21 @@ if(!$image) {
 }
 // invalid vcard
 if( is_null($contact)) {
-	OC_Log::write('contacts','photo.php. The VCard for ID '.$id.' is not RFC compatible',OC_Log::ERROR);
+	OCP\Util::writeLog('contacts','photo.php. The VCard for ID '.$id.' is not RFC compatible',OCP\Util::ERROR);
 } else {
-	OC_Response::enableCaching();
+	OCP\Response::enableCaching($caching);
 	OC_Contacts_App::setLastModifiedHeader($contact);
 
 	// Photo :-)
 	if($image->loadFromBase64($contact->getAsString('PHOTO'))) {
 		// OK
-		OC_Response::setETagHeader(md5($contact->getAsString('PHOTO')));
+		OCP\Response::setETagHeader(md5($contact->getAsString('PHOTO')));
 	}
 	else
 	// Logo :-/
 	if($image->loadFromBase64($contact->getAsString('LOGO'))) {
 		// OK
-		OC_Response::setETagHeader(md5($contact->getAsString('LOGO')));
+		OCP\Response::setETagHeader(md5($contact->getAsString('LOGO')));
 	}
 	if ($image->valid()) {
 		$max_size = 200;
diff --git a/apps/contacts/templates/index.php b/apps/contacts/templates/index.php
old mode 100644
new mode 100755
index b14a35e19ed6a84827fd9302b2b982996f29114a..79825067d82d4332f425694d08c5b3d99ea5c503
--- a/apps/contacts/templates/index.php
+++ b/apps/contacts/templates/index.php
@@ -1,19 +1,19 @@
 <script type='text/javascript'>
-	var totalurl = '<?php echo OC_Helper::linkToAbsolute('contacts', 'carddav.php'); ?>/addressbooks';
+	var totalurl = '<?php echo OCP\Util::linkToAbsolute('contacts', 'carddav.php'); ?>/addressbooks';
 	var categories = <?php echo json_encode($_['categories']); ?>;
-	var lang = '<?php echo OC_Preferences::getValue(OC_User::getUser(), 'core', 'lang', 'en'); ?>';
+	var lang = '<?php echo OCP\Config::getUserValue(OCP\USER::getUser(), 'core', 'lang', 'en'); ?>';
 </script>
-<div id="controls">
-	<form>
-		<input type="button" id="contacts_newcontact" value="<?php echo $l->t('Add Contact'); ?>">
-		<input type="button" id="chooseaddressbook" value="<?php echo $l->t('Addressbooks'); ?>">
-	</form>
-</div>
 <div id="leftcontent" class="leftcontent">
 	<ul id="contacts">
 		<?php echo $this->inc("part.contacts"); ?>
 	</ul>
 </div>
+	<div id="bottomcontrols">
+		<form>
+			<button class="svg" id="contacts_newcontact" title="<?php echo $l->t('Add Contact'); ?>"><img class="svg" src="<?php echo OCP\Util::linkTo('contacts', 'img/contact-new.svg'); ?>" alt="<?php echo $l->t('Add Contact'); ?>"   /></button>
+			<button class="svg" id="chooseaddressbook" title="<?php echo $l->t('Addressbooks'); ?>"><img class="svg" src="core/img/actions/settings.svg" alt="<?php echo $l->t('Addressbooks'); ?>" /></button>
+		</form>
+	</div>
 <div id="rightcontent" class="rightcontent" data-id="<?php echo $_['id']; ?>">
 	<?php
 		if ($_['id']){
diff --git a/apps/contacts/templates/part.chooseaddressbook.php b/apps/contacts/templates/part.chooseaddressbook.php
old mode 100644
new mode 100755
index 90894220ef8bdf9a0b1e2bac5006c0f8ce59d44f..91b2f51c3b43d7ad9b3fb6048d61fd08bdab8916
--- a/apps/contacts/templates/part.chooseaddressbook.php
+++ b/apps/contacts/templates/part.chooseaddressbook.php
@@ -1,7 +1,7 @@
-<div id="chooseaddressbook_dialog" title="<?php echo $l->t("Choose active Address Books"); ?>">
+<div id="chooseaddressbook_dialog" title="<?php echo $l->t("Configure Address Books"); ?>">
 <table width="100%" style="border: 0;">
 <?php
-$option_addressbooks = OC_Contacts_Addressbook::all(OC_User::getUser());
+$option_addressbooks = OC_Contacts_Addressbook::all(OCP\USER::getUser());
 for($i = 0; $i < count($option_addressbooks); $i++){
 	echo "<tr>";
 	$tmpl = new OC_Template('contacts', 'part.chooseaddressbook.rowfields');
@@ -14,11 +14,12 @@ for($i = 0; $i < count($option_addressbooks); $i++){
 <tr>
 	<td colspan="5" style="padding: 0.5em;">
 		<a class="button" href="#" onclick="Contacts.UI.Addressbooks.newAddressbook(this);"><?php echo $l->t('New Address Book') ?></a>
+		<a class="button" href="#" onclick="Contacts.UI.Addressbooks.importAddressbook(this);"><?php echo $l->t('Import from VCF') ?></a>
 	</td>
 </tr>
 <tr>
 	<td colspan="5">
-		<p style="margin: 0 auto;width: 90%;"><input style="display:none;width: 90%;float: left;" type="text" id="carddav_url" onmouseover="$('#carddav_url').select();" title="<?php echo $l->t("CardDav Link"); ?>"><img id="carddav_url_close" style="height: 20px;vertical-align: middle;display: none;" src="../../core/img/actions/delete.svg" alt="close" onclick="$('#carddav_url').hide();$('#carddav_url_close').hide();"/></p>
+		<p style="margin: 0 auto;width: 90%;"><input style="display:none;width: 90%;float: left;" type="text" id="carddav_url" onmouseover="$('#carddav_url').select();" title="<?php echo $l->t("CardDav Link"); ?>"><a class="action delete" id="carddav_url_close" style="height: 20px;vertical-align: middle;display: none;" title="close" onclick="$('#carddav_url').hide();$('#carddav_url_close').hide();"/></a></p>
 	</td>
 </tr>
 </table>
diff --git a/apps/contacts/templates/part.chooseaddressbook.rowfields.php b/apps/contacts/templates/part.chooseaddressbook.rowfields.php
old mode 100644
new mode 100755
index 95a4b2362aa7e36eed4f19dd72560015d37911c5..780920ea3c2b0d878af7c0d759ec3b27c056da96
--- a/apps/contacts/templates/part.chooseaddressbook.rowfields.php
+++ b/apps/contacts/templates/part.chooseaddressbook.rowfields.php
@@ -1,5 +1,18 @@
-<?php
-	// FIXME: Make this readable.
-	echo "<td width=\"20px\"><input id=\"active_" . $_['addressbook']["id"] . "\" type=\"checkbox\" onClick=\"Contacts.UI.Addressbooks.activation(this, " . $_['addressbook']["id"] . ")\"" . (OC_Contacts_Addressbook::isActive($_['addressbook']["id"]) ? ' checked="checked"' : '') . "></td>";
-	echo "<td><label for=\"active_" . $_['addressbook']["id"] . "\">" . htmlspecialchars($_['addressbook']["displayname"]) . "</label></td>";
-	echo "<td width=\"20px\"><a href=\"#\" onclick=\"Contacts.UI.showCardDAVUrl('" . OC_User::getUser() . "', '" . $_['addressbook']["uri"] . "');\" title=\"" . $l->t("CardDav Link") . "\" class=\"action\"><img  class=\"svg action\" src=\"../../core/img/actions/public.svg\"></a></td><td width=\"20px\"><a href=\"export.php?bookid=" . $_['addressbook']["id"] . "\" title=\"" . $l->t("Download") . "\" class=\"action\"><img  class=\"svg action\" src=\"../../core/img/actions/download.svg\"></a></td><td width=\"20px\"><a  href=\"#\" title=\"" . $l->t("Edit") . "\" class=\"action\" onclick=\"Contacts.UI.Addressbooks.editAddressbook(this, " . $_['addressbook']["id"] . ");\"><img class=\"svg action\" src=\"../../core/img/actions/rename.svg\"></a></td><td width=\"20px\"><a href=\"#\" onclick=\"Contacts.UI.Addressbooks.deleteAddressbook('" . $_['addressbook']["id"] . "');\" title=\"" . $l->t("Delete") . "\" class=\"action\"><img  class=\"svg action\" src=\"../../core/img/actions/delete.svg\"></a></td>";
+<td width="20px">
+	<input id="active_<?php echo $_['addressbook']["id"]; ?>" type="checkbox" onClick="Contacts.UI.Addressbooks.activation(this, <?php echo $_['addressbook']["id"]; ?>)" <?php echo (OC_Contacts_Addressbook::isActive($_['addressbook']["id"]) ? ' checked="checked"' : ''); ?>>
+</td>
+<td>
+	<label for="active_<?php echo $_['addressbook']["id"]; ?>"><?php echo htmlspecialchars($_['addressbook']["displayname"]); ?></label>
+</td>
+<td width="20px">
+	<a onclick="Contacts.UI.showCardDAVUrl('<?php echo OCP\USER::getUser(); ?>', '<?php echo rawurlencode($_['addressbook']["uri"]); ?>');" title="<?php echo $l->t("CardDav Link"); ?>" class="svg action globe"></a>
+</td>
+<td width="20px">
+	<a href="<?php echo OCP\Util::linkTo('contacts', 'export.php'); ?>?bookid=<?php echo $_['addressbook']["id"]; ?>" title="<?php echo $l->t("Download"); ?>" class="svg action download"></a>
+</td>
+<td width="20px">
+	<a title="<?php echo $l->t("Edit"); ?>" class="svg action edit" onclick="Contacts.UI.Addressbooks.editAddressbook(this, <?php echo $_['addressbook']["id"]; ?>);"></a>
+</td>
+<td width="20px">
+	<a onclick="Contacts.UI.Addressbooks.deleteAddressbook(this, <?php echo $_['addressbook']["id"]; ?>);" title="<?php echo $l->t("Delete"); ?>" class="svg action delete"></a>
+</td>
diff --git a/apps/contacts/templates/part.contact.php b/apps/contacts/templates/part.contact.php
old mode 100644
new mode 100755
index c09c20fd4e4d127e5f5102c8a9e1d13d1c59b660..8bc0457ed4e66f4221437f8fe009a7056ca82d90
--- a/apps/contacts/templates/part.contact.php
+++ b/apps/contacts/templates/part.contact.php
@@ -3,39 +3,35 @@ $id = isset($_['id']) ? $_['id'] : '';
 ?>
 <div id="card">
 	<div id="actionbar">
-	<a title="<?php echo $l->t('Add field'); ?>" class="svg action" id="contacts_propertymenu_button"></a>
-	<div id="contacts_propertymenu" style="display: none;">
-	<ul>
-		<li><a data-type="PHOTO"><?php echo $l->t('Profile picture'); ?></a></li>
-		<li><a data-type="ORG"><?php echo $l->t('Organization'); ?></a></li>
-		<li><a data-type="NICKNAME"><?php echo $l->t('Nickname'); ?></a></li>
-		<li><a data-type="BDAY"><?php echo $l->t('Birthday'); ?></a></li>
-		<li><a data-type="TEL"><?php echo $l->t('Phone'); ?></a></li>
-		<li><a data-type="EMAIL"><?php echo $l->t('Email'); ?></a></li>
-		<li><a data-type="ADR"><?php echo $l->t('Address'); ?></a></li>
-		<li><a data-type="NOTE"><?php echo $l->t('Note'); ?></a></li>
-		<li><a data-type="CATEGORIES"><?php echo $l->t('Groups'); ?></a></li>
+	<button title="<?php echo $l->t('Add field'); ?>" class="svg action" id="contacts_propertymenu_button"></button>
+	<div id="contacts_propertymenu" class="hidden">
+	<ul role="menu">
+		<li><a role="menuitem" data-type="PHOTO"><?php echo $l->t('Profile picture'); ?></a></li>
+		<li><a role="menuitem" data-type="ORG"><?php echo $l->t('Organization'); ?></a></li>
+		<li><a role="menuitem" data-type="NICKNAME"><?php echo $l->t('Nickname'); ?></a></li>
+		<li><a role="menuitem" data-type="BDAY"><?php echo $l->t('Birthday'); ?></a></li>
+		<li><a role="menuitem" data-type="TEL"><?php echo $l->t('Phone'); ?></a></li>
+		<li><a role="menuitem" data-type="EMAIL"><?php echo $l->t('Email'); ?></a></li>
+		<li><a role="menuitem" data-type="ADR"><?php echo $l->t('Address'); ?></a></li>
+		<li><a role="menuitem" data-type="NOTE"><?php echo $l->t('Note'); ?></a></li>
+		<li><a role="menuitem" data-type="CATEGORIES"><?php echo $l->t('Groups'); ?></a></li>
 	</ul>
 	</div>
-	<img  onclick="Contacts.UI.Card.doExport();" class="svg action" id="contacts_downloadcard" src="<?php echo image_path('', 'actions/download.svg'); ?>" title="<?php echo $l->t('Download contact');?>" />
-	<img class="svg action" id="contacts_deletecard" src="<?php echo image_path('', 'actions/delete.svg'); ?>" title="<?php echo $l->t('Delete contact');?>" />
+	<button class="svg action" id="contacts_downloadcard" title="<?php echo $l->t('Download contact');?>"></button>
+	<button class="svg action" id="contacts_deletecard" title="<?php echo $l->t('Delete contact');?>"></button>
 	</div>
 
 	<div id="contact_photo" class="contactsection">
 
-	<form class="float" id="file_upload_form" action="ajax/uploadphoto.php" method="post" enctype="multipart/form-data" target="file_upload_target" class="propertycontainer" data-element="PHOTO">
-	<fieldset id="photo">
-	<a class="action delete" onclick="$(this).tipsy('hide');Contacts.UI.Card.deleteProperty(this, 'single');" title="<?php echo $l->t('Delete'); ?>"></a>
-		<div class="tip" id="contacts_details_photo_wrapper" title="<?php echo $l->t('Click or drop to upload picture'); ?> (max <?php echo $_['uploadMaxHumanFilesize']; ?>)">
-		<!-- img style="padding: 1em;" id="contacts_details_photo" alt="Profile picture"  src="photo.php?id=<?php echo $_['id']; ?>" / -->
-		<progress id="contacts_details_photo_progress" style="display:none;" value="0" max="100">0 %</progress>
+	<form class="float" id="file_upload_form" action="<?php echo OCP\Util::linkTo('contacts', 'ajax/uploadphoto.php'); ?>" method="post" enctype="multipart/form-data" target="file_upload_target">
+		<div class="tip propertycontainer" id="contacts_details_photo_wrapper" title="<?php echo $l->t('Drop photo to upload'); ?> (max <?php echo $_['uploadMaxHumanFilesize']; ?>)" data-element="PHOTO">
+		<progress id="contacts_details_photo_progress" class="hidden" value="0" max="100">0 %</progress>
 		</div>
 		<input type="hidden" name="id" value="<?php echo $_['id'] ?>">
 		<input type="hidden" name="MAX_FILE_SIZE" value="<?php echo $_['uploadMaxFilesize'] ?>" id="max_upload">
 		<input type="hidden" class="max_human_file_size" value="(max <?php echo $_['uploadMaxHumanFilesize']; ?>)">
 		<input id="file_upload_start" type="file" accept="image/*" name="imagefile" />
 		<iframe name="file_upload_target" id='file_upload_target' src=""></iframe>
-	</fieldset>
 	</form>
 	</div> <!-- contact_photo -->
 
@@ -43,22 +39,22 @@ $id = isset($_['id']) ? $_['id'] : '';
 	<form method="post">
 	<input type="hidden" name="id" value="<?php echo $_['id'] ?>">
 	<fieldset id="ident" class="contactpart">
-	<!-- legend>Name</legend -->
 	<span class="propertycontainer" data-element="N"><input type="hidden" id="n" class="contacts_property" name="value" value="" /></span>
 	<span id="name" class="propertycontainer" data-element="FN">
-	<select class="float" id="fn_select" title="<?php echo $l->t('Format custom, Short name, Full name, Reverse or Reverse with comma'); ?>" style="width:16em;">
-	</select><a id="edit_name" class="action edit" title="<?php echo $l->t('Edit name details'); ?>"></a>
+	<select class="float" id="fn_select" title="<?php echo $l->t('Format custom, Short name, Full name, Reverse or Reverse with comma'); ?>">
+	</select><a role="button" id="edit_name" class="action edit" title="<?php echo $l->t('Edit name details'); ?>"></a>
 	</span>
 	<dl id="identityprops" class="form">
-		<dt style="display:none;" id="org_label" data-element="ORG"><label for="org"><?php echo $l->t('Organization'); ?></label></dt>
-		<dd style="display:none;" class="propertycontainer" id="org_value" data-element="ORG"><input id="org" required="required" name="value[ORG]" type="text" class="contacts_property big" name="value" value="" placeholder="<?php echo $l->t('Organization'); ?>" /><a class="action delete" onclick="$(this).tipsy('hide');Contacts.UI.Card.deleteProperty(this, 'single');" title="<?php echo $l->t('Delete'); ?>"></a></dd>
-		<dt style="display:none;" id="nickname_label" data-element="NICKNAME"><label for="nickname"><?php echo $l->t('Nickname'); ?></label></dt>
-		<dd style="display:none;" class="propertycontainer" id="nickname_value" data-element="NICKNAME"><input id="nickname" required="required" name="value[NICKNAME]" type="text" class="contacts_property big" name="value" value="" placeholder="<?php echo $l->t('Enter nickname'); ?>" /><a class="action delete" onclick="$(this).tipsy('hide');Contacts.UI.Card.deleteProperty(this, 'single');" title="<?php echo $l->t('Delete'); ?>"></a></dd>
-		<dt style="display:none;" id="bday_label" data-element="BDAY"><label for="bday"><?php echo $l->t('Birthday'); ?></label></dt>
-		<dd style="display:none;" class="propertycontainer" id="bday_value" data-element="BDAY"><input id="bday"  required="required" name="value" type="text" class="contacts_property big" value="" placeholder="<?php echo $l->t('dd-mm-yyyy'); ?>" /><a class="action delete" onclick="$(this).tipsy('hide');Contacts.UI.Card.deleteProperty(this, 'single');" title="<?php echo $l->t('Delete'); ?>"></a></dd>
-		<dt style="display:none;" id="categories_label" data-element="CATEGORIES"><label for="categories"><?php echo $l->t('Groups'); ?></label></dt>
-		<dd style="display:none;" class="propertycontainer" id="categories_value" data-element="CATEGORIES"><input id="categories" required="required" name="value[CATEGORIES]" type="text" class="contacts_property bold" name="value" value="" placeholder="
-<?php echo $l->t('Separate groups with commas'); ?>" /><a class="action delete" onclick="$(this).tipsy('hide');Contacts.UI.Card.deleteProperty(this, 'single');" title="<?php echo $l->t('Delete'); ?>"></a><a class="action edit" onclick="$(this).tipsy('hide');OCCategories.edit();" title="<?php echo $l->t('Edit groups'); ?>"></a></dd>
+		<dt class="hidden" id="org_label" data-element="ORG"><label for="org"><?php echo $l->t('Organization'); ?></label></dt>
+		<dd class="propertycontainer hidden" id="org_value" data-element="ORG"><input id="org" required="required" name="value[ORG]" type="text" class="contacts_property big" name="value" value="" placeholder="<?php echo $l->t('Organization'); ?>" /><a role="button" class="action delete" title="<?php echo $l->t('Delete'); ?>"></a></dd>
+		<dt class="hidden" id="nickname_label" data-element="NICKNAME"><label for="nickname"><?php echo $l->t('Nickname'); ?></label></dt>
+		<dd class="propertycontainer hidden" id="nickname_value" data-element="NICKNAME"><input id="nickname" required="required" name="value[NICKNAME]" type="text" class="contacts_property big" name="value" value="" placeholder="<?php echo $l->t('Enter nickname'); ?>" /><a role="button" class="action delete" title="<?php echo $l->t('Delete'); ?>"></a></dd>
+		<dt class="hidden" id="bday_label" data-element="BDAY"><label for="bday"><?php echo $l->t('Birthday'); ?></label></dt>
+		<dd class="propertycontainer hidden" id="bday_value" data-element="BDAY"><input id="bday"  required="required" name="value" type="text" class="contacts_property big" value="" placeholder="<?php echo $l->t('dd-mm-yyyy'); ?>" /><a role="button" class="action delete" title="<?php echo $l->t('Delete'); ?>"></a></dd>
+		<dt class="hidden" id="categories_label" data-element="CATEGORIES"><label for="categories"><?php echo $l->t('Groups'); ?></label></dt>
+		<dd class="propertycontainer hidden" id="categories_value" data-element="CATEGORIES"><input id="categories" required="required" name="value[CATEGORIES]" type="text" class="contacts_property bold" name="value" value="" placeholder="
+<?php echo $l->t('Separate groups with commas'); ?>" />
+		<a role="button" class="action delete" title="<?php echo $l->t('Delete'); ?>"></a><a role="button" class="action edit" title="<?php echo $l->t('Edit groups'); ?>"></a></dd>
 	</dl>
 	</fieldset>
 	</form>
@@ -70,39 +66,40 @@ $id = isset($_['id']) ? $_['id'] : '';
 		<!-- email addresses -->
 		<div id="emails">
 		<fieldset class="contactpart">
-		<!-- legend><?php echo $l->t('Email'); ?></legend -->
 			<ul id="emaillist" class="propertylist">
-			<li class="template" style="white-space: nowrap; display: none;" data-element="EMAIL">
+			<li class="template hidden" data-element="EMAIL">
 				<input type="checkbox" class="contacts_property tip" name="parameters[TYPE][]" value="PREF" title="<?php echo $l->t('Preferred'); ?>" />
-				<input type="email" required="required" class="nonempty contacts_property" style="width:15em;" name="value" value="" x-moz-errormessage="<?php echo $l->t('Please specify a valid email address.'); ?>" placeholder="<?php echo $l->t('Enter email address'); ?>" /><span class="listactions"><a onclick="Contacts.UI.mailTo(this)" class="action mail" title="<?php echo $l->t('Mail to address'); ?>"></a>
-				<a class="action delete" onclick="$(this).tipsy('hide');Contacts.UI.Card.deleteProperty(this, 'list');" title="<?php echo $l->t('Delete email address'); ?>"></a></span></li>
-			</ul><!-- a id="add_email" class="add" title="<?php echo $l->t('Add email address'); ?>"></a -->
+				<input type="email" required="required" class="nonempty contacts_property" name="value" value="" x-moz-errormessage="<?php echo $l->t('Please specify a valid email address.'); ?>" placeholder="<?php echo $l->t('Enter email address'); ?>" />
+				<select class="hidden" multiple="multiple" name="parameters[TYPE][]">
+					<?php echo html_select_options($_['email_types'], array()) ?>
+				</select>
+				<span class="listactions"><a class="action mail" title="<?php echo $l->t('Mail to address'); ?>"></a>
+				<a role="button" class="action delete" title="<?php echo $l->t('Delete email address'); ?>"></a></span></li>
+			</ul>
 		</div> <!-- email addresses-->
 
 		<!-- Phone numbers -->
 		<div id="phones">
 		<fieldset class="contactpart">
-		<!-- legend><?php echo $l->t('Phone'); ?></legend -->
 			<ul id="phonelist" class="propertylist">
-				<li class="template" style="white-space: nowrap; display: none;" data-element="TEL">
+				<li class="template hidden" data-element="TEL">
 				<input type="checkbox" class="contacts_property tip" name="parameters[TYPE][]" value="PREF" title="<?php echo $l->t('Preferred'); ?>" /> 
-				<input type="text" required="required" class="nonempty contacts_property" style="width:10em; border: 0px;" name="value" value="" placeholder="<?php echo $l->t('Enter phone number'); ?>" />
+				<input type="text" required="required" class="nonempty contacts_property" name="value" value="" placeholder="<?php echo $l->t('Enter phone number'); ?>" />
 				<select multiple="multiple" name="parameters[TYPE][]">
 					<?php echo html_select_options($_['phone_types'], array()) ?>
 				</select>
-				<a class="action delete" onclick="$(this).tipsy('hide');Contacts.UI.Card.deleteProperty(this, 'list');" title="<?php echo $l->t('Delete phone number'); ?>"></a></li>
-			</ul><!-- a id="add_phone" class="add" title="<?php echo $l->t('Add phone number'); ?>"></a -->
+				<a role="button" class="action delete" title="<?php echo $l->t('Delete phone number'); ?>"></a></li>
+			</ul>
 		</div> <!-- Phone numbers -->
 
 		<!-- Addresses -->
-		<div id="addresses" style="display:none;">
+		<div id="addresses" class="hidden">
 		<fieldset class="contactpart">
-		<!-- legend><?php echo $l->t('Address'); ?></legend -->
 		<div id="addressdisplay">
-			<dl class="addresscard template" style="display: none;" data-element="ADR"><dt>
+			<dl class="addresscard template hidden" data-element="ADR"><dt>
 			<input class="adr contacts_property" name="value" type="hidden" value="" />
 			<input type="hidden" class="adr_type contacts_property" name="parameters[TYPE][]" value="" />
-			<span class="adr_type_label"></span><a class="action globe" style="float:right;" onclick="$(this).tipsy('hide');Contacts.UI.searchOSM(this);" title="<?php echo $l->t('View on map'); ?>"></a><a class="action edit" style="float:right;" onclick="$(this).tipsy('hide');Contacts.UI.Card.editAddress(this, false);" title="<?php echo $l->t('Edit address details'); ?>"></a><a class="action delete" style="float:right;" onclick="$(this).tipsy('hide');Contacts.UI.Card.deleteProperty(this, 'list');" title="Delete address"></a>
+			<span class="adr_type_label"></span><a class="action globe" title="<?php echo $l->t('View on map'); ?>"></a><a class="action edit" title="<?php echo $l->t('Edit address details'); ?>"></a><a role="button" class="action delete" title="Delete address"></a>
 			</dt><dd><ul class="addresslist"></ul></dd></dl>
 
 		</fieldset>
@@ -113,7 +110,7 @@ $id = isset($_['id']) ? $_['id'] : '';
 	<div id="contact_note" class="contactsection">
 	<form class="float" method="post">
 	<fieldset id="note" class="formfloat propertycontainer contactpart" data-element="NOTE">
-	<textarea class="contacts_property note" name="value" cols="40" rows="10" required="required" placeholder="<?php echo $l->t('Add notes here.'); ?>"></textarea>
+	<textarea class="contacts_property note" name="value" cols="60" rows="15" required="required" placeholder="<?php echo $l->t('Add notes here.'); ?>"></textarea>
 	</fieldset>
 	</form>
 	</div> <!-- contact_note -->
@@ -128,6 +125,7 @@ $(document).ready(function(){
 			if(jsondata.status == 'success'){
 				$('#leftcontent li[data-id="<?php echo $id; ?>"]').addClass('active');
 				Contacts.UI.Card.loadContact(jsondata.data);
+				Contacts.UI.loadHandlers();
 			}
 			else{
 				OC.dialogs.alert(jsondata.data.message, t('contacts', 'Error'));
diff --git a/apps/contacts/templates/part.contactphoto.php b/apps/contacts/templates/part.contactphoto.php
old mode 100644
new mode 100755
index bcb2f75815c82f100ca3e5040558cc52400e87d9..bddf4cc8a8190fb7b22e654cec68df6690381469
--- a/apps/contacts/templates/part.contactphoto.php
+++ b/apps/contacts/templates/part.contactphoto.php
@@ -2,9 +2,15 @@
 $id = $_['id'];
 $wattr = isset($_['width'])?'width="'.$_['width'].'"':'';
 $hattr = isset($_['height'])?'height="'.$_['height'].'"':'';
-$rand = isset($_['refresh'])?'&'.rand().'='.rand():'';
+$rand = isset($_['refresh'])?'&refresh='.rand():'';
 ?>
-<img class="loading" id="contacts_details_photo" <?php echo $wattr; ?> <?php echo $hattr; ?> src="<?php echo OC_Helper::linkToAbsolute('contacts', 'photo.php'); ?>?id=<?php echo $id.$rand; ?>" />
+<ul id="phototools" class="transparent hidden">
+	<li><a class="svg delete" title="<?php echo $l->t('Delete current photo'); ?>"></a></li>
+	<li><a class="svg edit" title="<?php echo $l->t('Edit current photo'); ?>"></a></li>
+	<li><a class="svg upload" title="<?php echo $l->t('Upload new photo'); ?>"></a></li>
+	<li><a class="svg cloud" title="<?php echo $l->t('Select photo from ownCloud'); ?>"></a></li>
+</ul>
+<img class="loading" id="contacts_details_photo" <?php echo $wattr; ?> <?php echo $hattr; ?> src="<?php echo OCP\Util::linkToAbsolute('contacts', 'photo.php'); ?>?id=<?php echo $id.$rand; ?>" />
 <progress id="contacts_details_photo_progress" style="display:none;" value="0" max="100">0 %</progress>
 
 
diff --git a/apps/contacts/templates/part.cropphoto.php b/apps/contacts/templates/part.cropphoto.php
old mode 100644
new mode 100755
index 5faa4aa6ac6a2352f14de0e15a6b6f86adc2612a..599951d9a972fb8096dfc083c99488414c635183
--- a/apps/contacts/templates/part.cropphoto.php
+++ b/apps/contacts/templates/part.cropphoto.php
@@ -1,7 +1,7 @@
 <?php 
 $id = $_['id'];
 $tmp_path = $_['tmp_path'];
-OC_Log::write('contacts','templates/part.cropphoto.php: tmp_path: '.$tmp_path.', exists: '.file_exists($tmp_path), OC_Log::DEBUG);
+OCP\Util::writeLog('contacts','templates/part.cropphoto.php: tmp_path: '.$tmp_path.', exists: '.file_exists($tmp_path), OCP\Util::DEBUG);
 ?>
 <script language="Javascript">
 	jQuery(function($) {
@@ -38,13 +38,13 @@ OC_Log::write('contacts','templates/part.cropphoto.php: tmp_path: '.$tmp_path.',
 		return true;
 	});*/
 </script>
-<img id="cropbox" src="<?php echo OC_Helper::linkToAbsolute('contacts', 'dynphoto.php'); ?>?tmp_path=<?php echo urlencode($tmp_path); ?>" />
+<img id="cropbox" src="<?php echo OCP\Util::linkToAbsolute('contacts', 'dynphoto.php'); ?>?tmp_path=<?php echo urlencode($tmp_path); ?>" />
 <form id="cropform"
 	class="coords"
 	method="post"
 	enctype="multipart/form-data"
 	target="crop_target"
-	action="<?php echo OC_Helper::linkToAbsolute('contacts', 'ajax/savecrop.php'); ?>">
+	action="<?php echo OCP\Util::linkToAbsolute('contacts', 'ajax/savecrop.php'); ?>">
 
 	<input type="hidden" id="id" name="id" value="<?php echo $id; ?>" />
 	<input type="hidden" id="tmp_path" name="tmp_path" value="<?php echo $tmp_path; ?>" />
diff --git a/apps/contacts/templates/part.import.php b/apps/contacts/templates/part.import.php
old mode 100644
new mode 100755
index 570eda9b07d169d71bb96840acc5d03a2d41bb4f..a2f8aefa6f447416f00da515e38089ead3ef3f6c
--- a/apps/contacts/templates/part.import.php
+++ b/apps/contacts/templates/part.import.php
@@ -6,7 +6,7 @@
 <p style="text-align:center;"><b><?php echo $l->t('Please choose the addressbook'); ?></b>
 <select style="width:100%;" id="contacts" name="contacts">
 <?php
-$contacts_options = OC_Contacts_Addressbook::all(OC_User::getUser());
+$contacts_options = OC_Contacts_Addressbook::all(OCP\USER::getUser());
 $contacts_options[] = array('id'=>'newaddressbook', 'displayname'=>$l->t('create a new addressbook'));
 echo html_select_options($contacts_options, $contacts_options[0]['id'], array('value'=>'id', 'label'=>'displayname'));
 ?>
diff --git a/apps/contacts/templates/part.importaddressbook.php b/apps/contacts/templates/part.importaddressbook.php
new file mode 100755
index 0000000000000000000000000000000000000000..9a13ba1b0cdfab2dd6947762976a6e450e817497
--- /dev/null
+++ b/apps/contacts/templates/part.importaddressbook.php
@@ -0,0 +1,34 @@
+<?php
+/**
+ * Copyright (c) 2012 Thomas Tanghus <thomas@tanghus.net>
+ * This file is licensed under the Affero General Public License version 3 or
+ * later.
+ * See the COPYING-README file.
+ */
+?>
+<td id="importaddressbook_dialog" title="<?php echo $l->t("Import Addressbook"); ?>" colspan="6">
+<table>
+<tr>
+	<th><?php echo $l->t('Select address book to import to:') ?></th>
+	<td>
+		<select id="book" name="book" class="float">
+		<?php
+		$contacts_options = OC_Contacts_Addressbook::all(OCP\USER::getUser());
+		echo html_select_options($contacts_options, $contacts_options[0]['id'], array('value'=>'id', 'label'=>'displayname'));
+		?>
+		</select>
+		<span id="import_drop_target" class="droptarget float"><?php echo $l->t("Drop a VCF file to import contacts."); ?> (Max. <?php echo  $_['uploadMaxHumanFilesize']; ?>)</span>
+		<a class="svg upload float" title="<?php echo $l->t('Select from HD'); ?>"></a>
+	</td>
+</tr>
+</table>
+<form id="import_upload_form" action="<?php echo OCP\Util::linkTo('contacts', 'ajax/uploadimport.php'); ?>" method="post" enctype="multipart/form-data" target="import_upload_target">
+<input type="hidden" name="MAX_FILE_SIZE" value="<?php echo $_['uploadMaxFilesize'] ?>" id="max_upload">
+<input id="import_upload_start" type="file" accept="text/*" name="importfile" />
+<input id="close_button" style="float: left;" type="button" onclick="Contacts.UI.Addressbooks.cancel(this);" value="<?php echo $l->t("Cancel"); ?>">
+<iframe name="import_upload_target" id='import_upload_target' src=""></iframe>
+</form>
+</td>
+<script type="text/javascript">
+Contacts.UI.Addressbooks.loadImportHandlers();
+</script>
\ No newline at end of file
diff --git a/apps/contacts/templates/part.no_contacts.php b/apps/contacts/templates/part.no_contacts.php
index 7024a142aeca20b292240d3c040343af3b186115..5faa481bc3cdc02196e0e58f731877447d0d6bc6 100644
--- a/apps/contacts/templates/part.no_contacts.php
+++ b/apps/contacts/templates/part.no_contacts.php
@@ -1,8 +1,7 @@
 <div id="firstrun">
-	<?php echo $l->t('You have no contacts in your list.') ?>
+	<?php echo $l->t('You have no contacts in your addressbook.') ?>
 	<div id="selections">
-		<input type="button" value="<?php echo $l->t('Import contacts') ?>" onclick="Contacts.UI.Addressbooks.doImport()" />
 		<input type="button" value="<?php echo $l->t('Add contact') ?>" onclick="Contacts.UI.Card.editNew()" />
-		<input type="button" value="<?php echo $l->t('Edit addressbooks') ?>" onclick="Contacts.UI.Addressbooks.overview()" />
+		<input type="button" value="<?php echo $l->t('Configure addressbooks') ?>" onclick="Contacts.UI.Addressbooks.overview()" />
 	</div>
 </div>
diff --git a/apps/contacts/templates/settings.php b/apps/contacts/templates/settings.php
old mode 100644
new mode 100755
index 5627a15c50a7894fe6669c58e2a32f4724e71e0c..af0c766d8e94e0240c3c4d17d8818245eb41977b
--- a/apps/contacts/templates/settings.php
+++ b/apps/contacts/templates/settings.php
@@ -1,12 +1,12 @@
 <form id="contacts">
 	<fieldset class="personalblock">
-		<strong><?php echo $l->t('Contacts'); ?></strong><br />
-		<?php echo $l->t('CardDAV syncing addresses:'); ?>
+		<legend><?php echo $l->t('Contacts'); ?></legend>
+		<?php echo $l->t('CardDAV syncing addresses'); ?> (<a href="http://owncloud.org/synchronisation/" target="_blank"><?php echo $l->t('more info'); ?></a>)
 		<dl>
 		<dt><?php echo $l->t('Primary address (Kontact et al)'); ?></dt>
-		<dd><code><?php echo OC_Helper::linkToAbsolute('contacts', 'carddav.php'); ?>/</code></dd>
+		<dd><code><?php echo OCP\Util::linkToAbsolute('contacts', 'carddav.php'); ?>/</code></dd>
 		<dt><?php echo $l->t('iOS/OS X'); ?></dt>
-		<dd><code><?php echo OC_Helper::linkToAbsolute('contacts', 'carddav.php'); ?>/principals/<?php echo OC_User::getUser(); ?></code>/</dd>
+		<dd><code><?php echo OCP\Util::linkToAbsolute('contacts', 'carddav.php'); ?>/principals/<?php echo OCP\USER::getUser(); ?></code>/</dd>
 		</dl>
 		Powered by <a href="http://geonames.org/" target="_blank">geonames.org webservice</a>
 	</fieldset>
diff --git a/apps/contacts/thumbnail.php b/apps/contacts/thumbnail.php
old mode 100644
new mode 100755
index 5082626499bacbd10fc33a58a19157dd4f8c7af0..11d1db03108bfc2ed4d8efd3f476794ba2735fe2
--- a/apps/contacts/thumbnail.php
+++ b/apps/contacts/thumbnail.php
@@ -21,34 +21,35 @@
  */
 
 // Init owncloud
-require_once('../../lib/base.php');
-OC_JSON::checkLoggedIn();
-//OC_Util::checkLoggedIn();
-OC_Util::checkAppEnabled('contacts');
+
+OCP\JSON::checkLoggedIn();
+//OCP\User::checkLoggedIn();
+OCP\App::checkAppEnabled('contacts');
 
 function getStandardImage(){
-	OC_Response::setExpiresHeader('P10D');
-	OC_Response::enableCaching();
-	OC_Response::redirect(OC_Helper::imagePath('contacts', 'person.png'));
+	OCP\Response::setExpiresHeader('P10D');
+	OCP\Response::enableCaching();
+	OCP\Response::redirect(OCP\Util::imagePath('contacts', 'person.png'));
 }
 
 if(!function_exists('imagecreatefromjpeg')) {
-	OC_Log::write('contacts','thumbnail.php. GD module not installed',OC_Log::DEBUG);
+	OCP\Util::writeLog('contacts','thumbnail.php. GD module not installed',OCP\Util::DEBUG);
 	getStandardImage();
 	exit();
 }
 
 $id = $_GET['id'];
+$caching = isset($_GET['refresh']) ? 0 : null;
 
 $contact = OC_Contacts_App::getContactVCard($id);
 
 // invalid vcard
 if(is_null($contact)){
-	OC_Log::write('contacts','thumbnail.php. The VCard for ID '.$id.' is not RFC compatible',OC_Log::ERROR);
+	OCP\Util::writeLog('contacts','thumbnail.php. The VCard for ID '.$id.' is not RFC compatible',OCP\Util::ERROR);
 	getStandardImage();
 	exit();
 }
-OC_Response::enableCaching();
+OCP\Response::enableCaching($caching);
 OC_Contacts_App::setLastModifiedHeader($contact);
 
 $thumbnail_size = 23;
@@ -57,7 +58,7 @@ $thumbnail_size = 23;
 $image = new OC_Image();
 $photo = $contact->getAsString('PHOTO');
 if($photo) {
-	OC_Response::setETagHeader(md5($photo));
+	OCP\Response::setETagHeader(md5($photo));
 
 	if($image->loadFromBase64($photo)) {
 		if($image->centerCrop()) {
@@ -66,16 +67,16 @@ if($photo) {
 					// done
 					exit();
 				} else {
-					OC_Log::write('contacts','thumbnail.php. Couldn\'t display thumbnail for ID '.$id,OC_Log::ERROR);
+					OCP\Util::writeLog('contacts','thumbnail.php. Couldn\'t display thumbnail for ID '.$id,OCP\Util::ERROR);
 				}
 			} else {
-				OC_Log::write('contacts','thumbnail.php. Couldn\'t resize thumbnail for ID '.$id,OC_Log::ERROR);
+				OCP\Util::writeLog('contacts','thumbnail.php. Couldn\'t resize thumbnail for ID '.$id,OCP\Util::ERROR);
 			}
 		}else{
-			OC_Log::write('contacts','thumbnail.php. Couldn\'t crop thumbnail for ID '.$id,OC_Log::ERROR);
+			OCP\Util::writeLog('contacts','thumbnail.php. Couldn\'t crop thumbnail for ID '.$id,OCP\Util::ERROR);
 		}
 	} else {
-		OC_Log::write('contacts','thumbnail.php. Couldn\'t load image string for ID '.$id,OC_Log::ERROR);
+		OCP\Util::writeLog('contacts','thumbnail.php. Couldn\'t load image string for ID '.$id,OCP\Util::ERROR);
 	}
 }
 getStandardImage();
diff --git a/apps/external/ajax/setsites.php b/apps/external/ajax/setsites.php
old mode 100644
new mode 100755
index 0537b7ea5810fb92f9252c770b2100d8390641e4..c14daa258c12f914783123b0b52d9003380d67f0
--- a/apps/external/ajax/setsites.php
+++ b/apps/external/ajax/setsites.php
@@ -6,8 +6,8 @@
  * See the COPYING-README file.
  */
 
-require_once('../../../lib/base.php');
-OC_Util::checkAdminUser();
+ 
+OCP\User::checkAdminUser();
 
 $sites = array();
 for ($i = 0; $i < sizeof($_POST['site_name']); $i++) {
@@ -19,7 +19,7 @@ for ($i = 0; $i < sizeof($_POST['site_name']); $i++) {
 if (sizeof($sites) == 0)
 	OC_Appconfig::deleteKey('external', 'sites');
 else
-	OC_Appconfig::setValue('external', 'sites', json_encode($sites));
+	OCP\Config::setAppValue('external', 'sites', json_encode($sites));
 
 echo 'true';
 ?>
diff --git a/apps/external/appinfo/app.php b/apps/external/appinfo/app.php
old mode 100644
new mode 100755
index 74e6d5c94c68c71f8f560b983804ed9260814922..b569fc305ba00fb02b2bfb879334bb47aa2271b4
--- a/apps/external/appinfo/app.php
+++ b/apps/external/appinfo/app.php
@@ -22,14 +22,14 @@
  */
 
 OC::$CLASSPATH['OC_External'] = 'apps/external/lib/external.php';
-OC_Util::addStyle( 'external', 'style');
+OCP\Util::addStyle( 'external', 'style');
 
-OC_APP::registerAdmin('external', 'settings');
+OCP\App::registerAdmin('external', 'settings');
 
-OC_App::register(array('order' => 70, 'id' => 'external', 'name' => 'External'));
+OCP\App::register(array('order' => 70, 'id' => 'external', 'name' => 'External'));
 
 $sites = OC_External::getSites();
 for ($i = 0; $i < sizeof($sites); $i++) {
-	OC_App::addNavigationEntry(
-			array('id' => 'external_index' . ($i + 1), 'order' => 80 + $i, 'href' => OC_Helper::linkTo('external', 'index.php') . '?id=' . ($i + 1), 'icon' => OC_Helper::imagePath('external', 'external.png'), 'name' => $sites[$i][0]));
-}
\ No newline at end of file
+	OCP\App::addNavigationEntry(
+			array('id' => 'external_index' . ($i + 1), 'order' => 80 + $i, 'href' => OCP\Util::linkTo('external', 'index.php') . '?id=' . ($i + 1), 'icon' => OCP\Util::imagePath('external', 'external.png'), 'name' => $sites[$i][0]));
+}
diff --git a/apps/external/appinfo/info.xml b/apps/external/appinfo/info.xml
index 05f5709916d33282bfbfd8c5149746d38e8d844c..83130f17e62761c3332e58811c48109c0b9a3e84 100644
--- a/apps/external/appinfo/info.xml
+++ b/apps/external/appinfo/info.xml
@@ -3,7 +3,6 @@
 	<id>external</id>
 	<name>External</name>
 	<description>Show external Application in the ownCloud menu</description>
-	<version>1.0</version>
 	<licence>AGPL</licence>
 	<author>Frank Karlitschek</author>
 	<require>2</require>
diff --git a/apps/external/appinfo/version b/apps/external/appinfo/version
new file mode 100644
index 0000000000000000000000000000000000000000..9f8e9b69a33f4e8067d5b21661a35d8856758aba
--- /dev/null
+++ b/apps/external/appinfo/version
@@ -0,0 +1 @@
+1.0
\ No newline at end of file
diff --git a/apps/external/index.php b/apps/external/index.php
old mode 100644
new mode 100755
index 1c20f59eaffc9b0e280e1fdef58c776f10d6d842..f1f6cbac3cf2948ca2ef8d42085e2915ad5670a2
--- a/apps/external/index.php
+++ b/apps/external/index.php
@@ -20,10 +20,10 @@
  * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
  * 
  */
-require_once('../../lib/base.php');
+
 require_once('lib/external.php');
 
-OC_Util::checkLoggedIn();
+OCP\User::checkLoggedIn();
 
 if (isset($_GET['id'])) {
 
@@ -33,7 +33,7 @@ if (isset($_GET['id'])) {
 	$sites = OC_External::getSites();
 	if (sizeof($sites) >= $id) {
 		$url = $sites[$id - 1][1];
-		OC_App::setActiveNavigationEntry('external_index' . $id);
+		OCP\App::setActiveNavigationEntry('external_index' . $id);
 
 		$tmpl = new OC_Template('external', 'frame', 'user');
 		$tmpl->assign('url', $url);
diff --git a/apps/external/lib/external.php b/apps/external/lib/external.php
old mode 100644
new mode 100755
index 9dd32321135d3030ead9cfd37f02a1b1257572d1..9fff5d5569a37b0a1bb92d5ad4865fe386cfbc99
--- a/apps/external/lib/external.php
+++ b/apps/external/lib/external.php
@@ -24,7 +24,7 @@
 class OC_External {
 
 	public static function getSites() {
-		if (($sites = json_decode(OC_Appconfig::getValue("external", "sites", ''))) != NULL) {
+		if (($sites = json_decode(OCP\Config::getAppValue("external", "sites", ''))) != NULL) {
 			return $sites;	
 		}
 
diff --git a/apps/external/settings.php b/apps/external/settings.php
old mode 100644
new mode 100755
index 416c9a5c11f13da7fc21c043cb43e17d65790ff1..c1a4242c3336dbff1f147408a1346d7b0b99f06c
--- a/apps/external/settings.php
+++ b/apps/external/settings.php
@@ -1,8 +1,8 @@
 <?php
 
-OC_Util::checkAdminUser();
+OCP\User::checkAdminUser();
 
-OC_Util::addScript( "external", "admin" );
+OCP\Util::addscript( "external", "admin" );
 
 $tmpl = new OC_Template( 'external', 'settings');
 
diff --git a/files/admin.php b/apps/files/admin.php
old mode 100644
new mode 100755
similarity index 57%
rename from files/admin.php
rename to apps/files/admin.php
index 4ae3ee512363bd3c12ddb2ac940d0c815672fca7..a59a73f0a5b2667f1b719d7a0724a8eec799f90d
--- a/files/admin.php
+++ b/apps/files/admin.php
@@ -23,38 +23,38 @@
 
 
 // Init owncloud
-require_once('../lib/base.php');
+ 
 
-OC_Util::checkAdminUser();
+OCP\User::checkAdminUser();
 
 $htaccessWorking=(getenv('htaccessWorking')=='true');
 
-$upload_max_filesize = OC_Helper::computerFileSize(ini_get('upload_max_filesize'));
-$post_max_size = OC_Helper::computerFileSize(ini_get('post_max_size'));
-$maxUploadFilesize = OC_Helper::humanFileSize(min($upload_max_filesize, $post_max_size));
+$upload_max_filesize = OCP\Util::computerFileSize(ini_get('upload_max_filesize'));
+$post_max_size = OCP\Util::computerFileSize(ini_get('post_max_size'));
+$maxUploadFilesize = OCP\Util::humanFileSize(min($upload_max_filesize, $post_max_size));
 if($_POST) {
 	if(isset($_POST['maxUploadSize'])){
-		if(($setMaxSize = OC_Files::setUploadLimit(OC_Helper::computerFileSize($_POST['maxUploadSize']))) !== false) {
-			$maxUploadFilesize = OC_Helper::humanFileSize($setMaxSize);
+		if(($setMaxSize = OC_Files::setUploadLimit(OCP\Util::computerFileSize($_POST['maxUploadSize']))) !== false) {
+			$maxUploadFilesize = OCP\Util::humanFileSize($setMaxSize);
 		}
 	}
 	if(isset($_POST['maxZipInputSize'])) {
 		$maxZipInputSize=$_POST['maxZipInputSize'];
-		OC_Config::setValue('maxZipInputSize', OC_Helper::computerFileSize($maxZipInputSize));
+		OCP\Config::setSystemValue('maxZipInputSize', OCP\Util::computerFileSize($maxZipInputSize));
 	}
 	if(isset($_POST['submitFilesAdminSettings'])) {
-		OC_Config::setValue('allowZipDownload', isset($_POST['allowZipDownload']));
+		OCP\Config::setSystemValue('allowZipDownload', isset($_POST['allowZipDownload']));
 	}
 }
-$maxZipInputSize = OC_Helper::humanFileSize(OC_Config::getValue('maxZipInputSize', OC_Helper::computerFileSize('800 MB')));
-$allowZipDownload = intval(OC_Config::getValue('allowZipDownload', true));
+$maxZipInputSize = OCP\Util::humanFileSize(OCP\Config::getSystemValue('maxZipInputSize', OCP\Util::computerFileSize('800 MB')));
+$allowZipDownload = intval(OCP\Config::getSystemValue('allowZipDownload', true));
 
-OC_App::setActiveNavigationEntry( "files_administration" );
+OCP\App::setActiveNavigationEntry( "files_administration" );
 
 $tmpl = new OC_Template( 'files', 'admin' );
 $tmpl->assign( 'htaccessWorking', $htaccessWorking );
 $tmpl->assign( 'uploadMaxFilesize', $maxUploadFilesize);
-$tmpl->assign( 'maxPossibleUploadSize', OC_Helper::humanFileSize(PHP_INT_MAX));
+$tmpl->assign( 'maxPossibleUploadSize', OCP\Util::humanFileSize(PHP_INT_MAX));
 $tmpl->assign( 'allowZipDownload', $allowZipDownload);
 $tmpl->assign( 'maxZipInputSize', $maxZipInputSize);
 return $tmpl->fetchPage();
\ No newline at end of file
diff --git a/files/ajax/autocomplete.php b/apps/files/ajax/autocomplete.php
old mode 100644
new mode 100755
similarity index 91%
rename from files/ajax/autocomplete.php
rename to apps/files/ajax/autocomplete.php
index 8d7a5b482bd490903705b1661c586d4339f2ab9b..7ff34da96b3a9421b60fbdf1ba204bf450afc84c
--- a/files/ajax/autocomplete.php
+++ b/apps/files/ajax/autocomplete.php
@@ -3,9 +3,9 @@
 
 
 // Init owncloud
-require_once('../../lib/base.php');
 
-OC_JSON::checkLoggedIn();
+
+OCP\JSON::checkLoggedIn();
 
 // Get data
 $query = $_GET['term'];
@@ -51,6 +51,6 @@ if(OC_Filesystem::file_exists($base) and OC_Filesystem::is_dir($base)){
 		}
 	}
 }
-OC_JSON::encodedPrint($files);
+OCP\JSON::encodedPrint($files);
 
 ?>
diff --git a/files/ajax/delete.php b/apps/files/ajax/delete.php
old mode 100644
new mode 100755
similarity index 63%
rename from files/ajax/delete.php
rename to apps/files/ajax/delete.php
index 1725201fdd9e4541bce45d4334c6c86be60f274b..ed155de0dc76cf5e13e17701767ffd2615a393e0
--- a/files/ajax/delete.php
+++ b/apps/files/ajax/delete.php
@@ -1,9 +1,9 @@
 <?php
 
 // Init owncloud
-require_once('../../lib/base.php');
 
-OC_JSON::checkLoggedIn();
+
+OCP\JSON::checkLoggedIn();
 
 // Get data
 $dir = stripslashes($_GET["dir"]);
@@ -21,9 +21,9 @@ foreach($files as $file) {
 }
 
 if($success) {
-	OC_JSON::success(array("data" => array( "dir" => $dir, "files" => $files )));
+	OCP\JSON::success(array("data" => array( "dir" => $dir, "files" => $files )));
 } else {
-	OC_JSON::error(array("data" => array( "message" => "Could not delete:\n" . $filesWithError )));
+	OCP\JSON::error(array("data" => array( "message" => "Could not delete:\n" . $filesWithError )));
 }
 
 ?>
diff --git a/files/ajax/download.php b/apps/files/ajax/download.php
old mode 100644
new mode 100755
similarity index 93%
rename from files/ajax/download.php
rename to apps/files/ajax/download.php
index 39852613ab95ae10dd86fd86b7e07e029dc1d7db..fd2d9b891f5676f030633787871820526086d728
--- a/files/ajax/download.php
+++ b/apps/files/ajax/download.php
@@ -25,10 +25,10 @@
 $RUNTIME_APPTYPES=array('filesystem');
 
 // Init owncloud
-require_once('../../lib/base.php');
+
 
 // Check if we are a user
-OC_Util::checkLoggedIn();
+OCP\User::checkLoggedIn();
 
 $files = $_GET["files"];
 $dir = $_GET["dir"];
diff --git a/files/ajax/list.php b/apps/files/ajax/list.php
old mode 100644
new mode 100755
similarity index 85%
rename from files/ajax/list.php
rename to apps/files/ajax/list.php
index ec9ab7342dd94df17585afc359de882816c375c0..520e54e708d9869e0966a2ab3feda971ac89ecb1
--- a/files/ajax/list.php
+++ b/apps/files/ajax/list.php
@@ -4,9 +4,9 @@
 $RUNTIME_APPTYPES=array('filesystem');
 
 // Init owncloud
-require_once('../../lib/base.php');
 
-OC_JSON::checkLoggedIn();
+
+OCP\JSON::checkLoggedIn();
 
 // Load the files
 $dir = isset( $_GET['dir'] ) ? $_GET['dir'] : '';
@@ -33,7 +33,7 @@ if($doBreadcrumb){
 // make filelist
 $files = array();
 foreach( OC_Files::getdirectorycontent( $dir ) as $i ){
-	$i["date"] = OC_Util::formatDate($i["mtime"] );
+	$i["date"] = OCP\Util::formatDate($i["mtime"] );
 	$files[] = $i;
 }
 
@@ -41,6 +41,6 @@ $list = new OC_Template( "files", "part.list", "" );
 $list->assign( "files", $files );
 $data = array('files' => $list->fetchPage());
 
-OC_JSON::success(array('data' => $data));
+OCP\JSON::success(array('data' => $data));
 
 ?>
diff --git a/files/ajax/mimeicon.php b/apps/files/ajax/mimeicon.php
similarity index 76%
rename from files/ajax/mimeicon.php
rename to apps/files/ajax/mimeicon.php
index ff72ba0f5b76af7142000c5b981a7f60dc6f6d22..57898cd82d9c09f68289284c6a8e2a19c3573244 100644
--- a/files/ajax/mimeicon.php
+++ b/apps/files/ajax/mimeicon.php
@@ -4,7 +4,7 @@
 $RUNTIME_NOAPPS=false;
 
 // Init owncloud
-require_once('../../lib/base.php');
+
 
 print OC_Helper::mimetypeIcon($_GET['mime']);
 
diff --git a/apps/files/ajax/move.php b/apps/files/ajax/move.php
new file mode 100755
index 0000000000000000000000000000000000000000..945fe4e7b82a55ad4080bc801e195328a68408b3
--- /dev/null
+++ b/apps/files/ajax/move.php
@@ -0,0 +1,20 @@
+<?php
+
+// Init owncloud
+
+
+OCP\JSON::checkLoggedIn();
+
+// Get data
+$dir = stripslashes($_GET["dir"]);
+$file = stripslashes($_GET["file"]);
+$target = stripslashes($_GET["target"]);
+
+
+if(OC_Files::move($dir,$file,$target,$file)){
+	OCP\JSON::success(array("data" => array( "dir" => $dir, "files" => $file )));
+}else{
+	OCP\JSON::error(array("data" => array( "message" => "Could not move $file" )));
+}
+
+?>
diff --git a/files/ajax/newfile.php b/apps/files/ajax/newfile.php
old mode 100644
new mode 100755
similarity index 60%
rename from files/ajax/newfile.php
rename to apps/files/ajax/newfile.php
index 2d1372f06ee5fb8d40c57233fd6b964d9a9d6d5e..2712b54f063378f081dd6ec183f92f63628cf552
--- a/files/ajax/newfile.php
+++ b/apps/files/ajax/newfile.php
@@ -1,9 +1,9 @@
 <?php
 
 // Init owncloud
-require_once('../../lib/base.php');
 
-OC_JSON::checkLoggedIn();
+
+OCP\JSON::checkLoggedIn();
 
 // Get the params
 $dir = isset( $_POST['dir'] ) ? stripslashes($_POST['dir']) : '';
@@ -12,13 +12,13 @@ $content = isset( $_POST['content'] ) ? $_POST['content'] : '';
 $source = isset( $_POST['source'] ) ? stripslashes($_POST['source']) : '';
 
 if($filename == '') {
-	OC_JSON::error(array("data" => array( "message" => "Empty Filename" )));
+	OCP\JSON::error(array("data" => array( "message" => "Empty Filename" )));
 	exit();
 }
 
 if($source){
 	if(substr($source,0,8)!='https://' and substr($source,0,7)!='http://'){
-		OC_JSON::error(array("data" => array( "message" => "Not a valid source" )));
+		OCP\JSON::error(array("data" => array( "message" => "Not a valid source" )));
 		exit();
 	}
 	$sourceStream=fopen($source,'rb');
@@ -26,10 +26,10 @@ if($source){
 	$result=OC_Filesystem::file_put_contents($target,$sourceStream);
 	if($result){
 		$mime=OC_Filesystem::getMimetype($target);
-		OC_JSON::success(array("data" => array('mime'=>$mime)));
+		OCP\JSON::success(array("data" => array('mime'=>$mime)));
 		exit();
 	}else{
-		OC_JSON::error(array("data" => array( "message" => "Error while downloading ".$source. ' to '.$target )));
+		OCP\JSON::error(array("data" => array( "message" => "Error while downloading ".$source. ' to '.$target )));
 		exit();
 	}
 }
@@ -39,9 +39,9 @@ if(OC_Files::newFile($dir, $filename, 'file')) {
 	if($content){
 		OC_Filesystem::file_put_contents($dir.'/'.$filename,$content);
 	}
-	OC_JSON::success(array("data" => array('content'=>$content)));
+	OCP\JSON::success(array("data" => array('content'=>$content)));
 	exit();
 }
 
 
-OC_JSON::error(array("data" => array( "message" => "Error when creating the file" )));
+OCP\JSON::error(array("data" => array( "message" => "Error when creating the file" )));
diff --git a/files/ajax/newfolder.php b/apps/files/ajax/newfolder.php
old mode 100644
new mode 100755
similarity index 53%
rename from files/ajax/newfolder.php
rename to apps/files/ajax/newfolder.php
index 228e369fbef95c336dfd6426470a9a0951f2bbb9..512e0e1f6d99696dcbe288dfac2bc787ce87d48e
--- a/files/ajax/newfolder.php
+++ b/apps/files/ajax/newfolder.php
@@ -1,22 +1,22 @@
 <?php
 
 // Init owncloud
-require_once('../../lib/base.php');
 
-OC_JSON::checkLoggedIn();
+
+OCP\JSON::checkLoggedIn();
 
 // Get the params
 $dir = isset( $_POST['dir'] ) ? stripslashes($_POST['dir']) : '';
 $foldername = isset( $_POST['foldername'] ) ? stripslashes($_POST['foldername']) : '';
 
 if(trim($foldername) == '') {
-	OC_JSON::error(array("data" => array( "message" => "Empty Foldername" )));
+	OCP\JSON::error(array("data" => array( "message" => "Empty Foldername" )));
 	exit();
 }
 
 if(OC_Files::newFile($dir, stripslashes($foldername), 'dir')) {
-	OC_JSON::success(array("data" => array()));
+	OCP\JSON::success(array("data" => array()));
 	exit();
 }
 
-OC_JSON::error(array("data" => array( "message" => "Error when creating the folder" )));
+OCP\JSON::error(array("data" => array( "message" => "Error when creating the folder" )));
diff --git a/files/ajax/rawlist.php b/apps/files/ajax/rawlist.php
old mode 100644
new mode 100755
similarity index 69%
rename from files/ajax/rawlist.php
rename to apps/files/ajax/rawlist.php
index e02c5b6273342930cbb70695cc23f8931e48c50d..36dd35cc73e86d4b196798092cd5615d450653de
--- a/files/ajax/rawlist.php
+++ b/apps/files/ajax/rawlist.php
@@ -4,10 +4,10 @@
 $RUNTIME_APPTYPES=array('filesystem');
 
 // Init owncloud
-require_once('../../lib/base.php');
-require_once('../../lib/template.php');
 
-OC_JSON::checkLoggedIn();
+require_once('lib/template.php');
+
+OCP\JSON::checkLoggedIn();
 
 // Load the files
 $dir = isset( $_GET['dir'] ) ? $_GET['dir'] : '';
@@ -16,11 +16,11 @@ $mimetype = isset($_GET['mimetype']) ? $_GET['mimetype'] : '';
 // make filelist
 $files = array();
 foreach( OC_Files::getdirectorycontent( $dir, $mimetype ) as $i ){
-	$i["date"] = OC_Util::formatDate($i["mtime"] );
+	$i["date"] = OCP\Util::formatDate($i["mtime"] );
   $i['mimetype_icon'] = $i['type'] == 'dir' ? mimetype_icon('dir'): mimetype_icon($i['mimetype']);
 	$files[] = $i;
 }
 
-OC_JSON::success(array('data' => $files));
+OCP\JSON::success(array('data' => $files));
 
 ?>
diff --git a/apps/files/ajax/rename.php b/apps/files/ajax/rename.php
new file mode 100755
index 0000000000000000000000000000000000000000..e2fa3d54a61aad43feab0b0054e9c5125f6e705b
--- /dev/null
+++ b/apps/files/ajax/rename.php
@@ -0,0 +1,21 @@
+<?php
+
+// Init owncloud
+
+
+OCP\JSON::checkLoggedIn();
+
+// Get data
+$dir = stripslashes($_GET["dir"]);
+$file = stripslashes($_GET["file"]);
+$newname = stripslashes($_GET["newname"]);
+
+// Delete
+if( OC_Files::move( $dir, $file, $dir, $newname )) {
+	OCP\JSON::success(array("data" => array( "dir" => $dir, "file" => $file, "newname" => $newname )));
+}
+else{
+	OCP\JSON::error(array("data" => array( "message" => "Unable to rename file" )));
+}
+
+?>
diff --git a/files/ajax/scan.php b/apps/files/ajax/scan.php
old mode 100644
new mode 100755
similarity index 69%
rename from files/ajax/scan.php
rename to apps/files/ajax/scan.php
index db09b7d5c642a6a829d6c5752aa864ef86735270..d695ce816171b8ee7460b2272804c91f6cfd9d7e
--- a/files/ajax/scan.php
+++ b/apps/files/ajax/scan.php
@@ -1,10 +1,9 @@
 <?php
 
-require_once '../../lib/base.php';
-
 set_time_limit(0);//scanning can take ages
 
 $force=isset($_GET['force']) and $_GET['force']=='true';
+$dir=isset($_GET['dir'])?$_GET['dir']:'';
 $checkOnly=isset($_GET['checkonly']) and $_GET['checkonly']=='true';
 
 if(!$checkOnly){
@@ -15,18 +14,18 @@ if(!$checkOnly){
 //create the file cache if necesary
 if($force or !OC_FileCache::inCache('')){
 	if(!$checkOnly){
-		OC_DB::beginTransaction();
-		OC_FileCache::scan('',$eventSource);
+		OCP\DB::beginTransaction();
+		OC_FileCache::scan($dir,$eventSource);
 		OC_FileCache::clean();
-		OC_DB::commit();
+		OCP\DB::commit();
 		$eventSource->send('success',true);
 	}else{
-		OC_JSON::success(array('data'=>array('done'=>true)));
+		OCP\JSON::success(array('data'=>array('done'=>true)));
 		exit;
 	}
 }else{
 	if($checkOnly){
-		OC_JSON::success(array('data'=>array('done'=>false)));
+		OCP\JSON::success(array('data'=>array('done'=>false)));
 		exit;
 	}
 	if(isset($eventSource)){
diff --git a/files/ajax/timezone.php b/apps/files/ajax/timezone.php
similarity index 100%
rename from files/ajax/timezone.php
rename to apps/files/ajax/timezone.php
diff --git a/files/ajax/upload.php b/apps/files/ajax/upload.php
old mode 100644
new mode 100755
similarity index 69%
rename from files/ajax/upload.php
rename to apps/files/ajax/upload.php
index f8b8f0e2e5fcda79ef0f557390736b85d99cfa3b..d6c799af32c76e8069edea19d3dfaa863eebde22
--- a/files/ajax/upload.php
+++ b/apps/files/ajax/upload.php
@@ -1,20 +1,20 @@
 <?php
 
 // Init owncloud
-require_once('../../lib/base.php');
+
 
 // Firefox and Konqueror tries to download application/json for me.  --Arthur
-OC_JSON::setContentTypeHeader('text/plain');
+OCP\JSON::setContentTypeHeader('text/plain');
 
-OC_JSON::checkLoggedIn();
+OCP\JSON::checkLoggedIn();
 
 if (!isset($_FILES['files'])) {
-	OC_JSON::error(array("data" => array( "message" => "No file was uploaded. Unknown error" )));
+	OCP\JSON::error(array("data" => array( "message" => "No file was uploaded. Unknown error" )));
 	exit();
 }
 foreach ($_FILES['files']['error'] as $error) {
 	if ($error != 0) {
-		$l=new OC_L10N('files');
+		$l=OC_L10N::get('files');
 		$errors = array(
 			UPLOAD_ERR_OK=>$l->t("There is no error, the file uploaded with success"),
 			UPLOAD_ERR_INI_SIZE=>$l->t("The uploaded file exceeds the upload_max_filesize directive in php.ini").ini_get('upload_max_filesize'),
@@ -24,14 +24,13 @@ foreach ($_FILES['files']['error'] as $error) {
 			UPLOAD_ERR_NO_TMP_DIR=>$l->t("Missing a temporary folder"),
 			UPLOAD_ERR_CANT_WRITE=>$l->t('Failed to write to disk'),
 		);
-		OC_JSON::error(array("data" => array( "message" => $errors[$error] )));
+		OCP\JSON::error(array("data" => array( "message" => $errors[$error] )));
 		exit();
 	}
 }
 $files=$_FILES['files'];
 
 $dir = $_POST['dir'];
-$dir .= '/';
 $error='';
 
 $totalSize=0;
@@ -39,7 +38,7 @@ foreach($files['size'] as $size){
 	$totalSize+=$size;
 }
 if($totalSize>OC_Filesystem::free_space('/')){
-	OC_JSON::error(array("data" => array( "message" => "Not enough space available" )));
+	OCP\JSON::error(array("data" => array( "message" => "Not enough space available" )));
 	exit();
 }
 
@@ -47,18 +46,18 @@ $result=array();
 if(strpos($dir,'..') === false){
 	$fileCount=count($files['name']);
 	for($i=0;$i<$fileCount;$i++){
-		$target=stripslashes($dir) . $files['name'][$i];
+        $target = OCP\Files::buildNotExistingFileName(stripslashes($dir), $files['name'][$i]);
 		if(is_uploaded_file($files['tmp_name'][$i]) and OC_Filesystem::fromTmpFile($files['tmp_name'][$i],$target)){
 			$meta=OC_FileCache::getCached($target);
-			$result[]=array( "status" => "success", 'mime'=>$meta['mimetype'],'size'=>$meta['size'],'name'=>$files['name'][$i]);
+			$result[]=array( "status" => "success", 'mime'=>$meta['mimetype'],'size'=>$meta['size'],'name'=>basename($target));
 		}
 	}
-	OC_JSON::encodedPrint($result);
+	OCP\JSON::encodedPrint($result);
 	exit();
 }else{
 	$error='invalid dir';
 }
 
-OC_JSON::error(array('data' => array('error' => $error, "file" => $fileName)));
+OCP\JSON::error(array('data' => array('error' => $error, "file" => $fileName)));
 
 ?>
diff --git a/apps/files/appinfo/app.php b/apps/files/appinfo/app.php
new file mode 100755
index 0000000000000000000000000000000000000000..355b77d5e7e3beeb9a2886c5fea9f9c10be780e5
--- /dev/null
+++ b/apps/files/appinfo/app.php
@@ -0,0 +1,11 @@
+<?php
+
+
+$l=OC_L10N::get('files');
+
+OCP\App::register( array( "order" => 2, "id" => "files", "name" => "Files" ));
+OCP\App::registerAdmin('files','admin');
+
+OCP\App::addNavigationEntry( array( "id" => "files_index", "order" => 0, "href" => OCP\Util::linkTo( "files", "index.php" ), "icon" => OCP\Util::imagePath( "core", "places/home.svg" ), "name" => $l->t("Files") ));
+
+OC_Search::registerProvider('OC_Search_Provider_File');
diff --git a/apps/files/appinfo/info.xml b/apps/files/appinfo/info.xml
new file mode 100644
index 0000000000000000000000000000000000000000..2abf54e7da658106a60712a89c13c9495ad15c19
--- /dev/null
+++ b/apps/files/appinfo/info.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0"?>
+<info>
+	<id>files</id>
+	<name>Files</name>
+	<description>File Management</description>
+	<licence>AGPL</licence>
+	<author>Robin Appelman</author>
+	<require>2</require>
+	<default_enable/>
+</info>
diff --git a/apps/files/appinfo/install.php b/apps/files/appinfo/install.php
new file mode 100644
index 0000000000000000000000000000000000000000..8c1430900ae9e60e8a0b92315b2a96bcc1d76478
--- /dev/null
+++ b/apps/files/appinfo/install.php
@@ -0,0 +1,4 @@
+<?php
+if(!file_exists(OC::$WEBROOT.'/remote/webdav.php')){
+	file_put_contents(OC::$WEBROOT.'/remote/webdav.php', file_get_contents(OC::$APPSROOT . '/apps/files/appinfo/webdav.php'));
+}
diff --git a/apps/files/appinfo/remote.php b/apps/files/appinfo/remote.php
new file mode 100644
index 0000000000000000000000000000000000000000..3ac0023fb848faa41fdd027e780fc077269d5c2e
--- /dev/null
+++ b/apps/files/appinfo/remote.php
@@ -0,0 +1,52 @@
+<?php
+
+/**
+ * ownCloud
+ *
+ * @author Frank Karlitschek
+ * @author Jakob Sack
+ * @copyright 2010 Frank Karlitschek karlitschek@kde.org
+ * @copyright 2011 Jakob Sack kde@jakobsack.de
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or any later version.
+ *
+ * This library 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 AFFERO GENERAL PUBLIC LICENSE for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public
+ * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+// Do not load FS ...
+$RUNTIME_NOSETUPFS = true;
+require_once('../lib/base.php');
+
+// only need filesystem apps
+$RUNTIME_APPTYPES=array('filesystem','authentication');
+
+ 
+
+// Backends
+$authBackend = new OC_Connector_Sabre_Auth();
+$lockBackend = new OC_Connector_Sabre_Locks();
+
+// Create ownCloud Dir
+$publicDir = new OC_Connector_Sabre_Directory('');
+
+// Fire up server
+$server = new Sabre_DAV_Server($publicDir);
+$server->setBaseUri(OC::$WEBROOT.'/remote/webdav.php');
+
+// Load plugins
+$server->addPlugin(new Sabre_DAV_Auth_Plugin($authBackend,'ownCloud'));
+$server->addPlugin(new Sabre_DAV_Locks_Plugin($lockBackend));
+$server->addPlugin(new Sabre_DAV_Browser_Plugin(false)); // Show something in the Browser, but no upload
+
+// And off we go!
+$server->exec();
diff --git a/apps/files/appinfo/update.php b/apps/files/appinfo/update.php
new file mode 100644
index 0000000000000000000000000000000000000000..d00a1a321eb676edcef12f32e2e779dae44b0205
--- /dev/null
+++ b/apps/files/appinfo/update.php
@@ -0,0 +1,4 @@
+<?php
+if(!file_exists(OC::$WEBROOT.'/remote/webdav.php')){
+	file_put_contents(OC::$WEBROOT.'/remote/webdav.php', file_get_contents(OC::$APPROOT . '/apps/files/appinfo/webdav.php'));
+}
\ No newline at end of file
diff --git a/apps/files/appinfo/version b/apps/files/appinfo/version
new file mode 100644
index 0000000000000000000000000000000000000000..9f8e9b69a33f4e8067d5b21661a35d8856758aba
--- /dev/null
+++ b/apps/files/appinfo/version
@@ -0,0 +1 @@
+1.0
\ No newline at end of file
diff --git a/files/css/files.css b/apps/files/css/files.css
similarity index 59%
rename from files/css/files.css
rename to apps/files/css/files.css
index 9e950517b82ff279ce6b7b7196431bebbca46725..9df49ad471180ee0934d85e1d2fef1f9b274d7a1 100644
--- a/files/css/files.css
+++ b/apps/files/css/files.css
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, Jan-Christoph Borchardt
+/* Copyright (c) 2011, Jan-Christoph Borchardt, http://jancborchardt.net
  This file is licensed under the Affero General Public License version 3 or later.
  See the COPYING-README file. */
 
@@ -20,29 +20,32 @@
 #new>ul>li>p { cursor:pointer; }
 #new>ul>li>input { padding:0.3em; margin:-0.3em; }
 
-#file_newfolder_name { background-image:url('../../core/img/places/folder.svg'); font-weight:normal; width:7em; }
+#file_newfolder_name { background-image:url('%webroot%/core/img/places/folder.svg'); font-weight:normal; width:7em; }
 .file_upload_start, .file_upload_filename { font-size:1em; }
 #file_newfolder_submit, #file_upload_submit { width:3em; }
 .file_upload_target { display:none; }
 
-.file_upload_start { opacity:0; filter:alpha(opacity=0); z-index:1; position:absolute; left:0; top:0; width:100%; cursor:pointer;}
+.file_upload_start { -ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=0)"; filter:alpha(opacity=0); opacity:0; z-index:1; position:absolute; left:0; top:0; width:100%; cursor:pointer;}
 .file_upload_filename.active { border-bottom-right-radius:0 }
 .file_upload_filename { position: relative; z-index:100; padding-left: 0.8em; padding-right: 0.8em; cursor:pointer; border-top-left-radius:0; border-bottom-left-radius:0; }
-.file_upload_filename img { position: absolute; top: 0.4em; left: 0.4em; }
+.file_upload_filename img { position: absolute; top: 0.4em; left: 0.4em; -ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=100)"; filter:alpha(opacity=100); opacity:1; }
 
+#upload { position:absolute; right:13.5em; top:0em; }
+#upload #uploadprogressbar { position:relative; display:inline-block; width:10em; height:1.5em; top:.4em; }
 
 .file_upload_form, .file_upload_wrapper, .file_upload_start, .file_upload_filename, #file_upload_submit { cursor:pointer; }
 
 /* FILE TABLE */
 #emptyfolder { position:absolute; margin:10em 0 0 10em; font-size:1.5em; font-weight:bold; color:#888; text-shadow:#fff 0 1px 0; }
+.emptyfolder #new, .emptyfolder .file_upload_filename { background:#66f866; border:1px solid #5e5; -moz-box-shadow:0 1px 1px #f8f8f8, 0 1px 1px #cfc inset; -webkit-box-shadow:0 1px 1px #f8f8f8, 0 1px 1px #cfc inset; box-shadow:0 1px 1px #f8f8f8, 0 1px 1px #cfc inset; }
 table { position:relative; top:37px; width:100%; }
-tbody tr:hover, tbody tr:active, tbody tr.selected { background-color:#f8f8f8; height:1em; }
-tbody tr { background-color:#fff; }
+tbody tr { background-color:#fff; height:2.5em; }
+tbody tr:hover, tbody tr:active, tbody tr.selected { background-color:#f8f8f8; }
 tbody tr.selected { background-color:#eee; }
 tbody a { color:#000; }
-span.extention, td.date { color:#999; }
-span.extention { opacity:0; -webkit-transition:opacity 500ms; -moz-transition:opacity 500ms; -o-transition:opacity 500ms; transition:opacity 500ms; }
-tr:hover span.extention { opacity:1; }
+span.extension, span.uploading, td.date { color:#999; }
+span.extension { text-transform:lowercase; -ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=70)"; filter:alpha(opacity=70); opacity:.7; -webkit-transition:opacity 300ms; -moz-transition:opacity 300ms; -o-transition:opacity 300ms; transition:opacity 300ms; }
+tr:hover span.extension { -ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=100)"; filter:alpha(opacity=100); opacity:1; color:#777; }
 div.crumb { float:left; display:block; background:no-repeat right 0; padding:.75em 1.5em 0 1em; height:2.9em; }
 div.crumb:first-child { padding-left:1em; }
 div.crumb.last { font-weight:bold; }
@@ -56,26 +59,33 @@ table th#headerSize, table td.filesize { width:3em; padding:0 1em; text-align:ri
 table th#headerDate, table td.date { width:11em; padding:0 .1em 0 1em; text-align:left; }
 table td.selection, table th.selection, table td.fileaction { width:2em; text-align:center; }
 table td.filename a.name { display:block; height:1.5em; vertical-align:middle; margin-left:3em; }
-table tr[data-type="dir"] td.filename a.name {font-weight:bold; }
+table tr[data-type="dir"] td.filename a.name span.nametext {font-weight:bold; }
 table td.filename a.name input, table td.filename a.name form { width:100%; cursor:text; }
 table td.filename a, table td.login, table td.logout, table td.download, table td.upload, table td.create, table td.delete { padding:.2em .5em .5em 0; }
-table td.filename .nametext, .modified { float:left; padding:.3em 0; }
-table td.filename .nametext { width:60%; }
+table td.filename .nametext, .uploadtext, .modified { float:left; padding:.3em 0; }
+// TODO fix usability bug (accidental file/folder selection)
+table td.filename .nametext { width:40em; overflow:hidden; text-overflow:ellipsis; }
+table td.filename .uploadtext { font-weight:normal; margin-left:.5em; }
 table td.filename form { float:left; font-size:.85em; }
 table thead.fixed tr{ position:fixed; top:6.5em; z-index:49; -moz-box-shadow:0 -3px 7px #ddd; -webkit-box-shadow:0 -3px 7px #ddd; box-shadow:0 -3px 7px #ddd; }
 table thead.fixed { height:2em; }
-#fileList tr td.filename>input[type=checkbox]:first-child { opacity:0; -ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=0)"; float:left; margin:.7em 0 0 1em; /* bigger clickable area doesn’t work in FF width:2.8em; height:2.4em;*/ -webkit-transition:opacity 500ms; -moz-transition:opacity 500ms; -o-transition:opacity 500ms; transition:opacity 500ms; }
-#fileList tr td.filename>input[type="checkbox"]:hover:first-child { opacity:.8; -ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=80)"; }
-#fileList tr td.filename>input[type="checkbox"]:checked:first-child { opacity:1; }
+#fileList tr td.filename>input[type=checkbox]:first-child { -ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=0)"; filter:alpha(opacity=0); opacity:0; float:left; margin:.7em 0 0 1em; /* bigger clickable area doesn’t work in FF width:2.8em; height:2.4em;*/ -webkit-transition:opacity 200ms; -moz-transition:opacity 200ms; -o-transition:opacity 200ms; transition:opacity 200ms; }
+#fileList tr td.filename>input[type="checkbox"]:hover:first-child { -ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=80)"; filter:alpha(opacity=80); opacity:.8; }
+#fileList tr td.filename>input[type="checkbox"]:checked:first-child { -ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=100)"; filter:alpha(opacity=100); opacity:1; }
 #fileList tr td.filename { -webkit-transition:background-image 500ms; -moz-transition:background-image 500ms; -o-transition:background-image 500ms; transition:background-image 500ms; }
 #select_all { float:left; margin:.3em 0.6em 0 .5em; }
 #uploadsize-message,#delete-confirm { display:none; }
-.selectedActions a,#fileList a.action { float:right; display:inline; margin:0 .5em; padding:.3em .3em 0 .3em !important; }
-a.action>img{ max-height:16px; max-width:16px; }
-.selectedActions { display:none; }
+.fileactions { position:relative; top:.3em; font-size:.8em; float:right; }
+#fileList .fileactions a.action img { position:relative; top:.2em; }
+#fileList a.action { display:inline; margin:-.5em 0; padding:1em .5em 1em .5em !important; }
+a.action.delete { float:right; }
+a.action>img { max-height:16px; max-width:16px; vertical-align:text-bottom; }
+.selectedActions { display:none; float:right; }
+.selectedActions a { display:inline; margin:-.5em 0; padding:.5em !important; }
+.selectedActions a img { position:relative; top:.3em; }
 
 /* add breadcrumb divider to the File item in navigation panel */
-#navigation>ul>li:first-child { background:url('../../core/img/breadcrumb-start.svg') no-repeat 12.5em 0px; width:12.5em; padding-right:1em; position:fixed; }
+#navigation>ul>li:first-child { background:url('%webroot%/core/img/breadcrumb-start.svg') no-repeat 12.5em 0px; width:12.5em; padding-right:1em; position:fixed; }
 #navigation>ul>li:first-child+li { padding-top:2.9em; }
 
-#scanning-message{ top:40%; left:40%; position:absolute; display:none }
+#scanning-message{ top:40%; left:40%; position:absolute; display:none; }
diff --git a/files/download.php b/apps/files/download.php
old mode 100644
new mode 100755
similarity index 93%
rename from files/download.php
rename to apps/files/download.php
index d1f5ba486d7eaed89341f15cf94edd249d81593f..e98cf2ecd312037b13c839e0512ae3d0e3cfa2bf
--- a/files/download.php
+++ b/apps/files/download.php
@@ -22,10 +22,10 @@
 */
 
 // Init owncloud
-require_once('../lib/base.php');
+ 
 
 // Check if we are a user
-OC_Util::checkLoggedIn();
+OCP\User::checkLoggedIn();
 
 $filename = $_GET["file"];
 
@@ -41,7 +41,7 @@ $ftype=OC_Filesystem::getMimeType( $filename );
 
 header('Content-Type:'.$ftype);
 header('Content-Disposition: attachment; filename="'.basename($filename).'"');
-OC_Response::disableCaching();
+OCP\Response::disableCaching();
 header('Content-Length: '.OC_Filesystem::filesize($filename));
 
 @ob_end_clean();
diff --git a/files/index.php b/apps/files/index.php
old mode 100644
new mode 100755
similarity index 68%
rename from files/index.php
rename to apps/files/index.php
index 82d09608924c821e6111210cfc2692cb2cbd5671..e2a0eb80a03e9b4751dee1e6130aaf2237220431
--- a/files/index.php
+++ b/apps/files/index.php
@@ -21,22 +21,20 @@
 *
 */
 
-
-// Init owncloud
-require_once('../lib/base.php');
-
 // Check if we are a user
-OC_Util::checkLoggedIn();
+OCP\User::checkLoggedIn();
 
 // Load the files we need
-OC_Util::addStyle( "files", "files" );
-OC_Util::addScript( "files", "files" );
-OC_Util::addScript( 'files', 'filelist' );
-OC_Util::addScript( 'files', 'fileactions' );
+OCP\Util::addStyle( "files", "files" );
+OCP\Util::addscript( "files", "jquery.iframe-transport" );
+OCP\Util::addscript( "files", "jquery.fileupload" );
+OCP\Util::addscript( "files", "files" );
+OCP\Util::addscript( 'files', 'filelist' );
+OCP\Util::addscript( 'files', 'fileactions' );
 if(!isset($_SESSION['timezone'])){
-	OC_Util::addScript( 'files', 'timezone' );
+	OCP\Util::addscript( 'files', 'timezone' );
 }
-OC_App::setActiveNavigationEntry( "files_index" );
+OCP\App::setActiveNavigationEntry( "files_index" );
 // Load the files
 $dir = isset( $_GET['dir'] ) ? stripslashes($_GET['dir']) : '';
 // Redirect if directory does not exist
@@ -46,15 +44,15 @@ if(!OC_Filesystem::is_dir($dir.'/')) {
 
 $files = array();
 foreach( OC_Files::getdirectorycontent( $dir ) as $i ){
-	$i["date"] = OC_Util::formatDate($i["mtime"] );
+	$i["date"] = OCP\Util::formatDate($i["mtime"] );
 	if($i['type']=='file'){
 		$fileinfo=pathinfo($i['name']);
 		$i['basename']=$fileinfo['filename'];
 		if (!empty($fileinfo['extension'])) {
-			$i['extention']='.' . $fileinfo['extension'];
+			$i['extension']='.' . $fileinfo['extension'];
 		}
 		else {
-			$i['extention']='';
+			$i['extension']='';
 		}
 	}
 	if($i['directory']=='/'){
@@ -76,14 +74,14 @@ foreach( explode( "/", $dir ) as $i ){
 // make breadcrumb und filelist markup
 $list = new OC_Template( "files", "part.list", "" );
 $list->assign( "files", $files );
-$list->assign( "baseURL", OC_Helper::linkTo("files", "index.php")."?dir=");
-$list->assign( "downloadURL", OC_Helper::linkTo("files", "download.php")."?file=");
+$list->assign( "baseURL", OCP\Util::linkTo("files", "index.php")."?dir=");
+$list->assign( "downloadURL", OCP\Util::linkTo("files", "download.php")."?file=");
 $breadcrumbNav = new OC_Template( "files", "part.breadcrumb", "" );
 $breadcrumbNav->assign( "breadcrumb", $breadcrumb );
-$breadcrumbNav->assign( "baseURL", OC_Helper::linkTo("files", "index.php")."?dir=");
+$breadcrumbNav->assign( "baseURL", OCP\Util::linkTo("files", "index.php")."?dir=");
 
-$upload_max_filesize = OC_Helper::computerFileSize(ini_get('upload_max_filesize'));
-$post_max_size = OC_Helper::computerFileSize(ini_get('post_max_size'));
+$upload_max_filesize = OCP\Util::computerFileSize(ini_get('upload_max_filesize'));
+$post_max_size = OCP\Util::computerFileSize(ini_get('post_max_size'));
 $maxUploadFilesize = min($upload_max_filesize, $post_max_size);
 
 $freeSpace=OC_Filesystem::free_space('/');
@@ -97,8 +95,8 @@ $tmpl->assign( 'dir', $dir);
 $tmpl->assign( 'readonly', !OC_Filesystem::is_writable($dir));
 $tmpl->assign( "files", $files );
 $tmpl->assign( 'uploadMaxFilesize', $maxUploadFilesize);
-$tmpl->assign( 'uploadMaxHumanFilesize', OC_Helper::humanFileSize($maxUploadFilesize));
-$tmpl->assign( 'allowZipDownload', intval(OC_Config::getValue('allowZipDownload', true)));
+$tmpl->assign( 'uploadMaxHumanFilesize', OCP\Util::humanFileSize($maxUploadFilesize));
+$tmpl->assign( 'allowZipDownload', intval(OCP\Config::getSystemValue('allowZipDownload', true)));
 $tmpl->printPage();
 
 ?>
diff --git a/files/js/admin.js b/apps/files/js/admin.js
similarity index 100%
rename from files/js/admin.js
rename to apps/files/js/admin.js
diff --git a/files/js/fileactions.js b/apps/files/js/fileactions.js
similarity index 81%
rename from files/js/fileactions.js
rename to apps/files/js/fileactions.js
index 60c4fadedd0d2e9106a7391528d0fc4b9d3edeb2..68268a7d3a9ce0e8dd2a8870a6d4e915d7aaf365 100644
--- a/files/js/fileactions.js
+++ b/apps/files/js/fileactions.js
@@ -53,12 +53,13 @@ FileActions={
 	},
 	display:function(parent){
 		FileActions.currentFile=parent;
-		$('#fileList .action').remove();
+		$('#fileList span.fileactions, #fileList td.date a.action').remove();
 		var actions=FileActions.get(FileActions.getCurrentMimeType(),FileActions.getCurrentType());
 		var file=FileActions.getCurrentFile();
 		if($('tr').filterAttr('data-file',file).data('renaming')){
 			return;
 		}
+		parent.children('a.name').append('<span class="fileactions" />');
 		var defaultAction=FileActions.getDefault(FileActions.getCurrentMimeType(),FileActions.getCurrentType());
 		for(name in actions){
 			if((name=='Download' || actions[name]!=defaultAction) && name!='Delete'){
@@ -66,11 +67,10 @@ FileActions={
 				if(img.call){
 					img=img(file);
 				}
-				var html='<a href="#" original-title="'+name+'" class="action" style="display:none" />';
+				var html='<a href="#" class="action" style="display:none">';
+				if(img) { html+='<img src="'+img+'"/> '; }
+				html += name+'</a>';
 				var element=$(html);
-				if(img){
-					element.append($('<img src="'+img+'"/>'));
-				}
 				element.data('action',name);
 				element.click(function(event){
 					event.stopPropagation();
@@ -81,7 +81,7 @@ FileActions={
 					action(currentFile);
 				});
 				element.hide();
-				parent.children('a.name').append(element);
+				parent.find('a.name>span.fileactions').append(element);
 			}
 		}
 		if(actions['Delete']){
@@ -113,7 +113,7 @@ FileActions={
 		return false;
 	},
 	hide:function(){
-		$('#fileList .action').fadeOut(200,function(){
+		$('#fileList span.fileactions, #fileList td.date a.action').fadeOut(200,function(){
 			$(this).remove();
 		});
 	},
@@ -135,12 +135,25 @@ $(document).ready(function(){
 		var downloadScope = 'file';
 	}
 	FileActions.register(downloadScope,'Download',function(){return OC.imagePath('core','actions/download')},function(filename){
-		window.location='ajax/download.php?files='+encodeURIComponent(filename)+'&dir='+encodeURIComponent($('#dir').val());
+		window.location=OC.filePath('files', 'ajax', 'download.php') + '?files='+encodeURIComponent(filename)+'&dir='+encodeURIComponent($('#dir').val());
 	});
 });
 
 FileActions.register('all','Delete',function(){return OC.imagePath('core','actions/delete')},function(filename){
-	FileList.do_delete(filename);
+	if(Files.cancelUpload(filename)) {
+		if(filename.substr){
+			filename=[filename];
+		}
+		$.each(filename,function(index,file){
+			var filename = $('tr').filterAttr('data-file',file);
+			filename.hide();
+			filename.find('input[type="checkbox"]').removeAttr('checked');
+			filename.removeClass('selected');
+		});
+		procesSelection();
+	}else{
+		FileList.do_delete(filename);
+	}
 });
 
 FileActions.register('all','Rename',function(){return OC.imagePath('core','actions/rename')},function(filename){
diff --git a/files/js/filelist.js b/apps/files/js/filelist.js
similarity index 93%
rename from files/js/filelist.js
rename to apps/files/js/filelist.js
index 35847e06dfea783a56fb591820e5ae8d0ffe1afa..31fb5f892e44424f95135ef7e4b3de5b7d74b06f 100644
--- a/files/js/filelist.js
+++ b/apps/files/js/filelist.js
@@ -1,4 +1,5 @@
 FileList={
+	useUndo:true,
 	update:function(fileListHtml) {
 		$('#fileList').empty().html(fileListHtml);
 	},
@@ -7,15 +8,15 @@ FileList={
 		var html='<tr data-type="file" data-size="'+size+'">';
 		if(name.indexOf('.')!=-1){
 			var basename=name.substr(0,name.lastIndexOf('.'));
-			var extention=name.substr(name.lastIndexOf('.'));
+			var extension=name.substr(name.lastIndexOf('.'));
 		}else{
 			var basename=name;
-			var extention=false;
+			var extension=false;
 		}
 		html+='<td class="filename" style="background-image:url('+img+')"><input type="checkbox" />';
 		html+='<a class="name" href="download.php?file='+$('#dir').val()+'/'+name+'"><span class="nametext">'+basename
-		if(extention){
-			html+='<span class="extention">'+extention+'</span>';
+		if(extension){
+			html+='<span class="extension">'+extension+'</span>';
 		}
 		html+='</span></a></td>';
 		if(size!='Pending'){
@@ -42,6 +43,7 @@ FileList={
 		td.append('<input type="checkbox" />');
 		var link_elem = $('<a></a>').attr({ "class": "name", "href": "index.php?dir="+ encodeURIComponent($('#dir').val()+'/'+name).replace(/%2F/g, '/') });
 		link_elem.append($('<span></span>').addClass('nametext').text(name));
+		link_elem.append($('<span></span>').attr({'class': 'uploadtext', 'currentUploads': 0}));
 		td.append(link_elem);
 		html.append(td);
 		if(size!='Pending'){
@@ -147,7 +149,7 @@ FileList={
 			span.text(basename);
 			td.children('a.name').append(span);
 			if(newname.indexOf('.')>0){
-				span.append($('<span class="extention">'+newname.substr(newname.lastIndexOf('.'))+'</span>'));
+				span.append($('<span class="extension">'+newname.substr(newname.lastIndexOf('.'))+'</span>'));
 			}
 			$.get(OC.filePath('files','ajax','rename.php'), { dir : $('#dir').val(), newname: newname, file: name },function(){
 				tr.data('renaming',false);
@@ -163,7 +165,7 @@ FileList={
 		});
 	},
 	do_delete:function(files){
-		if(FileList.deleteFiles){//finish any ongoing deletes first
+		if(FileList.deleteFiles || !FileList.useUndo){//finish any ongoing deletes first
 			FileList.finishDelete(function(){
 				FileList.do_delete(files);
 			});
@@ -189,14 +191,13 @@ FileList={
 		if(!FileList.deleteCanceled && FileList.deleteFiles){
 			var fileNames=FileList.deleteFiles.join(';');
 			$.ajax({
-				url: 'ajax/delete.php',
+				url: OC.filePath('files', 'ajax', 'delete.php'),
 				async:!sync,
-				data: "dir="+$('#dir').val()+"&files="+encodeURIComponent(fileNames),
+				data: {dir:$('#dir').val(),files:fileNames},
 				complete: function(data){
 					boolOperationFinished(data, function(){
 						$('#notification').fadeOut();
 						$.each(FileList.deleteFiles,function(index,file){
-// 							alert(file);
 							FileList.remove(file);
 						});
 						FileList.deleteCanceled=true;
@@ -225,7 +226,7 @@ $(document).ready(function(){
 		}
 		$('#notification').fadeOut();
 	});
-	
+	FileList.useUndo=('onbeforeunload' in window)
 	$(window).bind('beforeunload', function (){
 		FileList.finishDelete(null,true);
 	});
diff --git a/files/js/files.js b/apps/files/js/files.js
similarity index 63%
rename from files/js/files.js
rename to apps/files/js/files.js
index 1c0a40c23684447e75f609b4ba0b0ea815730b37..2dce00035e162fe0195c035ea21f2dc6ab41547f 100644
--- a/files/js/files.js
+++ b/apps/files/js/files.js
@@ -1,3 +1,32 @@
+var uploadingFiles = {};
+Files={
+	cancelUpload:function(filename) {
+		if(uploadingFiles[filename]) {
+			uploadingFiles[filename].abort();
+			delete uploadingFiles[filename];
+			return true;
+		}
+		return false;
+	},
+	cancelUploads:function() {
+		$.each(uploadingFiles,function(index,file) {
+			if(typeof file['abort'] === 'function') {
+				file.abort();
+				var filename = $('tr').filterAttr('data-file',index);
+				filename.hide();
+				filename.find('input[type="checkbox"]').removeAttr('checked');
+				filename.removeClass('selected');
+			} else {
+				$.each(file,function(i,f) {
+					f.abort();
+					delete file[i];
+				});
+			}
+			delete uploadingFiles[index];
+		});
+		procesSelection();
+	}
+}
 $(document).ready(function() {
 	$('#fileList tr').each(function(){
 		//little hack to set unescape filenames in attribute
@@ -13,9 +42,11 @@ $(document).ready(function() {
 	//drag/drop of files
 	$('#fileList tr td.filename').draggable(dragOptions);
 	$('#fileList tr[data-type="dir"][data-write="true"] td.filename').droppable(folderDropOptions);
-	$('div.crumb').droppable(crumbDropOptions);
+	$('div.crumb:not(.last)').droppable(crumbDropOptions);
 	$('ul#apps>li:first-child').data('dir','');
-	$('ul#apps>li:first-child').droppable(crumbDropOptions);
+	if($('div.crumb').length){
+		$('ul#apps>li:first-child').droppable(crumbDropOptions);
+	}
 
 	// Triggers invisible file input
 	$('.file_upload_button_wrapper').live('click', function() {
@@ -138,7 +169,7 @@ $(document).ready(function() {
 		var dir=$('#dir').val()||'/';
 		$('#notification').text(t('files','generating ZIP-file, it may take some time.'));
 		$('#notification').fadeIn();
-		window.location='ajax/download.php?files='+encodeURIComponent(files)+'&dir='+encodeURIComponent(dir);
+		window.location=OC.filePath('files', 'ajax', 'download.php') + '?files='+encodeURIComponent(files)+'&dir='+encodeURIComponent(dir);
 		return false;
 	});
 
@@ -149,83 +180,205 @@ $(document).ready(function() {
 		return false;
 	});
 
-	$('.file_upload_start').live('change',function(){
-		var form=$(this).closest('form');
-		var that=this;
-		var uploadId=form.attr('data-upload-id');
-		var files=this.files;
-		var target=form.children('iframe');
-		var totalSize=0;
-		if(files){
-			for(var i=0;i<files.length;i++){
-				totalSize+=files[i].size;
-				if(FileList.deleteFiles && FileList.deleteFiles.indexOf(files[i].name)!=-1){//finish delete if we are uploading a deleted file
-					FileList.finishDelete(function(){
-						$(that).change();
-					});
-					return;
-				}
-			}
-		}
-		if(totalSize>$('#max_upload').val()){
-			$( "#uploadsize-message" ).dialog({
-				modal: true,
-				buttons: {
-					Close: function() {
-						$( this ).dialog( "close" );
+	// drag&drop support using jquery.fileupload
+	// TODO use OC.dialogs
+	$(document).bind('drop dragover', function (e) {
+			e.preventDefault(); // prevent browser from doing anything, if file isn't dropped in dropZone
+	});
+
+	$(function() {
+		$('.file_upload_start').fileupload({
+			dropZone: $('#content'), // restrict dropZone to content div
+			add: function(e, data) {
+				var files = data.files;
+				var totalSize=0;
+				if(files){
+					for(var i=0;i<files.length;i++){
+						totalSize+=files[i].size;
+						if(FileList.deleteFiles && FileList.deleteFiles.indexOf(files[i].name)!=-1){//finish delete if we are uploading a deleted file
+							FileList.finishDelete(function(){
+								$('.file_upload_start').change();
+							});
+							return;
+						}
 					}
 				}
-			});
-		}else{
-			target.load(function(){
-				var response=jQuery.parseJSON(target.contents().find('body').text());
-				//set mimetype and if needed filesize
-				if(response){
-					if(response[0] != undefined && response[0].status == 'success'){
-						for(var i=0;i<response.length;i++){
-							var file=response[i];
+				if(totalSize>$('#max_upload').val()){
+					$( '#uploadsize-message' ).dialog({
+						modal: true,
+						buttons: {
+							Close: function() {
+								$( this ).dialog( 'close' );
+							}
+						}
+					});
+				}else{
+				if($.support.xhrFileUpload) {
+					for(var i=0;i<files.length;i++){
+						var fileName = files[i].name
+						var dropTarget = $(e.originalEvent.target).closest('tr');
+						if(dropTarget && dropTarget.attr('data-type') === 'dir') { // drag&drop upload to folder
+							var dirName = dropTarget.attr('data-file')
+							var jqXHR =  $('.file_upload_start').fileupload('send', {files: files[i],
+									formData: function(form) {
+										var formArray = form.serializeArray();
+										formArray[1]['value'] = dirName;
+										return formArray;
+									}}).success(function(result, textStatus, jqXHR) {
+										var response;
+										response=jQuery.parseJSON(result);
+										if(response[0] == undefined || response[0].status != 'success') {
+											$('#notification').text(t('files', response.data.message));
+											$('#notification').fadeIn();
+										}
+										var file=response[0];
+										delete uploadingFiles[dirName][file.name];
+										var currentUploads = parseInt(uploadtext.attr('currentUploads'));
+										currentUploads -= 1;
+										uploadtext.attr('currentUploads', currentUploads);
+										if(currentUploads === 0) {
+											var img = OC.imagePath('core', 'filetypes/folder.png');
+											var tr=$('tr').filterAttr('data-file',dirName);
+											tr.find('td.filename').attr('style','background-image:url('+img+')');
+											uploadtext.text('');
+											uploadtext.hide();
+										} else {
+											uploadtext.text(currentUploads + ' files uploading')
+										}
+									})
+							.error(function(jqXHR, textStatus, errorThrown) {
+								if(errorThrown === 'abort') {
+									var currentUploads = parseInt(uploadtext.attr('currentUploads'));
+									currentUploads -= 1;
+									uploadtext.attr('currentUploads', currentUploads);
+									if(currentUploads === 0) {
+										var img = OC.imagePath('core', 'filetypes/folder.png');
+										var tr=$('tr').filterAttr('data-file',dirName);
+										tr.find('td.filename').attr('style','background-image:url('+img+')');
+										uploadtext.text('');
+										uploadtext.hide();
+									} else {
+										uploadtext.text(currentUploads + ' files uploading')
+									}
+									$('#notification').hide();
+									$('#notification').text(t('files', 'Upload cancelled.'));
+									$('#notification').fadeIn();
+								}
+							});
+							//TODO test with filenames containing slashes
+							if(uploadingFiles[dirName] === undefined) {
+								uploadingFiles[dirName] = {};
+							}
+							uploadingFiles[dirName][fileName] = jqXHR;
+						} else {
+							var jqXHR =  $('.file_upload_start').fileupload('send', {files: files[i]})
+									.success(function(result, textStatus, jqXHR) {
+										var response;
+										response=jQuery.parseJSON(result);
+										if(response[0] != undefined && response[0].status == 'success') {
+											var file=response[0];
+											delete uploadingFiles[file.name];
+											$('tr').filterAttr('data-file',file.name).data('mime',file.mime);
+											var size = $('tr').filterAttr('data-file',file.name).find('td.filesize').text();
+											if(size==t('files','Pending')){
+												$('tr').filterAttr('data-file',file.name).find('td.filesize').text(file.size);
+											}
+											FileList.loadingDone(file.name);
+										} else {
+											$('#notification').text(t('files', response.data.message));
+											$('#notification').fadeIn();
+											$('#fileList > tr').not('[data-mime]').fadeOut();
+											$('#fileList > tr').not('[data-mime]').remove();
+										}
+									})
+							.error(function(jqXHR, textStatus, errorThrown) {
+								if(errorThrown === 'abort') {
+									$('#notification').hide();
+									$('#notification').text(t('files', 'Upload cancelled.'));
+									$('#notification').fadeIn();
+								}
+							});
+							uploadingFiles[files[i].name] = jqXHR;
+						}
+					}
+				}else{
+					data.submit().success(function(data, status) {
+						response = jQuery.parseJSON(data[0].body.innerText);
+						if(response[0] != undefined && response[0].status == 'success') {
+							var file=response[0];
+							delete uploadingFiles[file.name];
 							$('tr').filterAttr('data-file',file.name).data('mime',file.mime);
-							if(size=='Pending'){
+							var size = $('tr').filterAttr('data-file',file.name).find('td.filesize').text();
+							if(size==t('files','Pending')){
 								$('tr').filterAttr('data-file',file.name).find('td.filesize').text(file.size);
 							}
 							FileList.loadingDone(file.name);
+						} else {
+							$('#notification').text(t('files', response.data.message));
+							$('#notification').fadeIn();
+							$('#fileList > tr').not('[data-mime]').fadeOut();
+							$('#fileList > tr').not('[data-mime]').remove();
 						}
-					}
-					else{
-						$('#notification').text(t('files',response.data.message));
-						$('#notification').fadeIn();
-						$('#fileList > tr').not('[data-mime]').fadeOut();
-						$('#fileList > tr').not('[data-mime]').remove();
-					}
+					});
 				}
-			});
-			form.submit();
-			var date=new Date();
-			if(files){
-				for(var i=0;i<files.length;i++){
-					if(files[i].size>0){
-						var size=files[i].size;
-					}else{
-						var size=t('files','Pending');
-					}
+									
+					var date=new Date();
 					if(files){
-						FileList.addFile(files[i].name,size,date,true);
+						for(var i=0;i<files.length;i++){
+							if(files[i].size>0){
+								var size=files[i].size;
+							}else{
+								var size=t('files','Pending');
+							}
+							if(files && !dirName){
+						FileList.addFile(getUniqueName(files[i].name),size,date,true);
+							} else if(dirName) {
+								var uploadtext = $('tr').filterAttr('data-type', 'dir').filterAttr('data-file', dirName).find('.uploadtext')
+								var currentUploads = parseInt(uploadtext.attr('currentUploads'));
+								currentUploads += 1;
+								uploadtext.attr('currentUploads', currentUploads);
+								if(currentUploads === 1) {
+									var img = OC.imagePath('core', 'loading.gif');
+									var tr=$('tr').filterAttr('data-file',dirName);
+									tr.find('td.filename').attr('style','background-image:url('+img+')');
+									uploadtext.text('1 file uploading');
+									uploadtext.show();
+								} else {
+									uploadtext.text(currentUploads + ' files uploading')
+								}
+							}
+						}
+					}else{
+						var filename=this.value.split('\\').pop(); //ie prepends C:\fakepath\ in front of the filename
+				FileList.addFile(getUniqueName(filename),'Pending',date,true);
 					}
 				}
-			}else{
-				var filename=this.value.split('\\').pop(); //ie prepends C:\fakepath\ in front of the filename
-				FileList.addFile(filename,'Pending',date,true);
+			},
+			fail: function(e, data) {
+				// TODO: cancel upload & display error notification
+			},
+			progress: function(e, data) {
+				// TODO: show nice progress bar in file row
+			},
+			progressall: function(e, data) {
+				var progress = (data.loaded/data.total)*100;
+				$('#uploadprogressbar').progressbar('value',progress);
+			},
+			start: function(e, data) {
+				$('#uploadprogressbar').progressbar({value:0});
+				$('#uploadprogressbar').fadeIn();
+				if(data.dataType != 'iframe ') {
+					$('#upload input.stop').show();
+				}
+			},
+			stop: function(e, data) {
+				if(data.dataType != 'iframe ') {
+					$('#upload input.stop').hide();
+				}	
+				$('#uploadprogressbar').progressbar('value',100);
+				$('#uploadprogressbar').fadeOut();
 			}
-
-			//clone the upload form and hide the new one to allow users to start a new upload while the old one is still uploading
-			var clone=form.clone();
-			uploadId++;
-			clone.attr('data-upload-id',uploadId);
-			clone.attr('target','file_upload_target_'+uploadId);
-			clone.children('iframe').attr('name','file_upload_target_'+uploadId)
-			clone.insertBefore(form);
-			form.hide();
-		}
+		})
 	});
 
 	//add multiply file upload attribute to all browsers except konqueror (which crashes when it's used)
@@ -368,12 +521,15 @@ $(document).ready(function() {
 	}, "json");
 });
 
-function scanFiles(force){
+function scanFiles(force,dir){
+	if(!dir){
+		dir='';
+	}
 	force=!!force; //cast to bool
 	scanFiles.scanning=true;
 	$('#scanning-message').show();
 	$('#fileList').remove();
-	var scannerEventSource=new OC.EventSource(OC.filePath('files','ajax','scan.php'),{force:force});
+	var scannerEventSource=new OC.EventSource(OC.filePath('files','ajax','scan.php'),{force:force,dir:dir});
 	scanFiles.cancel=scannerEventSource.close.bind(scannerEventSource);
 	scannerEventSource.listen('scanning',function(data){
 		$('#scan-count').text(data.count+' files scanned');
@@ -412,11 +568,11 @@ var dragOptions={
 };
 var folderDropOptions={
 	drop: function( event, ui ) {
-		var file=ui.draggable.text().trim();
+		var file=ui.draggable.parent().data('file');
 		var target=$(this).text().trim();
 		var dir=$('#dir').val();
 		$.ajax({
-			url: 'ajax/move.php',
+			url: OC.filePath('files', 'ajax', 'move.php'),
 		data: "dir="+encodeURIComponent(dir)+"&file="+encodeURIComponent(file)+'&target='+encodeURIComponent(dir)+'/'+encodeURIComponent(target),
 		complete: function(data){boolOperationFinished(data, function(){
 			var el = $('#fileList tr').filterAttr('data-file',file).find('td.filename');
@@ -438,11 +594,11 @@ var crumbDropOptions={
 		if(dir.substr(-1,1)!='/'){
 			dir=dir+'/';
 		}
-		if(target==dir){
+		if(target==dir || target+'/'==dir){
 			return;
 		}
 		$.ajax({
-			url: 'ajax/move.php',
+			url: OC.filePath('files', 'ajax', 'move.php'),
 		 data: "dir="+encodeURIComponent(dir)+"&file="+encodeURIComponent(file)+'&target='+encodeURIComponent(target),
 		 complete: function(data){boolOperationFinished(data, function(){
 			 FileList.remove(file);
@@ -568,3 +724,22 @@ function getMimeIcon(mime, ready){
 	}
 }
 getMimeIcon.cache={};
+
+function getUniqueName(name){
+	if($('tr').filterAttr('data-file',name).length>0){
+		var parts=name.split('.');
+		var extension=parts.pop();
+		var base=parts.join('.');
+		numMatch=base.match(/\((\d+)\)/);
+		var num=2;
+		if(numMatch && numMatch.length>0){
+			num=parseInt(numMatch[numMatch.length-1])+1;
+			base=base.split('(')
+			base.pop();
+			base=base.join('(').trim();
+		}
+		name=base+' ('+num+').'+extension;
+		return getUniqueName(name);
+	}
+	return name;
+}
diff --git a/apps/files/js/jquery.fileupload.js b/apps/files/js/jquery.fileupload.js
new file mode 100644
index 0000000000000000000000000000000000000000..a89e9dc2c4498fe50c7d8a4985bd952c639310f1
--- /dev/null
+++ b/apps/files/js/jquery.fileupload.js
@@ -0,0 +1,866 @@
+/*
+ * jQuery File Upload Plugin 5.9
+ * https://github.com/blueimp/jQuery-File-Upload
+ *
+ * Copyright 2010, Sebastian Tschan
+ * https://blueimp.net
+ *
+ * Licensed under the MIT license:
+ * http://www.opensource.org/licenses/MIT
+ */
+
+/*jslint nomen: true, unparam: true, regexp: true */
+/*global define, window, document, Blob, FormData, location */
+
+(function (factory) {
+    'use strict';
+    if (typeof define === 'function' && define.amd) {
+        // Register as an anonymous AMD module:
+        define([
+            'jquery',
+            'jquery.ui.widget'
+        ], factory);
+    } else {
+        // Browser globals:
+        factory(window.jQuery);
+    }
+}(function ($) {
+    'use strict';
+
+    // The FileReader API is not actually used, but works as feature detection,
+    // as e.g. Safari supports XHR file uploads via the FormData API,
+    // but not non-multipart XHR file uploads:
+    $.support.xhrFileUpload = !!(window.XMLHttpRequestUpload && window.FileReader);
+    $.support.xhrFormDataFileUpload = !!window.FormData;
+
+    // The fileupload widget listens for change events on file input fields defined
+    // via fileInput setting and paste or drop events of the given dropZone.
+    // In addition to the default jQuery Widget methods, the fileupload widget
+    // exposes the "add" and "send" methods, to add or directly send files using
+    // the fileupload API.
+    // By default, files added via file input selection, paste, drag & drop or
+    // "add" method are uploaded immediately, but it is possible to override
+    // the "add" callback option to queue file uploads.
+    $.widget('blueimp.fileupload', {
+
+        options: {
+            // The namespace used for event handler binding on the dropZone and
+            // fileInput collections.
+            // If not set, the name of the widget ("fileupload") is used.
+            namespace: undefined,
+            // The drop target collection, by the default the complete document.
+            // Set to null or an empty collection to disable drag & drop support:
+            dropZone: $(document),
+            // The file input field collection, that is listened for change events.
+            // If undefined, it is set to the file input fields inside
+            // of the widget element on plugin initialization.
+            // Set to null or an empty collection to disable the change listener.
+            fileInput: undefined,
+            // By default, the file input field is replaced with a clone after
+            // each input field change event. This is required for iframe transport
+            // queues and allows change events to be fired for the same file
+            // selection, but can be disabled by setting the following option to false:
+            replaceFileInput: true,
+            // The parameter name for the file form data (the request argument name).
+            // If undefined or empty, the name property of the file input field is
+            // used, or "files[]" if the file input name property is also empty:
+            paramName: undefined,
+            // By default, each file of a selection is uploaded using an individual
+            // request for XHR type uploads. Set to false to upload file
+            // selections in one request each:
+            singleFileUploads: true,
+            // To limit the number of files uploaded with one XHR request,
+            // set the following option to an integer greater than 0:
+            limitMultiFileUploads: undefined,
+            // Set the following option to true to issue all file upload requests
+            // in a sequential order:
+            sequentialUploads: false,
+            // To limit the number of concurrent uploads,
+            // set the following option to an integer greater than 0:
+            limitConcurrentUploads: undefined,
+            // Set the following option to true to force iframe transport uploads:
+            forceIframeTransport: false,
+            // Set the following option to the location of a redirect url on the
+            // origin server, for cross-domain iframe transport uploads:
+            redirect: undefined,
+            // The parameter name for the redirect url, sent as part of the form
+            // data and set to 'redirect' if this option is empty:
+            redirectParamName: undefined,
+            // Set the following option to the location of a postMessage window,
+            // to enable postMessage transport uploads:
+            postMessage: undefined,
+            // By default, XHR file uploads are sent as multipart/form-data.
+            // The iframe transport is always using multipart/form-data.
+            // Set to false to enable non-multipart XHR uploads:
+            multipart: true,
+            // To upload large files in smaller chunks, set the following option
+            // to a preferred maximum chunk size. If set to 0, null or undefined,
+            // or the browser does not support the required Blob API, files will
+            // be uploaded as a whole.
+            maxChunkSize: undefined,
+            // When a non-multipart upload or a chunked multipart upload has been
+            // aborted, this option can be used to resume the upload by setting
+            // it to the size of the already uploaded bytes. This option is most
+            // useful when modifying the options object inside of the "add" or
+            // "send" callbacks, as the options are cloned for each file upload.
+            uploadedBytes: undefined,
+            // By default, failed (abort or error) file uploads are removed from the
+            // global progress calculation. Set the following option to false to
+            // prevent recalculating the global progress data:
+            recalculateProgress: true,
+
+            // Additional form data to be sent along with the file uploads can be set
+            // using this option, which accepts an array of objects with name and
+            // value properties, a function returning such an array, a FormData
+            // object (for XHR file uploads), or a simple object.
+            // The form of the first fileInput is given as parameter to the function:
+            formData: function (form) {
+                return form.serializeArray();
+            },
+
+            // The add callback is invoked as soon as files are added to the fileupload
+            // widget (via file input selection, drag & drop, paste or add API call).
+            // If the singleFileUploads option is enabled, this callback will be
+            // called once for each file in the selection for XHR file uplaods, else
+            // once for each file selection.
+            // The upload starts when the submit method is invoked on the data parameter.
+            // The data object contains a files property holding the added files
+            // and allows to override plugin options as well as define ajax settings.
+            // Listeners for this callback can also be bound the following way:
+            // .bind('fileuploadadd', func);
+            // data.submit() returns a Promise object and allows to attach additional
+            // handlers using jQuery's Deferred callbacks:
+            // data.submit().done(func).fail(func).always(func);
+            add: function (e, data) {
+                data.submit();
+            },
+
+            // Other callbacks:
+            // Callback for the submit event of each file upload:
+            // submit: function (e, data) {}, // .bind('fileuploadsubmit', func);
+            // Callback for the start of each file upload request:
+            // send: function (e, data) {}, // .bind('fileuploadsend', func);
+            // Callback for successful uploads:
+            // done: function (e, data) {}, // .bind('fileuploaddone', func);
+            // Callback for failed (abort or error) uploads:
+            // fail: function (e, data) {}, // .bind('fileuploadfail', func);
+            // Callback for completed (success, abort or error) requests:
+            // always: function (e, data) {}, // .bind('fileuploadalways', func);
+            // Callback for upload progress events:
+            // progress: function (e, data) {}, // .bind('fileuploadprogress', func);
+            // Callback for global upload progress events:
+            // progressall: function (e, data) {}, // .bind('fileuploadprogressall', func);
+            // Callback for uploads start, equivalent to the global ajaxStart event:
+            // start: function (e) {}, // .bind('fileuploadstart', func);
+            // Callback for uploads stop, equivalent to the global ajaxStop event:
+            // stop: function (e) {}, // .bind('fileuploadstop', func);
+            // Callback for change events of the fileInput collection:
+            // change: function (e, data) {}, // .bind('fileuploadchange', func);
+            // Callback for paste events to the dropZone collection:
+            // paste: function (e, data) {}, // .bind('fileuploadpaste', func);
+            // Callback for drop events of the dropZone collection:
+            // drop: function (e, data) {}, // .bind('fileuploaddrop', func);
+            // Callback for dragover events of the dropZone collection:
+            // dragover: function (e) {}, // .bind('fileuploaddragover', func);
+
+            // The plugin options are used as settings object for the ajax calls.
+            // The following are jQuery ajax settings required for the file uploads:
+            processData: false,
+            contentType: false,
+            cache: false
+        },
+
+        // A list of options that require a refresh after assigning a new value:
+        _refreshOptionsList: [
+            'namespace',
+            'dropZone',
+            'fileInput',
+            'multipart',
+            'forceIframeTransport'
+        ],
+
+        _isXHRUpload: function (options) {
+            return !options.forceIframeTransport &&
+                ((!options.multipart && $.support.xhrFileUpload) ||
+                $.support.xhrFormDataFileUpload);
+        },
+
+        _getFormData: function (options) {
+            var formData;
+            if (typeof options.formData === 'function') {
+                return options.formData(options.form);
+            } else if ($.isArray(options.formData)) {
+                return options.formData;
+            } else if (options.formData) {
+                formData = [];
+                $.each(options.formData, function (name, value) {
+                    formData.push({name: name, value: value});
+                });
+                return formData;
+            }
+            return [];
+        },
+
+        _getTotal: function (files) {
+            var total = 0;
+            $.each(files, function (index, file) {
+                total += file.size || 1;
+            });
+            return total;
+        },
+
+        _onProgress: function (e, data) {
+            if (e.lengthComputable) {
+                var total = data.total || this._getTotal(data.files),
+                    loaded = parseInt(
+                        e.loaded / e.total * (data.chunkSize || total),
+                        10
+                    ) + (data.uploadedBytes || 0);
+                this._loaded += loaded - (data.loaded || data.uploadedBytes || 0);
+                data.lengthComputable = true;
+                data.loaded = loaded;
+                data.total = total;
+                // Trigger a custom progress event with a total data property set
+                // to the file size(s) of the current upload and a loaded data
+                // property calculated accordingly:
+                this._trigger('progress', e, data);
+                // Trigger a global progress event for all current file uploads,
+                // including ajax calls queued for sequential file uploads:
+                this._trigger('progressall', e, {
+                    lengthComputable: true,
+                    loaded: this._loaded,
+                    total: this._total
+                });
+            }
+        },
+
+        _initProgressListener: function (options) {
+            var that = this,
+                xhr = options.xhr ? options.xhr() : $.ajaxSettings.xhr();
+            // Accesss to the native XHR object is required to add event listeners
+            // for the upload progress event:
+            if (xhr.upload) {
+                $(xhr.upload).bind('progress', function (e) {
+                    var oe = e.originalEvent;
+                    // Make sure the progress event properties get copied over:
+                    e.lengthComputable = oe.lengthComputable;
+                    e.loaded = oe.loaded;
+                    e.total = oe.total;
+                    that._onProgress(e, options);
+                });
+                options.xhr = function () {
+                    return xhr;
+                };
+            }
+        },
+
+        _initXHRData: function (options) {
+            var formData,
+                file = options.files[0],
+                // Ignore non-multipart setting if not supported:
+                multipart = options.multipart || !$.support.xhrFileUpload;
+            if (!multipart || options.blob) {
+                // For non-multipart uploads and chunked uploads,
+                // file meta data is not part of the request body,
+                // so we transmit this data as part of the HTTP headers.
+                // For cross domain requests, these headers must be allowed
+                // via Access-Control-Allow-Headers or removed using
+                // the beforeSend callback:
+                options.headers = $.extend(options.headers, {
+                    'X-File-Name': file.name,
+                    'X-File-Type': file.type,
+                    'X-File-Size': file.size
+                });
+                if (!options.blob) {
+                    // Non-chunked non-multipart upload:
+                    options.contentType = file.type;
+                    options.data = file;
+                } else if (!multipart) {
+                    // Chunked non-multipart upload:
+                    options.contentType = 'application/octet-stream';
+                    options.data = options.blob;
+                }
+            }
+            if (multipart && $.support.xhrFormDataFileUpload) {
+                if (options.postMessage) {
+                    // window.postMessage does not allow sending FormData
+                    // objects, so we just add the File/Blob objects to
+                    // the formData array and let the postMessage window
+                    // create the FormData object out of this array:
+                    formData = this._getFormData(options);
+                    if (options.blob) {
+                        formData.push({
+                            name: options.paramName,
+                            value: options.blob
+                        });
+                    } else {
+                        $.each(options.files, function (index, file) {
+                            formData.push({
+                                name: options.paramName,
+                                value: file
+                            });
+                        });
+                    }
+                } else {
+                    if (options.formData instanceof FormData) {
+                        formData = options.formData;
+                    } else {
+                        formData = new FormData();
+                        $.each(this._getFormData(options), function (index, field) {
+                            formData.append(field.name, field.value);
+                        });
+                    }
+                    if (options.blob) {
+                        formData.append(options.paramName, options.blob, file.name);
+                    } else {
+                        $.each(options.files, function (index, file) {
+                            // File objects are also Blob instances.
+                            // This check allows the tests to run with
+                            // dummy objects:
+                            if (file instanceof Blob) {
+                                formData.append(options.paramName, file, file.name);
+                            }
+                        });
+                    }
+                }
+                options.data = formData;
+            }
+            // Blob reference is not needed anymore, free memory:
+            options.blob = null;
+        },
+
+        _initIframeSettings: function (options) {
+            // Setting the dataType to iframe enables the iframe transport:
+            options.dataType = 'iframe ' + (options.dataType || '');
+            // The iframe transport accepts a serialized array as form data:
+            options.formData = this._getFormData(options);
+            // Add redirect url to form data on cross-domain uploads:
+            if (options.redirect && $('<a></a>').prop('href', options.url)
+                    .prop('host') !== location.host) {
+                options.formData.push({
+                    name: options.redirectParamName || 'redirect',
+                    value: options.redirect
+                });
+            }
+        },
+
+        _initDataSettings: function (options) {
+            if (this._isXHRUpload(options)) {
+                if (!this._chunkedUpload(options, true)) {
+                    if (!options.data) {
+                        this._initXHRData(options);
+                    }
+                    this._initProgressListener(options);
+                }
+                if (options.postMessage) {
+                    // Setting the dataType to postmessage enables the
+                    // postMessage transport:
+                    options.dataType = 'postmessage ' + (options.dataType || '');
+                }
+            } else {
+                this._initIframeSettings(options, 'iframe');
+            }
+        },
+
+        _initFormSettings: function (options) {
+            // Retrieve missing options from the input field and the
+            // associated form, if available:
+            if (!options.form || !options.form.length) {
+                options.form = $(options.fileInput.prop('form'));
+            }
+            if (!options.paramName) {
+                options.paramName = options.fileInput.prop('name') ||
+                    'files[]';
+            }
+            if (!options.url) {
+                options.url = options.form.prop('action') || location.href;
+            }
+            // The HTTP request method must be "POST" or "PUT":
+            options.type = (options.type || options.form.prop('method') || '')
+                .toUpperCase();
+            if (options.type !== 'POST' && options.type !== 'PUT') {
+                options.type = 'POST';
+            }
+        },
+
+        _getAJAXSettings: function (data) {
+            var options = $.extend({}, this.options, data);
+            this._initFormSettings(options);
+            this._initDataSettings(options);
+            return options;
+        },
+
+        // Maps jqXHR callbacks to the equivalent
+        // methods of the given Promise object:
+        _enhancePromise: function (promise) {
+            promise.success = promise.done;
+            promise.error = promise.fail;
+            promise.complete = promise.always;
+            return promise;
+        },
+
+        // Creates and returns a Promise object enhanced with
+        // the jqXHR methods abort, success, error and complete:
+        _getXHRPromise: function (resolveOrReject, context, args) {
+            var dfd = $.Deferred(),
+                promise = dfd.promise();
+            context = context || this.options.context || promise;
+            if (resolveOrReject === true) {
+                dfd.resolveWith(context, args);
+            } else if (resolveOrReject === false) {
+                dfd.rejectWith(context, args);
+            }
+            promise.abort = dfd.promise;
+            return this._enhancePromise(promise);
+        },
+
+        // Uploads a file in multiple, sequential requests
+        // by splitting the file up in multiple blob chunks.
+        // If the second parameter is true, only tests if the file
+        // should be uploaded in chunks, but does not invoke any
+        // upload requests:
+        _chunkedUpload: function (options, testOnly) {
+            var that = this,
+                file = options.files[0],
+                fs = file.size,
+                ub = options.uploadedBytes = options.uploadedBytes || 0,
+                mcs = options.maxChunkSize || fs,
+                // Use the Blob methods with the slice implementation
+                // according to the W3C Blob API specification:
+                slice = file.webkitSlice || file.mozSlice || file.slice,
+                upload,
+                n,
+                jqXHR,
+                pipe;
+            if (!(this._isXHRUpload(options) && slice && (ub || mcs < fs)) ||
+                    options.data) {
+                return false;
+            }
+            if (testOnly) {
+                return true;
+            }
+            if (ub >= fs) {
+                file.error = 'uploadedBytes';
+                return this._getXHRPromise(
+                    false,
+                    options.context,
+                    [null, 'error', file.error]
+                );
+            }
+            // n is the number of blobs to upload,
+            // calculated via filesize, uploaded bytes and max chunk size:
+            n = Math.ceil((fs - ub) / mcs);
+            // The chunk upload method accepting the chunk number as parameter:
+            upload = function (i) {
+                if (!i) {
+                    return that._getXHRPromise(true, options.context);
+                }
+                // Upload the blobs in sequential order:
+                return upload(i -= 1).pipe(function () {
+                    // Clone the options object for each chunk upload:
+                    var o = $.extend({}, options);
+                    o.blob = slice.call(
+                        file,
+                        ub + i * mcs,
+                        ub + (i + 1) * mcs
+                    );
+                    // Store the current chunk size, as the blob itself
+                    // will be dereferenced after data processing:
+                    o.chunkSize = o.blob.size;
+                    // Process the upload data (the blob and potential form data):
+                    that._initXHRData(o);
+                    // Add progress listeners for this chunk upload:
+                    that._initProgressListener(o);
+                    jqXHR = ($.ajax(o) || that._getXHRPromise(false, o.context))
+                        .done(function () {
+                            // Create a progress event if upload is done and
+                            // no progress event has been invoked for this chunk:
+                            if (!o.loaded) {
+                                that._onProgress($.Event('progress', {
+                                    lengthComputable: true,
+                                    loaded: o.chunkSize,
+                                    total: o.chunkSize
+                                }), o);
+                            }
+                            options.uploadedBytes = o.uploadedBytes +=
+                                o.chunkSize;
+                        });
+                    return jqXHR;
+                });
+            };
+            // Return the piped Promise object, enhanced with an abort method,
+            // which is delegated to the jqXHR object of the current upload,
+            // and jqXHR callbacks mapped to the equivalent Promise methods:
+            pipe = upload(n);
+            pipe.abort = function () {
+                return jqXHR.abort();
+            };
+            return this._enhancePromise(pipe);
+        },
+
+        _beforeSend: function (e, data) {
+            if (this._active === 0) {
+                // the start callback is triggered when an upload starts
+                // and no other uploads are currently running,
+                // equivalent to the global ajaxStart event:
+                this._trigger('start');
+            }
+            this._active += 1;
+            // Initialize the global progress values:
+            this._loaded += data.uploadedBytes || 0;
+            this._total += this._getTotal(data.files);
+        },
+
+        _onDone: function (result, textStatus, jqXHR, options) {
+            if (!this._isXHRUpload(options)) {
+                // Create a progress event for each iframe load:
+                this._onProgress($.Event('progress', {
+                    lengthComputable: true,
+                    loaded: 1,
+                    total: 1
+                }), options);
+            }
+            options.result = result;
+            options.textStatus = textStatus;
+            options.jqXHR = jqXHR;
+            this._trigger('done', null, options);
+        },
+
+        _onFail: function (jqXHR, textStatus, errorThrown, options) {
+            options.jqXHR = jqXHR;
+            options.textStatus = textStatus;
+            options.errorThrown = errorThrown;
+            this._trigger('fail', null, options);
+            if (options.recalculateProgress) {
+                // Remove the failed (error or abort) file upload from
+                // the global progress calculation:
+                this._loaded -= options.loaded || options.uploadedBytes || 0;
+                this._total -= options.total || this._getTotal(options.files);
+            }
+        },
+
+        _onAlways: function (jqXHRorResult, textStatus, jqXHRorError, options) {
+            this._active -= 1;
+            options.textStatus = textStatus;
+            if (jqXHRorError && jqXHRorError.always) {
+                options.jqXHR = jqXHRorError;
+                options.result = jqXHRorResult;
+            } else {
+                options.jqXHR = jqXHRorResult;
+                options.errorThrown = jqXHRorError;
+            }
+            this._trigger('always', null, options);
+            if (this._active === 0) {
+                // The stop callback is triggered when all uploads have
+                // been completed, equivalent to the global ajaxStop event:
+                this._trigger('stop');
+                // Reset the global progress values:
+                this._loaded = this._total = 0;
+            }
+        },
+
+        _onSend: function (e, data) {
+            var that = this,
+                jqXHR,
+                slot,
+                pipe,
+                options = that._getAJAXSettings(data),
+                send = function (resolve, args) {
+                    that._sending += 1;
+                    jqXHR = jqXHR || (
+                        (resolve !== false &&
+                        that._trigger('send', e, options) !== false &&
+                        (that._chunkedUpload(options) || $.ajax(options))) ||
+                        that._getXHRPromise(false, options.context, args)
+                    ).done(function (result, textStatus, jqXHR) {
+                        that._onDone(result, textStatus, jqXHR, options);
+                    }).fail(function (jqXHR, textStatus, errorThrown) {
+                        that._onFail(jqXHR, textStatus, errorThrown, options);
+                    }).always(function (jqXHRorResult, textStatus, jqXHRorError) {
+                        that._sending -= 1;
+                        that._onAlways(
+                            jqXHRorResult,
+                            textStatus,
+                            jqXHRorError,
+                            options
+                        );
+                        if (options.limitConcurrentUploads &&
+                                options.limitConcurrentUploads > that._sending) {
+                            // Start the next queued upload,
+                            // that has not been aborted:
+                            var nextSlot = that._slots.shift();
+                            while (nextSlot) {
+                                if (!nextSlot.isRejected()) {
+                                    nextSlot.resolve();
+                                    break;
+                                }
+                                nextSlot = that._slots.shift();
+                            }
+                        }
+                    });
+                    return jqXHR;
+                };
+            this._beforeSend(e, options);
+            if (this.options.sequentialUploads ||
+                    (this.options.limitConcurrentUploads &&
+                    this.options.limitConcurrentUploads <= this._sending)) {
+                if (this.options.limitConcurrentUploads > 1) {
+                    slot = $.Deferred();
+                    this._slots.push(slot);
+                    pipe = slot.pipe(send);
+                } else {
+                    pipe = (this._sequence = this._sequence.pipe(send, send));
+                }
+                // Return the piped Promise object, enhanced with an abort method,
+                // which is delegated to the jqXHR object of the current upload,
+                // and jqXHR callbacks mapped to the equivalent Promise methods:
+                pipe.abort = function () {
+                    var args = [undefined, 'abort', 'abort'];
+                    if (!jqXHR) {
+                        if (slot) {
+                            slot.rejectWith(args);
+                        }
+                        return send(false, args);
+                    }
+                    return jqXHR.abort();
+                };
+                return this._enhancePromise(pipe);
+            }
+            return send();
+        },
+
+        _onAdd: function (e, data) {
+            var that = this,
+                result = true,
+                options = $.extend({}, this.options, data),
+                limit = options.limitMultiFileUploads,
+                fileSet,
+                i;
+            if (!(options.singleFileUploads || limit) ||
+                    !this._isXHRUpload(options)) {
+                fileSet = [data.files];
+            } else if (!options.singleFileUploads && limit) {
+                fileSet = [];
+                for (i = 0; i < data.files.length; i += limit) {
+                    fileSet.push(data.files.slice(i, i + limit));
+                }
+            }
+            data.originalFiles = data.files;
+            $.each(fileSet || data.files, function (index, element) {
+                var files = fileSet ? element : [element],
+                    newData = $.extend({}, data, {files: files});
+                newData.submit = function () {
+                    newData.jqXHR = this.jqXHR =
+                        (that._trigger('submit', e, this) !== false) &&
+                        that._onSend(e, this);
+                    return this.jqXHR;
+                };
+                return (result = that._trigger('add', e, newData));
+            });
+            return result;
+        },
+
+        // File Normalization for Gecko 1.9.1 (Firefox 3.5) support:
+        _normalizeFile: function (index, file) {
+            if (file.name === undefined && file.size === undefined) {
+                file.name = file.fileName;
+                file.size = file.fileSize;
+            }
+        },
+
+        _replaceFileInput: function (input) {
+            var inputClone = input.clone(true);
+            $('<form></form>').append(inputClone)[0].reset();
+            // Detaching allows to insert the fileInput on another form
+            // without loosing the file input value:
+            input.after(inputClone).detach();
+            // Avoid memory leaks with the detached file input:
+            $.cleanData(input.unbind('remove'));
+            // Replace the original file input element in the fileInput
+            // collection with the clone, which has been copied including
+            // event handlers:
+            this.options.fileInput = this.options.fileInput.map(function (i, el) {
+                if (el === input[0]) {
+                    return inputClone[0];
+                }
+                return el;
+            });
+            // If the widget has been initialized on the file input itself,
+            // override this.element with the file input clone:
+            if (input[0] === this.element[0]) {
+                this.element = inputClone;
+            }
+        },
+
+        _onChange: function (e) {
+            var that = e.data.fileupload,
+                data = {
+                    files: $.each($.makeArray(e.target.files), that._normalizeFile),
+                    fileInput: $(e.target),
+                    form: $(e.target.form)
+                };
+            if (!data.files.length) {
+                // If the files property is not available, the browser does not
+                // support the File API and we add a pseudo File object with
+                // the input value as name with path information removed:
+                data.files = [{name: e.target.value.replace(/^.*\\/, '')}];
+            }
+            if (that.options.replaceFileInput) {
+                that._replaceFileInput(data.fileInput);
+            }
+            if (that._trigger('change', e, data) === false ||
+                    that._onAdd(e, data) === false) {
+                return false;
+            }
+        },
+
+        _onPaste: function (e) {
+            var that = e.data.fileupload,
+                cbd = e.originalEvent.clipboardData,
+                items = (cbd && cbd.items) || [],
+                data = {files: []};
+            $.each(items, function (index, item) {
+                var file = item.getAsFile && item.getAsFile();
+                if (file) {
+                    data.files.push(file);
+                }
+            });
+            if (that._trigger('paste', e, data) === false ||
+                    that._onAdd(e, data) === false) {
+                return false;
+            }
+        },
+
+        _onDrop: function (e) {
+            var that = e.data.fileupload,
+                dataTransfer = e.dataTransfer = e.originalEvent.dataTransfer,
+                data = {
+                    files: $.each(
+                        $.makeArray(dataTransfer && dataTransfer.files),
+                        that._normalizeFile
+                    )
+                };
+            if (that._trigger('drop', e, data) === false ||
+                    that._onAdd(e, data) === false) {
+                return false;
+            }
+            e.preventDefault();
+        },
+
+        _onDragOver: function (e) {
+            var that = e.data.fileupload,
+                dataTransfer = e.dataTransfer = e.originalEvent.dataTransfer;
+            if (that._trigger('dragover', e) === false) {
+                return false;
+            }
+            if (dataTransfer) {
+                dataTransfer.dropEffect = dataTransfer.effectAllowed = 'copy';
+            }
+            e.preventDefault();
+        },
+
+        _initEventHandlers: function () {
+            var ns = this.options.namespace;
+            if (this._isXHRUpload(this.options)) {
+                this.options.dropZone
+                    .bind('dragover.' + ns, {fileupload: this}, this._onDragOver)
+                    .bind('drop.' + ns, {fileupload: this}, this._onDrop)
+                    .bind('paste.' + ns, {fileupload: this}, this._onPaste);
+            }
+            this.options.fileInput
+                .bind('change.' + ns, {fileupload: this}, this._onChange);
+        },
+
+        _destroyEventHandlers: function () {
+            var ns = this.options.namespace;
+            this.options.dropZone
+                .unbind('dragover.' + ns, this._onDragOver)
+                .unbind('drop.' + ns, this._onDrop)
+                .unbind('paste.' + ns, this._onPaste);
+            this.options.fileInput
+                .unbind('change.' + ns, this._onChange);
+        },
+
+        _setOption: function (key, value) {
+            var refresh = $.inArray(key, this._refreshOptionsList) !== -1;
+            if (refresh) {
+                this._destroyEventHandlers();
+            }
+            $.Widget.prototype._setOption.call(this, key, value);
+            if (refresh) {
+                this._initSpecialOptions();
+                this._initEventHandlers();
+            }
+        },
+
+        _initSpecialOptions: function () {
+            var options = this.options;
+            if (options.fileInput === undefined) {
+                options.fileInput = this.element.is('input:file') ?
+                        this.element : this.element.find('input:file');
+            } else if (!(options.fileInput instanceof $)) {
+                options.fileInput = $(options.fileInput);
+            }
+            if (!(options.dropZone instanceof $)) {
+                options.dropZone = $(options.dropZone);
+            }
+        },
+
+        _create: function () {
+            var options = this.options,
+                dataOpts = $.extend({}, this.element.data());
+            dataOpts[this.widgetName] = undefined;
+            $.extend(options, dataOpts);
+            options.namespace = options.namespace || this.widgetName;
+            this._initSpecialOptions();
+            this._slots = [];
+            this._sequence = this._getXHRPromise(true);
+            this._sending = this._active = this._loaded = this._total = 0;
+            this._initEventHandlers();
+        },
+
+        destroy: function () {
+            this._destroyEventHandlers();
+            $.Widget.prototype.destroy.call(this);
+        },
+
+        enable: function () {
+            $.Widget.prototype.enable.call(this);
+            this._initEventHandlers();
+        },
+
+        disable: function () {
+            this._destroyEventHandlers();
+            $.Widget.prototype.disable.call(this);
+        },
+
+        // This method is exposed to the widget API and allows adding files
+        // using the fileupload API. The data parameter accepts an object which
+        // must have a files property and can contain additional options:
+        // .fileupload('add', {files: filesList});
+        add: function (data) {
+            if (!data || this.options.disabled) {
+                return;
+            }
+            data.files = $.each($.makeArray(data.files), this._normalizeFile);
+            this._onAdd(null, data);
+        },
+
+        // This method is exposed to the widget API and allows sending files
+        // using the fileupload API. The data parameter accepts an object which
+        // must have a files property and can contain additional options:
+        // .fileupload('send', {files: filesList});
+        // The method returns a Promise object for the file upload call.
+        send: function (data) {
+            if (data && !this.options.disabled) {
+                data.files = $.each($.makeArray(data.files), this._normalizeFile);
+                if (data.files.length) {
+                    return this._onSend(null, data);
+                }
+            }
+            return this._getXHRPromise(false, data && data.context);
+        }
+
+    });
+
+}));
diff --git a/apps/files/js/jquery.iframe-transport.js b/apps/files/js/jquery.iframe-transport.js
new file mode 100644
index 0000000000000000000000000000000000000000..d85c0c112973b2f6a433fb4a375adcb1c08f9bf6
--- /dev/null
+++ b/apps/files/js/jquery.iframe-transport.js
@@ -0,0 +1,165 @@
+/*
+ * jQuery Iframe Transport Plugin 1.3
+ * https://github.com/blueimp/jQuery-File-Upload
+ *
+ * Copyright 2011, Sebastian Tschan
+ * https://blueimp.net
+ *
+ * Licensed under the MIT license:
+ * http://www.opensource.org/licenses/MIT
+ */
+
+/*jslint unparam: true, nomen: true */
+/*global define, window, document */
+
+(function (factory) {
+    'use strict';
+    if (typeof define === 'function' && define.amd) {
+        // Register as an anonymous AMD module:
+        define(['jquery'], factory);
+    } else {
+        // Browser globals:
+        factory(window.jQuery);
+    }
+}(function ($) {
+    'use strict';
+
+    // Helper variable to create unique names for the transport iframes:
+    var counter = 0;
+
+    // The iframe transport accepts three additional options:
+    // options.fileInput: a jQuery collection of file input fields
+    // options.paramName: the parameter name for the file form data,
+    //  overrides the name property of the file input field(s)
+    // options.formData: an array of objects with name and value properties,
+    //  equivalent to the return data of .serializeArray(), e.g.:
+    //  [{name: 'a', value: 1}, {name: 'b', value: 2}]
+    $.ajaxTransport('iframe', function (options) {
+        if (options.async && (options.type === 'POST' || options.type === 'GET')) {
+            var form,
+                iframe;
+            return {
+                send: function (_, completeCallback) {
+                    form = $('<form style="display:none;"></form>');
+                    // javascript:false as initial iframe src
+                    // prevents warning popups on HTTPS in IE6.
+                    // IE versions below IE8 cannot set the name property of
+                    // elements that have already been added to the DOM,
+                    // so we set the name along with the iframe HTML markup:
+                    iframe = $(
+                        '<iframe src="javascript:false;" name="iframe-transport-' +
+                            (counter += 1) + '"></iframe>'
+                    ).bind('load', function () {
+                        var fileInputClones;
+                        iframe
+                            .unbind('load')
+                            .bind('load', function () {
+                                var response;
+                                // Wrap in a try/catch block to catch exceptions thrown
+                                // when trying to access cross-domain iframe contents:
+                                try {
+                                    response = iframe.contents();
+                                    // Google Chrome and Firefox do not throw an
+                                    // exception when calling iframe.contents() on
+                                    // cross-domain requests, so we unify the response:
+                                    if (!response.length || !response[0].firstChild) {
+                                        throw new Error();
+                                    }
+                                } catch (e) {
+                                    response = undefined;
+                                }
+                                // The complete callback returns the
+                                // iframe content document as response object:
+                                completeCallback(
+                                    200,
+                                    'success',
+                                    {'iframe': response}
+                                );
+                                // Fix for IE endless progress bar activity bug
+                                // (happens on form submits to iframe targets):
+                                $('<iframe src="javascript:false;"></iframe>')
+                                    .appendTo(form);
+                                form.remove();
+                            });
+                        form
+                            .prop('target', iframe.prop('name'))
+                            .prop('action', options.url)
+                            .prop('method', options.type);
+                        if (options.formData) {
+                            $.each(options.formData, function (index, field) {
+                                $('<input type="hidden"/>')
+                                    .prop('name', field.name)
+                                    .val(field.value)
+                                    .appendTo(form);
+                            });
+                        }
+                        if (options.fileInput && options.fileInput.length &&
+                                options.type === 'POST') {
+                            fileInputClones = options.fileInput.clone();
+                            // Insert a clone for each file input field:
+                            options.fileInput.after(function (index) {
+                                return fileInputClones[index];
+                            });
+                            if (options.paramName) {
+                                options.fileInput.each(function () {
+                                    $(this).prop('name', options.paramName);
+                                });
+                            }
+                            // Appending the file input fields to the hidden form
+                            // removes them from their original location:
+                            form
+                                .append(options.fileInput)
+                                .prop('enctype', 'multipart/form-data')
+                                // enctype must be set as encoding for IE:
+                                .prop('encoding', 'multipart/form-data');
+                        }
+                        form.submit();
+                        // Insert the file input fields at their original location
+                        // by replacing the clones with the originals:
+                        if (fileInputClones && fileInputClones.length) {
+                            options.fileInput.each(function (index, input) {
+                                var clone = $(fileInputClones[index]);
+                                $(input).prop('name', clone.prop('name'));
+                                clone.replaceWith(input);
+                            });
+                        }
+                    });
+                    form.append(iframe).appendTo(document.body);
+                },
+                abort: function () {
+                    if (iframe) {
+                        // javascript:false as iframe src aborts the request
+                        // and prevents warning popups on HTTPS in IE6.
+                        // concat is used to avoid the "Script URL" JSLint error:
+                        iframe
+                            .unbind('load')
+                            .prop('src', 'javascript'.concat(':false;'));
+                    }
+                    if (form) {
+                        form.remove();
+                    }
+                }
+            };
+        }
+    });
+
+    // The iframe transport returns the iframe content document as response.
+    // The following adds converters from iframe to text, json, html, and script:
+    $.ajaxSetup({
+        converters: {
+            'iframe text': function (iframe) {
+                return $(iframe[0].body).text();
+            },
+            'iframe json': function (iframe) {
+                return $.parseJSON($(iframe[0].body).text());
+            },
+            'iframe html': function (iframe) {
+                return $(iframe[0].body).html();
+            },
+            'iframe script': function (iframe) {
+                return $.globalEval($(iframe[0].body).text());
+            }
+        }
+    });
+
+}));
diff --git a/files/js/timezone.js b/apps/files/js/timezone.js
similarity index 82%
rename from files/js/timezone.js
rename to apps/files/js/timezone.js
index d569683f2109491fa5c16a0f124aeac26014d793..4749417199d957169de66589408ccb743d9d67ec 100644
--- a/files/js/timezone.js
+++ b/apps/files/js/timezone.js
@@ -3,7 +3,7 @@ $(document).ready(function() {
 	var visitortimezone = (-new Date().getTimezoneOffset()/60);
 	$.ajax({
 		type: "GET",
-		url: "ajax/timezone.php",
+		url: OC.filePath('files', 'ajax', 'timezone.php'),
 		data: 'time='+ visitortimezone,
 		success: function(){
 			location.reload();
diff --git a/files/l10n/ar.php b/apps/files/l10n/ar.php
similarity index 100%
rename from files/l10n/ar.php
rename to apps/files/l10n/ar.php
diff --git a/files/l10n/bg_BG.php b/apps/files/l10n/bg_BG.php
similarity index 100%
rename from files/l10n/bg_BG.php
rename to apps/files/l10n/bg_BG.php
diff --git a/files/l10n/ca.php b/apps/files/l10n/ca.php
similarity index 100%
rename from files/l10n/ca.php
rename to apps/files/l10n/ca.php
diff --git a/files/l10n/cs_CZ.php b/apps/files/l10n/cs_CZ.php
similarity index 100%
rename from files/l10n/cs_CZ.php
rename to apps/files/l10n/cs_CZ.php
diff --git a/files/l10n/da.php b/apps/files/l10n/da.php
similarity index 100%
rename from files/l10n/da.php
rename to apps/files/l10n/da.php
diff --git a/files/l10n/de.php b/apps/files/l10n/de.php
similarity index 100%
rename from files/l10n/de.php
rename to apps/files/l10n/de.php
diff --git a/files/l10n/el.php b/apps/files/l10n/el.php
similarity index 100%
rename from files/l10n/el.php
rename to apps/files/l10n/el.php
diff --git a/files/l10n/eo.php b/apps/files/l10n/eo.php
similarity index 100%
rename from files/l10n/eo.php
rename to apps/files/l10n/eo.php
diff --git a/files/l10n/es.php b/apps/files/l10n/es.php
similarity index 100%
rename from files/l10n/es.php
rename to apps/files/l10n/es.php
diff --git a/files/l10n/et_EE.php b/apps/files/l10n/et_EE.php
similarity index 100%
rename from files/l10n/et_EE.php
rename to apps/files/l10n/et_EE.php
diff --git a/files/l10n/eu.php b/apps/files/l10n/eu.php
similarity index 100%
rename from files/l10n/eu.php
rename to apps/files/l10n/eu.php
diff --git a/files/l10n/fr.php b/apps/files/l10n/fr.php
similarity index 100%
rename from files/l10n/fr.php
rename to apps/files/l10n/fr.php
diff --git a/files/l10n/gl.php b/apps/files/l10n/gl.php
similarity index 100%
rename from files/l10n/gl.php
rename to apps/files/l10n/gl.php
diff --git a/files/l10n/he.php b/apps/files/l10n/he.php
similarity index 100%
rename from files/l10n/he.php
rename to apps/files/l10n/he.php
diff --git a/files/l10n/hr.php b/apps/files/l10n/hr.php
similarity index 100%
rename from files/l10n/hr.php
rename to apps/files/l10n/hr.php
diff --git a/files/l10n/hu_HU.php b/apps/files/l10n/hu_HU.php
similarity index 100%
rename from files/l10n/hu_HU.php
rename to apps/files/l10n/hu_HU.php
diff --git a/files/l10n/ia.php b/apps/files/l10n/ia.php
similarity index 100%
rename from files/l10n/ia.php
rename to apps/files/l10n/ia.php
diff --git a/files/l10n/id.php b/apps/files/l10n/id.php
similarity index 100%
rename from files/l10n/id.php
rename to apps/files/l10n/id.php
diff --git a/files/l10n/it.php b/apps/files/l10n/it.php
similarity index 100%
rename from files/l10n/it.php
rename to apps/files/l10n/it.php
diff --git a/files/l10n/ja_JP.php b/apps/files/l10n/ja_JP.php
similarity index 100%
rename from files/l10n/ja_JP.php
rename to apps/files/l10n/ja_JP.php
diff --git a/files/l10n/lb.php b/apps/files/l10n/lb.php
similarity index 100%
rename from files/l10n/lb.php
rename to apps/files/l10n/lb.php
diff --git a/files/l10n/lt_LT.php b/apps/files/l10n/lt_LT.php
similarity index 100%
rename from files/l10n/lt_LT.php
rename to apps/files/l10n/lt_LT.php
diff --git a/files/l10n/ms_MY.php b/apps/files/l10n/ms_MY.php
similarity index 100%
rename from files/l10n/ms_MY.php
rename to apps/files/l10n/ms_MY.php
diff --git a/files/l10n/nb_NO.php b/apps/files/l10n/nb_NO.php
similarity index 100%
rename from files/l10n/nb_NO.php
rename to apps/files/l10n/nb_NO.php
diff --git a/files/l10n/nl.php b/apps/files/l10n/nl.php
similarity index 100%
rename from files/l10n/nl.php
rename to apps/files/l10n/nl.php
diff --git a/files/l10n/nn_NO.php b/apps/files/l10n/nn_NO.php
similarity index 100%
rename from files/l10n/nn_NO.php
rename to apps/files/l10n/nn_NO.php
diff --git a/files/l10n/pl.php b/apps/files/l10n/pl.php
similarity index 100%
rename from files/l10n/pl.php
rename to apps/files/l10n/pl.php
diff --git a/files/l10n/pt_BR.php b/apps/files/l10n/pt_BR.php
similarity index 100%
rename from files/l10n/pt_BR.php
rename to apps/files/l10n/pt_BR.php
diff --git a/files/l10n/ro.php b/apps/files/l10n/ro.php
similarity index 100%
rename from files/l10n/ro.php
rename to apps/files/l10n/ro.php
diff --git a/files/l10n/ru.php b/apps/files/l10n/ru.php
similarity index 100%
rename from files/l10n/ru.php
rename to apps/files/l10n/ru.php
diff --git a/files/l10n/sk_SK.php b/apps/files/l10n/sk_SK.php
similarity index 100%
rename from files/l10n/sk_SK.php
rename to apps/files/l10n/sk_SK.php
diff --git a/files/l10n/sl.php b/apps/files/l10n/sl.php
similarity index 100%
rename from files/l10n/sl.php
rename to apps/files/l10n/sl.php
diff --git a/files/l10n/sr.php b/apps/files/l10n/sr.php
similarity index 100%
rename from files/l10n/sr.php
rename to apps/files/l10n/sr.php
diff --git a/files/l10n/sr@latin.php b/apps/files/l10n/sr@latin.php
similarity index 100%
rename from files/l10n/sr@latin.php
rename to apps/files/l10n/sr@latin.php
diff --git a/files/l10n/sv.php b/apps/files/l10n/sv.php
similarity index 100%
rename from files/l10n/sv.php
rename to apps/files/l10n/sv.php
diff --git a/files/l10n/th_TH.php b/apps/files/l10n/th_TH.php
similarity index 100%
rename from files/l10n/th_TH.php
rename to apps/files/l10n/th_TH.php
diff --git a/files/l10n/tr.php b/apps/files/l10n/tr.php
similarity index 100%
rename from files/l10n/tr.php
rename to apps/files/l10n/tr.php
diff --git a/files/l10n/xgettextfiles b/apps/files/l10n/xgettextfiles
similarity index 100%
rename from files/l10n/xgettextfiles
rename to apps/files/l10n/xgettextfiles
diff --git a/files/l10n/zh_CN.php b/apps/files/l10n/zh_CN.php
similarity index 100%
rename from files/l10n/zh_CN.php
rename to apps/files/l10n/zh_CN.php
diff --git a/files/settings.php b/apps/files/settings.php
old mode 100644
new mode 100755
similarity index 91%
rename from files/settings.php
rename to apps/files/settings.php
index c47eb130095a236b5c38135f5809ee13838c9e7d..cfadc54573da05e68d062926418add71fe531d32
--- a/files/settings.php
+++ b/apps/files/settings.php
@@ -23,14 +23,14 @@
 
 
 // Init owncloud
-require_once('../lib/base.php');
+ 
 
 // Check if we are a user
-OC_Util::checkLoggedIn();
+OCP\User::checkLoggedIn();
 
 // Load the files we need
-OC_Util::addStyle( "files", "files" );
-OC_Util::addScript( "files", "files" );
+OCP\Util::addStyle( "files", "files" );
+OCP\Util::addscript( "files", "files" );
 
 // Load the files
 $dir = isset( $_GET['dir'] ) ? $_GET['dir'] : '';
diff --git a/files/templates/admin.php b/apps/files/templates/admin.php
old mode 100644
new mode 100755
similarity index 73%
rename from files/templates/admin.php
rename to apps/files/templates/admin.php
index 9bcc40e9361c2f9f11c54a7bd9239de0f6bb31bc..c89070ce52ef8c11677a680429eeae9b1ecbd398
--- a/files/templates/admin.php
+++ b/apps/files/templates/admin.php
@@ -1,4 +1,4 @@
-<?php OC_Util::addScript('files','admin'); ?>
+<?php OCP\Util::addscript('files','admin'); ?>
 
 <form name="filesForm" action='#' method='post'>
 	<fieldset class="personalblock">
@@ -7,9 +7,13 @@
 			<label for="maxUploadSize"><?php echo $l->t( 'Maximum upload size' ); ?> </label><input name='maxUploadSize' id="maxUploadSize" value='<?php echo $_['uploadMaxFilesize'] ?>'/>(<?php echo $l->t('max. possible: '); echo $_['maxPossibleUploadSize'] ?>)<br/>
 		<?php endif;?>
 		<input type="checkbox" name="allowZipDownload" id="allowZipDownload" value="1" title="<?php echo $l->t( 'Needed for multi-file and folder downloads.' ); ?>"<?php if ($_['allowZipDownload']) echo ' checked="checked"'; ?> /> <label for="allowZipDownload"><?php echo $l->t( 'Enable ZIP-download' ); ?></label> <br/>
-		<fieldset class="personalblock">
-			<label for="maxZipInputSize"><?php echo $l->t( 'Maximum input size for ZIP files:' ); ?> </label><input name="maxZipInputSize" id="maxZipInputSize" value='<?php echo $_['maxZipInputSize'] ?>' title="<?php echo $l->t( '0 is unlimited' ); ?>"<?php if (!$_['allowZipDownload']) echo ' disabled="disabled"'; ?> /><br/>
-		</fieldset>
+
+			<input name="maxZipInputSize" id="maxZipInputSize" style="width:180px;" value='<?php echo $_['maxZipInputSize'] ?>' title="<?php echo $l->t( '0 is unlimited' ); ?>"<?php if (!$_['allowZipDownload']) echo ' disabled="disabled"'; ?> />
+			<label for="maxZipInputSize"><?php echo $l->t( 'Maximum input size for ZIP files' ); ?> </label><br />
+
 		<input type="submit" name="submitFilesAdminSettings" id="submitFilesAdminSettings" value="Save"/>
 	</fieldset>
 </form>
+
+
+
diff --git a/files/templates/index.php b/apps/files/templates/index.php
old mode 100644
new mode 100755
similarity index 70%
rename from files/templates/index.php
rename to apps/files/templates/index.php
index f591d066d8c65c56f93db4e10fb264d3f1ca4bc5..251936483877edf24b8f9cf69c7b529822d1ee30
--- a/files/templates/index.php
+++ b/apps/files/templates/index.php
@@ -2,7 +2,7 @@
 <div id="controls">
 	<?php echo($_['breadcrumb']); ?>
 	<?php if (!isset($_['readonly']) || !$_['readonly']):?>
-		<div class="actions">
+		<div class="actions <?php if (isset($_['files']) and ! $_['readonly'] and count($_['files'])==0):?>emptyfolder<?php endif; ?>">
 			<div id='new' class='button'>
 				<a><?php echo $l->t('New');?></a>
 				<ul class="popup popupTop">
@@ -12,16 +12,21 @@
 				</ul>
 			</div>
 			<div class="file_upload_wrapper svg">
-				<form data-upload-id='1' class="file_upload_form" action="ajax/upload.php" method="post" enctype="multipart/form-data" target="file_upload_target_1">
+				<form data-upload-id='1' class="file_upload_form" action="<?php echo OCP\Util::linkTo('files', 'ajax/upload.php'); ?>" method="post" enctype="multipart/form-data" target="file_upload_target_1">
 					<input type="hidden" name="MAX_FILE_SIZE" value="<?php echo $_['uploadMaxFilesize'] ?>" id="max_upload">
 					<input type="hidden" class="max_human_file_size" value="(max <?php echo $_['uploadMaxHumanFilesize']; ?>)">
-					<input type="hidden" name="dir" value="<?php echo $_['dir'] ?>" id="dir">
+					<input type="hidden" name="dir" value="<?php echo htmlentities($_['dir']) ?>" id="dir">
 					<button class="file_upload_filename">&nbsp;<img class='svg action' alt="Upload" src="<?php echo image_path("core", "actions/upload.svg"); ?>" /></button>
 					<input class="file_upload_start" type="file" name='files[]'/>
 						<a href="#" class="file_upload_button_wrapper" onclick="return false;" title="<?php echo $l->t('Upload'); echo  ' max. '.$_['uploadMaxHumanFilesize'] ?>"></a>
 					<iframe name="file_upload_target_1" class='file_upload_target' src=""></iframe>
 				</form>
 			</div>
+					<div id="upload">
+						<div id="uploadprogressbar"></div>
+						<input type="button" class="stop" style="display:none" value="<?php echo $l->t('Cancel upload');?>" onclick="javascript:Files.cancelUploads();" />
+					</div>
+
 		</div>
 		<div id="file_action_panel"></div>
 	<?php else:?>
@@ -41,14 +46,14 @@
 				<?php if(!isset($_['readonly']) || !$_['readonly']) { ?><input type="checkbox" id="select_all" /><?php } ?>
 				<span class='name'><?php echo $l->t( 'Name' ); ?></span>
 				<span class='selectedActions'>
-				<?php if($_['allowZipDownload']) : ?>
-					<a href="" title="<?php echo $l->t('Download')?>" class="download"><img class='svg' alt="Download" src="<?php echo image_path("core", "actions/download.svg"); ?>" /></a>
-				<?php endif; ?>
-				<a href="" title="Share" class="share"><img class='svg' alt="Share" src="<?php echo image_path("core", "actions/share.svg"); ?>" /></a>
+					<a href="" class="share"><img class='svg' alt="Share" src="<?php echo image_path("core", "actions/share.svg"); ?>" /> <?php echo $l->t('Share')?></a>
+					<?php if($_['allowZipDownload']) : ?>
+						<a href="" class="download"><img class='svg' alt="Download" src="<?php echo image_path("core", "actions/download.svg"); ?>" /> <?php echo $l->t('Download')?></a>
+					<?php endif; ?>
 				</span>
 			</th>
 			<th id="headerSize"><?php echo $l->t( 'Size' ); ?></th>
-			<th id="headerDate"><span id="modified"><?php echo $l->t( 'Modified' ); ?></span><span class="selectedActions"><a href="" title="Delete" class="delete"><img class="svg" alt="<?php echo $l->t('Delete')?>" src="<?php echo image_path("core", "actions/delete.svg"); ?>" /></a></span></th>
+			<th id="headerDate"><span id="modified"><?php echo $l->t( 'Modified' ); ?></span><span class="selectedActions"><a href="" class="delete"><?php echo $l->t('Delete all')?> <img class="svg" alt="<?php echo $l->t('Delete')?>" src="<?php echo image_path("core", "actions/delete.svg"); ?>" /></a></span></th>
 		</tr>
 	</thead>
 	<tbody id="fileList" data-readonly="<?php echo $_['readonly'];?>">
diff --git a/files/templates/part.breadcrumb.php b/apps/files/templates/part.breadcrumb.php
similarity index 89%
rename from files/templates/part.breadcrumb.php
rename to apps/files/templates/part.breadcrumb.php
index ab81cc5c03924c5d835fdd1aee449e19c280836e..16da6bb97b418e3fb6277d1413bcebb235e5ec9b 100644
--- a/files/templates/part.breadcrumb.php
+++ b/apps/files/templates/part.breadcrumb.php
@@ -1,6 +1,6 @@
 	<?php for($i=0; $i<count($_["breadcrumb"]); $i++):
         $crumb = $_["breadcrumb"][$i]; ?>
 		<div class="crumb <?php if($i == count($_["breadcrumb"])-1) echo 'last';?> svg" data-dir='<?php echo $crumb["dir"];?>' style='background-image:url("<?php echo image_path('core','breadcrumb.png');?>")'>
-    		<a href="<?php echo $_['baseURL'].$crumb["dir"]; ?>"><?php echo htmlspecialchars($crumb["name"]); ?></a>
+    		<a href="<?php echo $_['baseURL'].$crumb["dir"]; ?>"><?php echo htmlentities($crumb["name"]); ?></a>
 		</div>
 	<?php endfor;?>
\ No newline at end of file
diff --git a/files/templates/part.list.php b/apps/files/templates/part.list.php
similarity index 92%
rename from files/templates/part.list.php
rename to apps/files/templates/part.list.php
index b117d81a1a580b7ecbb871bbaebbd23f0313856d..b2db4cbb8df00127ae7d5e6236500705a6af7e40 100644
--- a/files/templates/part.list.php
+++ b/apps/files/templates/part.list.php
@@ -18,9 +18,13 @@
 						<?php if($file['type'] == 'dir'):?>
 							<?php echo htmlspecialchars($file['name']);?>
 						<?php else:?>
-							<?php echo htmlspecialchars($file['basename']);?><span class='extention'><?php echo $file['extention'];?></span>
+							<?php echo htmlspecialchars($file['basename']);?><span class='extension'><?php echo $file['extension'];?></span>
 						<?php endif;?>
 					</span>
+					<?php if($file['type'] == 'dir'):?>
+						<span class="uploadtext" currentUploads="0">
+						</span>
+					<?php endif;?>
 					</a>
 				</td>
 				<td class="filesize" title="<?php echo human_file_size($file['size']); ?>" style="color:rgb(<?php echo $simple_size_color.','.$simple_size_color.','.$simple_size_color ?>)"><?php echo $simple_file_size; ?></td>
diff --git a/apps/files_archive/appinfo/app.php b/apps/files_archive/appinfo/app.php
old mode 100644
new mode 100755
index 67809ec980aee9446f65a3a4efe2d9b4f45a9521..0b156ced277660046c11250fff7171761d81e30b
--- a/apps/files_archive/appinfo/app.php
+++ b/apps/files_archive/appinfo/app.php
@@ -6,14 +6,8 @@
  * See the COPYING-README file.
  */
 
-OC::$CLASSPATH['OC_Archive'] = 'apps/files_archive/lib/archive.php';
-OC::$CLASSPATH['Archive_Tar'] = '3rdparty/Archive/Tar.php';
-foreach(array('ZIP','TAR') as $type){
-	OC::$CLASSPATH['OC_Archive_'.$type] = 'apps/files_archive/lib/'.strtolower($type).'.php';
-}
-
 OC::$CLASSPATH['OC_Filestorage_Archive']='apps/files_archive/lib/storage.php';
 
 OC_Hook::connect('OC_Filesystem','get_mountpoint','OC_Filestorage_Archive','autoMount');
 
-OC_Util::addScript( 'files_archive', 'archive' );
+OCP\Util::addscript( 'files_archive', 'archive' );
diff --git a/apps/files_archive/appinfo/info.xml b/apps/files_archive/appinfo/info.xml
index 236b5a64b0586b8f27025dd7ac68a4700792f81e..9872187f9b30fd5717454b5be8681f76e69c9aa8 100644
--- a/apps/files_archive/appinfo/info.xml
+++ b/apps/files_archive/appinfo/info.xml
@@ -3,11 +3,11 @@
 	<id>files_archive</id>
 	<name>Archive support</name>
 	<description>Transparent opening of archives</description>
-	<version>0.1</version>
 	<licence>AGPL</licence>
 	<author>Robin Appelman</author>
 	<require>3</require>
 	<types>
 		<filesystem/>
 	</types>
+	<default_enable/>
 </info>
diff --git a/apps/files_archive/appinfo/version b/apps/files_archive/appinfo/version
new file mode 100644
index 0000000000000000000000000000000000000000..ceab6e11ece0bcec917c12e11d350946f085d549
--- /dev/null
+++ b/apps/files_archive/appinfo/version
@@ -0,0 +1 @@
+0.1
\ No newline at end of file
diff --git a/apps/files_archive/lib/storage.php b/apps/files_archive/lib/storage.php
old mode 100644
new mode 100755
index 700d963304230d7834423ca20dd6a83cbc955370..086a338db25f26543b4300133d75d67461ad6709
--- a/apps/files_archive/lib/storage.php
+++ b/apps/files_archive/lib/storage.php
@@ -104,7 +104,7 @@ class OC_Filestorage_Archive extends OC_Filestorage_Common{
 	}
 	public function touch($path, $mtime=null){
 		if(is_null($mtime)){
-			$tmpFile=OC_Helper::tmpFile();
+			$tmpFile=OCP\Files::tmpFile();
 			$this->archive->extractFile($path,$tmpFile);
 			$this->archive->addfile($path,$tmpFile);
 		}else{
diff --git a/apps/files_archive/tests/data/data.tar.gz b/apps/files_archive/tests/data/data.tar.gz
new file mode 100644
index 0000000000000000000000000000000000000000..39f2cdada026961896bd35542d4a99c387b87fba
Binary files /dev/null and b/apps/files_archive/tests/data/data.tar.gz differ
diff --git a/apps/files_archive/tests/data/data.zip b/apps/files_archive/tests/data/data.zip
new file mode 100644
index 0000000000000000000000000000000000000000..eccef53eb4ee2d8694102fe36c4cb063091b8374
Binary files /dev/null and b/apps/files_archive/tests/data/data.zip differ
diff --git a/apps/files_archive/tests/data/lorem.txt b/apps/files_archive/tests/data/lorem.txt
new file mode 100644
index 0000000000000000000000000000000000000000..b62c3fb2ffd39a3c809ce00ed2f764936de7f83c
--- /dev/null
+++ b/apps/files_archive/tests/data/lorem.txt
@@ -0,0 +1,4 @@
+Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
+Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
+Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.
+Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
\ No newline at end of file
diff --git a/apps/files_archive/tests/storage.php b/apps/files_archive/tests/storage.php
old mode 100644
new mode 100755
index 4d0a83356bdb22a45b3dfdd132c4f15f93b7a9e5..7ebcce4ac6fdc1f6c723588fc78f92e0c29b4127
--- a/apps/files_archive/tests/storage.php
+++ b/apps/files_archive/tests/storage.php
@@ -13,7 +13,7 @@ class Test_Filestorage_Archive_Zip extends Test_FileStorage {
 	private $tmpFile;
 	
 	public function setUp(){
-		$this->tmpFile=OC_Helper::tmpFile('.zip');
+		$this->tmpFile=OCP\Files::tmpFile('.zip');
 		$this->instance=new OC_Filestorage_Archive(array('archive'=>$this->tmpFile));
 	}
 
diff --git a/apps/files_archive/tests/tar.php b/apps/files_archive/tests/tar.php
deleted file mode 100644
index 193a65b550a1e32e5d20960dc1e4aef95e3bed1d..0000000000000000000000000000000000000000
--- a/apps/files_archive/tests/tar.php
+++ /dev/null
@@ -1,20 +0,0 @@
-<?php
-/**
- * Copyright (c) 2012 Robin Appelman <icewind@owncloud.com>
- * This file is licensed under the Affero General Public License version 3 or
- * later.
- * See the COPYING-README file.
- */
-
-require_once('archive.php');
-
-class Test_Archive_TAR extends Test_Archive{
-	protected function getExisting(){
-		$dir=OC::$SERVERROOT.'/apps/files_archive/tests/data';
-		return new OC_Archive_TAR($dir.'/data.tar.gz');
-	}
-
-	protected function getNew(){
-		return new OC_Archive_TAR(OC_Helper::tmpFile('.tar.gz'));
-	}
-}
diff --git a/apps/files_archive/tests/zip.php b/apps/files_archive/tests/zip.php
deleted file mode 100644
index 3ff713eda706361be11a668ac37b5b659b835520..0000000000000000000000000000000000000000
--- a/apps/files_archive/tests/zip.php
+++ /dev/null
@@ -1,20 +0,0 @@
-<?php
-/**
- * Copyright (c) 2012 Robin Appelman <icewind@owncloud.com>
- * This file is licensed under the Affero General Public License version 3 or
- * later.
- * See the COPYING-README file.
- */
-
-require_once('archive.php');
-
-class Test_Archive_ZIP extends Test_Archive{
-	protected function getExisting(){
-		$dir=OC::$SERVERROOT.'/apps/files_archive/tests/data';
-		return new OC_Archive_ZIP($dir.'/data.zip');
-	}
-
-	protected function getNew(){
-		return new OC_Archive_ZIP(OC_Helper::tmpFile('.zip'));
-	}
-}
diff --git a/apps/files_encryption/appinfo/app.php b/apps/files_encryption/appinfo/app.php
old mode 100644
new mode 100755
index 68c445d5d775299801c846bfd8382aa109884c0e..02fc9dfa2673ad71240d9ab2d5f0d670b758fe79
--- a/apps/files_encryption/appinfo/app.php
+++ b/apps/files_encryption/appinfo/app.php
@@ -10,10 +10,10 @@ OC_Hook::connect('OC_User','post_login','OC_Crypt','loginListener');
 
 stream_wrapper_register('crypt','OC_CryptStream');
 
-if(!isset($_SESSION['enckey']) and OC_User::isLoggedIn()){//force the user to re-loggin if the encryption key isn't unlocked (happens when a user is logged in before the encryption app is enabled)
-	OC_User::logout();
+if(!isset($_SESSION['enckey']) and OCP\User::isLoggedIn()){//force the user to re-loggin if the encryption key isn't unlocked (happens when a user is logged in before the encryption app is enabled)
+	OCP\User::logout();
 	header("Location: ".OC::$WEBROOT.'/');
 	exit();
 }
 
-OC_App::registerAdmin('files_encryption', 'settings');
+OCP\App::registerAdmin('files_encryption', 'settings');
diff --git a/apps/files_encryption/appinfo/info.xml b/apps/files_encryption/appinfo/info.xml
index 691b265bf60721ca3d0914633d78edd48cd48ebb..c2e1aa9604340afc49f247eec5f214f02bc74774 100644
--- a/apps/files_encryption/appinfo/info.xml
+++ b/apps/files_encryption/appinfo/info.xml
@@ -3,7 +3,6 @@
 	<id>files_encryption</id>
 	<name>Encryption</name>
 	<description>Server side encryption of files</description>
-	<version>0.1</version>
 	<licence>AGPL</licence>
 	<author>Robin Appelman</author>
 	<require>3</require>
diff --git a/apps/files_encryption/appinfo/version b/apps/files_encryption/appinfo/version
new file mode 100644
index 0000000000000000000000000000000000000000..ceab6e11ece0bcec917c12e11d350946f085d549
--- /dev/null
+++ b/apps/files_encryption/appinfo/version
@@ -0,0 +1 @@
+0.1
\ No newline at end of file
diff --git a/apps/files_encryption/js/settings.js b/apps/files_encryption/js/settings.js
index adbf0c8724582e5cabaa9fde98c523eb9d262d82..37d62265c9439b9991ab8d9ee5f1b20604b00260 100644
--- a/apps/files_encryption/js/settings.js
+++ b/apps/files_encryption/js/settings.js
@@ -16,4 +16,9 @@ $(document).ready(function(){
 		var blackList=$('#encryption_blacklist').val().join(',');
 		OC.AppConfig.setValue('files_encryption','type_blacklist',blackList);
 	}
+
+	$('#enbale_encryption').change(function(){
+		var checked=$('#enbale_encryption').is(':checked');
+		OC.AppConfig.setValue('files_encryption','enable_encryption',(checked)?'true':'false');
+	})
 })
\ No newline at end of file
diff --git a/apps/files_encryption/lib/crypt.php b/apps/files_encryption/lib/crypt.php
old mode 100644
new mode 100755
index 246d4f672db1abdbd41d2d89ca3c40a11c2dc182..37eaedc3fc9f9916b029390e04ba184478fdffd2
--- a/apps/files_encryption/lib/crypt.php
+++ b/apps/files_encryption/lib/crypt.php
@@ -91,8 +91,8 @@ class OC_Crypt {
 	}
 
 	public static function changekeypasscode($oldPassword, $newPassword) {
-		if(OC_User::isLoggedIn()){
-			$username=OC_USER::getUser();
+		if(OCP\User::isLoggedIn()){
+			$username=OCP\USER::getUser();
 			$view=new OC_FilesystemView('/'.$username);
 
 			// read old key
@@ -119,7 +119,7 @@ class OC_Crypt {
 	 */
 	public static function encrypt( $content, $key='') {
 		$bf = self::getBlowfish($key);
-		return($bf->encrypt($content));
+		return $bf->encrypt($content);
 	}
 
 	/**
@@ -132,61 +132,62 @@ class OC_Crypt {
 	*/
 	public static function decrypt( $content, $key='') {
 		$bf = self::getBlowfish($key);
-		return($bf->decrypt($content));
+		$data=$bf->decrypt($content);
+		return rtrim($data, "\0");
 	}
 
 	/**
 	* @brief encryption of a file
-	* @param $filename
-	* @param $key the encryption key
+	* @param string $source
+	* @param string $target
+	* @param string $key the decryption key
 	*
 	* This function encrypts a file
 	*/
-	public static function encryptfile( $filename, $key) {
-		$handleread  = fopen($filename, "rb");
-		if($handleread<>FALSE) {
-			$handlewrite = fopen($filename.OC_Crypt::$encription_extension, "wb");
+	public static function encryptFile( $source, $target, $key='') {
+		$handleread  = fopen($source, "rb");
+		if($handleread!=FALSE) {
+			$handlewrite = fopen($target, "wb");
 			while (!feof($handleread)) {
 				$content = fread($handleread, 8192);
 				$enccontent=OC_CRYPT::encrypt( $content, $key);
 				fwrite($handlewrite, $enccontent);
 			}
 			fclose($handlewrite);
-			unlink($filename);
+			fclose($handleread);
 		}
-		fclose($handleread);
 	}
 
 
-        /**
-         * @brief decryption of a file
-         * @param $filename
-         * @param $key the decryption key
-         *
-         * This function decrypts a file
-         */
-	public static function decryptfile( $filename, $key) {
-		$handleread  = fopen($filename.OC_Crypt::$encription_extension, "rb");
-		if($handleread<>FALSE) {
-			$handlewrite = fopen($filename, "wb");
+	/**
+		* @brief decryption of a file
+		* @param string $source
+		* @param string $target
+		* @param string $key the decryption key
+		*
+		* This function decrypts a file
+		*/
+	public static function decryptFile( $source, $target, $key='') {
+		$handleread  = fopen($source, "rb");
+		if($handleread!=FALSE) {
+			$handlewrite = fopen($target, "wb");
 			while (!feof($handleread)) {
 				$content = fread($handleread, 8192);
 				$enccontent=OC_CRYPT::decrypt( $content, $key);
 				fwrite($handlewrite, $enccontent);
 			}
 			fclose($handlewrite);
-			unlink($filename.OC_Crypt::$encription_extension);
+			fclose($handleread);
 		}
-		fclose($handleread);
 	}
 	
 	/**
 	 * encrypt data in 8192b sized blocks
 	 */
-	public static function blockEncrypt($data){
+	public static function blockEncrypt($data, $key=''){
 		$result='';
 		while(strlen($data)){
-			$result=self::encrypt(substr($data,0,8192));
+			$result.=self::encrypt(substr($data,0,8192),$key);
 			$data=substr($data,8192);
 		}
 		return $result;
@@ -195,10 +196,10 @@ class OC_Crypt {
 	/**
 	 * decrypt data in 8192b sized blocks
 	 */
-	public static function blockDecrypt($data){
+	public static function blockDecrypt($data, $key=''){
 		$result='';
 		while(strlen($data)){
-			$result=self::decrypt(substr($data,0,8192));
+			$result.=self::decrypt(substr($data,0,8192),$key);
 			$data=substr($data,8192);
 		}
 		return $result;
diff --git a/apps/files_encryption/lib/cryptstream.php b/apps/files_encryption/lib/cryptstream.php
old mode 100644
new mode 100755
index 86583096f1dbeaba4273dad36bfd2eb829550da7..1a7c595cb838a6eabb340a98d039a302a6fbef64
--- a/apps/files_encryption/lib/cryptstream.php
+++ b/apps/files_encryption/lib/cryptstream.php
@@ -33,6 +33,7 @@ class OC_CryptStream{
 	private $path;
 	private $readBuffer;//for streams that dont support seeking
 	private $meta=array();//header/meta for source stream
+	private $count;
 
 	public function stream_open($path, $mode, $options, &$opened_path){
 		$path=str_replace('crypt://','',$path);
@@ -41,12 +42,12 @@ class OC_CryptStream{
 			$this->path=self::$sourceStreams[basename($path)]['path'];
 		}else{
 			$this->path=$path;
-			OC_Log::write('files_encryption','open encrypted '.$path. ' in '.$mode,OC_Log::DEBUG);
+			OCP\Util::writeLog('files_encryption','open encrypted '.$path. ' in '.$mode,OCP\Util::DEBUG);
 			OC_FileProxy::$enabled=false;//disable fileproxies so we can open the source file
 			$this->source=OC_FileSystem::fopen($path,$mode);
 			OC_FileProxy::$enabled=true;
 			if(!is_resource($this->source)){
-				OC_Log::write('files_encryption','failed to open '.$path,OC_Log::ERROR);
+				OCP\Util::writeLog('files_encryption','failed to open '.$path,OCP\Util::ERROR);
 			}
 		}
 		if(is_resource($this->source)){
@@ -64,29 +65,19 @@ class OC_CryptStream{
 	}
 	
 	public function stream_read($count){
-		$pos=0;
-		$currentPos=ftell($this->source);
-		$offset=$currentPos%8192;
-		$result='';
-		if($offset>0){
-			if($this->meta['seekable']){
-				fseek($this->source,-$offset,SEEK_CUR);//if seeking isnt supported the internal read buffer will be used
-			}else{
-				$pos=strlen($this->readBuffer);
-				$result=$this->readBuffer;
-			}
-		}
-		while($count>$pos){
-			$data=fread($this->source,8192);
-			$pos+=8192;
-			if(strlen($data)){
-				$result.=OC_Crypt::decrypt($data);
-			}
+		//$count will always be 8192 https://bugs.php.net/bug.php?id=21641
+		//This makes this function a lot simpler but will breake everything the moment it's fixed
+		if($count!=8192){
+			OCP\Util::writeLog('files_encryption','php bug 21641 no longer holds, decryption will not work',OCP\Util::FATAL);
+			die();
 		}
-		if(!$this->meta['seekable']){
-			$this->readBuffer=substr($result,$count);
+		$data=fread($this->source,8192);
+		if(strlen($data)){
+			$result=OC_Crypt::decrypt($data);
+		}else{
+			$result='';
 		}
-		return substr($result,0,$count);
+		return $result;
 	}
 	
 	public function stream_write($data){
@@ -102,14 +93,6 @@ class OC_CryptStream{
 			$data=substr($block,0,$currentPos%8192).$data;
 		}
 		while(strlen($data)>0){
-			if(strlen($data)<8192){
-				//fetch the current data in that block and append it to the input so we always write entire blocks
-				$oldPos=ftell($this->source);
-				$encryptedBlock=fread($this->source,8192);
-				fseek($this->source,$oldPos);
-				$block=OC_Crypt::decrypt($encryptedBlock);
-				$data.=substr($block,strlen($data));
-			}
 			$encrypted=OC_Crypt::encrypt(substr($data,0,8192));
 			fwrite($this->source,$encrypted);
 			$data=substr($data,8192);
@@ -147,7 +130,9 @@ class OC_CryptStream{
 	}
 
 	public function stream_close(){
-		OC_FileCache::put($this->path,array('encrypted'=>true));
+		if($this->meta['mode']!='r' and $this->meta['mode']!='rb'){
+			OC_FileCache::put($this->path,array('encrypted'=>true));
+		}
 		return fclose($this->source);
 	}
-}
\ No newline at end of file
+}
diff --git a/apps/files_encryption/lib/proxy.php b/apps/files_encryption/lib/proxy.php
old mode 100644
new mode 100755
index c1c26d7754f31c9498ce6983bbef6028c47a9b93..06f963fc98173626155420e923779e9effbf712b
--- a/apps/files_encryption/lib/proxy.php
+++ b/apps/files_encryption/lib/proxy.php
@@ -27,7 +27,7 @@
 
 class OC_FileProxy_Encryption extends OC_FileProxy{
 	private static $blackList=null; //mimetypes blacklisted from encryption
-	private static $metaData=array(); //metadata cache
+	private static $enableEncryption=null;
 	
 	/**
 	 * check if a file should be encrypted during write
@@ -35,14 +35,20 @@ class OC_FileProxy_Encryption extends OC_FileProxy{
 	 * @return bool
 	 */
 	private static function shouldEncrypt($path){
+		if(is_null(self::$enableEncryption)){
+			self::$enableEncryption=(OCP\Config::getAppValue('files_encryption','enable_encryption','true')=='true');
+		}
+		if(!self::$enableEncryption){
+			return false;
+		}
 		if(is_null(self::$blackList)){
-			self::$blackList=explode(',',OC_Appconfig::getValue('files_encryption','type_blacklist','jpg,png,jpeg,avi,mpg,mpeg,mkv,mp3,oga,ogv,ogg'));
+			self::$blackList=explode(',',OCP\Config::getAppValue('files_encryption','type_blacklist','jpg,png,jpeg,avi,mpg,mpeg,mkv,mp3,oga,ogv,ogg'));
 		}
 		if(self::isEncrypted($path)){
 			return true;
 		}
-		$extention=substr($path,strrpos($path,'.')+1);
-		if(array_search($extention,self::$blackList)===false){
+		$extension=substr($path,strrpos($path,'.')+1);
+		if(array_search($extension,self::$blackList)===false){
 			return true;
 		}
 	}
@@ -53,13 +59,8 @@ class OC_FileProxy_Encryption extends OC_FileProxy{
 	 * @return bool
 	 */
 	private static function isEncrypted($path){
-		if(isset(self::$metaData[$path])){
-			$metadata=self::$metaData[$path];
-		}else{
-			$metadata=OC_FileCache::getCached($path);
-			self::$metaData[$path]=$metadata;
-		}
-		return (bool)$metadata['encrypted'];
+		$metadata=OC_FileCache::getCached($path);
+		return isset($metadata['encrypted']) and (bool)$metadata['encrypted'];
 	}
 	
 	public function preFile_put_contents($path,&$data){
@@ -89,14 +90,9 @@ class OC_FileProxy_Encryption extends OC_FileProxy{
 		}elseif(self::shouldEncrypt($path) and $meta['mode']!='r' and $meta['mode']!='rb'){
 			if(OC_Filesystem::file_exists($path) and OC_Filesystem::filesize($path)>0){
 				//first encrypt the target file so we don't end up with a half encrypted file
-				OC_Log::write('files_encryption','Decrypting '.$path.' before writing',OC_Log::DEBUG);
+				OCP\Util::writeLog('files_encryption','Decrypting '.$path.' before writing',OCP\Util::DEBUG);
 				$tmp=fopen('php://temp');
-				while(!feof($result)){
-					$chunk=fread($result,8192);
-					if($chunk){
-						fwrite($tmp,$chunk);
-					}
-				}
+				OCP\Files::streamCopy($result,$tmp);
 				fclose($result);
 				OC_Filesystem::file_put_contents($path,$tmp);
 				fclose($tmp);
@@ -108,7 +104,7 @@ class OC_FileProxy_Encryption extends OC_FileProxy{
 
 	public function postGetMimeType($path,$mime){
 		if(self::isEncrypted($path)){
-			$mime=OC_Helper::getMimeType('crypt://'.$path,'w');
+			$mime=OCP\Files::getMimeType('crypt://'.$path,'w');
 		}
 		return $mime;
 	}
diff --git a/apps/files_encryption/settings.php b/apps/files_encryption/settings.php
old mode 100644
new mode 100755
index 396ad1ba78d7f28e9374110664dfb07169b2c699..aed9079529c1a67dc5137ee90db1391c4d70448a
--- a/apps/files_encryption/settings.php
+++ b/apps/files_encryption/settings.php
@@ -7,10 +7,12 @@
  */
 
 $tmpl = new OC_Template( 'files_encryption', 'settings');
-$blackList=explode(',',OC_Appconfig::getValue('files_encryption','type_blacklist','jpg,png,jpeg,avi,mpg,mpeg,mkv,mp3,oga,ogv,ogg'));
+$blackList=explode(',',OCP\Config::getAppValue('files_encryption','type_blacklist','jpg,png,jpeg,avi,mpg,mpeg,mkv,mp3,oga,ogv,ogg'));
+$enabled=(OCP\Config::getAppValue('files_encryption','enable_encryption','true')=='true');
 $tmpl->assign('blacklist',$blackList);
+$tmpl->assign('encryption_enabled',$enabled);
 
-OC_Util::addScript('files_encryption','settings');
-OC_Util::addScript('core','multiselect');
+OCP\Util::addscript('files_encryption','settings');
+OCP\Util::addscript('core','multiselect');
 
 return $tmpl->fetchPage();
diff --git a/apps/files_encryption/templates/settings.php b/apps/files_encryption/templates/settings.php
index 724a03836a8ea37767c8aee32155a4e5d8d19bfc..25b5a06f56ca8a02b76037df690e376f3e5d94a9 100644
--- a/apps/files_encryption/templates/settings.php
+++ b/apps/files_encryption/templates/settings.php
@@ -7,5 +7,6 @@
 				<option selected="selected" value="<?php echo $type;?>"><?php echo $type;?></option>
 			<?php endforeach;?>
 		</select>
+		<input type='checkbox' id='enbale_encryption' <?php if($_['encryption_enabled']){echo 'checked="checked"';} ?>></input><label for='enbale_encryption'><?php echo $l->t('Enable Encryption')?></label>
 	</fieldset>
 </form>
diff --git a/apps/files_encryption/tests/encryption.php b/apps/files_encryption/tests/encryption.php
new file mode 100755
index 0000000000000000000000000000000000000000..00466cc671c1b041f9a162959672e5330810deb7
--- /dev/null
+++ b/apps/files_encryption/tests/encryption.php
@@ -0,0 +1,42 @@
+<?php
+/**
+ * Copyright (c) 2012 Robin Appelman <icewind@owncloud.com>
+ * This file is licensed under the Affero General Public License version 3 or
+ * later.
+ * See the COPYING-README file.
+ */
+
+class Test_Encryption extends UnitTestCase {
+	function testEncryption(){
+		$key=uniqid();
+		$file=OC::$SERVERROOT.'/3rdparty/MDB2.php';
+		$source=file_get_contents($file); //nice large text file
+		$encrypted=OC_Crypt::encrypt($source,$key);
+		$decrypted=OC_Crypt::decrypt($encrypted,$key);
+		$this->assertNotEqual($encrypted,$source);
+		$this->assertEqual($decrypted,$source);
+
+		$chunk=substr($source,0,8192);
+		$encrypted=OC_Crypt::encrypt($chunk,$key);
+		$this->assertEqual(strlen($chunk),strlen($encrypted));
+		$decrypted=OC_Crypt::decrypt($encrypted,$key);
+		$this->assertEqual($decrypted,$chunk);
+		
+		$encrypted=OC_Crypt::blockEncrypt($source,$key);
+		$decrypted=OC_Crypt::blockDecrypt($encrypted,$key);
+		$this->assertNotEqual($encrypted,$source);
+		$this->assertEqual($decrypted,$source);
+
+		$tmpFileEncrypted=OCP\Files::tmpFile();
+		OC_Crypt::encryptfile($file,$tmpFileEncrypted,$key);
+		$encrypted=file_get_contents($tmpFileEncrypted);
+		$decrypted=OC_Crypt::blockDecrypt($encrypted,$key);
+		$this->assertNotEqual($encrypted,$source);
+		$this->assertEqual($decrypted,$source);
+
+		$tmpFileDecrypted=OCP\Files::tmpFile();
+		OC_Crypt::decryptfile($tmpFileEncrypted,$tmpFileDecrypted,$key);
+		$decrypted=file_get_contents($tmpFileDecrypted);
+		$this->assertEqual($decrypted,$source);
+	}
+}
diff --git a/apps/files_encryption/tests/stream.php b/apps/files_encryption/tests/stream.php
new file mode 100755
index 0000000000000000000000000000000000000000..b23805d60b00374e94583a94a6756ce02bc652e3
--- /dev/null
+++ b/apps/files_encryption/tests/stream.php
@@ -0,0 +1,56 @@
+<?php
+/**
+ * Copyright (c) 2012 Robin Appelman <icewind@owncloud.com>
+ * This file is licensed under the Affero General Public License version 3 or
+ * later.
+ * See the COPYING-README file.
+ */
+
+class Test_CryptStream extends UnitTestCase {
+	private $tmpFiles=array();
+	
+	function testStream(){
+		$stream=$this->getStream('test1','w');
+		fwrite($stream,'foobar');
+		fclose($stream);
+
+		$stream=$this->getStream('test1','r');
+		$data=fread($stream,6);
+		fclose($stream);
+		$this->assertEqual('foobar',$data);
+
+		$file=OC::$SERVERROOT.'/3rdparty/MDB2.php';
+		$source=fopen($file,'r');
+		$target=$this->getStream('test2','w');
+		OCP\Files::streamCopy($source,$target);
+		fclose($target);
+		fclose($source);
+
+		$stream=$this->getStream('test2','r');
+		$data=stream_get_contents($stream);
+		$original=file_get_contents($file);
+		$this->assertEqual(strlen($original),strlen($data));
+		$this->assertEqual($original,$data);
+	}
+
+	/**
+	 * get a cryptstream to a temporary file
+	 * @param string $id
+	 * @param string $mode
+	 * @return resource
+	 */
+	function getStream($id,$mode){
+		if($id===''){
+			$id=uniqid();
+		}
+		if(!isset($this->tmpFiles[$id])){
+			$file=OCP\Files::tmpFile();
+			$this->tmpFiles[$id]=$file;
+		}else{
+			$file=$this->tmpFiles[$id];
+		}
+		$stream=fopen($file,$mode);
+		OC_CryptStream::$sourceStreams[$id]=array('path'=>'dummy','stream'=>$stream);
+		return fopen('crypt://streams/'.$id,$mode);
+	}
+}
diff --git a/apps/files_external/appinfo/app.php b/apps/files_external/appinfo/app.php
index 95770b44b75446e1789aa45057a6fe9441507151..784ed032d475150134f8bf298424843db24a9680 100644
--- a/apps/files_external/appinfo/app.php
+++ b/apps/files_external/appinfo/app.php
@@ -9,3 +9,4 @@
 OC::$CLASSPATH['OC_Filestorage_FTP']='apps/files_external/lib/ftp.php';
 OC::$CLASSPATH['OC_Filestorage_DAV']='apps/files_external/lib/webdav.php';
 OC::$CLASSPATH['OC_Filestorage_Google']='apps/files_external/lib/google.php';
+OC::$CLASSPATH['OC_Filestorage_SWIFT']='apps/files_external/lib/swift.php';
diff --git a/apps/files_external/appinfo/info.xml b/apps/files_external/appinfo/info.xml
index fb58297ff172c9ccb5ebf55085a4002d13cea1f9..1918925389de69ca1395d9a539e14f570e835e23 100644
--- a/apps/files_external/appinfo/info.xml
+++ b/apps/files_external/appinfo/info.xml
@@ -3,7 +3,6 @@
 	<id>files_external</id>
 	<name>External storage support</name>
 	<description>Mount external storage sources</description>
-	<version>0.1</version>
 	<licence>AGPL</licence>
 	<author>Robin Appelman</author>
 	<require>3</require>
diff --git a/apps/files_external/appinfo/version b/apps/files_external/appinfo/version
new file mode 100644
index 0000000000000000000000000000000000000000..ceab6e11ece0bcec917c12e11d350946f085d549
--- /dev/null
+++ b/apps/files_external/appinfo/version
@@ -0,0 +1 @@
+0.1
\ No newline at end of file
diff --git a/apps/files_external/lib/ftp.php b/apps/files_external/lib/ftp.php
old mode 100644
new mode 100755
index 802446b4fd8536345bee78d33397bb1910ac9013..981eeab58bf3b1cad0e2e785bfcb51700f739fb9
--- a/apps/files_external/lib/ftp.php
+++ b/apps/files_external/lib/ftp.php
@@ -108,7 +108,7 @@ class OC_FileStorage_FTP extends OC_Filestorage_Common{
 				}else{
 					$ext='';
 				}
-				$tmpFile=OC_Helper::tmpFile($ext);
+				$tmpFile=OCP\Files::tmpFile($ext);
 				OC_CloseStreamWrapper::$callBacks[$tmpFile]=array($this,'writeBack');
 				if($this->file_exists($path)){
 					$this->getFile($path,$tmpFile);
diff --git a/apps/files_external/lib/google.php b/apps/files_external/lib/google.php
old mode 100644
new mode 100755
index 0d6db1987f85cb71187f6bee747c50160041610c..d2285a6d82ce15830016a62c7c5e4b834e7c8059
--- a/apps/files_external/lib/google.php
+++ b/apps/files_external/lib/google.php
@@ -29,6 +29,8 @@ class OC_Filestorage_Google extends OC_Filestorage_Common {
 	private $sig_method;
 	private $entries;
 
+	private static $tempFiles = array();
+
 	public function __construct($arguments) {
 		$consumer_key = isset($arguments['consumer_key']) ? $arguments['consumer_key'] : 'anonymous';
 		$consumer_secret = isset($arguments['consumer_secret']) ? $arguments['consumer_secret'] : 'anonymous';
@@ -38,11 +40,11 @@ class OC_Filestorage_Google extends OC_Filestorage_Common {
 		$this->entries = array();
 	}
 
-	private function sendRequest($feedUri, $http_method, $isDownload = false, $postData = null) {
-		$feedUri = trim($feedUri);
+	private function sendRequest($uri, $httpMethod, $postData = null, $extraHeaders = null, $isDownload = false, $returnHeaders = false, $isContentXML = true) {
+		$uri = trim($uri);
 		// create an associative array from each key/value url query param pair.
 		$params = array();
-		$pieces = explode('?', $feedUri);
+		$pieces = explode('?', $uri);
 		if (isset($pieces[1])) {
 			$params = explode_assoc('=', '&', $pieces[1]);
 		}
@@ -51,16 +53,22 @@ class OC_Filestorage_Google extends OC_Filestorage_Common {
 		foreach ($params as $key => $value) {
 			$tempStr .= '&' . urlencode($key) . '=' . urlencode($value);
 		}
-		$feedUri = preg_replace('/&/', '?', $tempStr, 1);
-		$request = OAuthRequest::from_consumer_and_token($this->consumer, $this->oauth_token, $http_method, $feedUri, $params);
+		$uri = preg_replace('/&/', '?', $tempStr, 1);
+		$request = OAuthRequest::from_consumer_and_token($this->consumer, $this->oauth_token, $httpMethod, $uri, $params);
 		$request->sign_request($this->sig_method, $this->consumer, $this->oauth_token);
 		$auth_header = $request->to_header();
-		$headers = array($auth_header, 'Content-Type: application/atom+xml', 'GData-Version: 3.0');
-		$curl = curl_init($feedUri);
+		$headers = array($auth_header, 'GData-Version: 3.0');
+		if ($isContentXML) {
+			$headers = array_merge($headers, array('Content-Type: application/atom+xml'));
+		}
+		if (is_array($extraHeaders)) {
+			$headers = array_merge($headers, $extraHeaders);
+		}
+		$curl = curl_init($uri);
 		curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
 		curl_setopt($curl, CURLOPT_FAILONERROR, false);
 		curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
-		switch ($http_method) {
+		switch ($httpMethod) {
 			case 'GET':
 				curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
 				break;
@@ -72,30 +80,50 @@ class OC_Filestorage_Google extends OC_Filestorage_Common {
 			case 'PUT':
 				$headers[] = 'If-Match: *';
 				curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
-				curl_setopt($curl, CURLOPT_CUSTOMREQUEST, $http_method);
+				curl_setopt($curl, CURLOPT_CUSTOMREQUEST, $httpMethod);
 				curl_setopt($curl, CURLOPT_POSTFIELDS, $postData);
 				break;
 			case 'DELETE':
 				$headers[] = 'If-Match: *';
 				curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
-				curl_setopt($curl, CURLOPT_CUSTOMREQUEST, $http_method);
+				curl_setopt($curl, CURLOPT_CUSTOMREQUEST, $httpMethod);
 				break;
 			default:
 				curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
 		}
 		if ($isDownload) {
 			$tmpFile = OC_Helper::tmpFile();
-			$fp = fopen($tmpFile, 'w');
-			curl_setopt($curl, CURLOPT_FILE, $fp);
-			curl_exec($curl);
-			curl_close($curl);
-			return $tmpFile;
+			$handle = fopen($tmpFile, 'w');
+			curl_setopt($curl, CURLOPT_FILE, $handle);
+		}
+		if ($returnHeaders) {
+			curl_setopt($curl, CURLOPT_HEADER, true);
 		}
 		$result = curl_exec($curl);
+		$httpCode = curl_getinfo($curl, CURLINFO_HTTP_CODE);
 		curl_close($curl);
-		$dom = new DOMDocument();
-		$dom->loadXML($result);
-		return $dom;
+		if ($result) {
+			// TODO https://developers.google.com/google-apps/documents-list/#handling_api_errors
+			// TODO Log error messages
+			if ($httpCode <= 308) {
+				if ($isDownload) {
+					return $tmpFile;
+				} else {
+					return $result;
+				}
+			}
+		}
+		return false; 
+	}
+
+	private function getFeed($feedUri, $httpMethod, $postData = null) {
+		$result = $this->sendRequest($feedUri, $httpMethod, $postData);
+		if ($result) {
+			$dom = new DOMDocument();
+			$dom->loadXML($result);
+			return $dom;
+		}
+		return false;
 	}
 
 	private function getResource($path) {
@@ -106,14 +134,14 @@ class OC_Filestorage_Google extends OC_Filestorage_Common {
 			// Strip the file extension; file could be a native Google Docs resource
 			if ($pos = strpos($file, '.')) {
 				$title = substr($file, 0, $pos);
-				$dom = $this->sendRequest('https://docs.google.com/feeds/default/private/full?showfolders=true&title='.$title, 'GET');
+				$dom = $this->getFeed('https://docs.google.com/feeds/default/private/full?showfolders=true&title='.$title, 'GET');
 				// Check if request was successful and entry exists
 				if ($dom && $entry = $dom->getElementsByTagName('entry')->item(0)) {
 					$this->entries[$file] = $entry;
 					return $entry;
 				}
 			}
-			$dom = $this->sendRequest('https://docs.google.com/feeds/default/private/full?showfolders=true&title='.$file, 'GET');
+			$dom = $this->getFeed('https://docs.google.com/feeds/default/private/full?showfolders=true&title='.$file, 'GET');
 			// Check if request was successful and entry exists
 			if ($dom && $entry = $dom->getElementsByTagName('entry')->item(0)) {
 				$this->entries[$file] = $entry;
@@ -143,15 +171,15 @@ class OC_Filestorage_Google extends OC_Filestorage_Common {
 	
 
 	public function mkdir($path) {
-		$dir = dirname($path);
+		$collection = dirname($path);
 		// Check if path parent is root directory
-		if ($dir == '/' || $dir == '\.' || $dir == '.') {
-			$feedUri = 'https://docs.google.com/feeds/default/private/full';
+		if ($collection == '/' || $collection == '\.' || $collection == '.') {
+			$uri = 'https://docs.google.com/feeds/default/private/full';
 		// Get parent content link
 		} else if ($dom = $this->getResource(basename($dir))) {
-			$feedUri = $dom->getElementsByTagName('content')->item(0)->getAttribute('src');
+			$uri = $dom->getElementsByTagName('content')->item(0)->getAttribute('src');
 		}
-		if (isset($feedUri)) {
+		if (isset($uri)) {
 			$title = basename($path);
 			// Construct post data
 			$postData = '<?xml version="1.0" encoding="UTF-8"?>';
@@ -159,7 +187,7 @@ class OC_Filestorage_Google extends OC_Filestorage_Common {
 			$postData .= '<category scheme="http://schemas.google.com/g/2005#kind" term="http://schemas.google.com/docs/2007#folder"/>';
 			$postData .= '<title>'.$title.'</title>';
 			$postData .= '</entry>';
-			if ($dom = $this->sendRequest($feedUri, 'POST', $postData)) {
+			if ($dom = $this->sendRequest($uri, 'POST', $postData)) {
 				return true;
 			}
 		}
@@ -182,7 +210,7 @@ class OC_Filestorage_Google extends OC_Filestorage_Common {
 		}
 		$files = array();
 		while ($next) {
-			$dom = $this->sendRequest($next, 'GET');
+			$dom = $this->getFeed($next, 'GET');
 			$links = $dom->getElementsByTagName('link');
 			foreach ($links as $link) {
 				if ($link->getAttribute('rel') == 'next') {
@@ -286,72 +314,170 @@ class OC_Filestorage_Google extends OC_Filestorage_Common {
 			$links = $entry->getElementsByTagName('link');
 			foreach ($links as $link) {
 				if ($link->getAttribute('rel') == 'self') {
-					$feedUri = $link->getAttribute('href');
+					$uri = $link->getAttribute('href');
+					break;
 				}
 			}
 		}
-		if (isset($feedUri)) {
-			$this->sendRequest($feedUri, 'DELETE');
+		if (isset($uri)) {
+			$this->sendRequest($uri, 'DELETE');
 			return true;
 		}
 		return false;
 	}
 
 	public function rename($path1, $path2) {
-		// TODO Add support for moving to different collections
-		// Get resource edit link to rename resource
 		if ($entry = $this->getResource($path1)) {
-			$etag = $entry->getElementsByTagName('entry')->item(0)->getAttribute('gd:etag');
-			$links = $entry->getElementsByTagName('link');
-			foreach ($links as $link) {
-				if ($link->getAttribute('rel') == 'edit') {
-					$feedUri = $link->getAttribute('href');
+			$collection = dirname($path2);
+			if (dirname($path1) == $collection) {
+				// Get resource edit link to rename resource
+				$etag = $entry->getAttribute('gd:etag');
+				$links = $entry->getElementsByTagName('link');
+				foreach ($links as $link) {
+					if ($link->getAttribute('rel') == 'edit') {
+						$uri = $link->getAttribute('href');
+						break;
+					}
+				}
+				$title = basename($path);
+				// Construct post data
+				$postData = '<?xml version="1.0" encoding="UTF-8"?>';
+				$postData .= '<entry xmlns="http://www.w3.org/2005/Atom" xmlns:docs="http://schemas.google.com/docs/2007" xmlns:gd="http://schemas.google.com/g/2005" gd:etag='.$etag.'>';
+				$postData .= '<title>'.$title.'</title>';
+				$postData .= '</entry>';
+				$this->sendRequest($uri, 'PUT', $postData);
+				return true;
+			} else {
+				// Move to different collection
+				if ($collectionEntry = $this->getResource($collection)) {
+					$feedUri = $colelctionEntry->getElementsByTagName('content')->item(0)->getAttribute('src');
+					// Construct post data
+					$postData = '<?xml version="1.0" encoding="UTF-8"?>';
+					$postData .= '<entry xmlns="http://www.w3.org/2005/Atom">';
+					$postData .= '<id>'.$entry->getElementsByTagName('id')->item(0).'</id>';
+					$postData .= '</entry>';
+					$this->sendRequest($uri, 'POST', $postData);
+					return true;
 				}
 			}
 		}
-		if (isset($etag) && isset($feedUri)) {
-			$title = basename($path2);
-			// Construct post data
-			$postData = '<?xml version="1.0" encoding="UTF-8"?>';
-			$postData .= '<entry xmlns="http://www.w3.org/2005/Atom" xmlns:docs="http://schemas.google.com/docs/2007" xmlns:gd="http://schemas.google.com/g/2005" gd:etag='.$etag.'>';
-			$postData .= '<title>'.$title.'</title>';
-			$postData .= '</entry>';
-			$this->sendRequest($feedUri, 'PUT', $postData);
-			return true;
-		}
 		return false;
 	}
 
 	public function fopen($path, $mode) {
-		if ($entry = $this->getResource($path)) {
-			switch ($mode) {
-				case 'r':
-				case 'rb':
+		switch ($mode) {
+			case 'r':
+			case 'rb':
+				if ($entry = $this->getResource($path)) {
 					$extension = $this->getExtension($entry);
 					$downloadUri = $entry->getElementsByTagName('content')->item(0)->getAttribute('src');
 					// TODO Non-native documents don't need these additional parameters
 					$downloadUri .= '&exportFormat='.$extension.'&format='.$extension;
-					$tmpFile = $this->sendRequest($downloadUri, 'GET', true);
+					$tmpFile = $this->sendRequest($downloadUri, 'GET', null, null, true);
 					return fopen($tmpFile, 'r');
-				case 'w':
-				case 'wb':
-				case 'a':
-				case 'ab':
-				case 'r+':
-				case 'w+':
-				case 'wb+':
-				case 'a+':
-				case 'x':
-				case 'x+':
-				case 'c':
-				case 'c+':
-					// TODO Edit documents
-			}
-			
+				}
+			case 'w':
+			case 'wb':
+			case 'a':
+			case 'ab':
+			case 'r+':
+			case 'w+':
+			case 'wb+':
+			case 'a+':
+			case 'x':
+			case 'x+':
+			case 'c':
+			case 'c+':
+				if (strrpos($path,'.') !== false) {
+					$ext = substr($path,strrpos($path,'.'));
+				} else {
+					$ext = '';
+				}
+				$tmpFile = OC_Helper::tmpFile($ext);
+				OC_CloseStreamWrapper::$callBacks[$tmpFile] = array($this, 'writeBack');
+				if ($this->file_exists($path)) {
+					$source = $this->fopen($path, 'r');
+					file_put_contents($tmpFile, $source);
+				}
+				self::$tempFiles[$tmpFile] = $path;
+				return fopen('close://'.$tmpFile, $mode);
 		}
 		return false;
 	}
 
+	public function writeBack($tmpFile) {
+		if (isset(self::$tempFiles[$tmpFile])) {
+			$this->uploadFile($tmpFile, self::$tempFiles[$tmpFile]);
+			unlink($tmpFile);
+		}
+	}
+
+	private function uploadFile($path, $target) {
+		$entry = $this->getResource($target);
+		if (!$entry) {
+			if (dirname($target) == '.' || dirname($target) == '/') {
+				$uploadUri = 'https://docs.google.com/feeds/upload/create-session/default/private/full/folder%3Aroot/contents';
+			} else {
+				$entry = $this->getResource(dirname($target));
+			}
+		}
+		if (!isset($uploadUri) && $entry) {
+			$etag = $entry->getAttribute('gd:etag');
+			$links = $entry->getElementsByTagName('link');
+			foreach ($links as $link) {
+				if ($link->getAttribute('rel') == 'http://schemas.google.com/g/2005#resumable-edit-media') {
+					$uploadUri = $link->getAttribute('href');
+					break;
+				}
+			}
+		}
+		if (isset($uploadUri) && $handle = fopen($path, 'r')) {
+			$uploadUri .= '?convert=false';
+			$mimetype = OC_Helper::getMimeType($path);
+			$size = filesize($path);
+			$headers = array('X-Upload-Content-Type: ' => $mimetype, 'X-Upload-Content-Length: ' => $size);
+			$postData = '<?xml version="1.0" encoding="UTF-8"?>';
+			$postData .= '<entry xmlns="http://www.w3.org/2005/Atom" xmlns:docs="http://schemas.google.com/docs/2007">';
+			$postData .= '<title>'.basename($target).'</title>';
+			$postData .= '</entry>';
+			$result = $this->sendRequest($uploadUri, 'POST', $postData, $headers, false, true);
+			if ($result) {
+				// Get location to upload file
+				if (preg_match('@^Location: (.*)$@m', $result, $matches)) {
+					$uploadUri = trim($matches[1]);
+				}
+			} else {
+				return false;
+			}
+			// 512 kB chunks
+			$chunkSize = 524288;
+			$i = 0;
+			while (!feof($handle)) {
+				if ($i + $chunkSize > $size) {
+					if ($i == 0) {
+						$chunkSize = $size;
+					} else {
+						$chunkSize = $size % $i;
+					}
+				}
+				$end = $i + $chunkSize - 1;
+				$headers = array('Content-Length: '.$chunkSize, 'Content-Type: '.$mimetype, 'Content Range: bytes '.$i.'-'.$end.'/'.$size);
+				$postData = fread($handle, $chunkSize);
+				$result = $this->sendRequest($uploadUri, 'PUT', $postData, $headers, false, true, false);
+				if ($result) {
+					// Get next location to upload file chunk
+					if (preg_match('@^Location: (.*)$@m', $result, $matches)) {
+						$uploadUri = trim($matches[1]);
+					}
+					$i += $chunkSize;
+				} else {
+					return false;
+				}
+			}
+			// TODO Wait for resource entry
+		}
+	}
+	
 	public function getMimeType($path, $entry = null) {
 		// Entry can be passed, because extension is required for opendir and the entry can't be cached without the extension
 		if ($entry == null) {
@@ -393,7 +519,7 @@ class OC_Filestorage_Google extends OC_Filestorage_Common {
 	}
 	
 	public function free_space($path) {
-		if ($dom = $this->sendRequest('https://docs.google.com/feeds/metadata/default', 'GET')) {
+		if ($dom = $this->getFeed('https://docs.google.com/feeds/metadata/default', 'GET')) {
 			// NOTE: Native Google Docs resources don't count towards quota
 			$total = $dom->getElementsByTagNameNS('http://schemas.google.com/g/2005', 'quotaBytesTotal')->item(0)->nodeValue;
 			$used = $dom->getElementsByTagNameNS('http://schemas.google.com/g/2005', 'quotaBytesUsed')->item(0)->nodeValue;
diff --git a/apps/files_external/lib/swift.php b/apps/files_external/lib/swift.php
new file mode 100755
index 0000000000000000000000000000000000000000..e3ba9c240cf7e511ef2b6221f326e9e6ff366a0e
--- /dev/null
+++ b/apps/files_external/lib/swift.php
@@ -0,0 +1,531 @@
+<?php
+/**
+ * Copyright (c) 2012 Robin Appelman <icewind@owncloud.com>
+ * This file is licensed under the Affero General Public License version 3 or
+ * later.
+ * See the COPYING-README file.
+ */
+
+require_once('php-cloudfiles/cloudfiles.php');
+
+class OC_FileStorage_SWIFT extends OC_Filestorage_Common{
+	private $host;
+	private $root;
+	private $user;
+	private $token;
+	private $secure;
+	/**
+	 * @var CF_Authentication auth
+	 */
+	private $auth;
+	/**
+	 * @var CF_Connection conn
+	 */
+	private $conn;
+	/**
+	 * @var CF_Container rootContainer
+	 */
+	private $rootContainer;
+
+	private static $tempFiles=array();
+	private $objects=array();
+	private $containers=array();
+
+	const SUBCONTAINER_FILE='.subcontainers';
+
+	/**
+	 * translate directory path to container name
+	 * @param string path
+	 * @return string
+	 */
+	private function getContainerName($path){
+		$path=trim($this->root.$path,'/');
+		return str_replace('/','\\',$path);
+	}
+
+	/**
+	 * get container by path
+	 * @param string path
+	 * @return CF_Container
+	 */
+	private function getContainer($path){
+		if($path=='' or $path=='/'){
+			return $this->rootContainer;
+		}
+		if(isset($this->containers[$path])){
+			return $this->containers[$path];
+		}
+		try{
+			$container=$this->conn->get_container($this->getContainerName($path));
+			$this->containers[$path]=$container;
+			return $container;
+		}catch(NoSuchContainerException $e){
+			return null;
+		}
+	}
+
+	/**
+	 * create container
+	 * @param string path
+	 * @return CF_Container
+	 */
+	private function createContainer($path){
+		if($path=='' or $path=='/'){
+			return $this->conn->create_container($this->getContainerName($path));
+		}
+		$parent=dirname($path);
+		if($parent=='' or $parent=='/'){
+			$parentContainer=$this->rootContainer;
+		}else{
+			if(!$this->containerExists($parent)){
+				$parentContainer=$this->createContainer($parent);
+			}else{
+				$parentContainer=$this->getContainer($parent);
+			}
+		}
+		$this->addSubContainer($parentContainer,basename($path));
+		return $this->conn->create_container($this->getContainerName($path));
+	}
+
+	/**
+	 * get object by path
+	 * @param string path
+	 * @return CF_Object
+	 */
+	private function getObject($path){
+		if(isset($this->objects[$path])){
+			return $this->objects[$path];
+		}
+		$container=$this->getContainer(dirname($path));
+		if(is_null($container)){
+			return null;
+		}else{
+			try{
+				$obj=$container->get_object(basename($path));
+				$this->objects[$path]=$obj;
+				return $obj;
+			}catch(NoSuchObjectException $e){
+				return null;
+			}
+		}
+	}
+
+	/**
+	 * get the names of all objects in a container
+	 * @param CF_Container
+	 * @return array
+	 */
+	private function getObjects($container){
+		if(is_null($container)){
+			return array();
+		}else{
+			$files=$container->get_objects();
+			foreach($files as &$file){
+				$file=$file->name;
+			}
+			return $files;
+		}
+	}
+
+	/**
+	 * create object
+	 * @param string path
+	 * @return CF_Object
+	 */
+	private function createObject($path){
+		$container=$this->getContainer(dirname($path));
+		if(!is_null($container)){
+			$container=$this->createContainer($path);
+		}
+		return $container->create_object(basename($path));
+	}
+
+	/**
+	 * check if an object exists
+	 * @param string
+	 * @return bool
+	 */
+	private function objectExists($path){
+		return !is_null($this->getObject($path));
+	}
+
+	/**
+	 * check if container for path exists
+	 * @param string path
+	 * @return bool
+	 */
+	private function containerExists($path){
+		return !is_null($this->getContainer($path));
+	}
+
+	/**
+	 * get the list of emulated sub containers
+	 * @param CF_Container container
+	 * @return array
+	 */
+	private function getSubContainers($container){
+		$tmpFile=OCP\Files::tmpFile();
+		$obj=$this->getSubContainerFile($container);
+		try{
+			$obj->save_to_filename($tmpFile);
+		}catch(Exception $e){
+			return array();
+		}
+		$obj->save_to_filename($tmpFile);
+		$containers=file($tmpFile);
+		unlink($tmpFile);
+		foreach($containers as &$sub){
+			$sub=trim($sub);
+		}
+		return $containers;
+	}
+
+	/**
+	 * add an emulated sub container
+	 * @param CF_Container container
+	 * @param string name
+	 * @return bool
+	 */
+	private function addSubContainer($container,$name){
+		if(!$name){
+			return false;
+		}
+		$tmpFile=OCP\Files::tmpFile();
+		$obj=$this->getSubContainerFile($container);
+		try{
+			$obj->save_to_filename($tmpFile);
+			$containers=file($tmpFile);
+			foreach($containers as &$sub){
+				$sub=trim($sub);
+			}
+			if(array_search($name,$containers)!==false){
+				unlink($tmpFile);
+				return false;
+			}else{
+				$fh=fopen($tmpFile,'a');
+				fwrite($fh,$name."\n");
+			}
+		}catch(Exception $e){
+			$containers=array();
+			file_put_contents($tmpFile,$name."\n");
+		}
+
+		$obj->load_from_filename($tmpFile);
+		unlink($tmpFile);
+		return true;
+	}
+
+	/**
+	 * remove an emulated sub container
+	 * @param CF_Container container
+	 * @param string name
+	 * @return bool
+	 */
+	private function removeSubContainer($container,$name){
+		if(!$name){
+			return false;
+		}
+		$tmpFile=OCP\Files::tmpFile();
+		$obj=$this->getSubContainerFile($container);
+		try{
+			$obj->save_to_filename($tmpFile);
+			$containers=file($tmpFile);
+		}catch(Exception $e){
+			return false;
+		}
+		foreach($containers as &$sub){
+			$sub=trim($sub);
+		}
+		$i=array_search($name,$containers);
+		if($i===false){
+			unlink($tmpFile);
+			return false;
+		}else{
+			unset($containers[$i]);
+			file_put_contents($tmpFile,implode("\n",$containers)."\n");
+		}
+
+		$obj->load_from_filename($tmpFile);
+		unlink($tmpFile);
+		return true;
+	}
+
+	/**
+	 * ensure a subcontainer file exists and return it's object
+	 * @param CF_Container container
+	 * @return CF_Object
+	 */
+	private function getSubContainerFile($container){
+		try{
+			return $container->get_object(self::SUBCONTAINER_FILE);
+		}catch(NoSuchObjectException $e){
+			return $container->create_object(self::SUBCONTAINER_FILE);
+		}
+	}
+
+	public function __construct($params){
+		$this->token=$params['token'];
+		$this->host=$params['host'];
+		$this->user=$params['user'];
+		$this->root=isset($params['root'])?$params['root']:'/';
+		$this->secure=isset($params['secure'])?(bool)$params['secure']:true;
+		if(substr($this->root,0,1)!='/'){
+			$this->root='/'.$this->root;
+		}
+		$this->auth = new CF_Authentication($this->user, $this->token, null, $this->host);
+		$this->auth->authenticate();
+		
+		$this->conn = new CF_Connection($this->auth);
+
+		if(!$this->containerExists($this->root)){
+			$this->rootContainer=$this->createContainer('/');
+		}else{
+			$this->rootContainer=$this->getContainer('/');
+		}
+	}
+
+
+	public function mkdir($path){
+		if($this->containerExists($path)){
+			return false;
+		}else{
+			$this->createContainer($path);
+			return true;
+		}
+	}
+
+	public function rmdir($path){
+		if(!$this->containerExists($path)){
+			return false;
+		}else{
+			$this->emptyContainer($path);
+			if($path!='' and $path!='/'){
+				$parentContainer=$this->getContainer(dirname($path));
+				$this->removeSubContainer($parentContainer,basename($path));
+			}
+			
+			$this->conn->delete_container($this->getContainerName($path));
+			unset($this->containers[$path]);
+			return true;
+		}
+	}
+
+	private function emptyContainer($path){
+		$container=$this->getContainer($path);
+		if(is_null($container)){
+			return;
+		}
+		$subContainers=$this->getSubContainers($container);
+		foreach($subContainers as $sub){
+			if($sub){
+				$this->emptyContainer($path.'/'.$sub);
+				$this->conn->delete_container($this->getContainerName($path.'/'.$sub));
+				unset($this->containers[$path.'/'.$sub]);
+			}
+		}
+
+		$objects=$this->getObjects($container);
+		foreach($objects as $object){
+			$container->delete_object($object);
+			unset($this->objects[$path.'/'.$object]);
+		}
+	}
+
+	public function opendir($path){
+		$container=$this->getContainer($path);
+		$files=$this->getObjects($container);
+		$i=array_search(self::SUBCONTAINER_FILE,$files);
+		if($i!==false){
+			unset($files[$i]);
+		}
+		$subContainers=$this->getSubContainers($container);
+		$files=array_merge($files,$subContainers);
+		$id=$this->getContainerName($path);
+		OC_FakeDirStream::$dirs[$id]=$files;
+		return opendir('fakedir://'.$id);
+	}
+
+	public function filetype($path){
+		if($this->containerExists($path)){
+			return 'dir';
+		}else{
+			return 'file';
+		}
+	}
+
+	public function is_readable($path){
+		return true;
+	}
+
+	public function is_writable($path){
+		return true;
+	}
+
+	public function file_exists($path){
+		if($this->is_dir($path)){
+			return true;
+		}else{
+			return $this->objectExists($path);
+		}
+	}
+
+	public function file_get_contents($path){
+		$obj=$this->getObject($path);
+		if(is_null($obj)){
+			return false;
+		}
+		return $obj->read();
+	}
+
+	public function file_put_contents($path,$content){
+		$obj=$this->getObject($path);
+		if(is_null($obj)){
+			$container=$this->getContainer(dirname($path));
+			if(is_null($container)){
+				return false;
+			}
+			$obj=$container->create_object(basename($path));
+		}
+		$this->resetMTime($obj);
+		return $obj->write($content);
+	}
+
+	public function unlink($path){
+		if($this->objectExists($path)){
+			$container=$this->getContainer(dirname($path));
+			$container->delete_object(basename($path));
+			unset($this->objects[$path]);
+		}else{
+			return false;
+		}
+	}
+
+	public function fopen($path,$mode){
+		$obj=$this->getObject($path);
+		if(is_null($obj)){
+			return false;
+		}
+		switch($mode){
+			case 'r':
+			case 'rb':
+				$fp = fopen('php://temp', 'r+');
+				$obj->stream($fp);
+				
+				rewind($fp);
+				return $fp;
+			case 'w':
+			case 'wb':
+			case 'a':
+			case 'ab':
+			case 'r+':
+			case 'w+':
+			case 'wb+':
+			case 'a+':
+			case 'x':
+			case 'x+':
+			case 'c':
+			case 'c+':
+				$tmpFile=$this->getTmpFile($path);
+				OC_CloseStreamWrapper::$callBacks[$tmpFile]=array($this,'writeBack');
+				self::$tempFiles[$tmpFile]=$path;
+				return fopen('close://'.$tmpFile,$mode);
+		}
+	}
+
+	public function writeBack($tmpFile){
+		if(isset(self::$tempFiles[$tmpFile])){
+			$this->fromTmpFile($tmpFile,self::$tempFiles[$tmpFile]);
+			unlink($tmpFile);
+		}
+	}
+
+	public function free_space($path){
+		return 0;
+	}
+
+	public function touch($path,$mtime=null){
+		$obj=$this->getObject($path);
+		if(is_null($obj)){
+			return false;
+		}
+		if(is_null($mtime)){
+			$mtime=time();
+		}
+		
+		//emulate setting mtime with metadata
+		$obj->metadata['Mtime']=$mtime;
+		$obj->sync_metadata();
+	}
+
+	public function rename($path1,$path2){
+		$sourceContainer=$this->getContainer(dirname($path1));
+		$targetContainer=$this->getContainer(dirname($path2));
+		$result=$sourceContainer->move_object_to(basename($path1),$targetContainer,basename($path2));
+		unset($this->objects[$path1]);
+		if($result){
+			$targetObj=$this->getObject($path2);
+			$this->resetMTime($targetObj);
+		}
+		return $result;
+	}
+
+	public function copy($path1,$path2){
+		$sourceContainer=$this->getContainer(dirname($path1));
+		$targetContainer=$this->getContainer(dirname($path2));
+		$result=$sourceContainer->copy_object_to(basename($path1),$targetContainer,basename($path2));
+		if($result){
+			$targetObj=$this->getObject($path2);
+			$this->resetMTime($targetObj);
+		}
+		return $result;
+	}
+
+	public function stat($path){
+		$obj=$this->getObject($path);
+		if(is_null($obj)){
+			return false;
+		}
+
+		if(isset($obj->metadata['Mtime']) and $obj->metadata['Mtime']>-1){
+			$mtime=$obj->metadata['Mtime'];
+		}else{
+			$mtime=strtotime($obj->last_modified);
+		}
+		return array(
+			'mtime'=>$mtime,
+			'size'=>$obj->content_length,
+			'ctime'=>-1,
+		);
+	}
+
+	private function getTmpFile($path){
+		$obj=$this->getObject($path);
+		if(!is_null($obj)){
+			$tmpFile=OCP\Files::tmpFile();
+			$obj->save_to_filename($tmpFile);
+			return $tmpFile;
+		}else{
+			return false;
+		}
+	}
+
+	private function fromTmpFile($tmpFile,$path){
+		$obj=$this->getObject($path);
+		if(is_null($obj)){
+			$obj=$this->createObject($path);
+		}
+		$obj->load_from_filename($tmpFile);
+		$this->resetMTime($obj);
+	}
+
+	/**
+	 * remove custom mtime metadata
+	 * @param CF_Object obj
+	 */
+	private function resetMTime($obj){
+		if(isset($obj->metadata['Mtime'])){
+			$obj->metadata['Mtime']=-1;
+			$obj->sync_metadata();
+		}
+	}
+}
diff --git a/apps/files_external/lib/webdav.php b/apps/files_external/lib/webdav.php
old mode 100644
new mode 100755
index 7a2da5c8ec029b1348ce4726ee31bac640c24337..07c90d4878e94b208b3abd1f4c610ba25195f19a
--- a/apps/files_external/lib/webdav.php
+++ b/apps/files_external/lib/webdav.php
@@ -150,7 +150,7 @@ class OC_FileStorage_DAV extends OC_Filestorage_Common{
 				}else{
 					$ext='';
 				}
-				$tmpFile=OC_Helper::tmpFile($ext);
+				$tmpFile=OCP\Files::tmpFile($ext);
 				OC_CloseStreamWrapper::$callBacks[$tmpFile]=array($this,'writeBack');
 				if($this->file_exists($path)){
 					$this->getFile($path,$tmpFile);
diff --git a/apps/files_external/tests/config.php b/apps/files_external/tests/config.php
index fa4c74a6e26327f8ffb211dcd2571e3c5fc2f67f..5b6517755f29b5f2b9fc2e8f31e55ba86362b2e9 100644
--- a/apps/files_external/tests/config.php
+++ b/apps/files_external/tests/config.php
@@ -21,5 +21,12 @@ return array(
 		'token'=>'test',
 		'token_secret'=>'test',
 		'root'=>'/google',
-	)
+	),
+	'swift'=>array(
+		'run'=>false,
+		'user'=>'test:tester',
+		'token'=>'testing',
+		'host'=>'localhost:8080/auth',
+		'root'=>'/',
+	),
 );
diff --git a/apps/files_external/tests/ftp.php b/apps/files_external/tests/ftp.php
old mode 100644
new mode 100755
index e30fb9a1c3869be6c84a9715fb116fe948eda83f..68481b4e66bcca947862b2348ce510ed5647af70
--- a/apps/files_external/tests/ftp.php
+++ b/apps/files_external/tests/ftp.php
@@ -23,7 +23,7 @@ if(!is_array($config) or !isset($config['ftp']) or !$config['ftp']['run']){
 		}
 
 		public function tearDown(){
-			OC_Helper::rmdirr($this->instance->constructUrl(''));
+			OCP\Files::rmdirr($this->instance->constructUrl(''));
 		}
 	}
 }
diff --git a/apps/files_external/tests/swift.php b/apps/files_external/tests/swift.php
new file mode 100644
index 0000000000000000000000000000000000000000..f0bde6ed605ae5f09c7b0a42f6759a2b2a0d6570
--- /dev/null
+++ b/apps/files_external/tests/swift.php
@@ -0,0 +1,32 @@
+<?php
+/**
+ * Copyright (c) 2012 Robin Appelman <icewind@owncloud.com>
+ * This file is licensed under the Affero General Public License version 3 or
+ * later.
+ * See the COPYING-README file.
+ */
+
+$config=include('apps/files_external/tests/config.php');
+if(!is_array($config) or !isset($config['swift']) or !$config['swift']['run']){
+	abstract class Test_Filestorage_SWIFT extends Test_FileStorage{}
+	return;
+}else{
+	class Test_Filestorage_SWIFT extends Test_FileStorage {
+		private $config;
+		private $id;
+
+		public function setUp(){
+			$id=uniqid();
+			$this->config=include('apps/files_external/tests/config.php');
+			$this->config['swift']['root'].='/'.$id;//make sure we have an new empty folder to work in
+			$this->instance=new OC_Filestorage_SWIFT($this->config['swift']);
+		}
+
+		
+		public function tearDown(){
+		    $this->instance->rmdir('');
+		}
+		
+	}
+}
+
diff --git a/apps/files_imageviewer/appinfo/app.php b/apps/files_imageviewer/appinfo/app.php
old mode 100644
new mode 100755
index 0f77076b79ba8968173e32a8b7cd90cd616b487d..6c8d8c30cade13aff96ea55fb3bf2137a3ea4a76
--- a/apps/files_imageviewer/appinfo/app.php
+++ b/apps/files_imageviewer/appinfo/app.php
@@ -1,8 +1,8 @@
 <?php
 
-OC_Util::addScript( 'files_imageviewer', 'lightbox' );
-OC_Util::addScript('files_imageviewer', 'jquery.mousewheel-3.0.4.pack');
-OC_Util::addScript('files_imageviewer', 'jquery.fancybox-1.3.4.pack');
-OC_Util::addStyle( 'files_imageviewer', 'jquery.fancybox-1.3.4' );
+OCP\Util::addscript( 'files_imageviewer', 'lightbox' );
+OCP\Util::addscript('files_imageviewer', 'jquery.mousewheel-3.0.4.pack');
+OCP\Util::addscript('files_imageviewer', 'jquery.fancybox-1.3.4.pack');
+OCP\Util::addStyle( 'files_imageviewer', 'jquery.fancybox-1.3.4' );
 
 ?>
diff --git a/apps/files_imageviewer/appinfo/info.xml b/apps/files_imageviewer/appinfo/info.xml
index 00b55c254dd727fe189bcb6484eb238ce19a2dab..dbc78ffba0f8bc5c2906cd6f971a49af5bfb8ab2 100644
--- a/apps/files_imageviewer/appinfo/info.xml
+++ b/apps/files_imageviewer/appinfo/info.xml
@@ -3,7 +3,6 @@
 	<id>files_imageviewer</id>
 	<name>Image Viewer</name>
 	<description>Simple image viewer for owncloud</description>
-	<version>1.0</version>
 	<licence>AGPL</licence>
 	<author>Robin Appelman</author>
 	<require>2</require>
diff --git a/apps/files_imageviewer/appinfo/version b/apps/files_imageviewer/appinfo/version
new file mode 100644
index 0000000000000000000000000000000000000000..9f8e9b69a33f4e8067d5b21661a35d8856758aba
--- /dev/null
+++ b/apps/files_imageviewer/appinfo/version
@@ -0,0 +1 @@
+1.0
\ No newline at end of file
diff --git a/apps/files_imageviewer/css/jquery.fancybox-1.3.4.css b/apps/files_imageviewer/css/jquery.fancybox-1.3.4.css
index 1dfd9b95d35ce0d58e1171912212219374df8bc4..5fdf7af14cbc790c9d60d133d42072ce485f363d 100644
--- a/apps/files_imageviewer/css/jquery.fancybox-1.3.4.css
+++ b/apps/files_imageviewer/css/jquery.fancybox-1.3.4.css
@@ -35,7 +35,7 @@
 	left: 0;
 	width: 40px;
 	height: 480px;
-	background-image: url('../img/fancybox.png');
+	background-image: url('%appswebroot%/apps/files_imageviewer/img/fancybox.png');
 }
 
 #fancybox-overlay {
@@ -99,7 +99,7 @@
 	right: -15px;
 	width: 30px;
 	height: 30px;
-	background: transparent url('../img/fancybox.png') -40px 0px;
+	background: transparent url('%appswebroot%/apps/files_imageviewer/img/fancybox.png') -40px 0px;
 	cursor: pointer;
 	z-index: 1103;
 	display: none;
@@ -137,7 +137,7 @@
 	width: 35%;
 	cursor: pointer;
 	outline: none;
-	background: transparent url('../img/blank.gif');
+	background: transparent url('%appswebroot%/apps/files_imageviewer/img/blank.gif');
 	z-index: 1102;
 	display: none;
 }
@@ -163,12 +163,12 @@
 }
 
 #fancybox-left-ico {
-	background-image: url('../img/fancybox.png');
+	background-image: url('%appswebroot%/apps/files_imageviewer/img/fancybox.png');
 	background-position: -40px -30px;
 }
 
 #fancybox-right-ico {
-	background-image: url('../img/fancybox.png');
+	background-image: url('%appswebroot%/apps/files_imageviewer/img/fancybox.png');
 	background-position: -40px -60px;
 }
 
@@ -199,13 +199,13 @@
 	top: -20px;
 	left: 0;
 	width: 100%;
-	background-image: url('../img/fancybox-x.png');
+	background-image: url('%appswebroot%/apps/files_imageviewer/img/fancybox-x.png');
 }
 
 #fancybox-bg-ne {
 	top: -20px;
 	right: -20px;
-	background-image: url('../img/fancybox.png');
+	background-image: url('%appswebroot%/apps/files_imageviewer/img/fancybox.png');
 	background-position: -40px -162px;
 }
 
@@ -213,14 +213,14 @@
 	top: 0;
 	right: -20px;
 	height: 100%;
-	background-image: url('../img/fancybox-y.png');
+	background-image: url('%appswebroot%/apps/files_imageviewer/img/fancybox-y.png');
 	background-position: -20px 0px;
 }
 
 #fancybox-bg-se {
 	bottom: -20px;
 	right: -20px;
-	background-image: url('../img/fancybox.png');
+	background-image: url('%appswebroot%/apps/files_imageviewer/img/fancybox.png');
 	background-position: -40px -182px; 
 }
 
@@ -228,14 +228,14 @@
 	bottom: -20px;
 	left: 0;
 	width: 100%;
-	background-image: url('../img/fancybox-x.png');
+	background-image: url('%appswebroot%/apps/files_imageviewer/img/fancybox-x.png');
 	background-position: 0px -20px;
 }
 
 #fancybox-bg-sw {
 	bottom: -20px;
 	left: -20px;
-	background-image: url('../img/fancybox.png');
+	background-image: url('%appswebroot%/apps/files_imageviewer/img/fancybox.png');
 	background-position: -40px -142px;
 }
 
@@ -243,13 +243,13 @@
 	top: 0;
 	left: -20px;
 	height: 100%;
-	background-image: url('../img/fancybox-y.png');
+	background-image: url('%appswebroot%/apps/files_imageviewer/img/fancybox-y.png');
 }
 
 #fancybox-bg-nw {
 	top: -20px;
 	left: -20px;
-	background-image: url('../img/fancybox.png');
+	background-image: url('%appswebroot%/apps/files_imageviewer/img/fancybox.png');
 	background-position: -40px -122px;
 }
 
@@ -282,7 +282,7 @@
 
 #fancybox-title-over {
 	padding: 10px;
-	background-image: url('../img/fancy_title_over.png');
+	background-image: url('%appswebroot%/apps/files_imageviewer/img/fancy_title_over.png');
 	display: block;
 }
 
@@ -306,7 +306,7 @@
 
 #fancybox-title-float-left {
 	padding: 0 0 0 15px;
-	background: url('../img/fancybox.png') -40px -90px no-repeat;
+	background: url('%appswebroot%/apps/files_imageviewer/img/fancybox.png') -40px -90px no-repeat;
 }
 
 #fancybox-title-float-main {
@@ -314,25 +314,25 @@
 	line-height: 29px;
 	font-weight: bold;
 	padding: 0 0 3px 0;
-	background: url('../img/fancybox-x.png') 0px -40px;
+	background: url('%appswebroot%/apps/files_imageviewer/img/fancybox-x.png') 0px -40px;
 }
 
 #fancybox-title-float-right {
 	padding: 0 0 0 15px;
-	background: url('../img/fancybox.png') -55px -90px no-repeat;
+	background: url('%appswebroot%/apps/files_imageviewer/img/fancybox.png') -55px -90px no-repeat;
 }
 
 /* IE6 */
 
-.fancybox-ie6 #fancybox-close { background: transparent; filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='../img/fancy_close.png', sizingMethod='scale'); }
+.fancybox-ie6 #fancybox-close { background: transparent; filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='%appswebroot%/apps/files_imageviewer/img/fancy_close.png', sizingMethod='scale'); }
 
-.fancybox-ie6 #fancybox-left-ico { background: transparent; filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='../img/fancy_nav_left.png', sizingMethod='scale'); }
-.fancybox-ie6 #fancybox-right-ico { background: transparent; filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='../img/fancy_nav_right.png', sizingMethod='scale'); }
+.fancybox-ie6 #fancybox-left-ico { background: transparent; filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='%appswebroot%/apps/files_imageviewer/img/fancy_nav_left.png', sizingMethod='scale'); }
+.fancybox-ie6 #fancybox-right-ico { background: transparent; filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='%appswebroot%/apps/files_imageviewer/img/fancy_nav_right.png', sizingMethod='scale'); }
 
-.fancybox-ie6 #fancybox-title-over { background: transparent; filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='../img/fancy_title_over.png', sizingMethod='scale'); zoom: 1; }
-.fancybox-ie6 #fancybox-title-float-left { background: transparent; filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='../img/fancy_title_left.png', sizingMethod='scale'); }
-.fancybox-ie6 #fancybox-title-float-main { background: transparent; filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='../img/fancy_title_main.png', sizingMethod='scale'); }
-.fancybox-ie6 #fancybox-title-float-right { background: transparent; filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='../img/fancy_title_right.png', sizingMethod='scale'); }
+.fancybox-ie6 #fancybox-title-over { background: transparent; filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='%appswebroot%/apps/files_imageviewer/img/fancy_title_over.png', sizingMethod='scale'); zoom: 1; }
+.fancybox-ie6 #fancybox-title-float-left { background: transparent; filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='%appswebroot%/apps/files_imageviewer/img/fancy_title_left.png', sizingMethod='scale'); }
+.fancybox-ie6 #fancybox-title-float-main { background: transparent; filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='%appswebroot%/apps/files_imageviewer/img/fancy_title_main.png', sizingMethod='scale'); }
+.fancybox-ie6 #fancybox-title-float-right { background: transparent; filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='%appswebroot%/apps/files_imageviewer/img/fancy_title_right.png', sizingMethod='scale'); }
 
 .fancybox-ie6 #fancybox-bg-w, .fancybox-ie6 #fancybox-bg-e, .fancybox-ie6 #fancybox-left, .fancybox-ie6 #fancybox-right, #fancybox-hide-sel-frame {
 	height: expression(this.parentNode.clientHeight + "px");
@@ -343,17 +343,17 @@
 	top: expression( (-20 + (document.documentElement.clientHeight ? document.documentElement.clientHeight/2 : document.body.clientHeight/2 ) + ( ignoreMe = document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop )) + 'px');
 }
 
-#fancybox-loading.fancybox-ie6 div	{ background: transparent; filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='../img/fancy_loading.png', sizingMethod='scale'); }
+#fancybox-loading.fancybox-ie6 div	{ background: transparent; filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='%appswebroot%/apps/files_imageviewer/img/fancy_loading.png', sizingMethod='scale'); }
 
 /* IE6, IE7, IE8 */
 
 .fancybox-ie .fancybox-bg { background: transparent !important; }
 
-.fancybox-ie #fancybox-bg-n { filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='../img/fancy_shadow_n.png', sizingMethod='scale'); }
-.fancybox-ie #fancybox-bg-ne { filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='../img/fancy_shadow_ne.png', sizingMethod='scale'); }
-.fancybox-ie #fancybox-bg-e { filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='../img/fancy_shadow_e.png', sizingMethod='scale'); }
-.fancybox-ie #fancybox-bg-se { filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='../img/fancy_shadow_se.png', sizingMethod='scale'); }
-.fancybox-ie #fancybox-bg-s { filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='../img/fancy_shadow_s.png', sizingMethod='scale'); }
-.fancybox-ie #fancybox-bg-sw { filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='../img/fancy_shadow_sw.png', sizingMethod='scale'); }
-.fancybox-ie #fancybox-bg-w { filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='../img/fancy_shadow_w.png', sizingMethod='scale'); }
-.fancybox-ie #fancybox-bg-nw { filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='../img/fancy_shadow_nw.png', sizingMethod='scale'); }
+.fancybox-ie #fancybox-bg-n { filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='%appswebroot%/apps/files_imageviewer/img/fancy_shadow_n.png', sizingMethod='scale'); }
+.fancybox-ie #fancybox-bg-ne { filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='%appswebroot%/apps/files_imageviewer/img/fancy_shadow_ne.png', sizingMethod='scale'); }
+.fancybox-ie #fancybox-bg-e { filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='%appswebroot%/apps/files_imageviewer/img/fancy_shadow_e.png', sizingMethod='scale'); }
+.fancybox-ie #fancybox-bg-se { filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='%appswebroot%/apps/files_imageviewer/img/fancy_shadow_se.png', sizingMethod='scale'); }
+.fancybox-ie #fancybox-bg-s { filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='%appswebroot%/apps/files_imageviewer/img/fancy_shadow_s.png', sizingMethod='scale'); }
+.fancybox-ie #fancybox-bg-sw { filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='%appswebroot%/apps/files_imageviewer/img/fancy_shadow_sw.png', sizingMethod='scale'); }
+.fancybox-ie #fancybox-bg-w { filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='%appswebroot%/apps/files_imageviewer/img/fancy_shadow_w.png', sizingMethod='scale'); }
+.fancybox-ie #fancybox-bg-nw { filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='%appswebroot%/apps/files_imageviewer/img/fancy_shadow_nw.png', sizingMethod='scale'); }
diff --git a/apps/files_imageviewer/js/lightbox.js b/apps/files_imageviewer/js/lightbox.js
index 94743aa85e049808d884838dd6d9e130a7824bd5..c0f569de351d164a775627c3b664627311650505 100644
--- a/apps/files_imageviewer/js/lightbox.js
+++ b/apps/files_imageviewer/js/lightbox.js
@@ -18,6 +18,9 @@ $(document).ready(function() {
 });
 
 function viewImage(dir, file) {
+	if(file.indexOf('.psd')>0){//can't view those
+		return;
+	}
 	var location=OC.filePath('files','ajax','download.php')+'?files='+file+'&dir='+dir;
 	$.fancybox({
 		"href": location,
diff --git a/apps/files_pdfviewer/appinfo/app.php b/apps/files_pdfviewer/appinfo/app.php
index 0f0b40764d9360763c2df56aff39cb7a75b8e6e4..06b156706747489db5d8f0a9f158b9f8777c31b0 100755
--- a/apps/files_pdfviewer/appinfo/app.php
+++ b/apps/files_pdfviewer/appinfo/app.php
@@ -1,7 +1,7 @@
 <?php
 //load the required files
-OC_Util::addScript( 'files_pdfviewer', 'viewer');
-OC_Util::addStyle( 'files_pdfviewer', 'viewer');
-OC_Util::addScript( 'files_pdfviewer', 'pdfjs/build/pdf');
-OC_Util::addScript( 'files_pdfviewer', 'pdfview');
+OCP\Util::addscript( 'files_pdfviewer', 'viewer');
+OCP\Util::addStyle( 'files_pdfviewer', 'viewer');
+OCP\Util::addscript( 'files_pdfviewer', 'pdfjs/build/pdf');
+OCP\Util::addscript( 'files_pdfviewer', 'pdfview');
 ?>
diff --git a/apps/files_pdfviewer/appinfo/info.xml b/apps/files_pdfviewer/appinfo/info.xml
old mode 100755
new mode 100644
index f133f1900d77173f2f5d49522735ad492f1e20e7..0e81729a8bc1201f3480f84bad9a521e04ef91ec
--- a/apps/files_pdfviewer/appinfo/info.xml
+++ b/apps/files_pdfviewer/appinfo/info.xml
@@ -3,7 +3,6 @@
 	<id>files_pdfviewer</id>
 	<name>PDF Viewer</name>
 	<description>Inline PDF viewer (pdfjs-based)</description>
-	<version>0.1</version>
 	<licence>GPL</licence>
 	<author>Joan Creus</author>
 	<require>2</require>
diff --git a/apps/files_pdfviewer/appinfo/version b/apps/files_pdfviewer/appinfo/version
new file mode 100644
index 0000000000000000000000000000000000000000..ceab6e11ece0bcec917c12e11d350946f085d549
--- /dev/null
+++ b/apps/files_pdfviewer/appinfo/version
@@ -0,0 +1 @@
+0.1
\ No newline at end of file
diff --git a/apps/files_pdfviewer/css/history.png b/apps/files_pdfviewer/css/history.png
old mode 100755
new mode 100644
diff --git a/apps/files_pdfviewer/css/viewer.css b/apps/files_pdfviewer/css/viewer.css
old mode 100755
new mode 100644
diff --git a/apps/files_pdfviewer/js/pdfjs/LICENSE b/apps/files_pdfviewer/js/pdfjs/LICENSE
old mode 100755
new mode 100644
diff --git a/apps/files_pdfviewer/js/pdfjs/build/pdf.js b/apps/files_pdfviewer/js/pdfjs/build/pdf.js
old mode 100755
new mode 100644
index 3447358d3bb798dd9fe78a1f63ac610ac1fc7ef3..a19a9b75fea2da1a8a5adc61c0b9b6a3f9d043e0
--- a/apps/files_pdfviewer/js/pdfjs/build/pdf.js
+++ b/apps/files_pdfviewer/js/pdfjs/build/pdf.js
@@ -7,7 +7,7 @@ var PDFJS = {};
   // Use strict in our context only - users might not want it
   'use strict';
 
-  PDFJS.build = 'PDFJSSCRIPT_BUNDLE_VER';
+  PDFJS.build = 'd823592';
 
   // Files are inserted below - see Makefile
   /* PDFJSSCRIPT_INCLUDE_ALL */
@@ -18,6 +18,8 @@ var PDFJS = {};
 
 var globalScope = (typeof window === 'undefined') ? this : window;
 
+var isWorker = (typeof window == 'undefined');
+
 var ERRORS = 0, WARNINGS = 1, TODOS = 5;
 var verbosity = WARNINGS;
 
@@ -44,7 +46,9 @@ function getPdf(arg, callback) {
   var xhr = new XMLHttpRequest();
   xhr.open('GET', params.url);
   xhr.mozResponseType = xhr.responseType = 'arraybuffer';
-  xhr.expected = (document.URL.indexOf('file:') === 0) ? 0 : 200;
+  var protocol = params.url.indexOf(':') < 0 ? window.location.protocol :
+    params.url.substring(0, params.url.indexOf(':') + 1);
+  xhr.expected = (protocol === 'http:' || protocol === 'https:') ? 200 : 0;
 
   if ('progress' in params)
     xhr.onprogress = params.progress || undefined;
@@ -52,41 +56,43 @@ function getPdf(arg, callback) {
   if ('error' in params)
     xhr.onerror = params.error || undefined;
 
-  xhr.onreadystatechange = function getPdfOnreadystatechange() {
-    if (xhr.readyState === 4 && xhr.status === xhr.expected) {
-      var data = (xhr.mozResponseArrayBuffer || xhr.mozResponse ||
-                  xhr.responseArrayBuffer || xhr.response);
-      callback(data);
+  xhr.onreadystatechange = function getPdfOnreadystatechange(e) {
+    if (xhr.readyState === 4) {
+      if (xhr.status === xhr.expected) {
+        var data = (xhr.mozResponseArrayBuffer || xhr.mozResponse ||
+                    xhr.responseArrayBuffer || xhr.response);
+        callback(data);
+      } else if (params.error) {
+        params.error(e);
+      }
     }
   };
   xhr.send(null);
 }
 globalScope.PDFJS.getPdf = getPdf;
+globalScope.PDFJS.pdfBug = false;
 
-var Page = (function pagePage() {
-  function constructor(xref, pageNumber, pageDict, ref) {
+var Page = (function PageClosure() {
+  function Page(xref, pageNumber, pageDict, ref) {
     this.pageNumber = pageNumber;
     this.pageDict = pageDict;
-    this.stats = {
-      create: Date.now(),
-      compile: 0.0,
-      fonts: 0.0,
-      images: 0.0,
-      render: 0.0
-    };
+    this.stats = new StatTimer();
+    this.stats.enabled = !!globalScope.PDFJS.enableStats;
     this.xref = xref;
     this.ref = ref;
+
+    this.displayReadyPromise = null;
   }
 
-  constructor.prototype = {
-    getPageProp: function pageGetPageProp(key) {
-      return this.xref.fetchIfRef(this.pageDict.get(key));
+  Page.prototype = {
+    getPageProp: function Page_getPageProp(key) {
+      return this.pageDict.get(key);
     },
-    inheritPageProp: function pageInheritPageProp(key) {
+    inheritPageProp: function Page_inheritPageProp(key) {
       var dict = this.pageDict;
       var obj = dict.get(key);
       while (obj === undefined) {
-        dict = this.xref.fetchIfRef(dict.get('Parent'));
+        dict = dict.get('Parent');
         if (!dict)
           break;
         obj = dict.get(key);
@@ -107,23 +113,35 @@ var Page = (function pagePage() {
       return shadow(this, 'mediaBox', obj);
     },
     get view() {
-      var obj = this.inheritPageProp('CropBox');
+      var cropBox = this.inheritPageProp('CropBox');
       var view = {
         x: 0,
         y: 0,
         width: this.width,
         height: this.height
       };
-      if (isArray(obj) && obj.length == 4) {
-        var tl = this.rotatePoint(obj[0], obj[1]);
-        var br = this.rotatePoint(obj[2], obj[3]);
-        view.x = Math.min(tl.x, br.x);
-        view.y = Math.min(tl.y, br.y);
-        view.width = Math.abs(tl.x - br.x);
-        view.height = Math.abs(tl.y - br.y);
-      }
+      if (!isArray(cropBox) || cropBox.length !== 4)
+        return shadow(this, 'view', view);
 
-      return shadow(this, 'cropBox', view);
+      var mediaBox = this.mediaBox;
+      var offsetX = mediaBox[0], offsetY = mediaBox[1];
+
+      // From the spec, 6th ed., p.963:
+      // "The crop, bleed, trim, and art boxes should not ordinarily
+      // extend beyond the boundaries of the media box. If they do, they are
+      // effectively reduced to their intersection with the media box."
+      cropBox = Util.intersect(cropBox, mediaBox);
+      if (!cropBox)
+        return shadow(this, 'view', view);
+
+      var tl = this.rotatePoint(cropBox[0] - offsetX, cropBox[1] - offsetY);
+      var br = this.rotatePoint(cropBox[2] - offsetX, cropBox[3] - offsetY);
+      view.x = Math.min(tl.x, br.x);
+      view.y = Math.min(tl.y, br.y);
+      view.width = Math.abs(tl.x - br.x);
+      view.height = Math.abs(tl.y - br.y);
+
+      return shadow(this, 'view', view);
     },
     get annotations() {
       return shadow(this, 'annotations', this.inheritPageProp('Annots'));
@@ -165,77 +183,80 @@ var Page = (function pagePage() {
       return shadow(this, 'rotate', rotate);
     },
 
-    startRenderingFromIRQueue: function pageStartRenderingFromIRQueue(
-                                                IRQueue, fonts) {
+    startRenderingFromOperatorList:
+      function Page_startRenderingFromOperatorList(operatorList, fonts) {
       var self = this;
-      this.IRQueue = IRQueue;
-      var gfx = new CanvasGraphics(this.ctx, this.objs);
+      this.operatorList = operatorList;
 
       var displayContinuation = function pageDisplayContinuation() {
         // Always defer call to display() to work around bug in
         // Firefox error reporting from XHR callbacks.
         setTimeout(function pageSetTimeout() {
-          try {
-            self.display(gfx, self.callback);
-          } catch (e) {
-            if (self.callback) self.callback(e.toString());
-            throw e;
-          }
+          self.displayReadyPromise.resolve();
         });
       };
 
       this.ensureFonts(fonts,
-                       function pageStartRenderingFromIRQueueEnsureFonts() {
-        displayContinuation();
-      });
+        function pageStartRenderingFromOperatorListEnsureFonts() {
+          displayContinuation();
+        }
+      );
     },
 
-    getIRQueue: function pageGetIRQueue(handler, dependency) {
-      if (this.IRQueue) {
+    getOperatorList: function Page_getOperatorList(handler, dependency) {
+      if (this.operatorList) {
         // content was compiled
-        return this.IRQueue;
+        return this.operatorList;
       }
 
+      this.stats.time('Build IR Queue');
+
       var xref = this.xref;
-      var content = xref.fetchIfRef(this.content);
-      var resources = xref.fetchIfRef(this.resources);
+      var content = this.content;
+      var resources = this.resources;
       if (isArray(content)) {
         // fetching items
         var i, n = content.length;
         for (i = 0; i < n; ++i)
           content[i] = xref.fetchIfRef(content[i]);
         content = new StreamsSequenceStream(content);
+      } else if (!content) {
+        // replacing non-existent page content with empty one
+        content = new Stream(new Uint8Array(0));
       }
 
       var pe = this.pe = new PartialEvaluator(
                                 xref, handler, 'p' + this.pageNumber + '_');
-      var IRQueue = {};
-      return (this.IRQueue = pe.getIRQueue(content, resources, IRQueue,
-                                           dependency));
+
+      this.operatorList = pe.getOperatorList(content, resources, dependency);
+      this.stats.timeEnd('Build IR Queue');
+      return this.operatorList;
     },
 
-    ensureFonts: function pageEnsureFonts(fonts, callback) {
+    ensureFonts: function Page_ensureFonts(fonts, callback) {
+      this.stats.time('Font Loading');
       // Convert the font names to the corresponding font obj.
       for (var i = 0, ii = fonts.length; i < ii; i++) {
         fonts[i] = this.objs.objs[fonts[i]].data;
       }
 
       // Load all the fonts
-      var fontObjs = FontLoader.bind(
+      FontLoader.bind(
         fonts,
         function pageEnsureFontsFontObjs(fontObjs) {
-          this.stats.fonts = Date.now();
+          this.stats.timeEnd('Font Loading');
 
           callback.call(this);
-        }.bind(this),
-        this.objs
+        }.bind(this)
       );
     },
 
-    display: function pageDisplay(gfx, callback) {
+    display: function Page_display(gfx, callback) {
+      var stats = this.stats;
+      stats.time('Rendering');
       var xref = this.xref;
-      var resources = xref.fetchIfRef(this.resources);
-      var mediaBox = xref.fetchIfRef(this.mediaBox);
+      var resources = this.resources;
+      var mediaBox = this.mediaBox;
       assertWellFormed(isDict(resources), 'invalid page resources');
 
       gfx.xref = xref;
@@ -246,20 +267,29 @@ var Page = (function pagePage() {
             rotate: this.rotate });
 
       var startIdx = 0;
-      var length = this.IRQueue.fnArray.length;
-      var IRQueue = this.IRQueue;
+      var length = this.operatorList.fnArray.length;
+      var operatorList = this.operatorList;
+      var stepper = null;
+      if (PDFJS.pdfBug && StepperManager.enabled) {
+        stepper = StepperManager.create(this.pageNumber);
+        stepper.init(operatorList);
+        stepper.nextBreakPoint = stepper.getNextBreakPoint();
+      }
 
       var self = this;
       function next() {
-        startIdx = gfx.executeIRQueue(IRQueue, startIdx, next);
+        startIdx =
+          gfx.executeOperatorList(operatorList, startIdx, next, stepper);
         if (startIdx == length) {
-          self.stats.render = Date.now();
+          gfx.endDrawing();
+          stats.timeEnd('Rendering');
+          stats.timeEnd('Overall');
           if (callback) callback();
         }
       }
       next();
     },
-    rotatePoint: function pageRotatePoint(x, y, reverse) {
+    rotatePoint: function Page_rotatePoint(x, y, reverse) {
       var rotate = reverse ? (360 - this.rotate) : this.rotate;
       switch (rotate) {
         case 180:
@@ -274,58 +304,183 @@ var Page = (function pagePage() {
           return {x: x, y: this.height - y};
       }
     },
-    getLinks: function pageGetLinks() {
+    getLinks: function Page_getLinks() {
+      var links = [];
+      var annotations = pageGetAnnotations();
+      var i, n = annotations.length;
+      for (i = 0; i < n; ++i) {
+        if (annotations[i].type != 'Link')
+          continue;
+        links.push(annotations[i]);
+      }
+      return links;
+    },
+    getAnnotations: function Page_getAnnotations() {
       var xref = this.xref;
-      var annotations = xref.fetchIfRef(this.annotations) || [];
+      function getInheritableProperty(annotation, name) {
+        var item = annotation;
+        while (item && !item.has(name)) {
+          item = item.get('Parent');
+        }
+        if (!item)
+          return null;
+        return item.get(name);
+      }
+      function isValidUrl(url) {
+        if (!url)
+          return false;
+        var colon = url.indexOf(':');
+        if (colon < 0)
+          return false;
+        var protocol = url.substr(0, colon);
+        switch (protocol) {
+          case 'http':
+          case 'https':
+          case 'ftp':
+            return true;
+          default:
+            return false;
+        }
+      }
+
+      var annotations = this.annotations || [];
       var i, n = annotations.length;
-      var links = [];
+      var items = [];
       for (i = 0; i < n; ++i) {
-        var annotation = xref.fetch(annotations[i]);
+        var annotationRef = annotations[i];
+        var annotation = xref.fetch(annotationRef);
         if (!isDict(annotation))
           continue;
         var subtype = annotation.get('Subtype');
-        if (!isName(subtype) || subtype.name != 'Link')
+        if (!isName(subtype))
           continue;
         var rect = annotation.get('Rect');
         var topLeftCorner = this.rotatePoint(rect[0], rect[1]);
         var bottomRightCorner = this.rotatePoint(rect[2], rect[3]);
 
-        var link = {};
-        link.x = Math.min(topLeftCorner.x, bottomRightCorner.x);
-        link.y = Math.min(topLeftCorner.y, bottomRightCorner.y);
-        link.width = Math.abs(topLeftCorner.x - bottomRightCorner.x);
-        link.height = Math.abs(topLeftCorner.y - bottomRightCorner.y);
-        var a = this.xref.fetchIfRef(annotation.get('A'));
-        if (a) {
-          switch (a.get('S').name) {
-            case 'URI':
-              link.url = a.get('URI');
-              break;
-            case 'GoTo':
-              link.dest = a.get('D');
+        var item = {};
+        item.type = subtype.name;
+        item.x = Math.min(topLeftCorner.x, bottomRightCorner.x);
+        item.y = Math.min(topLeftCorner.y, bottomRightCorner.y);
+        item.width = Math.abs(topLeftCorner.x - bottomRightCorner.x);
+        item.height = Math.abs(topLeftCorner.y - bottomRightCorner.y);
+        switch (subtype.name) {
+          case 'Link':
+            var a = annotation.get('A');
+            if (a) {
+              switch (a.get('S').name) {
+                case 'URI':
+                  var url = a.get('URI');
+                  // TODO: pdf spec mentions urls can be relative to a Base
+                  // entry in the dictionary.
+                  if (!isValidUrl(url))
+                    url = '';
+                  item.url = url;
+                  break;
+                case 'GoTo':
+                  item.dest = a.get('D');
+                  break;
+                default:
+                  TODO('other link types');
+              }
+            } else if (annotation.has('Dest')) {
+              // simple destination link
+              var dest = annotation.get('Dest');
+              item.dest = isName(dest) ? dest.name : dest;
+            }
+            break;
+          case 'Widget':
+            var fieldType = getInheritableProperty(annotation, 'FT');
+            if (!isName(fieldType))
               break;
-            default:
-              TODO('other link types');
-          }
-        } else if (annotation.has('Dest')) {
-          // simple destination link
-          var dest = annotation.get('Dest');
-          link.dest = isName(dest) ? dest.name : dest;
+            item.fieldType = fieldType.name;
+            // Building the full field name by collecting the field and
+            // its ancestors 'T' properties and joining them using '.'.
+            var fieldName = [];
+            var namedItem = annotation, ref = annotationRef;
+            while (namedItem) {
+              var parent = namedItem.get('Parent');
+              var parentRef = namedItem.getRaw('Parent');
+              var name = namedItem.get('T');
+              if (name) {
+                fieldName.unshift(stringToPDFString(name));
+              } else {
+                // The field name is absent, that means more than one field
+                // with the same name may exist. Replacing the empty name
+                // with the '`' plus index in the parent's 'Kids' array.
+                // This is not in the PDF spec but necessary to id the
+                // the input controls.
+                var kids = parent.get('Kids');
+                var j, jj;
+                for (j = 0, jj = kids.length; j < jj; j++) {
+                  var kidRef = kids[j];
+                  if (kidRef.num == ref.num && kidRef.gen == ref.gen)
+                    break;
+                }
+                fieldName.unshift('`' + j);
+              }
+              namedItem = parent;
+              ref = parentRef;
+            }
+            item.fullName = fieldName.join('.');
+            var alternativeText = stringToPDFString(annotation.get('TU') || '');
+            item.alternativeText = alternativeText;
+            var da = getInheritableProperty(annotation, 'DA') || '';
+            var m = /([\d\.]+)\sTf/.exec(da);
+            if (m)
+              item.fontSize = parseFloat(m[1]);
+            item.textAlignment = getInheritableProperty(annotation, 'Q');
+            item.flags = getInheritableProperty(annotation, 'Ff') || 0;
+            break;
+          case 'Text':
+            var content = annotation.get('Contents');
+            var title = annotation.get('T');
+            item.content = stringToPDFString(content || '');
+            item.title = stringToPDFString(title || '');
+            item.name = annotation.get('Name').name;
+            break;
+          default:
+            TODO('unimplemented annotation type: ' + subtype.name);
+            break;
         }
-        links.push(link);
+        items.push(item);
       }
-      return links;
+      return items;
     },
-    startRendering: function pageStartRendering(ctx, callback)  {
-      this.ctx = ctx;
-      this.callback = callback;
-
-      this.startRenderingTime = Date.now();
-      this.pdf.startRendering(this);
+    startRendering: function Page_startRendering(ctx, callback, textLayer)  {
+      var stats = this.stats;
+      stats.time('Overall');
+      // If there is no displayReadyPromise yet, then the operatorList was never
+      // requested before. Make the request and create the promise.
+      if (!this.displayReadyPromise) {
+        this.pdf.startRendering(this);
+        this.displayReadyPromise = new Promise();
+      }
+
+      // Once the operatorList and fonts are loaded, do the actual rendering.
+      this.displayReadyPromise.then(
+        function pageDisplayReadyPromise() {
+          var gfx = new CanvasGraphics(ctx, this.objs, textLayer);
+          try {
+            this.display(gfx, callback);
+          } catch (e) {
+            if (callback)
+              callback(e);
+            else
+              error(e);
+          }
+        }.bind(this),
+        function pageDisplayReadPromiseError(reason) {
+          if (callback)
+            callback(reason);
+          else
+            error(reason);
+        }
+      );
     }
   };
 
-  return constructor;
+  return Page;
 })();
 
 /**
@@ -334,12 +489,9 @@ var Page = (function pagePage() {
  * Right now there exists one PDFDocModel on the main thread + one object
  * for each worker. If there is no worker support enabled, there are two
  * `PDFDocModel` objects on the main thread created.
- * TODO: Refactor the internal object structure, such that there is no
- * need for the `PDFDocModel` anymore and there is only one object on the
- * main thread and not one entire copy on each worker instance.
  */
-var PDFDocModel = (function pdfDoc() {
-  function constructor(arg, callback) {
+var PDFDocModel = (function PDFDocModelClosure() {
+  function PDFDocModel(arg, callback) {
     if (isStream(arg))
       init.call(this, arg);
     else if (isArrayBuffer(arg))
@@ -352,6 +504,7 @@ var PDFDocModel = (function pdfDoc() {
     assertWellFormed(stream.length > 0, 'stream must have data');
     this.stream = stream;
     this.setup();
+    this.acroForm = this.catalog.catDict.get('AcroForm');
   }
 
   function find(stream, needle, limit, backwards) {
@@ -370,7 +523,7 @@ var PDFDocModel = (function pdfDoc() {
     return true; /* found */
   }
 
-  constructor.prototype = {
+  PDFDocModel.prototype = {
     get linearization() {
       var length = this.stream.length;
       var linearization = false;
@@ -392,12 +545,17 @@ var PDFDocModel = (function pdfDoc() {
         if (find(stream, 'endobj', 1024))
           startXRef = stream.pos + 6;
       } else {
-        // Find startxref at the end of the file.
-        var start = stream.end - 1024;
-        if (start < 0)
-          start = 0;
-        stream.pos = start;
-        if (find(stream, 'startxref', 1024, true)) {
+        // Find startxref by jumping backward from the end of the file.
+        var step = 1024;
+        var found = false, pos = stream.end;
+        while (!found && pos > 0) {
+          pos -= step - 'startxref'.length;
+          if (pos < 0)
+            pos = 0;
+          stream.pos = pos;
+          found = find(stream, 'startxref', step, true);
+        }
+        if (found) {
           stream.skip(9);
           var ch;
           do {
@@ -426,7 +584,7 @@ var PDFDocModel = (function pdfDoc() {
     },
     // Find the header, remove leading garbage and setup the stream
     // starting from the header.
-    checkHeader: function pdfDocCheckHeader() {
+    checkHeader: function PDFDocModel_checkHeader() {
       var stream = this.stream;
       stream.reset();
       if (find(stream, '%PDF-', 1024)) {
@@ -436,12 +594,13 @@ var PDFDocModel = (function pdfDoc() {
       }
       // May not be a PDF file, continue anyway.
     },
-    setup: function pdfDocSetup(ownerPassword, userPassword) {
+    setup: function PDFDocModel_setup(ownerPassword, userPassword) {
       this.checkHeader();
-      this.xref = new XRef(this.stream,
-                           this.startXRef,
-                           this.mainXRefEntriesOffset);
-      this.catalog = new Catalog(this.xref);
+      var xref = new XRef(this.stream,
+                          this.startXRef,
+                          this.mainXRefEntriesOffset);
+      this.xref = xref;
+      this.catalog = new Catalog(xref);
     },
     get numPages() {
       var linearization = this.linearization;
@@ -449,16 +608,51 @@ var PDFDocModel = (function pdfDoc() {
       // shadow the prototype getter
       return shadow(this, 'numPages', num);
     },
-    getPage: function pdfDocGetPage(n) {
+    getDocumentInfo: function PDFDocModel_getDocumentInfo() {
+      var info;
+      if (this.xref.trailer.has('Info')) {
+        var infoDict = this.xref.trailer.get('Info');
+
+        info = {};
+        infoDict.forEach(function(key, value) {
+          info[key] = typeof value !== 'string' ? value :
+            stringToPDFString(value);
+        });
+      }
+
+      return shadow(this, 'getDocumentInfo', info);
+    },
+    getFingerprint: function PDFDocModel_getFingerprint() {
+      var xref = this.xref, fileID;
+      if (xref.trailer.has('ID')) {
+        fileID = '';
+        var id = xref.trailer.get('ID')[0];
+        id.split('').forEach(function(el) {
+          fileID += Number(el.charCodeAt(0)).toString(16);
+        });
+      } else {
+        // If we got no fileID, then we generate one,
+        // from the first 100 bytes of PDF
+        var data = this.stream.bytes.subarray(0, 100);
+        var hash = calculateMD5(data, 0, data.length);
+        fileID = '';
+        for (var i = 0, length = hash.length; i < length; i++) {
+          fileID += Number(hash[i]).toString(16);
+        }
+      }
+
+      return shadow(this, 'getFingerprint', fileID);
+    },
+    getPage: function PDFDocModel_getPage(n) {
       return this.catalog.getPage(n);
     }
   };
 
-  return constructor;
+  return PDFDocModel;
 })();
 
-var PDFDoc = (function pdfDoc() {
-  function constructor(arg, callback) {
+var PDFDoc = (function PDFDocClosure() {
+  function PDFDoc(arg, callback) {
     var stream = null;
     var data = null;
 
@@ -474,9 +668,10 @@ var PDFDoc = (function pdfDoc() {
 
     this.data = data;
     this.stream = stream;
-    this.pdf = new PDFDocModel(stream);
-
-    this.catalog = this.pdf.catalog;
+    this.pdfModel = new PDFDocModel(stream);
+    this.fingerprint = this.pdfModel.getFingerprint();
+    this.info = this.pdfModel.getDocumentInfo();
+    this.catalog = this.pdfModel.catalog;
     this.objs = new PDFObjects();
 
     this.pageCache = [];
@@ -491,49 +686,59 @@ var PDFDoc = (function pdfDoc() {
     if (!globalScope.PDFJS.disableWorker && typeof Worker !== 'undefined') {
       var workerSrc = PDFJS.workerSrc;
       if (typeof workerSrc === 'undefined') {
-        throw 'No PDFJS.workerSrc specified';
+        error('No PDFJS.workerSrc specified');
       }
 
-      var worker;
       try {
-        worker = new Worker(workerSrc);
-      } catch (e) {
-        // Some versions of FF can't create a worker on localhost, see:
-        // https://bugzilla.mozilla.org/show_bug.cgi?id=683280
-        globalScope.PDFJS.disableWorker = true;
-        this.setupFakeWorker();
-        return;
-      }
-
-      var messageHandler = new MessageHandler('main', worker);
-
-      // Tell the worker the file it was created from.
-      messageHandler.send('workerSrc', workerSrc);
-
-      messageHandler.on('test', function pdfDocTest(supportTypedArray) {
-        if (supportTypedArray) {
-          this.worker = worker;
-          this.setupMessageHandler(messageHandler);
+        var worker;
+        if (PDFJS.isFirefoxExtension) {
+          // The firefox extension can't load the worker from the resource://
+          // url so we have to inline the script and then use the blob loader.
+          var bb = new MozBlobBuilder();
+          bb.append(document.querySelector('#PDFJS_SCRIPT_TAG').textContent);
+          var blobUrl = window.URL.createObjectURL(bb.getBlob());
+          worker = new Worker(blobUrl);
         } else {
-          this.setupFakeWorker();
+          // Some versions of FF can't create a worker on localhost, see:
+          // https://bugzilla.mozilla.org/show_bug.cgi?id=683280
+          worker = new Worker(workerSrc);
         }
-      }.bind(this));
 
-      var testObj = new Uint8Array(1);
-      messageHandler.send('test', testObj);
-    } else {
-      this.setupFakeWorker();
+        var messageHandler = new MessageHandler('main', worker);
+
+        messageHandler.on('test', function pdfDocTest(supportTypedArray) {
+          if (supportTypedArray) {
+            this.worker = worker;
+            this.setupMessageHandler(messageHandler);
+          } else {
+            globalScope.PDFJS.disableWorker = true;
+            this.setupFakeWorker();
+          }
+        }.bind(this));
+
+        var testObj = new Uint8Array(1);
+        // Some versions of Opera throw a DATA_CLONE_ERR on
+        // serializing the typed array.
+        messageHandler.send('test', testObj);
+        return;
+      } catch (e) {
+        warn('The worker has been disabled.');
+      }
     }
+    // Either workers are disabled, not supported or have thrown an exception.
+    // Thus, we fallback to a faked worker.
+    globalScope.PDFJS.disableWorker = true;
+    this.setupFakeWorker();
   }
 
-  constructor.prototype = {
-    setupFakeWorker: function() {
+  PDFDoc.prototype = {
+    setupFakeWorker: function PDFDoc_setupFakeWorker() {
       // If we don't use a worker, just post/sendMessage to the main thread.
       var fakeWorker = {
-        postMessage: function pdfDocPostMessage(obj) {
+        postMessage: function PDFDoc_postMessage(obj) {
           fakeWorker.onmessage({data: obj});
         },
-        terminate: function pdfDocTerminate() {}
+        terminate: function PDFDoc_terminate() {}
       };
 
       var messageHandler = new MessageHandler('main', fakeWorker);
@@ -545,7 +750,7 @@ var PDFDoc = (function pdfDoc() {
     },
 
 
-    setupMessageHandler: function(messageHandler) {
+    setupMessageHandler: function PDFDoc_setupMessageHandler(messageHandler) {
       this.messageHandler = messageHandler;
 
       messageHandler.on('page', function pdfDocPage(data) {
@@ -553,7 +758,8 @@ var PDFDoc = (function pdfDoc() {
         var page = this.pageCache[pageNum];
         var depFonts = data.depFonts;
 
-        page.startRenderingFromIRQueue(data.IRQueue, depFonts);
+        page.stats.timeEnd('Page Request');
+        page.startRenderingFromOperatorList(data.operatorList, depFonts);
       }, this);
 
       messageHandler.on('obj', function pdfDocObj(data) {
@@ -562,8 +768,12 @@ var PDFDoc = (function pdfDoc() {
 
         switch (type) {
           case 'JpegStream':
-            var IR = data[2];
-            new JpegImageLoader(id, IR, this.objs);
+            var imageData = data[2];
+            loadJpegStream(id, imageData, this.objs);
+            break;
+          case 'Image':
+            var imageData = data[2];
+            this.objs.resolve(id, imageData);
             break;
           case 'Font':
             var name = data[2];
@@ -571,46 +781,63 @@ var PDFDoc = (function pdfDoc() {
             var properties = data[4];
 
             if (file) {
+              // Rewrap the ArrayBuffer in a stream.
               var fontFileDict = new Dict();
-              fontFileDict.map = file.dict.map;
-
-              var fontFile = new Stream(file.bytes, file.start,
-                                        file.end - file.start, fontFileDict);
-
-              // Check if this is a FlateStream. Otherwise just use the created
-              // Stream one. This makes complex_ttf_font.pdf work.
-              var cmf = file.bytes[0];
-              if ((cmf & 0x0f) == 0x08) {
-                file = new FlateStream(fontFile);
-              } else {
-                file = fontFile;
-              }
+              file = new Stream(file, 0, file.length, fontFileDict);
             }
 
-            // For now, resolve the font object here direclty. The real font
-            // object is then created in FontLoader.bind().
-            this.objs.resolve(id, {
-              name: name,
-              file: file,
-              properties: properties
-            });
+            // At this point, only the font object is created but the font is
+            // not yet attached to the DOM. This is done in `FontLoader.bind`.
+            var font = new Font(name, file, properties);
+            this.objs.resolve(id, font);
             break;
           default:
-            throw 'Got unkown object type ' + type;
+            error('Got unkown object type ' + type);
         }
       }, this);
 
-      messageHandler.on('font_ready', function pdfDocFontReady(data) {
-        var id = data[0];
-        var font = new FontShape(data[1]);
+      messageHandler.on('page_error', function pdfDocError(data) {
+        var page = this.pageCache[data.pageNum];
+        if (page.displayReadyPromise)
+          page.displayReadyPromise.reject(data.error);
+        else
+          error(data.error);
+      }, this);
 
-        // If there is no string, then there is nothing to attach to the DOM.
-        if (!font.str) {
-          this.objs.resolve(id, font);
-        } else {
-          this.objs.setData(id, font);
-        }
-      }.bind(this));
+      messageHandler.on('jpeg_decode', function(data, promise) {
+        var imageData = data[0];
+        var components = data[1];
+        if (components != 3 && components != 1)
+          error('Only 3 component or 1 component can be returned');
+
+        var img = new Image();
+        img.onload = (function messageHandler_onloadClosure() {
+          var width = img.width;
+          var height = img.height;
+          var size = width * height;
+          var rgbaLength = size * 4;
+          var buf = new Uint8Array(size * components);
+          var tmpCanvas = createScratchCanvas(width, height);
+          var tmpCtx = tmpCanvas.getContext('2d');
+          tmpCtx.drawImage(img, 0, 0);
+          var data = tmpCtx.getImageData(0, 0, width, height).data;
+
+          if (components == 3) {
+            for (var i = 0, j = 0; i < rgbaLength; i += 4, j += 3) {
+              buf[j] = data[i];
+              buf[j + 1] = data[i + 1];
+              buf[j + 2] = data[i + 2];
+            }
+          } else if (components == 1) {
+            for (var i = 0, j = 0; i < rgbaLength; i += 4, j++) {
+              buf[j] = data[i];
+            }
+          }
+          promise.resolve({ data: buf, width: width, height: height});
+        }).bind(this);
+        var src = 'data:image/jpeg;base64,' + window.btoa(imageData);
+        img.src = src;
+      });
 
       setTimeout(function pdfDocFontReadySetTimeout() {
         messageHandler.send('doc', this.data);
@@ -619,21 +846,22 @@ var PDFDoc = (function pdfDoc() {
     },
 
     get numPages() {
-      return this.pdf.numPages;
+      return this.pdfModel.numPages;
     },
 
-    startRendering: function pdfDocStartRendering(page) {
+    startRendering: function PDFDoc_startRendering(page) {
       // The worker might not be ready to receive the page request yet.
       this.workerReadyPromise.then(function pdfDocStartRenderingThen() {
+        page.stats.time('Page Request');
         this.messageHandler.send('page_request', page.pageNumber + 1);
       }.bind(this));
     },
 
-    getPage: function pdfDocGetPage(n) {
+    getPage: function PDFDoc_getPage(n) {
       if (this.pageCache[n])
         return this.pageCache[n];
 
-      var page = this.pdf.getPage(n);
+      var page = this.pdfModel.getPage(n);
       // Add a reference to the objects such that Page can forward the reference
       // to the CanvasGraphics and so on.
       page.objs = this.objs;
@@ -641,7 +869,7 @@ var PDFDoc = (function pdfDoc() {
       return (this.pageCache[n] = page);
     },
 
-    destroy: function pdfDocDestroy() {
+    destroy: function PDFDoc_destroy() {
       if (this.worker)
         this.worker.terminate();
 
@@ -658,7 +886,7 @@ var PDFDoc = (function pdfDoc() {
     }
   };
 
-  return constructor;
+  return PDFDoc;
 })();
 
 globalScope.PDFJS.PDFDoc = PDFDoc;
@@ -741,24 +969,102 @@ function stringToBytes(str) {
 
 var IDENTITY_MATRIX = [1, 0, 0, 1, 0, 0];
 
-var Util = (function utilUtil() {
-  function constructor() {}
-  constructor.makeCssRgb = function makergb(r, g, b) {
+var Util = (function UtilClosure() {
+  function Util() {}
+
+  Util.makeCssRgb = function Util_makeCssRgb(r, g, b) {
     var ri = (255 * r) | 0, gi = (255 * g) | 0, bi = (255 * b) | 0;
     return 'rgb(' + ri + ',' + gi + ',' + bi + ')';
   };
-  constructor.makeCssCmyk = function makecmyk(c, m, y, k) {
+
+  Util.makeCssCmyk = function Util_makeCssCmyk(c, m, y, k) {
     c = (new DeviceCmykCS()).getRgb([c, m, y, k]);
     var ri = (255 * c[0]) | 0, gi = (255 * c[1]) | 0, bi = (255 * c[2]) | 0;
     return 'rgb(' + ri + ',' + gi + ',' + bi + ')';
   };
-  constructor.applyTransform = function apply(p, m) {
+
+  // For 2d affine transforms
+  Util.applyTransform = function Util_applyTransform(p, m) {
     var xt = p[0] * m[0] + p[1] * m[2] + m[4];
     var yt = p[0] * m[1] + p[1] * m[3] + m[5];
     return [xt, yt];
   };
 
-  return constructor;
+  // Apply a generic 3d matrix M on a 3-vector v:
+  //   | a b c |   | X |
+  //   | d e f | x | Y |
+  //   | g h i |   | Z |
+  // M is assumed to be serialized as [a,b,c,d,e,f,g,h,i],
+  // with v as [X,Y,Z]
+  Util.apply3dTransform = function Util_apply3dTransform(m, v) {
+    return [
+      m[0] * v[0] + m[1] * v[1] + m[2] * v[2],
+      m[3] * v[0] + m[4] * v[1] + m[5] * v[2],
+      m[6] * v[0] + m[7] * v[1] + m[8] * v[2]
+    ];
+  }
+
+  // Normalize rectangle rect=[x1, y1, x2, y2] so that (x1,y1) < (x2,y2)
+  // For coordinate systems whose origin lies in the bottom-left, this
+  // means normalization to (BL,TR) ordering. For systems with origin in the
+  // top-left, this means (TL,BR) ordering.
+  Util.normalizeRect = function Util_normalizeRect(rect) {
+    var r = rect.slice(0); // clone rect
+    if (rect[0] > rect[2]) {
+      r[0] = rect[2];
+      r[2] = rect[0];
+    }
+    if (rect[1] > rect[3]) {
+      r[1] = rect[3];
+      r[3] = rect[1];
+    }
+    return r;
+  }
+
+  // Returns a rectangle [x1, y1, x2, y2] corresponding to the
+  // intersection of rect1 and rect2. If no intersection, returns 'false'
+  // The rectangle coordinates of rect1, rect2 should be [x1, y1, x2, y2]
+  Util.intersect = function Util_intersect(rect1, rect2) {
+    function compare(a, b) {
+      return a - b;
+    };
+
+    // Order points along the axes
+    var orderedX = [rect1[0], rect1[2], rect2[0], rect2[2]].sort(compare),
+        orderedY = [rect1[1], rect1[3], rect2[1], rect2[3]].sort(compare),
+        result = [];
+
+    rect1 = Util.normalizeRect(rect1);
+    rect2 = Util.normalizeRect(rect2);
+
+    // X: first and second points belong to different rectangles?
+    if ((orderedX[0] === rect1[0] && orderedX[1] === rect2[0]) ||
+        (orderedX[0] === rect2[0] && orderedX[1] === rect1[0])) {
+      // Intersection must be between second and third points
+      result[0] = orderedX[1];
+      result[2] = orderedX[2];
+    } else {
+      return false;
+    }
+
+    // Y: first and second points belong to different rectangles?
+    if ((orderedY[0] === rect1[1] && orderedY[1] === rect2[1]) ||
+        (orderedY[0] === rect2[1] && orderedY[1] === rect1[1])) {
+      // Intersection must be between second and third points
+      result[1] = orderedY[1];
+      result[3] = orderedY[2];
+    } else {
+      return false;
+    }
+
+    return result;
+  }
+
+  Util.sign = function Util_sign(num) {
+    return num < 0 ? -1 : 1;
+  };
+
+  return Util;
 })();
 
 var PDFStringTranslateTable = [
@@ -862,7 +1168,7 @@ function isPDFFunction(v) {
  * can be set. If any of these happens twice or the data is required before
  * it was set, an exception is throw.
  */
-var Promise = (function promise() {
+var Promise = (function PromiseClosure() {
   var EMPTY_PROMISE = {};
 
   /**
@@ -871,6 +1177,8 @@ var Promise = (function promise() {
    */
   function Promise(name, data) {
     this.name = name;
+    this.isRejected = false;
+    this.error = null;
     // If you build a promise and pass in some data it's already resolved.
     if (data != null) {
       this.isResolved = true;
@@ -881,8 +1189,35 @@ var Promise = (function promise() {
       this._data = EMPTY_PROMISE;
     }
     this.callbacks = [];
+    this.errbacks = [];
+  };
+  /**
+   * Builds a promise that is resolved when all the passed in promises are
+   * resolved.
+   * @param {Promise[]} promises Array of promises to wait for.
+   * @return {Promise} New dependant promise.
+   */
+  Promise.all = function Promise_all(promises) {
+    var deferred = new Promise();
+    var unresolved = promises.length;
+    var results = [];
+    if (unresolved === 0) {
+      deferred.resolve(results);
+      return deferred;
+    }
+    for (var i = 0; i < unresolved; ++i) {
+      var promise = promises[i];
+      promise.then((function(i) {
+        return function(value) {
+          results[i] = value;
+          unresolved--;
+          if (unresolved === 0)
+            deferred.resolve(results);
+        };
+      })(i));
+    }
+    return deferred;
   };
-
   Promise.prototype = {
     hasData: false,
 
@@ -891,8 +1226,8 @@ var Promise = (function promise() {
         return;
       }
       if (this._data !== EMPTY_PROMISE) {
-        throw 'Promise ' + this.name +
-                                ': Cannot set the data of a promise twice';
+        error('Promise ' + this.name +
+              ': Cannot set the data of a promise twice');
       }
       this._data = value;
       this.hasData = true;
@@ -904,12 +1239,12 @@ var Promise = (function promise() {
 
     get data() {
       if (this._data === EMPTY_PROMISE) {
-        throw 'Promise ' + this.name + ': Cannot get data that isn\'t set';
+        error('Promise ' + this.name + ': Cannot get data that isn\'t set');
       }
       return this._data;
     },
 
-    onData: function promiseOnData(callback) {
+    onData: function Promise_onData(callback) {
       if (this._data !== EMPTY_PROMISE) {
         callback(this._data);
       } else {
@@ -917,13 +1252,16 @@ var Promise = (function promise() {
       }
     },
 
-    resolve: function promiseResolve(data) {
+    resolve: function Promise_resolve(data) {
       if (this.isResolved) {
-        throw 'A Promise can be resolved only once ' + this.name;
+        error('A Promise can be resolved only once ' + this.name);
+      }
+      if (this.isRejected) {
+        error('The Promise was already rejected ' + this.name);
       }
 
       this.isResolved = true;
-      this.data = data;
+      this.data = data || null;
       var callbacks = this.callbacks;
 
       for (var i = 0, ii = callbacks.length; i < ii; i++) {
@@ -931,17 +1269,39 @@ var Promise = (function promise() {
       }
     },
 
-    then: function promiseThen(callback) {
+    reject: function Promise_reject(reason) {
+      if (this.isRejected) {
+        error('A Promise can be rejected only once ' + this.name);
+      }
+      if (this.isResolved) {
+        error('The Promise was already resolved ' + this.name);
+      }
+
+      this.isRejected = true;
+      this.error = reason || null;
+      var errbacks = this.errbacks;
+
+      for (var i = 0, ii = errbacks.length; i < ii; i++) {
+        errbacks[i].call(null, reason);
+      }
+    },
+
+    then: function Promise_then(callback, errback) {
       if (!callback) {
-        throw 'Requiring callback' + this.name;
+        error('Requiring callback' + this.name);
       }
 
       // If the promise is already resolved, call the callback directly.
       if (this.isResolved) {
         var data = this.data;
         callback.call(null, data);
+      } else if (this.isRejected && errback) {
+        var error = this.error;
+        errback.call(null, error);
       } else {
         this.callbacks.push(callback);
+        if (errback)
+          this.errbacks.push(errback);
       }
     }
   };
@@ -949,6 +1309,58 @@ var Promise = (function promise() {
   return Promise;
 })();
 
+var StatTimer = (function StatTimerClosure() {
+  function rpad(str, pad, length) {
+    while (str.length < length)
+      str += pad;
+    return str;
+  }
+  function StatTimer() {
+    this.started = {};
+    this.times = [];
+    this.enabled = true;
+  }
+  StatTimer.prototype = {
+    time: function StatTimer_time(name) {
+      if (!this.enabled)
+        return;
+      if (name in this.started)
+        throw 'Timer is already running for ' + name;
+      this.started[name] = Date.now();
+    },
+    timeEnd: function StatTimer_timeEnd(name) {
+      if (!this.enabled)
+        return;
+      if (!(name in this.started))
+        throw 'Timer has not been started for ' + name;
+      this.times.push({
+        'name': name,
+        'start': this.started[name],
+        'end': Date.now()
+      });
+      // Remove timer from started so it can be called again.
+      delete this.started[name];
+    },
+    toString: function StatTimer_toString() {
+      var times = this.times;
+      var out = '';
+      // Find the longest name for padding purposes.
+      var longest = 0;
+      for (var i = 0, ii = times.length; i < ii; ++i) {
+        var name = times[i]['name'];
+        if (name.length > longest)
+          longest = name.length;
+      }
+      for (var i = 0, ii = times.length; i < ii; ++i) {
+        var span = times[i];
+        var duration = span.end - span.start;
+        out += rpad(span['name'], ' ', longest) + ' ' + duration + 'ms\n';
+      }
+      return out;
+    }
+  };
+  return StatTimer;
+})();
 /* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
 
@@ -957,12 +1369,145 @@ var Promise = (function promise() {
 // <canvas> contexts store most of the state we need natively.
 // However, PDF needs a bit more state, which we store here.
 
-var CanvasExtraState = (function canvasExtraState() {
-  function constructor(old) {
+var TextRenderingMode = {
+  FILL: 0,
+  STROKE: 1,
+  FILL_STROKE: 2,
+  INVISIBLE: 3,
+  FILL_ADD_TO_PATH: 4,
+  STROKE_ADD_TO_PATH: 5,
+  FILL_STROKE_ADD_TO_PATH: 6,
+  ADD_TO_PATH: 7
+};
+
+// Minimal font size that would be used during canvas fillText operations.
+var MIN_FONT_SIZE = 1;
+
+function createScratchCanvas(width, height) {
+  var canvas = document.createElement('canvas');
+  canvas.width = width;
+  canvas.height = height;
+  return canvas;
+}
+
+function addContextCurrentTransform(ctx) {
+  // If the context doesn't expose a `mozCurrentTransform`, add a JS based on.
+  if (!ctx.mozCurrentTransform) {
+    // Store the original context
+    ctx._originalSave = ctx.save;
+    ctx._originalRestore = ctx.restore;
+    ctx._originalRotate = ctx.rotate;
+    ctx._originalScale = ctx.scale;
+    ctx._originalTranslate = ctx.translate;
+    ctx._originalTransform = ctx.transform;
+
+    ctx._transformMatrix = [1, 0, 0, 1, 0, 0];
+    ctx._transformStack = [];
+
+    Object.defineProperty(ctx, 'mozCurrentTransform', {
+      get: function getCurrentTransform() {
+        return this._transformMatrix;
+      }
+    });
+
+    Object.defineProperty(ctx, 'mozCurrentTransformInverse', {
+      get: function getCurrentTransformInverse() {
+        // Calculation done using WolframAlpha:
+        // http://www.wolframalpha.com/input/?
+        //   i=Inverse+{{a%2C+c%2C+e}%2C+{b%2C+d%2C+f}%2C+{0%2C+0%2C+1}}
+
+        var m = this._transformMatrix;
+        var a = m[0], b = m[1], c = m[2], d = m[3], e = m[4], f = m[5];
+
+        var ad_bc = a * d - b * c;
+        var bc_ad = b * c - a * d;
+
+        return [
+          d / ad_bc,
+          b / bc_ad,
+          c / bc_ad,
+          a / ad_bc,
+          (d * e - c * f) / bc_ad,
+          (b * e - a * f) / ad_bc
+        ];
+      }
+    });
+
+    ctx.save = function ctxSave() {
+      var old = this._transformMatrix;
+      this._transformStack.push(old);
+      this._transformMatrix = old.slice(0, 6);
+
+      this._originalSave();
+    };
+
+    ctx.restore = function ctxRestore() {
+      var prev = this._transformStack.pop();
+      if (prev) {
+        this._transformMatrix = prev;
+        this._originalRestore();
+      }
+    };
+
+    ctx.translate = function ctxTranslate(x, y) {
+      var m = this._transformMatrix;
+      m[4] = m[0] * x + m[2] * y + m[4];
+      m[5] = m[1] * x + m[3] * y + m[5];
+
+      this._originalTranslate(x, y);
+    };
+
+    ctx.scale = function ctxScale(x, y) {
+      var m = this._transformMatrix;
+      m[0] = m[0] * x;
+      m[1] = m[1] * x;
+      m[2] = m[2] * y;
+      m[3] = m[3] * y;
+
+      this._originalScale(x, y);
+    };
+
+    ctx.transform = function ctxTransform(a, b, c, d, e, f) {
+      var m = this._transformMatrix;
+      this._transformMatrix = [
+        m[0] * a + m[2] * b,
+        m[1] * a + m[3] * b,
+        m[0] * c + m[2] * d,
+        m[1] * c + m[3] * d,
+        m[0] * e + m[2] * f + m[4],
+        m[1] * e + m[3] * f + m[5]
+      ];
+
+      ctx._originalTransform(a, b, c, d, e, f);
+    };
+
+    ctx.rotate = function ctxRotate(angle) {
+      var cosValue = Math.cos(angle);
+      var sinValue = Math.sin(angle);
+
+      var m = this._transformMatrix;
+      this._transformMatrix = [
+        m[0] * cosValue + m[2] * sinValue,
+        m[1] * cosValue + m[3] * sinValue,
+        m[0] * (-sinValue) + m[2] * cosValue,
+        m[1] * (-sinValue) + m[3] * cosValue,
+        m[4],
+        m[5]
+      ];
+
+      this._originalRotate(angle);
+    };
+  }
+}
+
+var CanvasExtraState = (function CanvasExtraStateClosure() {
+  function CanvasExtraState(old) {
     // Are soft masks and alpha values shapes or opacities?
     this.alphaIsShape = false;
     this.fontSize = 0;
+    this.fontSizeScale = 1;
     this.textMatrix = IDENTITY_MATRIX;
+    this.fontMatrix = IDENTITY_MATRIX;
     this.leading = 0;
     // Current point (in user coordinates)
     this.x = 0;
@@ -974,6 +1519,7 @@ var CanvasExtraState = (function canvasExtraState() {
     this.charSpacing = 0;
     this.wordSpacing = 0;
     this.textHScale = 1;
+    this.textRenderingMode = TextRenderingMode.FILL;
     // Color spaces
     this.fillColorSpace = new DeviceGrayCS();
     this.fillColorSpaceObj = null;
@@ -987,47 +1533,40 @@ var CanvasExtraState = (function canvasExtraState() {
     // Note: fill alpha applies to all non-stroking operations
     this.fillAlpha = 1;
     this.strokeAlpha = 1;
+    this.lineWidth = 1;
 
     this.old = old;
   }
 
-  constructor.prototype = {
-    clone: function canvasextra_clone() {
+  CanvasExtraState.prototype = {
+    clone: function CanvasExtraState_clone() {
       return Object.create(this);
     },
-    setCurrentPoint: function canvasextra_setCurrentPoint(x, y) {
+    setCurrentPoint: function CanvasExtraState_setCurrentPoint(x, y) {
       this.x = x;
       this.y = y;
     }
   };
-  return constructor;
+  return CanvasExtraState;
 })();
 
-function ScratchCanvas(width, height) {
-  var canvas = document.createElement('canvas');
-  canvas.width = width;
-  canvas.height = height;
-  return canvas;
-}
-
-var CanvasGraphics = (function canvasGraphics() {
-  // Defines the time the executeIRQueue is going to be executing
+var CanvasGraphics = (function CanvasGraphicsClosure() {
+  // Defines the time the executeOperatorList is going to be executing
   // before it stops and shedules a continue of execution.
-  var kExecutionTime = 50;
-
-  // Number of IR commands to execute before checking
-  // if we execute longer then `kExecutionTime`.
-  var kExecutionTimeCheck = 500;
+  var kExecutionTime = 15;
 
-  function constructor(canvasCtx, objs) {
+  function CanvasGraphics(canvasCtx, objs, textLayer) {
     this.ctx = canvasCtx;
     this.current = new CanvasExtraState();
     this.stateStack = [];
     this.pendingClip = null;
     this.res = null;
     this.xobjs = null;
-    this.ScratchCanvas = ScratchCanvas;
     this.objs = objs;
+    this.textLayer = textLayer;
+    if (canvasCtx) {
+      addContextCurrentTransform(canvasCtx);
+    }
   }
 
   var LINE_CAP_STYLES = ['butt', 'round', 'square'];
@@ -1035,8 +1574,37 @@ var CanvasGraphics = (function canvasGraphics() {
   var NORMAL_CLIP = {};
   var EO_CLIP = {};
 
-  constructor.prototype = {
-    beginDrawing: function canvasGraphicsBeginDrawing(mediaBox) {
+  CanvasGraphics.prototype = {
+    slowCommands: {
+      'stroke': true,
+      'closeStroke': true,
+      'fill': true,
+      'eoFill': true,
+      'fillStroke': true,
+      'eoFillStroke': true,
+      'closeFillStroke': true,
+      'closeEOFillStroke': true,
+      'showText': true,
+      'showSpacedText': true,
+      'setStrokeColorSpace': true,
+      'setFillColorSpace': true,
+      'setStrokeColor': true,
+      'setStrokeColorN': true,
+      'setFillColor': true,
+      'setFillColorN': true,
+      'setStrokeGray': true,
+      'setFillGray': true,
+      'setStrokeRGBColor': true,
+      'setFillRGBColor': true,
+      'setStrokeCMYKColor': true,
+      'setFillCMYKColor': true,
+      'paintJpegXObject': true,
+      'paintImageXObject': true,
+      'paintImageMaskXObject': true,
+      'shadingFill': true
+    },
+
+    beginDrawing: function CanvasGraphics_beginDrawing(mediaBox) {
       var cw = this.ctx.canvas.width, ch = this.ctx.canvas.height;
       this.ctx.save();
       switch (mediaBox.rotate) {
@@ -1053,43 +1621,63 @@ var CanvasGraphics = (function canvasGraphics() {
           this.ctx.transform(0, -1, -1, 0, cw, ch);
           break;
       }
+      // Scale so that canvas units are the same as PDF user space units
       this.ctx.scale(cw / mediaBox.width, ch / mediaBox.height);
+      // Move the media left-top corner to the (0,0) canvas position
+      this.ctx.translate(-mediaBox.x, -mediaBox.y);
+
+      if (this.textLayer)
+        this.textLayer.beginLayout();
     },
 
-    executeIRQueue: function canvasGraphicsExecuteIRQueue(codeIR,
-                                  executionStartIdx, continueCallback) {
-      var argsArray = codeIR.argsArray;
-      var fnArray = codeIR.fnArray;
+    executeOperatorList: function CanvasGraphics_executeOperatorList(
+                                    operatorList,
+                                    executionStartIdx, continueCallback,
+                                    stepper) {
+      var argsArray = operatorList.argsArray;
+      var fnArray = operatorList.fnArray;
       var i = executionStartIdx || 0;
       var argsArrayLen = argsArray.length;
 
+      // Sometimes the OperatorList to execute is empty.
+      if (argsArrayLen == i) {
+        return i;
+      }
+
       var executionEndIdx;
-      var startTime = Date.now();
+      var endTime = Date.now() + kExecutionTime;
 
       var objs = this.objs;
+      var fnName;
+      var slowCommands = this.slowCommands;
 
-      do {
-        executionEndIdx = Math.min(argsArrayLen, i + kExecutionTimeCheck);
+      while (true) {
+        if (stepper && i === stepper.nextBreakPoint) {
+          stepper.breakIt(i, continueCallback);
+          return i;
+        }
 
-        for (i; i < executionEndIdx; i++) {
-          if (fnArray[i] !== 'dependency') {
-            this[fnArray[i]].apply(this, argsArray[i]);
-          } else {
-            var deps = argsArray[i];
-            for (var n = 0, nn = deps.length; n < nn; n++) {
-              var depObjId = deps[n];
-
-              // If the promise isn't resolved yet, add the continueCallback
-              // to the promise and bail out.
-              if (!objs.isResolved(depObjId)) {
-                objs.get(depObjId, continueCallback);
-                return i;
-              }
+        fnName = fnArray[i];
+
+        if (fnName !== 'dependency') {
+          this[fnName].apply(this, argsArray[i]);
+        } else {
+          var deps = argsArray[i];
+          for (var n = 0, nn = deps.length; n < nn; n++) {
+            var depObjId = deps[n];
+
+            // If the promise isn't resolved yet, add the continueCallback
+            // to the promise and bail out.
+            if (!objs.isResolved(depObjId)) {
+              objs.get(depObjId, continueCallback);
+              return i;
             }
           }
         }
 
-        // If the entire IRQueue was executed, stop as were done.
+        i++;
+
+        // If the entire operatorList was executed, stop as were done.
         if (i == argsArrayLen) {
           return i;
         }
@@ -1097,44 +1685,50 @@ var CanvasGraphics = (function canvasGraphics() {
         // If the execution took longer then a certain amount of time, shedule
         // to continue exeution after a short delay.
         // However, this is only possible if a 'continueCallback' is passed in.
-        if (continueCallback && (Date.now() - startTime) > kExecutionTime) {
+        if (continueCallback && slowCommands[fnName] && Date.now() > endTime) {
           setTimeout(continueCallback, 0);
           return i;
         }
 
-        // If the IRQueue isn't executed completly yet OR the execution time
-        // was short enough, do another execution round.
-      } while (true);
+        // If the operatorList isn't executed completely yet OR the execution
+        // time was short enough, do another execution round.
+      }
     },
 
-    endDrawing: function canvasGraphicsEndDrawing() {
+    endDrawing: function CanvasGraphics_endDrawing() {
       this.ctx.restore();
+
+      if (this.textLayer)
+        this.textLayer.endLayout();
     },
 
     // Graphics state
-    setLineWidth: function canvasGraphicsSetLineWidth(width) {
+    setLineWidth: function CanvasGraphics_setLineWidth(width) {
+      this.current.lineWidth = width;
       this.ctx.lineWidth = width;
     },
-    setLineCap: function canvasGraphicsSetLineCap(style) {
+    setLineCap: function CanvasGraphics_setLineCap(style) {
       this.ctx.lineCap = LINE_CAP_STYLES[style];
     },
-    setLineJoin: function canvasGraphicsSetLineJoin(style) {
+    setLineJoin: function CanvasGraphics_setLineJoin(style) {
       this.ctx.lineJoin = LINE_JOIN_STYLES[style];
     },
-    setMiterLimit: function canvasGraphicsSetMiterLimit(limit) {
+    setMiterLimit: function CanvasGraphics_setMiterLimit(limit) {
       this.ctx.miterLimit = limit;
     },
-    setDash: function canvasGraphicsSetDash(dashArray, dashPhase) {
+    setDash: function CanvasGraphics_setDash(dashArray, dashPhase) {
       this.ctx.mozDash = dashArray;
       this.ctx.mozDashOffset = dashPhase;
+      this.ctx.webkitLineDash = dashArray;
+      this.ctx.webkitLineDashOffset = dashPhase;
     },
-    setRenderingIntent: function canvasGraphicsSetRenderingIntent(intent) {
+    setRenderingIntent: function CanvasGraphics_setRenderingIntent(intent) {
       TODO('set rendering intent: ' + intent);
     },
-    setFlatness: function canvasGraphicsSetFlatness(flatness) {
+    setFlatness: function CanvasGraphics_setFlatness(flatness) {
       TODO('set flatness: ' + flatness);
     },
-    setGState: function canvasGraphicsSetGState(states) {
+    setGState: function CanvasGraphics_setGState(states) {
       for (var i = 0, ii = states.length; i < ii; i++) {
         var state = states[i];
         var key = state[0];
@@ -1175,55 +1769,57 @@ var CanvasGraphics = (function canvasGraphics() {
         }
       }
     },
-    save: function canvasGraphicsSave() {
+    save: function CanvasGraphics_save() {
       this.ctx.save();
       var old = this.current;
       this.stateStack.push(old);
       this.current = old.clone();
     },
-    restore: function canvasGraphicsRestore() {
+    restore: function CanvasGraphics_restore() {
       var prev = this.stateStack.pop();
       if (prev) {
         this.current = prev;
         this.ctx.restore();
       }
     },
-    transform: function canvasGraphicsTransform(a, b, c, d, e, f) {
+    transform: function CanvasGraphics_transform(a, b, c, d, e, f) {
       this.ctx.transform(a, b, c, d, e, f);
     },
 
     // Path
-    moveTo: function canvasGraphicsMoveTo(x, y) {
+    moveTo: function CanvasGraphics_moveTo(x, y) {
       this.ctx.moveTo(x, y);
       this.current.setCurrentPoint(x, y);
     },
-    lineTo: function canvasGraphicsLineTo(x, y) {
+    lineTo: function CanvasGraphics_lineTo(x, y) {
       this.ctx.lineTo(x, y);
       this.current.setCurrentPoint(x, y);
     },
-    curveTo: function canvasGraphicsCurveTo(x1, y1, x2, y2, x3, y3) {
+    curveTo: function CanvasGraphics_curveTo(x1, y1, x2, y2, x3, y3) {
       this.ctx.bezierCurveTo(x1, y1, x2, y2, x3, y3);
       this.current.setCurrentPoint(x3, y3);
     },
-    curveTo2: function canvasGraphicsCurveTo2(x2, y2, x3, y3) {
+    curveTo2: function CanvasGraphics_curveTo2(x2, y2, x3, y3) {
       var current = this.current;
       this.ctx.bezierCurveTo(current.x, current.y, x2, y2, x3, y3);
       current.setCurrentPoint(x3, y3);
     },
-    curveTo3: function canvasGraphicsCurveTo3(x1, y1, x3, y3) {
+    curveTo3: function CanvasGraphics_curveTo3(x1, y1, x3, y3) {
       this.curveTo(x1, y1, x3, y3, x3, y3);
       this.current.setCurrentPoint(x3, y3);
     },
-    closePath: function canvasGraphicsClosePath() {
+    closePath: function CanvasGraphics_closePath() {
       this.ctx.closePath();
     },
-    rectangle: function canvasGraphicsRectangle(x, y, width, height) {
+    rectangle: function CanvasGraphics_rectangle(x, y, width, height) {
       this.ctx.rect(x, y, width, height);
     },
-    stroke: function canvasGraphicsStroke(consumePath) {
+    stroke: function CanvasGraphics_stroke(consumePath) {
       consumePath = typeof consumePath !== 'undefined' ? consumePath : true;
       var ctx = this.ctx;
       var strokeColor = this.current.strokeColor;
+      if (this.current.lineWidth === 0)
+        ctx.lineWidth = this.getSinglePixelWidth();
       // For stroke we want to temporarily change the global alpha to the
       // stroking alpha.
       ctx.globalAlpha = this.current.strokeAlpha;
@@ -1243,11 +1839,11 @@ var CanvasGraphics = (function canvasGraphics() {
       // Restore the global alpha to the fill alpha
       ctx.globalAlpha = this.current.fillAlpha;
     },
-    closeStroke: function canvasGraphicsCloseStroke() {
+    closeStroke: function CanvasGraphics_closeStroke() {
       this.closePath();
       this.stroke();
     },
-    fill: function canvasGraphicsFill(consumePath) {
+    fill: function CanvasGraphics_fill(consumePath) {
       consumePath = typeof consumePath !== 'undefined' ? consumePath : true;
       var ctx = this.ctx;
       var fillColor = this.current.fillColor;
@@ -1264,126 +1860,204 @@ var CanvasGraphics = (function canvasGraphics() {
       if (consumePath)
         this.consumePath();
     },
-    eoFill: function canvasGraphicsEoFill() {
+    eoFill: function CanvasGraphics_eoFill() {
       var savedFillRule = this.setEOFillRule();
       this.fill();
       this.restoreFillRule(savedFillRule);
     },
-    fillStroke: function canvasGraphicsFillStroke() {
+    fillStroke: function CanvasGraphics_fillStroke() {
       this.fill(false);
       this.stroke(false);
 
       this.consumePath();
     },
-    eoFillStroke: function canvasGraphicsEoFillStroke() {
+    eoFillStroke: function CanvasGraphics_eoFillStroke() {
       var savedFillRule = this.setEOFillRule();
       this.fillStroke();
       this.restoreFillRule(savedFillRule);
     },
-    closeFillStroke: function canvasGraphicsCloseFillStroke() {
+    closeFillStroke: function CanvasGraphics_closeFillStroke() {
       this.closePath();
       this.fillStroke();
     },
-    closeEOFillStroke: function canvasGraphicsCloseEOFillStroke() {
+    closeEOFillStroke: function CanvasGraphics_closeEOFillStroke() {
       var savedFillRule = this.setEOFillRule();
       this.closePath();
       this.fillStroke();
       this.restoreFillRule(savedFillRule);
     },
-    endPath: function canvasGraphicsEndPath() {
+    endPath: function CanvasGraphics_endPath() {
       this.consumePath();
     },
 
     // Clipping
-    clip: function canvasGraphicsClip() {
+    clip: function CanvasGraphics_clip() {
       this.pendingClip = NORMAL_CLIP;
     },
-    eoClip: function canvasGraphicsEoClip() {
+    eoClip: function CanvasGraphics_eoClip() {
       this.pendingClip = EO_CLIP;
     },
 
     // Text
-    beginText: function canvasGraphicsBeginText() {
+    beginText: function CanvasGraphics_beginText() {
       this.current.textMatrix = IDENTITY_MATRIX;
       this.current.x = this.current.lineX = 0;
       this.current.y = this.current.lineY = 0;
     },
-    endText: function canvasGraphicsEndText() {
+    endText: function CanvasGraphics_endText() {
     },
-    setCharSpacing: function canvasGraphicsSetCharSpacing(spacing) {
+    setCharSpacing: function CanvasGraphics_setCharSpacing(spacing) {
       this.current.charSpacing = spacing;
     },
-    setWordSpacing: function canvasGraphicsSetWordSpacing(spacing) {
+    setWordSpacing: function CanvasGraphics_setWordSpacing(spacing) {
       this.current.wordSpacing = spacing;
     },
-    setHScale: function canvasGraphicsSetHScale(scale) {
+    setHScale: function CanvasGraphics_setHScale(scale) {
       this.current.textHScale = scale / 100;
     },
-    setLeading: function canvasGraphicsSetLeading(leading) {
+    setLeading: function CanvasGraphics_setLeading(leading) {
       this.current.leading = -leading;
     },
-    setFont: function canvasGraphicsSetFont(fontRefName, size) {
-      var fontObj = this.objs.get(fontRefName).fontObj;
+    setFont: function CanvasGraphics_setFont(fontRefName, size) {
+      var fontObj = this.objs.get(fontRefName);
+      var current = this.current;
+
+      if (!fontObj)
+        error('Can\'t find font for ' + fontRefName);
+
+      // Slice-clone matrix so we can manipulate it without affecting original
+      if (fontObj.fontMatrix)
+        current.fontMatrix = fontObj.fontMatrix.slice(0);
+      else
+        current.fontMatrix = IDENTITY_MATRIX.slice(0);
 
-      if (!fontObj) {
-        throw 'Can\'t find font for ' + fontRefName;
+      // A valid matrix needs all main diagonal elements to be non-zero
+      // This also ensures we bypass FF bugzilla bug #719844.
+      if (current.fontMatrix[0] === 0 ||
+          current.fontMatrix[3] === 0) {
+        warn('Invalid font matrix for font ' + fontRefName);
       }
 
-      var name = fontObj.loadedName || 'sans-serif';
+      // The spec for Tf (setFont) says that 'size' specifies the font 'scale',
+      // and in some docs this can be negative (inverted x-y axes).
+      // We implement this condition with fontMatrix.
+      if (size < 0) {
+        size = -size;
+        current.fontMatrix[0] *= -1;
+        current.fontMatrix[3] *= -1;
+      }
 
       this.current.font = fontObj;
       this.current.fontSize = size;
 
+      if (fontObj.coded)
+        return; // we don't need ctx.font for Type3 fonts
+
       var name = fontObj.loadedName || 'sans-serif';
       var bold = fontObj.black ? (fontObj.bold ? 'bolder' : 'bold') :
                                  (fontObj.bold ? 'bold' : 'normal');
 
       var italic = fontObj.italic ? 'italic' : 'normal';
-      var serif = fontObj.serif ? 'serif' : 'sans-serif';
+      var serif = fontObj.isSerifFont ? 'serif' : 'sans-serif';
       var typeface = '"' + name + '", ' + serif;
-      var rule = italic + ' ' + bold + ' ' + size + 'px ' + typeface;
+
+      // Some font backends cannot handle fonts below certain size.
+      // Keeping the font at minimal size and using the fontSizeScale to change
+      // the current transformation matrix before the fillText/strokeText.
+      // See https://bugzilla.mozilla.org/show_bug.cgi?id=726227
+      var browserFontSize = size >= MIN_FONT_SIZE ? size : MIN_FONT_SIZE;
+      this.current.fontSizeScale = browserFontSize != MIN_FONT_SIZE ? 1.0 :
+                                   size / MIN_FONT_SIZE;
+
+      var rule = italic + ' ' + bold + ' ' + browserFontSize + 'px ' + typeface;
       this.ctx.font = rule;
     },
-    setTextRenderingMode: function canvasGraphicsSetTextRenderingMode(mode) {
-      TODO('text rendering mode: ' + mode);
+    setTextRenderingMode: function CanvasGraphics_setTextRenderingMode(mode) {
+      if (mode >= TextRenderingMode.FILL_ADD_TO_PATH)
+        TODO('unsupported text rendering mode: ' + mode);
+      this.current.textRenderingMode = mode;
     },
-    setTextRise: function canvasGraphicsSetTextRise(rise) {
+    setTextRise: function CanvasGraphics_setTextRise(rise) {
       TODO('text rise: ' + rise);
     },
-    moveText: function canvasGraphicsMoveText(x, y) {
+    moveText: function CanvasGraphics_moveText(x, y) {
       this.current.x = this.current.lineX += x;
       this.current.y = this.current.lineY += y;
     },
-    setLeadingMoveText: function canvasGraphicsSetLeadingMoveText(x, y) {
+    setLeadingMoveText: function CanvasGraphics_setLeadingMoveText(x, y) {
       this.setLeading(-y);
       this.moveText(x, y);
     },
-    setTextMatrix: function canvasGraphicsSetTextMatrix(a, b, c, d, e, f) {
+    setTextMatrix: function CanvasGraphics_setTextMatrix(a, b, c, d, e, f) {
       this.current.textMatrix = [a, b, c, d, e, f];
 
       this.current.x = this.current.lineX = 0;
       this.current.y = this.current.lineY = 0;
     },
-    nextLine: function canvasGraphicsNextLine() {
+    nextLine: function CanvasGraphics_nextLine() {
       this.moveText(0, this.current.leading);
     },
-    showText: function canvasGraphicsShowText(text) {
+    applyTextTransforms: function CanvasGraphics_applyTextTransforms() {
+      var ctx = this.ctx;
+      var current = this.current;
+      var textHScale = current.textHScale;
+      var fontMatrix = current.fontMatrix || IDENTITY_MATRIX;
+
+      ctx.transform.apply(ctx, current.textMatrix);
+      ctx.scale(1, -1);
+      ctx.translate(current.x, -1 * current.y);
+      ctx.transform.apply(ctx, fontMatrix);
+      ctx.scale(textHScale, 1);
+    },
+    getTextGeometry: function CanvasGraphics_getTextGeometry() {
+      var geometry = {};
+      var ctx = this.ctx;
+      var font = this.current.font;
+      var ctxMatrix = ctx.mozCurrentTransform;
+      if (ctxMatrix) {
+        var bl = Util.applyTransform([0, 0], ctxMatrix);
+        var tr = Util.applyTransform([1, 1], ctxMatrix);
+        geometry.x = bl[0];
+        geometry.y = bl[1];
+        geometry.hScale = tr[0] - bl[0];
+        geometry.vScale = tr[1] - bl[1];
+      }
+      geometry.spaceWidth = font.spaceWidth;
+      return geometry;
+    },
+
+    showText: function CanvasGraphics_showText(str, skipTextSelection) {
       var ctx = this.ctx;
       var current = this.current;
       var font = current.font;
-      var glyphs = font.charsToGlyphs(text);
+      var glyphs = font.charsToGlyphs(str);
       var fontSize = current.fontSize;
+      var fontSizeScale = current.fontSizeScale;
       var charSpacing = current.charSpacing;
       var wordSpacing = current.wordSpacing;
       var textHScale = current.textHScale;
+      var fontMatrix = current.fontMatrix || IDENTITY_MATRIX;
+      var textHScale2 = textHScale * fontMatrix[0];
       var glyphsLength = glyphs.length;
+      var textLayer = this.textLayer;
+      var text = {str: '', length: 0, canvasWidth: 0, geom: {}};
+      var textSelection = textLayer && !skipTextSelection ? true : false;
+      var textRenderingMode = current.textRenderingMode;
+
+      // Type3 fonts - each glyph is a "mini-PDF"
       if (font.coded) {
         ctx.save();
         ctx.transform.apply(ctx, current.textMatrix);
         ctx.translate(current.x, current.y);
 
-        var fontMatrix = font.fontMatrix || IDENTITY_MATRIX;
-        ctx.scale(1 / textHScale, 1);
+        ctx.scale(textHScale, 1);
+
+        if (textSelection) {
+          this.save();
+          ctx.scale(1, -1);
+          text.geom = this.getTextGeometry();
+          this.restore();
+        }
         for (var i = 0; i < glyphsLength; ++i) {
 
           var glyph = glyphs[i];
@@ -1396,85 +2070,183 @@ var CanvasGraphics = (function canvasGraphics() {
           this.save();
           ctx.scale(fontSize, fontSize);
           ctx.transform.apply(ctx, fontMatrix);
-          this.executeIRQueue(glyph.codeIRQueue);
+          this.executeOperatorList(glyph.operatorList);
           this.restore();
 
           var transformed = Util.applyTransform([glyph.width, 0], fontMatrix);
-          var width = transformed[0] * fontSize + charSpacing;
+          var width = transformed[0] * fontSize +
+              Util.sign(current.fontMatrix[0]) * charSpacing;
 
           ctx.translate(width, 0);
-          current.x += width;
+          current.x += width * textHScale;
 
+          text.str += glyph.unicode;
+          text.length++;
+          text.canvasWidth += width;
         }
         ctx.restore();
       } else {
         ctx.save();
-        ctx.transform.apply(ctx, current.textMatrix);
-        ctx.scale(1, -1);
-        ctx.translate(current.x, -1 * current.y);
-        ctx.transform.apply(ctx, font.fontMatrix || IDENTITY_MATRIX);
+        this.applyTextTransforms();
 
-        ctx.scale(1 / textHScale, 1);
+        var lineWidth = current.lineWidth;
+        var scale = Math.abs(current.textMatrix[0] * fontMatrix[0]);
+        if (scale == 0 || lineWidth == 0)
+          lineWidth = this.getSinglePixelWidth();
+        else
+          lineWidth /= scale;
+
+        if (textSelection)
+          text.geom = this.getTextGeometry();
+
+        if (fontSizeScale != 1.0) {
+          ctx.scale(fontSizeScale, fontSizeScale);
+          lineWidth /= fontSizeScale;
+        }
 
-        var width = 0;
+        ctx.lineWidth = lineWidth;
+
+        var x = 0;
         for (var i = 0; i < glyphsLength; ++i) {
           var glyph = glyphs[i];
           if (glyph === null) {
             // word break
-            width += wordSpacing;
+            x += Util.sign(current.fontMatrix[0]) * wordSpacing;
             continue;
           }
 
-          var unicode = glyph.unicode;
-          var char = (unicode >= 0x10000) ?
-            String.fromCharCode(0xD800 | ((unicode - 0x10000) >> 10),
-            0xDC00 | (unicode & 0x3FF)) : String.fromCharCode(unicode);
+          var character = glyph.fontChar;
+          var charWidth = glyph.width * fontSize * 0.001 +
+              Util.sign(current.fontMatrix[0]) * charSpacing;
+
+          if (!glyph.disabled) {
+            var scaledX = x / fontSizeScale;
+            switch (textRenderingMode) {
+              default: // other unsupported rendering modes
+              case TextRenderingMode.FILL:
+              case TextRenderingMode.FILL_ADD_TO_PATH:
+                ctx.fillText(character, scaledX, 0);
+                break;
+              case TextRenderingMode.STROKE:
+              case TextRenderingMode.STROKE_ADD_TO_PATH:
+                ctx.strokeText(character, scaledX, 0);
+                break;
+              case TextRenderingMode.FILL_STROKE:
+              case TextRenderingMode.FILL_STROKE_ADD_TO_PATH:
+                ctx.fillText(character, scaledX, 0);
+                ctx.strokeText(character, scaledX, 0);
+                break;
+              case TextRenderingMode.INVISIBLE:
+                break;
+            }
+          }
+
+          x += charWidth;
 
-          ctx.fillText(char, width, 0);
-          width += glyph.width * fontSize * 0.001 + charSpacing;
+          var glyphUnicode = glyph.unicode === ' ' ? '\u00A0' : glyph.unicode;
+          var glyphUnicodeLength = glyphUnicode.length;
+          //reverse an arabic ligature
+          if (glyphUnicodeLength > 1 &&
+              isRTLRangeFor(glyphUnicode.charCodeAt(0))) {
+            for (var ii = glyphUnicodeLength - 1; ii >= 0; ii--)
+              text.str += glyphUnicode[ii];
+          } else
+            text.str += glyphUnicode;
+          text.length += glyphUnicodeLength;
+          text.canvasWidth += charWidth;
         }
-        current.x += width;
-
+        current.x += x * textHScale2;
         ctx.restore();
       }
-    },
 
-    showSpacedText: function canvasGraphicsShowSpacedText(arr) {
+      if (textSelection)
+        this.textLayer.appendText(text, font.loadedName, fontSize);
+
+      return text;
+    },
+    showSpacedText: function CanvasGraphics_showSpacedText(arr) {
       var ctx = this.ctx;
       var current = this.current;
+      var font = current.font;
       var fontSize = current.fontSize;
       var textHScale = current.textHScale;
+      if (!font.coded)
+        textHScale *= (current.fontMatrix || IDENTITY_MATRIX)[0];
       var arrLength = arr.length;
+      var textLayer = this.textLayer;
+      var text = {str: '', length: 0, canvasWidth: 0, geom: {}};
+      var textSelection = textLayer ? true : false;
+
+      if (textSelection) {
+        ctx.save();
+        // Type3 fonts - each glyph is a "mini-PDF" (see also showText)
+        if (font.coded) {
+          ctx.transform.apply(ctx, current.textMatrix);
+          ctx.scale(1, -1);
+          ctx.translate(current.x, -1 * current.y);
+          ctx.scale(textHScale, 1);
+        } else
+          this.applyTextTransforms();
+        text.geom = this.getTextGeometry();
+        ctx.restore();
+      }
+
       for (var i = 0; i < arrLength; ++i) {
         var e = arr[i];
         if (isNum(e)) {
-          current.x -= e * 0.001 * fontSize * textHScale;
+          var spacingLength = -e * 0.001 * fontSize * textHScale;
+          current.x += spacingLength;
+
+          if (textSelection) {
+            // Emulate precise spacing via HTML spaces
+            text.canvasWidth += spacingLength;
+            if (e < 0 && text.geom.spaceWidth > 0) { // avoid div by zero
+              var numFakeSpaces = Math.round(-e / text.geom.spaceWidth);
+              if (numFakeSpaces > 0) {
+                text.str += '\u00A0';
+                text.length++;
+              }
+            }
+          }
         } else if (isString(e)) {
-          this.showText(e);
+          var shownText = this.showText(e, true);
+
+          if (textSelection) {
+            if (shownText.str === ' ') {
+              text.str += '\u00A0';
+            } else {
+              text.str += shownText.str;
+            }
+            text.canvasWidth += shownText.canvasWidth;
+            text.length += shownText.length;
+          }
         } else {
           malformed('TJ array element ' + e + ' is not string or num');
         }
       }
+
+      if (textSelection)
+        this.textLayer.appendText(text, font.loadedName, fontSize);
     },
-    nextLineShowText: function canvasGraphicsNextLineShowText(text) {
+    nextLineShowText: function CanvasGraphics_nextLineShowText(text) {
       this.nextLine();
       this.showText(text);
     },
     nextLineSetSpacingShowText:
-      function canvasGraphicsNextLineSetSpacingShowText(wordSpacing,
-                                                        charSpacing,
-                                                        text) {
+      function CanvasGraphics_nextLineSetSpacingShowText(wordSpacing,
+                                                         charSpacing,
+                                                         text) {
       this.setWordSpacing(wordSpacing);
       this.setCharSpacing(charSpacing);
       this.nextLineShowText(text);
     },
 
     // Type3 fonts
-    setCharWidth: function canvasGraphicsSetCharWidth(xWidth, yWidth) {
+    setCharWidth: function CanvasGraphics_setCharWidth(xWidth, yWidth) {
       // We can safely ignore this since the width should be the same
       // as the width in the Widths array.
     },
-    setCharWidthAndBounds: function canvasGraphicsSetCharWidthAndBounds(xWidth,
+    setCharWidthAndBounds: function CanvasGraphics_setCharWidthAndBounds(xWidth,
                                                                         yWidth,
                                                                         llx,
                                                                         lly,
@@ -1488,20 +2260,20 @@ var CanvasGraphics = (function canvasGraphics() {
     },
 
     // Color
-    setStrokeColorSpace: function canvasGraphicsSetStrokeColorSpace(raw) {
+    setStrokeColorSpace: function CanvasGraphics_setStrokeColorSpace(raw) {
       this.current.strokeColorSpace = ColorSpace.fromIR(raw);
     },
-    setFillColorSpace: function canvasGraphicsSetFillColorSpace(raw) {
+    setFillColorSpace: function CanvasGraphics_setFillColorSpace(raw) {
       this.current.fillColorSpace = ColorSpace.fromIR(raw);
     },
-    setStrokeColor: function canvasGraphicsSetStrokeColor(/*...*/) {
+    setStrokeColor: function CanvasGraphics_setStrokeColor(/*...*/) {
       var cs = this.current.strokeColorSpace;
-      var color = cs.getRgb(arguments);
-      var color = Util.makeCssRgb.apply(null, cs.getRgb(arguments));
+      var rgbColor = cs.getRgb(arguments);
+      var color = Util.makeCssRgb(rgbColor[0], rgbColor[1], rgbColor[2]);
       this.ctx.strokeStyle = color;
       this.current.strokeColor = color;
     },
-    getColorN_IR_Pattern: function canvasGraphicsGetColorN_IR_Pattern(IR, cs) {
+    getColorN_Pattern: function CanvasGraphics_getColorN_Pattern(IR, cs) {
       if (IR[0] == 'TilingPattern') {
         var args = IR[1];
         var base = cs.base;
@@ -1517,37 +2289,38 @@ var CanvasGraphics = (function canvasGraphics() {
         }
         var pattern = new TilingPattern(IR, color, this.ctx, this.objs);
       } else if (IR[0] == 'RadialAxial' || IR[0] == 'Dummy') {
-        var pattern = Pattern.shadingFromIR(this.ctx, IR);
+        var pattern = Pattern.shadingFromIR(IR);
       } else {
-        throw 'Unkown IR type';
+        error('Unkown IR type ' + IR[0]);
       }
       return pattern;
     },
-    setStrokeColorN_IR: function canvasGraphicsSetStrokeColorN(/*...*/) {
+    setStrokeColorN: function CanvasGraphics_setStrokeColorN(/*...*/) {
       var cs = this.current.strokeColorSpace;
 
       if (cs.name == 'Pattern') {
-        this.current.strokeColor = this.getColorN_IR_Pattern(arguments, cs);
+        this.current.strokeColor = this.getColorN_Pattern(arguments, cs);
       } else {
         this.setStrokeColor.apply(this, arguments);
       }
     },
-    setFillColor: function canvasGraphicsSetFillColor(/*...*/) {
+    setFillColor: function CanvasGraphics_setFillColor(/*...*/) {
       var cs = this.current.fillColorSpace;
-      var color = Util.makeCssRgb.apply(null, cs.getRgb(arguments));
+      var rgbColor = cs.getRgb(arguments);
+      var color = Util.makeCssRgb(rgbColor[0], rgbColor[1], rgbColor[2]);
       this.ctx.fillStyle = color;
       this.current.fillColor = color;
     },
-    setFillColorN_IR: function canvasGraphicsSetFillColorN(/*...*/) {
+    setFillColorN: function CanvasGraphics_setFillColorN(/*...*/) {
       var cs = this.current.fillColorSpace;
 
       if (cs.name == 'Pattern') {
-        this.current.fillColor = this.getColorN_IR_Pattern(arguments, cs);
+        this.current.fillColor = this.getColorN_Pattern(arguments, cs);
       } else {
         this.setFillColor.apply(this, arguments);
       }
     },
-    setStrokeGray: function canvasGraphicsSetStrokeGray(gray) {
+    setStrokeGray: function CanvasGraphics_setStrokeGray(gray) {
       if (!(this.current.strokeColorSpace instanceof DeviceGrayCS))
         this.current.strokeColorSpace = new DeviceGrayCS();
 
@@ -1555,7 +2328,7 @@ var CanvasGraphics = (function canvasGraphics() {
       this.ctx.strokeStyle = color;
       this.current.strokeColor = color;
     },
-    setFillGray: function canvasGraphicsSetFillGray(gray) {
+    setFillGray: function CanvasGraphics_setFillGray(gray) {
       if (!(this.current.fillColorSpace instanceof DeviceGrayCS))
         this.current.fillColorSpace = new DeviceGrayCS();
 
@@ -1563,7 +2336,7 @@ var CanvasGraphics = (function canvasGraphics() {
       this.ctx.fillStyle = color;
       this.current.fillColor = color;
     },
-    setStrokeRGBColor: function canvasGraphicsSetStrokeRGBColor(r, g, b) {
+    setStrokeRGBColor: function CanvasGraphics_setStrokeRGBColor(r, g, b) {
       if (!(this.current.strokeColorSpace instanceof DeviceRgbCS))
         this.current.strokeColorSpace = new DeviceRgbCS();
 
@@ -1571,7 +2344,7 @@ var CanvasGraphics = (function canvasGraphics() {
       this.ctx.strokeStyle = color;
       this.current.strokeColor = color;
     },
-    setFillRGBColor: function canvasGraphicsSetFillRGBColor(r, g, b) {
+    setFillRGBColor: function CanvasGraphics_setFillRGBColor(r, g, b) {
       if (!(this.current.fillColorSpace instanceof DeviceRgbCS))
         this.current.fillColorSpace = new DeviceRgbCS();
 
@@ -1579,7 +2352,7 @@ var CanvasGraphics = (function canvasGraphics() {
       this.ctx.fillStyle = color;
       this.current.fillColor = color;
     },
-    setStrokeCMYKColor: function canvasGraphicsSetStrokeCMYKColor(c, m, y, k) {
+    setStrokeCMYKColor: function CanvasGraphics_setStrokeCMYKColor(c, m, y, k) {
       if (!(this.current.strokeColorSpace instanceof DeviceCmykCS))
         this.current.strokeColorSpace = new DeviceCmykCS();
 
@@ -1587,7 +2360,7 @@ var CanvasGraphics = (function canvasGraphics() {
       this.ctx.strokeStyle = color;
       this.current.strokeColor = color;
     },
-    setFillCMYKColor: function canvasGraphicsSetFillCMYKColor(c, m, y, k) {
+    setFillCMYKColor: function CanvasGraphics_setFillCMYKColor(c, m, y, k) {
       if (!(this.current.fillColorSpace instanceof DeviceCmykCS))
         this.current.fillColorSpace = new DeviceCmykCS();
 
@@ -1596,11 +2369,12 @@ var CanvasGraphics = (function canvasGraphics() {
       this.current.fillColor = color;
     },
 
-    shadingFill: function canvasGraphicsShadingFill(patternIR) {
+    shadingFill: function CanvasGraphics_shadingFill(patternIR) {
       var ctx = this.ctx;
 
       this.save();
-      ctx.fillStyle = Pattern.shadingFromIR(ctx, patternIR);
+      var pattern = Pattern.shadingFromIR(patternIR);
+      ctx.fillStyle = pattern.getPattern(ctx);
 
       var inv = ctx.mozCurrentTransformInverse;
       if (inv) {
@@ -1609,9 +2383,9 @@ var CanvasGraphics = (function canvasGraphics() {
         var height = canvas.height;
 
         var bl = Util.applyTransform([0, 0], inv);
-        var br = Util.applyTransform([0, width], inv);
-        var ul = Util.applyTransform([height, 0], inv);
-        var ur = Util.applyTransform([height, width], inv);
+        var br = Util.applyTransform([0, height], inv);
+        var ul = Util.applyTransform([width, 0], inv);
+        var ur = Util.applyTransform([width, height], inv);
 
         var x0 = Math.min(bl[0], br[0], ul[0], ur[0]);
         var y0 = Math.min(bl[1], br[1], ul[1], ur[1]);
@@ -1633,14 +2407,14 @@ var CanvasGraphics = (function canvasGraphics() {
     },
 
     // Images
-    beginInlineImage: function canvasGraphicsBeginInlineImage() {
+    beginInlineImage: function CanvasGraphics_beginInlineImage() {
       error('Should not call beginInlineImage');
     },
-    beginImageData: function canvasGraphicsBeginImageData() {
+    beginImageData: function CanvasGraphics_beginImageData() {
       error('Should not call beginImageData');
     },
 
-    paintFormXObjectBegin: function canvasGraphicsPaintFormXObjectBegin(matrix,
+    paintFormXObjectBegin: function CanvasGraphics_paintFormXObjectBegin(matrix,
                                                                         bbox) {
       this.save();
 
@@ -1656,13 +2430,13 @@ var CanvasGraphics = (function canvasGraphics() {
       }
     },
 
-    paintFormXObjectEnd: function canvasGraphicsPaintFormXObjectEnd() {
+    paintFormXObjectEnd: function CanvasGraphics_paintFormXObjectEnd() {
       this.restore();
     },
 
-    paintJpegXObject: function canvasGraphicsPaintJpegXObject(objId, w, h) {
-      var image = this.objs.get(objId);
-      if (!image) {
+    paintJpegXObject: function CanvasGraphics_paintJpegXObject(objId, w, h) {
+      var domImage = this.objs.get(objId);
+      if (!domImage) {
         error('Dependent image isn\'t ready yet');
       }
 
@@ -1672,14 +2446,13 @@ var CanvasGraphics = (function canvasGraphics() {
       // scale the image to the unit square
       ctx.scale(1 / w, -1 / h);
 
-      var domImage = image.getImage();
       ctx.drawImage(domImage, 0, 0, domImage.width, domImage.height,
                     0, -h, w, h);
 
       this.restore();
     },
 
-    paintImageMaskXObject: function canvasGraphicsPaintImageMaskXObject(
+    paintImageMaskXObject: function CanvasGraphics_paintImageMaskXObject(
                              imgArray, inverseDecode, width, height) {
       function applyStencilMask(buffer, inverseDecode) {
         var imgArrayPos = 0;
@@ -1709,7 +2482,7 @@ var CanvasGraphics = (function canvasGraphics() {
       // scale the image to the unit square
       ctx.scale(1 / w, -1 / h);
 
-      var tmpCanvas = new this.ScratchCanvas(w, h);
+      var tmpCanvas = createScratchCanvas(w, h);
       var tmpCtx = tmpCanvas.getContext('2d');
 
       var fillColor = this.current.fillColor;
@@ -1728,7 +2501,11 @@ var CanvasGraphics = (function canvasGraphics() {
       this.restore();
     },
 
-    paintImageXObject: function canvasGraphicsPaintImageXObject(imgData) {
+    paintImageXObject: function CanvasGraphics_paintImageXObject(objId) {
+      var imgData = this.objs.get(objId);
+      if (!imgData)
+        error('Dependent image isn\'t ready yet');
+
       this.save();
       var ctx = this.ctx;
       var w = imgData.width;
@@ -1736,59 +2513,49 @@ var CanvasGraphics = (function canvasGraphics() {
       // scale the image to the unit square
       ctx.scale(1 / w, -1 / h);
 
-      var tmpCanvas = new this.ScratchCanvas(w, h);
+      var tmpCanvas = createScratchCanvas(w, h);
       var tmpCtx = tmpCanvas.getContext('2d');
-      var tmpImgData;
-
-      // Some browsers can set an UInt8Array directly as imageData, some
-      // can't. As long as we don't have proper feature detection, just
-      // copy over each pixel and set the imageData that way.
-      tmpImgData = tmpCtx.getImageData(0, 0, w, h);
-
-      // Copy over the imageData.
-      var tmpImgDataPixels = tmpImgData.data;
-      var len = tmpImgDataPixels.length;
+      this.putBinaryImageData(tmpCtx, imgData, w, h);
 
-      while (len--) {
-        tmpImgDataPixels[len] = imgData.data[len];
-      }
-
-      tmpCtx.putImageData(tmpImgData, 0, 0);
       ctx.drawImage(tmpCanvas, 0, -h);
       this.restore();
     },
 
+    putBinaryImageData: function CanvasGraphics_putBinaryImageData() {
+      //
+    },
+
     // Marked content
 
-    markPoint: function canvasGraphicsMarkPoint(tag) {
+    markPoint: function CanvasGraphics_markPoint(tag) {
       TODO('Marked content');
     },
-    markPointProps: function canvasGraphicsMarkPointProps(tag, properties) {
+    markPointProps: function CanvasGraphics_markPointProps(tag, properties) {
       TODO('Marked content');
     },
-    beginMarkedContent: function canvasGraphicsBeginMarkedContent(tag) {
+    beginMarkedContent: function CanvasGraphics_beginMarkedContent(tag) {
       TODO('Marked content');
     },
-    beginMarkedContentProps:
-      function canvasGraphicsBeginMarkedContentProps(tag, properties) {
+    beginMarkedContentProps: function CanvasGraphics_beginMarkedContentProps(
+                                        tag, properties) {
       TODO('Marked content');
     },
-    endMarkedContent: function canvasGraphicsEndMarkedContent() {
+    endMarkedContent: function CanvasGraphics_endMarkedContent() {
       TODO('Marked content');
     },
 
     // Compatibility
 
-    beginCompat: function canvasGraphicsBeginCompat() {
+    beginCompat: function CanvasGraphics_beginCompat() {
       TODO('ignore undefined operators (should we do that anyway?)');
     },
-    endCompat: function canvasGraphicsEndCompat() {
+    endCompat: function CanvasGraphics_endCompat() {
       TODO('stop ignoring undefined operators');
     },
 
     // Helper functions
 
-    consumePath: function canvasGraphicsConsumePath() {
+    consumePath: function CanvasGraphics_consumePath() {
       if (this.pendingClip) {
         var savedFillRule = null;
         if (this.pendingClip == EO_CLIP)
@@ -1805,139 +2572,214 @@ var CanvasGraphics = (function canvasGraphics() {
     // We generally keep the canvas context set for
     // nonzero-winding, and just set evenodd for the operations
     // that need them.
-    setEOFillRule: function canvasGraphicsSetEOFillRule() {
+    setEOFillRule: function CanvasGraphics_setEOFillRule() {
       var savedFillRule = this.ctx.mozFillRule;
       this.ctx.mozFillRule = 'evenodd';
       return savedFillRule;
     },
-    restoreFillRule: function canvasGraphicsRestoreFillRule(rule) {
+    restoreFillRule: function CanvasGraphics_restoreFillRule(rule) {
       this.ctx.mozFillRule = rule;
+    },
+    getSinglePixelWidth: function CanvasGraphics_getSinglePixelWidth(scale) {
+      var inverse = this.ctx.mozCurrentTransformInverse;
+      return Math.abs(inverse[0] + inverse[2]);
     }
   };
 
-  return constructor;
+  return CanvasGraphics;
 })();
 
+if (!isWorker) {
+  // Feature detection if the browser can use an Uint8Array directly as imgData.
+  var canvas = document.createElement('canvas');
+  canvas.width = 1;
+  canvas.height = 1;
+  var ctx = canvas.getContext('2d');
+
+  try {
+    ctx.putImageData({
+      width: 1,
+      height: 1,
+      data: new Uint8Array(4)
+    }, 0, 0);
+
+    CanvasGraphics.prototype.putBinaryImageData =
+      function CanvasGraphicsPutBinaryImageDataNative(ctx, imgData) {
+        ctx.putImageData(imgData, 0, 0);
+      };
+  } catch (e) {
+    CanvasGraphics.prototype.putBinaryImageData =
+      function CanvasGraphicsPutBinaryImageDataShim(ctx, imgData, w, h) {
+        var tmpImgData = ctx.getImageData(0, 0, w, h);
+
+        // Copy over the imageData pixel by pixel.
+        var tmpImgDataPixels = tmpImgData.data;
+        var len = tmpImgDataPixels.length;
+
+        while (len--) {
+          tmpImgDataPixels[len] = imgData.data[len];
+        }
+
+        ctx.putImageData(tmpImgData, 0, 0);
+      };
+  }
+}
 /* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
 
 'use strict';
 
-var Name = (function nameName() {
-  function constructor(name) {
+var Name = (function NameClosure() {
+  function Name(name) {
     this.name = name;
   }
 
-  constructor.prototype = {
-  };
+  Name.prototype = {};
 
-  return constructor;
+  return Name;
 })();
 
-var Cmd = (function cmdCmd() {
-  function constructor(cmd) {
+var Cmd = (function CmdClosure() {
+  function Cmd(cmd) {
     this.cmd = cmd;
   }
 
-  constructor.prototype = {
+  Cmd.prototype = {};
+
+  var cmdCache = {};
+
+  Cmd.get = function Cmd_get(cmd) {
+    var cmdValue = cmdCache[cmd];
+    if (cmdValue)
+      return cmdValue;
+
+    return cmdCache[cmd] = new Cmd(cmd);
   };
 
-  return constructor;
+  return Cmd;
 })();
 
-var Dict = (function dictDict() {
-  function constructor() {
+var Dict = (function DictClosure() {
+  // xref is optional
+  function Dict(xref) {
+    // Map should only be used internally, use functions below to access.
     this.map = Object.create(null);
+    this.xref = xref;
   }
 
-  constructor.prototype = {
-    get: function dictGet(key1, key2, key3) {
+  Dict.prototype = {
+    // automatically dereferences Ref objects
+    get: function Dict_get(key1, key2, key3) {
       var value;
+      var xref = this.xref;
       if (typeof (value = this.map[key1]) != 'undefined' || key1 in this.map ||
           typeof key2 == 'undefined') {
-        return value;
+        return xref ? this.xref.fetchIfRef(value) : value;
       }
       if (typeof (value = this.map[key2]) != 'undefined' || key2 in this.map ||
           typeof key3 == 'undefined') {
-        return value;
+        return xref ? this.xref.fetchIfRef(value) : value;
       }
-
-      return this.map[key3] || null;
+      value = this.map[key3] || null;
+      return xref ? this.xref.fetchIfRef(value) : value;
+    },
+    // no dereferencing
+    getRaw: function Dict_getRaw(key) {
+      return this.map[key];
+    },
+    // creates new map and dereferences all Refs
+    getAll: function Dict_getAll() {
+      var all = {};
+      for (var key in this.map)
+        all[key] = this.get(key);
+      return all;
     },
 
-    set: function dictSet(key, value) {
+    set: function Dict_set(key, value) {
       this.map[key] = value;
     },
 
-    has: function dictHas(key) {
+    has: function Dict_has(key) {
       return key in this.map;
     },
 
-    forEach: function dictForEach(callback) {
+    forEach: function Dict_forEach(callback) {
       for (var key in this.map) {
-        callback(key, this.map[key]);
+        callback(key, this.get(key));
       }
     }
   };
 
-  return constructor;
+  return Dict;
 })();
 
-var Ref = (function refRef() {
-  function constructor(num, gen) {
+var Ref = (function RefClosure() {
+  function Ref(num, gen) {
     this.num = num;
     this.gen = gen;
   }
 
-  constructor.prototype = {
-  };
+  Ref.prototype = {};
 
-  return constructor;
+  return Ref;
 })();
 
 // The reference is identified by number and generation,
 // this structure stores only one instance of the reference.
-var RefSet = (function refSet() {
-  function constructor() {
+var RefSet = (function RefSetClosure() {
+  function RefSet() {
     this.dict = {};
   }
 
-  constructor.prototype = {
-    has: function refSetHas(ref) {
+  RefSet.prototype = {
+    has: function RefSet_has(ref) {
       return !!this.dict['R' + ref.num + '.' + ref.gen];
     },
 
-    put: function refSetPut(ref) {
+    put: function RefSet_put(ref) {
       this.dict['R' + ref.num + '.' + ref.gen] = ref;
     }
   };
 
-  return constructor;
+  return RefSet;
 })();
 
-var Catalog = (function catalogCatalog() {
-  function constructor(xref) {
+var Catalog = (function CatalogClosure() {
+  function Catalog(xref) {
     this.xref = xref;
     var obj = xref.getCatalogObj();
     assertWellFormed(isDict(obj), 'catalog object is not a dictionary');
     this.catDict = obj;
   }
 
-  constructor.prototype = {
+  Catalog.prototype = {
+    get metadata() {
+      var stream = this.catDict.get('Metadata');
+      var metadata;
+      if (stream && isDict(stream.dict)) {
+        var type = stream.dict.get('Type');
+        var subtype = stream.dict.get('Subtype');
+
+        if (isName(type) && isName(subtype) &&
+            type.name === 'Metadata' && subtype.name === 'XML') {
+          metadata = stringToPDFString(bytesToString(stream.getBytes()));
+        }
+      }
+
+      return shadow(this, 'metadata', metadata);
+    },
     get toplevelPagesDict() {
       var pagesObj = this.catDict.get('Pages');
-      assertWellFormed(isRef(pagesObj), 'invalid top-level pages reference');
-      var xrefObj = this.xref.fetch(pagesObj);
-      assertWellFormed(isDict(xrefObj), 'invalid top-level pages dictionary');
+      assertWellFormed(isDict(pagesObj), 'invalid top-level pages dictionary');
       // shadow the prototype getter
-      return shadow(this, 'toplevelPagesDict', xrefObj);
+      return shadow(this, 'toplevelPagesDict', pagesObj);
     },
     get documentOutline() {
-      var obj = this.catDict.get('Outlines');
       var xref = this.xref;
+      var obj = this.catDict.get('Outlines');
       var root = { items: [] };
-      if (isRef(obj)) {
-        obj = xref.fetch(obj).get('First');
+      if (isDict(obj)) {
+        obj = obj.getRaw('First');
         var processed = new RefSet();
         if (isRef(obj)) {
           var queue = [{obj: obj, parent: root}];
@@ -1946,18 +2788,20 @@ var Catalog = (function catalogCatalog() {
           processed.put(obj);
           while (queue.length > 0) {
             var i = queue.shift();
-            var outlineDict = xref.fetch(i.obj);
+            var outlineDict = xref.fetchIfRef(i.obj);
+            if (outlineDict === null)
+              continue;
             if (!outlineDict.has('Title'))
               error('Invalid outline item');
             var dest = outlineDict.get('A');
             if (dest)
-              dest = xref.fetchIfRef(dest).get('D');
+              dest = dest.get('D');
             else if (outlineDict.has('Dest')) {
-              dest = outlineDict.get('Dest');
+              dest = outlineDict.getRaw('Dest');
               if (isName(dest))
                 dest = dest.name;
             }
-            var title = xref.fetchIfRef(outlineDict.get('Title'));
+            var title = outlineDict.get('Title');
             var outlineItem = {
               dest: dest,
               title: stringToPDFString(title),
@@ -1968,12 +2812,12 @@ var Catalog = (function catalogCatalog() {
               items: []
             };
             i.parent.items.push(outlineItem);
-            obj = outlineDict.get('First');
+            obj = outlineDict.getRaw('First');
             if (isRef(obj) && !processed.has(obj)) {
               queue.push({obj: obj, parent: outlineItem});
               processed.put(obj);
             }
-            obj = outlineDict.get('Next');
+            obj = outlineDict.getRaw('Next');
             if (isRef(obj) && !processed.has(obj)) {
               queue.push({obj: obj, parent: i.parent});
               processed.put(obj);
@@ -1993,7 +2837,7 @@ var Catalog = (function catalogCatalog() {
       // shadow the prototype getter
       return shadow(this, 'num', obj);
     },
-    traverseKids: function catalogTraverseKids(pagesDict) {
+    traverseKids: function Catalog_traverseKids(pagesDict) {
       var pageCache = this.pageCache;
       var kids = pagesDict.get('Kids');
       assertWellFormed(isArray(kids),
@@ -2001,7 +2845,7 @@ var Catalog = (function catalogCatalog() {
       for (var i = 0, ii = kids.length; i < ii; ++i) {
         var kid = kids[i];
         assertWellFormed(isRef(kid),
-                         'page dictionary kid is not a reference');
+                        'page dictionary kid is not a reference');
         var obj = this.xref.fetch(kid);
         if (isDict(obj, 'Page') || (isDict(obj) && !obj.has('Kids'))) {
           pageCache.push(new Page(this.xref, pageCache.length, obj, kid));
@@ -2015,8 +2859,7 @@ var Catalog = (function catalogCatalog() {
       }
     },
     get destinations() {
-      function fetchDestination(xref, ref) {
-        var dest = xref.fetchIfRef(ref);
+      function fetchDestination(dest) {
         return isDict(dest) ? dest.get('D') : dest;
       }
 
@@ -2024,16 +2867,16 @@ var Catalog = (function catalogCatalog() {
       var dests = {}, nameTreeRef, nameDictionaryRef;
       var obj = this.catDict.get('Names');
       if (obj)
-        nameTreeRef = xref.fetchIfRef(obj).get('Dests');
+        nameTreeRef = obj.getRaw('Dests');
       else if (this.catDict.has('Dests'))
         nameDictionaryRef = this.catDict.get('Dests');
 
       if (nameDictionaryRef) {
         // reading simple destination dictionary
-        obj = xref.fetchIfRef(nameDictionaryRef);
+        obj = nameDictionaryRef;
         obj.forEach(function catalogForEach(key, value) {
           if (!value) return;
-          dests[key] = fetchDestination(xref, value);
+          dests[key] = fetchDestination(value);
         });
       }
       if (nameTreeRef) {
@@ -2057,13 +2900,13 @@ var Catalog = (function catalogCatalog() {
           }
           var names = obj.get('Names');
           for (i = 0, n = names.length; i < n; i += 2) {
-            dests[names[i]] = fetchDestination(xref, names[i + 1]);
+            dests[names[i]] = fetchDestination(xref.fetchIfRef(names[i + 1]));
           }
         }
       }
       return shadow(this, 'destinations', dests);
     },
-    getPage: function catalogGetPage(n) {
+    getPage: function Catalog_getPage(n) {
       var pageCache = this.pageCache;
       if (!pageCache) {
         pageCache = this.pageCache = [];
@@ -2073,105 +2916,101 @@ var Catalog = (function catalogCatalog() {
     }
   };
 
-  return constructor;
+  return Catalog;
 })();
 
-var XRef = (function xRefXRef() {
-  function constructor(stream, startXRef, mainXRefEntriesOffset) {
+var XRef = (function XRefClosure() {
+  function XRef(stream, startXRef, mainXRefEntriesOffset) {
     this.stream = stream;
     this.entries = [];
     this.xrefstms = {};
     var trailerDict = this.readXRef(startXRef);
-
+    trailerDict.xref = this;
+    this.trailer = trailerDict;
     // prepare the XRef cache
     this.cache = [];
 
     var encrypt = trailerDict.get('Encrypt');
     if (encrypt) {
       var fileId = trailerDict.get('ID');
-      this.encrypt = new CipherTransformFactory(this.fetch(encrypt),
+      this.encrypt = new CipherTransformFactory(encrypt,
                                                 fileId[0] /*, password */);
     }
 
     // get the root dictionary (catalog) object
-    if (!isRef(this.root = trailerDict.get('Root')))
+    if (!(this.root = trailerDict.get('Root')))
       error('Invalid root reference');
   }
 
-  constructor.prototype = {
-    readXRefTable: function readXRefTable(parser) {
+  XRef.prototype = {
+    readXRefTable: function XRef_readXRefTable(parser) {
+      // Example of cross-reference table:
+      // xref
+      // 0 1                    <-- subsection header (first obj #, obj count)
+      // 0000000000 65535 f     <-- actual object (offset, generation #, f/n)
+      // 23 2                   <-- subsection header ... and so on ...
+      // 0000025518 00002 n
+      // 0000025635 00000 n
+      // trailer
+      // ...
+
+      // Outer loop is over subsection headers
       var obj;
-      while (true) {
-        if (isCmd(obj = parser.getObj(), 'trailer'))
-          break;
-        if (!isInt(obj))
-          error('Invalid XRef table');
-        var first = obj;
-        if (!isInt(obj = parser.getObj()))
-          error('Invalid XRef table');
-        var n = obj;
-        if (first < 0 || n < 0 || (first + n) != ((first + n) | 0))
-          error('Invalid XRef table: ' + first + ', ' + n);
-        for (var i = first; i < first + n; ++i) {
+      while (!isCmd(obj = parser.getObj(), 'trailer')) {
+        var first = obj,
+            count = parser.getObj();
+
+        if (!isInt(first) || !isInt(count))
+          error('Invalid XRef table: wrong types in subsection header');
+
+        // Inner loop is over objects themselves
+        for (var i = 0; i < count; i++) {
           var entry = {};
-          if (!isInt(obj = parser.getObj()))
-            error('Invalid XRef table: ' + first + ', ' + n);
-          entry.offset = obj;
-          if (!isInt(obj = parser.getObj()))
-            error('Invalid XRef table: ' + first + ', ' + n);
-          entry.gen = obj;
-          obj = parser.getObj();
-          if (isCmd(obj, 'n')) {
-            entry.uncompressed = true;
-          } else if (isCmd(obj, 'f')) {
+          entry.offset = parser.getObj();
+          entry.gen = parser.getObj();
+          var type = parser.getObj();
+
+          if (isCmd(type, 'f'))
             entry.free = true;
-          } else {
-            error('Invalid XRef table: ' + first + ', ' + n);
-          }
-          if (!this.entries[i]) {
-            // In some buggy PDF files the xref table claims to start at 1
-            // instead of 0.
-            if (i == 1 && first == 1 &&
-                entry.offset == 0 && entry.gen == 65535 && entry.free) {
-              i = first = 0;
-            }
-            this.entries[i] = entry;
-          }
-        }
-      }
+          else if (isCmd(type, 'n'))
+            entry.uncompressed = true;
 
-      // read the trailer dictionary
-      var dict;
-      if (!isDict(dict = parser.getObj()))
-        error('Invalid XRef table');
-
-      // get the 'Prev' pointer
-      var prev;
-      obj = dict.get('Prev');
-      if (isInt(obj)) {
-        prev = obj;
-      } else if (isRef(obj)) {
-        // certain buggy PDF generators generate "/Prev NNN 0 R" instead
-        // of "/Prev NNN"
-        prev = obj.num;
-      }
-      if (prev) {
-        this.readXRef(prev);
-      }
+          // Validate entry obj
+          if (!isInt(entry.offset) || !isInt(entry.gen) ||
+              !(entry.free || entry.uncompressed)) {
+            error('Invalid entry in XRef subsection: ' + first + ', ' + count);
+          }
 
-      // check for 'XRefStm' key
-      if (isInt(obj = dict.get('XRefStm'))) {
-        var pos = obj;
-        // ignore previously loaded xref streams (possible infinite recursion)
-        if (!(pos in this.xrefstms)) {
-          this.xrefstms[pos] = 1;
-          this.readXRef(pos);
+          if (!this.entries[i + first])
+            this.entries[i + first] = entry;
         }
       }
 
+      // Sanity check: as per spec, first object must have these properties
+      if (this.entries[0] &&
+          !(this.entries[0].gen === 65535 && this.entries[0].free))
+        error('Invalid XRef table: unexpected first object');
+
+      // Sanity check
+      if (!isCmd(obj, 'trailer'))
+        error('Invalid XRef table: could not find trailer dictionary');
+
+      // Read trailer dictionary, e.g.
+      // trailer
+      //    << /Size 22
+      //      /Root 20R
+      //      /Info 10R
+      //      /ID [ <81b14aafa313db63dbd6f981e49f94f4> ]
+      //    >>
+      // The parser goes through the entire stream << ... >> and provides
+      // a getter interface for the key-value table
+      var dict = parser.getObj();
+      if (!isDict(dict))
+        error('Invalid XRef table: could not parse trailer dictionary');
+
       return dict;
     },
-    readXRefStream: function readXRefStream(stream) {
+    readXRefStream: function XRef_readXRefStream(stream) {
       var streamParameters = stream.parameters;
       var byteWidths = streamParameters.get('W');
       var range = streamParameters.get('Index');
@@ -2220,12 +3059,9 @@ var XRef = (function xRefXRef() {
         }
         range.splice(0, 2);
       }
-      var prev = streamParameters.get('Prev');
-      if (isInt(prev))
-        this.readXRef(prev);
       return streamParameters;
     },
-    indexObjects: function indexObjects() {
+    indexObjects: function XRef_indexObjects() {
       // Simple scan through the PDF content to find objects,
       // trailers and XRef streams.
       function readToken(data, offset) {
@@ -2317,7 +3153,7 @@ var XRef = (function xRefXRef() {
       var dict;
       for (var i = 0, ii = trailers.length; i < ii; ++i) {
         stream.pos = trailers[i];
-        var parser = new Parser(new Lexer(stream), true);
+        var parser = new Parser(new Lexer(stream), true, null);
         var obj = parser.getObj();
         if (!isCmd(obj, 'trailer'))
           continue;
@@ -2333,50 +3169,88 @@ var XRef = (function xRefXRef() {
         return dict;
       // nothing helps
       error('Invalid PDF structure');
-      return null;
     },
-    readXRef: function readXref(startXRef) {
+    readXRef: function XRef_readXRef(startXRef) {
       var stream = this.stream;
       stream.pos = startXRef;
-      var parser = new Parser(new Lexer(stream), true);
-      var obj = parser.getObj();
-      // parse an old-style xref table
-      if (isCmd(obj, 'xref'))
-        return this.readXRefTable(parser);
-      // parse an xref stream
-      if (isInt(obj)) {
-        if (!isInt(parser.getObj()) ||
-            !isCmd(parser.getObj(), 'obj') ||
-            !isStream(obj = parser.getObj())) {
-          error('Invalid XRef stream');
+
+      try {
+        var parser = new Parser(new Lexer(stream), true, null);
+        var obj = parser.getObj();
+        var dict;
+
+        // Get dictionary
+        if (isCmd(obj, 'xref')) {
+          // Parse end-of-file XRef
+          dict = this.readXRefTable(parser);
+
+          // Recursively get other XRefs 'XRefStm', if any
+          obj = dict.get('XRefStm');
+          if (isInt(obj)) {
+            var pos = obj;
+            // ignore previously loaded xref streams
+            // (possible infinite recursion)
+            if (!(pos in this.xrefstms)) {
+              this.xrefstms[pos] = 1;
+              this.readXRef(pos);
+            }
+          }
+        } else if (isInt(obj)) {
+          // Parse in-stream XRef
+          if (!isInt(parser.getObj()) ||
+              !isCmd(parser.getObj(), 'obj') ||
+              !isStream(obj = parser.getObj())) {
+            error('Invalid XRef stream');
+          }
+          dict = this.readXRefStream(obj);
+        }
+
+        // Recursively get previous dictionary, if any
+        obj = dict.get('Prev');
+        if (isInt(obj))
+          this.readXRef(obj);
+        else if (isRef(obj)) {
+          // The spec says Prev must not be a reference, i.e. "/Prev NNN"
+          // This is a fallback for non-compliant PDFs, i.e. "/Prev NNN 0 R"
+          this.readXRef(obj.num);
         }
-        return this.readXRefStream(obj);
+
+        return dict;
+      } catch (e) {
+        log('(while reading XRef): ' + e);
       }
+
+      warn('Indexing all PDF objects');
       return this.indexObjects();
     },
-    getEntry: function xRefGetEntry(i) {
+    getEntry: function XRef_getEntry(i) {
       var e = this.entries[i];
-      if (e.free)
-        error('reading an XRef stream not implemented yet');
-      return e;
+      if (e === null)
+        return null;
+      return e.free ? null : e; // returns null is the entry is free
     },
-    fetchIfRef: function xRefFetchIfRef(obj) {
+    fetchIfRef: function XRef_fetchIfRef(obj) {
       if (!isRef(obj))
         return obj;
       return this.fetch(obj);
     },
-    fetch: function xRefFetch(ref, suppressEncryption) {
+    fetch: function XRef_fetch(ref, suppressEncryption) {
+      assertWellFormed(isRef(ref), 'ref object is not a reference');
       var num = ref.num;
-      var e = this.cache[num];
-      if (e)
-        return e;
+      if (num in this.cache)
+        return this.cache[num];
+
+      var e = this.getEntry(num);
+
+      // the referenced entry can be free
+      if (e === null)
+        return (this.cache[num] = e);
 
-      e = this.getEntry(num);
       var gen = ref.gen;
       var stream, parser;
       if (e.uncompressed) {
         if (e.gen != gen)
-          throw ('inconsistent generation in XRef');
+          error('inconsistent generation in XRef');
         stream = this.stream.makeSubStream(e.offset);
         parser = new Parser(new Lexer(stream), true, this);
         var obj1 = parser.getObj();
@@ -2409,7 +3283,7 @@ var XRef = (function xRefXRef() {
           e = parser.getObj();
         }
         // Don't cache streams since they are mutable (except images).
-        if (!isStream(e) || e.getImage)
+        if (!isStream(e) || e instanceof JpegStream)
           this.cache[num] = e;
         return e;
       }
@@ -2423,7 +3297,7 @@ var XRef = (function xRefXRef() {
       if (!isInt(first) || !isInt(n)) {
         error('invalid first and n parameters for ObjStm stream');
       }
-      parser = new Parser(new Lexer(stream), false);
+      parser = new Parser(new Lexer(stream), false, this);
       var i, entries = [], nums = [];
       // read the object numbers to populate cache
       for (i = 0; i < n; ++i) {
@@ -2448,12 +3322,12 @@ var XRef = (function xRefXRef() {
       }
       return e;
     },
-    getCatalogObj: function xRefGetCatalogObj() {
-      return this.fetch(this.root);
+    getCatalogObj: function XRef_getCatalogObj() {
+      return this.root;
     }
   };
 
-  return constructor;
+  return XRef;
 })();
 
 /**
@@ -2462,7 +3336,7 @@ var XRef = (function xRefXRef() {
  * inside of a worker. The `PDFObjects` implements some basic functions to
  * manage these objects.
  */
-var PDFObjects = (function pdfObjects() {
+var PDFObjects = (function PDFObjectsClosure() {
   function PDFObjects() {
     this.objs = {};
   }
@@ -2475,7 +3349,7 @@ var PDFObjects = (function pdfObjects() {
      * Ensures there is an object defined for `objId`. Stores `data` on the
      * object *if* it is created.
      */
-    ensureObj: function pdfObjectsEnsureObj(objId, data) {
+    ensureObj: function PDFObjects_ensureObj(objId, data) {
       if (this.objs[objId])
         return this.objs[objId];
       return this.objs[objId] = new Promise(objId, data);
@@ -2490,7 +3364,7 @@ var PDFObjects = (function pdfObjects() {
      * function and the object is already resolved, the callback gets called
      * right away.
      */
-    get: function pdfObjectsGet(objId, callback) {
+    get: function PDFObjects_get(objId, callback) {
       // If there is a callback, then the get can be async and the object is
       // not required to be resolved right now
       if (callback) {
@@ -2504,18 +3378,16 @@ var PDFObjects = (function pdfObjects() {
 
       // If there isn't an object yet or the object isn't resolved, then the
       // data isn't ready yet!
-      if (!obj || !obj.isResolved) {
-        throw 'Requesting object that isn\'t resolved yet ' + objId;
-        return null;
-      } else {
-        return obj.data;
-      }
+      if (!obj || !obj.isResolved)
+        error('Requesting object that isn\'t resolved yet ' + objId);
+
+      return obj.data;
     },
 
     /**
      * Resolves the object `objId` with optional `data`.
      */
-    resolve: function pdfObjectsResolve(objId, data) {
+    resolve: function PDFObjects_resolve(objId, data) {
       var objs = this.objs;
 
       // In case there is a promise already on this object, just resolve it.
@@ -2526,11 +3398,11 @@ var PDFObjects = (function pdfObjects() {
       }
     },
 
-    onData: function pdfObjectsOnData(objId, callback) {
+    onData: function PDFObjects_onData(objId, callback) {
       this.ensureObj(objId).onData(callback);
     },
 
-    isResolved: function pdfObjectsIsResolved(objId) {
+    isResolved: function PDFObjects_isResolved(objId) {
       var objs = this.objs;
       if (!objs[objId]) {
         return false;
@@ -2539,7 +3411,7 @@ var PDFObjects = (function pdfObjects() {
       }
     },
 
-    hasData: function pdfObjectsHasData(objId) {
+    hasData: function PDFObjects_hasData(objId) {
       var objs = this.objs;
       if (!objs[objId]) {
         return false;
@@ -2551,7 +3423,7 @@ var PDFObjects = (function pdfObjects() {
     /**
      * Sets the data of an object but *doesn't* resolve it.
      */
-    setData: function pdfObjectsSetData(objId, data) {
+    setData: function PDFObjects_setData(objId, data) {
       // Watchout! If you call `this.ensureObj(objId, data)` you're going to
       // create a *resolved* promise which shouldn't be the case!
       this.ensureObj(objId).data = data;
@@ -2565,14 +3437,14 @@ var PDFObjects = (function pdfObjects() {
 
 'use strict';
 
-var PDFFunction = (function pdfFunction() {
+var PDFFunction = (function PDFFunctionClosure() {
   var CONSTRUCT_SAMPLED = 0;
   var CONSTRUCT_INTERPOLATED = 2;
   var CONSTRUCT_STICHED = 3;
   var CONSTRUCT_POSTSCRIPT = 4;
 
   return {
-    getSampleArray: function pdfFunctionGetSampleArray(size, outputSize, bps,
+    getSampleArray: function PDFFunction_getSampleArray(size, outputSize, bps,
                                                        str) {
       var length = 1;
       for (var i = 0, ii = size.length; i < ii; i++)
@@ -2600,7 +3472,7 @@ var PDFFunction = (function pdfFunction() {
       return array;
     },
 
-    getIR: function pdfFunctionGetIR(xref, fn) {
+    getIR: function PDFFunction_getIR(xref, fn) {
       var dict = fn.dict;
       if (!dict)
         dict = fn;
@@ -2619,7 +3491,7 @@ var PDFFunction = (function pdfFunction() {
       return typeFn.call(this, fn, dict, xref);
     },
 
-    fromIR: function pdfFunctionFromIR(IR) {
+    fromIR: function PDFFunction_fromIR(IR) {
       var type = IR[0];
       switch (type) {
         case CONSTRUCT_SAMPLED:
@@ -2634,16 +3506,16 @@ var PDFFunction = (function pdfFunction() {
       }
     },
 
-    parse: function pdfFunctionParse(xref, fn) {
+    parse: function PDFFunction_parse(xref, fn) {
       var IR = this.getIR(xref, fn);
       return this.fromIR(IR);
     },
 
-    constructSampled: function pdfFunctionConstructSampled(str, dict) {
+    constructSampled: function PDFFunction_constructSampled(str, dict) {
       function toMultiArray(arr) {
         var inputLength = arr.length;
         var outputLength = arr.length / 2;
-        var out = new Array(outputLength);
+        var out = [];
         var index = 0;
         for (var i = 0; i < inputLength; i += 2) {
           out[index] = [arr[i], arr[i + 1]];
@@ -2687,114 +3559,104 @@ var PDFFunction = (function pdfFunction() {
       else
         decode = toMultiArray(decode);
 
-      // Precalc the multipliers
-      var inputMul = new Float64Array(inputSize);
-      for (var i = 0; i < inputSize; ++i) {
-        inputMul[i] = (encode[i][1] - encode[i][0]) /
-                  (domain[i][1] - domain[i][0]);
-      }
-
-      var idxMul = new Int32Array(inputSize);
-      idxMul[0] = outputSize;
-      for (i = 1; i < inputSize; ++i) {
-        idxMul[i] = idxMul[i - 1] * size[i - 1];
-      }
-
-      var nSamples = outputSize;
-      for (i = 0; i < inputSize; ++i)
-          nSamples *= size[i];
-
       var samples = this.getSampleArray(size, outputSize, bps, str);
 
       return [
         CONSTRUCT_SAMPLED, inputSize, domain, encode, decode, samples, size,
-        outputSize, bps, range, inputMul, idxMul, nSamples
+        outputSize, Math.pow(2, bps) - 1, range
       ];
     },
 
-    constructSampledFromIR: function pdfFunctionConstructSampledFromIR(IR) {
-      var inputSize = IR[1];
-      var domain = IR[2];
-      var encode = IR[3];
-      var decode = IR[4];
-      var samples = IR[5];
-      var size = IR[6];
-      var outputSize = IR[7];
-      var bps = IR[8];
-      var range = IR[9];
-      var inputMul = IR[10];
-      var idxMul = IR[11];
-      var nSamples = IR[12];
+    constructSampledFromIR: function PDFFunction_constructSampledFromIR(IR) {
+      // See chapter 3, page 109 of the PDF reference
+      function interpolate(x, xmin, xmax, ymin, ymax) {
+        return ymin + ((x - xmin) * ((ymax - ymin) / (xmax - xmin)));
+      }
 
       return function constructSampledFromIRResult(args) {
-        if (inputSize != args.length)
+        // See chapter 3, page 110 of the PDF reference.
+        var m = IR[1];
+        var domain = IR[2];
+        var encode = IR[3];
+        var decode = IR[4];
+        var samples = IR[5];
+        var size = IR[6];
+        var n = IR[7];
+        var mask = IR[8];
+        var range = IR[9];
+
+        if (m != args.length)
           error('Incorrect number of arguments: ' + inputSize + ' != ' +
                 args.length);
-        // Most of the below is a port of Poppler's implementation.
-        // TODO: There's a few other ways to do multilinear interpolation such
-        // as piecewise, which is much faster but an approximation.
-        var out = new Float64Array(outputSize);
-        var x;
-        var e = new Array(inputSize);
-        var efrac0 = new Float64Array(inputSize);
-        var efrac1 = new Float64Array(inputSize);
-        var sBuf = new Float64Array(1 << inputSize);
-        var i, j, k, idx, t;
-
-        // map input values into sample array
-        for (i = 0; i < inputSize; ++i) {
-          x = (args[i] - domain[i][0]) * inputMul[i] + encode[i][0];
-          if (x < 0) {
-            x = 0;
-          } else if (x > size[i] - 1) {
-            x = size[i] - 1;
-          }
-          e[i] = [Math.floor(x), 0];
-          if ((e[i][1] = e[i][0] + 1) >= size[i]) {
-            // this happens if in[i] = domain[i][1]
-            e[i][1] = e[i][0];
-          }
-          efrac1[i] = x - e[i][0];
-          efrac0[i] = 1 - efrac1[i];
-        }
-
-        // for each output, do m-linear interpolation
-        for (i = 0; i < outputSize; ++i) {
 
-          // pull 2^m values out of the sample array
-          for (j = 0; j < (1 << inputSize); ++j) {
-            idx = i;
-            for (k = 0, t = j; k < inputSize; ++k, t >>= 1) {
-              idx += idxMul[k] * (e[k][t & 1]);
-            }
-            if (idx >= 0 && idx < nSamples) {
-              sBuf[j] = samples[idx];
+        var x = args;
+
+        // Building the cube vertices: its part and sample index
+        // http://rjwagner49.com/Mathematics/Interpolation.pdf
+        var cubeVertices = 1 << m;
+        var cubeN = new Float64Array(cubeVertices);
+        var cubeVertex = new Uint32Array(cubeVertices);
+        for (var j = 0; j < cubeVertices; j++)
+          cubeN[j] = 1;
+
+        var k = n, pos = 1;
+        // Map x_i to y_j for 0 <= i < m using the sampled function.
+        for (var i = 0; i < m; ++i) {
+          // x_i' = min(max(x_i, Domain_2i), Domain_2i+1)
+          var domain_2i = domain[i][0];
+          var domain_2i_1 = domain[i][1];
+          var xi = Math.min(Math.max(x[i], domain_2i), domain_2i_1);
+
+          // e_i = Interpolate(x_i', Domain_2i, Domain_2i+1,
+          //                   Encode_2i, Encode_2i+1)
+          var e = interpolate(xi, domain_2i, domain_2i_1,
+                              encode[i][0], encode[i][1]);
+
+          // e_i' = min(max(e_i, 0), Size_i - 1)
+          var size_i = size[i];
+          e = Math.min(Math.max(e, 0), size_i - 1);
+
+          // Adjusting the cube: N and vertex sample index
+          var e0 = e < size_i - 1 ? Math.floor(e) : e - 1; // e1 = e0 + 1;
+          var n0 = e0 + 1 - e; // (e1 - e) / (e1 - e0);
+          var n1 = e - e0; // (e - e0) / (e1 - e0);
+          var offset0 = e0 * k;
+          var offset1 = offset0 + k; // e1 * k
+          for (var j = 0; j < cubeVertices; j++) {
+            if (j & pos) {
+              cubeN[j] *= n1;
+              cubeVertex[j] += offset1;
             } else {
-              sBuf[j] = 0; // TODO Investigate if this is what Adobe does
+              cubeN[j] *= n0;
+              cubeVertex[j] += offset0;
             }
           }
 
-          // do m sets of interpolations
-          for (j = 0, t = (1 << inputSize); j < inputSize; ++j, t >>= 1) {
-            for (k = 0; k < t; k += 2) {
-              sBuf[k >> 1] = efrac0[j] * sBuf[k] + efrac1[j] * sBuf[k + 1];
-            }
-          }
+          k *= size_i;
+          pos <<= 1;
+        }
 
-          // map output value to range
-          out[i] = (sBuf[0] * (decode[i][1] - decode[i][0]) + decode[i][0]);
-          if (out[i] < range[i][0]) {
-            out[i] = range[i][0];
-          } else if (out[i] > range[i][1]) {
-            out[i] = range[i][1];
-          }
+        var y = new Float64Array(n);
+        for (var j = 0; j < n; ++j) {
+          // Sum all cube vertices' samples portions
+          var rj = 0;
+          for (var i = 0; i < cubeVertices; i++)
+            rj += samples[cubeVertex[i] + j] * cubeN[i];
+
+          // r_j' = Interpolate(r_j, 0, 2^BitsPerSample - 1,
+          //                    Decode_2j, Decode_2j+1)
+          rj = interpolate(rj, 0, 1, decode[j][0], decode[j][1]);
+
+          // y_j = min(max(r_j, range_2j), range_2j+1)
+          y[j] = Math.min(Math.max(rj, range[j][0]), range[j][1]);
         }
-        return out;
+
+        return y;
       }
     },
 
-    constructInterpolated:
-    function pdfFunctionConstructInterpolated(str, dict) {
+    constructInterpolated: function PDFFunction_constructInterpolated(str,
+                                                                      dict) {
       var c0 = dict.get('C0') || [0];
       var c1 = dict.get('C1') || [1];
       var n = dict.get('N');
@@ -2811,7 +3673,7 @@ var PDFFunction = (function pdfFunction() {
     },
 
     constructInterpolatedFromIR:
-    function pdfFunctionconstructInterpolatedFromIR(IR) {
+      function PDFFunction_constructInterpolatedFromIR(IR) {
       var c0 = IR[1];
       var diff = IR[2];
       var n = IR[3];
@@ -2830,9 +3692,8 @@ var PDFFunction = (function pdfFunction() {
       }
     },
 
-    constructStiched: function pdfFunctionConstructStiched(fn, dict, xref) {
+    constructStiched: function PDFFunction_constructStiched(fn, dict, xref) {
       var domain = dict.get('Domain');
-      var range = dict.get('Range');
 
       if (!domain)
         error('No domain');
@@ -2852,7 +3713,7 @@ var PDFFunction = (function pdfFunction() {
       return [CONSTRUCT_STICHED, domain, bounds, encode, fns];
     },
 
-    constructStichedFromIR: function pdfFunctionConstructStichedFromIR(IR) {
+    constructStichedFromIR: function PDFFunction_constructStichedFromIR(IR) {
       var domain = IR[1];
       var bounds = IR[2];
       var encode = IR[3];
@@ -2898,87 +3759,621 @@ var PDFFunction = (function pdfFunction() {
       };
     },
 
-    constructPostScript: function pdfFunctionConstructPostScript() {
-      return [CONSTRUCT_POSTSCRIPT];
+    constructPostScript: function PDFFunction_constructPostScript(fn, dict,
+                                                                  xref) {
+      var domain = dict.get('Domain');
+      var range = dict.get('Range');
+
+      if (!domain)
+        error('No domain.');
+
+      if (!range)
+        error('No range.');
+
+      var lexer = new PostScriptLexer(fn);
+      var parser = new PostScriptParser(lexer);
+      var code = parser.parse();
+
+      return [CONSTRUCT_POSTSCRIPT, domain, range, code];
     },
 
-    constructPostScriptFromIR: function pdfFunctionConstructPostScriptFromIR() {
-      TODO('unhandled type of function');
-      return function constructPostScriptFromIRResult() {
-        return [255, 105, 180];
+    constructPostScriptFromIR: function PDFFunction_constructPostScriptFromIR(
+                                          IR) {
+      var domain = IR[1];
+      var range = IR[2];
+      var code = IR[3];
+      var numOutputs = range.length / 2;
+      var evaluator = new PostScriptEvaluator(code);
+      // Cache the values for a big speed up, the cache size is limited though
+      // since the number of possible values can be huge from a PS function.
+      var cache = new FunctionCache();
+      return function constructPostScriptFromIRResult(args) {
+        var initialStack = [];
+        for (var i = 0, ii = (domain.length / 2); i < ii; ++i) {
+          initialStack.push(args[i]);
+        }
+
+        var key = initialStack.join('_');
+        if (cache.has(key))
+          return cache.get(key);
+
+        var stack = evaluator.execute(initialStack);
+        var transformed = [];
+        for (i = numOutputs - 1; i >= 0; --i) {
+          var out = stack.pop();
+          var rangeIndex = 2 * i;
+          if (out < range[rangeIndex])
+            out = range[rangeIndex];
+          else if (out > range[rangeIndex + 1])
+            out = range[rangeIndex + 1];
+          transformed[i] = out;
+        }
+        cache.set(key, transformed);
+        return transformed;
       };
     }
   };
 })();
 
-/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
+var FunctionCache = (function FunctionCacheClosure() {
+  // Of 10 PDF's with type4 functions the maxium number of distinct values seen
+  // was 256. This still may need some tweaking in the future though.
+  var MAX_CACHE_SIZE = 1024;
+  function FunctionCache() {
+    this.cache = {};
+    this.total = 0;
+  }
+  FunctionCache.prototype = {
+    has: function FunctionCache_has(key) {
+      return key in this.cache;
+    },
+    get: function FunctionCache_get(key) {
+      return this.cache[key];
+    },
+    set: function FunctionCache_set(key, value) {
+      if (this.total < MAX_CACHE_SIZE) {
+        this.cache[key] = value;
+        this.total++;
+      }
+    }
+  };
+  return FunctionCache;
+})();
 
-'use strict';
+var PostScriptStack = (function PostScriptStackClosure() {
+  var MAX_STACK_SIZE = 100;
+  function PostScriptStack(initialStack) {
+    this.stack = initialStack || [];
+  }
 
-var ISOAdobeCharset = [
-  '.notdef', 'space', 'exclam', 'quotedbl', 'numbersign', 'dollar',
-  'percent', 'ampersand', 'quoteright', 'parenleft', 'parenright',
-  'asterisk', 'plus', 'comma', 'hyphen', 'period', 'slash', 'zero',
-  'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight',
-  'nine', 'colon', 'semicolon', 'less', 'equal', 'greater', 'question',
-  'at', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
-  'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
-  'bracketleft', 'backslash', 'bracketright', 'asciicircum', 'underscore',
-  'quoteleft', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l',
-  'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
-  'braceleft', 'bar', 'braceright', 'asciitilde', 'exclamdown', 'cent',
-  'sterling', 'fraction', 'yen', 'florin', 'section', 'currency',
-  'quotesingle', 'quotedblleft', 'guillemotleft', 'guilsinglleft',
-  'guilsinglright', 'fi', 'fl', 'endash', 'dagger', 'daggerdbl',
-  'periodcentered', 'paragraph', 'bullet', 'quotesinglbase',
-  'quotedblbase', 'quotedblright', 'guillemotright', 'ellipsis',
-  'perthousand', 'questiondown', 'grave', 'acute', 'circumflex', 'tilde',
-  'macron', 'breve', 'dotaccent', 'dieresis', 'ring', 'cedilla',
-  'hungarumlaut', 'ogonek', 'caron', 'emdash', 'AE', 'ordfeminine',
-  'Lslash', 'Oslash', 'OE', 'ordmasculine', 'ae', 'dotlessi', 'lslash',
-  'oslash', 'oe', 'germandbls', 'onesuperior', 'logicalnot', 'mu',
-  'trademark', 'Eth', 'onehalf', 'plusminus', 'Thorn', 'onequarter',
-  'divide', 'brokenbar', 'degree', 'thorn', 'threequarters', 'twosuperior',
-  'registered', 'minus', 'eth', 'multiply', 'threesuperior', 'copyright',
-  'Aacute', 'Acircumflex', 'Adieresis', 'Agrave', 'Aring', 'Atilde',
-  'Ccedilla', 'Eacute', 'Ecircumflex', 'Edieresis', 'Egrave', 'Iacute',
-  'Icircumflex', 'Idieresis', 'Igrave', 'Ntilde', 'Oacute', 'Ocircumflex',
-  'Odieresis', 'Ograve', 'Otilde', 'Scaron', 'Uacute', 'Ucircumflex',
-  'Udieresis', 'Ugrave', 'Yacute', 'Ydieresis', 'Zcaron', 'aacute',
-  'acircumflex', 'adieresis', 'agrave', 'aring', 'atilde', 'ccedilla',
-  'eacute', 'ecircumflex', 'edieresis', 'egrave', 'iacute', 'icircumflex',
-  'idieresis', 'igrave', 'ntilde', 'oacute', 'ocircumflex', 'odieresis',
-  'ograve', 'otilde', 'scaron', 'uacute', 'ucircumflex', 'udieresis',
-  'ugrave', 'yacute', 'ydieresis', 'zcaron'
-];
+  PostScriptStack.prototype = {
+    push: function PostScriptStack_push(value) {
+      if (this.stack.length >= MAX_STACK_SIZE)
+        error('PostScript function stack overflow.');
+      this.stack.push(value);
+    },
+    pop: function PostScriptStack_pop() {
+      if (this.stack.length <= 0)
+        error('PostScript function stack underflow.');
+      return this.stack.pop();
+    },
+    copy: function PostScriptStack_copy(n) {
+      if (this.stack.length + n >= MAX_STACK_SIZE)
+        error('PostScript function stack overflow.');
+      var stack = this.stack;
+      for (var i = stack.length - n, j = n - 1; j >= 0; j--, i++)
+        stack.push(stack[i]);
+    },
+    index: function PostScriptStack_index(n) {
+      this.push(this.stack[this.stack.length - n - 1]);
+    },
+    // rotate the last n stack elements p times
+    roll: function PostScriptStack_roll(n, p) {
+      var stack = this.stack;
+      var l = stack.length - n;
+      var r = stack.length - 1, c = l + (p - Math.floor(p / n) * n), i, j, t;
+      for (i = l, j = r; i < j; i++, j--) {
+        t = stack[i]; stack[i] = stack[j]; stack[j] = t;
+      }
+      for (i = l, j = c - 1; i < j; i++, j--) {
+        t = stack[i]; stack[i] = stack[j]; stack[j] = t;
+      }
+      for (i = c, j = r; i < j; i++, j--) {
+        t = stack[i]; stack[i] = stack[j]; stack[j] = t;
+      }
+    }
+  };
+  return PostScriptStack;
+})();
+var PostScriptEvaluator = (function PostScriptEvaluatorClosure() {
+  function PostScriptEvaluator(operators, operands) {
+    this.operators = operators;
+    this.operands = operands;
+  }
+  PostScriptEvaluator.prototype = {
+    execute: function PostScriptEvaluator_execute(initialStack) {
+      var stack = new PostScriptStack(initialStack);
+      var counter = 0;
+      var operators = this.operators;
+      var length = operators.length;
+      var operator, a, b;
+      while (counter < length) {
+        operator = operators[counter++];
+        if (typeof operator == 'number') {
+          // Operator is really an operand and should be pushed to the stack.
+          stack.push(operator);
+          continue;
+        }
+        switch (operator) {
+          // non standard ps operators
+          case 'jz': // jump if false
+            b = stack.pop();
+            a = stack.pop();
+            if (!a)
+              counter = b;
+            break;
+          case 'j': // jump
+            a = stack.pop();
+            counter = a;
+            break;
 
-var ExpertCharset = [
-  '.notdef', 'space', 'exclamsmall', 'Hungarumlautsmall', 'dollaroldstyle',
-  'dollarsuperior', 'ampersandsmall', 'Acutesmall', 'parenleftsuperior',
-  'parenrightsuperior', 'twodotenleader', 'onedotenleader', 'comma',
-  'hyphen', 'period', 'fraction', 'zerooldstyle', 'oneoldstyle',
-  'twooldstyle', 'threeoldstyle', 'fouroldstyle', 'fiveoldstyle',
-  'sixoldstyle', 'sevenoldstyle', 'eightoldstyle', 'nineoldstyle',
-  'colon', 'semicolon', 'commasuperior', 'threequartersemdash',
-  'periodsuperior', 'questionsmall', 'asuperior', 'bsuperior',
-  'centsuperior', 'dsuperior', 'esuperior', 'isuperior', 'lsuperior',
-  'msuperior', 'nsuperior', 'osuperior', 'rsuperior', 'ssuperior',
-  'tsuperior', 'ff', 'fi', 'fl', 'ffi', 'ffl', 'parenleftinferior',
-  'parenrightinferior', 'Circumflexsmall', 'hyphensuperior', 'Gravesmall',
-  'Asmall', 'Bsmall', 'Csmall', 'Dsmall', 'Esmall', 'Fsmall', 'Gsmall',
-  'Hsmall', 'Ismall', 'Jsmall', 'Ksmall', 'Lsmall', 'Msmall', 'Nsmall',
-  'Osmall', 'Psmall', 'Qsmall', 'Rsmall', 'Ssmall', 'Tsmall', 'Usmall',
-  'Vsmall', 'Wsmall', 'Xsmall', 'Ysmall', 'Zsmall', 'colonmonetary',
-  'onefitted', 'rupiah', 'Tildesmall', 'exclamdownsmall', 'centoldstyle',
-  'Lslashsmall', 'Scaronsmall', 'Zcaronsmall', 'Dieresissmall',
-  'Brevesmall', 'Caronsmall', 'Dotaccentsmall', 'Macronsmall',
-  'figuredash', 'hypheninferior', 'Ogoneksmall', 'Ringsmall',
-  'Cedillasmall', 'onequarter', 'onehalf', 'threequarters',
-  'questiondownsmall', 'oneeighth', 'threeeighths', 'fiveeighths',
-  'seveneighths', 'onethird', 'twothirds', 'zerosuperior', 'onesuperior',
-  'twosuperior', 'threesuperior', 'foursuperior', 'fivesuperior',
-  'sixsuperior', 'sevensuperior', 'eightsuperior', 'ninesuperior',
+          // all ps operators in alphabetical order (excluding if/ifelse)
+          case 'abs':
+            a = stack.pop();
+            stack.push(Math.abs(a));
+            break;
+          case 'add':
+            b = stack.pop();
+            a = stack.pop();
+            stack.push(a + b);
+            break;
+          case 'and':
+            b = stack.pop();
+            a = stack.pop();
+            if (isBool(a) && isBool(b))
+              stack.push(a && b);
+            else
+              stack.push(a & b);
+            break;
+          case 'atan':
+            a = stack.pop();
+            stack.push(Math.atan(a));
+            break;
+          case 'bitshift':
+            b = stack.pop();
+            a = stack.pop();
+            if (a > 0)
+              stack.push(a << b);
+            else
+              stack.push(a >> b);
+            break;
+          case 'ceiling':
+            a = stack.pop();
+            stack.push(Math.ceil(a));
+            break;
+          case 'copy':
+            a = stack.pop();
+            stack.copy(a);
+            break;
+          case 'cos':
+            a = stack.pop();
+            stack.push(Math.cos(a));
+            break;
+          case 'cvi':
+            a = stack.pop() | 0;
+            stack.push(a);
+            break;
+          case 'cvr':
+            // noop
+            break;
+          case 'div':
+            b = stack.pop();
+            a = stack.pop();
+            stack.push(a / b);
+            break;
+          case 'dup':
+            stack.copy(1);
+            break;
+          case 'eq':
+            b = stack.pop();
+            a = stack.pop();
+            stack.push(a == b);
+            break;
+          case 'exch':
+            stack.roll(2, 1);
+            break;
+          case 'exp':
+            b = stack.pop();
+            a = stack.pop();
+            stack.push(Math.pow(a, b));
+            break;
+          case 'false':
+            stack.push(false);
+            break;
+          case 'floor':
+            a = stack.pop();
+            stack.push(Math.floor(a));
+            break;
+          case 'ge':
+            b = stack.pop();
+            a = stack.pop();
+            stack.push(a >= b);
+            break;
+          case 'gt':
+            b = stack.pop();
+            a = stack.pop();
+            stack.push(a > b);
+            break;
+          case 'idiv':
+            b = stack.pop();
+            a = stack.pop();
+            stack.push((a / b) | 0);
+            break;
+          case 'index':
+            a = stack.pop();
+            stack.index(a);
+            break;
+          case 'le':
+            b = stack.pop();
+            a = stack.pop();
+            stack.push(a <= b);
+            break;
+          case 'ln':
+            a = stack.pop();
+            stack.push(Math.log(a));
+            break;
+          case 'log':
+            a = stack.pop();
+            stack.push(Math.log(a) / Math.LN10);
+            break;
+          case 'lt':
+            b = stack.pop();
+            a = stack.pop();
+            stack.push(a < b);
+            break;
+          case 'mod':
+            b = stack.pop();
+            a = stack.pop();
+            stack.push(a % b);
+            break;
+          case 'mul':
+            b = stack.pop();
+            a = stack.pop();
+            stack.push(a * b);
+            break;
+          case 'ne':
+            b = stack.pop();
+            a = stack.pop();
+            stack.push(a != b);
+            break;
+          case 'neg':
+            a = stack.pop();
+            stack.push(-b);
+            break;
+          case 'not':
+            a = stack.pop();
+            if (isBool(a) && isBool(b))
+              stack.push(a && b);
+            else
+              stack.push(a & b);
+            break;
+          case 'or':
+            b = stack.pop();
+            a = stack.pop();
+            if (isBool(a) && isBool(b))
+              stack.push(a || b);
+            else
+              stack.push(a | b);
+            break;
+          case 'pop':
+            stack.pop();
+            break;
+          case 'roll':
+            b = stack.pop();
+            a = stack.pop();
+            stack.roll(a, b);
+            break;
+          case 'round':
+            a = stack.pop();
+            stack.push(Math.round(a));
+            break;
+          case 'sin':
+            a = stack.pop();
+            stack.push(Math.sin(a));
+            break;
+          case 'sqrt':
+            a = stack.pop();
+            stack.push(Math.sqrt(a));
+            break;
+          case 'sub':
+            b = stack.pop();
+            a = stack.pop();
+            stack.push(a - b);
+            break;
+          case 'true':
+            stack.push(true);
+            break;
+          case 'truncate':
+            a = stack.pop();
+            a = a < 0 ? Math.ceil(a) : Math.floor(a);
+            stack.push(a);
+            break;
+          case 'xor':
+            b = stack.pop();
+            a = stack.pop();
+            if (isBool(a) && isBool(b))
+              stack.push(a != b);
+            else
+              stack.push(a ^ b);
+            break;
+          default:
+            error('Unknown operator ' + operator);
+            break;
+        }
+      }
+      return stack.stack;
+    }
+  };
+  return PostScriptEvaluator;
+})();
+
+var PostScriptParser = (function PostScriptParserClosure() {
+  function PostScriptParser(lexer) {
+    this.lexer = lexer;
+    this.operators = [];
+    this.token;
+    this.prev;
+  }
+  PostScriptParser.prototype = {
+    nextToken: function PostScriptParser_nextToken() {
+      this.prev = this.token;
+      this.token = this.lexer.getToken();
+    },
+    accept: function PostScriptParser_accept(type) {
+      if (this.token.type == type) {
+        this.nextToken();
+        return true;
+      }
+      return false;
+    },
+    expect: function PostScriptParser_expect(type) {
+      if (this.accept(type))
+        return true;
+      error('Unexpected symbol: found ' + this.token.type + ' expected ' +
+            type + '.');
+    },
+    parse: function PostScriptParser_parse() {
+      this.nextToken();
+      this.expect(PostScriptTokenTypes.LBRACE);
+      this.parseBlock();
+      this.expect(PostScriptTokenTypes.RBRACE);
+      return this.operators;
+    },
+    parseBlock: function PostScriptParser_parseBlock() {
+      while (true) {
+        if (this.accept(PostScriptTokenTypes.NUMBER)) {
+          this.operators.push(this.prev.value);
+        } else if (this.accept(PostScriptTokenTypes.OPERATOR)) {
+          this.operators.push(this.prev.value);
+        } else if (this.accept(PostScriptTokenTypes.LBRACE)) {
+          this.parseCondition();
+        } else {
+          return;
+        }
+      }
+    },
+    parseCondition: function PostScriptParser_parseCondition() {
+      // Add two place holders that will be updated later
+      var conditionLocation = this.operators.length;
+      this.operators.push(null, null);
+
+      this.parseBlock();
+      this.expect(PostScriptTokenTypes.RBRACE);
+      if (this.accept(PostScriptTokenTypes.IF)) {
+        // The true block is right after the 'if' so it just falls through on
+        // true else it jumps and skips the true block.
+        this.operators[conditionLocation] = this.operators.length;
+        this.operators[conditionLocation + 1] = 'jz';
+      } else if (this.accept(PostScriptTokenTypes.LBRACE)) {
+        var jumpLocation = this.operators.length;
+        this.operators.push(null, null);
+        var endOfTrue = this.operators.length;
+        this.parseBlock();
+        this.expect(PostScriptTokenTypes.RBRACE);
+        this.expect(PostScriptTokenTypes.IFELSE);
+        // The jump is added at the end of the true block to skip the false
+        // block.
+        this.operators[jumpLocation] = this.operators.length;
+        this.operators[jumpLocation + 1] = 'j';
+
+        this.operators[conditionLocation] = endOfTrue;
+        this.operators[conditionLocation + 1] = 'jz';
+      } else {
+        error('PS Function: error parsing conditional.');
+      }
+    }
+  };
+  return PostScriptParser;
+})();
+
+var PostScriptTokenTypes = {
+  LBRACE: 0,
+  RBRACE: 1,
+  NUMBER: 2,
+  OPERATOR: 3,
+  IF: 4,
+  IFELSE: 5
+};
+
+var PostScriptToken = (function PostScriptTokenClosure() {
+  function PostScriptToken(type, value) {
+    this.type = type;
+    this.value = value;
+  }
+
+  var opCache = {};
+
+  PostScriptToken.getOperator = function PostScriptToken_getOperator(op) {
+    var opValue = opCache[op];
+    if (opValue)
+      return opValue;
+
+    return opCache[op] = new PostScriptToken(PostScriptTokenTypes.OPERATOR, op);
+  };
+
+  PostScriptToken.LBRACE = new PostScriptToken(PostScriptTokenTypes.LBRACE,
+                                                '{');
+  PostScriptToken.RBRACE = new PostScriptToken(PostScriptTokenTypes.RBRACE,
+                                                '}');
+  PostScriptToken.IF = new PostScriptToken(PostScriptTokenTypes.IF, 'IF');
+  PostScriptToken.IFELSE = new PostScriptToken(PostScriptTokenTypes.IFELSE,
+                                                'IFELSE');
+  return PostScriptToken;
+})();
+
+var PostScriptLexer = (function PostScriptLexerClosure() {
+  function PostScriptLexer(stream) {
+    this.stream = stream;
+  }
+  PostScriptLexer.prototype = {
+    getToken: function PostScriptLexer_getToken() {
+      var s = '';
+      var ch;
+      var comment = false;
+      var stream = this.stream;
+
+      // skip comments
+      while (true) {
+        if (!(ch = stream.getChar()))
+          return EOF;
+
+        if (comment) {
+          if (ch == '\x0a' || ch == '\x0d')
+            comment = false;
+        } else if (ch == '%') {
+          comment = true;
+        } else if (!Lexer.isSpace(ch)) {
+          break;
+        }
+      }
+      switch (ch) {
+        case '0': case '1': case '2': case '3': case '4':
+        case '5': case '6': case '7': case '8': case '9':
+        case '+': case '-': case '.':
+          return new PostScriptToken(PostScriptTokenTypes.NUMBER,
+                                      this.getNumber(ch));
+        case '{':
+          return PostScriptToken.LBRACE;
+        case '}':
+          return PostScriptToken.RBRACE;
+      }
+      // operator
+      var str = ch.toLowerCase();
+      while (true) {
+        ch = stream.lookChar().toLowerCase();
+        if (ch >= 'a' && ch <= 'z')
+          str += ch;
+        else
+          break;
+        stream.skip();
+      }
+      switch (str) {
+        case 'if':
+          return PostScriptToken.IF;
+        case 'ifelse':
+          return PostScriptToken.IFELSE;
+        default:
+          return PostScriptToken.getOperator(str);
+      }
+    },
+    getNumber: function PostScriptLexer_getNumber(ch) {
+      var str = ch;
+      var stream = this.stream;
+      while (true) {
+        ch = stream.lookChar();
+        if ((ch >= '0' && ch <= '9') || ch == '-' || ch == '.')
+          str += ch;
+        else
+          break;
+        stream.skip();
+      }
+      var value = parseFloat(str);
+      if (isNaN(value))
+        error('Invalid floating point number: ' + value);
+      return value;
+    }
+  };
+  return PostScriptLexer;
+})();
+
+/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
+
+'use strict';
+
+var ISOAdobeCharset = [
+  '.notdef', 'space', 'exclam', 'quotedbl', 'numbersign', 'dollar',
+  'percent', 'ampersand', 'quoteright', 'parenleft', 'parenright',
+  'asterisk', 'plus', 'comma', 'hyphen', 'period', 'slash', 'zero',
+  'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight',
+  'nine', 'colon', 'semicolon', 'less', 'equal', 'greater', 'question',
+  'at', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
+  'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
+  'bracketleft', 'backslash', 'bracketright', 'asciicircum', 'underscore',
+  'quoteleft', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l',
+  'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
+  'braceleft', 'bar', 'braceright', 'asciitilde', 'exclamdown', 'cent',
+  'sterling', 'fraction', 'yen', 'florin', 'section', 'currency',
+  'quotesingle', 'quotedblleft', 'guillemotleft', 'guilsinglleft',
+  'guilsinglright', 'fi', 'fl', 'endash', 'dagger', 'daggerdbl',
+  'periodcentered', 'paragraph', 'bullet', 'quotesinglbase',
+  'quotedblbase', 'quotedblright', 'guillemotright', 'ellipsis',
+  'perthousand', 'questiondown', 'grave', 'acute', 'circumflex', 'tilde',
+  'macron', 'breve', 'dotaccent', 'dieresis', 'ring', 'cedilla',
+  'hungarumlaut', 'ogonek', 'caron', 'emdash', 'AE', 'ordfeminine',
+  'Lslash', 'Oslash', 'OE', 'ordmasculine', 'ae', 'dotlessi', 'lslash',
+  'oslash', 'oe', 'germandbls', 'onesuperior', 'logicalnot', 'mu',
+  'trademark', 'Eth', 'onehalf', 'plusminus', 'Thorn', 'onequarter',
+  'divide', 'brokenbar', 'degree', 'thorn', 'threequarters', 'twosuperior',
+  'registered', 'minus', 'eth', 'multiply', 'threesuperior', 'copyright',
+  'Aacute', 'Acircumflex', 'Adieresis', 'Agrave', 'Aring', 'Atilde',
+  'Ccedilla', 'Eacute', 'Ecircumflex', 'Edieresis', 'Egrave', 'Iacute',
+  'Icircumflex', 'Idieresis', 'Igrave', 'Ntilde', 'Oacute', 'Ocircumflex',
+  'Odieresis', 'Ograve', 'Otilde', 'Scaron', 'Uacute', 'Ucircumflex',
+  'Udieresis', 'Ugrave', 'Yacute', 'Ydieresis', 'Zcaron', 'aacute',
+  'acircumflex', 'adieresis', 'agrave', 'aring', 'atilde', 'ccedilla',
+  'eacute', 'ecircumflex', 'edieresis', 'egrave', 'iacute', 'icircumflex',
+  'idieresis', 'igrave', 'ntilde', 'oacute', 'ocircumflex', 'odieresis',
+  'ograve', 'otilde', 'scaron', 'uacute', 'ucircumflex', 'udieresis',
+  'ugrave', 'yacute', 'ydieresis', 'zcaron'
+];
+
+var ExpertCharset = [
+  '.notdef', 'space', 'exclamsmall', 'Hungarumlautsmall', 'dollaroldstyle',
+  'dollarsuperior', 'ampersandsmall', 'Acutesmall', 'parenleftsuperior',
+  'parenrightsuperior', 'twodotenleader', 'onedotenleader', 'comma',
+  'hyphen', 'period', 'fraction', 'zerooldstyle', 'oneoldstyle',
+  'twooldstyle', 'threeoldstyle', 'fouroldstyle', 'fiveoldstyle',
+  'sixoldstyle', 'sevenoldstyle', 'eightoldstyle', 'nineoldstyle',
+  'colon', 'semicolon', 'commasuperior', 'threequartersemdash',
+  'periodsuperior', 'questionsmall', 'asuperior', 'bsuperior',
+  'centsuperior', 'dsuperior', 'esuperior', 'isuperior', 'lsuperior',
+  'msuperior', 'nsuperior', 'osuperior', 'rsuperior', 'ssuperior',
+  'tsuperior', 'ff', 'fi', 'fl', 'ffi', 'ffl', 'parenleftinferior',
+  'parenrightinferior', 'Circumflexsmall', 'hyphensuperior', 'Gravesmall',
+  'Asmall', 'Bsmall', 'Csmall', 'Dsmall', 'Esmall', 'Fsmall', 'Gsmall',
+  'Hsmall', 'Ismall', 'Jsmall', 'Ksmall', 'Lsmall', 'Msmall', 'Nsmall',
+  'Osmall', 'Psmall', 'Qsmall', 'Rsmall', 'Ssmall', 'Tsmall', 'Usmall',
+  'Vsmall', 'Wsmall', 'Xsmall', 'Ysmall', 'Zsmall', 'colonmonetary',
+  'onefitted', 'rupiah', 'Tildesmall', 'exclamdownsmall', 'centoldstyle',
+  'Lslashsmall', 'Scaronsmall', 'Zcaronsmall', 'Dieresissmall',
+  'Brevesmall', 'Caronsmall', 'Dotaccentsmall', 'Macronsmall',
+  'figuredash', 'hypheninferior', 'Ogoneksmall', 'Ringsmall',
+  'Cedillasmall', 'onequarter', 'onehalf', 'threequarters',
+  'questiondownsmall', 'oneeighth', 'threeeighths', 'fiveeighths',
+  'seveneighths', 'onethird', 'twothirds', 'zerosuperior', 'onesuperior',
+  'twosuperior', 'threesuperior', 'foursuperior', 'fivesuperior',
+  'sixsuperior', 'sevensuperior', 'eightsuperior', 'ninesuperior',
   'zeroinferior', 'oneinferior', 'twoinferior', 'threeinferior',
   'fourinferior', 'fiveinferior', 'sixinferior', 'seveninferior',
   'eightinferior', 'nineinferior', 'centinferior', 'dollarinferior',
@@ -9954,34 +11349,34 @@ var CIDToUnicodeMaps = {
 
 'use strict';
 
-var ColorSpace = (function colorSpaceColorSpace() {
+var ColorSpace = (function ColorSpaceClosure() {
   // Constructor should define this.numComps, this.defaultColor, this.name
-  function constructor() {
+  function ColorSpace() {
     error('should not call ColorSpace constructor');
   }
 
-  constructor.prototype = {
+  ColorSpace.prototype = {
     // Input: array of size numComps representing color component values
     // Output: array of rgb values, each value ranging from [0.1]
-    getRgb: function colorSpaceGetRgb(color) {
+    getRgb: function ColorSpace_getRgb(color) {
       error('Should not call ColorSpace.getRgb: ' + color);
     },
     // Input: Uint8Array of component values, each value scaled to [0,255]
     // Output: Uint8Array of rgb values, each value scaled to [0,255]
-    getRgbBuffer: function colorSpaceGetRgbBuffer(input) {
+    getRgbBuffer: function ColorSpace_getRgbBuffer(input) {
       error('Should not call ColorSpace.getRgbBuffer: ' + input);
     }
   };
 
-  constructor.parse = function colorSpaceParse(cs, xref, res) {
-    var IR = constructor.parseToIR(cs, xref, res);
+  ColorSpace.parse = function ColorSpace_parse(cs, xref, res) {
+    var IR = ColorSpace.parseToIR(cs, xref, res);
     if (IR instanceof AlternateCS)
       return IR;
 
-    return constructor.fromIR(IR);
+    return ColorSpace.fromIR(IR);
   };
 
-  constructor.fromIR = function colorSpaceFromIR(IR) {
+  ColorSpace.fromIR = function ColorSpace_fromIR(IR) {
     var name = isArray(IR) ? IR[0] : IR;
 
     switch (name) {
@@ -10008,15 +11403,20 @@ var ColorSpace = (function colorSpaceColorSpace() {
 
         return new AlternateCS(numComps, ColorSpace.fromIR(alt),
                                 PDFFunction.fromIR(tintFnIR));
+      case 'LabCS':
+        var whitePoint = IR[1].WhitePoint;
+        var blackPoint = IR[1].BlackPoint;
+        var range = IR[1].Range;
+        return new LabCS(whitePoint, blackPoint, range);
       default:
         error('Unkown name ' + name);
     }
     return null;
   };
 
-  constructor.parseToIR = function colorSpaceParseToIR(cs, xref, res) {
+  ColorSpace.parseToIR = function ColorSpace_parseToIR(cs, xref, res) {
     if (isName(cs)) {
-      var colorSpaces = xref.fetchIfRef(res.get('ColorSpace'));
+      var colorSpaces = res.get('ColorSpace');
       if (isDict(colorSpaces)) {
         var refcs = colorSpaces.get(cs.name);
         if (refcs)
@@ -10081,6 +11481,7 @@ var ColorSpace = (function colorSpaceColorSpace() {
             basePatternCS = ColorSpace.parseToIR(basePatternCS, xref, res);
           return ['PatternCS', basePatternCS];
         case 'Indexed':
+        case 'I':
           var baseIndexedCS = ColorSpace.parseToIR(cs[1], xref, res);
           var hiVal = cs[2] + 1;
           var lookup = xref.fetchIfRef(cs[3]);
@@ -10097,6 +11498,8 @@ var ColorSpace = (function colorSpaceColorSpace() {
           var tintFnIR = PDFFunction.getIR(xref, xref.fetchIfRef(cs[3]));
           return ['AlternateCS', numComps, alt, tintFnIR];
         case 'Lab':
+          var params = cs[1].getAll();
+          return ['LabCS', params];
         default:
           error('unimplemented color space object "' + mode + '"');
       }
@@ -10105,8 +11508,31 @@ var ColorSpace = (function colorSpaceColorSpace() {
     }
     return null;
   };
+  /**
+   * Checks if a decode map matches the default decode map for a color space.
+   * This handles the general decode maps where there are two values per
+   * component. e.g. [0, 1, 0, 1, 0, 1] for a RGB color.
+   * This does not handle Lab, Indexed, or Pattern decode maps since they are
+   * slightly different.
+   * @param {Array} decode Decode map (usually from an image).
+   * @param {Number} n Number of components the color space has.
+   */
+  ColorSpace.isDefaultDecode = function ColorSpace_isDefaultDecode(decode, n) {
+    if (!decode)
+      return true;
 
-  return constructor;
+    if (n * 2 !== decode.length) {
+      warning('The decode map is not the correct length');
+      return true;
+    }
+    for (var i = 0, ii = decode.length; i < ii; i += 2) {
+      if (decode[i] != 0 || decode[i + 1] != 1)
+        return false;
+    }
+    return true;
+  };
+
+  return ColorSpace;
 })();
 
 /**
@@ -10115,8 +11541,8 @@ var ColorSpace = (function colorSpaceColorSpace() {
  * Both color spaces use a tinting function to convert colors to a base color
  * space.
  */
-var AlternateCS = (function alternateCS() {
-  function constructor(numComps, base, tintFn) {
+var AlternateCS = (function AlternateCSClosure() {
+  function AlternateCS(numComps, base, tintFn) {
     this.name = 'Alternate';
     this.numComps = numComps;
     this.defaultColor = [];
@@ -10126,12 +11552,12 @@ var AlternateCS = (function alternateCS() {
     this.tintFn = tintFn;
   }
 
-  constructor.prototype = {
-    getRgb: function altcs_getRgb(color) {
+  AlternateCS.prototype = {
+    getRgb: function AlternateCS_getRgb(color) {
       var tinted = this.tintFn(color);
       return this.base.getRgb(tinted);
     },
-    getRgbBuffer: function altcs_getRgbBuffer(input, bits) {
+    getRgbBuffer: function AlternateCS_getRgbBuffer(input, bits) {
       var tintFn = this.tintFn;
       var base = this.base;
       var scale = 1 / ((1 << bits) - 1);
@@ -10140,7 +11566,7 @@ var AlternateCS = (function alternateCS() {
       var baseNumComps = base.numComps;
       var baseBuf = new Uint8Array(baseNumComps * length);
       var numComps = this.numComps;
-      var scaled = new Array(numComps);
+      var scaled = [];
 
       for (var i = 0; i < length; i += numComps) {
         for (var z = 0; z < numComps; ++z)
@@ -10151,24 +11577,27 @@ var AlternateCS = (function alternateCS() {
           baseBuf[pos++] = 255 * tinted[j];
       }
       return base.getRgbBuffer(baseBuf, 8);
+    },
+    isDefaultDecode: function AlternateCS_isDefaultDecode(decodeMap) {
+      return ColorSpace.isDefaultDecode(decodeMap, this.numComps);
     }
   };
 
-  return constructor;
+  return AlternateCS;
 })();
 
-var PatternCS = (function patternCS() {
-  function constructor(baseCS) {
+var PatternCS = (function PatternCSClosure() {
+  function PatternCS(baseCS) {
     this.name = 'Pattern';
     this.base = baseCS;
   }
-  constructor.prototype = {};
+  PatternCS.prototype = {};
 
-  return constructor;
+  return PatternCS;
 })();
 
-var IndexedCS = (function indexedCS() {
-  function constructor(base, highVal, lookup) {
+var IndexedCS = (function IndexedCSClosure() {
+  function IndexedCS(base, highVal, lookup) {
     this.name = 'Indexed';
     this.numComps = 1;
     this.defaultColor = [0];
@@ -10191,8 +11620,8 @@ var IndexedCS = (function indexedCS() {
     this.lookup = lookupArray;
   }
 
-  constructor.prototype = {
-    getRgb: function indexcs_getRgb(color) {
+  IndexedCS.prototype = {
+    getRgb: function IndexedCS_getRgb(color) {
       var numComps = this.base.numComps;
       var start = color[0] * numComps;
       var c = [];
@@ -10202,7 +11631,7 @@ var IndexedCS = (function indexedCS() {
 
       return this.base.getRgb(c);
     },
-    getRgbBuffer: function indexcs_getRgbBuffer(input) {
+    getRgbBuffer: function IndexedCS_getRgbBuffer(input) {
       var base = this.base;
       var numComps = base.numComps;
       var lookup = this.lookup;
@@ -10218,24 +11647,28 @@ var IndexedCS = (function indexedCS() {
       }
 
       return base.getRgbBuffer(baseBuf, 8);
+    },
+    isDefaultDecode: function IndexedCS_isDefaultDecode(decodeMap) {
+      // indexed color maps shouldn't be changed
+      return true;
     }
   };
-  return constructor;
+  return IndexedCS;
 })();
 
-var DeviceGrayCS = (function deviceGrayCS() {
-  function constructor() {
+var DeviceGrayCS = (function DeviceGrayCSClosure() {
+  function DeviceGrayCS() {
     this.name = 'DeviceGray';
     this.numComps = 1;
     this.defaultColor = [0];
   }
 
-  constructor.prototype = {
-    getRgb: function graycs_getRgb(color) {
+  DeviceGrayCS.prototype = {
+    getRgb: function DeviceGrayCS_getRgb(color) {
       var c = color[0];
       return [c, c, c];
     },
-    getRgbBuffer: function graycs_getRgbBuffer(input, bits) {
+    getRgbBuffer: function DeviceGrayCS_getRgbBuffer(input, bits) {
       var scale = 255 / ((1 << bits) - 1);
       var length = input.length;
       var rgbBuf = new Uint8Array(length * 3);
@@ -10246,22 +11679,25 @@ var DeviceGrayCS = (function deviceGrayCS() {
         rgbBuf[j++] = c;
       }
       return rgbBuf;
+    },
+    isDefaultDecode: function DeviceGrayCS_isDefaultDecode(decodeMap) {
+      return ColorSpace.isDefaultDecode(decodeMap, this.numComps);
     }
   };
-  return constructor;
+  return DeviceGrayCS;
 })();
 
-var DeviceRgbCS = (function deviceRgbCS() {
-  function constructor() {
+var DeviceRgbCS = (function DeviceRgbCSClosure() {
+  function DeviceRgbCS() {
     this.name = 'DeviceRGB';
     this.numComps = 3;
     this.defaultColor = [0, 0, 0];
   }
-  constructor.prototype = {
-    getRgb: function rgbcs_getRgb(color) {
+  DeviceRgbCS.prototype = {
+    getRgb: function DeviceRgbCS_getRgb(color) {
       return color;
     },
-    getRgbBuffer: function rgbcs_getRgbBuffer(input, bits) {
+    getRgbBuffer: function DeviceRgbCS_getRgbBuffer(input, bits) {
       if (bits == 8)
         return input;
       var scale = 255 / ((1 << bits) - 1);
@@ -10270,73 +11706,37 @@ var DeviceRgbCS = (function deviceRgbCS() {
       for (i = 0; i < length; ++i)
         rgbBuf[i] = (scale * input[i]) | 0;
       return rgbBuf;
+    },
+    isDefaultDecode: function DeviceRgbCS_isDefaultDecode(decodeMap) {
+      return ColorSpace.isDefaultDecode(decodeMap, this.numComps);
     }
   };
-  return constructor;
+  return DeviceRgbCS;
 })();
 
-var DeviceCmykCS = (function deviceCmykCS() {
-  function constructor() {
+var DeviceCmykCS = (function DeviceCmykCSClosure() {
+  function DeviceCmykCS() {
     this.name = 'DeviceCMYK';
     this.numComps = 4;
     this.defaultColor = [0, 0, 0, 1];
   }
-  constructor.prototype = {
-    getRgb: function cmykcs_getRgb(color) {
+  DeviceCmykCS.prototype = {
+    getRgb: function DeviceCmykCS_getRgb(color) {
       var c = color[0], m = color[1], y = color[2], k = color[3];
-      var c1 = 1 - c, m1 = 1 - m, y1 = 1 - y, k1 = 1 - k;
-
-      var x, r, g, b;
-      // this is a matrix multiplication, unrolled for performance
-      // code is taken from the poppler implementation
-      x = c1 * m1 * y1 * k1; // 0 0 0 0
-      r = g = b = x;
-      x = c1 * m1 * y1 * k;  // 0 0 0 1
-      r += 0.1373 * x;
-      g += 0.1216 * x;
-      b += 0.1255 * x;
-      x = c1 * m1 * y * k1;  // 0 0 1 0
-      r += x;
-      g += 0.9490 * x;
-      x = c1 * m1 * y * k;   // 0 0 1 1
-      r += 0.1098 * x;
-      g += 0.1020 * x;
-      x = c1 * m * y1 * k1;  // 0 1 0 0
-      r += 0.9255 * x;
-      b += 0.5490 * x;
-      x = c1 * m * y1 * k;   // 0 1 0 1
-      r += 0.1412 * x;
-      x = c1 * m * y * k1;   // 0 1 1 0
-      r += 0.9294 * x;
-      g += 0.1098 * x;
-      b += 0.1412 * x;
-      x = c1 * m * y * k;    // 0 1 1 1
-      r += 0.1333 * x;
-      x = c * m1 * y1 * k1;  // 1 0 0 0
-      g += 0.6784 * x;
-      b += 0.9373 * x;
-      x = c * m1 * y1 * k;   // 1 0 0 1
-      g += 0.0588 * x;
-      b += 0.1412 * x;
-      x = c * m1 * y * k1;   // 1 0 1 0
-      g += 0.6510 * x;
-      b += 0.3137 * x;
-      x = c * m1 * y * k;    // 1 0 1 1
-      g += 0.0745 * x;
-      x = c * m * y1 * k1;   // 1 1 0 0
-      r += 0.1804 * x;
-      g += 0.1922 * x;
-      b += 0.5725 * x;
-      x = c * m * y1 * k;    // 1 1 0 1
-      b += 0.0078 * x;
-      x = c * m * y * k1;    // 1 1 1 0
-      r += 0.2118 * x;
-      g += 0.2119 * x;
-      b += 0.2235 * x;
+
+      // CMYK -> CMY: http://www.easyrgb.com/index.php?X=MATH&H=14#text14
+      c = (c * (1 - k) + k);
+      m = (m * (1 - k) + k);
+      y = (y * (1 - k) + k);
+
+      // CMY -> RGB: http://www.easyrgb.com/index.php?X=MATH&H=12#text12
+      var r = (1 - c);
+      var g = (1 - m);
+      var b = (1 - y);
 
       return [r, g, b];
     },
-    getRgbBuffer: function cmykcs_getRgbBuffer(colorBuf, bits) {
+    getRgbBuffer: function DeviceCmykCS_getRgbBuffer(colorBuf, bits) {
       var scale = 1 / ((1 << bits) - 1);
       var length = colorBuf.length / 4;
       var rgbBuf = new Uint8Array(length * 3);
@@ -10354,38 +11754,154 @@ var DeviceCmykCS = (function deviceCmykCS() {
       }
 
       return rgbBuf;
+    },
+    isDefaultDecode: function DeviceCmykCS_isDefaultDecode(decodeMap) {
+      return ColorSpace.isDefaultDecode(decodeMap, this.numComps);
     }
   };
 
-  return constructor;
+  return DeviceCmykCS;
 })();
 
-/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
+//
+// LabCS: Based on "PDF Reference, Sixth Ed", p.250
+//
+var LabCS = (function LabCSClosure() {
+  function LabCS(whitePoint, blackPoint, range) {
+    this.name = 'Lab';
+    this.numComps = 3;
+    this.defaultColor = [0, 0, 0];
 
-'use strict';
+    if (!whitePoint)
+      error('WhitePoint missing - required for color space Lab');
+    blackPoint = blackPoint || [0, 0, 0];
+    range = range || [-100, 100, -100, 100];
+
+    // Translate args to spec variables
+    this.XW = whitePoint[0];
+    this.YW = whitePoint[1];
+    this.ZW = whitePoint[2];
+    this.amin = range[0];
+    this.amax = range[1];
+    this.bmin = range[2];
+    this.bmax = range[3];
+
+    // These are here just for completeness - the spec doesn't offer any
+    // formulas that use BlackPoint in Lab
+    this.XB = blackPoint[0];
+    this.YB = blackPoint[1];
+    this.ZB = blackPoint[2];
+
+    // Validate vars as per spec
+    if (this.XW < 0 || this.ZW < 0 || this.YW !== 1)
+      error('Invalid WhitePoint components, no fallback available');
+
+    if (this.XB < 0 || this.YB < 0 || this.ZB < 0) {
+      warn('Invalid BlackPoint, falling back to default');
+      this.XB = this.YB = this.ZB = 0;
+    }
 
-var ARCFourCipher = (function arcFourCipher() {
-  function constructor(key) {
-    this.a = 0;
-    this.b = 0;
-    var s = new Uint8Array(256);
-    var i, j = 0, tmp, keyLength = key.length;
-    for (i = 0; i < 256; ++i)
-      s[i] = i;
-    for (i = 0; i < 256; ++i) {
-      tmp = s[i];
-      j = (j + tmp + key[i % keyLength]) & 0xFF;
-      s[i] = s[j];
-      s[j] = tmp;
+    if (this.amin > this.amax || this.bmin > this.bmax) {
+      warn('Invalid Range, falling back to defaults');
+      this.amin = -100;
+      this.amax = 100;
+      this.bmin = -100;
+      this.bmax = 100;
     }
-    this.s = s;
+  };
+
+  // Function g(x) from spec
+  function g(x) {
+    if (x >= 6 / 29)
+      return x * x * x;
+    else
+      return (108 / 841) * (x - 4 / 29);
   }
 
-  constructor.prototype = {
-    encryptBlock: function arcFourCipherEncryptBlock(data) {
-      var i, n = data.length, tmp, tmp2;
-      var a = this.a, b = this.b, s = this.s;
+  LabCS.prototype = {
+    getRgb: function LabCS_getRgb(color) {
+      // Ls,as,bs <---> L*,a*,b* in the spec
+      var Ls = color[0], as = color[1], bs = color[2];
+
+      // Adjust limits of 'as' and 'bs'
+      as = as > this.amax ? this.amax : as;
+      as = as < this.amin ? this.amin : as;
+      bs = bs > this.bmax ? this.bmax : bs;
+      bs = bs < this.bmin ? this.bmin : bs;
+
+      // Computes intermediate variables X,Y,Z as per spec
+      var M = (Ls + 16) / 116;
+      var L = M + (as / 500);
+      var N = M - (bs / 200);
+      var X = this.XW * g(L);
+      var Y = this.YW * g(M);
+      var Z = this.ZW * g(N);
+
+      // XYZ to RGB 3x3 matrix, from:
+      // http://www.poynton.com/notes/colour_and_gamma/ColorFAQ.html#RTFToC18
+      var XYZtoRGB = [3.240479, -1.537150, -0.498535,
+                      -0.969256, 1.875992, 0.041556,
+                      0.055648, -0.204043, 1.057311];
+
+      return Util.apply3dTransform(XYZtoRGB, [X, Y, Z]);
+    },
+    getRgbBuffer: function LabCS_getRgbBuffer(input, bits) {
+      if (bits == 8)
+        return input;
+      var scale = 255 / ((1 << bits) - 1);
+      var i, length = input.length / 3;
+      var rgbBuf = new Uint8Array(length);
+
+      var j = 0;
+      for (i = 0; i < length; ++i) {
+        // Convert L*, a*, s* into RGB
+        var rgb = this.getRgb([input[i], input[i + 1], input[i + 2]]);
+        rgbBuf[j++] = rgb[0];
+        rgbBuf[j++] = rgb[1];
+        rgbBuf[j++] = rgb[2];
+      }
+
+      return rgbBuf;
+    },
+    isDefaultDecode: function LabCS_isDefaultDecode(decodeMap) {
+      // From Table 90 in Adobe's:
+      // "Document management - Portable document format", 1st ed, 2008
+      if (decodeMap[0] === 0 && decodeMap[1] === 100 &&
+          decodeMap[2] === this.amin && decodeMap[3] === this.amax &&
+          decodeMap[4] === this.bmin && decodeMap[5] === this.bmax)
+        return true;
+      else
+        return false;
+    }
+  };
+  return LabCS;
+})();
+/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
+
+'use strict';
+
+var ARCFourCipher = (function ARCFourCipherClosure() {
+  function ARCFourCipher(key) {
+    this.a = 0;
+    this.b = 0;
+    var s = new Uint8Array(256);
+    var i, j = 0, tmp, keyLength = key.length;
+    for (i = 0; i < 256; ++i)
+      s[i] = i;
+    for (i = 0; i < 256; ++i) {
+      tmp = s[i];
+      j = (j + tmp + key[i % keyLength]) & 0xFF;
+      s[i] = s[j];
+      s[j] = tmp;
+    }
+    this.s = s;
+  }
+
+  ARCFourCipher.prototype = {
+    encryptBlock: function ARCFourCipher_encryptBlock(data) {
+      var i, n = data.length, tmp, tmp2;
+      var a = this.a, b = this.b, s = this.s;
       var output = new Uint8Array(n);
       for (i = 0; i < n; ++i) {
         a = (a + 1) & 0xFF;
@@ -10401,12 +11917,12 @@ var ARCFourCipher = (function arcFourCipher() {
       return output;
     }
   };
-  constructor.prototype.decryptBlock = constructor.prototype.encryptBlock;
+  ARCFourCipher.prototype.decryptBlock = ARCFourCipher.prototype.encryptBlock;
 
-  return constructor;
+  return ARCFourCipher;
 })();
 
-var calculateMD5 = (function calculateMD5() {
+var calculateMD5 = (function calculateMD5Closure() {
   var r = new Uint8Array([
     7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22,
     5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20,
@@ -10490,20 +12006,20 @@ var calculateMD5 = (function calculateMD5() {
   return hash;
 })();
 
-var NullCipher = (function nullCipher() {
-  function constructor() {
+var NullCipher = (function NullCipherClosure() {
+  function NullCipher() {
   }
 
-  constructor.prototype = {
-    decryptBlock: function nullCipherDecryptBlock(data) {
+  NullCipher.prototype = {
+    decryptBlock: function NullCipher_decryptBlock(data) {
       return data;
     }
   };
 
-  return constructor;
+  return NullCipher;
 })();
 
-var AES128Cipher = (function aes128Cipher() {
+var AES128Cipher = (function AES128CipherClosure() {
   var rcon = new Uint8Array([
     0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c,
     0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a,
@@ -10692,7 +12208,7 @@ var AES128Cipher = (function aes128Cipher() {
     return state;
   }
 
-  function constructor(key) {
+  function AES128Cipher(key) {
     this.key = expandKey128(key);
     this.buffer = new Uint8Array(16);
     this.bufferPosition = 0;
@@ -10732,8 +12248,8 @@ var AES128Cipher = (function aes128Cipher() {
     return output;
   }
 
-  constructor.prototype = {
-    decryptBlock: function aes128CipherDecryptBlock(data) {
+  AES128Cipher.prototype = {
+    decryptBlock: function AES128Cipher_decryptBlock(data) {
       var i, sourceLength = data.length;
       var buffer = this.buffer, bufferLength = this.bufferPosition;
       // waiting for IV values -- they are at the start of the stream
@@ -10753,16 +12269,16 @@ var AES128Cipher = (function aes128Cipher() {
     }
   };
 
-  return constructor;
+  return AES128Cipher;
 })();
 
-var CipherTransform = (function cipherTransform() {
-  function constructor(stringCipherConstructor, streamCipherConstructor) {
+var CipherTransform = (function CipherTransformClosure() {
+  function CipherTransform(stringCipherConstructor, streamCipherConstructor) {
     this.stringCipherConstructor = stringCipherConstructor;
     this.streamCipherConstructor = streamCipherConstructor;
   }
-  constructor.prototype = {
-    createStream: function cipherTransformCreateStream(stream) {
+  CipherTransform.prototype = {
+    createStream: function CipherTransform_createStream(stream) {
       var cipher = new this.streamCipherConstructor();
       return new DecryptStream(stream,
         function cipherTransformDecryptStream(data) {
@@ -10770,17 +12286,17 @@ var CipherTransform = (function cipherTransform() {
         }
       );
     },
-    decryptString: function cipherTransformDecryptString(s) {
+    decryptString: function CipherTransform_decryptString(s) {
       var cipher = new this.stringCipherConstructor();
       var data = stringToBytes(s);
       data = cipher.decryptBlock(data);
       return bytesToString(data);
     }
   };
-  return constructor;
+  return CipherTransform;
 })();
 
-var CipherTransformFactory = (function cipherTransformFactory() {
+var CipherTransformFactory = (function CipherTransformFactoryClosure() {
   function prepareKeyData(fileId, password, ownerPassword, userPassword,
                           flags, revision, keyLength, encryptMetadata) {
     var defaultPasswordBytes = new Uint8Array([
@@ -10852,7 +12368,7 @@ var CipherTransformFactory = (function cipherTransformFactory() {
 
   var identityName = new Name('Identity');
 
-  function constructor(dict, fileId, password) {
+  function CipherTransformFactory(dict, fileId, password) {
     var filter = dict.get('Filter');
     if (!isName(filter) || filter.name != 'Standard')
       error('unknown encryption method');
@@ -10932,12 +12448,11 @@ var CipherTransformFactory = (function cipherTransformFactory() {
       };
     }
     error('Unknown crypto method');
-    return null;
   }
 
-  constructor.prototype = {
-    createCipherTransform: function buildCipherCreateCipherTransform(num,
-                                                                     gen) {
+  CipherTransformFactory.prototype = {
+    createCipherTransform:
+      function CipherTransformFactory_createCipherTransform(num, gen) {
       if (this.algorithm == 4) {
         return new CipherTransform(
           buildCipherConstructor(this.cf, this.stmf,
@@ -10954,7 +12469,7 @@ var CipherTransformFactory = (function cipherTransformFactory() {
     }
   };
 
-  return constructor;
+  return CipherTransformFactory;
 })();
 
 /* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
@@ -10962,8 +12477,8 @@ var CipherTransformFactory = (function cipherTransformFactory() {
 
 'use strict';
 
-var PartialEvaluator = (function partialEvaluator() {
-  function constructor(xref, handler, uniquePrefix) {
+var PartialEvaluator = (function PartialEvaluatorClosure() {
+  function PartialEvaluator(xref, handler, uniquePrefix) {
     this.state = new EvalState();
     this.stateStack = [];
 
@@ -11070,14 +12585,27 @@ var PartialEvaluator = (function partialEvaluator() {
     EX: 'endCompat'
   };
 
-  constructor.prototype = {
-    getIRQueue: function partialEvaluatorGetIRQueue(stream, resources,
-                                    queue, dependency) {
+  function splitCombinedOperations(operations) {
+    // Two operations can be combined together, trying to find which two
+    // operations were concatenated.
+    for (var i = operations.length - 1; i > 0; i--) {
+      var op1 = operations.substring(0, i), op2 = operations.substring(i);
+      if (op1 in OP_MAP && op2 in OP_MAP)
+        return [op1, op2]; // operations found
+    }
+    return null;
+  }
+
+  PartialEvaluator.prototype = {
+    getOperatorList: function PartialEvaluator_getOperatorList(stream,
+                                                               resources,
+                                                               dependency,
+                                                               queue) {
 
       var self = this;
       var xref = this.xref;
       var handler = this.handler;
-      var uniquePrefix = this.uniquePrefix;
+      var uniquePrefix = this.uniquePrefix || '';
 
       function insertDependency(depList) {
         fnArray.push('dependency');
@@ -11090,18 +12618,14 @@ var PartialEvaluator = (function partialEvaluator() {
         }
       }
 
-      function handleSetFont(fontName, fontRef) {
+      function handleSetFont(fontName, font) {
         var loadedName = null;
 
         var fontRes = resources.get('Font');
 
-        // TODO: TOASK: Is it possible to get here? If so, what does
-        // args[0].name should be like???
         assert(fontRes, 'fontRes not available');
 
-        fontRes = xref.fetchIfRef(fontRes);
-        fontRef = fontRef || fontRes.get(fontName);
-        var font = xref.fetchIfRef(fontRef);
+        font = xref.fetchIfRef(font) || fontRes.get(fontName);
         assertWellFormed(isDict(font));
         if (!font.translated) {
           font.translated = self.translateFont(font, xref, resources,
@@ -11114,6 +12638,15 @@ var PartialEvaluator = (function partialEvaluator() {
             font.loadedName = loadedName;
 
             var translated = font.translated;
+            // Convert the file to an ArrayBuffer which will be turned back into
+            // a Stream in the main thread.
+            if (translated.file)
+              translated.file = translated.file.getBytes();
+            if (translated.properties.file) {
+              translated.properties.file =
+                  translated.properties.file.getBytes();
+            }
+
             handler.send('obj', [
                 loadedName,
                 'Font',
@@ -11127,7 +12660,7 @@ var PartialEvaluator = (function partialEvaluator() {
 
         // Ensure the font is ready before the font is set
         // and later on used for drawing.
-        // TODO: This should get insert to the IRQueue only once per
+        // OPTIMIZE: This should get insert to the operatorList only once per
         // page.
         insertDependency([loadedName]);
         return loadedName;
@@ -11138,65 +12671,60 @@ var PartialEvaluator = (function partialEvaluator() {
         var w = dict.get('Width', 'W');
         var h = dict.get('Height', 'H');
 
-        if (image instanceof JpegStream && image.isNative) {
-          var objId = 'img_' + uniquePrefix + (++self.objIdCounter);
-          handler.send('obj', [objId, 'JpegStream', image.getIR()]);
-
-          // Add the dependency on the image object.
-          insertDependency([objId]);
-
-          // The normal fn.
-          fn = 'paintJpegXObject';
-          args = [objId, w, h];
-
+        var imageMask = dict.get('ImageMask', 'IM') || false;
+        if (imageMask) {
+          // This depends on a tmpCanvas beeing filled with the
+          // current fillStyle, such that processing the pixel
+          // data can't be done here. Instead of creating a
+          // complete PDFImage, only read the information needed
+          // for later.
+
+          var width = dict.get('Width', 'W');
+          var height = dict.get('Height', 'H');
+          var bitStrideLength = (width + 7) >> 3;
+          var imgArray = image.getBytes(bitStrideLength * height);
+          var decode = dict.get('Decode', 'D');
+          var inverseDecode = !!decode && decode[0] > 0;
+
+          fn = 'paintImageMaskXObject';
+          args = [imgArray, inverseDecode, width, height];
           return;
         }
 
-        // Needs to be rendered ourself.
-
-        // Figure out if the image has an imageMask.
-        var imageMask = dict.get('ImageMask', 'IM') || false;
-
         // If there is no imageMask, create the PDFImage and a lot
         // of image processing can be done here.
-        if (!imageMask) {
-          var imageObj = new PDFImage(xref, resources, image, inline);
-
-          if (imageObj.imageMask) {
-            throw 'Can\'t handle this in the web worker :/';
-          }
-
-          var imgData = {
-            width: w,
-            height: h,
-            data: new Uint8Array(w * h * 4)
-          };
-          var pixels = imgData.data;
-          imageObj.fillRgbaBuffer(pixels, imageObj.decode);
-
-          fn = 'paintImageXObject';
-          args = [imgData];
+        var objId = 'img_' + uniquePrefix + (++self.objIdCounter);
+        insertDependency([objId]);
+        args = [objId, w, h];
+
+        var softMask = dict.get('SMask', 'IM') || false;
+        if (!softMask && image instanceof JpegStream &&
+            image.isNativelySupported(xref, resources)) {
+          // These JPEGs don't need any more processing so we can just send it.
+          fn = 'paintJpegXObject';
+          handler.send('obj', [objId, 'JpegStream', image.getIR()]);
           return;
         }
 
-        // This depends on a tmpCanvas beeing filled with the
-        // current fillStyle, such that processing the pixel
-        // data can't be done here. Instead of creating a
-        // complete PDFImage, only read the information needed
-        // for later.
-        fn = 'paintImageMaskXObject';
+        fn = 'paintImageXObject';
 
-        var width = dict.get('Width', 'W');
-        var height = dict.get('Height', 'H');
-        var bitStrideLength = (width + 7) >> 3;
-        var imgArray = image.getBytes(bitStrideLength * height);
-        var decode = dict.get('Decode', 'D');
-        var inverseDecode = !!decode && decode[0] > 0;
-
-        args = [imgArray, inverseDecode, width, height];
+        PDFImage.buildImage(function(imageObj) {
+            var drawWidth = imageObj.drawWidth;
+            var drawHeight = imageObj.drawHeight;
+            var imgData = {
+              width: drawWidth,
+              height: drawHeight,
+              data: new Uint8Array(drawWidth * drawHeight * 4)
+            };
+            var pixels = imgData.data;
+            imageObj.fillRgbaBuffer(pixels, drawWidth, drawHeight);
+            handler.send('obj', [objId, 'Image', imgData]);
+          }, handler, xref, resources, image, inline);
       }
 
-      uniquePrefix = uniquePrefix || '';
+      if (!queue)
+        queue = {};
+
       if (!queue.argsArray) {
         queue.argsArray = [];
       }
@@ -11207,45 +12735,48 @@ var PartialEvaluator = (function partialEvaluator() {
       var fnArray = queue.fnArray, argsArray = queue.argsArray;
       var dependencyArray = dependency || [];
 
-      resources = xref.fetchIfRef(resources) || new Dict();
-      var xobjs = xref.fetchIfRef(resources.get('XObject')) || new Dict();
-      var patterns = xref.fetchIfRef(resources.get('Pattern')) || new Dict();
-      var parser = new Parser(new Lexer(stream), false);
+      resources = resources || new Dict();
+      var xobjs = resources.get('XObject') || new Dict();
+      var patterns = resources.get('Pattern') || new Dict();
+      var parser = new Parser(new Lexer(stream), false, xref);
       var res = resources;
+      var hasNextObj = false, nextObj;
       var args = [], obj;
-      var getObjBt = function getObjBt() {
-        parser = this.oldParser;
-        return { name: 'BT' };
-      };
       var TILING_PATTERN = 1, SHADING_PATTERN = 2;
 
-      while (!isEOF(obj = parser.getObj())) {
+      while (true) {
+        if (hasNextObj) {
+          obj = nextObj;
+          hasNextObj = false;
+        } else {
+          obj = parser.getObj();
+          if (isEOF(obj))
+            break;
+        }
+
         if (isCmd(obj)) {
           var cmd = obj.cmd;
           var fn = OP_MAP[cmd];
           if (!fn) {
             // invalid content command, trying to recover
-            if (cmd.substr(-2) == 'BT') {
-              fn = OP_MAP[cmd.substr(0, cmd.length - 2)];
-              // feeding 'BT' on next interation
-              parser = {
-                getObj: getObjBt,
-                oldParser: parser
-              };
+            var cmds = splitCombinedOperations(cmd);
+            if (cmds) {
+              cmd = cmds[0];
+              fn = OP_MAP[cmd];
+              // feeding other command on the next interation
+              hasNextObj = true;
+              nextObj = Cmd.get(cmds[1]);
             }
           }
           assertWellFormed(fn, 'Unknown command "' + cmd + '"');
           // TODO figure out how to type-check vararg functions
 
           if ((cmd == 'SCN' || cmd == 'scn') && !args[args.length - 1].code) {
-            // Use the IR version for setStroke/FillColorN.
-            fn += '_IR';
-
             // compile tiling patterns
             var patternName = args[args.length - 1];
             // SCN/scn applies patterns along with normal colors
             if (isName(patternName)) {
-              var pattern = xref.fetchIfRef(patterns.get(patternName.name));
+              var pattern = patterns.get(patternName.name);
               if (pattern) {
                 var dict = isStream(pattern) ? pattern.dict : pattern;
                 var typeNum = dict.get('PatternType');
@@ -11253,21 +12784,20 @@ var PartialEvaluator = (function partialEvaluator() {
                 if (typeNum == TILING_PATTERN) {
                   // Create an IR of the pattern code.
                   var depIdx = dependencyArray.length;
-                  var queueObj = {};
-                  var codeIR = this.getIRQueue(pattern, dict.get('Resources'),
-                                               queueObj, dependencyArray);
+                  var operatorList = this.getOperatorList(pattern,
+                      dict.get('Resources') || resources, dependencyArray);
 
                   // Add the dependencies that are required to execute the
-                  // codeIR.
+                  // operatorList.
                   insertDependency(dependencyArray.slice(depIdx));
 
-                  args = TilingPattern.getIR(codeIR, dict, args);
+                  args = TilingPattern.getIR(operatorList, dict, args);
                 }
                 else if (typeNum == SHADING_PATTERN) {
-                  var shading = xref.fetchIfRef(dict.get('Shading'));
+                  var shading = dict.get('Shading');
                   var matrix = dict.get('Matrix');
-                  var pattern = Pattern.parseShading(shading, matrix, xref, res,
-                                                                  null /*ctx*/);
+                  var pattern = Pattern.parseShading(shading, matrix, xref,
+                                                     res);
                   args = pattern.getIR();
                 } else {
                   error('Unkown PatternType ' + typeNum);
@@ -11279,7 +12809,6 @@ var PartialEvaluator = (function partialEvaluator() {
             var name = args[0].name;
             var xobj = xobjs.get(name);
             if (xobj) {
-              xobj = xref.fetchIfRef(xobj);
               assertWellFormed(isStream(xobj), 'XObject should be a stream');
 
               var type = xobj.dict.get('Subtype');
@@ -11295,14 +12824,18 @@ var PartialEvaluator = (function partialEvaluator() {
                 fnArray.push('paintFormXObjectBegin');
                 argsArray.push([matrix, bbox]);
 
-                // This adds the IRQueue of the xObj to the current queue.
+                // This adds the operatorList of the xObj to the current queue.
                 var depIdx = dependencyArray.length;
 
-                this.getIRQueue(xobj, xobj.dict.get('Resources'), queue,
-                                dependencyArray);
+                // Pass in the current `queue` object. That means the `fnArray`
+                // and the `argsArray` in this scope is reused and new commands
+                // are added to them.
+                this.getOperatorList(xobj,
+                    xobj.dict.get('Resources') || resources,
+                    dependencyArray, queue);
 
                // Add the dependencies that are required to execute the
-               // codeIR.
+               // operatorList.
                insertDependency(dependencyArray.slice(depIdx));
 
                 fn = 'paintFormXObjectEnd';
@@ -11326,28 +12859,27 @@ var PartialEvaluator = (function partialEvaluator() {
               args = [ColorSpace.parseToIR(args[0], xref, resources)];
               break;
             case 'shadingFill':
-              var shadingRes = xref.fetchIfRef(res.get('Shading'));
+              var shadingRes = res.get('Shading');
               if (!shadingRes)
                 error('No shading resource found');
 
-              var shading = xref.fetchIfRef(shadingRes.get(args[0].name));
+              var shading = shadingRes.get(args[0].name);
               if (!shading)
                 error('No shading object found');
 
-              var shadingFill = Pattern.parseShading(shading, null, xref, res,
-                                                      null);
+              var shadingFill = Pattern.parseShading(shading, null, xref, res);
               var patternIR = shadingFill.getIR();
               args = [patternIR];
               fn = 'shadingFill';
               break;
             case 'setGState':
               var dictName = args[0];
-              var extGState = xref.fetchIfRef(resources.get('ExtGState'));
+              var extGState = resources.get('ExtGState');
 
               if (!isDict(extGState) || !extGState.has(dictName.name))
                 break;
 
-              var gsState = xref.fetchIfRef(extGState.get(dictName.name));
+              var gsState = extGState.get(dictName.name);
 
               // This array holds the converted/processed state data.
               var gsStateObj = [];
@@ -11412,10 +12944,7 @@ var PartialEvaluator = (function partialEvaluator() {
         }
       }
 
-      return {
-        fnArray: fnArray,
-        argsArray: argsArray
-      };
+      return queue;
     },
 
     extractDataStructures: function
@@ -11429,7 +12958,7 @@ var PartialEvaluator = (function partialEvaluator() {
 
       if (properties.composite) {
         // CIDSystemInfo helps to match CID to glyphs
-        var cidSystemInfo = xref.fetchIfRef(dict.get('CIDSystemInfo'));
+        var cidSystemInfo = dict.get('CIDSystemInfo');
         if (isDict(cidSystemInfo)) {
           properties.cidSystemInfo = {
             registry: cidSystemInfo.get('Registry'),
@@ -11438,20 +12967,24 @@ var PartialEvaluator = (function partialEvaluator() {
           };
         }
 
-        var cidToGidMap = xref.fetchIfRef(dict.get('CIDToGIDMap'));
+        var cidToGidMap = dict.get('CIDToGIDMap');
         if (isStream(cidToGidMap))
           properties.cidToGidMap = this.readCidToGidMap(cidToGidMap);
       }
 
+      var flags = properties.flags;
       var differences = [];
-      var baseEncoding = Encodings.StandardEncoding;
+      var baseEncoding = !!(flags & FontFlags.Symbolic) ?
+                         Encodings.symbolsEncoding : Encodings.StandardEncoding;
       var hasEncoding = dict.has('Encoding');
       if (hasEncoding) {
-        var encoding = xref.fetchIfRef(dict.get('Encoding'));
+        var encoding = dict.get('Encoding');
         if (isDict(encoding)) {
           var baseName = encoding.get('BaseEncoding');
           if (baseName)
             baseEncoding = Encodings[baseName.name];
+          else
+            hasEncoding = false; // base encoding was not provided
 
           // Load the differences between the base and original
           if (encoding.has('Differences')) {
@@ -11471,14 +13004,14 @@ var PartialEvaluator = (function partialEvaluator() {
           error('Encoding is not a Name nor a Dict');
         }
       }
+
       properties.differences = differences;
       properties.baseEncoding = baseEncoding;
       properties.hasEncoding = hasEncoding;
     },
 
-    readToUnicode:
-      function partialEvaluatorReadToUnicode(toUnicode, xref) {
-      var cmapObj = xref.fetchIfRef(toUnicode);
+    readToUnicode: function PartialEvaluator_readToUnicode(toUnicode, xref) {
+      var cmapObj = toUnicode;
       var charToUnicode = [];
       if (isName(cmapObj)) {
         var isIdentityMap = cmapObj.name.substr(0, 9) == 'Identity-';
@@ -11491,9 +13024,9 @@ var PartialEvaluator = (function partialEvaluator() {
 
         var cmap = cmapObj.getBytes(cmapObj.length);
         for (var i = 0, ii = cmap.length; i < ii; i++) {
-          var byte = cmap[i];
-          if (byte == 0x20 || byte == 0x0D || byte == 0x0A ||
-              byte == 0x3C || byte == 0x5B || byte == 0x5D) {
+          var octet = cmap[i];
+          if (octet == 0x20 || octet == 0x0D || octet == 0x0A ||
+              octet == 0x3C || octet == 0x5B || octet == 0x5D) {
             switch (token) {
               case 'usecmap':
                 error('usecmap is not implemented');
@@ -11513,9 +13046,21 @@ var PartialEvaluator = (function partialEvaluator() {
                   var startRange = tokens[j];
                   var endRange = tokens[j + 1];
                   var code = tokens[j + 2];
-                  while (startRange <= endRange) {
-                    charToUnicode[startRange] = code++;
-                    ++startRange;
+                  if (code == 0xFFFF) {
+                    // CMap is broken, assuming code == startRange
+                    code = startRange;
+                  }
+                  if (isArray(code)) {
+                    var codeindex = 0;
+                    while (startRange <= endRange) {
+                      charToUnicode[startRange] = code[codeindex++];
+                      ++startRange;
+                    }
+                  } else {
+                    while (startRange <= endRange) {
+                      charToUnicode[startRange] = code++;
+                      ++startRange;
+                    }
                   }
                 }
                 break;
@@ -11538,7 +13083,7 @@ var PartialEvaluator = (function partialEvaluator() {
                 tokens.push(token);
                 token = '';
             }
-            switch (byte) {
+            switch (octet) {
               case 0x5B:
                 // begin list parsing
                 tokens.push(beginArrayToken);
@@ -11552,21 +13097,39 @@ var PartialEvaluator = (function partialEvaluator() {
                 tokens.push(items);
                 break;
             }
-          } else if (byte == 0x3E) {
+          } else if (octet == 0x3E) {
             if (token.length) {
-              // parsing hex number
-              tokens.push(parseInt(token, 16));
-              token = '';
+              if (token.length <= 4) {
+                // parsing hex number
+                tokens.push(parseInt(token, 16));
+                token = '';
+              } else {
+                // parsing hex UTF-16BE numbers
+                var str = [];
+                for (var k = 0, kk = token.length; k < kk; k += 4) {
+                  var b = parseInt(token.substr(k, 4), 16);
+                  if (b <= 0x10) {
+                    k += 4;
+                    b = (b << 16) | parseInt(token.substr(k, 4), 16);
+                    b -= 0x10000;
+                    str.push(0xD800 | (b >> 10));
+                    str.push(0xDC00 | (b & 0x3FF));
+                    break;
+                  }
+                  str.push(b);
+                }
+                tokens.push(String.fromCharCode.apply(String, str));
+                token = '';
+              }
             }
           } else {
-            token += String.fromCharCode(byte);
+            token += String.fromCharCode(octet);
           }
         }
       }
       return charToUnicode;
     },
-    readCidToGidMap:
-      function partialEvaluatorReadCidToGidMap(cidToGidStream) {
+    readCidToGidMap: function PartialEvaluator_readCidToGidMap(cidToGidStream) {
       // Extract the encoding from the CIDToGIDMap
       var glyphsData = cidToGidStream.getBytes();
 
@@ -11583,16 +13146,16 @@ var PartialEvaluator = (function partialEvaluator() {
       return result;
     },
 
-    extractWidths: function partialEvaluatorWidths(dict,
+    extractWidths: function PartialEvaluator_extractWidths(dict,
                                                    xref,
                                                    descriptor,
                                                    properties) {
       var glyphsWidths = [];
       var defaultWidth = 0;
       if (properties.composite) {
-        defaultWidth = xref.fetchIfRef(dict.get('DW')) || 1000;
+        defaultWidth = dict.get('DW') || 1000;
 
-        var widths = xref.fetchIfRef(dict.get('W'));
+        var widths = dict.get('W');
         if (widths) {
           var start = 0, end = 0;
           for (var i = 0, ii = widths.length; i < ii; i++) {
@@ -11613,7 +13176,7 @@ var PartialEvaluator = (function partialEvaluator() {
         }
       } else {
         var firstChar = properties.firstChar;
-        var widths = xref.fetchIfRef(dict.get('Widths'));
+        var widths = dict.get('Widths');
         if (widths) {
           var j = firstChar;
           for (var i = 0, ii = widths.length; i < ii; i++)
@@ -11635,7 +13198,7 @@ var PartialEvaluator = (function partialEvaluator() {
       properties.widths = glyphsWidths;
     },
 
-    getBaseFontMetrics: function getBaseFontMetrics(name) {
+    getBaseFontMetrics: function PartialEvaluator_getBaseFontMetrics(name) {
       var defaultWidth = 0, widths = [];
       var glyphWidths = Metrics[stdFontMap[name] || name];
       if (isNum(glyphWidths)) {
@@ -11650,8 +13213,10 @@ var PartialEvaluator = (function partialEvaluator() {
       };
     },
 
-    translateFont: function partialEvaluatorTranslateFont(dict, xref, resources,
-                                                          dependency) {
+    translateFont: function PartialEvaluator_translateFont(dict,
+                                                           xref,
+                                                           resources,
+                                                           dependency) {
       var baseDict = dict;
       var type = dict.get('Subtype');
       assertWellFormed(isName(type), 'invalid font Subtype');
@@ -11666,10 +13231,7 @@ var PartialEvaluator = (function partialEvaluator() {
         if (!df)
           return null;
 
-        if (isRef(df))
-          df = xref.fetch(df);
-
-        dict = xref.fetchIfRef(isRef(df) ? df : df[0]);
+        dict = isArray(df) ? xref.fetchIfRef(df[0]) : df;
 
         type = dict.get('Subtype');
         assertWellFormed(isName(type), 'invalid font Subtype');
@@ -11677,7 +13239,7 @@ var PartialEvaluator = (function partialEvaluator() {
       }
       var maxCharIndex = composite ? 0xFFFF : 0xFF;
 
-      var descriptor = xref.fetchIfRef(dict.get('FontDescriptor'));
+      var descriptor = dict.get('FontDescriptor');
       if (!descriptor) {
         if (type.name == 'Type3') {
           // FontDescriptor is only required for Type3 fonts when the document
@@ -11696,10 +13258,18 @@ var PartialEvaluator = (function partialEvaluator() {
           baseFontName = baseFontName.name.replace(/[,_]/g, '-');
           var metrics = this.getBaseFontMetrics(baseFontName);
 
+          // Simulating descriptor flags attribute
+          var fontNameWoStyle = baseFontName.split('-')[0];
+          var flags = (serifFonts[fontNameWoStyle] ||
+            (fontNameWoStyle.search(/serif/gi) != -1) ? FontFlags.Serif : 0) |
+            (symbolsFonts[fontNameWoStyle] ? FontFlags.Symbolic :
+            FontFlags.Nonsymbolic);
+
           var properties = {
             type: type.name,
             widths: metrics.widths,
             defaultWidth: metrics.defaultWidth,
+            flags: flags,
             firstChar: 0,
             lastChar: maxCharIndex
           };
@@ -11711,34 +13281,31 @@ var PartialEvaluator = (function partialEvaluator() {
             properties: properties
           };
         }
-
       }
 
       // According to the spec if 'FontDescriptor' is declared, 'FirstChar',
-      // 'LastChar' and 'Widths' should exists too, but some PDF encoders seems
+      // 'LastChar' and 'Widths' should exist too, but some PDF encoders seem
       // to ignore this rule when a variant of a standart font is used.
       // TODO Fill the width array depending on which of the base font this is
       // a variant.
-      var firstChar = xref.fetchIfRef(dict.get('FirstChar')) || 0;
-      var lastChar = xref.fetchIfRef(dict.get('LastChar')) || maxCharIndex;
-      var fontName = xref.fetchIfRef(descriptor.get('FontName'));
+      var firstChar = dict.get('FirstChar') || 0;
+      var lastChar = dict.get('LastChar') || maxCharIndex;
+      var fontName = descriptor.get('FontName');
+      // Some bad pdf's have a string as the font name.
+      if (isString(fontName))
+        fontName = new Name(fontName);
       assertWellFormed(isName(fontName), 'invalid font name');
 
       var fontFile = descriptor.get('FontFile', 'FontFile2', 'FontFile3');
       if (fontFile) {
-        fontFile = xref.fetchIfRef(fontFile);
         if (fontFile.dict) {
           var subtype = fontFile.dict.get('Subtype');
           if (subtype)
             subtype = subtype.name;
 
           var length1 = fontFile.dict.get('Length1');
-          if (!isInt(length1))
-            length1 = xref.fetchIfRef(length1);
 
           var length2 = fontFile.dict.get('Length2');
-          if (!isInt(length2))
-            length2 = xref.fetchIfRef(length2);
         }
       }
 
@@ -11767,15 +13334,14 @@ var PartialEvaluator = (function partialEvaluator() {
 
       if (type.name === 'Type3') {
         properties.coded = true;
-        var charProcs = xref.fetchIfRef(dict.get('CharProcs'));
-        var fontResources = xref.fetchIfRef(dict.get('Resources')) || resources;
+        var charProcs = dict.get('CharProcs').getAll();
+        var fontResources = dict.get('Resources') || resources;
         properties.resources = fontResources;
-        properties.charProcIRQueues = {};
-        for (var key in charProcs.map) {
-          var glyphStream = xref.fetchIfRef(charProcs.map[key]);
-          var queueObj = {};
-          properties.charProcIRQueues[key] =
-            this.getIRQueue(glyphStream, fontResources, queueObj, dependency);
+        properties.charProcOperatorList = {};
+        for (var key in charProcs) {
+          var glyphStream = charProcs[key];
+          properties.charProcOperatorList[key] =
+            this.getOperatorList(glyphStream, fontResources, dependency);
         }
       }
 
@@ -11788,11 +13354,11 @@ var PartialEvaluator = (function partialEvaluator() {
     }
   };
 
-  return constructor;
+  return PartialEvaluator;
 })();
 
-var EvalState = (function evalState() {
-  function constructor() {
+var EvalState = (function EvalStateClosure() {
+  function EvalState() {
     // Are soft masks and alpha values shapes or opacities?
     this.alphaIsShape = false;
     this.fontSize = 0;
@@ -11809,9 +13375,9 @@ var EvalState = (function evalState() {
     this.fillColorSpace = null;
     this.strokeColorSpace = null;
   }
-  constructor.prototype = {
+  EvalState.prototype = {
   };
-  return constructor;
+  return EvalState;
 })();
 
 /* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
@@ -11819,8 +13385,6 @@ var EvalState = (function evalState() {
 
 'use strict';
 
-var isWorker = (typeof window == 'undefined');
-
 /**
  * Maximum time to wait for a font to be loaded by font-face rules.
  */
@@ -11829,6 +13393,7 @@ var kMaxWaitForFontFace = 1000;
 // Unicode Private Use Area
 var kCmapGlyphOffset = 0xE000;
 var kSizeOfGlyphArea = 0x1900;
+var kSymbolicFontGlyphOffset = 0xF000;
 
 // PDF Glyph Space Units are one Thousandth of a TextSpace Unit
 // except for Type 3 fonts
@@ -11837,269 +13402,253 @@ var kPDFGlyphSpaceUnits = 1000;
 // Until hinting is fully supported this constant can be used
 var kHintingEnabled = false;
 
+var FontFlags = {
+  FixedPitch: 1,
+  Serif: 2,
+  Symbolic: 4,
+  Script: 8,
+  Nonsymbolic: 32,
+  Italic: 64,
+  AllCap: 65536,
+  SmallCap: 131072,
+  ForceBold: 262144
+};
+
 var Encodings = {
-  get ExpertEncoding() {
-    return shadow(this, 'ExpertEncoding', ['', '', '', '', '', '', '', '', '',
-      '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '',
-      '', '', '', '', '', 'space', 'exclamsmall', 'Hungarumlautsmall', '',
-      'dollaroldstyle', 'dollarsuperior', 'ampersandsmall', 'Acutesmall',
-      'parenleftsuperior', 'parenrightsuperior', 'twodotenleader',
-      'onedotenleader', 'comma', 'hyphen', 'period', 'fraction',
-      'zerooldstyle', 'oneoldstyle', 'twooldstyle', 'threeoldstyle',
-      'fouroldstyle', 'fiveoldstyle', 'sixoldstyle', 'sevenoldstyle',
-      'eightoldstyle', 'nineoldstyle', 'colon', 'semicolon', 'commasuperior',
-      'threequartersemdash', 'periodsuperior', 'questionsmall', '',
-      'asuperior', 'bsuperior', 'centsuperior', 'dsuperior', 'esuperior', '',
-      '', 'isuperior', '', '', 'lsuperior', 'msuperior', 'nsuperior',
-      'osuperior', '', '', 'rsuperior', 'ssuperior', 'tsuperior', '', 'ff',
-      'fi', 'fl', 'ffi', 'ffl', 'parenleftinferior', '', 'parenrightinferior',
-      'Circumflexsmall', 'hyphensuperior', 'Gravesmall', 'Asmall', 'Bsmall',
-      'Csmall', 'Dsmall', 'Esmall', 'Fsmall', 'Gsmall', 'Hsmall', 'Ismall',
-      'Jsmall', 'Ksmall', 'Lsmall', 'Msmall', 'Nsmall', 'Osmall', 'Psmall',
-      'Qsmall', 'Rsmall', 'Ssmall', 'Tsmall', 'Usmall', 'Vsmall', 'Wsmall',
-      'Xsmall', 'Ysmall', 'Zsmall', 'colonmonetary', 'onefitted', 'rupiah',
-      'Tildesmall', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '',
-      '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '',
-      '', 'exclamdownsmall', 'centoldstyle', 'Lslashsmall', '', '',
-      'Scaronsmall', 'Zcaronsmall', 'Dieresissmall', 'Brevesmall',
-      'Caronsmall', '', 'Dotaccentsmall', '', '', 'Macronsmall', '', '',
-      'figuredash', 'hypheninferior', '', '', 'Ogoneksmall', 'Ringsmall',
-      'Cedillasmall', '', '', '', 'onequarter', 'onehalf', 'threequarters',
-      'questiondownsmall', 'oneeighth', 'threeeighths', 'fiveeighths',
-      'seveneighths', 'onethird', 'twothirds', '', '', 'zerosuperior',
-      'onesuperior', 'twosuperior', 'threesuperior', 'foursuperior',
-      'fivesuperior', 'sixsuperior', 'sevensuperior', 'eightsuperior',
-      'ninesuperior', 'zeroinferior', 'oneinferior', 'twoinferior',
-      'threeinferior', 'fourinferior', 'fiveinferior', 'sixinferior',
-      'seveninferior', 'eightinferior', 'nineinferior', 'centinferior',
-      'dollarinferior', 'periodinferior', 'commainferior', 'Agravesmall',
-      'Aacutesmall', 'Acircumflexsmall', 'Atildesmall', 'Adieresissmall',
-      'Aringsmall', 'AEsmall', 'Ccedillasmall', 'Egravesmall', 'Eacutesmall',
-      'Ecircumflexsmall', 'Edieresissmall', 'Igravesmall', 'Iacutesmall',
-      'Icircumflexsmall', 'Idieresissmall', 'Ethsmall', 'Ntildesmall',
-      'Ogravesmall', 'Oacutesmall', 'Ocircumflexsmall', 'Otildesmall',
-      'Odieresissmall', 'OEsmall', 'Oslashsmall', 'Ugravesmall', 'Uacutesmall',
-      'Ucircumflexsmall', 'Udieresissmall', 'Yacutesmall', 'Thornsmall',
-      'Ydieresissmall'
-    ]);
-  },
-  get MacExpertEncoding() {
-    return shadow(this, 'MacExpertEncoding', ['', '', '', '', '', '', '', '',
-      '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '',
-      '', '', '', '', '', '', 'space', 'exclamsmall', 'Hungarumlautsmall',
-      'centoldstyle', 'dollaroldstyle', 'dollarsuperior', 'ampersandsmall',
-      'Acutesmall', 'parenleftsuperior', 'parenrightsuperior',
-      'twodotenleader', 'onedotenleader', 'comma', 'hyphen', 'period',
-      'fraction', 'zerooldstyle', 'oneoldstyle', 'twooldstyle',
-      'threeoldstyle', 'fouroldstyle', 'fiveoldstyle', 'sixoldstyle',
-      'sevenoldstyle', 'eightoldstyle', 'nineoldstyle', 'colon', 'semicolon',
-      '', 'threequartersemdash', '', 'questionsmall', '', '', '', '',
-      'Ethsmall', '', '', 'onequarter', 'onehalf', 'threequarters',
-      'oneeighth', 'threeeighths', 'fiveeighths', 'seveneighths', 'onethird',
-      'twothirds', '', '', '', '', '', '', 'ff', 'fi', 'fl', 'ffi', 'ffl',
-      'parenleftinferior', '', 'parenrightinferior', 'Circumflexsmall',
-      'hypheninferior', 'Gravesmall', 'Asmall', 'Bsmall', 'Csmall', 'Dsmall',
-      'Esmall', 'Fsmall', 'Gsmall', 'Hsmall', 'Ismall', 'Jsmall', 'Ksmall',
-      'Lsmall', 'Msmall', 'Nsmall', 'Osmall', 'Psmall', 'Qsmall', 'Rsmall',
-      'Ssmall', 'Tsmall', 'Usmall', 'Vsmall', 'Wsmall', 'Xsmall', 'Ysmall',
-      'Zsmall', 'colonmonetary', 'onefitted', 'rupiah', 'Tildesmall', '', '',
-      'asuperior', 'centsuperior', '', '', '', '', 'Aacutesmall',
-      'Agravesmall', 'Acircumflexsmall', 'Adieresissmall', 'Atildesmall',
-      'Aringsmall', 'Ccedillasmall', 'Eacutesmall', 'Egravesmall',
-      'Ecircumflexsmall', 'Edieresissmall', 'Iacutesmall', 'Igravesmall',
-      'Icircumflexsmall', 'Idieresissmall', 'Ntildesmall', 'Oacutesmall',
-      'Ogravesmall', 'Ocircumflexsmall', 'Odieresissmall', 'Otildesmall',
-      'Uacutesmall', 'Ugravesmall', 'Ucircumflexsmall', 'Udieresissmall', '',
-      'eightsuperior', 'fourinferior', 'threeinferior', 'sixinferior',
-      'eightinferior', 'seveninferior', 'Scaronsmall', '', 'centinferior',
-      'twoinferior', '', 'Dieresissmall', '', 'Caronsmall', 'osuperior',
-      'fiveinferior', '', 'commainferior', 'periodinferior', 'Yacutesmall', '',
-      'dollarinferior', '', 'Thornsmall', '', 'nineinferior', 'zeroinferior',
-      'Zcaronsmall', 'AEsmall', 'Oslashsmall', 'questiondownsmall',
-      'oneinferior', 'Lslashsmall', '', '', '', '', '', '', 'Cedillasmall', '',
-      '', '', '', '', 'OEsmall', 'figuredash', 'hyphensuperior', '', '', '',
-      '', 'exclamdownsmall', '', 'Ydieresissmall', '', 'onesuperior',
-      'twosuperior', 'threesuperior', 'foursuperior', 'fivesuperior',
-      'sixsuperior', 'sevensuperior', 'ninesuperior', 'zerosuperior', '',
-      'esuperior', 'rsuperior', 'tsuperior', '', '', 'isuperior', 'ssuperior',
-      'dsuperior', '', '', '', '', '', 'lsuperior', 'Ogoneksmall',
-      'Brevesmall', 'Macronsmall', 'bsuperior', 'nsuperior', 'msuperior',
-      'commasuperior', 'periodsuperior', 'Dotaccentsmall', 'Ringsmall'
-    ]);
-  },
-  get MacRomanEncoding() {
-    return shadow(this, 'MacRomanEncoding', ['', '', '', '', '', '', '', '',
-      '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '',
-      '', '', '', '', '', '', 'space', 'exclam', 'quotedbl', 'numbersign',
-      'dollar', 'percent', 'ampersand', 'quotesingle', 'parenleft',
-      'parenright', 'asterisk', 'plus', 'comma', 'hyphen', 'period', 'slash',
-      'zero', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight',
-      'nine', 'colon', 'semicolon', 'less', 'equal', 'greater', 'question',
-      'at', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
-      'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
-      'bracketleft', 'backslash', 'bracketright', 'asciicircum', 'underscore',
-      'grave', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
-      'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
-      'braceleft', 'bar', 'braceright', 'asciitilde', '', 'Adieresis', 'Aring',
-      'Ccedilla', 'Eacute', 'Ntilde', 'Odieresis', 'Udieresis', 'aacute',
-      'agrave', 'acircumflex', 'adieresis', 'atilde', 'aring', 'ccedilla',
-      'eacute', 'egrave', 'ecircumflex', 'edieresis', 'iacute', 'igrave',
-      'icircumflex', 'idieresis', 'ntilde', 'oacute', 'ograve', 'ocircumflex',
-      'odieresis', 'otilde', 'uacute', 'ugrave', 'ucircumflex', 'udieresis',
-      'dagger', 'degree', 'cent', 'sterling', 'section', 'bullet', 'paragraph',
-      'germandbls', 'registered', 'copyright', 'trademark', 'acute',
-      'dieresis', 'notequal', 'AE', 'Oslash', 'infinity', 'plusminus',
-      'lessequal', 'greaterequal', 'yen', 'mu', 'partialdiff', 'summation',
-      'product', 'pi', 'integral', 'ordfeminine', 'ordmasculine', 'Omega',
-      'ae', 'oslash', 'questiondown', 'exclamdown', 'logicalnot', 'radical',
-      'florin', 'approxequal', 'Delta', 'guillemotleft', 'guillemotright',
-      'ellipsis', 'space', 'Agrave', 'Atilde', 'Otilde', 'OE', 'oe', 'endash',
-      'emdash', 'quotedblleft', 'quotedblright', 'quoteleft', 'quoteright',
-      'divide', 'lozenge', 'ydieresis', 'Ydieresis', 'fraction', 'currency',
-      'guilsinglleft', 'guilsinglright', 'fi', 'fl', 'daggerdbl',
-      'periodcentered', 'quotesinglbase', 'quotedblbase', 'perthousand',
-      'Acircumflex', 'Ecircumflex', 'Aacute', 'Edieresis', 'Egrave', 'Iacute',
-      'Icircumflex', 'Idieresis', 'Igrave', 'Oacute', 'Ocircumflex', 'apple',
-      'Ograve', 'Uacute', 'Ucircumflex', 'Ugrave', 'dotlessi', 'circumflex',
-      'tilde', 'macron', 'breve', 'dotaccent', 'ring', 'cedilla',
-      'hungarumlaut', 'ogonek', 'caron'
-    ]);
-  },
-  get StandardEncoding() {
-    return shadow(this, 'StandardEncoding', ['', '', '', '', '', '', '', '',
-      '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '',
-      '', '', '', '', '', '', 'space', 'exclam', 'quotedbl', 'numbersign',
-      'dollar', 'percent', 'ampersand', 'quoteright', 'parenleft',
-      'parenright', 'asterisk', 'plus', 'comma', 'hyphen', 'period', 'slash',
-      'zero', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight',
-      'nine', 'colon', 'semicolon', 'less', 'equal', 'greater', 'question',
-      'at', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
-      'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
-      'bracketleft', 'backslash', 'bracketright', 'asciicircum', 'underscore',
-      'quoteleft', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l',
-      'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
-      'braceleft', 'bar', 'braceright', 'asciitilde', '', '', 'exclamdown',
-      'cent', 'sterling', 'fraction', 'yen', 'florin', 'section', 'currency',
-      'quotesingle', 'quotedblleft', 'guillemotleft', 'guilsinglleft',
-      'guilsinglright', 'fi', 'fl', '', 'endash', 'dagger', 'daggerdbl',
-      'periodcentered', '', 'paragraph', 'bullet', 'quotesinglbase',
-      'quotedblbase', 'quotedblright', 'guillemotright', 'ellipsis',
-      'perthousand', '', 'questiondown', '', 'grave', 'acute', 'circumflex',
-      'tilde', 'macron', 'breve', 'dotaccent', 'dieresis', '', 'ring',
-      'cedilla', '', 'hungarumlaut', 'ogonek', 'caron', 'emdash', '', '', '',
-      '', '', '', '', '', '', '', '', '', '', '', '', '', 'AE', '',
-      'ordfeminine', '', '', '', '', 'Lslash', 'Oslash', 'OE', 'ordmasculine',
-      '', '', '', '', '', 'ae', '', '', '', 'dotlessi', '', '', 'lslash',
-      'oslash', 'oe', 'germandbls'
-    ]);
-  },
-  get WinAnsiEncoding() {
-    return shadow(this, 'WinAnsiEncoding', ['', '', '', '', '', '', '', '', '',
-      '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '',
-      '', '', '', '', '', 'space', 'exclam', 'quotedbl', 'numbersign',
-      'dollar', 'percent', 'ampersand', 'quotesingle', 'parenleft',
-      'parenright', 'asterisk', 'plus', 'comma', 'hyphen', 'period', 'slash',
-      'zero', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight',
-      'nine', 'colon', 'semicolon', 'less', 'equal', 'greater', 'question',
-      'at', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
-      'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
-      'bracketleft', 'backslash', 'bracketright', 'asciicircum', 'underscore',
-      'grave', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
-      'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
-      'braceleft', 'bar', 'braceright', 'asciitilde', 'bullet', 'Euro',
-      'bullet', 'quotesinglbase', 'florin', 'quotedblbase', 'ellipsis',
-      'dagger', 'daggerdbl', 'circumflex', 'perthousand', 'Scaron',
-      'guilsinglleft', 'OE', 'bullet', 'Zcaron', 'bullet', 'bullet',
-      'quoteleft', 'quoteright', 'quotedblleft', 'quotedblright', 'bullet',
-      'endash', 'emdash', 'tilde', 'trademark', 'scaron', 'guilsinglright',
-      'oe', 'bullet', 'zcaron', 'Ydieresis', 'space', 'exclamdown', 'cent',
-      'sterling', 'currency', 'yen', 'brokenbar', 'section', 'dieresis',
-      'copyright', 'ordfeminine', 'guillemotleft', 'logicalnot', 'hyphen',
-      'registered', 'macron', 'degree', 'plusminus', 'twosuperior',
-      'threesuperior', 'acute', 'mu', 'paragraph', 'periodcentered',
-      'cedilla', 'onesuperior', 'ordmasculine', 'guillemotright', 'onequarter',
-      'onehalf', 'threequarters', 'questiondown', 'Agrave', 'Aacute',
-      'Acircumflex', 'Atilde', 'Adieresis', 'Aring', 'AE', 'Ccedilla',
-      'Egrave', 'Eacute', 'Ecircumflex', 'Edieresis', 'Igrave', 'Iacute',
-      'Icircumflex', 'Idieresis', 'Eth', 'Ntilde', 'Ograve', 'Oacute',
-      'Ocircumflex', 'Otilde', 'Odieresis', 'multiply', 'Oslash', 'Ugrave',
-      'Uacute', 'Ucircumflex', 'Udieresis', 'Yacute', 'Thorn', 'germandbls',
-      'agrave', 'aacute', 'acircumflex', 'atilde', 'adieresis', 'aring', 'ae',
-      'ccedilla', 'egrave', 'eacute', 'ecircumflex', 'edieresis', 'igrave',
-      'iacute', 'icircumflex', 'idieresis', 'eth', 'ntilde', 'ograve',
-      'oacute', 'ocircumflex', 'otilde', 'odieresis', 'divide', 'oslash',
-      'ugrave', 'uacute', 'ucircumflex', 'udieresis', 'yacute', 'thorn',
-      'ydieresis'
-    ]);
-  },
-  get symbolsEncoding() {
-    return shadow(this, 'symbolsEncoding', ['', '', '', '', '', '', '', '', '',
-      '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '',
-      '', '', '', '', '', 'space', 'exclam', 'universal', 'numbersign',
-      'existential', 'percent', 'ampersand', 'suchthat', 'parenleft',
-      'parenright', 'asteriskmath', 'plus', 'comma', 'minus', 'period',
-      'slash', 'zero', 'one', 'two', 'three', 'four', 'five', 'six', 'seven',
-      'eight', 'nine', 'colon', 'semicolon', 'less', 'equal', 'greater',
-      'question', 'congruent', 'Alpha', 'Beta', 'Chi', 'Delta', 'Epsilon',
-      'Phi', 'Gamma', 'Eta', 'Iota', 'theta1', 'Kappa', 'Lambda', 'Mu', 'Nu',
-      'Omicron', 'Pi', 'Theta', 'Rho', 'Sigma', 'Tau', 'Upsilon', 'sigma1',
-      'Omega', 'Xi', 'Psi', 'Zeta', 'bracketleft', 'therefore', 'bracketright',
-      'perpendicular', 'underscore', 'radicalex', 'alpha', 'beta', 'chi',
-      'delta', 'epsilon', 'phi', 'gamma', 'eta', 'iota', 'phi1', 'kappa',
-      'lambda', 'mu', 'nu', 'omicron', 'pi', 'theta', 'rho', 'sigma', 'tau',
-      'upsilon', 'omega1', 'omega', 'xi', 'psi', 'zeta', 'braceleft', 'bar',
-      'braceright', 'similar', '', '', '', '', '', '', '', '', '', '', '', '',
-      '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '',
-      '', '', '', 'Euro', 'Upsilon1', 'minute', 'lessequal', 'fraction',
-      'infinity', 'florin', 'club', 'diamond', 'heart', 'spade', 'arrowboth',
-      'arrowleft', 'arrowup', 'arrowright', 'arrowdown', 'degree', 'plusminus',
-      'second', 'greaterequal', 'multiply', 'proportional', 'partialdiff',
-      'bullet', 'divide', 'notequal', 'equivalence', 'approxequal', 'ellipsis',
-      'arrowvertex', 'arrowhorizex', 'carriagereturn', 'aleph', 'Ifraktur',
-      'Rfraktur', 'weierstrass', 'circlemultiply', 'circleplus', 'emptyset',
-      'intersection', 'union', 'propersuperset', 'reflexsuperset', 'notsubset',
-      'propersubset', 'reflexsubset', 'element', 'notelement', 'angle',
-      'gradient', 'registerserif', 'copyrightserif', 'trademarkserif',
-      'product', 'radical', 'dotmath', 'logicalnot', 'logicaland', 'logicalor',
-      'arrowdblboth', 'arrowdblleft', 'arrowdblup', 'arrowdblright',
-      'arrowdbldown', 'lozenge', 'angleleft', 'registersans', 'copyrightsans',
-      'trademarksans', 'summation', 'parenlefttp', 'parenleftex',
-      'parenleftbt', 'bracketlefttp', 'bracketleftex', 'bracketleftbt',
-      'bracelefttp', 'braceleftmid', 'braceleftbt', 'braceex', '',
-      'angleright', 'integral', 'integraltp', 'integralex', 'integralbt',
-      'parenrighttp', 'parenrightex', 'parenrightbt', 'bracketrighttp',
-      'bracketrightex', 'bracketrightbt', 'bracerighttp', 'bracerightmid',
-      'bracerightbt'
-    ]);
-  },
-  get zapfDingbatsEncoding() {
-    return shadow(this, 'zapfDingbatsEncoding', ['', '', '', '', '', '', '',
-      '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '',
-      '', '', '', '', '', '', '', 'space', 'a1', 'a2', 'a202', 'a3', 'a4',
-      'a5', 'a119', 'a118', 'a117', 'a11', 'a12', 'a13', 'a14', 'a15', 'a16',
-      'a105', 'a17', 'a18', 'a19', 'a20', 'a21', 'a22', 'a23', 'a24', 'a25',
-      'a26', 'a27', 'a28', 'a6', 'a7', 'a8', 'a9', 'a10', 'a29', 'a30', 'a31',
-      'a32', 'a33', 'a34', 'a35', 'a36', 'a37', 'a38', 'a39', 'a40', 'a41',
-      'a42', 'a43', 'a44', 'a45', 'a46', 'a47', 'a48', 'a49', 'a50', 'a51',
-      'a52', 'a53', 'a54', 'a55', 'a56', 'a57', 'a58', 'a59', 'a60', 'a61',
-      'a62', 'a63', 'a64', 'a65', 'a66', 'a67', 'a68', 'a69', 'a70', 'a71',
-      'a72', 'a73', 'a74', 'a203', 'a75', 'a204', 'a76', 'a77', 'a78', 'a79',
-      'a81', 'a82', 'a83', 'a84', 'a97', 'a98', 'a99', 'a100', '', '', '', '',
-      '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '',
-      '', '', '', '', '', '', '', '', '', '', '', '', 'a101', 'a102', 'a103',
-      'a104', 'a106', 'a107', 'a108', 'a112', 'a111', 'a110', 'a109', 'a120',
-      'a121', 'a122', 'a123', 'a124', 'a125', 'a126', 'a127', 'a128', 'a129',
-      'a130', 'a131', 'a132', 'a133', 'a134', 'a135', 'a136', 'a137', 'a138',
-      'a139', 'a140', 'a141', 'a142', 'a143', 'a144', 'a145', 'a146', 'a147',
-      'a148', 'a149', 'a150', 'a151', 'a152', 'a153', 'a154', 'a155', 'a156',
-      'a157', 'a158', 'a159', 'a160', 'a161', 'a163', 'a164', 'a196', 'a165',
-      'a192', 'a166', 'a167', 'a168', 'a169', 'a170', 'a171', 'a172', 'a173',
-      'a162', 'a174', 'a175', 'a176', 'a177', 'a178', 'a179', 'a193', 'a180',
-      'a199', 'a181', 'a200', 'a182', '', 'a201', 'a183', 'a184', 'a197',
-      'a185', 'a194', 'a198', 'a186', 'a195', 'a187', 'a188', 'a189', 'a190',
-      'a191'
-    ]);
-  }
+  ExpertEncoding: ['', '', '', '', '', '', '', '', '', '', '', '', '', '', '',
+    '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '',
+    'space', 'exclamsmall', 'Hungarumlautsmall', '', 'dollaroldstyle',
+    'dollarsuperior', 'ampersandsmall', 'Acutesmall', 'parenleftsuperior',
+    'parenrightsuperior', 'twodotenleader', 'onedotenleader', 'comma',
+    'hyphen', 'period', 'fraction', 'zerooldstyle', 'oneoldstyle',
+    'twooldstyle', 'threeoldstyle', 'fouroldstyle', 'fiveoldstyle',
+    'sixoldstyle', 'sevenoldstyle', 'eightoldstyle', 'nineoldstyle', 'colon',
+    'semicolon', 'commasuperior', 'threequartersemdash', 'periodsuperior',
+    'questionsmall', '', 'asuperior', 'bsuperior', 'centsuperior', 'dsuperior',
+    'esuperior', '', '', 'isuperior', '', '', 'lsuperior', 'msuperior',
+    'nsuperior', 'osuperior', '', '', 'rsuperior', 'ssuperior', 'tsuperior',
+    '', 'ff', 'fi', 'fl', 'ffi', 'ffl', 'parenleftinferior', '',
+    'parenrightinferior', 'Circumflexsmall', 'hyphensuperior', 'Gravesmall',
+    'Asmall', 'Bsmall', 'Csmall', 'Dsmall', 'Esmall', 'Fsmall', 'Gsmall',
+    'Hsmall', 'Ismall', 'Jsmall', 'Ksmall', 'Lsmall', 'Msmall', 'Nsmall',
+    'Osmall', 'Psmall', 'Qsmall', 'Rsmall', 'Ssmall', 'Tsmall', 'Usmall',
+    'Vsmall', 'Wsmall', 'Xsmall', 'Ysmall', 'Zsmall', 'colonmonetary',
+    'onefitted', 'rupiah', 'Tildesmall', '', '', '', '', '', '', '', '', '',
+    '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '',
+    '', '', '', '', '', '', 'exclamdownsmall', 'centoldstyle', 'Lslashsmall',
+    '', '', 'Scaronsmall', 'Zcaronsmall', 'Dieresissmall', 'Brevesmall',
+    'Caronsmall', '', 'Dotaccentsmall', '', '', 'Macronsmall', '', '',
+    'figuredash', 'hypheninferior', '', '', 'Ogoneksmall', 'Ringsmall',
+    'Cedillasmall', '', '', '', 'onequarter', 'onehalf', 'threequarters',
+    'questiondownsmall', 'oneeighth', 'threeeighths', 'fiveeighths',
+    'seveneighths', 'onethird', 'twothirds', '', '', 'zerosuperior',
+    'onesuperior', 'twosuperior', 'threesuperior', 'foursuperior',
+    'fivesuperior', 'sixsuperior', 'sevensuperior', 'eightsuperior',
+    'ninesuperior', 'zeroinferior', 'oneinferior', 'twoinferior',
+    'threeinferior', 'fourinferior', 'fiveinferior', 'sixinferior',
+    'seveninferior', 'eightinferior', 'nineinferior', 'centinferior',
+    'dollarinferior', 'periodinferior', 'commainferior', 'Agravesmall',
+    'Aacutesmall', 'Acircumflexsmall', 'Atildesmall', 'Adieresissmall',
+    'Aringsmall', 'AEsmall', 'Ccedillasmall', 'Egravesmall', 'Eacutesmall',
+    'Ecircumflexsmall', 'Edieresissmall', 'Igravesmall', 'Iacutesmall',
+    'Icircumflexsmall', 'Idieresissmall', 'Ethsmall', 'Ntildesmall',
+    'Ogravesmall', 'Oacutesmall', 'Ocircumflexsmall', 'Otildesmall',
+    'Odieresissmall', 'OEsmall', 'Oslashsmall', 'Ugravesmall', 'Uacutesmall',
+    'Ucircumflexsmall', 'Udieresissmall', 'Yacutesmall', 'Thornsmall',
+    'Ydieresissmall'],
+  MacExpertEncoding: ['', '', '', '', '', '', '', '', '', '', '', '', '', '',
+    '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '',
+    'space', 'exclamsmall', 'Hungarumlautsmall', 'centoldstyle',
+    'dollaroldstyle', 'dollarsuperior', 'ampersandsmall', 'Acutesmall',
+    'parenleftsuperior', 'parenrightsuperior', 'twodotenleader',
+    'onedotenleader', 'comma', 'hyphen', 'period', 'fraction', 'zerooldstyle',
+    'oneoldstyle', 'twooldstyle', 'threeoldstyle', 'fouroldstyle',
+    'fiveoldstyle', 'sixoldstyle', 'sevenoldstyle', 'eightoldstyle',
+    'nineoldstyle', 'colon', 'semicolon', '', 'threequartersemdash', '',
+    'questionsmall', '', '', '', '', 'Ethsmall', '', '', 'onequarter',
+    'onehalf', 'threequarters', 'oneeighth', 'threeeighths', 'fiveeighths',
+    'seveneighths', 'onethird', 'twothirds', '', '', '', '', '', '', 'ff',
+    'fi', 'fl', 'ffi', 'ffl', 'parenleftinferior', '', 'parenrightinferior',
+    'Circumflexsmall', 'hypheninferior', 'Gravesmall', 'Asmall', 'Bsmall',
+    'Csmall', 'Dsmall', 'Esmall', 'Fsmall', 'Gsmall', 'Hsmall', 'Ismall',
+    'Jsmall', 'Ksmall', 'Lsmall', 'Msmall', 'Nsmall', 'Osmall', 'Psmall',
+    'Qsmall', 'Rsmall', 'Ssmall', 'Tsmall', 'Usmall', 'Vsmall', 'Wsmall',
+    'Xsmall', 'Ysmall', 'Zsmall', 'colonmonetary', 'onefitted', 'rupiah',
+    'Tildesmall', '', '', 'asuperior', 'centsuperior', '', '', '', '',
+    'Aacutesmall', 'Agravesmall', 'Acircumflexsmall', 'Adieresissmall',
+    'Atildesmall', 'Aringsmall', 'Ccedillasmall', 'Eacutesmall', 'Egravesmall',
+    'Ecircumflexsmall', 'Edieresissmall', 'Iacutesmall', 'Igravesmall',
+    'Icircumflexsmall', 'Idieresissmall', 'Ntildesmall', 'Oacutesmall',
+    'Ogravesmall', 'Ocircumflexsmall', 'Odieresissmall', 'Otildesmall',
+    'Uacutesmall', 'Ugravesmall', 'Ucircumflexsmall', 'Udieresissmall', '',
+    'eightsuperior', 'fourinferior', 'threeinferior', 'sixinferior',
+    'eightinferior', 'seveninferior', 'Scaronsmall', '', 'centinferior',
+    'twoinferior', '', 'Dieresissmall', '', 'Caronsmall', 'osuperior',
+    'fiveinferior', '', 'commainferior', 'periodinferior', 'Yacutesmall', '',
+    'dollarinferior', '', 'Thornsmall', '', 'nineinferior', 'zeroinferior',
+    'Zcaronsmall', 'AEsmall', 'Oslashsmall', 'questiondownsmall',
+    'oneinferior', 'Lslashsmall', '', '', '', '', '', '', 'Cedillasmall', '',
+    '', '', '', '', 'OEsmall', 'figuredash', 'hyphensuperior', '', '', '', '',
+    'exclamdownsmall', '', 'Ydieresissmall', '', 'onesuperior', 'twosuperior',
+    'threesuperior', 'foursuperior', 'fivesuperior', 'sixsuperior',
+    'sevensuperior', 'ninesuperior', 'zerosuperior', '', 'esuperior',
+    'rsuperior', 'tsuperior', '', '', 'isuperior', 'ssuperior', 'dsuperior',
+    '', '', '', '', '', 'lsuperior', 'Ogoneksmall', 'Brevesmall',
+    'Macronsmall', 'bsuperior', 'nsuperior', 'msuperior', 'commasuperior',
+    'periodsuperior', 'Dotaccentsmall', 'Ringsmall'],
+  MacRomanEncoding: ['', '', '', '', '', '', '', '', '', '', '', '', '', '', '',
+    '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '',
+    'space', 'exclam', 'quotedbl', 'numbersign', 'dollar', 'percent',
+    'ampersand', 'quotesingle', 'parenleft', 'parenright', 'asterisk', 'plus',
+    'comma', 'hyphen', 'period', 'slash', 'zero', 'one', 'two', 'three',
+    'four', 'five', 'six', 'seven', 'eight', 'nine', 'colon', 'semicolon',
+    'less', 'equal', 'greater', 'question', 'at', 'A', 'B', 'C', 'D', 'E', 'F',
+    'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U',
+    'V', 'W', 'X', 'Y', 'Z', 'bracketleft', 'backslash', 'bracketright',
+    'asciicircum', 'underscore', 'grave', 'a', 'b', 'c', 'd', 'e', 'f', 'g',
+    'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
+    'w', 'x', 'y', 'z', 'braceleft', 'bar', 'braceright', 'asciitilde', '',
+    'Adieresis', 'Aring', 'Ccedilla', 'Eacute', 'Ntilde', 'Odieresis',
+    'Udieresis', 'aacute', 'agrave', 'acircumflex', 'adieresis', 'atilde',
+    'aring', 'ccedilla', 'eacute', 'egrave', 'ecircumflex', 'edieresis',
+    'iacute', 'igrave', 'icircumflex', 'idieresis', 'ntilde', 'oacute',
+    'ograve', 'ocircumflex', 'odieresis', 'otilde', 'uacute', 'ugrave',
+    'ucircumflex', 'udieresis', 'dagger', 'degree', 'cent', 'sterling',
+    'section', 'bullet', 'paragraph', 'germandbls', 'registered', 'copyright',
+    'trademark', 'acute', 'dieresis', 'notequal', 'AE', 'Oslash', 'infinity',
+    'plusminus', 'lessequal', 'greaterequal', 'yen', 'mu', 'partialdiff',
+    'summation', 'product', 'pi', 'integral', 'ordfeminine', 'ordmasculine',
+    'Omega', 'ae', 'oslash', 'questiondown', 'exclamdown', 'logicalnot',
+    'radical', 'florin', 'approxequal', 'Delta', 'guillemotleft',
+    'guillemotright', 'ellipsis', '', 'Agrave', 'Atilde', 'Otilde', 'OE',
+    'oe', 'endash', 'emdash', 'quotedblleft', 'quotedblright', 'quoteleft',
+    'quoteright', 'divide', 'lozenge', 'ydieresis', 'Ydieresis', 'fraction',
+    'currency', 'guilsinglleft', 'guilsinglright', 'fi', 'fl', 'daggerdbl',
+    'periodcentered', 'quotesinglbase', 'quotedblbase', 'perthousand',
+    'Acircumflex', 'Ecircumflex', 'Aacute', 'Edieresis', 'Egrave', 'Iacute',
+    'Icircumflex', 'Idieresis', 'Igrave', 'Oacute', 'Ocircumflex', 'apple',
+    'Ograve', 'Uacute', 'Ucircumflex', 'Ugrave', 'dotlessi', 'circumflex',
+    'tilde', 'macron', 'breve', 'dotaccent', 'ring', 'cedilla', 'hungarumlaut',
+    'ogonek', 'caron'],
+  StandardEncoding: ['', '', '', '', '', '', '', '', '', '', '', '', '', '', '',
+    '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '',
+    'space', 'exclam', 'quotedbl', 'numbersign', 'dollar', 'percent',
+    'ampersand', 'quoteright', 'parenleft', 'parenright', 'asterisk', 'plus',
+    'comma', 'hyphen', 'period', 'slash', 'zero', 'one', 'two', 'three',
+    'four', 'five', 'six', 'seven', 'eight', 'nine', 'colon', 'semicolon',
+    'less', 'equal', 'greater', 'question', 'at', 'A', 'B', 'C', 'D', 'E', 'F',
+    'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U',
+    'V', 'W', 'X', 'Y', 'Z', 'bracketleft', 'backslash', 'bracketright',
+    'asciicircum', 'underscore', 'quoteleft', 'a', 'b', 'c', 'd', 'e', 'f',
+    'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u',
+    'v', 'w', 'x', 'y', 'z', 'braceleft', 'bar', 'braceright', 'asciitilde',
+    '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '',
+    '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', 'exclamdown',
+    'cent', 'sterling', 'fraction', 'yen', 'florin', 'section', 'currency',
+    'quotesingle', 'quotedblleft', 'guillemotleft', 'guilsinglleft',
+    'guilsinglright', 'fi', 'fl', '', 'endash', 'dagger', 'daggerdbl',
+    'periodcentered', '', 'paragraph', 'bullet', 'quotesinglbase',
+    'quotedblbase', 'quotedblright', 'guillemotright', 'ellipsis',
+    'perthousand', '', 'questiondown', '', 'grave', 'acute', 'circumflex',
+    'tilde', 'macron', 'breve', 'dotaccent', 'dieresis', '', 'ring', 'cedilla',
+    '', 'hungarumlaut', 'ogonek', 'caron', 'emdash', '', '', '', '', '', '',
+    '', '', '', '', '', '', '', '', '', '', 'AE', '', 'ordfeminine', '', '',
+    '', '', 'Lslash', 'Oslash', 'OE', 'ordmasculine', '', '', '', '', '', 'ae',
+    '', '', '', 'dotlessi', '', '', 'lslash', 'oslash', 'oe', 'germandbls'],
+  WinAnsiEncoding: ['', '', '', '', '', '', '', '', '', '', '', '', '', '', '',
+    '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '',
+    'space', 'exclam', 'quotedbl', 'numbersign', 'dollar', 'percent',
+    'ampersand', 'quotesingle', 'parenleft', 'parenright', 'asterisk', 'plus',
+    'comma', 'hyphen', 'period', 'slash', 'zero', 'one', 'two', 'three',
+    'four', 'five', 'six', 'seven', 'eight', 'nine', 'colon', 'semicolon',
+    'less', 'equal', 'greater', 'question', 'at', 'A', 'B', 'C', 'D', 'E', 'F',
+    'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U',
+    'V', 'W', 'X', 'Y', 'Z', 'bracketleft', 'backslash', 'bracketright',
+    'asciicircum', 'underscore', 'grave', 'a', 'b', 'c', 'd', 'e', 'f', 'g',
+    'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
+    'w', 'x', 'y', 'z', 'braceleft', 'bar', 'braceright', 'asciitilde',
+    'bullet', 'Euro', 'bullet', 'quotesinglbase', 'florin', 'quotedblbase',
+    'ellipsis', 'dagger', 'daggerdbl', 'circumflex', 'perthousand', 'Scaron',
+    'guilsinglleft', 'OE', 'bullet', 'Zcaron', 'bullet', 'bullet', 'quoteleft',
+    'quoteright', 'quotedblleft', 'quotedblright', 'bullet', 'endash',
+    'emdash', 'tilde', 'trademark', 'scaron', 'guilsinglright', 'oe', 'bullet',
+    'zcaron', 'Ydieresis', '', 'exclamdown', 'cent', 'sterling',
+    'currency', 'yen', 'brokenbar', 'section', 'dieresis', 'copyright',
+    'ordfeminine', 'guillemotleft', 'logicalnot', 'hyphen', 'registered',
+    'macron', 'degree', 'plusminus', 'twosuperior', 'threesuperior', 'acute',
+    'mu', 'paragraph', 'periodcentered', 'cedilla', 'onesuperior',
+    'ordmasculine', 'guillemotright', 'onequarter', 'onehalf', 'threequarters',
+    'questiondown', 'Agrave', 'Aacute', 'Acircumflex', 'Atilde', 'Adieresis',
+    'Aring', 'AE', 'Ccedilla', 'Egrave', 'Eacute', 'Ecircumflex', 'Edieresis',
+    'Igrave', 'Iacute', 'Icircumflex', 'Idieresis', 'Eth', 'Ntilde', 'Ograve',
+    'Oacute', 'Ocircumflex', 'Otilde', 'Odieresis', 'multiply', 'Oslash',
+    'Ugrave', 'Uacute', 'Ucircumflex', 'Udieresis', 'Yacute', 'Thorn',
+    'germandbls', 'agrave', 'aacute', 'acircumflex', 'atilde', 'adieresis',
+    'aring', 'ae', 'ccedilla', 'egrave', 'eacute', 'ecircumflex', 'edieresis',
+    'igrave', 'iacute', 'icircumflex', 'idieresis', 'eth', 'ntilde', 'ograve',
+    'oacute', 'ocircumflex', 'otilde', 'odieresis', 'divide', 'oslash',
+    'ugrave', 'uacute', 'ucircumflex', 'udieresis', 'yacute', 'thorn',
+    'ydieresis'],
+  symbolsEncoding: ['', '', '', '', '', '', '', '', '', '', '', '', '', '', '',
+    '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '',
+    'space', 'exclam', 'universal', 'numbersign', 'existential', 'percent',
+    'ampersand', 'suchthat', 'parenleft', 'parenright', 'asteriskmath', 'plus',
+    'comma', 'minus', 'period', 'slash', 'zero', 'one', 'two', 'three', 'four',
+    'five', 'six', 'seven', 'eight', 'nine', 'colon', 'semicolon', 'less',
+    'equal', 'greater', 'question', 'congruent', 'Alpha', 'Beta', 'Chi',
+    'Delta', 'Epsilon', 'Phi', 'Gamma', 'Eta', 'Iota', 'theta1', 'Kappa',
+    'Lambda', 'Mu', 'Nu', 'Omicron', 'Pi', 'Theta', 'Rho', 'Sigma', 'Tau',
+    'Upsilon', 'sigma1', 'Omega', 'Xi', 'Psi', 'Zeta', 'bracketleft',
+    'therefore', 'bracketright', 'perpendicular', 'underscore', 'radicalex',
+    'alpha', 'beta', 'chi', 'delta', 'epsilon', 'phi', 'gamma', 'eta', 'iota',
+    'phi1', 'kappa', 'lambda', 'mu', 'nu', 'omicron', 'pi', 'theta', 'rho',
+    'sigma', 'tau', 'upsilon', 'omega1', 'omega', 'xi', 'psi', 'zeta',
+    'braceleft', 'bar', 'braceright', 'similar', '', '', '', '', '', '', '',
+    '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '',
+    '', '', '', '', '', '', '', 'Euro', 'Upsilon1', 'minute', 'lessequal',
+    'fraction', 'infinity', 'florin', 'club', 'diamond', 'heart', 'spade',
+    'arrowboth', 'arrowleft', 'arrowup', 'arrowright', 'arrowdown', 'degree',
+    'plusminus', 'second', 'greaterequal', 'multiply', 'proportional',
+    'partialdiff', 'bullet', 'divide', 'notequal', 'equivalence',
+    'approxequal', 'ellipsis', 'arrowvertex', 'arrowhorizex', 'carriagereturn',
+    'aleph', 'Ifraktur', 'Rfraktur', 'weierstrass', 'circlemultiply',
+    'circleplus', 'emptyset', 'intersection', 'union', 'propersuperset',
+    'reflexsuperset', 'notsubset', 'propersubset', 'reflexsubset', 'element',
+    'notelement', 'angle', 'gradient', 'registerserif', 'copyrightserif',
+    'trademarkserif', 'product', 'radical', 'dotmath', 'logicalnot',
+    'logicaland', 'logicalor', 'arrowdblboth', 'arrowdblleft', 'arrowdblup',
+    'arrowdblright', 'arrowdbldown', 'lozenge', 'angleleft', 'registersans',
+    'copyrightsans', 'trademarksans', 'summation', 'parenlefttp',
+    'parenleftex', 'parenleftbt', 'bracketlefttp', 'bracketleftex',
+    'bracketleftbt', 'bracelefttp', 'braceleftmid', 'braceleftbt', 'braceex',
+    '', 'angleright', 'integral', 'integraltp', 'integralex', 'integralbt',
+    'parenrighttp', 'parenrightex', 'parenrightbt', 'bracketrighttp',
+    'bracketrightex', 'bracketrightbt', 'bracerighttp', 'bracerightmid',
+    'bracerightbt'],
+  zapfDingbatsEncoding: ['', '', '', '', '', '', '', '', '', '', '', '', '', '',
+    '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '',
+    'space', 'a1', 'a2', 'a202', 'a3', 'a4', 'a5', 'a119', 'a118', 'a117',
+    'a11', 'a12', 'a13', 'a14', 'a15', 'a16', 'a105', 'a17', 'a18', 'a19',
+    'a20', 'a21', 'a22', 'a23', 'a24', 'a25', 'a26', 'a27', 'a28', 'a6', 'a7',
+    'a8', 'a9', 'a10', 'a29', 'a30', 'a31', 'a32', 'a33', 'a34', 'a35', 'a36',
+    'a37', 'a38', 'a39', 'a40', 'a41', 'a42', 'a43', 'a44', 'a45', 'a46',
+    'a47', 'a48', 'a49', 'a50', 'a51', 'a52', 'a53', 'a54', 'a55', 'a56',
+    'a57', 'a58', 'a59', 'a60', 'a61', 'a62', 'a63', 'a64', 'a65', 'a66',
+    'a67', 'a68', 'a69', 'a70', 'a71', 'a72', 'a73', 'a74', 'a203', 'a75',
+    'a204', 'a76', 'a77', 'a78', 'a79', 'a81', 'a82', 'a83', 'a84', 'a97',
+    'a98', 'a99', 'a100', '', '', '', '', '', '', '', '', '', '', '', '', '',
+    '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '',
+    '', '', 'a101', 'a102', 'a103', 'a104', 'a106', 'a107', 'a108', 'a112',
+    'a111', 'a110', 'a109', 'a120', 'a121', 'a122', 'a123', 'a124', 'a125',
+    'a126', 'a127', 'a128', 'a129', 'a130', 'a131', 'a132', 'a133', 'a134',
+    'a135', 'a136', 'a137', 'a138', 'a139', 'a140', 'a141', 'a142', 'a143',
+    'a144', 'a145', 'a146', 'a147', 'a148', 'a149', 'a150', 'a151', 'a152',
+    'a153', 'a154', 'a155', 'a156', 'a157', 'a158', 'a159', 'a160', 'a161',
+    'a163', 'a164', 'a196', 'a165', 'a192', 'a166', 'a167', 'a168', 'a169',
+    'a170', 'a171', 'a172', 'a173', 'a162', 'a174', 'a175', 'a176', 'a177',
+    'a178', 'a179', 'a193', 'a180', 'a199', 'a181', 'a200', 'a182', '', 'a201',
+    'a183', 'a184', 'a197', 'a185', 'a194', 'a198', 'a186', 'a195', 'a187',
+    'a188', 'a189', 'a190', 'a191']
 };
 
 /**
@@ -12157,6 +13706,21 @@ var stdFontMap = {
   'TimesNewRomanPSMT-Italic': 'Times-Italic'
 };
 
+/**
+ * Holds the map of the non-standard fonts that might be included as a standard
+ * fonts without glyph data.
+ */
+var nonStdFontMap = {
+  'ComicSansMS': 'Comic Sans MS',
+  'ComicSansMS-Bold': 'Comic Sans MS-Bold',
+  'ComicSansMS-BoldItalic': 'Comic Sans MS-BoldItalic',
+  'ComicSansMS-Italic': 'Comic Sans MS-Italic',
+  'LucidaConsole': 'Courier',
+  'LucidaConsole-Bold': 'Courier-Bold',
+  'LucidaConsole-BoldItalic': 'Courier-BoldOblique',
+  'LucidaConsole-Italic': 'Courier-Oblique'
+};
+
 var serifFonts = {
   'Adobe Jenson': true, 'Adobe Text': true, 'Albertus': true,
   'Aldus': true, 'Alexandria': true, 'Algerian': true,
@@ -12204,13 +13768,30 @@ var serifFonts = {
   'Wide Latin': true, 'Windsor': true, 'XITS': true
 };
 
+var symbolsFonts = {
+  'Dingbats': true, 'Symbol': true, 'ZapfDingbats': true
+};
+
+// Some characters, e.g. copyrightserif, mapped to the private use area and
+// might not be displayed using standard fonts. Mapping/hacking well-known chars
+// to the similar equivalents in the normal characters range.
+function mapPrivateUseChars(code) {
+  switch (code) {
+    case 0xF8E9: // copyrightsans
+    case 0xF6D9: // copyrightserif
+      return 0x00A9; // copyright
+    default:
+      return code;
+  }
+}
+
 var FontLoader = {
   listeningForFontLoad: false,
 
   bind: function fontLoaderBind(fonts, callback) {
     function checkFontsLoaded() {
-      for (var i = 0, ii = objs.length; i < ii; i++) {
-        var fontObj = objs[i];
+      for (var i = 0, ii = fonts.length; i < ii; i++) {
+        var fontObj = fonts[i];
         if (fontObj.loading) {
           return false;
         }
@@ -12223,52 +13804,45 @@ var FontLoader = {
       return true;
     }
 
-    var rules = [], names = [], objs = [];
+    var rules = [], names = [], fontsToLoad = [];
+    var fontCreateTimer = 0;
 
     for (var i = 0, ii = fonts.length; i < ii; i++) {
       var font = fonts[i];
 
-      // If there is already a fontObj on the font, then it was loaded/attached
-      // to the page already and we don't have to do anything for this font
-      // here future.
-      if (font.fontObj) {
+      // Add the font to the DOM only once or skip if the font
+      // is already loaded.
+      if (font.attached || font.loading == false) {
         continue;
       }
+      font.attached = true;
 
-      var obj = new Font(font.name, font.file, font.properties);
-
-      // Store the fontObj on the font such that `setFont` in CanvasGraphics
-      // can reuse it later again.
-      font.fontObj = obj;
-
-      objs.push(obj);
+      fontsToLoad.push(font);
 
       var str = '';
-      var data = obj.data;
+      var data = font.data;
       if (data) {
         var length = data.length;
         for (var j = 0; j < length; j++)
           str += String.fromCharCode(data[j]);
 
-        var rule = isWorker ? obj.bindWorker(str) : obj.bindDOM(str);
+        var rule = font.bindDOM(str);
         if (rule) {
           rules.push(rule);
-          names.push(obj.loadedName);
+          names.push(font.loadedName);
         }
       }
     }
 
     this.listeningForFontLoad = false;
     if (!isWorker && rules.length) {
-      FontLoader.prepareFontLoadEvent(rules, names, objs);
+      FontLoader.prepareFontLoadEvent(rules, names, fontsToLoad);
     }
 
     if (!checkFontsLoaded()) {
       document.documentElement.addEventListener(
         'pdfjsFontLoad', checkFontsLoaded, false);
     }
-
-    return objs;
   },
   // Set things up so that at least one pdfjsFontLoad event is
   // dispatched when all the @font-face |rules| for |names| have been
@@ -12276,7 +13850,7 @@ var FontLoader = {
   // has already started in this (outer) document, so that they should
   // be ordered before the load in the subdocument.
   prepareFontLoadEvent: function fontLoaderPrepareFontLoadEvent(rules, names,
-                                                                objs) {
+                                                                fonts) {
       /** Hack begin */
       // There's no event when a font has finished downloading so the
       // following code is a dirty hack to 'guess' when a font is
@@ -12300,6 +13874,15 @@ var FontLoader = {
       // The postMessage() hackery was added to work around chrome bug
       // 82402.
 
+      // Validate the names parameter -- the values can used to construct HTML.
+      if (!/^\w+$/.test(names.join(''))) {
+        error('Invalid font name(s): ' + names.join());
+
+        // Normally the error-function throws. But if a malicious code
+        // intercepts the function call then the return is needed.
+        return;
+      }
+
       var div = document.createElement('div');
       div.setAttribute('style',
                        'visibility: hidden;' +
@@ -12317,8 +13900,8 @@ var FontLoader = {
           'message',
           function fontLoaderMessage(e) {
             var fontNames = JSON.parse(e.data);
-            for (var i = 0, ii = objs.length; i < ii; ++i) {
-              var font = objs[i];
+            for (var i = 0, ii = fonts.length; i < ii; ++i) {
+              var font = fonts[i];
               font.loading = false;
             }
             var evt = document.createEvent('Events');
@@ -12346,7 +13929,8 @@ var FontLoader = {
       src += '  window.onload = function fontLoaderOnload() {\n';
       src += '    parent.postMessage(JSON.stringify(fontNames), "*");\n';
       src += '  }';
-      src += '</script></head><body>';
+      // Hack so the end script tag isn't counted if this is inline JS.
+      src += '</scr' + 'ipt></head><body>';
       for (var i = 0, ii = names.length; i < ii; ++i) {
         src += '<p style="font-family:\'' + names[i] + '\'">Hi</p>';
       }
@@ -12535,20 +14119,20 @@ function getUnicodeRangeFor(value) {
   return -1;
 }
 
-function adaptUnicode(unicode) {
-  return (unicode <= 0x1F || (unicode >= 127 && unicode < kSizeOfGlyphArea)) ?
-    unicode + kCmapGlyphOffset : unicode;
-}
-
-function isAdaptedUnicode(unicode) {
-  return unicode >= kCmapGlyphOffset &&
-    unicode < kCmapGlyphOffset + kSizeOfGlyphArea;
+function isRTLRangeFor(value) {
+  var range = UnicodeRanges[13];
+  if (value >= range.begin && value < range.end)
+    return true;
+  range = UnicodeRanges[11];
+  if (value >= range.begin && value < range.end)
+    return true;
+  return false;
 }
 
 function isSpecialUnicode(unicode) {
   return (unicode <= 0x1F || (unicode >= 127 && unicode < kSizeOfGlyphArea)) ||
-    unicode >= kCmapGlyphOffset &&
-    unicode < kCmapGlyphOffset + kSizeOfGlyphArea;
+    (unicode >= kCmapGlyphOffset &&
+    unicode < kCmapGlyphOffset + kSizeOfGlyphArea);
 }
 
 /**
@@ -12559,18 +14143,19 @@ function isSpecialUnicode(unicode) {
  *   var type1Font = new Font("MyFontName", binaryFile, propertiesObject);
  *   type1Font.bind();
  */
-var Font = (function Font() {
-  var constructor = function font_constructor(name, file, properties) {
+var Font = (function FontClosure() {
+  function Font(name, file, properties) {
     this.name = name;
     this.coded = properties.coded;
-    this.charProcIRQueues = properties.charProcIRQueues;
+    this.charProcOperatorList = properties.charProcOperatorList;
     this.resources = properties.resources;
     this.sizes = [];
 
     var names = name.split('+');
     names = names.length > 1 ? names[1] : names[0];
     names = names.split(/[-,_]/g)[0];
-    this.serif = serifFonts[names] || (name.search(/serif/gi) != -1);
+    this.isSerifFont = !!(properties.flags & FontFlags.Serif);
+    this.isSymbolicFont = !!(properties.flags & FontFlags.Symbolic);
 
     var type = properties.type;
     this.type = type;
@@ -12578,7 +14163,7 @@ var Font = (function Font() {
     // If the font is to be ignored, register it like an already loaded font
     // to avoid the cost of waiting for it be be loaded by the platform.
     if (properties.ignore) {
-      this.loadedName = this.serif ? 'serif' : 'sans-serif';
+      this.loadedName = this.isSerifFont ? 'serif' : 'sans-serif';
       this.loading = false;
       return;
     }
@@ -12587,21 +14172,30 @@ var Font = (function Font() {
     this.widths = properties.widths;
     this.defaultWidth = properties.defaultWidth;
     this.composite = properties.composite;
-    this.toUnicode = properties.toUnicode;
     this.hasEncoding = properties.hasEncoding;
 
     this.fontMatrix = properties.fontMatrix;
-    if (properties.type == 'Type3')
+    this.widthMultiplier = 1.0;
+    if (properties.type == 'Type3') {
+      this.encoding = properties.baseEncoding;
       return;
+    }
 
     // Trying to fix encoding using glyph CIDSystemInfo.
     this.loadCidToUnicode(properties);
 
+    if (properties.toUnicode)
+      this.toUnicode = properties.toUnicode;
+    else
+      this.rebuildToUnicode(properties);
+
+    this.toFontChar = this.buildToFontChar(this.toUnicode);
+
     if (!file) {
       // The file data is not specified. Trying to fix the font name
       // to be used with the canvas.font.
       var fontName = name.replace(/[,_]/g, '-');
-      fontName = stdFontMap[fontName] || fontName;
+      fontName = stdFontMap[fontName] || nonStdFontMap[fontName] || fontName;
 
       this.bold = (fontName.search(/bold/gi) != -1);
       this.italic = (fontName.search(/oblique/gi) != -1) ||
@@ -12626,7 +14220,7 @@ var Font = (function Font() {
 
         var subtype = properties.subtype;
         var cff = (subtype == 'Type1C' || subtype == 'CIDFontType0C') ?
-          new Type2CFF(file, properties) : new CFF(name, file, properties);
+          new CFFFont(file, properties) : new Type1Font(name, file, properties);
 
         // Wrap the CFF data inside an OTF font file
         data = this.convert(name, cff, properties);
@@ -12648,9 +14242,10 @@ var Font = (function Font() {
 
     this.data = data;
     this.fontMatrix = properties.fontMatrix;
+    this.widthMultiplier = !properties.fontMatrix ? 1.0 :
+      1.0 / properties.fontMatrix[0];
     this.encoding = properties.baseEncoding;
-    this.hasShortCmap = properties.hasShortCmap;
-    this.loadedName = getUniqueName();
+    this.loadedName = properties.loadedName;
     this.loading = true;
   };
 
@@ -12703,6 +14298,13 @@ var Font = (function Font() {
            String.fromCharCode(value & 0xff);
   };
 
+  function safeString16(value) {
+    // clamp value to the 16-bit int range
+    value = value > 0x7FFF ? 0x7FFF : value < -0x8000 ? -0x8000 : value;
+    return String.fromCharCode((value >> 8) & 0xff) +
+           String.fromCharCode(value & 0xff);
+  };
+
   function string32(value) {
     return String.fromCharCode((value >> 24) & 0xff) +
            String.fromCharCode((value >> 16) & 0xff) +
@@ -12777,15 +14379,15 @@ var Font = (function Font() {
     var ranges = [];
     for (var n = 0; n < length; ) {
       var start = codes[n].unicode;
-      var startCode = codes[n].code;
+      var codeIndices = [codes[n].code];
       ++n;
       var end = start;
       while (n < length && end + 1 == codes[n].unicode) {
+        codeIndices.push(codes[n].code);
         ++end;
         ++n;
       }
-      var endCode = codes[n - 1].code;
-      ranges.push([start, end, startCode, endCode]);
+      ranges.push([start, end, codeIndices]);
     }
 
     return ranges;
@@ -12828,17 +14430,16 @@ var Font = (function Font() {
         idDeltas += string16(0);
         idRangeOffsets += string16(offset);
 
-        var startCode = range[2];
-        var endCode = range[3];
-        for (var j = startCode; j <= endCode; ++j)
-          glyphsIds += string16(deltas[j]);
+        var codes = range[2];
+        for (var j = 0, jj = codes.length; j < jj; ++j)
+          glyphsIds += string16(deltas[codes[j]]);
       }
     } else {
       for (var i = 0; i < segCount - 1; i++) {
         var range = ranges[i];
         var start = range[0];
         var end = range[1];
-        var startCode = range[2];
+        var startCode = range[2][0];
 
         startCount += string16(start);
         endCount += string16(end);
@@ -13042,13 +14643,13 @@ var Font = (function Font() {
     return nameTable;
   }
 
-  constructor.prototype = {
+  Font.prototype = {
     name: null,
     font: null,
     mimetype: null,
     encoding: null,
 
-    checkAndRepair: function font_checkAndRepair(name, font, properties) {
+    checkAndRepair: function Font_checkAndRepair(name, font, properties) {
       function readTableEntry(file) {
         var tag = file.getBytes(4);
         tag = String.fromCharCode(tag[0]) +
@@ -13115,7 +14716,7 @@ var Font = (function Font() {
           properties.baseEncoding = encoding;
       }
 
-      function replaceCMapTable(cmap, font, properties) {
+      function readCMapTable(cmap, font) {
         var start = (font.start ? font.start : 0) + cmap.offset;
         font.pos = start;
 
@@ -13132,7 +14733,7 @@ var Font = (function Font() {
         }
 
         // Check that table are sorted by platformID then encodingID,
-        records.sort(function fontReplaceCMapTableSort(a, b) {
+        records.sort(function fontReadCMapTableSort(a, b) {
           return ((a.platformID << 16) + a.encodingID) -
                  ((b.platformID << 16) + b.encodingID);
         });
@@ -13187,16 +14788,15 @@ var Font = (function Font() {
             for (var j = 0; j < 256; j++) {
               var index = font.getByte();
               if (index) {
-                var unicode = adaptUnicode(j);
-                glyphs.push({ unicode: unicode, code: j });
+                glyphs.push({ unicode: j, code: j });
                 ids.push(index);
               }
             }
-
-            properties.hasShortCmap = true;
-
-            createGlyphNameMap(glyphs, ids, properties);
-            return cmap.data = createCMapTable(glyphs, ids);
+            return {
+              glyphs: glyphs,
+              ids: ids,
+              hasShortCmap: true
+            };
           } else if (format == 4) {
             // re-creating the table in format 4 since the encoding
             // might be changed
@@ -13248,17 +14848,18 @@ var Font = (function Font() {
                 var glyphCode = offsetIndex < 0 ? j :
                   offsets[offsetIndex + j - start];
                 glyphCode = (glyphCode + delta) & 0xFFFF;
-                if (glyphCode == 0 || isAdaptedUnicode(j))
+                if (glyphCode == 0)
                   continue;
 
-                var unicode = adaptUnicode(j);
-                glyphs.push({ unicode: unicode, code: j });
+                glyphs.push({ unicode: j, code: j });
                 ids.push(glyphCode);
               }
             }
 
-            createGlyphNameMap(glyphs, ids, properties);
-            return cmap.data = createCMapTable(glyphs, ids);
+            return {
+              glyphs: glyphs,
+              ids: ids
+            };
           } else if (format == 6) {
             // Format 6 is a 2-bytes dense mapping, which means the font data
             // lives glue together even if they are pretty far in the unicode
@@ -13273,19 +14874,18 @@ var Font = (function Font() {
             for (var j = 0; j < entryCount; j++) {
               var glyphCode = int16(font.getBytes(2));
               var code = firstCode + j;
-              if (isAdaptedUnicode(glyphCode))
-                continue;
 
-              var unicode = adaptUnicode(code);
-              glyphs.push({ unicode: unicode, code: code });
+              glyphs.push({ unicode: code, code: code });
               ids.push(glyphCode);
             }
 
-            createGlyphNameMap(glyphs, ids, properties);
-            return cmap.data = createCMapTable(glyphs, ids);
+            return {
+              glyphs: glyphs,
+              ids: ids
+            };
           }
         }
-        return cmap.data;
+        error('Unsupported cmap table format');
       };
 
       function sanitizeMetrics(font, header, metrics, numGlyphs) {
@@ -13321,6 +14921,61 @@ var Font = (function Font() {
         }
       };
 
+      function sanitizeGlyph(source, sourceStart, sourceEnd, dest, destStart) {
+        if (sourceEnd - sourceStart <= 12) {
+          // glyph with data less than 12 is invalid one
+          return 0;
+        }
+        var glyf = source.subarray(sourceStart, sourceEnd);
+        var contoursCount = (glyf[0] << 8) | glyf[1];
+        if (contoursCount & 0x8000) {
+          // complex glyph, writing as is
+          dest.set(glyf, destStart);
+          return glyf.length;
+        }
+
+        var j = 10, flagsCount = 0;
+        for (var i = 0; i < contoursCount; i++) {
+          var endPoint = (glyf[j] << 8) | glyf[j + 1];
+          flagsCount = endPoint + 1;
+          j += 2;
+        }
+        // skipping instructions
+        var instructionsLength = (glyf[j] << 8) | glyf[j + 1];
+        j += 2 + instructionsLength;
+        // validating flags
+        var coordinatesLength = 0;
+        for (var i = 0; i < flagsCount; i++) {
+          var flag = glyf[j++];
+          if (flag & 0xC0) {
+            // reserved flags must be zero, rejecting
+            return 0;
+          }
+          var xyLength = ((flag & 2) ? 1 : (flag & 16) ? 0 : 2) +
+                         ((flag & 4) ? 1 : (flag & 32) ? 0 : 2);
+          coordinatesLength += xyLength;
+          if (flag & 8) {
+            var repeat = glyf[j++];
+            i += repeat;
+            coordinatesLength += repeat * xyLength;
+          }
+        }
+        var glyphDataLength = j + coordinatesLength;
+        if (glyphDataLength > glyf.length) {
+          // not enough data for coordinates
+          return 0;
+        }
+        if (glyf.length - glyphDataLength > 3) {
+          // truncating and aligning to 4 bytes the long glyph data
+          glyphDataLength = (glyphDataLength + 3) & ~3;
+          dest.set(glyf.subarray(0, glyphDataLength), destStart);
+          return glyphDataLength;
+        }
+        // glyph data is fine
+        dest.set(glyf, destStart);
+        return glyf.length;
+      }
+
       function sanitizeGlyphLocations(loca, glyf, numGlyphs,
                                       isGlyphLocationsLong) {
         var itemSize, itemDecode, itemEncode;
@@ -13347,20 +15002,64 @@ var Font = (function Font() {
           };
         }
         var locaData = loca.data;
+        // removing the invalid glyphs
+        var oldGlyfData = glyf.data;
+        var oldGlyfDataLength = oldGlyfData.length;
+        var newGlyfData = new Uint8Array(oldGlyfDataLength);
         var startOffset = itemDecode(locaData, 0);
-        var firstOffset = itemDecode(locaData, itemSize);
-        if (firstOffset - startOffset < 12 || startOffset > 0) {
-          // removing first glyph
-          glyf.data = glyf.data.subarray(firstOffset);
-          glyf.length -= firstOffset;
-
-          itemEncode(locaData, 0, 0);
-          var i, pos = itemSize;
-          for (i = 1; i <= numGlyphs; ++i) {
-            itemEncode(locaData, pos,
-              itemDecode(locaData, pos) - firstOffset);
-            pos += itemSize;
+        var writeOffset = 0;
+        itemEncode(locaData, 0, writeOffset);
+        for (var i = 0, j = itemSize; i < numGlyphs; i++, j += itemSize) {
+          var endOffset = itemDecode(locaData, j);
+          if (endOffset > oldGlyfDataLength) {
+            // glyph end offset points outside glyf data, rejecting the glyph
+            itemEncode(locaData, j, writeOffset);
+            startOffset = endOffset;
+            continue;
           }
+
+          var newLength = sanitizeGlyph(oldGlyfData, startOffset, endOffset,
+                                        newGlyfData, writeOffset);
+          writeOffset += newLength;
+          itemEncode(locaData, j, writeOffset);
+          startOffset = endOffset;
+        }
+
+        if (writeOffset == 0) {
+          // glyf table cannot be empty -- redoing the glyf and loca tables
+          // to have single glyph with one point
+          var simpleGlyph = new Uint8Array(
+            [0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 0]);
+          for (var i = 0, j = itemSize; i < numGlyphs; i++, j += itemSize)
+            itemEncode(locaData, j, simpleGlyph.length);
+          glyf.data = simpleGlyph;
+          return;
+        }
+
+        glyf.data = newGlyfData.subarray(0, writeOffset);
+      }
+
+      function findEmptyGlyphs(locaTable, isGlyphLocationsLong, emptyGlyphIds) {
+        var itemSize, itemDecode;
+        if (isGlyphLocationsLong) {
+          itemSize = 4;
+          itemDecode = function fontItemDecodeLong(data, offset) {
+            return (data[offset] << 24) | (data[offset + 1] << 16) |
+                   (data[offset + 2] << 8) | data[offset + 3];
+          };
+        } else {
+          itemSize = 2;
+          itemDecode = function fontItemDecode(data, offset) {
+            return (data[offset] << 9) | (data[offset + 1] << 1);
+          };
+        }
+        var data = locaTable.data, length = data.length;
+        var lastOffset = itemDecode(data, 0);
+        for (var i = itemSize, j = 0; i < length; i += itemSize, j++) {
+          var offset = itemDecode(data, i);
+          if (offset == lastOffset)
+            emptyGlyphIds[j] = true;
+          lastOffset = offset;
         }
       }
 
@@ -13490,11 +15189,15 @@ var Font = (function Font() {
       sanitizeMetrics(font, hhea, hmtx, numGlyphs);
       sanitizeMetrics(font, vhea, vmtx, numGlyphs);
 
+      var isGlyphLocationsLong = int16([head.data[50], head.data[51]]);
       if (head && loca && glyf) {
-        var isGlyphLocationsLong = int16([head.data[50], head.data[51]]);
         sanitizeGlyphLocations(loca, glyf, numGlyphs, isGlyphLocationsLong);
       }
 
+      var emptyGlyphIds = [];
+      if (glyf)
+        findEmptyGlyphs(loca, isGlyphLocationsLong, emptyGlyphIds);
+
       // Sanitizer reduces the glyph advanceWidth to the maxAdvanceWidth
       // Sometimes it's 0. That needs to be fixed
       if (hhea.data[10] == 0 && hhea.data[11] == 0) {
@@ -13507,8 +15210,9 @@ var Font = (function Font() {
         readGlyphNameMap(post, properties);
       }
 
-      // Replace the old CMAP table with a shiny new one
+      var glyphs, ids;
       if (properties.type == 'CIDFontType2') {
+        // Replace the old CMAP table with a shiny new one
         // Type2 composite fonts map characters directly to glyphs so the cmap
         // table must be replaced.
         // canvas fillText will reencode some characters even if the font has a
@@ -13524,19 +15228,236 @@ var Font = (function Font() {
           tables.push(cmap);
         }
 
-        var glyphs = [];
-        for (i = 1; i < numGlyphs; i++) {
-          if (isAdaptedUnicode(i))
-            continue;
+        var cidToGidMap = properties.cidToGidMap || [];
+        var gidToCidMap = [0];
+        if (cidToGidMap.length > 0) {
+          for (var j = cidToGidMap.length - 1; j >= 0; j--) {
+            var gid = cidToGidMap[j];
+            if (gid)
+              gidToCidMap[gid] = j;
+          }
+          // filling the gaps using CID above the CIDs currently used in font
+          var nextCid = cidToGidMap.length;
+          for (var i = 1; i < numGlyphs; i++) {
+            if (!gidToCidMap[i])
+              gidToCidMap[i] = nextCid++;
+          }
+        }
 
-          glyphs.push({ unicode: adaptUnicode(i) });
+        glyphs = [];
+        ids = [];
+
+        var usedUnicodes = [];
+        var unassignedUnicodeItems = [];
+        for (var i = 1; i < numGlyphs; i++) {
+          var cid = gidToCidMap[i] || i;
+          var unicode = this.toFontChar[cid];
+          if (!unicode || typeof unicode !== 'number' ||
+              isSpecialUnicode(unicode) || unicode in usedUnicodes) {
+            unassignedUnicodeItems.push(i);
+            continue;
+          }
+          usedUnicodes[unicode] = true;
+          glyphs.push({ unicode: unicode, code: cid });
+          ids.push(i);
+        }
+        // trying to fit as many unassigned symbols as we can
+        // in the range allocated for the user defined symbols
+        var unusedUnicode = kCmapGlyphOffset;
+        for (var j = 0, jj = unassignedUnicodeItems.length; j < jj; j++) {
+          var i = unassignedUnicodeItems[j];
+          var cid = gidToCidMap[i] || i;
+          while (unusedUnicode in usedUnicodes)
+            unusedUnicode++;
+          if (unusedUnicode >= kCmapGlyphOffset + kSizeOfGlyphArea)
+            break;
+          var unicode = unusedUnicode++;
+          this.toFontChar[cid] = unicode;
+          usedUnicodes[unicode] = true;
+          glyphs.push({ unicode: unicode, code: cid });
+          ids.push(i);
         }
-        cmap.data = createCMapTable(glyphs);
       } else {
-        replaceCMapTable(cmap, font, properties);
+        var cmapTable = readCMapTable(cmap, font);
+
+        glyphs = cmapTable.glyphs;
+        ids = cmapTable.ids;
+
+        var hasShortCmap = !!cmapTable.hasShortCmap;
+        var toFontChar = this.toFontChar;
+
+        if (hasShortCmap && ids.length == numGlyphs) {
+          // Fixes the short cmap tables -- some generators use incorrect
+          // glyph id.
+          for (var i = 0, ii = ids.length; i < ii; i++)
+            ids[i] = i;
+        }
+
+        var unusedUnicode = kCmapGlyphOffset;
+        var glyphNames = properties.glyphNames || [];
+        var encoding = properties.baseEncoding;
+        var differences = properties.differences;
+        if (toFontChar && toFontChar.length > 0) {
+          // checking if cmap is just identity map
+          var isIdentity = true;
+          for (var i = 0, ii = glyphs.length; i < ii; i++) {
+            if (glyphs[i].unicode != i + 1) {
+              isIdentity = false;
+              break;
+            }
+          }
+          // if it is, replacing with meaningful toUnicode values
+          if (isIdentity && !this.isSymbolicFont) {
+            var usedUnicodes = [], unassignedUnicodeItems = [];
+            for (var i = 0, ii = glyphs.length; i < ii; i++) {
+              var unicode = toFontChar[i + 1];
+              if (!unicode || typeof unicode !== 'number' ||
+                  unicode in usedUnicodes) {
+                unassignedUnicodeItems.push(i);
+                continue;
+              }
+              glyphs[i].unicode = unicode;
+              usedUnicodes[unicode] = true;
+            }
+            for (var j = 0, jj = unassignedUnicodeItems.length; j < jj; j++) {
+              var i = unassignedUnicodeItems[j];
+              while (unusedUnicode in usedUnicodes)
+                unusedUnicode++;
+              var cid = i + 1;
+              // override only if unicode mapping is not specified
+              if (!(cid in toFontChar))
+                toFontChar[cid] = unusedUnicode;
+              glyphs[i].unicode = unusedUnicode++;
+            }
+            this.useToFontChar = true;
+          }
+        }
+
+        // remove glyph references outside range of avaialable glyphs or empty
+        var glyphsRemoved = 0;
+        for (var i = ids.length - 1; i >= 0; i--) {
+          if (ids[i] < numGlyphs &&
+              (!emptyGlyphIds[ids[i]] || this.isSymbolicFont))
+            continue;
+          ids.splice(i, 1);
+          glyphs.splice(i, 1);
+          glyphsRemoved++;
+        }
+
+        // checking if it's a "true" symbolic font
+        if (this.isSymbolicFont) {
+          var minUnicode = 0xFFFF, maxUnicode = 0;
+          for (var i = 0, ii = glyphs.length; i < ii; i++) {
+            var unicode = glyphs[i].unicode;
+            minUnicode = Math.min(minUnicode, unicode);
+            maxUnicode = Math.max(maxUnicode, unicode);
+          }
+          // high byte must be the same for min and max unicodes
+          if ((maxUnicode & 0xFF00) != (minUnicode & 0xFF00))
+            this.isSymbolicFont = false;
+        }
+
+        // heuristics: if removed more than 2 glyphs encoding WinAnsiEncoding
+        // does not set properly
+        if (glyphsRemoved > 2) {
+          warn('Switching TrueType encoding to MacRomanEncoding for ' +
+               this.name + ' font');
+          encoding = Encodings.MacRomanEncoding;
+        }
+
+        if (hasShortCmap && this.hasEncoding && !this.isSymbolicFont) {
+          // Re-encode short map encoding to unicode -- that simplifies the
+          // resolution of MacRoman encoded glyphs logic for TrueType fonts:
+          // copying all characters to private use area, all mapping all known
+          // glyphs to the unicodes. The glyphs and ids arrays will grow.
+          var usedUnicodes = [];
+          for (var i = 0, ii = glyphs.length; i < ii; i++) {
+            var code = glyphs[i].unicode;
+            var gid = ids[i];
+            glyphs[i].unicode += kCmapGlyphOffset;
+            toFontChar[code] = glyphs[i].unicode;
+
+            var glyphName = glyphNames[gid] || encoding[code];
+            if (glyphName in GlyphsUnicode) {
+              var unicode = GlyphsUnicode[glyphName];
+              if (unicode in usedUnicodes)
+                continue;
+
+              usedUnicodes[unicode] = true;
+              glyphs.push({
+                unicode: unicode,
+                code: glyphs[i].code
+              });
+              ids.push(gid);
+              toFontChar[code] = unicode;
+            }
+          }
+          this.useToFontChar = true;
+        } else if (!this.isSymbolicFont && (this.hasEncoding ||
+                    properties.glyphNames || differences.length > 0)) {
+          // Re-encode cmap encoding to unicode, based on the 'post' table data
+          // diffrence array or base encoding
+          var reverseMap = [];
+          for (var i = 0, ii = glyphs.length; i < ii; i++)
+            reverseMap[glyphs[i].unicode] = i;
+
+          var newGlyphUnicodes = [];
+          for (var i = 0, ii = glyphs.length; i < ii; i++) {
+            var code = glyphs[i].unicode;
+            var changeCode = false;
+            var gid = ids[i];
+
+            var glyphName = glyphNames[gid];
+            if (!glyphName) {
+              glyphName = differences[code] || encoding[code];
+              changeCode = true;
+            }
+            if (glyphName in GlyphsUnicode) {
+              var unicode = GlyphsUnicode[glyphName];
+              if (!unicode || reverseMap[unicode] === i)
+                continue; // unknown glyph name or in its own place
+
+              newGlyphUnicodes[i] = unicode;
+              if (changeCode)
+                toFontChar[code] = unicode;
+              delete reverseMap[code];
+            }
+          }
+          for (var index in newGlyphUnicodes) {
+            var unicode = newGlyphUnicodes[index];
+            if (reverseMap[unicode]) {
+              // avoiding assigning to the same unicode
+              glyphs[index].unicode = unusedUnicode++;
+              continue;
+            }
+            glyphs[index].unicode = unicode;
+            reverseMap[unicode] = index;
+          }
+          this.useToFontChar = true;
+        }
+
+        // Moving all symbolic font glyphs into 0xF000 - 0xF0FF range.
+        if (this.isSymbolicFont) {
+          for (var i = 0, ii = glyphs.length; i < ii; i++) {
+            var code = glyphs[i].unicode & 0xFF;
+            var fontCharCode = kSymbolicFontGlyphOffset | code;
+            glyphs[i].unicode = toFontChar[code] = fontCharCode;
+          }
+          this.useToFontChar = true;
+        }
+
+        createGlyphNameMap(glyphs, ids, properties);
         this.glyphNameMap = properties.glyphNameMap;
       }
 
+      // Converting glyphs and ids into font's cmap table
+      cmap.data = createCMapTable(glyphs, ids);
+      var unicodeIsEnabled = [];
+      for (var i = 0, ii = glyphs.length; i < ii; i++) {
+        unicodeIsEnabled[glyphs[i].unicode] = true;
+      }
+      this.unicodeIsEnabled = unicodeIsEnabled;
+
       // Rewrite the 'post' table if needed
       if (requiredTables.indexOf('post') != -1) {
         tables.push({
@@ -13583,7 +15504,7 @@ var Font = (function Font() {
       return stringToArray(ttf.file);
     },
 
-    convert: function font_convert(fontName, font, properties) {
+    convert: function Font_convert(fontName, font, properties) {
       function isFixedPitch(glyphs) {
         for (var i = 0, ii = glyphs.length - 1; i < ii; i++) {
           if (glyphs[i] != glyphs[i + 1])
@@ -13624,6 +15545,14 @@ var Font = (function Font() {
         }
         properties.baseEncoding = encoding;
       }
+      if (properties.subtype == 'CIDFontType0C') {
+        var toFontChar = [];
+        for (var i = 0; i < charstrings.length; ++i) {
+          var charstring = charstrings[i];
+          toFontChar[charstring.code] = charstring.unicode;
+        }
+        this.toFontChar = toFontChar;
+      }
 
       var fields = {
         // PostScript Font Program
@@ -13648,9 +15577,9 @@ var Font = (function Font() {
               '\x00\x00\x00\x00\x9e\x0b\x7e\x27' + // creation date
               '\x00\x00\x00\x00\x9e\x0b\x7e\x27' + // modifification date
               '\x00\x00' + // xMin
-              string16(properties.descent) + // yMin
+              safeString16(properties.descent) + // yMin
               '\x0F\xFF' + // xMax
-              string16(properties.ascent) + // yMax
+              safeString16(properties.ascent) + // yMax
               string16(properties.italicAngle ? 2 : 0) + // macStyle
               '\x00\x11' + // lowestRecPPEM
               '\x00\x00' + // fontDirectionHint
@@ -13662,15 +15591,15 @@ var Font = (function Font() {
         'hhea': (function fontFieldsHhea() {
           return stringToArray(
               '\x00\x01\x00\x00' + // Version number
-              string16(properties.ascent) + // Typographic Ascent
-              string16(properties.descent) + // Typographic Descent
+              safeString16(properties.ascent) + // Typographic Ascent
+              safeString16(properties.descent) + // Typographic Descent
               '\x00\x00' + // Line Gap
               '\xFF\xFF' + // advanceWidthMax
               '\x00\x00' + // minLeftSidebearing
               '\x00\x00' + // minRightSidebearing
               '\x00\x00' + // xMaxExtent
-              string16(properties.capHeight) + // caretSlopeRise
-              string16(Math.tan(properties.italicAngle) *
+              safeString16(properties.capHeight) + // caretSlopeRise
+              safeString16(Math.tan(properties.italicAngle) *
                        properties.xHeight) + // caretSlopeRun
               '\x00\x00' + // caretOffset
               '\x00\x00' + // -reserved-
@@ -13684,8 +15613,11 @@ var Font = (function Font() {
         // Horizontal metrics
         'hmtx': (function fontFieldsHmtx() {
           var hmtx = '\x00\x00\x00\x00'; // Fake .notdef
-          for (var i = 0, ii = charstrings.length; i < ii; i++)
-            hmtx += string16(charstrings[i].width) + string16(0);
+          for (var i = 0, ii = charstrings.length; i < ii; i++) {
+            var charstring = charstrings[i];
+            var width = 'width' in charstring ? charstring.width : 0;
+            hmtx += string16(width) + string16(0);
+          }
           return stringToArray(hmtx);
         })(),
 
@@ -13714,17 +15646,48 @@ var Font = (function Font() {
       return stringToArray(otf.file);
     },
 
-    loadCidToUnicode: function font_loadCidToUnicode(properties) {
-      if (properties.cidToGidMap) {
-        this.cidToUnicode = properties.cidToGidMap;
-        return;
+    buildToFontChar: function Font_buildToFontChar(toUnicode) {
+      var result = [];
+      var unusedUnicode = kCmapGlyphOffset;
+      for (var i = 0, ii = toUnicode.length; i < ii; i++) {
+        var unicode = toUnicode[i];
+        var fontCharCode = typeof unicode === 'object' ? unusedUnicode++ :
+          unicode;
+        if (typeof unicode !== 'undefined')
+          result[i] = fontCharCode;
+      }
+      return result;
+    },
+
+    rebuildToUnicode: function Font_rebuildToUnicode(properties) {
+      var firstChar = properties.firstChar, lastChar = properties.lastChar;
+      var map = [];
+      if (properties.composite) {
+        var isIdentityMap = this.cidToUnicode.length == 0;
+        for (var i = firstChar, ii = lastChar; i <= ii; i++) {
+          // TODO missing map the character according font's CMap
+          var cid = i;
+          map[i] = isIdentityMap ? cid : this.cidToUnicode[cid];
+        }
+      } else {
+        for (var i = firstChar, ii = lastChar; i <= ii; i++) {
+          var glyph = properties.differences[i];
+          if (!glyph)
+            glyph = properties.baseEncoding[i];
+          if (!!glyph && (glyph in GlyphsUnicode))
+            map[i] = GlyphsUnicode[glyph];
+        }
       }
+      this.toUnicode = map;
+    },
 
+    loadCidToUnicode: function Font_loadCidToUnicode(properties) {
       if (!properties.cidSystemInfo)
         return;
 
-      var cidToUnicodeMap = [];
+      var cidToUnicodeMap = [], unicodeToCIDMap = [];
       this.cidToUnicode = cidToUnicodeMap;
+      this.unicodeToCID = unicodeToCIDMap;
 
       var cidSystemInfo = properties.cidSystemInfo;
       var cidToUnicode;
@@ -13736,43 +15699,38 @@ var Font = (function Font() {
       if (!cidToUnicode)
         return; // identity encoding
 
-      var glyph = 1, i, j, k, ii;
+      var cid = 1, i, j, k, ii;
       for (i = 0, ii = cidToUnicode.length; i < ii; ++i) {
         var unicode = cidToUnicode[i];
         if (isArray(unicode)) {
           var length = unicode.length;
-          for (j = 0; j < length; j++)
-            cidToUnicodeMap[unicode[j]] = glyph;
-          glyph++;
+          for (j = 0; j < length; j++) {
+            cidToUnicodeMap[cid] = unicode[j];
+            unicodeToCIDMap[unicode[j]] = cid;
+          }
+          cid++;
         } else if (typeof unicode === 'object') {
           var fillLength = unicode.f;
           if (fillLength) {
             k = unicode.c;
             for (j = 0; j < fillLength; ++j) {
-              cidToUnicodeMap[k] = glyph++;
+              cidToUnicodeMap[cid] = k;
+              unicodeToCIDMap[k] = cid;
+              cid++;
               k++;
             }
           } else
-            glyph += unicode.s;
+            cid += unicode.s;
         } else if (unicode) {
-          cidToUnicodeMap[unicode] = glyph++;
+          cidToUnicodeMap[cid] = unicode;
+          unicodeToCIDMap[unicode] = cid;
+          cid++;
         } else
-          glyph++;
+          cid++;
       }
     },
 
-    bindWorker: function font_bindWorker(data) {
-      postMessage({
-        action: 'font',
-        data: {
-          raw: data,
-          fontName: this.loadedName,
-          mimetype: this.mimetype
-        }
-      });
-    },
-
-    bindDOM: function font_bindDom(data) {
+    bindDOM: function Font_bindDOM(data) {
       var fontName = this.loadedName;
 
       // Add the font-face rule to the document
@@ -13780,89 +15738,137 @@ var Font = (function Font() {
                  window.btoa(data) + ');');
       var rule = "@font-face { font-family:'" + fontName + "';src:" + url + '}';
 
-      document.documentElement.firstChild.appendChild(
-        document.createElement('style'));
+      var styleElement = document.createElement('style');
+      document.documentElement.getElementsByTagName('head')[0].appendChild(
+        styleElement);
 
-      var styleSheet = document.styleSheets[document.styleSheets.length - 1];
+      var styleSheet = styleElement.sheet;
       styleSheet.insertRule(rule, styleSheet.cssRules.length);
 
+      if (PDFJS.pdfBug && FontInspector.enabled)
+        FontInspector.fontAdded(this, url);
+
       return rule;
     },
 
-    charToGlyph: function fonts_charToGlyph(charcode) {
-      var unicode, width, codeIRQueue;
+    get spaceWidth() {
+      // trying to estimate space character width
+      var possibleSpaceReplacements = ['space', 'minus', 'one', 'i'];
+      var width;
+      for (var i = 0, ii = possibleSpaceReplacements.length; i < ii; i++) {
+        var glyphName = possibleSpaceReplacements[i];
+        // if possible, getting width by glyph name
+        if (glyphName in this.widths) {
+          width = this.widths[glyphName];
+          break;
+        }
+        var glyphUnicode = GlyphsUnicode[glyphName];
+        // finding the charcode via unicodeToCID map
+        var charcode = 0;
+        if (this.composite)
+          charcode = this.unicodeToCID[glyphUnicode];
+        // ... via toUnicode map
+        if (!charcode && 'toUnicode' in this)
+          charcode = this.toUnicode.indexOf(glyphUnicode);
+        // setting it to unicode if negative or undefined
+        if (!(charcode > 0))
+          charcode = glyphUnicode;
+        // trying to get width via charcode
+        width = this.widths[charcode];
+        if (width)
+          break; // the non-zero width found
+      }
+      width = (width || this.defaultWidth) * this.widthMultiplier;
+      return shadow(this, 'spaceWidth', width);
+    },
+
+    charToGlyph: function Font_charToGlyph(charcode) {
+      var fontCharCode, width, operatorList, disabled;
 
       var width = this.widths[charcode];
 
       switch (this.type) {
         case 'CIDFontType0':
           if (this.noUnicodeAdaptation) {
-            width = this.widths[this.cidToUnicode[charcode]];
-            unicode = charcode;
+            width = this.widths[this.unicodeToCID[charcode] || charcode];
+            fontCharCode = mapPrivateUseChars(charcode);
             break;
           }
-          unicode = adaptUnicode(this.cidToUnicode[charcode] || charcode);
+          fontCharCode = this.toFontChar[charcode] || charcode;
           break;
         case 'CIDFontType2':
           if (this.noUnicodeAdaptation) {
-            width = this.widths[this.cidToUnicode[charcode]];
-            unicode = charcode;
+            width = this.widths[this.unicodeToCID[charcode] || charcode];
+            fontCharCode = mapPrivateUseChars(charcode);
             break;
           }
-          unicode = adaptUnicode(this.cidToUnicode[charcode] || charcode);
+          fontCharCode = this.toFontChar[charcode] || charcode;
           break;
         case 'Type1':
           var glyphName = this.differences[charcode] || this.encoding[charcode];
+          if (!isNum(width))
+            width = this.widths[glyphName];
           if (this.noUnicodeAdaptation) {
-            if (!isNum(width))
-              width = this.widths[glyphName];
-            unicode = GlyphsUnicode[glyphName] || charcode;
+            fontCharCode = mapPrivateUseChars(GlyphsUnicode[glyphName] ||
+              charcode);
             break;
           }
-          unicode = this.glyphNameMap[glyphName] ||
-            adaptUnicode(GlyphsUnicode[glyphName] || charcode);
+          fontCharCode = this.glyphNameMap[glyphName] ||
+            GlyphsUnicode[glyphName] || charcode;
           break;
         case 'Type3':
           var glyphName = this.differences[charcode] || this.encoding[charcode];
-          codeIRQueue = this.charProcIRQueues[glyphName];
-          unicode = charcode;
+          operatorList = this.charProcOperatorList[glyphName];
+          fontCharCode = charcode;
           break;
         case 'TrueType':
+          if (this.useToFontChar) {
+            fontCharCode = this.toFontChar[charcode] || charcode;
+            break;
+          }
           var glyphName = this.differences[charcode] || this.encoding[charcode];
           if (!glyphName)
             glyphName = Encodings.StandardEncoding[charcode];
           if (!isNum(width))
             width = this.widths[glyphName];
           if (this.noUnicodeAdaptation) {
-            unicode = GlyphsUnicode[glyphName] || charcode;
+            fontCharCode = GlyphsUnicode[glyphName] || charcode;
             break;
           }
-          if (!this.hasEncoding) {
-            unicode = adaptUnicode(charcode);
+          if (!this.hasEncoding || this.isSymbolicFont) {
+            fontCharCode = this.useToFontChar ? this.toFontChar[charcode] :
+              charcode;
             break;
           }
-          if (this.hasShortCmap) {
-            var j = Encodings.MacRomanEncoding.indexOf(glyphName);
-            unicode = j >= 0 && !isSpecialUnicode(j) ? j :
-              this.glyphNameMap[glyphName];
-          } else {
-            unicode = glyphName in GlyphsUnicode ?
-              adaptUnicode(GlyphsUnicode[glyphName]) :
-              this.glyphNameMap[glyphName];
-          }
+
+          // MacRoman encoding address by re-encoding the cmap table
+          fontCharCode = glyphName in this.glyphNameMap ?
+            this.glyphNameMap[glyphName] : GlyphsUnicode[glyphName];
           break;
         default:
           warn('Unsupported font type: ' + this.type);
           break;
       }
+
+      var unicodeChars = !('toUnicode' in this) ? charcode :
+        this.toUnicode[charcode] || charcode;
+      if (typeof unicodeChars === 'number')
+        unicodeChars = String.fromCharCode(unicodeChars);
+
+      width = (isNum(width) ? width : this.defaultWidth) * this.widthMultiplier;
+      disabled = this.unicodeIsEnabled ?
+        !this.unicodeIsEnabled[fontCharCode] : false;
+
       return {
-        unicode: unicode,
-        width: isNum(width) ? width : this.defaultWidth,
-        codeIRQueue: codeIRQueue
+        fontChar: String.fromCharCode(fontCharCode),
+        unicode: unicodeChars,
+        width: width,
+        disabled: disabled,
+        operatorList: operatorList
       };
     },
 
-    charsToGlyphs: function fonts_chars2Glyphs(chars) {
+    charsToGlyphs: function Font_charsToGlyphs(chars) {
       var charsCache = this.charsCache;
       var glyphs;
 
@@ -13910,7 +15916,7 @@ var Font = (function Font() {
     }
   };
 
-  return constructor;
+  return Font;
 })();
 
 /*
@@ -14197,7 +16203,13 @@ var Type1Parser = function type1Parser() {
     while (str[index++] != ']')
       count++;
 
-    var array = str.substr(start, count).split(' ');
+    str = str.substr(start, count);
+
+    str = str.trim();
+    // Remove adjacent spaces
+    str = str.replace(/\s+/g, ' ');
+
+    var array = str.split(' ');
     for (var i = 0, ii = array.length; i < ii; i++)
       array[i] = parseFloat(array[i] || 0);
     return array;
@@ -14220,7 +16232,7 @@ var Type1Parser = function type1Parser() {
     return c == ' ' || c == '\n' || c == '\x0d';
   }
 
-  this.extractFontProgram = function t1_extractFontProgram(stream) {
+  this.extractFontProgram = function Type1Parser_extractFontProgram(stream) {
     var eexec = decrypt(stream, kEexecEncryptionKey, 4);
     var eexecStr = '';
     for (var i = 0, ii = eexec.length; i < ii; i++)
@@ -14231,7 +16243,7 @@ var Type1Parser = function type1Parser() {
       subrs: [],
       charstrings: [],
       properties: {
-        'private': {
+        'privateData': {
           'lenIV': 4
         }
       }
@@ -14260,7 +16272,7 @@ var Type1Parser = function type1Parser() {
           (token == 'RD' || token == '-|')) {
         i++;
         var data = eexec.slice(i, i + length);
-        var lenIV = program.properties.private['lenIV'];
+        var lenIV = program.properties.privateData['lenIV'];
         var encoded = decrypt(data, kCharStringsEncryptionKey, lenIV);
         var str = decodeCharString(encoded);
 
@@ -14300,7 +16312,7 @@ var Type1Parser = function type1Parser() {
                 var length = parseInt(getToken(), 10);
                 getToken(); // read in 'RD'
                 var data = eexec.slice(i + 1, i + 1 + length);
-                var lenIV = program.properties.private['lenIV'];
+                var lenIV = program.properties.privateData['lenIV'];
                 var encoded = decrypt(data, kCharStringsEncryptionKey, lenIV);
                 var str = decodeCharString(encoded);
                 i = i + 1 + length;
@@ -14316,12 +16328,12 @@ var Type1Parser = function type1Parser() {
             case '/FamilyOtherBlues':
             case '/StemSnapH':
             case '/StemSnapV':
-              program.properties.private[token.substring(1)] =
+              program.properties.privateData[token.substring(1)] =
                 readNumberArray(eexecStr, i + 1);
               break;
             case '/StdHW':
             case '/StdVW':
-              program.properties.private[token.substring(1)] =
+              program.properties.privateData[token.substring(1)] =
                 readNumberArray(eexecStr, i + 2)[0];
               break;
             case '/BlueShift':
@@ -14330,7 +16342,7 @@ var Type1Parser = function type1Parser() {
             case '/BlueScale':
             case '/LanguageGroup':
             case '/ExpansionFactor':
-              program.properties.private[token.substring(1)] =
+              program.properties.privateData[token.substring(1)] =
                 readNumber(eexecStr, i + 1);
               break;
           }
@@ -14345,7 +16357,8 @@ var Type1Parser = function type1Parser() {
     return program;
   };
 
-  this.extractFontHeader = function t1_extractFontHeader(stream, properties) {
+  this.extractFontHeader = function Type1Parser_extractFontHeader(stream,
+                                                                  properties) {
     var headerString = '';
     for (var i = 0, ii = stream.length; i < ii; i++)
       headerString += String.fromCharCode(stream[i]);
@@ -14354,14 +16367,14 @@ var Type1Parser = function type1Parser() {
     var count = headerString.length;
     for (var i = 0; i < count; i++) {
       var getToken = function getToken() {
-        var char = headerString[i];
-        while (i < count && (isSeparator(char) || char == '/'))
-          char = headerString[++i];
+        var character = headerString[i];
+        while (i < count && (isSeparator(character) || character == '/'))
+          character = headerString[++i];
 
         var token = '';
-        while (i < count && !(isSeparator(char) || char == '/')) {
-          token += char;
-          char = headerString[++i];
+        while (i < count && !(isSeparator(character) || character == '/')) {
+          token += character;
+          character = headerString[++i];
         }
 
         return token;
@@ -14421,7 +16434,7 @@ var Type1Parser = function type1Parser() {
  * The CFF class takes a Type1 file and wrap it into a
  * 'Compact Font Format' which itself embed Type2 charstrings.
  */
-var CFFStrings = [
+var CFFStandardStrings = [
   '.notdef', 'space', 'exclam', 'quotedbl', 'numbersign', 'dollar', 'percent',
   'ampersand', 'quoteright', 'parenleft', 'parenright', 'asterisk', 'plus',
   'comma', 'hyphen', 'period', 'slash', 'zero', 'one', 'two', 'three', 'four',
@@ -14491,7 +16504,8 @@ var CFFStrings = [
 
 var type1Parser = new Type1Parser();
 
-var CFF = function cffCFF(name, file, properties) {
+// Type1Font is also a CIDFontType0.
+var Type1Font = function Type1Font(name, file, properties) {
   // Get the data block containing glyphs and subrs informations
   var headerBlock = file.getBytes(properties.length1);
   type1Parser.extractFontHeader(headerBlock, properties);
@@ -14511,8 +16525,9 @@ var CFF = function cffCFF(name, file, properties) {
                         subrs, properties);
 };
 
-CFF.prototype = {
-  createCFFIndexHeader: function cff_createCFFIndexHeader(objects, isByte) {
+Type1Font.prototype = {
+  createCFFIndexHeader: function Type1Font_createCFFIndexHeader(objects,
+                                                                isByte) {
     // First 2 bytes contains the number of objects contained into this index
     var count = objects.length;
 
@@ -14548,7 +16563,7 @@ CFF.prototype = {
     return data;
   },
 
-  encodeNumber: function cff_encodeNumber(value) {
+  encodeNumber: function Type1Font_encodeNumber(value) {
     // some of the fonts has ouf-of-range values
     // they are just arithmetic overflows
     // make sanitizer happy
@@ -14566,25 +16581,16 @@ CFF.prototype = {
     }
   },
 
-  getOrderedCharStrings: function cff_getOrderedCharStrings(glyphs,
+  getOrderedCharStrings: function Type1Font_getOrderedCharStrings(glyphs,
                                                             properties) {
     var charstrings = [];
-    var reverseMapping = {};
-    var encoding = properties.baseEncoding;
     var i, length, glyphName;
-    for (i = 0, length = encoding.length; i < length; ++i) {
-      glyphName = encoding[i];
-      if (!glyphName || isSpecialUnicode(i))
-        continue;
-      reverseMapping[glyphName] = i;
-    }
-    reverseMapping['.notdef'] = 0;
     var unusedUnicode = kCmapGlyphOffset;
     for (i = 0, length = glyphs.length; i < length; i++) {
       var item = glyphs[i];
       var glyphName = item.glyph;
-      var unicode = glyphName in reverseMapping ?
-        reverseMapping[glyphName] : unusedUnicode++;
+      var unicode = glyphName in GlyphsUnicode ?
+        GlyphsUnicode[glyphName] : unusedUnicode++;
       charstrings.push({
         glyph: glyphName,
         unicode: unicode,
@@ -14601,7 +16607,8 @@ CFF.prototype = {
     return charstrings;
   },
 
-  getType2Charstrings: function cff_getType2Charstrings(type1Charstrings) {
+  getType2Charstrings: function Type1Font_getType2Charstrings(
+                                  type1Charstrings) {
     var type2Charstrings = [];
     var count = type1Charstrings.length;
     for (var i = 0; i < count; i++) {
@@ -14612,7 +16619,7 @@ CFF.prototype = {
     return type2Charstrings;
   },
 
-  getType2Subrs: function cff_getType2Subrs(type1Subrs) {
+  getType2Subrs: function Type1Font_getType2Subrs(type1Subrs) {
     var bias = 0;
     var count = type1Subrs.length;
     if (count < 1240)
@@ -14664,7 +16671,7 @@ CFF.prototype = {
     'hvcurveto': 31
   },
 
-  flattenCharstring: function flattenCharstring(charstring, map) {
+  flattenCharstring: function Type1Font_flattenCharstring(charstring, map) {
     // charstring changes size - can't cache .length in loop
     for (var i = 0; i < charstring.length; i++) {
       var command = charstring[i];
@@ -14691,7 +16698,7 @@ CFF.prototype = {
     return charstring;
   },
 
-  wrap: function wrap(name, glyphs, charstrings, subrs, properties) {
+  wrap: function Type1Font_wrap(name, glyphs, charstrings, subrs, properties) {
     var fields = {
       // major version, minor version, header size, offset size
       'header': '\x01\x00\x04\x04',
@@ -14735,7 +16742,7 @@ CFF.prototype = {
           dict += self.encodeNumber(offset) + '\x11'; // Charstrings
 
           offset = offset + fields.charstrings.length;
-          dict += self.encodeNumber(fields.private.length);
+          dict += self.encodeNumber(fields.privateData.length);
           dict += self.encodeNumber(offset) + '\x12'; // Private
 
           return header + String.fromCharCode(dict.length + 1) + dict;
@@ -14760,7 +16767,7 @@ CFF.prototype = {
 
         var count = glyphs.length;
         for (var i = 0; i < count; i++) {
-          var index = CFFStrings.indexOf(charstrings[i].glyph);
+          var index = CFFStandardStrings.indexOf(charstrings[i].glyph);
           // Some characters like asterikmath && circlecopyrt are
           // missing from the original strings, for the moment let's
           // map them to .notdef and see later if it cause any
@@ -14776,7 +16783,7 @@ CFF.prototype = {
       'charstrings': this.createCFFIndexHeader([[0x8B, 0x0E]].concat(glyphs),
                                                true),
 
-      'private': (function cffWrapPrivate(self) {
+      'privateData': (function cffWrapPrivate(self) {
         var data =
             '\x8b\x14' + // defaultWidth
             '\x8b\x15';  // nominalWidth
@@ -14794,9 +16801,9 @@ CFF.prototype = {
           ExpansionFactor: '\x0c\x18'
         };
         for (var field in fieldMap) {
-          if (!properties.private.hasOwnProperty(field))
+          if (!properties.privateData.hasOwnProperty(field))
             continue;
-          var value = properties.private[field];
+          var value = properties.privateData[field];
 
           if (isArray(value)) {
             data += self.encodeNumber(value[0]);
@@ -14829,106 +16836,31 @@ CFF.prototype = {
   }
 };
 
-var Type2CFF = (function type2CFF() {
-  // TODO: replace parsing code with the Type2Parser in font_utils.js
-  function constructor(file, properties) {
-    var bytes = file.getBytes();
-    this.bytes = bytes;
+var CFFFont = (function CFFFontClosure() {
+  function CFFFont(file, properties) {
     this.properties = properties;
 
-    this.data = this.parse();
+    var parser = new CFFParser(file, properties);
+    var cff = parser.parse();
+    var compiler = new CFFCompiler(cff);
+    this.readExtra(cff);
+    try {
+      this.data = compiler.compile();
+    } catch (e) {
+      warn('Failed to compile font ' + properties.loadedName);
+      // There may have just been an issue with the compiler, set the data
+      // anyway and hope the font loaded.
+      this.data = file;
+    }
   }
 
-  constructor.prototype = {
-    parse: function cff_parse() {
-      var header = this.parseHeader();
-      var properties = this.properties;
-      var nameIndex = this.parseIndex(header.endPos);
-
-      var dictIndex = this.parseIndex(nameIndex.endPos);
-      if (dictIndex.length != 1)
-        error('CFF contains more than 1 font');
-
-      var stringIndex = this.parseIndex(dictIndex.endPos);
-      var gsubrIndex = this.parseIndex(stringIndex.endPos);
-
-      var strings = this.getStrings(stringIndex);
-
-      var baseDict = this.parseDict(dictIndex.get(0).data);
-      var topDict = this.getTopDict(baseDict, strings);
-
-      var bytes = this.bytes;
-
-      var privateDict = {};
-      var privateInfo = topDict.Private;
-      if (privateInfo) {
-        var privOffset = privateInfo[1], privLength = privateInfo[0];
-        var privBytes = bytes.subarray(privOffset, privOffset + privLength);
-        baseDict = this.parseDict(privBytes);
-        privateDict = this.getPrivDict(baseDict, strings);
-      } else {
-        privateDict.defaultWidthX = properties.defaultWidth;
-      }
-
-      var charStrings = this.parseIndex(topDict.CharStrings);
-      var charset = this.parseCharsets(topDict.charset,
-                                       charStrings.length, strings);
-      var encoding = this.parseEncoding(topDict.Encoding, properties,
-                                             strings, charset);
-
-      var charset, encoding;
-      var isCIDFont = properties.subtype == 'CIDFontType0C';
-      if (isCIDFont) {
-        charset = [];
-        charset.length = charStrings.length;
-        encoding = this.parseCidMap(topDict.charset,
-                                    charStrings.length);
-      } else {
-        charset = this.parseCharsets(topDict.charset,
-                                     charStrings.length, strings);
-        encoding = this.parseEncoding(topDict.Encoding, properties,
-                                      strings, charset);
-      }
-
-      // The font sanitizer does not support CFF encoding with a
-      // supplement, since the encoding is not really use to map
-      // between gid to glyph, let's overwrite what is declared in
-      // the top dictionary to let the sanitizer think the font use
-      // StandardEncoding, that's a lie but that's ok.
-      if (encoding.hasSupplement)
-        bytes[topDict.Encoding] &= 0x7F;
-
-      // The CFF specification state that the 'dotsection' command
-      // (12, 0) is deprecated and treated as a no-op, but all Type2
-      // charstrings processors should support them. Unfortunately
-      // the font sanitizer don't. As a workaround the sequence (12, 0)
-      // is replaced by a useless (0, hmoveto).
-      var count = charStrings.length;
-      for (var i = 0; i < count; i++) {
-        var charstring = charStrings.get(i);
-
-        var start = charstring.start;
-        var data = charstring.data;
-        var length = data.length;
-        for (var j = 0; j <= length; j) {
-          var value = data[j++];
-          if (value == 12 && data[j++] == 0) {
-              bytes[start + j - 2] = 139;
-              bytes[start + j - 1] = 22;
-          } else if (value === 28) {
-            j += 2;
-          } else if (value >= 247 && value <= 254) {
-            j++;
-          } else if (value == 255) {
-            j += 4;
-          }
-        }
-      }
-
+  CFFFont.prototype = {
+    readExtra: function CFFFont_readExtra(cff) {
       // charstrings contains info about glyphs (one element per glyph
       // containing mappings for {unicode, width})
-      var charstrings = this.getCharStrings(charset, encoding.encoding,
-                                            privateDict, this.properties);
+      var charset = cff.charset.charset;
+      var encoding = cff.encoding ? cff.encoding.encoding : null;
+      var charstrings = this.getCharStrings(charset, encoding);
 
       // create the mapping between charstring and glyph id
       var glyphIds = [];
@@ -14937,301 +16869,127 @@ var Type2CFF = (function type2CFF() {
 
       this.charstrings = charstrings;
       this.glyphIds = glyphIds;
-
-      var data = [];
-      for (var i = 0, ii = bytes.length; i < ii; ++i)
-        data.push(bytes[i]);
-      return data;
     },
-
-    getCharStrings: function cff_charstrings(charsets, encoding,
-                                             privateDict, properties) {
+    getCharStrings: function CFFFont_getCharStrings(charsets, encoding) {
       var charstrings = [];
       var unicodeUsed = [];
       var unassignedUnicodeItems = [];
+      var inverseEncoding = [];
+      // CID fonts don't have an encoding.
+      if (encoding !== null)
+        for (var charcode in encoding)
+          inverseEncoding[encoding[charcode]] = charcode | 0;
+      else
+        inverseEncoding = charsets;
       for (var i = 0, ii = charsets.length; i < ii; i++) {
         var glyph = charsets[i];
-        var encodingFound = false;
-        for (var charcode in encoding) {
-          if (encoding[charcode] == i) {
-            var code = charcode | 0;
-            charstrings.push({
-              unicode: adaptUnicode(code),
-              code: code,
-              gid: i,
-              glyph: glyph
-            });
-            unicodeUsed[code] = true;
-            encodingFound = true;
-            break;
-          }
-        }
-        if (!encodingFound) {
+        if (glyph == '.notdef')
+          continue;
+
+        var code = inverseEncoding[i];
+        if (!code || isSpecialUnicode(code)) {
           unassignedUnicodeItems.push(i);
+          continue;
         }
+        charstrings.push({
+          unicode: code,
+          code: code,
+          gid: i,
+          glyph: glyph
+        });
+        unicodeUsed[code] = true;
       }
 
-      var nextUnusedUnicode = 0x21;
+      var nextUnusedUnicode = kCmapGlyphOffset;
       for (var j = 0, jj = unassignedUnicodeItems.length; j < jj; ++j) {
         var i = unassignedUnicodeItems[j];
         // giving unicode value anyway
-        while (unicodeUsed[nextUnusedUnicode])
+        while (nextUnusedUnicode in unicodeUsed)
           nextUnusedUnicode++;
-        var code = nextUnusedUnicode++;
+        var unicode = nextUnusedUnicode++;
         charstrings.push({
-          unicode: adaptUnicode(code),
-          code: code,
+          unicode: unicode,
+          code: inverseEncoding[i] || 0,
           gid: i,
           glyph: charsets[i]
         });
       }
 
       // sort the array by the unicode value (again)
-      charstrings.sort(function type2CFFGetCharStringsSort(a, b) {
+      charstrings.sort(function getCharStringsSort(a, b) {
         return a.unicode - b.unicode;
       });
       return charstrings;
-    },
-
-    parseEncoding: function cff_parseencoding(pos, properties, strings,
-                                              charset) {
-      var encoding = {};
-      var bytes = this.bytes;
-      var result = {
-        encoding: encoding,
-        hasSupplement: false
-      };
-
-      function readSupplement() {
-        var supplementsCount = bytes[pos++];
-        for (var i = 0; i < supplementsCount; i++) {
-          var code = bytes[pos++];
-          var sid = (bytes[pos++] << 8) + (bytes[pos++] & 0xff);
-          encoding[code] = properties.differences.indexOf(strings[sid]);
-        }
-      }
-
-      if (pos == 0 || pos == 1) {
-        var gid = 1;
-        var baseEncoding = pos ? Encodings.ExpertEncoding :
-                                 Encodings.StandardEncoding;
-        for (var i = 0, ii = charset.length; i < ii; i++) {
-          var index = baseEncoding.indexOf(charset[i]);
-          if (index != -1)
-            encoding[index] = gid++;
-        }
-      } else {
-        var format = bytes[pos++];
-        switch (format & 0x7f) {
-          case 0:
-            var glyphsCount = bytes[pos++];
-            for (var i = 1; i <= glyphsCount; i++)
-              encoding[bytes[pos++]] = i;
-            break;
-
-          case 1:
-            var rangesCount = bytes[pos++];
-            var gid = 1;
-            for (var i = 0; i < rangesCount; i++) {
-              var start = bytes[pos++];
-              var left = bytes[pos++];
-              for (var j = start; j <= start + left; j++)
-                encoding[j] = gid++;
-            }
-            break;
-
-          default:
-            error('Unknow encoding format: ' + format + ' in CFF');
-            break;
-        }
-        if (format & 0x80) {
-          readSupplement();
-          result.hasSupplement = true;
-        }
-      }
-      return result;
-    },
-
-    parseCharsets: function cff_parsecharsets(pos, length, strings) {
-      if (pos == 0) {
-        return ISOAdobeCharset.slice();
-      } else if (pos == 1) {
-        return ExpertCharset.slice();
-      } else if (pos == 2) {
-        return ExpertSubsetCharset.slice();
-      }
-
-      var bytes = this.bytes;
-      var format = bytes[pos++];
-      var charset = ['.notdef'];
-
-      // subtract 1 for the .notdef glyph
-      length -= 1;
-
-      switch (format) {
-        case 0:
-          for (var i = 0; i < length; i++) {
-            var sid = (bytes[pos++] << 8) | bytes[pos++];
-            charset.push(strings[sid]);
-          }
-          break;
-        case 1:
-          while (charset.length <= length) {
-            var sid = (bytes[pos++] << 8) | bytes[pos++];
-            var count = bytes[pos++];
-            for (var i = 0; i <= count; i++)
-              charset.push(strings[sid++]);
-          }
-          break;
-        case 2:
-          while (charset.length <= length) {
-            var sid = (bytes[pos++] << 8) | bytes[pos++];
-            var count = (bytes[pos++] << 8) | bytes[pos++];
-            for (var i = 0; i <= count; i++)
-              charset.push(strings[sid++]);
-          }
-          break;
-        default:
-          error('Unknown charset format');
-      }
-      return charset;
-    },
+    }
+  };
 
-    parseCidMap: function cff_parsecharsets(pos, length) {
-      var bytes = this.bytes;
-      var format = bytes[pos++];
+  return CFFFont;
+})();
 
-      var encoding = {};
-      var map = {encoding: encoding};
+var CFFParser = (function CFFParserClosure() {
+  function CFFParser(file, properties) {
+    this.bytes = file.getBytes();
+    this.properties = properties;
+  }
+  CFFParser.prototype = {
+    parse: function CFFParser_parse() {
+      var properties = this.properties;
+      var cff = new CFF();
+      this.cff = cff;
 
-      encoding[0] = 0;
+      // The first five sections must be in order, all the others are reached
+      // via offsets contained in one of the below.
+      var header = this.parseHeader();
+      var nameIndex = this.parseIndex(header.endPos);
+      var topDictIndex = this.parseIndex(nameIndex.endPos);
+      var stringIndex = this.parseIndex(topDictIndex.endPos);
+      var globalSubrIndex = this.parseIndex(stringIndex.endPos);
 
-      var gid = 1;
-      switch (format) {
-        case 0:
-          while (gid < length) {
-            var cid = (bytes[pos++] << 8) | bytes[pos++];
-            encoding[cid] = gid++;
-          }
-          break;
-        case 1:
-          while (gid < length) {
-            var cid = (bytes[pos++] << 8) | bytes[pos++];
-            var count = bytes[pos++];
-            for (var i = 0; i <= count; i++)
-              encoding[cid++] = gid++;
-          }
-          break;
-        case 2:
-          while (gid < length) {
-            var cid = (bytes[pos++] << 8) | bytes[pos++];
-            var count = (bytes[pos++] << 8) | bytes[pos++];
-            for (var i = 0; i <= count; i++)
-              encoding[cid++] = gid++;
-          }
-          break;
-        default:
-          error('Unknown charset format');
-      }
-      return map;
-    },
+      var topDictParsed = this.parseDict(topDictIndex.obj.get(0));
+      var topDict = this.createDict(CFFTopDict, topDictParsed, cff.strings);
 
-    getPrivDict: function cff_getprivdict(baseDict, strings) {
-      var dict = {};
+      cff.header = header.obj;
+      cff.names = this.parseNameIndex(nameIndex.obj);
+      cff.strings = this.parseStringIndex(stringIndex.obj);
+      cff.topDict = topDict;
+      cff.globalSubrIndex = globalSubrIndex.obj;
 
-      // default values
-      dict['defaultWidthX'] = 0;
-      dict['nominalWidthX'] = 0;
+      this.parsePrivateDict(cff.topDict);
 
-      for (var i = 0, ii = baseDict.length; i < ii; ++i) {
-        var pair = baseDict[i];
-        var key = pair[0];
-        var value = pair[1];
-        switch (key) {
-          case 20:
-            dict['defaultWidthX'] = value[0];
-          case 21:
-            dict['nominalWidthX'] = value[0];
-          default:
-            TODO('interpret top dict key: ' + key);
-        }
-      }
-      return dict;
-    },
-    getTopDict: function cff_gettopdict(baseDict, strings) {
-      var dict = {};
+      cff.isCIDFont = topDict.hasName('ROS');
 
-      // default values
-      dict['Encoding'] = 0;
-      dict['charset'] = 0;
+      var charStringOffset = topDict.getByName('CharStrings');
+      cff.charStrings = this.parseCharStrings(charStringOffset);
 
-      for (var i = 0, ii = baseDict.length; i < ii; ++i) {
-        var pair = baseDict[i];
-        var key = pair[0];
-        var value = pair[1];
-        switch (key) {
-          case 1:
-            dict['Notice'] = strings[value[0]];
-            break;
-          case 4:
-            dict['Weight'] = strings[value[0]];
-            break;
-          case 3094:
-            dict['BaseFontName'] = strings[value[0]];
-            break;
-          case 5:
-            dict['FontBBox'] = value;
-            break;
-          case 13:
-            dict['UniqueID'] = value[0];
-            break;
-          case 15:
-            dict['charset'] = value[0];
-            break;
-          case 16:
-            dict['Encoding'] = value[0];
-            break;
-          case 17:
-            dict['CharStrings'] = value[0];
-            break;
-          case 18:
-            dict['Private'] = value;
-            break;
-          case 3102:
-          case 3103:
-          case 3104:
-          case 3105:
-          case 3106:
-          case 3107:
-          case 3108:
-          case 3109:
-          case 3110:
-            dict['cidOperatorPresent'] = true;
-            break;
-          default:
-            TODO('interpret top dict key');
+      var charset, encoding;
+      if (cff.isCIDFont) {
+        var fdArrayIndex = this.parseIndex(topDict.getByName('FDArray')).obj;
+        for (var i = 0, ii = fdArrayIndex.count; i < ii; ++i) {
+          var dictRaw = fdArrayIndex.get(i);
+          var fontDict = this.createDict(CFFTopDict, this.parseDict(dictRaw),
+                                         cff.strings);
+          this.parsePrivateDict(fontDict);
+          cff.fdArray.push(fontDict);
         }
+        // cid fonts don't have an encoding
+        encoding = null;
+        charset = this.parseCharsets(topDict.getByName('charset'),
+                                     cff.charStrings.count, cff.strings, true);
+        cff.fdSelect = this.parseFDSelect(topDict.getByName('FDSelect'),
+                                             cff.charStrings.count);
+      } else {
+        charset = this.parseCharsets(topDict.getByName('charset'),
+                                     cff.charStrings.count, cff.strings, false);
+        encoding = this.parseEncoding(topDict.getByName('Encoding'),
+                                      properties,
+                                      cff.strings, charset.charset);
       }
-      return dict;
-    },
-    getStrings: function cff_getStrings(stringIndex) {
-      function bytesToString(bytesArray) {
-        var str = '';
-        for (var i = 0, ii = bytesArray.length; i < ii; i++)
-          str += String.fromCharCode(bytesArray[i]);
-        return str;
-      }
+      cff.charset = charset;
+      cff.encoding = encoding;
 
-      var stringArray = [];
-      for (var i = 0, ii = CFFStrings.length; i < ii; i++)
-        stringArray.push(CFFStrings[i]);
-
-      for (var i = 0, ii = stringIndex.length; i < ii; i++)
-        stringArray.push(bytesToString(stringIndex.get(i).data));
-
-      return stringArray;
+      return cff;
     },
-    parseHeader: function cff_parseHeader() {
+    parseHeader: function CFFParser_parseHeader() {
       var bytes = this.bytes;
       var offset = 0;
 
@@ -15239,17 +16997,18 @@ var Type2CFF = (function type2CFF() {
         ++offset;
 
       if (offset != 0) {
-        warning('cff data is shifted');
+        warn('cff data is shifted');
         bytes = bytes.subarray(offset);
         this.bytes = bytes;
       }
-
-      return {
-        endPos: bytes[2],
-        offsetSize: bytes[3]
-      };
+      var major = bytes[0];
+      var minor = bytes[1];
+      var hdrSize = bytes[2];
+      var offSize = bytes[3];
+      var header = new CFFHeader(major, minor, hdrSize, offSize);
+      return {obj: header, endPos: hdrSize};
     },
-    parseDict: function cff_parseDict(dict) {
+    parseDict: function CFFParser_parseDict(dict) {
       var pos = 0;
 
       function parseOperand() {
@@ -15266,11 +17025,11 @@ var Type2CFF = (function type2CFF() {
           value = (value << 8) | dict[pos++];
           value = (value << 8) | dict[pos++];
           return value;
-        } else if (value <= 246) {
+        } else if (value >= 32 && value <= 246) {
           return value - 139;
-        } else if (value <= 250) {
+        } else if (value >= 247 && value <= 250) {
           return ((value - 247) * 256) + dict[pos++] + 108;
-        } else if (value <= 254) {
+        } else if (value >= 251 && value <= 254) {
           return -((value - 251) * 256) - dict[pos++] - 108;
         } else {
           error('255 is not a valid DICT command');
@@ -15308,27 +17067,8 @@ var Type2CFF = (function type2CFF() {
       while (pos < end) {
         var b = dict[pos];
         if (b <= 21) {
-          if (b === 12) {
-            ++pos;
-            var op = dict[pos];
-            if ((op > 14 && op < 17) ||
-                (op > 23 && op < 30) || op > 38) {
-              warn('Invalid CFF dictionary key: ' + op);
-              // trying to replace it with initialRandomSeed
-              // to pass sanitizer
-              dict[pos] = 19;
-            }
-            var b = (b << 8) | op;
-          }
-          if (!operands.length && b == 8 &&
-              dict[pos + 1] == 9) {
-            // no operands for FamilyBlues, removing the key
-            // and next one is FamilyOtherBlues - skipping them
-            // also replacing FamilyBlues to pass sanitizer
-            dict[pos] = 139;
-            pos += 2;
-            continue;
-          }
+          if (b === 12)
+            b = (b << 8) | dict[++pos];
           entries.push([b, operands]);
           operands = [];
           ++pos;
@@ -15338,10 +17078,12 @@ var Type2CFF = (function type2CFF() {
       }
       return entries;
     },
-    parseIndex: function cff_parseIndex(pos) {
+    parseIndex: function CFFParser_parseIndex(pos) {
+      var cffIndex = new CFFIndex();
       var bytes = this.bytes;
-      var count = bytes[pos++] << 8 | bytes[pos++];
+      var count = (bytes[pos++] << 8) | bytes[pos++];
       var offsets = [];
+      var start = pos;
       var end = pos;
 
       if (count != 0) {
@@ -15359,142 +17101,1063 @@ var Type2CFF = (function type2CFF() {
         }
         end = offsets[count];
       }
+      for (var i = 0, ii = offsets.length - 1; i < ii; ++i) {
+        var offsetStart = offsets[i];
+        var offsetEnd = offsets[i + 1];
+        cffIndex.add(bytes.subarray(offsetStart, offsetEnd));
+      }
+      return {obj: cffIndex, endPos: end};
+    },
+    parseNameIndex: function CFFParser_parseNameIndex(index) {
+      var names = [];
+      for (var i = 0, ii = index.count; i < ii; ++i) {
+        var name = index.get(i);
+        // OTS doesn't allow names to be over 127 characters.
+        var length = Math.min(name.length, 127);
+        var data = [];
+        // OTS also only permits certain characters in the name.
+        for (var j = 0; j < length; ++j) {
+          var c = name[j];
+          if (j === 0 && c === 0) {
+            data[j] = c;
+            continue;
+          }
+          if ((c < 33 || c > 126) || c === 91 /* [ */ || c === 93 /* ] */ ||
+              c === 40 /* ( */ || c === 41 /* ) */ || c === 123 /* { */ ||
+              c === 125 /* } */ || c === 60 /* < */ || c === 62 /* > */ ||
+              c === 47 /* / */ || c === 37 /* % */) {
+            data[j] = 95;
+            continue;
+          }
+          data[j] = c;
+        }
+        names.push(String.fromCharCode.apply(null, data));
+      }
+      return names;
+    },
+    parseStringIndex: function CFFParser_parseStringIndex(index) {
+      var strings = new CFFStrings();
+      for (var i = 0, ii = index.count; i < ii; ++i) {
+        var data = index.get(i);
+        strings.add(String.fromCharCode.apply(null, data));
+      }
+      return strings;
+    },
+    createDict: function CFFParser_createDict(type, dict, strings) {
+      var cffDict = new type(strings);
+      var types = cffDict.types;
 
-      return {
-        get: function index_get(index) {
-          if (index >= count)
-            return null;
-
-          var start = offsets[index];
-          var end = offsets[index + 1];
-          return {
-            start: start,
-            end: end,
-            data: bytes.subarray(start, end)
-          };
-        },
-        length: count,
-        endPos: end
-      };
+      for (var i = 0, ii = dict.length; i < ii; ++i) {
+        var pair = dict[i];
+        var key = pair[0];
+        var value = pair[1];
+        cffDict.setByKey(key, value);
+      }
+      return cffDict;
+    },
+    parseCharStrings: function CFFParser_parseCharStrings(charStringOffset) {
+      var charStrings = this.parseIndex(charStringOffset).obj;
+      // The CFF specification state that the 'dotsection' command
+      // (12, 0) is deprecated and treated as a no-op, but all Type2
+      // charstrings processors should support them. Unfortunately
+      // the font sanitizer don't. As a workaround the sequence (12, 0)
+      // is replaced by a useless (0, hmoveto).
+      var count = charStrings.count;
+      for (var i = 0; i < count; i++) {
+        var charstring = charStrings.get(i);
+
+        var data = charstring;
+        var length = data.length;
+        for (var j = 0; j <= length; j) {
+          var value = data[j++];
+          if (value == 12 && data[j++] == 0) {
+              data[j - 2] = 139;
+              data[j - 1] = 22;
+          } else if (value === 28) {
+            j += 2;
+          } else if (value >= 247 && value <= 254) {
+            j++;
+          } else if (value == 255) {
+            j += 4;
+          }
+        }
+      }
+      return charStrings;
+    },
+    parsePrivateDict: function CFFParser_parsePrivateDict(parentDict) {
+      // no private dict, do nothing
+      if (!parentDict.hasName('Private'))
+        return;
+      var privateOffset = parentDict.getByName('Private');
+      // make sure the params are formatted correctly
+      if (!isArray(privateOffset) || privateOffset.length !== 2) {
+        parentDict.removeByName('Private');
+        return;
+      }
+      var size = privateOffset[0];
+      var offset = privateOffset[1];
+      // remove empty dicts or ones that refer to invalid location
+      if (size === 0 || offset >= this.bytes.length) {
+        parentDict.removeByName('Private');
+        return;
+      }
+
+      var privateDictEnd = offset + size;
+      var dictData = this.bytes.subarray(offset, privateDictEnd);
+      var dict = this.parseDict(dictData);
+      var privateDict = this.createDict(CFFPrivateDict, dict,
+                                        parentDict.strings);
+      parentDict.privateDict = privateDict;
+
+      // Parse the Subrs index also since it's relative to the private dict.
+      if (!privateDict.getByName('Subrs'))
+        return;
+      var subrsOffset = privateDict.getByName('Subrs');
+      var relativeOffset = offset + subrsOffset;
+      // Validate the offset.
+      if (subrsOffset === 0 || relativeOffset >= this.bytes.length) {
+        privateDict.removeByName('Subrs');
+        return;
+      }
+      var subrsIndex = this.parseIndex(relativeOffset);
+      privateDict.subrsIndex = subrsIndex.obj;
+    },
+    parseCharsets: function CFFParser_parseCharsets(pos, length, strings, cid) {
+      if (pos == 0) {
+        return new CFFCharset(true, CFFCharsetPredefinedTypes.ISO_ADOBE,
+                              ISOAdobeCharset);
+      } else if (pos == 1) {
+        return new CFFCharset(true, CFFCharsetPredefinedTypes.EXPERT,
+                              ExpertCharset);
+      } else if (pos == 2) {
+        return new CFFCharset(true, CFFCharsetPredefinedTypes.EXPERT_SUBSET,
+                              ExpertSubsetCharset);
+      }
+
+      var bytes = this.bytes;
+      var start = pos;
+      var format = bytes[pos++];
+      var charset = ['.notdef'];
+
+      // subtract 1 for the .notdef glyph
+      length -= 1;
+
+      switch (format) {
+        case 0:
+          for (var i = 0; i < length; i++) {
+            var id = (bytes[pos++] << 8) | bytes[pos++];
+            charset.push(cid ? id : strings.get(id));
+          }
+          break;
+        case 1:
+          while (charset.length <= length) {
+            var id = (bytes[pos++] << 8) | bytes[pos++];
+            var count = bytes[pos++];
+            for (var i = 0; i <= count; i++)
+              charset.push(cid ? id++ : strings.get(id++));
+          }
+          break;
+        case 2:
+          while (charset.length <= length) {
+            var id = (bytes[pos++] << 8) | bytes[pos++];
+            var count = (bytes[pos++] << 8) | bytes[pos++];
+            for (var i = 0; i <= count; i++)
+              charset.push(cid ? id++ : strings.get(id++));
+          }
+          break;
+        default:
+          error('Unknown charset format');
+      }
+      // Raw won't be needed if we actually compile the charset.
+      var end = pos;
+      var raw = bytes.subarray(start, end);
+
+      return new CFFCharset(false, format, charset, raw);
+    },
+    parseEncoding: function CFFParser_parseEncoding(pos,
+                                                    properties,
+                                                    strings,
+                                                    charset) {
+      var encoding = {};
+      var bytes = this.bytes;
+      var predefined = false;
+      var hasSupplement = false;
+      var format;
+      var raw = null;
+
+      function readSupplement() {
+        var supplementsCount = bytes[pos++];
+        for (var i = 0; i < supplementsCount; i++) {
+          var code = bytes[pos++];
+          var sid = (bytes[pos++] << 8) + (bytes[pos++] & 0xff);
+          encoding[code] = properties.differences.indexOf(strings.get(sid));
+        }
+      }
+
+      if (pos == 0 || pos == 1) {
+        predefined = true;
+        format = pos;
+        var gid = 1;
+        var baseEncoding = pos ? Encodings.ExpertEncoding :
+                                 Encodings.StandardEncoding;
+        for (var i = 0, ii = charset.length; i < ii; i++) {
+          var index = baseEncoding.indexOf(charset[i]);
+          if (index != -1)
+            encoding[index] = gid++;
+        }
+      } else {
+        var dataStart = pos;
+        var format = bytes[pos++];
+        switch (format & 0x7f) {
+          case 0:
+            var glyphsCount = bytes[pos++];
+            for (var i = 1; i <= glyphsCount; i++)
+              encoding[bytes[pos++]] = i;
+            break;
+
+          case 1:
+            var rangesCount = bytes[pos++];
+            var gid = 1;
+            for (var i = 0; i < rangesCount; i++) {
+              var start = bytes[pos++];
+              var left = bytes[pos++];
+              for (var j = start; j <= start + left; j++)
+                encoding[j] = gid++;
+            }
+            break;
+
+          default:
+            error('Unknow encoding format: ' + format + ' in CFF');
+            break;
+        }
+        var dataEnd = pos;
+        if (format & 0x80) {
+          // The font sanitizer does not support CFF encoding with a
+          // supplement, since the encoding is not really used to map
+          // between gid to glyph, let's overwrite what is declared in
+          // the top dictionary to let the sanitizer think the font use
+          // StandardEncoding, that's a lie but that's ok.
+          bytes[dataStart] &= 0x7f;
+          readSupplement();
+          hasSupplement = true;
+        }
+        raw = bytes.subarray(dataStart, dataEnd);
+      }
+      format = format & 0x7f;
+      return new CFFEncoding(predefined, format, encoding, raw);
+    },
+    parseFDSelect: function CFFParser_parseFDSelect(pos, length) {
+      var start = pos;
+      var bytes = this.bytes;
+      var format = bytes[pos++];
+      var fdSelect = [];
+      switch (format) {
+        case 0:
+          for (var i = 0; i < length; ++i) {
+            var id = bytes[pos++];
+            fdSelect.push(id);
+          }
+          break;
+        case 3:
+          var rangesCount = (bytes[pos++] << 8) | bytes[pos++];
+          for (var i = 0; i < rangesCount; ++i) {
+            var first = (bytes[pos++] << 8) | bytes[pos++];
+            var fdIndex = bytes[pos++];
+            var next = (bytes[pos] << 8) | bytes[pos + 1];
+            for (var j = first; j < next; ++j)
+              fdSelect.push(fdIndex);
+          }
+          // Advance past the sentinel(next).
+          pos += 2;
+          break;
+        default:
+          error('Unknown fdselect format ' + format);
+          break;
+      }
+      var end = pos;
+      return new CFFFDSelect(fdSelect, bytes.subarray(start, end));
     }
   };
+  return CFFParser;
+})();
 
-  return constructor;
+// Compact Font Format
+var CFF = (function CFFClosure() {
+  function CFF() {
+    this.header = null;
+    this.names = [];
+    this.topDict = null;
+    this.strings = new CFFStrings();
+    this.globalSubrIndex = null;
+
+    // The following could really be per font, but since we only have one font
+    // store them here.
+    this.encoding = null;
+    this.charset = null;
+    this.charStrings = null;
+    this.fdArray = [];
+    this.fdSelect = null;
+
+    this.isCIDFont = false;
+  }
+  return CFF;
 })();
 
-/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
+var CFFHeader = (function CFFHeaderClosure() {
+  function CFFHeader(major, minor, hdrSize, offSize) {
+    this.major = major;
+    this.minor = minor;
+    this.hdrSize = hdrSize;
+    this.offSize = offSize;
+  }
+  return CFFHeader;
+})();
 
-'use strict';
+var CFFStrings = (function CFFStringsClosure() {
+  function CFFStrings() {
+    this.strings = [];
+  }
+  CFFStrings.prototype = {
+    get: function CFFStrings_get(index) {
+      if (index >= 0 && index <= 390)
+        return CFFStandardStrings[index];
+      if (index - 391 <= this.strings.length)
+        return this.strings[index - 391];
+      return CFFStandardStrings[0];
+    },
+    add: function CFFStrings_add(value) {
+      this.strings.push(value);
+    },
+    get count() {
+      return this.strings.length;
+    }
+  };
+  return CFFStrings;
+})();
 
-var GlyphsUnicode = {
-  A: 0x0041,
-  AE: 0x00C6,
-  AEacute: 0x01FC,
-  AEmacron: 0x01E2,
-  AEsmall: 0xF7E6,
-  Aacute: 0x00C1,
-  Aacutesmall: 0xF7E1,
-  Abreve: 0x0102,
-  Abreveacute: 0x1EAE,
-  Abrevecyrillic: 0x04D0,
-  Abrevedotbelow: 0x1EB6,
-  Abrevegrave: 0x1EB0,
-  Abrevehookabove: 0x1EB2,
-  Abrevetilde: 0x1EB4,
-  Acaron: 0x01CD,
-  Acircle: 0x24B6,
-  Acircumflex: 0x00C2,
-  Acircumflexacute: 0x1EA4,
-  Acircumflexdotbelow: 0x1EAC,
-  Acircumflexgrave: 0x1EA6,
-  Acircumflexhookabove: 0x1EA8,
-  Acircumflexsmall: 0xF7E2,
-  Acircumflextilde: 0x1EAA,
-  Acute: 0xF6C9,
-  Acutesmall: 0xF7B4,
-  Acyrillic: 0x0410,
-  Adblgrave: 0x0200,
-  Adieresis: 0x00C4,
-  Adieresiscyrillic: 0x04D2,
-  Adieresismacron: 0x01DE,
-  Adieresissmall: 0xF7E4,
-  Adotbelow: 0x1EA0,
-  Adotmacron: 0x01E0,
-  Agrave: 0x00C0,
-  Agravesmall: 0xF7E0,
-  Ahookabove: 0x1EA2,
-  Aiecyrillic: 0x04D4,
-  Ainvertedbreve: 0x0202,
-  Alpha: 0x0391,
-  Alphatonos: 0x0386,
-  Amacron: 0x0100,
-  Amonospace: 0xFF21,
-  Aogonek: 0x0104,
-  Aring: 0x00C5,
-  Aringacute: 0x01FA,
-  Aringbelow: 0x1E00,
-  Aringsmall: 0xF7E5,
-  Asmall: 0xF761,
-  Atilde: 0x00C3,
-  Atildesmall: 0xF7E3,
-  Aybarmenian: 0x0531,
-  B: 0x0042,
-  Bcircle: 0x24B7,
-  Bdotaccent: 0x1E02,
-  Bdotbelow: 0x1E04,
-  Becyrillic: 0x0411,
-  Benarmenian: 0x0532,
-  Beta: 0x0392,
-  Bhook: 0x0181,
-  Blinebelow: 0x1E06,
-  Bmonospace: 0xFF22,
-  Brevesmall: 0xF6F4,
-  Bsmall: 0xF762,
-  Btopbar: 0x0182,
-  C: 0x0043,
-  Caarmenian: 0x053E,
-  Cacute: 0x0106,
-  Caron: 0xF6CA,
-  Caronsmall: 0xF6F5,
-  Ccaron: 0x010C,
-  Ccedilla: 0x00C7,
-  Ccedillaacute: 0x1E08,
-  Ccedillasmall: 0xF7E7,
-  Ccircle: 0x24B8,
-  Ccircumflex: 0x0108,
-  Cdot: 0x010A,
-  Cdotaccent: 0x010A,
-  Cedillasmall: 0xF7B8,
-  Chaarmenian: 0x0549,
-  Cheabkhasiancyrillic: 0x04BC,
-  Checyrillic: 0x0427,
-  Chedescenderabkhasiancyrillic: 0x04BE,
-  Chedescendercyrillic: 0x04B6,
-  Chedieresiscyrillic: 0x04F4,
-  Cheharmenian: 0x0543,
-  Chekhakassiancyrillic: 0x04CB,
-  Cheverticalstrokecyrillic: 0x04B8,
-  Chi: 0x03A7,
-  Chook: 0x0187,
-  Circumflexsmall: 0xF6F6,
-  Cmonospace: 0xFF23,
-  Coarmenian: 0x0551,
-  Csmall: 0xF763,
-  D: 0x0044,
-  DZ: 0x01F1,
-  DZcaron: 0x01C4,
-  Daarmenian: 0x0534,
-  Dafrican: 0x0189,
-  Dcaron: 0x010E,
-  Dcedilla: 0x1E10,
-  Dcircle: 0x24B9,
-  Dcircumflexbelow: 0x1E12,
-  Dcroat: 0x0110,
-  Ddotaccent: 0x1E0A,
-  Ddotbelow: 0x1E0C,
-  Decyrillic: 0x0414,
-  Deicoptic: 0x03EE,
+var CFFIndex = (function CFFIndexClosure() {
+  function CFFIndex() {
+    this.objects = [];
+    this.length = 0;
+  }
+  CFFIndex.prototype = {
+    add: function CFFIndex_add(data) {
+      this.length += data.length;
+      this.objects.push(data);
+    },
+    get: function CFFIndex_get(index) {
+      return this.objects[index];
+    },
+    get count() {
+      return this.objects.length;
+    }
+  };
+  return CFFIndex;
+})();
+
+var CFFDict = (function CFFDictClosure() {
+  function CFFDict(tables, strings) {
+    this.keyToNameMap = tables.keyToNameMap;
+    this.nameToKeyMap = tables.nameToKeyMap;
+    this.defaults = tables.defaults;
+    this.types = tables.types;
+    this.opcodes = tables.opcodes;
+    this.order = tables.order;
+    this.strings = strings;
+    this.values = {};
+  }
+  CFFDict.prototype = {
+    // value should always be an array
+    setByKey: function CFFDict_setByKey(key, value) {
+      if (!(key in this.keyToNameMap))
+        return false;
+      // ignore empty values
+      if (value.length === 0)
+        return true;
+      var type = this.types[key];
+      // remove the array wrapping these types of values
+      if (type === 'num' || type === 'sid' || type === 'offset')
+        value = value[0];
+      this.values[key] = value;
+      return true;
+    },
+    hasName: function CFFDict_hasName(name) {
+      return this.nameToKeyMap[name] in this.values;
+    },
+    getByName: function CFFDict_getByName(name) {
+      if (!(name in this.nameToKeyMap))
+        error('Invalid dictionary name "' + name + '"');
+      var key = this.nameToKeyMap[name];
+      if (!(key in this.values))
+        return this.defaults[key];
+      return this.values[key];
+    },
+    removeByName: function CFFDict_removeByName(name) {
+      delete this.values[this.nameToKeyMap[name]];
+    }
+  };
+  CFFDict.createTables = function CFFDict_createTables(layout) {
+    var tables = {
+      keyToNameMap: {},
+      nameToKeyMap: {},
+      defaults: {},
+      types: {},
+      opcodes: {},
+      order: []
+    };
+    for (var i = 0, ii = layout.length; i < ii; ++i) {
+      var entry = layout[i];
+      var key = isArray(entry[0]) ? (entry[0][0] << 8) + entry[0][1] : entry[0];
+      tables.keyToNameMap[key] = entry[1];
+      tables.nameToKeyMap[entry[1]] = key;
+      tables.types[key] = entry[2];
+      tables.defaults[key] = entry[3];
+      tables.opcodes[key] = isArray(entry[0]) ? entry[0] : [entry[0]];
+      tables.order.push(key);
+    }
+    return tables;
+  };
+  return CFFDict;
+})();
+
+var CFFTopDict = (function CFFTopDictClosure() {
+  var layout = [
+    [[12, 30], 'ROS', ['sid', 'sid', 'num'], null],
+    [[12, 20], 'SyntheticBase', 'num', null],
+    [0, 'version', 'sid', null],
+    [1, 'Notice', 'sid', null],
+    [[12, 0], 'Copyright', 'sid', null],
+    [2, 'FullName', 'sid', null],
+    [3, 'FamilyName', 'sid', null],
+    [4, 'Weight', 'sid', null],
+    [[12, 1], 'isFixedPitch', 'num', 0],
+    [[12, 2], 'ItalicAngle', 'num', 0],
+    [[12, 3], 'UnderlinePosition', 'num', -100],
+    [[12, 4], 'UnderlineThickness', 'num', 50],
+    [[12, 5], 'PaintType', 'num', 0],
+    [[12, 6], 'CharstringType', 'num', 2],
+    [[12, 7], 'FontMatrix', ['num', 'num', 'num', 'num', 'num', 'num'],
+                            [.001, 0, 0, .001, 0, 0]],
+    [13, 'UniqueID', 'num', null],
+    [5, 'FontBBox', ['num', 'num', 'num', 'num'], [0, 0, 0, 0]],
+    [[12, 8], 'StrokeWidth', 'num', 0],
+    [14, 'XUID', 'array', null],
+    [15, 'charset', 'offset', 0],
+    [16, 'Encoding', 'offset', 0],
+    [17, 'CharStrings', 'offset', 0],
+    [18, 'Private', ['offset', 'offset'], null],
+    [[12, 21], 'PostScript', 'sid', null],
+    [[12, 22], 'BaseFontName', 'sid', null],
+    [[12, 23], 'BaseFontBlend', 'delta', null],
+    [[12, 31], 'CIDFontVersion', 'num', 0],
+    [[12, 32], 'CIDFontRevision', 'num', 0],
+    [[12, 33], 'CIDFontType', 'num', 0],
+    [[12, 34], 'CIDCount', 'num', 8720],
+    [[12, 35], 'UIDBase', 'num', null],
+    [[12, 36], 'FDArray', 'offset', null],
+    [[12, 37], 'FDSelect', 'offset', null],
+    [[12, 38], 'FontName', 'sid', null]];
+  var tables = null;
+  function CFFTopDict(strings) {
+    if (tables === null)
+      tables = CFFDict.createTables(layout);
+    CFFDict.call(this, tables, strings);
+    this.privateDict = null;
+  }
+  CFFTopDict.prototype = Object.create(CFFDict.prototype);
+  return CFFTopDict;
+})();
+
+var CFFPrivateDict = (function CFFPrivateDictClosure() {
+  var layout = [
+    [6, 'BlueValues', 'delta', null],
+    [7, 'OtherBlues', 'delta', null],
+    [8, 'FamilyBlues', 'delta', null],
+    [9, 'FamilyOtherBlues', 'delta', null],
+    [[12, 9], 'BlueScale', 'num', 0.039625],
+    [[12, 10], 'BlueShift', 'num', 7],
+    [[12, 11], 'BlueFuzz', 'num', 1],
+    [10, 'StdHW', 'num', null],
+    [11, 'StdVW', 'num', null],
+    [[12, 12], 'StemSnapH', 'delta', null],
+    [[12, 13], 'StemSnapV', 'delta', null],
+    [[12, 14], 'ForceBold', 'num', 0],
+    [[12, 17], 'LanguageGroup', 'num', 0],
+    [[12, 18], 'ExpansionFactor', 'num', 0.06],
+    [[12, 19], 'initialRandomSeed', 'num', 0],
+    [19, 'Subrs', 'offset', null],
+    [20, 'defaultWidthX', 'num', 0],
+    [21, 'nominalWidthX', 'num', 0]
+  ];
+  var tables = null;
+  function CFFPrivateDict(strings) {
+    if (tables === null)
+      tables = CFFDict.createTables(layout);
+    CFFDict.call(this, tables, strings);
+    this.subrsIndex = null;
+  }
+  CFFPrivateDict.prototype = Object.create(CFFDict.prototype);
+  return CFFPrivateDict;
+})();
+
+var CFFCharsetPredefinedTypes = {
+  ISO_ADOBE: 0,
+  EXPERT: 1,
+  EXPERT_SUBSET: 2
+};
+var CFFCharsetEmbeddedTypes = {
+  FORMAT0: 0,
+  FORMAT1: 1,
+  FORMAT2: 2
+};
+var CFFCharset = (function CFFCharsetClosure() {
+  function CFFCharset(predefined, format, charset, raw) {
+    this.predefined = predefined;
+    this.format = format;
+    this.charset = charset;
+    this.raw = raw;
+  }
+  return CFFCharset;
+})();
+
+var CFFEncodingPredefinedTypes = {
+  STANDARD: 0,
+  EXPERT: 1
+};
+var CFFCharsetEmbeddedTypes = {
+  FORMAT0: 0,
+  FORMAT1: 1
+};
+var CFFEncoding = (function CFFEncodingClosure() {
+  function CFFEncoding(predefined, format, encoding, raw) {
+    this.predefined = predefined;
+    this.format = format;
+    this.encoding = encoding;
+    this.raw = raw;
+  }
+  return CFFEncoding;
+})();
+
+var CFFFDSelect = (function CFFFDSelectClosure() {
+  function CFFFDSelect(fdSelect, raw) {
+    this.fdSelect = fdSelect;
+    this.raw = raw;
+  }
+  return CFFFDSelect;
+})();
+
+// Helper class to keep track of where an offset is within the data and helps
+// filling in that offset once it's known.
+var CFFOffsetTracker = (function CFFOffsetTrackerClosure() {
+  function CFFOffsetTracker() {
+    this.offsets = {};
+  }
+  CFFOffsetTracker.prototype = {
+    isTracking: function CFFOffsetTracker_isTracking(key) {
+      return key in this.offsets;
+    },
+    track: function CFFOffsetTracker_track(key, location) {
+      if (key in this.offsets)
+        error('Already tracking location of ' + key);
+      this.offsets[key] = location;
+    },
+    offset: function CFFOffsetTracker_offset(value) {
+      for (var key in this.offsets) {
+        this.offsets[key] += value;
+      }
+    },
+    setEntryLocation: function CFFOffsetTracker_setEntryLocation(key,
+                                                                 values,
+                                                                 output) {
+      if (!(key in this.offsets))
+        error('Not tracking location of ' + key);
+      var data = output.data;
+      var dataOffset = this.offsets[key];
+      var size = 5;
+      for (var i = 0, ii = values.length; i < ii; ++i) {
+        var offset0 = i * size + dataOffset;
+        var offset1 = offset0 + 1;
+        var offset2 = offset0 + 2;
+        var offset3 = offset0 + 3;
+        var offset4 = offset0 + 4;
+        // It's easy to screw up offsets so perform this sanity check.
+        if (data[offset0] !== 0x1d || data[offset1] !== 0 ||
+            data[offset2] !== 0 || data[offset3] !== 0 || data[offset4] !== 0)
+          error('writing to an offset that is not empty');
+        var value = values[i];
+        data[offset0] = 0x1d;
+        data[offset1] = (value >> 24) & 0xFF;
+        data[offset2] = (value >> 16) & 0xFF;
+        data[offset3] = (value >> 8) & 0xFF;
+        data[offset4] = value & 0xFF;
+      }
+    }
+  };
+  return CFFOffsetTracker;
+})();
+
+// Takes a CFF and converts it to the binary representation.
+var CFFCompiler = (function CFFCompilerClosure() {
+  function stringToArray(str) {
+    var array = [];
+    for (var i = 0, ii = str.length; i < ii; ++i)
+      array[i] = str.charCodeAt(i);
+
+    return array;
+  };
+  function CFFCompiler(cff) {
+    this.cff = cff;
+  }
+  CFFCompiler.prototype = {
+    compile: function CFFCompiler_compile() {
+      var cff = this.cff;
+      var output = {
+        data: [],
+        length: 0,
+        add: function CFFCompiler_add(data) {
+          this.data = this.data.concat(data);
+          this.length = this.data.length;
+        }
+      };
+
+      // Compile the five entries that must be in order.
+      var header = this.compileHeader(cff.header);
+      output.add(header);
+
+      var nameIndex = this.compileNameIndex(cff.names);
+      output.add(nameIndex);
+
+      var compiled = this.compileTopDicts([cff.topDict], output.length);
+      output.add(compiled.output);
+      var topDictTracker = compiled.trackers[0];
+
+      var stringIndex = this.compileStringIndex(cff.strings.strings);
+      output.add(stringIndex);
+
+      var globalSubrIndex = this.compileIndex(cff.globalSubrIndex);
+      output.add(globalSubrIndex);
+
+      // Now start on the other entries that have no specfic order.
+      if (cff.encoding && cff.topDict.hasName('Encoding')) {
+        if (cff.encoding.predefined) {
+          topDictTracker.setEntryLocation('Encoding', [cff.encoding.format],
+                                          output);
+        } else {
+          var encoding = this.compileEncoding(cff.encoding);
+          topDictTracker.setEntryLocation('Encoding', [output.length], output);
+          output.add(encoding);
+        }
+      }
+
+      if (cff.charset && cff.topDict.hasName('charset')) {
+        if (cff.charset.predefined) {
+          topDictTracker.setEntryLocation('charset', [cff.charset.format],
+                                          output);
+        } else {
+          var charset = this.compileCharset(cff.charset);
+          topDictTracker.setEntryLocation('charset', [output.length], output);
+          output.add(charset);
+        }
+      }
+
+      var charStrings = this.compileCharStrings(cff.charStrings);
+      topDictTracker.setEntryLocation('CharStrings', [output.length], output);
+      output.add(charStrings);
+
+      if (cff.isCIDFont) {
+        // For some reason FDSelect must be in front of FDArray on windows. OSX
+        // and linux don't seem to care.
+        topDictTracker.setEntryLocation('FDSelect', [output.length], output);
+        var fdSelect = this.compileFDSelect(cff.fdSelect.raw);
+        output.add(fdSelect);
+
+        var compiled = this.compileTopDicts(cff.fdArray, output.length);
+        topDictTracker.setEntryLocation('FDArray', [output.length], output);
+        output.add(compiled.output);
+        var fontDictTrackers = compiled.trackers;
+
+        this.compilePrivateDicts(cff.fdArray, fontDictTrackers, output);
+      }
+
+      this.compilePrivateDicts([cff.topDict], [topDictTracker], output);
+
+      return output.data;
+    },
+    encodeNumber: function CFFCompiler_encodeNumber(value) {
+      if (parseFloat(value) == parseInt(value) && !isNaN(value)) // isInt
+        return this.encodeInteger(value);
+      else
+        return this.encodeFloat(value);
+    },
+    encodeFloat: function CFFCompiler_encodeFloat(value) {
+      value = value.toString();
+      // Strip off the any leading zeros.
+      if (value.substr(0, 2) === '0.')
+        value = value.substr(1);
+      else if (value.substr(0, 3) === '-0.')
+        value = '-' + value.substr(2);
+      var nibbles = [];
+      for (var i = 0, ii = value.length; i < ii; ++i) {
+        var a = value.charAt(i), b = value.charAt(i + 1);
+        var nibble;
+        if (a === 'e' && b === '-') {
+          nibble = 0xc;
+          ++i;
+        } else if (a === '.') {
+          nibble = 0xa;
+        } else if (a === 'E') {
+          nibble = 0xb;
+        } else if (a === '-') {
+          nibble = 0xe;
+        } else {
+          nibble = a;
+        }
+        nibbles.push(nibble);
+      }
+      nibbles.push(0xf);
+      if (nibbles.length % 2)
+        nibbles.push(0xf);
+      var out = [30];
+      for (var i = 0, ii = nibbles.length; i < ii; i += 2)
+        out.push(nibbles[i] << 4 | nibbles[i + 1]);
+      return out;
+    },
+    encodeInteger: function CFFCompiler_encodeInteger(value) {
+      var code;
+      if (value >= -107 && value <= 107) {
+        code = [value + 139];
+      } else if (value >= 108 && value <= 1131) {
+        value = [value - 108];
+        code = [(value >> 8) + 247, value & 0xFF];
+      } else if (value >= -1131 && value <= -108) {
+        value = -value - 108;
+        code = [(value >> 8) + 251, value & 0xFF];
+      } else if (value >= -32768 && value <= 32767) {
+        code = [0x1c, (value >> 8) & 0xFF, value & 0xFF];
+      } else {
+        code = [0x1d,
+                (value >> 24) & 0xFF,
+                (value >> 16) & 0xFF,
+                (value >> 8) & 0xFF,
+                 value & 0xFF];
+      }
+      return code;
+    },
+    compileHeader: function CFFCompiler_compileHeader(header) {
+      return [
+        header.major,
+        header.minor,
+        header.hdrSize,
+        header.offSize
+      ];
+    },
+    compileNameIndex: function CFFCompiler_compileNameIndex(names) {
+      var nameIndex = new CFFIndex();
+      for (var i = 0, ii = names.length; i < ii; ++i)
+        nameIndex.add(stringToArray(names[i]));
+      return this.compileIndex(nameIndex);
+    },
+    compileTopDicts: function CFFCompiler_compileTopDicts(dicts, length) {
+      var fontDictTrackers = [];
+      var fdArrayIndex = new CFFIndex();
+      for (var i = 0, ii = dicts.length; i < ii; ++i) {
+        var fontDict = dicts[i];
+        var fontDictTracker = new CFFOffsetTracker();
+        var fontDictData = this.compileDict(fontDict, fontDictTracker);
+        fontDictTrackers.push(fontDictTracker);
+        fdArrayIndex.add(fontDictData);
+        fontDictTracker.offset(length);
+      }
+      fdArrayIndex = this.compileIndex(fdArrayIndex, fontDictTrackers);
+      return {
+        trackers: fontDictTrackers,
+        output: fdArrayIndex
+      };
+    },
+    compilePrivateDicts: function CFFCompiler_compilePrivateDicts(dicts,
+                                                                  trackers,
+                                                                  output) {
+      for (var i = 0, ii = dicts.length; i < ii; ++i) {
+        var fontDict = dicts[i];
+        if (!fontDict.privateDict || !fontDict.hasName('Private'))
+          continue;
+        var privateDict = fontDict.privateDict;
+        var privateDictTracker = new CFFOffsetTracker();
+        var privateDictData = this.compileDict(privateDict, privateDictTracker);
+
+        privateDictTracker.offset(output.length);
+        trackers[i].setEntryLocation('Private',
+                                     [privateDictData.length, output.length],
+                                     output);
+        output.add(privateDictData);
+
+        if (privateDict.subrsIndex && privateDict.hasName('Subrs')) {
+          var subrs = this.compileIndex(privateDict.subrsIndex);
+          privateDictTracker.setEntryLocation('Subrs', [privateDictData.length],
+                                              output);
+          output.add(subrs);
+        }
+      }
+    },
+    compileDict: function CFFCompiler_compileDict(dict, offsetTracker) {
+      var out = [];
+      // The dictionary keys must be in a certain order.
+      var order = dict.order;
+      for (var i = 0; i < order.length; ++i) {
+        var key = order[i];
+        if (!(key in dict.values))
+          continue;
+        var values = dict.values[key];
+        var types = dict.types[key];
+        if (!isArray(types)) types = [types];
+        if (!isArray(values)) values = [values];
+
+        // Remove any empty dict values.
+        if (values.length === 0)
+          continue;
+
+        for (var j = 0, jj = types.length; j < jj; ++j) {
+          var type = types[j];
+          var value = values[j];
+          switch (type) {
+            case 'num':
+            case 'sid':
+              out = out.concat(this.encodeNumber(value));
+              break;
+            case 'offset':
+              // For offsets we just insert a 32bit integer so we don't have to
+              // deal with figuring out the length of the offset when it gets
+              // replaced later on by the compiler.
+              var name = dict.keyToNameMap[key];
+              // Some offsets have the offset and the length, so just record the
+              // position of the first one.
+              if (!offsetTracker.isTracking(name))
+                offsetTracker.track(name, out.length);
+              out = out.concat([0x1d, 0, 0, 0, 0]);
+              break;
+            case 'array':
+            case 'delta':
+              out = out.concat(this.encodeNumber(value));
+              for (var k = 1, kk = values.length; k < kk; ++k)
+                out = out.concat(this.encodeNumber(values[k]));
+              break;
+            default:
+              error('Unknown data type of ' + type);
+              break;
+          }
+        }
+        out = out.concat(dict.opcodes[key]);
+      }
+      return out;
+    },
+    compileStringIndex: function CFFCompiler_compileStringIndex(strings) {
+      var stringIndex = new CFFIndex();
+      for (var i = 0, ii = strings.length; i < ii; ++i)
+        stringIndex.add(stringToArray(strings[i]));
+      return this.compileIndex(stringIndex);
+    },
+    compileGlobalSubrIndex: function CFFCompiler_compileGlobalSubrIndex() {
+      var globalSubrIndex = this.cff.globalSubrIndex;
+      this.out.writeByteArray(this.compileIndex(globalSubrIndex));
+    },
+    compileCharStrings: function CFFCompiler_compileCharStrings(charStrings) {
+      return this.compileIndex(charStrings);
+    },
+    compileCharset: function CFFCompiler_compileCharset(charset) {
+      return this.compileTypedArray(charset.raw);
+    },
+    compileEncoding: function CFFCompiler_compileEncoding(encoding) {
+      return this.compileTypedArray(encoding.raw);
+    },
+    compileFDSelect: function CFFCompiler_compileFDSelect(fdSelect) {
+      return this.compileTypedArray(fdSelect);
+    },
+    compileTypedArray: function CFFCompiler_compileTypedArray(data) {
+      var out = [];
+      for (var i = 0, ii = data.length; i < ii; ++i)
+        out[i] = data[i];
+      return out;
+    },
+    compileIndex: function CFFCompiler_compileIndex(index, trackers) {
+      trackers = trackers || [];
+      var objects = index.objects;
+      // First 2 bytes contains the number of objects contained into this index
+      var count = objects.length;
+
+      // If there is no object, just create an index. This technically
+      // should just be [0, 0] but OTS has an issue with that.
+      if (count == 0)
+        return [0, 0, 0];
+
+      var data = [(count >> 8) & 0xFF, count & 0xff];
+
+      var lastOffset = 1;
+      for (var i = 0; i < count; ++i)
+        lastOffset += objects[i].length;
+
+      var offsetSize;
+      if (lastOffset < 0x100)
+        offsetSize = 1;
+      else if (lastOffset < 0x10000)
+        offsetSize = 2;
+      else if (lastOffset < 0x1000000)
+        offsetSize = 3;
+      else
+        offsetSize = 4;
+
+      // Next byte contains the offset size use to reference object in the file
+      data.push(offsetSize);
+
+      // Add another offset after this one because we need a new offset
+      var relativeOffset = 1;
+      for (var i = 0; i < count + 1; i++) {
+        if (offsetSize === 1) {
+          data.push(relativeOffset & 0xFF);
+        } else if (offsetSize === 2) {
+          data.push((relativeOffset >> 8) & 0xFF,
+                     relativeOffset & 0xFF);
+        } else if (offsetSize === 3) {
+          data.push((relativeOffset >> 16) & 0xFF,
+                    (relativeOffset >> 8) & 0xFF,
+                     relativeOffset & 0xFF);
+        } else {
+          data.push((relativeOffset >>> 24) & 0xFF,
+                    (relativeOffset >> 16) & 0xFF,
+                    (relativeOffset >> 8) & 0xFF,
+                     relativeOffset & 0xFF);
+        }
+
+        if (objects[i])
+          relativeOffset += objects[i].length;
+      }
+      var offset = data.length;
+
+      for (var i = 0; i < count; i++) {
+        // Notify the tracker where the object will be offset in the data.
+        if (trackers[i])
+          trackers[i].offset(data.length);
+        for (var j = 0, jj = objects[i].length; j < jj; j++)
+          data.push(objects[i][j]);
+      }
+      return data;
+    }
+  };
+  return CFFCompiler;
+})();
+
+/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
+
+'use strict';
+
+var GlyphsUnicode = {
+  A: 0x0041,
+  AE: 0x00C6,
+  AEacute: 0x01FC,
+  AEmacron: 0x01E2,
+  AEsmall: 0xF7E6,
+  Aacute: 0x00C1,
+  Aacutesmall: 0xF7E1,
+  Abreve: 0x0102,
+  Abreveacute: 0x1EAE,
+  Abrevecyrillic: 0x04D0,
+  Abrevedotbelow: 0x1EB6,
+  Abrevegrave: 0x1EB0,
+  Abrevehookabove: 0x1EB2,
+  Abrevetilde: 0x1EB4,
+  Acaron: 0x01CD,
+  Acircle: 0x24B6,
+  Acircumflex: 0x00C2,
+  Acircumflexacute: 0x1EA4,
+  Acircumflexdotbelow: 0x1EAC,
+  Acircumflexgrave: 0x1EA6,
+  Acircumflexhookabove: 0x1EA8,
+  Acircumflexsmall: 0xF7E2,
+  Acircumflextilde: 0x1EAA,
+  Acute: 0xF6C9,
+  Acutesmall: 0xF7B4,
+  Acyrillic: 0x0410,
+  Adblgrave: 0x0200,
+  Adieresis: 0x00C4,
+  Adieresiscyrillic: 0x04D2,
+  Adieresismacron: 0x01DE,
+  Adieresissmall: 0xF7E4,
+  Adotbelow: 0x1EA0,
+  Adotmacron: 0x01E0,
+  Agrave: 0x00C0,
+  Agravesmall: 0xF7E0,
+  Ahookabove: 0x1EA2,
+  Aiecyrillic: 0x04D4,
+  Ainvertedbreve: 0x0202,
+  Alpha: 0x0391,
+  Alphatonos: 0x0386,
+  Amacron: 0x0100,
+  Amonospace: 0xFF21,
+  Aogonek: 0x0104,
+  Aring: 0x00C5,
+  Aringacute: 0x01FA,
+  Aringbelow: 0x1E00,
+  Aringsmall: 0xF7E5,
+  Asmall: 0xF761,
+  Atilde: 0x00C3,
+  Atildesmall: 0xF7E3,
+  Aybarmenian: 0x0531,
+  B: 0x0042,
+  Bcircle: 0x24B7,
+  Bdotaccent: 0x1E02,
+  Bdotbelow: 0x1E04,
+  Becyrillic: 0x0411,
+  Benarmenian: 0x0532,
+  Beta: 0x0392,
+  Bhook: 0x0181,
+  Blinebelow: 0x1E06,
+  Bmonospace: 0xFF22,
+  Brevesmall: 0xF6F4,
+  Bsmall: 0xF762,
+  Btopbar: 0x0182,
+  C: 0x0043,
+  Caarmenian: 0x053E,
+  Cacute: 0x0106,
+  Caron: 0xF6CA,
+  Caronsmall: 0xF6F5,
+  Ccaron: 0x010C,
+  Ccedilla: 0x00C7,
+  Ccedillaacute: 0x1E08,
+  Ccedillasmall: 0xF7E7,
+  Ccircle: 0x24B8,
+  Ccircumflex: 0x0108,
+  Cdot: 0x010A,
+  Cdotaccent: 0x010A,
+  Cedillasmall: 0xF7B8,
+  Chaarmenian: 0x0549,
+  Cheabkhasiancyrillic: 0x04BC,
+  Checyrillic: 0x0427,
+  Chedescenderabkhasiancyrillic: 0x04BE,
+  Chedescendercyrillic: 0x04B6,
+  Chedieresiscyrillic: 0x04F4,
+  Cheharmenian: 0x0543,
+  Chekhakassiancyrillic: 0x04CB,
+  Cheverticalstrokecyrillic: 0x04B8,
+  Chi: 0x03A7,
+  Chook: 0x0187,
+  Circumflexsmall: 0xF6F6,
+  Cmonospace: 0xFF23,
+  Coarmenian: 0x0551,
+  Csmall: 0xF763,
+  D: 0x0044,
+  DZ: 0x01F1,
+  DZcaron: 0x01C4,
+  Daarmenian: 0x0534,
+  Dafrican: 0x0189,
+  Dcaron: 0x010E,
+  Dcedilla: 0x1E10,
+  Dcircle: 0x24B9,
+  Dcircumflexbelow: 0x1E12,
+  Dcroat: 0x0110,
+  Ddotaccent: 0x1E0A,
+  Ddotbelow: 0x1E0C,
+  Decyrillic: 0x0414,
+  Deicoptic: 0x03EE,
   Delta: 0x2206,
   Deltagreek: 0x0394,
   Dhook: 0x018A,
@@ -16892,27 +19555,7 @@ var GlyphsUnicode = {
   dalet: 0x05D3,
   daletdagesh: 0xFB33,
   daletdageshhebrew: 0xFB33,
-  dalethatafpatah: 0x05D305B2,
-  dalethatafpatahhebrew: 0x05D305B2,
-  dalethatafsegol: 0x05D305B1,
-  dalethatafsegolhebrew: 0x05D305B1,
   dalethebrew: 0x05D3,
-  dalethiriq: 0x05D305B4,
-  dalethiriqhebrew: 0x05D305B4,
-  daletholam: 0x05D305B9,
-  daletholamhebrew: 0x05D305B9,
-  daletpatah: 0x05D305B7,
-  daletpatahhebrew: 0x05D305B7,
-  daletqamats: 0x05D305B8,
-  daletqamatshebrew: 0x05D305B8,
-  daletqubuts: 0x05D305BB,
-  daletqubutshebrew: 0x05D305BB,
-  daletsegol: 0x05D305B6,
-  daletsegolhebrew: 0x05D305B6,
-  daletsheva: 0x05D305B0,
-  daletshevahebrew: 0x05D305B0,
-  dalettsere: 0x05D305B5,
-  dalettserehebrew: 0x05D305B5,
   dalfinalarabic: 0xFEAA,
   dammaarabic: 0x064F,
   dammalowarabic: 0x064F,
@@ -17229,10 +19872,6 @@ var GlyphsUnicode = {
   finalkafdagesh: 0xFB3A,
   finalkafdageshhebrew: 0xFB3A,
   finalkafhebrew: 0x05DA,
-  finalkafqamats: 0x05DA05B8,
-  finalkafqamatshebrew: 0x05DA05B8,
-  finalkafsheva: 0x05DA05B0,
-  finalkafshevahebrew: 0x05DA05B0,
   finalmem: 0x05DD,
   finalmemhebrew: 0x05DD,
   finalnun: 0x05DF,
@@ -17421,14 +20060,7 @@ var GlyphsUnicode = {
   hakatakanahalfwidth: 0xFF8A,
   halantgurmukhi: 0x0A4D,
   hamzaarabic: 0x0621,
-  hamzadammaarabic: 0x0621064F,
-  hamzadammatanarabic: 0x0621064C,
-  hamzafathaarabic: 0x0621064E,
-  hamzafathatanarabic: 0x0621064B,
   hamzalowarabic: 0x0621,
-  hamzalowkasraarabic: 0x06210650,
-  hamzalowkasratanarabic: 0x0621064D,
-  hamzasukunarabic: 0x06210652,
   hangulfiller: 0x3164,
   hardsigncyrillic: 0x044A,
   harpoonleftbarbup: 0x21BC,
@@ -17860,10 +20492,6 @@ var GlyphsUnicode = {
   lameddagesh: 0xFB3C,
   lameddageshhebrew: 0xFB3C,
   lamedhebrew: 0x05DC,
-  lamedholam: 0x05DC05B9,
-  lamedholamdagesh: '05DC 05B9 05BC',
-  lamedholamdageshhebrew: '05DC 05B9 05BC',
-  lamedholamhebrew: 0x05DC05B9,
   lamfinalarabic: 0xFEDE,
   lamhahinitialarabic: 0xFCCA,
   laminitialarabic: 0xFEDF,
@@ -17873,8 +20501,6 @@ var GlyphsUnicode = {
   lammedialarabic: 0xFEE0,
   lammeemhahinitialarabic: 0xFD88,
   lammeeminitialarabic: 0xFCCC,
-  lammeemjeeminitialarabic: 'FEDF FEE4 FEA0',
-  lammeemkhahinitialarabic: 'FEDF FEE4 FEA8',
   largecircle: 0x25EF,
   lbar: 0x019A,
   lbelt: 0x026C,
@@ -18171,7 +20797,6 @@ var GlyphsUnicode = {
   noonfinalarabic: 0xFEE6,
   noonghunnaarabic: 0x06BA,
   noonghunnafinalarabic: 0xFB9F,
-  noonhehinitialarabic: 0xFEE7FEEC,
   nooninitialarabic: 0xFEE7,
   noonjeeminitialarabic: 0xFCD2,
   noonjeemisolatedarabic: 0xFC4B,
@@ -18543,27 +21168,7 @@ var GlyphsUnicode = {
   qof: 0x05E7,
   qofdagesh: 0xFB47,
   qofdageshhebrew: 0xFB47,
-  qofhatafpatah: 0x05E705B2,
-  qofhatafpatahhebrew: 0x05E705B2,
-  qofhatafsegol: 0x05E705B1,
-  qofhatafsegolhebrew: 0x05E705B1,
   qofhebrew: 0x05E7,
-  qofhiriq: 0x05E705B4,
-  qofhiriqhebrew: 0x05E705B4,
-  qofholam: 0x05E705B9,
-  qofholamhebrew: 0x05E705B9,
-  qofpatah: 0x05E705B7,
-  qofpatahhebrew: 0x05E705B7,
-  qofqamats: 0x05E705B8,
-  qofqamatshebrew: 0x05E705B8,
-  qofqubuts: 0x05E705BB,
-  qofqubutshebrew: 0x05E705BB,
-  qofsegol: 0x05E705B6,
-  qofsegolhebrew: 0x05E705B6,
-  qofsheva: 0x05E705B0,
-  qofshevahebrew: 0x05E705B0,
-  qoftsere: 0x05E705B5,
-  qoftserehebrew: 0x05E705B5,
   qparen: 0x24AC,
   quarternote: 0x2669,
   qubuts: 0x05BB,
@@ -18637,32 +21242,11 @@ var GlyphsUnicode = {
   reharmenian: 0x0580,
   rehfinalarabic: 0xFEAE,
   rehiragana: 0x308C,
-  rehyehaleflamarabic: '0631 FEF3 FE8E 0644',
   rekatakana: 0x30EC,
   rekatakanahalfwidth: 0xFF9A,
   resh: 0x05E8,
   reshdageshhebrew: 0xFB48,
-  reshhatafpatah: 0x05E805B2,
-  reshhatafpatahhebrew: 0x05E805B2,
-  reshhatafsegol: 0x05E805B1,
-  reshhatafsegolhebrew: 0x05E805B1,
   reshhebrew: 0x05E8,
-  reshhiriq: 0x05E805B4,
-  reshhiriqhebrew: 0x05E805B4,
-  reshholam: 0x05E805B9,
-  reshholamhebrew: 0x05E805B9,
-  reshpatah: 0x05E805B7,
-  reshpatahhebrew: 0x05E805B7,
-  reshqamats: 0x05E805B8,
-  reshqamatshebrew: 0x05E805B8,
-  reshqubuts: 0x05E805BB,
-  reshqubutshebrew: 0x05E805BB,
-  reshsegol: 0x05E805B6,
-  reshsegolhebrew: 0x05E805B6,
-  reshsheva: 0x05E805B0,
-  reshshevahebrew: 0x05E805B0,
-  reshtsere: 0x05E805B5,
-  reshtserehebrew: 0x05E805B5,
   reversedtilde: 0x223D,
   reviahebrew: 0x0597,
   reviamugrashhebrew: 0x0597,
@@ -18861,7 +21445,6 @@ var GlyphsUnicode = {
   shaddadammaarabic: 0xFC61,
   shaddadammatanarabic: 0xFC5E,
   shaddafathaarabic: 0xFC60,
-  shaddafathatanarabic: 0x0651064B,
   shaddakasraarabic: 0xFC62,
   shaddakasratanarabic: 0xFC5F,
   shade: 0x2592,
@@ -19058,7 +21641,6 @@ var GlyphsUnicode = {
   tchehfinalarabic: 0xFB7B,
   tchehinitialarabic: 0xFB7C,
   tchehmedialarabic: 0xFB7D,
-  tchehmeeminitialarabic: 0xFB7CFEE4,
   tcircle: 0x24E3,
   tcircumflexbelow: 0x1E71,
   tcommaaccent: 0x0163,
@@ -19671,7 +22253,8 @@ var GlyphsUnicode = {
   zretroflexhook: 0x0290,
   zstroke: 0x01B6,
   zuhiragana: 0x305A,
-  zukatakana: 0x30BA
+  zukatakana: 0x30BA,
+  '.notdef': 0x0000
 };
 
 /* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
@@ -19679,15 +22262,44 @@ var GlyphsUnicode = {
 
 'use strict';
 
-var PDFImage = (function pdfImage() {
-  function constructor(xref, res, image, inline) {
-    this.image = image;
-    if (image.getParams) {
-      // JPX/JPEG2000 streams directly contain bits per component
-      // and color space mode information.
-      TODO('get params from actual stream');
-      // var bits = ...
-      // var colorspace = ...
+var PDFImage = (function PDFImageClosure() {
+  /**
+   * Decode the image in the main thread if it supported. Resovles the promise
+   * when the image data is ready.
+   */
+  function handleImageData(handler, xref, res, image, promise) {
+    if (image instanceof JpegStream && image.isNativelyDecodable(xref, res)) {
+      // For natively supported jpegs send them to the main thread for decoding.
+      var dict = image.dict;
+      var colorSpace = dict.get('ColorSpace', 'CS');
+      colorSpace = ColorSpace.parse(colorSpace, xref, res);
+      var numComps = colorSpace.numComps;
+      handler.send('jpeg_decode', [image.getIR(), numComps], function(message) {
+        var data = message.data;
+        var stream = new Stream(data, 0, data.length, image.dict);
+        promise.resolve(stream);
+      });
+    } else {
+      promise.resolve(image);
+    }
+  }
+  /**
+   * Decode and clamp a value. The formula is different from the spec because we
+   * don't decode to float range [0,1], we decode it in the [0,max] range.
+   */
+  function decodeAndClamp(value, addend, coefficient, max) {
+    value = addend + value * coefficient;
+    // Clamp the value to the range
+    return value < 0 ? 0 : value > max ? max : value;
+  }
+  function PDFImage(xref, res, image, inline, smask) {
+    this.image = image;
+    if (image.getParams) {
+      // JPX/JPEG2000 streams directly contain bits per component
+      // and color space mode information.
+      TODO('get params from actual stream');
+      // var bits = ...
+      // var colorspace = ...
     }
     // TODO cache rendered images?
 
@@ -19725,34 +22337,143 @@ var PDFImage = (function pdfImage() {
     }
 
     this.decode = dict.get('Decode', 'D');
+    this.needsDecode = false;
+    if (this.decode && this.colorSpace &&
+        !this.colorSpace.isDefaultDecode(this.decode)) {
+      this.needsDecode = true;
+      // Do some preprocessing to avoid more math.
+      var max = (1 << bitsPerComponent) - 1;
+      this.decodeCoefficients = [];
+      this.decodeAddends = [];
+      for (var i = 0, j = 0; i < this.decode.length; i += 2, ++j) {
+        var dmin = this.decode[i];
+        var dmax = this.decode[i + 1];
+        this.decodeCoefficients[j] = dmax - dmin;
+        this.decodeAddends[j] = max * dmin;
+      }
+    }
 
-    var mask = xref.fetchIfRef(dict.get('Mask'));
-    var smask = xref.fetchIfRef(dict.get('SMask'));
+    var mask = dict.get('Mask');
 
     if (mask) {
       TODO('masked images');
     } else if (smask) {
-      this.smask = new PDFImage(xref, res, smask);
+      this.smask = new PDFImage(xref, res, smask, false);
     }
   }
+  /**
+   * Handles processing of image data and calls the callback with an argument
+   * of a PDFImage when the image is ready to be used.
+   */
+  PDFImage.buildImage = function PDFImage_buildImage(callback, handler, xref,
+                                                     res, image, inline) {
+    var imageDataPromise = new Promise();
+    var smaskPromise = new Promise();
+    // The image data and smask data may not be ready yet, wait till both are
+    // resolved.
+    Promise.all([imageDataPromise, smaskPromise]).then(function(results) {
+      var imageData = results[0], smaskData = results[1];
+      var image = new PDFImage(xref, res, imageData, inline, smaskData);
+      callback(image);
+    });
 
-  constructor.prototype = {
-    getComponents: function getComponents(buffer, decodeMap) {
+    handleImageData(handler, xref, res, image, imageDataPromise);
+
+    var smask = image.dict.get('SMask');
+    if (smask)
+      handleImageData(handler, xref, res, smask, smaskPromise);
+    else
+      smaskPromise.resolve(null);
+  };
+
+  /**
+   * Resize an image using the nearest neighbor algorithm.  Currently only
+   * supports one and three component images.
+   * @param {TypedArray} pixels The original image with one component.
+   * @param {Number} bpc Number of bits per component.
+   * @param {Number} components Number of color components, 1 or 3 is supported.
+   * @param {Number} w1 Original width.
+   * @param {Number} h1 Original height.
+   * @param {Number} w2 New width.
+   * @param {Number} h2 New height.
+   * @return {TypedArray} Resized image data.
+   */
+  PDFImage.resize = function PDFImage_resize(pixels, bpc, components,
+                                             w1, h1, w2, h2) {
+    var length = w2 * h2 * components;
+    var temp = bpc <= 8 ? new Uint8Array(length) :
+        bpc <= 16 ? new Uint16Array(length) : new Uint32Array(length);
+    var xRatio = w1 / w2;
+    var yRatio = h1 / h2;
+    var px, py, newIndex, oldIndex;
+    for (var i = 0; i < h2; i++) {
+      for (var j = 0; j < w2; j++) {
+        px = Math.floor(j * xRatio);
+        py = Math.floor(i * yRatio);
+        newIndex = (i * w2) + j;
+        oldIndex = ((py * w1) + px);
+        if (components === 1) {
+          temp[newIndex] = pixels[oldIndex];
+        } else if (components === 3) {
+          newIndex *= 3;
+          oldIndex *= 3;
+          temp[newIndex] = pixels[oldIndex];
+          temp[newIndex + 1] = pixels[oldIndex + 1];
+          temp[newIndex + 2] = pixels[oldIndex + 2];
+        }
+      }
+    }
+    return temp;
+  };
+
+  PDFImage.prototype = {
+    get drawWidth() {
+      if (!this.smask)
+        return this.width;
+      return Math.max(this.width, this.smask.width);
+    },
+    get drawHeight() {
+      if (!this.smask)
+        return this.height;
+      return Math.max(this.height, this.smask.height);
+    },
+    getComponents: function PDFImage_getComponents(buffer) {
       var bpc = this.bpc;
-      if (bpc == 8)
+      var needsDecode = this.needsDecode;
+      var decodeMap = this.decode;
+
+      // This image doesn't require any extra work.
+      if (bpc == 8 && !needsDecode)
         return buffer;
 
+      var bufferLength = buffer.length;
       var width = this.width;
       var height = this.height;
       var numComps = this.numComps;
 
-      var length = width * height;
+      var length = width * height * numComps;
       var bufferPos = 0;
       var output = bpc <= 8 ? new Uint8Array(length) :
         bpc <= 16 ? new Uint16Array(length) : new Uint32Array(length);
       var rowComps = width * numComps;
+      var decodeAddends, decodeCoefficients;
+      if (needsDecode) {
+        decodeAddends = this.decodeAddends;
+        decodeCoefficients = this.decodeCoefficients;
+      }
+      var max = (1 << bpc) - 1;
 
-      if (bpc == 1) {
+      if (bpc == 8) {
+        // Optimization for reading 8 bpc images that have a decode.
+        for (var i = 0, ii = length; i < ii; ++i) {
+          var compIndex = i % numComps;
+          var value = buffer[i];
+          value = decodeAndClamp(value, decodeAddends[compIndex],
+                          decodeCoefficients[compIndex], max);
+          output[i] = value;
+        }
+      } else if (bpc == 1) {
+        // Optimization for reading 1 bpc images.
         var valueZero = 0, valueOne = 1;
         if (decodeMap) {
           valueZero = decodeMap[0] ? 1 : 0;
@@ -19777,8 +22498,7 @@ var PDFImage = (function pdfImage() {
           output[i] = !(buf & mask) ? valueZero : valueOne;
         }
       } else {
-        if (decodeMap != null)
-          TODO('interpolate component values');
+        // The general case that handles all other bpc values.
         var bits = 0, buf = 0;
         for (var i = 0, ii = length; i < ii; ++i) {
           if (i % rowComps == 0) {
@@ -19792,51 +22512,44 @@ var PDFImage = (function pdfImage() {
           }
 
           var remainingBits = bits - bpc;
-          output[i] = buf >> remainingBits;
+          var value = buf >> remainingBits;
+          if (needsDecode) {
+            var compIndex = i % numComps;
+            value = decodeAndClamp(value, decodeAddends[compIndex],
+                            decodeCoefficients[compIndex], max);
+          }
+          output[i] = value;
           buf = buf & ((1 << remainingBits) - 1);
           bits = remainingBits;
         }
       }
       return output;
     },
-    getOpacity: function getOpacity() {
+    getOpacity: function PDFImage_getOpacity(width, height) {
       var smask = this.smask;
-      var width = this.width;
-      var height = this.height;
-      var buf = new Uint8Array(width * height);
+      var originalWidth = this.width;
+      var originalHeight = this.height;
+      var buf;
 
       if (smask) {
-        if (smask.image.getImage) {
-          // smask is a DOM image
-          var tempCanvas = new ScratchCanvas(width, height);
-          var tempCtx = tempCanvas.getContext('2d');
-          var domImage = smask.image.getImage();
-          tempCtx.drawImage(domImage, 0, 0, domImage.width, domImage.height,
-            0, 0, width, height);
-          var data = tempCtx.getImageData(0, 0, width, height).data;
-          for (var i = 0, j = 0, ii = width * height; i < ii; ++i, j += 4)
-            buf[i] = data[j]; // getting first component value
-          return buf;
-        }
         var sw = smask.width;
         var sh = smask.height;
-        if (sw != this.width || sh != this.height)
-          error('smask dimensions do not match image dimensions: ' + sw +
-                ' != ' + this.width + ', ' + sh + ' != ' + this.height);
-
+        buf = new Uint8Array(sw * sh);
         smask.fillGrayBuffer(buf);
-        return buf;
+        if (sw != width || sh != height)
+          buf = PDFImage.resize(buf, smask.bps, 1, sw, sh, width, height);
       } else {
+        buf = new Uint8Array(width * height);
         for (var i = 0, ii = width * height; i < ii; ++i)
           buf[i] = 255;
       }
       return buf;
     },
-    applyStencilMask: function applyStencilMask(buffer, inverseDecode) {
+    applyStencilMask: function PDFImage_applyStencilMask(buffer,
+                                                         inverseDecode) {
       var width = this.width, height = this.height;
       var bitStrideLength = (width + 7) >> 3;
-      this.image.reset();
-      var imgArray = this.image.getBytes(bitStrideLength * height);
+      var imgArray = this.getImageBytes(bitStrideLength * height);
       var imgArrayPos = 0;
       var i, j, mask, buf;
       // removing making non-masked pixels transparent
@@ -19856,21 +22569,23 @@ var PDFImage = (function pdfImage() {
         }
       }
     },
-    fillRgbaBuffer: function fillRgbaBuffer(buffer, decodeMap) {
+    fillRgbaBuffer: function PDFImage_fillRgbaBuffer(buffer, width, height) {
       var numComps = this.numComps;
-      var width = this.width;
-      var height = this.height;
+      var originalWidth = this.width;
+      var originalHeight = this.height;
       var bpc = this.bpc;
 
       // rows start at byte boundary;
-      var rowBytes = (width * numComps * bpc + 7) >> 3;
-      this.image.reset();
-      var imgArray = this.image.getBytes(height * rowBytes);
+      var rowBytes = (originalWidth * numComps * bpc + 7) >> 3;
+      var imgArray = this.getImageBytes(originalHeight * rowBytes);
 
       var comps = this.colorSpace.getRgbBuffer(
-        this.getComponents(imgArray, decodeMap), bpc);
+        this.getComponents(imgArray), bpc);
+      if (originalWidth != width || originalHeight != height)
+        comps = PDFImage.resize(comps, this.bpc, 3, originalWidth,
+                                originalHeight, width, height);
       var compsPos = 0;
-      var opacity = this.getOpacity();
+      var opacity = this.getOpacity(width, height);
       var opacityPos = 0;
       var length = width * height * 4;
 
@@ -19881,7 +22596,7 @@ var PDFImage = (function pdfImage() {
         buffer[i + 3] = opacity[opacityPos++];
       }
     },
-    fillGrayBuffer: function fillGrayBuffer(buffer) {
+    fillGrayBuffer: function PDFImage_fillGrayBuffer(buffer) {
       var numComps = this.numComps;
       if (numComps != 1)
         error('Reading gray scale from a color image: ' + numComps);
@@ -19892,50 +22607,39 @@ var PDFImage = (function pdfImage() {
 
       // rows start at byte boundary;
       var rowBytes = (width * numComps * bpc + 7) >> 3;
-      this.image.reset();
-      var imgArray = this.image.getBytes(height * rowBytes);
+      var imgArray = this.getImageBytes(height * rowBytes);
 
       var comps = this.getComponents(imgArray);
       var length = width * height;
-
+      // we aren't using a colorspace so we need to scale the value
+      var scale = 255 / ((1 << bpc) - 1);
       for (var i = 0; i < length; ++i)
-        buffer[i] = comps[i];
+        buffer[i] = (scale * comps[i]) | 0;
+    },
+    getImageBytes: function PDFImage_getImageBytes(length) {
+      this.image.reset();
+      return this.image.getBytes(length);
     }
   };
-  return constructor;
+  return PDFImage;
 })();
 
-var JpegImageLoader = (function jpegImage() {
-  function JpegImageLoader(objId, imageData, objs) {
-    var src = 'data:image/jpeg;base64,' + window.btoa(imageData);
-
-    var img = new Image();
-    img.onload = (function jpegImageLoaderOnload() {
-      this.loaded = true;
-
-      objs.resolve(objId, this);
-
-      if (this.onLoad)
-        this.onLoad();
-    }).bind(this);
-    img.src = src;
-    this.domImage = img;
-  }
-
-  JpegImageLoader.prototype = {
-    getImage: function jpegImageLoaderGetImage() {
-      return this.domImage;
-    }
-  };
-
-  return JpegImageLoader;
-})();
+function loadJpegStream(id, imageData, objs) {
+  var img = new Image();
+  img.onload = (function loadJpegStream_onloadClosure() {
+    objs.resolve(id, img);
+  });
+  img.src = 'data:image/jpeg;base64,' + window.btoa(imageData);
+}
 
 /* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
 
 'use strict';
 
+// The Metrics object contains glyph widths (in glyph space units).
+// As per PDF spec, for most fonts (Type 3 being an exception) a glyph
+// space unit corresponds to 1/1000th of text space unit.
 var Metrics = {
   'Courier': 600,
   'Courier-Bold': 600,
@@ -22886,8 +25590,8 @@ function isEOF(v) {
   return v == EOF;
 }
 
-var Parser = (function parserParser() {
-  function constructor(lexer, allowStreams, xref) {
+var Parser = (function ParserClosure() {
+  function Parser(lexer, allowStreams, xref) {
     this.lexer = lexer;
     this.allowStreams = allowStreams;
     this.xref = xref;
@@ -22895,12 +25599,12 @@ var Parser = (function parserParser() {
     this.refill();
   }
 
-  constructor.prototype = {
-    refill: function parserRefill() {
+  Parser.prototype = {
+    refill: function Parser_refill() {
       this.buf1 = this.lexer.getObj();
       this.buf2 = this.lexer.getObj();
     },
-    shift: function parserShift() {
+    shift: function Parser_shift() {
       if (isCmd(this.buf2, 'ID')) {
         this.buf1 = this.buf2;
         this.buf2 = null;
@@ -22911,7 +25615,7 @@ var Parser = (function parserParser() {
         this.buf2 = this.lexer.getObj();
       }
     },
-    getObj: function parserGetObj(cipherTransform) {
+    getObj: function Parser_getObj(cipherTransform) {
       if (isCmd(this.buf1, 'BI')) { // inline image
         this.shift();
         return this.makeInlineImage(cipherTransform);
@@ -22928,17 +25632,16 @@ var Parser = (function parserParser() {
       }
       if (isCmd(this.buf1, '<<')) { // dictionary or stream
         this.shift();
-        var dict = new Dict();
+        var dict = new Dict(this.xref);
         while (!isCmd(this.buf1, '>>') && !isEOF(this.buf1)) {
-          if (!isName(this.buf1)) {
+          if (!isName(this.buf1))
             error('Dictionary key must be a name object');
-          } else {
-            var key = this.buf1.name;
-            this.shift();
-            if (isEOF(this.buf1))
-              break;
-            dict.set(key, this.getObj(cipherTransform));
-          }
+
+          var key = this.buf1.name;
+          this.shift();
+          if (isEOF(this.buf1))
+            break;
+          dict.set(key, this.getObj(cipherTransform));
         }
         if (isEOF(this.buf1))
           error('End of file inside dictionary');
@@ -22976,38 +25679,37 @@ var Parser = (function parserParser() {
       this.shift();
       return obj;
     },
-    makeInlineImage: function parserMakeInlineImage(cipherTransform) {
+    makeInlineImage: function Parser_makeInlineImage(cipherTransform) {
       var lexer = this.lexer;
       var stream = lexer.stream;
 
       // parse dictionary
       var dict = new Dict();
       while (!isCmd(this.buf1, 'ID') && !isEOF(this.buf1)) {
-        if (!isName(this.buf1)) {
+        if (!isName(this.buf1))
           error('Dictionary key must be a name object');
-        } else {
-          var key = this.buf1.name;
-          this.shift();
-          if (isEOF(this.buf1))
-            break;
-          dict.set(key, this.getObj(cipherTransform));
-        }
+
+        var key = this.buf1.name;
+        this.shift();
+        if (isEOF(this.buf1))
+          break;
+        dict.set(key, this.getObj(cipherTransform));
       }
 
       // parse image stream
       var startPos = stream.pos;
 
-      // searching for the /\sEI\s/
+      // searching for the /EI\s/
       var state = 0, ch;
       while (state != 4 && (ch = stream.getByte()) != null) {
         switch (ch) {
           case 0x20:
           case 0x0D:
           case 0x0A:
-            state = state === 3 ? 4 : 1;
+            state = state === 3 ? 4 : 0;
             break;
           case 0x45:
-            state = state === 1 ? 2 : 0;
+            state = 2;
             break;
           case 0x49:
             state = state === 2 ? 3 : 0;
@@ -23034,12 +25736,16 @@ var Parser = (function parserParser() {
       imageStream = this.filter(imageStream, dict, length);
       imageStream.parameters = dict;
 
-      this.buf2 = new Cmd('EI');
+      this.buf2 = Cmd.get('EI');
       this.shift();
 
       return imageStream;
     },
-    makeStream: function parserMakeStream(dict, cipherTransform) {
+    fetchIfRef: function Parser_fetchIfRef(obj) {
+      // not relying on the xref.fetchIfRef -- xref might not be set
+      return isRef(obj) ? this.xref.fetch(obj) : obj;
+    },
+    makeStream: function Parser_makeStream(dict, cipherTransform) {
       var lexer = this.lexer;
       var stream = lexer.stream;
 
@@ -23048,14 +25754,9 @@ var Parser = (function parserParser() {
       var pos = stream.pos;
 
       // get length
-      var length = dict.get('Length');
-      var xref = this.xref;
-      if (xref)
-        length = xref.fetchIfRef(length);
-      if (!isInt(length)) {
+      var length = this.fetchIfRef(dict.get('Length'));
+      if (!isInt(length))
         error('Bad ' + length + ' attribute in stream');
-        length = 0;
-      }
 
       // skip over the stream data
       stream.pos = pos + length;
@@ -23072,9 +25773,9 @@ var Parser = (function parserParser() {
       stream.parameters = dict;
       return stream;
     },
-    filter: function parserFilter(stream, dict, length) {
-      var filter = dict.get('Filter', 'F');
-      var params = dict.get('DecodeParms', 'DP');
+    filter: function Parser_filter(stream, dict, length) {
+      var filter = this.fetchIfRef(dict.get('Filter', 'F'));
+      var params = this.fetchIfRef(dict.get('DecodeParms', 'DP'));
       if (isName(filter))
         return this.makeFilter(stream, filter.name, length, params);
       if (isArray(filter)) {
@@ -23084,25 +25785,25 @@ var Parser = (function parserParser() {
           filter = filterArray[i];
           if (!isName(filter))
             error('Bad filter name: ' + filter);
-          else {
-            params = null;
-            if (isArray(paramsArray) && (i in paramsArray))
-              params = paramsArray[i];
-            stream = this.makeFilter(stream, filter.name, length, params);
-            // after the first stream the length variable is invalid
-            length = null;
-          }
+
+          params = null;
+          if (isArray(paramsArray) && (i in paramsArray))
+            params = paramsArray[i];
+          stream = this.makeFilter(stream, filter.name, length, params);
+          // after the first stream the length variable is invalid
+          length = null;
         }
       }
       return stream;
     },
-    makeFilter: function parserMakeFilter(stream, name, length, params) {
+    makeFilter: function Parser_makeFilter(stream, name, length, params) {
       if (name == 'FlateDecode' || name == 'Fl') {
         if (params) {
           return new PredictorStream(new FlateStream(stream), params);
         }
         return new FlateStream(stream);
-      } else if (name == 'LZWDecode' || name == 'LZW') {
+      }
+      if (name == 'LZWDecode' || name == 'LZW') {
         var earlyChange = 1;
         if (params) {
           if (params.has('EarlyChange'))
@@ -23111,31 +25812,41 @@ var Parser = (function parserParser() {
             new LZWStream(stream, earlyChange), params);
         }
         return new LZWStream(stream, earlyChange);
-      } else if (name == 'DCTDecode' || name == 'DCT') {
+      }
+      if (name == 'DCTDecode' || name == 'DCT') {
         var bytes = stream.getBytes(length);
         return new JpegStream(bytes, stream.dict, this.xref);
-      } else if (name == 'ASCII85Decode' || name == 'A85') {
+      }
+      if (name == 'JPXDecode' || name == 'JPX') {
+        var bytes = stream.getBytes(length);
+        return new JpxStream(bytes, stream.dict);
+      }
+      if (name == 'ASCII85Decode' || name == 'A85') {
         return new Ascii85Stream(stream);
-      } else if (name == 'ASCIIHexDecode' || name == 'AHx') {
+      }
+      if (name == 'ASCIIHexDecode' || name == 'AHx') {
         return new AsciiHexStream(stream);
-      } else if (name == 'CCITTFaxDecode' || name == 'CCF') {
+      }
+      if (name == 'CCITTFaxDecode' || name == 'CCF') {
         return new CCITTFaxStream(stream, params);
-      } else {
-        TODO('filter "' + name + '" not supported yet');
       }
+      if (name == 'RunLengthDecode') {
+        return new RunLengthStream(stream);
+      }
+      warn('filter "' + name + '" not supported yet');
       return stream;
     }
   };
 
-  return constructor;
+  return Parser;
 })();
 
-var Lexer = (function lexer() {
-  function constructor(stream) {
+var Lexer = (function LexerClosure() {
+  function Lexer(stream) {
     this.stream = stream;
   }
 
-  constructor.isSpace = function lexerIsSpace(ch) {
+  Lexer.isSpace = function Lexer_isSpace(ch) {
     return ch == ' ' || ch == '\t' || ch == '\x0d' || ch == '\x0a';
   };
 
@@ -23169,8 +25880,8 @@ var Lexer = (function lexer() {
     return -1;
   }
 
-  constructor.prototype = {
-    getNumber: function lexerGetNumber(ch) {
+  Lexer.prototype = {
+    getNumber: function Lexer_getNumber(ch) {
       var floating = false;
       var str = ch;
       var stream = this.stream;
@@ -23198,7 +25909,7 @@ var Lexer = (function lexer() {
         error('Invalid floating point number: ' + value);
       return value;
     },
-    getString: function lexerGetString() {
+    getString: function Lexer_getString() {
       var numParen = 1;
       var done = false;
       var str = '';
@@ -23282,7 +25993,7 @@ var Lexer = (function lexer() {
       } while (!done);
       return str;
     },
-    getName: function lexerGetName(ch) {
+    getName: function Lexer_getName(ch) {
       var str = '';
       var stream = this.stream;
       while (!!(ch = stream.lookChar()) && !specialChars[ch.charCodeAt(0)]) {
@@ -23309,7 +26020,7 @@ var Lexer = (function lexer() {
               str.length);
       return new Name(str);
     },
-    getHexString: function lexerGetHexString(ch) {
+    getHexString: function Lexer_getHexString(ch) {
       var str = '';
       var stream = this.stream;
       for (;;) {
@@ -23338,7 +26049,7 @@ var Lexer = (function lexer() {
       }
       return str;
     },
-    getObj: function lexerGetObj() {
+    getObj: function Lexer_getObj() {
       // skip whitespace and comments
       var comment = false;
       var stream = this.stream;
@@ -23369,14 +26080,14 @@ var Lexer = (function lexer() {
         // array punctuation
         case '[':
         case ']':
-          return new Cmd(ch);
+          return Cmd.get(ch);
         // hex string or dict punctuation
         case '<':
           ch = stream.lookChar();
           if (ch == '<') {
             // dict punctuation
             stream.skip();
-            return new Cmd('<<');
+            return Cmd.get('<<');
           }
           return this.getHexString(ch);
         // dict punctuation
@@ -23384,25 +26095,23 @@ var Lexer = (function lexer() {
           ch = stream.lookChar();
           if (ch == '>') {
             stream.skip();
-            return new Cmd('>>');
+            return Cmd.get('>>');
           }
         case '{':
         case '}':
-          return new Cmd(ch);
+          return Cmd.get(ch);
         // fall through
         case ')':
           error('Illegal character: ' + ch);
-          return Error;
       }
 
       // command
       var str = ch;
       while (!!(ch = stream.lookChar()) && !specialChars[ch.charCodeAt(0)]) {
         stream.skip();
-        if (str.length == 128) {
+        if (str.length == 128)
           error('Command token too long: ' + str.length);
-          break;
-        }
+
         str += ch;
       }
       if (str == 'true')
@@ -23411,9 +26120,9 @@ var Lexer = (function lexer() {
         return false;
       if (str == 'null')
         return null;
-      return new Cmd(str);
+      return Cmd.get(str);
     },
-    skipToNextLine: function lexerSkipToNextLine() {
+    skipToNextLine: function Lexer_skipToNextLine() {
       var stream = this.stream;
       while (true) {
         var ch = stream.getChar();
@@ -23426,17 +26135,17 @@ var Lexer = (function lexer() {
         }
       }
     },
-    skip: function lexerSkip() {
+    skip: function Lexer_skip() {
       this.stream.skip();
     }
   };
 
-  return constructor;
+  return Lexer;
 })();
 
-var Linearization = (function linearizationLinearization() {
-  function constructor(stream) {
-    this.parser = new Parser(new Lexer(stream), false);
+var Linearization = (function LinearizationClosure() {
+  function Linearization(stream) {
+    this.parser = new Parser(new Lexer(stream), false, null);
     var obj1 = this.parser.getObj();
     var obj2 = this.parser.getObj();
     var obj3 = this.parser.getObj();
@@ -23449,8 +26158,8 @@ var Linearization = (function linearizationLinearization() {
     }
   }
 
-  constructor.prototype = {
-    getInt: function linearizationGetInt(name) {
+  Linearization.prototype = {
+    getInt: function Linearization_getInt(name) {
       var linDict = this.linDict;
       var obj;
       if (isDict(linDict) &&
@@ -23459,9 +26168,8 @@ var Linearization = (function linearizationLinearization() {
         return obj;
       }
       error('"' + name + '" field in linearization table is invalid');
-      return 0;
     },
-    getHint: function linearizationGetHint(index) {
+    getHint: function Linearization_getHint(index) {
       var linDict = this.linDict;
       var obj1, obj2;
       if (isDict(linDict) &&
@@ -23472,7 +26180,6 @@ var Linearization = (function linearizationLinearization() {
         return obj2;
       }
       error('Hints table in linearization table is invalid: ' + index);
-      return 0;
     },
     get length() {
       if (!isDict(this.linDict))
@@ -23508,7 +26215,7 @@ var Linearization = (function linearizationLinearization() {
     }
   };
 
-  return constructor;
+  return Linearization;
 })();
 
 /* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
@@ -23516,48 +26223,53 @@ var Linearization = (function linearizationLinearization() {
 
 'use strict';
 
-var Pattern = (function patternPattern() {
+var PatternType = {
+  AXIAL: 2,
+  RADIAL: 3
+};
+
+var Pattern = (function PatternClosure() {
   // Constructor should define this.getPattern
-  function constructor() {
+  function Pattern() {
     error('should not call Pattern constructor');
   }
 
-  constructor.prototype = {
+  Pattern.prototype = {
     // Input: current Canvas context
     // Output: the appropriate fillStyle or strokeStyle
-    getPattern: function pattern_getStyle(ctx) {
+    getPattern: function Pattern_getPattern(ctx) {
       error('Should not call Pattern.getStyle: ' + ctx);
     }
   };
 
-  constructor.shadingFromIR = function pattern_shadingFromIR(ctx, raw) {
-    return Shadings[raw[0]].fromIR(ctx, raw);
+  Pattern.shadingFromIR = function Pattern_shadingFromIR(raw) {
+    return Shadings[raw[0]].fromIR(raw);
   };
 
-  constructor.parseShading = function pattern_shading(shading, matrix, xref,
-                                                      res, ctx) {
+  Pattern.parseShading = function Pattern_parseShading(shading, matrix, xref,
+                                                       res) {
 
     var dict = isStream(shading) ? shading.dict : shading;
     var type = dict.get('ShadingType');
 
     switch (type) {
-      case 2:
-      case 3:
-        // both radial and axial shadings are handled by RadialAxial shading
-        return new Shadings.RadialAxial(dict, matrix, xref, res, ctx);
+      case PatternType.AXIAL:
+      case PatternType.RADIAL:
+        // Both radial and axial shadings are handled by RadialAxial shading.
+        return new Shadings.RadialAxial(dict, matrix, xref, res);
       default:
         return new Shadings.Dummy();
     }
   };
-  return constructor;
+  return Pattern;
 })();
 
 var Shadings = {};
 
 // Radial and axial shading have very similar implementations
 // If needed, the implementations can be broken into two classes
-Shadings.RadialAxial = (function radialAxialShading() {
-  function constructor(dict, matrix, xref, res, ctx) {
+Shadings.RadialAxial = (function RadialAxialClosure() {
+  function RadialAxial(dict, matrix, xref, res, ctx) {
     this.matrix = matrix;
     this.coordsArr = dict.get('Coords');
     this.shadingType = dict.get('ShadingType');
@@ -23587,10 +26299,9 @@ Shadings.RadialAxial = (function radialAxialShading() {
     this.extendEnd = extendEnd;
 
     var fnObj = dict.get('Function');
-    fnObj = xref.fetchIfRef(fnObj);
     if (isArray(fnObj))
       error('No support for array of functions');
-    else if (!isPDFFunction(fnObj))
+    if (!isPDFFunction(fnObj))
       error('Invalid function');
     var fn = PDFFunction.parse(xref, fnObj);
 
@@ -23602,56 +26313,60 @@ Shadings.RadialAxial = (function radialAxialShading() {
 
     var colorStops = [];
     for (var i = t0; i <= t1; i += step) {
-      var color = fn([i]);
-      var rgbColor = Util.makeCssRgb.apply(this, cs.getRgb(color));
-      colorStops.push([(i - t0) / diff, rgbColor]);
+      var rgbColor = cs.getRgb(fn([i]));
+      var cssColor = Util.makeCssRgb(rgbColor[0], rgbColor[1], rgbColor[2]);
+      colorStops.push([(i - t0) / diff, cssColor]);
     }
 
     this.colorStops = colorStops;
   }
 
-  constructor.fromIR = function radialAxialShadingGetIR(ctx, raw) {
+  RadialAxial.fromIR = function RadialAxial_fromIR(raw) {
     var type = raw[1];
     var colorStops = raw[2];
     var p0 = raw[3];
     var p1 = raw[4];
     var r0 = raw[5];
     var r1 = raw[6];
+    return {
+      type: 'Pattern',
+      getPattern: function(ctx) {
+        var curMatrix = ctx.mozCurrentTransform;
+        if (curMatrix) {
+          var userMatrix = ctx.mozCurrentTransformInverse;
+
+          p0 = Util.applyTransform(p0, curMatrix);
+          p0 = Util.applyTransform(p0, userMatrix);
+
+          p1 = Util.applyTransform(p1, curMatrix);
+          p1 = Util.applyTransform(p1, userMatrix);
+        }
 
-    var curMatrix = ctx.mozCurrentTransform;
-    if (curMatrix) {
-      var userMatrix = ctx.mozCurrentTransformInverse;
-
-      p0 = Util.applyTransform(p0, curMatrix);
-      p0 = Util.applyTransform(p0, userMatrix);
-
-      p1 = Util.applyTransform(p1, curMatrix);
-      p1 = Util.applyTransform(p1, userMatrix);
-    }
-
-    var grad;
-    if (type == 2)
-      grad = ctx.createLinearGradient(p0[0], p0[1], p1[0], p1[1]);
-    else if (type == 3)
-      grad = ctx.createRadialGradient(p0[0], p0[1], r0, p1[0], p1[1], r1);
+        var grad;
+        if (type == PatternType.AXIAL)
+          grad = ctx.createLinearGradient(p0[0], p0[1], p1[0], p1[1]);
+        else if (type == PatternType.RADIAL)
+          grad = ctx.createRadialGradient(p0[0], p0[1], r0, p1[0], p1[1], r1);
 
-    for (var i = 0, ii = colorStops.length; i < ii; ++i) {
-      var c = colorStops[i];
-      grad.addColorStop(c[0], c[1]);
-    }
-    return grad;
+        for (var i = 0, ii = colorStops.length; i < ii; ++i) {
+          var c = colorStops[i];
+          grad.addColorStop(c[0], c[1]);
+        }
+        return grad;
+      }
+    };
   };
 
-  constructor.prototype = {
-    getIR: function radialAxialShadingGetIR() {
+  RadialAxial.prototype = {
+    getIR: function RadialAxial_getIR() {
       var coordsArr = this.coordsArr;
       var type = this.shadingType;
-      if (type == 2) {
+      if (type == PatternType.AXIAL) {
         var p0 = [coordsArr[0], coordsArr[1]];
         var p1 = [coordsArr[2], coordsArr[3]];
         var r0 = null;
         var r1 = null;
-      } else if (type == 3) {
+      } else if (type == PatternType.RADIAL) {
         var p0 = [coordsArr[0], coordsArr[1]];
         var p1 = [coordsArr[3], coordsArr[4]];
         var r0 = coordsArr[2];
@@ -23670,31 +26385,35 @@ Shadings.RadialAxial = (function radialAxialShading() {
     }
   };
 
-  return constructor;
+  return RadialAxial;
 })();
 
-Shadings.Dummy = (function dummyShading() {
-  function constructor() {
+Shadings.Dummy = (function DummyClosure() {
+  function Dummy() {
     this.type = 'Pattern';
   }
 
-  constructor.fromIR = function dummyShadingFromIR() {
+  Dummy.fromIR = function Dummy_fromIR() {
     return 'hotpink';
   };
 
-  constructor.prototype = {
-    getIR: function dummyShadingGetIR() {
+  Dummy.prototype = {
+    getIR: function Dummy_getIR() {
       return ['Dummy'];
     }
   };
-  return constructor;
+  return Dummy;
 })();
 
-var TilingPattern = (function tilingPattern() {
-  var PAINT_TYPE_COLORED = 1, PAINT_TYPE_UNCOLORED = 2;
+var TilingPattern = (function TilingPatternClosure() {
+  var PaintType = {
+    COLORED: 1,
+    UNCOLORED: 2
+  };
+  var MAX_PATTERN_SIZE = 512;
 
   function TilingPattern(IR, color, ctx, objs) {
-    var IRQueue = IR[2];
+    var operatorList = IR[2];
     this.matrix = IR[3];
     var bbox = IR[4];
     var xstep = IR[5];
@@ -23717,30 +26436,30 @@ var TilingPattern = (function tilingPattern() {
     var width = botRight[0] - topLeft[0];
     var height = botRight[1] - topLeft[1];
 
-    // TODO: hack to avoid OOM, we would idealy compute the tiling
+    // TODO: hack to avoid OOM, we would ideally compute the tiling
     // pattern to be only as large as the acual size in device space
     // This could be computed with .mozCurrentTransform, but still
     // needs to be implemented
-    while (Math.abs(width) > 512 || Math.abs(height) > 512) {
-      width = 512;
-      height = 512;
+    while (Math.abs(width) > MAX_PATTERN_SIZE ||
+           Math.abs(height) > MAX_PATTERN_SIZE) {
+      width = height = MAX_PATTERN_SIZE;
     }
 
-    var tmpCanvas = new ScratchCanvas(width, height);
+    var tmpCanvas = createScratchCanvas(width, height);
 
     // set the new canvas element context as the graphics context
     var tmpCtx = tmpCanvas.getContext('2d');
     var graphics = new CanvasGraphics(tmpCtx, objs);
 
     switch (paintType) {
-      case PAINT_TYPE_COLORED:
+      case PaintType.COLORED:
         tmpCtx.fillStyle = ctx.fillStyle;
         tmpCtx.strokeStyle = ctx.strokeStyle;
         break;
-      case PAINT_TYPE_UNCOLORED:
-        color = Util.makeCssRgb.apply(this, color);
-        tmpCtx.fillStyle = color;
-        tmpCtx.strokeStyle = color;
+      case PaintType.UNCOLORED:
+        var cssColor = Util.makeCssRgb(this, color[0], color[1], color[2]);
+        tmpCtx.fillStyle = cssColor;
+        tmpCtx.strokeStyle = cssColor;
         break;
       default:
         error('Unsupported paint type: ' + paintType);
@@ -23763,12 +26482,12 @@ var TilingPattern = (function tilingPattern() {
       graphics.endPath();
     }
 
-    graphics.executeIRQueue(IRQueue);
+    graphics.executeOperatorList(operatorList);
 
     this.canvas = tmpCanvas;
   }
 
-  TilingPattern.getIR = function tiling_getIR(codeIR, dict, args) {
+  TilingPattern.getIR = function TilingPattern_getIR(operatorList, dict, args) {
     var matrix = dict.get('Matrix');
     var bbox = dict.get('BBox');
     var xstep = dict.get('XStep');
@@ -23776,12 +26495,12 @@ var TilingPattern = (function tilingPattern() {
     var paintType = dict.get('PaintType');
 
     return [
-      'TilingPattern', args, codeIR, matrix, bbox, xstep, ystep, paintType
+      'TilingPattern', args, operatorList, matrix, bbox, xstep, ystep, paintType
     ];
   };
 
   TilingPattern.prototype = {
-    getPattern: function tiling_getPattern() {
+    getPattern: function TilingPattern_getPattern() {
       var matrix = this.matrix;
       var curMatrix = this.curMatrix;
       var ctx = this.ctx;
@@ -23807,8 +26526,8 @@ var TilingPattern = (function tilingPattern() {
 
 'use strict';
 
-var Stream = (function streamStream() {
-  function constructor(arrayBuffer, start, length, dict) {
+var Stream = (function StreamClosure() {
+  function Stream(arrayBuffer, start, length, dict) {
     this.bytes = new Uint8Array(arrayBuffer);
     this.start = start || 0;
     this.pos = this.start;
@@ -23818,18 +26537,18 @@ var Stream = (function streamStream() {
 
   // required methods for a stream. if a particular stream does not
   // implement these, an error should be thrown
-  constructor.prototype = {
+  Stream.prototype = {
     get length() {
       return this.end - this.start;
     },
-    getByte: function stream_getByte() {
+    getByte: function Stream_getByte() {
       if (this.pos >= this.end)
         return null;
       return this.bytes[this.pos++];
     },
     // returns subarray of original buffer
     // should only be read
-    getBytes: function stream_getBytes(length) {
+    getBytes: function Stream_getBytes(length) {
       var bytes = this.bytes;
       var pos = this.pos;
       var strEnd = this.end;
@@ -23844,38 +26563,38 @@ var Stream = (function streamStream() {
       this.pos = end;
       return bytes.subarray(pos, end);
     },
-    lookChar: function stream_lookChar() {
+    lookChar: function Stream_lookChar() {
       if (this.pos >= this.end)
         return null;
       return String.fromCharCode(this.bytes[this.pos]);
     },
-    getChar: function stream_getChar() {
+    getChar: function Stream_getChar() {
       if (this.pos >= this.end)
         return null;
       return String.fromCharCode(this.bytes[this.pos++]);
     },
-    skip: function stream_skip(n) {
+    skip: function Stream_skip(n) {
       if (!n)
         n = 1;
       this.pos += n;
     },
-    reset: function stream_reset() {
+    reset: function Stream_reset() {
       this.pos = this.start;
     },
-    moveStart: function stream_moveStart() {
+    moveStart: function Stream_moveStart() {
       this.start = this.pos;
     },
-    makeSubStream: function stream_makeSubstream(start, length, dict) {
+    makeSubStream: function Stream_makeSubStream(start, length, dict) {
       return new Stream(this.bytes.buffer, start, length, dict);
     },
     isStream: true
   };
 
-  return constructor;
+  return Stream;
 })();
 
-var StringStream = (function stringStream() {
-  function constructor(str) {
+var StringStream = (function StringStreamClosure() {
+  function StringStream(str) {
     var length = str.length;
     var bytes = new Uint8Array(length);
     for (var n = 0; n < length; ++n)
@@ -23883,22 +26602,22 @@ var StringStream = (function stringStream() {
     Stream.call(this, bytes);
   }
 
-  constructor.prototype = Stream.prototype;
+  StringStream.prototype = Stream.prototype;
 
-  return constructor;
+  return StringStream;
 })();
 
 // super class for the decoding streams
-var DecodeStream = (function decodeStream() {
-  function constructor() {
+var DecodeStream = (function DecodeStreamClosure() {
+  function DecodeStream() {
     this.pos = 0;
     this.bufferLength = 0;
     this.eof = false;
     this.buffer = null;
   }
 
-  constructor.prototype = {
-    ensureBuffer: function decodestream_ensureBuffer(requested) {
+  DecodeStream.prototype = {
+    ensureBuffer: function DecodeStream_ensureBuffer(requested) {
       var buffer = this.buffer;
       var current = buffer ? buffer.byteLength : 0;
       if (requested < current)
@@ -23911,7 +26630,7 @@ var DecodeStream = (function decodeStream() {
         buffer2[i] = buffer[i];
       return (this.buffer = buffer2);
     },
-    getByte: function decodestream_getByte() {
+    getByte: function DecodeStream_getByte() {
       var pos = this.pos;
       while (this.bufferLength <= pos) {
         if (this.eof)
@@ -23920,7 +26639,7 @@ var DecodeStream = (function decodeStream() {
       }
       return this.buffer[this.pos++];
     },
-    getBytes: function decodestream_getBytes(length) {
+    getBytes: function DecodeStream_getBytes(length) {
       var end, pos = this.pos;
 
       if (length) {
@@ -23948,7 +26667,7 @@ var DecodeStream = (function decodeStream() {
       this.pos = end;
       return this.buffer.subarray(pos, end);
     },
-    lookChar: function decodestream_lookChar() {
+    lookChar: function DecodeStream_lookChar() {
       var pos = this.pos;
       while (this.bufferLength <= pos) {
         if (this.eof)
@@ -23957,7 +26676,7 @@ var DecodeStream = (function decodeStream() {
       }
       return String.fromCharCode(this.buffer[this.pos]);
     },
-    getChar: function decodestream_getChar() {
+    getChar: function DecodeStream_getChar() {
       var pos = this.pos;
       while (this.bufferLength <= pos) {
         if (this.eof)
@@ -23966,40 +26685,40 @@ var DecodeStream = (function decodeStream() {
       }
       return String.fromCharCode(this.buffer[this.pos++]);
     },
-    makeSubStream: function decodestream_makeSubstream(start, length, dict) {
+    makeSubStream: function DecodeStream_makeSubStream(start, length, dict) {
       var end = start + length;
       while (this.bufferLength <= end && !this.eof)
         this.readBlock();
       return new Stream(this.buffer, start, length, dict);
     },
-    skip: function decodestream_skip(n) {
+    skip: function DecodeStream_skip(n) {
       if (!n)
         n = 1;
       this.pos += n;
     },
-    reset: function decodestream_reset() {
+    reset: function DecodeStream_reset() {
       this.pos = 0;
     }
   };
 
-  return constructor;
+  return DecodeStream;
 })();
 
-var FakeStream = (function fakeStream() {
-  function constructor(stream) {
+var FakeStream = (function FakeStreamClosure() {
+  function FakeStream(stream) {
     this.dict = stream.dict;
     DecodeStream.call(this);
   }
 
-  constructor.prototype = Object.create(DecodeStream.prototype);
-  constructor.prototype.readBlock = function fakeStreamReadBlock() {
+  FakeStream.prototype = Object.create(DecodeStream.prototype);
+  FakeStream.prototype.readBlock = function FakeStream_readBlock() {
     var bufferLength = this.bufferLength;
     bufferLength += 1024;
     var buffer = this.ensureBuffer(bufferLength);
     this.bufferLength = bufferLength;
   };
 
-  constructor.prototype.getBytes = function fakeStreamGetBytes(length) {
+  FakeStream.prototype.getBytes = function FakeStream_getBytes(length) {
     var end, pos = this.pos;
 
     if (length) {
@@ -24021,18 +26740,20 @@ var FakeStream = (function fakeStream() {
     return this.buffer.subarray(pos, end);
   };
 
-  return constructor;
+  return FakeStream;
 })();
 
-var StreamsSequenceStream = (function streamSequenceStream() {
-  function constructor(streams) {
+var StreamsSequenceStream = (function StreamsSequenceStreamClosure() {
+  function StreamsSequenceStream(streams) {
     this.streams = streams;
     DecodeStream.call(this);
   }
 
-  constructor.prototype = Object.create(DecodeStream.prototype);
+  StreamsSequenceStream.prototype = Object.create(DecodeStream.prototype);
+
+  StreamsSequenceStream.prototype.readBlock =
+    function streamSequenceStreamReadBlock() {
 
-  constructor.prototype.readBlock = function streamSequenceStreamReadBlock() {
     var streams = this.streams;
     if (streams.length == 0) {
       this.eof = true;
@@ -24047,10 +26768,10 @@ var StreamsSequenceStream = (function streamSequenceStream() {
     this.bufferLength = newLength;
   };
 
-  return constructor;
+  return StreamsSequenceStream;
 })();
 
-var FlateStream = (function flateStream() {
+var FlateStream = (function FlateStreamClosure() {
   var codeLenCodeMap = new Uint32Array([
     16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15
   ]);
@@ -24143,7 +26864,7 @@ var FlateStream = (function flateStream() {
     0x50003, 0x50013, 0x5000b, 0x5001b, 0x50007, 0x50017, 0x5000f, 0x00000
   ]), 5];
 
-  function constructor(stream) {
+  function FlateStream(stream) {
     var bytes = stream.getBytes();
     var bytesPos = 0;
 
@@ -24168,9 +26889,9 @@ var FlateStream = (function flateStream() {
     DecodeStream.call(this);
   }
 
-  constructor.prototype = Object.create(DecodeStream.prototype);
+  FlateStream.prototype = Object.create(DecodeStream.prototype);
 
-  constructor.prototype.getBits = function flateStreamGetBits(bits) {
+  FlateStream.prototype.getBits = function FlateStream_getBits(bits) {
     var codeSize = this.codeSize;
     var codeBuf = this.codeBuf;
     var bytes = this.bytes;
@@ -24190,7 +26911,7 @@ var FlateStream = (function flateStream() {
     return b;
   };
 
-  constructor.prototype.getCode = function flateStreamGetCode(table) {
+  FlateStream.prototype.getCode = function FlateStream_getCode(table) {
     var codes = table[0];
     var maxLen = table[1];
     var codeSize = this.codeSize;
@@ -24216,7 +26937,7 @@ var FlateStream = (function flateStream() {
     return codeVal;
   };
 
-  constructor.prototype.generateHuffmanTable =
+  FlateStream.prototype.generateHuffmanTable =
     function flateStreamGenerateHuffmanTable(lengths) {
     var n = lengths.length;
 
@@ -24255,7 +26976,7 @@ var FlateStream = (function flateStream() {
     return [codes, maxLen];
   };
 
-  constructor.prototype.readBlock = function flateStreamReadBlock() {
+  FlateStream.prototype.readBlock = function FlateStream_readBlock() {
     // read block header
     var hdr = this.getBits(3);
     if (hdr & 1)
@@ -24386,11 +27107,11 @@ var FlateStream = (function flateStream() {
     }
   };
 
-  return constructor;
+  return FlateStream;
 })();
 
-var PredictorStream = (function predictorStream() {
-  function constructor(stream, params) {
+var PredictorStream = (function PredictorStreamClosure() {
+  function PredictorStream(stream, params) {
     var predictor = this.predictor = params.get('Predictor') || 1;
 
     if (predictor <= 1)
@@ -24417,15 +27138,14 @@ var PredictorStream = (function predictorStream() {
     return this;
   }
 
-  constructor.prototype = Object.create(DecodeStream.prototype);
+  PredictorStream.prototype = Object.create(DecodeStream.prototype);
 
-  constructor.prototype.readBlockTiff =
+  PredictorStream.prototype.readBlockTiff =
     function predictorStreamReadBlockTiff() {
     var rowBytes = this.rowBytes;
 
     var bufferLength = this.bufferLength;
     var buffer = this.ensureBuffer(bufferLength + rowBytes);
-    var currentRow = buffer.subarray(bufferLength, bufferLength + rowBytes);
 
     var bits = this.bits;
     var colors = this.colors;
@@ -24434,6 +27154,7 @@ var PredictorStream = (function predictorStream() {
 
     var inbuf = 0, outbuf = 0;
     var inbits = 0, outbits = 0;
+    var pos = bufferLength;
 
     if (bits === 1) {
       for (var i = 0; i < rowBytes; ++i) {
@@ -24441,19 +27162,21 @@ var PredictorStream = (function predictorStream() {
         inbuf = (inbuf << 8) | c;
         // bitwise addition is exclusive or
         // first shift inbuf and then add
-        currentRow[i] = (c ^ (inbuf >> colors)) & 0xFF;
+        buffer[pos++] = (c ^ (inbuf >> colors)) & 0xFF;
         // truncate inbuf (assumes colors < 16)
         inbuf &= 0xFFFF;
       }
     } else if (bits === 8) {
       for (var i = 0; i < colors; ++i)
-        currentRow[i] = rawBytes[i];
-      for (; i < rowBytes; ++i)
-        currentRow[i] = currentRow[i - colors] + rawBytes[i];
+        buffer[pos++] = rawBytes[i];
+      for (; i < rowBytes; ++i) {
+        buffer[pos] = buffer[pos - colors] + rawBytes[i];
+        pos++;
+      }
     } else {
       var compArray = new Uint8Array(colors + 1);
       var bitMask = (1 << bits) - 1;
-      var j = 0, k = 0;
+      var j = 0, k = bufferLength;
       var columns = this.columns;
       for (var i = 0; i < columns; ++i) {
         for (var kk = 0; kk < colors; ++kk) {
@@ -24467,20 +27190,22 @@ var PredictorStream = (function predictorStream() {
           outbuf = (outbuf << bits) | compArray[kk];
           outbits += bits;
           if (outbits >= 8) {
-            currentRow[k++] = (outbuf >> (outbits - 8)) & 0xFF;
+            buffer[k++] = (outbuf >> (outbits - 8)) & 0xFF;
             outbits -= 8;
           }
         }
       }
       if (outbits > 0) {
-        currentRow[k++] = (outbuf << (8 - outbits)) +
+        buffer[k++] = (outbuf << (8 - outbits)) +
         (inbuf & ((1 << (8 - outbits)) - 1));
       }
     }
     this.bufferLength += rowBytes;
   };
 
-  constructor.prototype.readBlockPng = function predictorStreamReadBlockPng() {
+  PredictorStream.prototype.readBlockPng =
+    function predictorStreamReadBlockPng() {
+
     var rowBytes = this.rowBytes;
     var pixBytes = this.pixBytes;
 
@@ -24490,32 +27215,35 @@ var PredictorStream = (function predictorStream() {
     var bufferLength = this.bufferLength;
     var buffer = this.ensureBuffer(bufferLength + rowBytes);
 
-    var currentRow = buffer.subarray(bufferLength, bufferLength + rowBytes);
     var prevRow = buffer.subarray(bufferLength - rowBytes, bufferLength);
     if (prevRow.length == 0)
       prevRow = new Uint8Array(rowBytes);
 
+    var j = bufferLength;
     switch (predictor) {
       case 0:
         for (var i = 0; i < rowBytes; ++i)
-          currentRow[i] = rawBytes[i];
+          buffer[j++] = rawBytes[i];
         break;
       case 1:
         for (var i = 0; i < pixBytes; ++i)
-          currentRow[i] = rawBytes[i];
-        for (; i < rowBytes; ++i)
-          currentRow[i] = (currentRow[i - pixBytes] + rawBytes[i]) & 0xFF;
+          buffer[j++] = rawBytes[i];
+        for (; i < rowBytes; ++i) {
+          buffer[j] = (buffer[j - pixBytes] + rawBytes[i]) & 0xFF;
+          j++;
+        }
         break;
       case 2:
         for (var i = 0; i < rowBytes; ++i)
-          currentRow[i] = (prevRow[i] + rawBytes[i]) & 0xFF;
+          buffer[j++] = (prevRow[i] + rawBytes[i]) & 0xFF;
         break;
       case 3:
         for (var i = 0; i < pixBytes; ++i)
-          currentRow[i] = (prevRow[i] >> 1) + rawBytes[i];
+          buffer[j++] = (prevRow[i] >> 1) + rawBytes[i];
         for (; i < rowBytes; ++i) {
-          currentRow[i] = (((prevRow[i] + currentRow[i - pixBytes]) >> 1) +
+          buffer[j] = (((prevRow[i] + buffer[j - pixBytes]) >> 1) +
                            rawBytes[i]) & 0xFF;
+          j++;
         }
         break;
       case 4:
@@ -24524,12 +27252,12 @@ var PredictorStream = (function predictorStream() {
         for (var i = 0; i < pixBytes; ++i) {
           var up = prevRow[i];
           var c = rawBytes[i];
-          currentRow[i] = up + c;
+          buffer[j++] = up + c;
         }
         for (; i < rowBytes; ++i) {
           var up = prevRow[i];
           var upLeft = prevRow[i - pixBytes];
-          var left = currentRow[i - pixBytes];
+          var left = buffer[j - pixBytes];
           var p = left + up - upLeft;
 
           var pa = p - left;
@@ -24544,11 +27272,11 @@ var PredictorStream = (function predictorStream() {
 
           var c = rawBytes[i];
           if (pa <= pb && pa <= pc)
-            currentRow[i] = left + c;
+            buffer[j++] = left + c;
           else if (pb <= pc)
-            currentRow[i] = up + c;
+            buffer[j++] = up + c;
           else
-            currentRow[i] = upLeft + c;
+            buffer[j++] = upLeft + c;
         }
         break;
       default:
@@ -24557,7 +27285,7 @@ var PredictorStream = (function predictorStream() {
     this.bufferLength += rowBytes;
   };
 
-  return constructor;
+  return PredictorStream;
 })();
 
 /**
@@ -24567,7 +27295,7 @@ var PredictorStream = (function predictorStream() {
  * a library to decode these images and the stream behaves like all the other
  * DecodeStreams.
  */
-var JpegStream = (function jpegStream() {
+var JpegStream = (function JpegStreamClosure() {
   function isAdobeImage(bytes) {
     var maxBytesScanned = Math.max(bytes.length - 16, 1024);
     // Looking for APP14, 'Adobe'
@@ -24598,63 +27326,184 @@ var JpegStream = (function jpegStream() {
     return newBytes;
   }
 
-  function constructor(bytes, dict, xref) {
+  function JpegStream(bytes, dict, xref) {
     // TODO: per poppler, some images may have 'junk' before that
     // need to be removed
     this.dict = dict;
 
-    // Flag indicating wether the image can be natively loaded.
-    this.isNative = true;
-
-    this.colorTransform = -1;
+    this.isAdobeImage = false;
+    this.colorTransform = dict.get('ColorTransform') || -1;
 
     if (isAdobeImage(bytes)) {
-      // when bug 674619 land, let's check if browser can do
-      // normal cmyk and then we won't have to the following
-      var cs = xref.fetchIfRef(dict.get('ColorSpace'));
-
-      // DeviceRGB and DeviceGray are the only Adobe images that work natively
-      if (isName(cs) && (cs.name === 'DeviceRGB' || cs.name === 'DeviceGray')) {
-        bytes = fixAdobeImage(bytes);
-        this.src = bytesToString(bytes);
-      } else {
-        this.colorTransform = dict.get('ColorTransform');
-        this.isNative = false;
-        this.bytes = bytes;
-      }
-    } else {
-      this.src = bytesToString(bytes);
+      this.isAdobeImage = true;
+      bytes = fixAdobeImage(bytes);
+    }
+
+    this.bytes = bytes;
+
+    DecodeStream.call(this);
+  }
+
+  JpegStream.prototype = Object.create(DecodeStream.prototype);
+
+  JpegStream.prototype.ensureBuffer = function JpegStream_ensureBuffer(req) {
+    if (this.bufferLength)
+      return;
+    try {
+      var jpegImage = new JpegImage();
+      if (this.colorTransform != -1)
+        jpegImage.colorTransform = this.colorTransform;
+      jpegImage.parse(this.bytes);
+      var width = jpegImage.width;
+      var height = jpegImage.height;
+      var data = jpegImage.getData(width, height);
+      this.buffer = data;
+      this.bufferLength = data.length;
+    } catch (e) {
+      error('JPEG error: ' + e);
     }
+  };
+  JpegStream.prototype.getIR = function JpegStream_getIR() {
+    return bytesToString(this.bytes);
+  };
+  JpegStream.prototype.getChar = function JpegStream_getChar() {
+    error('internal error: getChar is not valid on JpegStream');
+  };
+  /**
+   * Checks if the image can be decoded and displayed by the browser without any
+   * further processing such as color space conversions.
+   */
+  JpegStream.prototype.isNativelySupported =
+    function JpegStream_isNativelySupported(xref, res) {
+    var cs = ColorSpace.parse(this.dict.get('ColorSpace'), xref, res);
+    // when bug 674619 lands, let's check if browser can do
+    // normal cmyk and then we won't need to decode in JS
+    if (cs.name === 'DeviceGray' || cs.name === 'DeviceRGB')
+      return true;
+    if (cs.name === 'DeviceCMYK' && !this.isAdobeImage &&
+        this.colorTransform < 1)
+      return true;
+    return false;
+  };
+  /**
+   * Checks if the image can be decoded by the browser.
+   */
+  JpegStream.prototype.isNativelyDecodable =
+    function JpegStream_isNativelyDecodable(xref, res) {
+    var cs = ColorSpace.parse(this.dict.get('ColorSpace'), xref, res);
+    var numComps = cs.numComps;
+    if (numComps == 1 || numComps == 3)
+      return true;
+
+    return false;
+  };
+
+  return JpegStream;
+})();
+
+/**
+ * For JPEG 2000's we use a library to decode these images and
+ * the stream behaves like all the other DecodeStreams.
+ */
+var JpxStream = (function JpxStreamClosure() {
+  function JpxStream(bytes, dict) {
+    this.dict = dict;
+    this.bytes = bytes;
 
     DecodeStream.call(this);
   }
 
-  constructor.prototype = Object.create(DecodeStream.prototype);
+  JpxStream.prototype = Object.create(DecodeStream.prototype);
 
-  constructor.prototype.ensureBuffer = function jpegStreamEnsureBuffer(req) {
+  JpxStream.prototype.ensureBuffer = function JpxStream_ensureBuffer(req) {
     if (this.bufferLength)
       return;
-    var jpegImage = new JpegImage();
-    jpegImage.colorTransform = this.colorTransform;
-    jpegImage.parse(this.bytes);
-    var width = jpegImage.width;
-    var height = jpegImage.height;
-    var data = jpegImage.getData(width, height);
+
+    var jpxImage = new JpxImage();
+    jpxImage.parse(this.bytes);
+
+    var width = jpxImage.width;
+    var height = jpxImage.height;
+    var componentsCount = jpxImage.componentsCount;
+    if (componentsCount != 1 && componentsCount != 3 && componentsCount != 4)
+      error('JPX with ' + componentsCount + ' components is not supported');
+
+    var data = new Uint8Array(width * height * componentsCount);
+
+    for (var k = 0, kk = jpxImage.tiles.length; k < kk; k++) {
+      var tileCompoments = jpxImage.tiles[k];
+      var tileWidth = tileCompoments[0].width;
+      var tileHeight = tileCompoments[0].height;
+      var tileLeft = tileCompoments[0].left;
+      var tileTop = tileCompoments[0].top;
+
+      var dataPosition, sourcePosition, data0, data1, data2, data3, rowFeed;
+      switch (componentsCount) {
+        case 1:
+          data0 = tileCompoments[0].items;
+
+          dataPosition = width * tileTop + tileLeft;
+          rowFeed = width - tileWidth;
+          sourcePosition = 0;
+          for (var j = 0; j < tileHeight; j++) {
+            for (var i = 0; i < tileWidth; i++)
+              data[dataPosition++] = data0[sourcePosition++];
+            dataPosition += rowFeed;
+          }
+          break;
+        case 3:
+          data0 = tileCompoments[0].items;
+          data1 = tileCompoments[1].items;
+          data2 = tileCompoments[2].items;
+
+          dataPosition = (width * tileTop + tileLeft) * 3;
+          rowFeed = (width - tileWidth) * 3;
+          sourcePosition = 0;
+          for (var j = 0; j < tileHeight; j++) {
+            for (var i = 0; i < tileWidth; i++) {
+              data[dataPosition++] = data0[sourcePosition];
+              data[dataPosition++] = data1[sourcePosition];
+              data[dataPosition++] = data2[sourcePosition];
+              sourcePosition++;
+            }
+            dataPosition += rowFeed;
+          }
+          break;
+        case 4:
+          data0 = tileCompoments[0].items;
+          data1 = tileCompoments[1].items;
+          data2 = tileCompoments[2].items;
+          data3 = tileCompoments[3].items;
+
+          dataPosition = (width * tileTop + tileLeft) * 4;
+          rowFeed = (width - tileWidth) * 4;
+          sourcePosition = 0;
+          for (var j = 0; j < tileHeight; j++) {
+            for (var i = 0; i < tileWidth; i++) {
+              data[dataPosition++] = data0[sourcePosition];
+              data[dataPosition++] = data1[sourcePosition];
+              data[dataPosition++] = data2[sourcePosition];
+              data[dataPosition++] = data3[sourcePosition];
+              sourcePosition++;
+            }
+            dataPosition += rowFeed;
+          }
+          break;
+      }
+    }
+
     this.buffer = data;
     this.bufferLength = data.length;
   };
-  constructor.prototype.getIR = function jpegStreamGetIR() {
-    return this.src;
-  };
-  constructor.prototype.getChar = function jpegStreamGetChar() {
-      error('internal error: getChar is not valid on JpegStream');
+  JpxStream.prototype.getChar = function JpxStream_getChar() {
+    error('internal error: getChar is not valid on JpxStream');
   };
 
-  return constructor;
+  return JpxStream;
 })();
 
-var DecryptStream = (function decryptStream() {
-  function constructor(str, decrypt) {
+var DecryptStream = (function DecryptStreamClosure() {
+  function DecryptStream(str, decrypt) {
     this.str = str;
     this.dict = str.dict;
     this.decrypt = decrypt;
@@ -24664,9 +27513,9 @@ var DecryptStream = (function decryptStream() {
 
   var chunkSize = 512;
 
-  constructor.prototype = Object.create(DecodeStream.prototype);
+  DecryptStream.prototype = Object.create(DecodeStream.prototype);
 
-  constructor.prototype.readBlock = function decryptStreamReadBlock() {
+  DecryptStream.prototype.readBlock = function DecryptStream_readBlock() {
     var chunk = this.str.getBytes(chunkSize);
     if (!chunk || chunk.length == 0) {
       this.eof = true;
@@ -24683,11 +27532,11 @@ var DecryptStream = (function decryptStream() {
     this.bufferLength = bufferLength;
   };
 
-  return constructor;
+  return DecryptStream;
 })();
 
-var Ascii85Stream = (function ascii85Stream() {
-  function constructor(str) {
+var Ascii85Stream = (function Ascii85StreamClosure() {
+  function Ascii85Stream(str) {
     this.str = str;
     this.dict = str.dict;
     this.input = new Uint8Array(5);
@@ -24695,9 +27544,9 @@ var Ascii85Stream = (function ascii85Stream() {
     DecodeStream.call(this);
   }
 
-  constructor.prototype = Object.create(DecodeStream.prototype);
+  Ascii85Stream.prototype = Object.create(DecodeStream.prototype);
 
-  constructor.prototype.readBlock = function ascii85StreamReadBlock() {
+  Ascii85Stream.prototype.readBlock = function Ascii85Stream_readBlock() {
     var tildaCode = '~'.charCodeAt(0);
     var zCode = 'z'.charCodeAt(0);
     var str = this.str;
@@ -24752,11 +27601,11 @@ var Ascii85Stream = (function ascii85Stream() {
     }
   };
 
-  return constructor;
+  return Ascii85Stream;
 })();
 
-var AsciiHexStream = (function asciiHexStream() {
-  function constructor(str) {
+var AsciiHexStream = (function AsciiHexStreamClosure() {
+  function AsciiHexStream(str) {
     this.str = str;
     this.dict = str.dict;
 
@@ -24790,9 +27639,9 @@ var AsciiHexStream = (function asciiHexStream() {
       102: 15
   };
 
-  constructor.prototype = Object.create(DecodeStream.prototype);
+  AsciiHexStream.prototype = Object.create(DecodeStream.prototype);
 
-  constructor.prototype.readBlock = function asciiHexStreamReadBlock() {
+  AsciiHexStream.prototype.readBlock = function AsciiHexStream_readBlock() {
     var gtCode = '>'.charCodeAt(0), bytes = this.str.getBytes(), c, n,
         decodeLength, buffer, bufferLength, i, length;
 
@@ -24822,10 +27671,55 @@ var AsciiHexStream = (function asciiHexStream() {
     this.eof = true;
   };
 
-  return constructor;
+  return AsciiHexStream;
+})();
+
+var RunLengthStream = (function RunLengthStreamClosure() {
+  function RunLengthStream(str) {
+    this.str = str;
+    this.dict = str.dict;
+
+    DecodeStream.call(this);
+  }
+
+  RunLengthStream.prototype = Object.create(DecodeStream.prototype);
+
+  RunLengthStream.prototype.readBlock = function RunLengthStream_readBlock() {
+    // The repeatHeader has following format. The first byte defines type of run
+    // and amount of bytes to repeat/copy: n = 0 through 127 - copy next n bytes
+    // (in addition to the second byte from the header), n = 129 through 255 -
+    // duplicate the second byte from the header (257 - n) times, n = 128 - end.
+    var repeatHeader = this.str.getBytes(2);
+    if (!repeatHeader || repeatHeader.length < 2 || repeatHeader[0] == 128) {
+      this.eof = true;
+      return;
+    }
+
+    var bufferLength = this.bufferLength;
+    var n = repeatHeader[0];
+    if (n < 128) {
+      // copy n bytes
+      var buffer = this.ensureBuffer(bufferLength + n + 1);
+      buffer[bufferLength++] = repeatHeader[1];
+      if (n > 0) {
+        var source = this.str.getBytes(n);
+        buffer.set(source, bufferLength);
+        bufferLength += n;
+      }
+    } else {
+      n = 257 - n;
+      var b = repeatHeader[1];
+      var buffer = this.ensureBuffer(bufferLength + n + 1);
+      for (var i = 0; i < n; i++)
+        buffer[bufferLength++] = b;
+    }
+    this.bufferLength = bufferLength;
+  };
+
+  return RunLengthStream;
 })();
 
-var CCITTFaxStream = (function ccittFaxStream() {
+var CCITTFaxStream = (function CCITTFaxStreamClosure() {
 
   var ccittEOL = -2;
   var twoDimPass = 0;
@@ -25253,1770 +28147,4144 @@ var CCITTFaxStream = (function ccittFaxStream() {
     [2, 2], [2, 2], [2, 2], [2, 2]
   ];
 
-  function constructor(str, params) {
-    this.str = str;
-    this.dict = str.dict;
+  function CCITTFaxStream(str, params) {
+    this.str = str;
+    this.dict = str.dict;
+
+    params = params || new Dict();
+
+    this.encoding = params.get('K') || 0;
+    this.eoline = params.get('EndOfLine') || false;
+    this.byteAlign = params.get('EncodedByteAlign') || false;
+    this.columns = params.get('Columns') || 1728;
+    this.rows = params.get('Rows') || 0;
+    var eoblock = params.get('EndOfBlock');
+    if (eoblock == null)
+      eoblock = true;
+    this.eoblock = eoblock;
+    this.black = params.get('BlackIs1') || false;
+
+    this.codingLine = new Uint32Array(this.columns + 1);
+    this.refLine = new Uint32Array(this.columns + 2);
+
+    this.codingLine[0] = this.columns;
+    this.codingPos = 0;
+
+    this.row = 0;
+    this.nextLine2D = this.encoding < 0;
+    this.inputBits = 0;
+    this.inputBuf = 0;
+    this.outputBits = 0;
+    this.buf = EOF;
+
+    var code1;
+    while ((code1 = this.lookBits(12)) == 0) {
+      this.eatBits(1);
+    }
+    if (code1 == 1) {
+      this.eatBits(12);
+    }
+    if (this.encoding > 0) {
+      this.nextLine2D = !this.lookBits(1);
+      this.eatBits(1);
+    }
+
+    DecodeStream.call(this);
+  }
+
+  CCITTFaxStream.prototype = Object.create(DecodeStream.prototype);
+
+  CCITTFaxStream.prototype.readBlock = function CCITTFaxStream_readBlock() {
+    while (!this.eof) {
+      var c = this.lookChar();
+      this.buf = EOF;
+      this.ensureBuffer(this.bufferLength + 1);
+      this.buffer[this.bufferLength++] = c;
+    }
+  };
+
+  CCITTFaxStream.prototype.addPixels =
+    function ccittFaxStreamAddPixels(a1, blackPixels) {
+    var codingLine = this.codingLine;
+    var codingPos = this.codingPos;
+
+    if (a1 > codingLine[codingPos]) {
+      if (a1 > this.columns) {
+        warn('row is wrong length');
+        this.err = true;
+        a1 = this.columns;
+      }
+      if ((codingPos & 1) ^ blackPixels) {
+        ++codingPos;
+      }
+
+      codingLine[codingPos] = a1;
+    }
+    this.codingPos = codingPos;
+  };
+
+  CCITTFaxStream.prototype.addPixelsNeg =
+    function ccittFaxStreamAddPixelsNeg(a1, blackPixels) {
+    var codingLine = this.codingLine;
+    var codingPos = this.codingPos;
+
+    if (a1 > codingLine[codingPos]) {
+      if (a1 > this.columns) {
+        warn('row is wrong length');
+        this.err = true;
+        a1 = this.columns;
+      }
+      if ((codingPos & 1) ^ blackPixels)
+        ++codingPos;
+
+      codingLine[codingPos] = a1;
+    } else if (a1 < codingLine[codingPos]) {
+      if (a1 < 0) {
+        warn('invalid code');
+        this.err = true;
+        a1 = 0;
+      }
+      while (codingPos > 0 && a1 < codingLine[codingPos - 1])
+        --codingPos;
+      codingLine[codingPos] = a1;
+    }
+
+    this.codingPos = codingPos;
+  };
+
+  CCITTFaxStream.prototype.lookChar = function CCITTFaxStream_lookChar() {
+    if (this.buf != EOF)
+      return this.buf;
+
+    var refLine = this.refLine;
+    var codingLine = this.codingLine;
+    var columns = this.columns;
+
+    var refPos, blackPixels, bits;
+
+    if (this.outputBits == 0) {
+      if (this.eof)
+        return null;
+
+      this.err = false;
+
+      var code1, code2, code3;
+      if (this.nextLine2D) {
+        for (var i = 0; codingLine[i] < columns; ++i)
+          refLine[i] = codingLine[i];
+
+        refLine[i++] = columns;
+        refLine[i] = columns;
+        codingLine[0] = 0;
+        this.codingPos = 0;
+        refPos = 0;
+        blackPixels = 0;
+
+        while (codingLine[this.codingPos] < columns) {
+          code1 = this.getTwoDimCode();
+          switch (code1) {
+            case twoDimPass:
+              this.addPixels(refLine[refPos + 1], blackPixels);
+              if (refLine[refPos + 1] < columns)
+                refPos += 2;
+              break;
+            case twoDimHoriz:
+              code1 = code2 = 0;
+              if (blackPixels) {
+                do {
+                  code1 += (code3 = this.getBlackCode());
+                } while (code3 >= 64);
+                do {
+                  code2 += (code3 = this.getWhiteCode());
+                } while (code3 >= 64);
+              } else {
+                do {
+                  code1 += (code3 = this.getWhiteCode());
+                } while (code3 >= 64);
+                do {
+                  code2 += (code3 = this.getBlackCode());
+                } while (code3 >= 64);
+              }
+              this.addPixels(codingLine[this.codingPos] +
+                             code1, blackPixels);
+              if (codingLine[this.codingPos] < columns) {
+                this.addPixels(codingLine[this.codingPos] + code2,
+                               blackPixels ^ 1);
+              }
+              while (refLine[refPos] <= codingLine[this.codingPos] &&
+                     refLine[refPos] < columns) {
+                refPos += 2;
+              }
+              break;
+            case twoDimVertR3:
+              this.addPixels(refLine[refPos] + 3, blackPixels);
+              blackPixels ^= 1;
+              if (codingLine[this.codingPos] < columns) {
+                ++refPos;
+                while (refLine[refPos] <= codingLine[this.codingPos] &&
+                       refLine[refPos] < columns)
+                  refPos += 2;
+              }
+              break;
+            case twoDimVertR2:
+              this.addPixels(refLine[refPos] + 2, blackPixels);
+              blackPixels ^= 1;
+              if (codingLine[this.codingPos] < columns) {
+                ++refPos;
+                while (refLine[refPos] <= codingLine[this.codingPos] &&
+                       refLine[refPos] < columns) {
+                  refPos += 2;
+                }
+              }
+              break;
+            case twoDimVertR1:
+              this.addPixels(refLine[refPos] + 1, blackPixels);
+              blackPixels ^= 1;
+              if (codingLine[this.codingPos] < columns) {
+                ++refPos;
+                while (refLine[refPos] <= codingLine[this.codingPos] &&
+                       refLine[refPos] < columns)
+                  refPos += 2;
+              }
+              break;
+            case twoDimVert0:
+              this.addPixels(refLine[refPos], blackPixels);
+              blackPixels ^= 1;
+              if (codingLine[this.codingPos] < columns) {
+                ++refPos;
+                while (refLine[refPos] <= codingLine[this.codingPos] &&
+                       refLine[refPos] < columns)
+                  refPos += 2;
+              }
+              break;
+            case twoDimVertL3:
+              this.addPixelsNeg(refLine[refPos] - 3, blackPixels);
+              blackPixels ^= 1;
+              if (codingLine[this.codingPos] < columns) {
+                if (refPos > 0)
+                  --refPos;
+                else
+                  ++refPos;
+                while (refLine[refPos] <= codingLine[this.codingPos] &&
+                       refLine[refPos] < columns)
+                  refPos += 2;
+              }
+              break;
+            case twoDimVertL2:
+              this.addPixelsNeg(refLine[refPos] - 2, blackPixels);
+              blackPixels ^= 1;
+              if (codingLine[this.codingPos] < columns) {
+                if (refPos > 0)
+                  --refPos;
+                else
+                  ++refPos;
+                while (refLine[refPos] <= codingLine[this.codingPos] &&
+                       refLine[refPos] < columns)
+                  refPos += 2;
+              }
+              break;
+            case twoDimVertL1:
+              this.addPixelsNeg(refLine[refPos] - 1, blackPixels);
+              blackPixels ^= 1;
+              if (codingLine[this.codingPos] < columns) {
+                if (refPos > 0)
+                  --refPos;
+                else
+                  ++refPos;
+
+                while (refLine[refPos] <= codingLine[this.codingPos] &&
+                       refLine[refPos] < columns)
+                  refPos += 2;
+              }
+              break;
+            case EOF:
+              this.addPixels(columns, 0);
+              this.eof = true;
+              break;
+            default:
+              warn('bad 2d code');
+              this.addPixels(columns, 0);
+              this.err = true;
+          }
+        }
+      } else {
+        codingLine[0] = 0;
+        this.codingPos = 0;
+        blackPixels = 0;
+        while (codingLine[this.codingPos] < columns) {
+          code1 = 0;
+          if (blackPixels) {
+            do {
+              code1 += (code3 = this.getBlackCode());
+            } while (code3 >= 64);
+          } else {
+            do {
+              code1 += (code3 = this.getWhiteCode());
+            } while (code3 >= 64);
+          }
+          this.addPixels(codingLine[this.codingPos] + code1, blackPixels);
+          blackPixels ^= 1;
+        }
+      }
+
+      if (this.byteAlign)
+        this.inputBits &= ~7;
+
+      var gotEOL = false;
+
+      if (!this.eoblock && this.row == this.rows - 1) {
+        this.eof = true;
+      } else {
+        code1 = this.lookBits(12);
+        while (code1 == 0) {
+          this.eatBits(1);
+          code1 = this.lookBits(12);
+        }
+        if (code1 == 1) {
+          this.eatBits(12);
+          gotEOL = true;
+        } else if (code1 == EOF) {
+          this.eof = true;
+        }
+      }
+
+      if (!this.eof && this.encoding > 0) {
+        this.nextLine2D = !this.lookBits(1);
+        this.eatBits(1);
+      }
+
+      if (this.eoblock && gotEOL) {
+        code1 = this.lookBits(12);
+        if (code1 == 1) {
+          this.eatBits(12);
+          if (this.encoding > 0) {
+            this.lookBits(1);
+            this.eatBits(1);
+          }
+          if (this.encoding >= 0) {
+            for (var i = 0; i < 4; ++i) {
+              code1 = this.lookBits(12);
+              if (code1 != 1)
+                warn('bad rtc code: ' + code1);
+              this.eatBits(12);
+              if (this.encoding > 0) {
+                this.lookBits(1);
+                this.eatBits(1);
+              }
+            }
+          }
+          this.eof = true;
+        }
+      } else if (this.err && this.eoline) {
+        while (true) {
+          code1 = this.lookBits(13);
+          if (code1 == EOF) {
+            this.eof = true;
+            return null;
+          }
+          if ((code1 >> 1) == 1) {
+            break;
+          }
+          this.eatBits(1);
+        }
+        this.eatBits(12);
+        if (this.encoding > 0) {
+          this.eatBits(1);
+          this.nextLine2D = !(code1 & 1);
+        }
+      }
+
+      if (codingLine[0] > 0)
+        this.outputBits = codingLine[this.codingPos = 0];
+      else
+        this.outputBits = codingLine[this.codingPos = 1];
+      this.row++;
+    }
+
+    if (this.outputBits >= 8) {
+      this.buf = (this.codingPos & 1) ? 0 : 0xFF;
+      this.outputBits -= 8;
+      if (this.outputBits == 0 && codingLine[this.codingPos] < columns) {
+        this.codingPos++;
+        this.outputBits = (codingLine[this.codingPos] -
+                           codingLine[this.codingPos - 1]);
+      }
+    } else {
+      var bits = 8;
+      this.buf = 0;
+      do {
+        if (this.outputBits > bits) {
+          this.buf <<= bits;
+          if (!(this.codingPos & 1)) {
+            this.buf |= 0xFF >> (8 - bits);
+          }
+          this.outputBits -= bits;
+          bits = 0;
+        } else {
+          this.buf <<= this.outputBits;
+          if (!(this.codingPos & 1)) {
+            this.buf |= 0xFF >> (8 - this.outputBits);
+          }
+          bits -= this.outputBits;
+          this.outputBits = 0;
+          if (codingLine[this.codingPos] < columns) {
+            this.codingPos++;
+            this.outputBits = (codingLine[this.codingPos] -
+                               codingLine[this.codingPos - 1]);
+          } else if (bits > 0) {
+            this.buf <<= bits;
+            bits = 0;
+          }
+        }
+      } while (bits);
+    }
+    if (this.black) {
+      this.buf ^= 0xFF;
+    }
+    return this.buf;
+  };
+
+  // This functions returns the code found from the table.
+  // The start and end parameters set the boundaries for searching the table.
+  // The limit parameter is optional. Function returns an array with three
+  // values. The first array element indicates whether a valid code is being
+  // returned. The second array element is the actual code. The third array
+  // element indicates whether EOF was reached.
+  CCITTFaxStream.prototype.findTableCode =
+    function ccittFaxStreamFindTableCode(start, end, table, limit) {
+
+    var limitValue = limit || 0;
+    for (var i = start; i <= end; ++i) {
+      var code = this.lookBits(i);
+      if (code == EOF)
+        return [true, 1, false];
+      if (i < end)
+        code <<= end - i;
+      if (!limitValue || code >= limitValue) {
+        var p = table[code - limitValue];
+        if (p[0] == i) {
+          this.eatBits(i);
+          return [true, p[1], true];
+        }
+      }
+    }
+    return [false, 0, false];
+  };
+
+  CCITTFaxStream.prototype.getTwoDimCode =
+    function ccittFaxStreamGetTwoDimCode() {
+
+    var code = 0;
+    var p;
+    if (this.eoblock) {
+      code = this.lookBits(7);
+      p = twoDimTable[code];
+      if (p && p[0] > 0) {
+        this.eatBits(p[0]);
+        return p[1];
+      }
+    } else {
+      var result = this.findTableCode(1, 7, twoDimTable);
+      if (result[0] && result[2])
+        return result[1];
+    }
+    warn('Bad two dim code');
+    return EOF;
+  };
+
+  CCITTFaxStream.prototype.getWhiteCode =
+    function ccittFaxStreamGetWhiteCode() {
+
+    var code = 0;
+    var p;
+    var n;
+    if (this.eoblock) {
+      code = this.lookBits(12);
+      if (code == EOF)
+        return 1;
+
+      if ((code >> 5) == 0)
+        p = whiteTable1[code];
+      else
+        p = whiteTable2[code >> 3];
+
+      if (p[0] > 0) {
+        this.eatBits(p[0]);
+        return p[1];
+      }
+    } else {
+      var result = this.findTableCode(1, 9, whiteTable2);
+      if (result[0])
+        return result[1];
+
+      result = this.findTableCode(11, 12, whiteTable1);
+      if (result[0])
+        return result[1];
+    }
+    warn('bad white code');
+    this.eatBits(1);
+    return 1;
+  };
+
+  CCITTFaxStream.prototype.getBlackCode =
+    function ccittFaxStreamGetBlackCode() {
+
+    var code, p;
+    if (this.eoblock) {
+      code = this.lookBits(13);
+      if (code == EOF)
+        return 1;
+      if ((code >> 7) == 0)
+        p = blackTable1[code];
+      else if ((code >> 9) == 0 && (code >> 7) != 0)
+        p = blackTable2[(code >> 1) - 64];
+      else
+        p = blackTable3[code >> 7];
+
+      if (p[0] > 0) {
+        this.eatBits(p[0]);
+        return p[1];
+      }
+    } else {
+      var result = this.findTableCode(2, 6, blackTable3);
+      if (result[0])
+        return result[1];
+
+      result = this.findTableCode(7, 12, blackTable2, 64);
+      if (result[0])
+        return result[1];
+
+      result = this.findTableCode(10, 13, blackTable1);
+      if (result[0])
+        return result[1];
+    }
+    warn('bad black code');
+    this.eatBits(1);
+    return 1;
+  };
+
+  CCITTFaxStream.prototype.lookBits = function CCITTFaxStream_lookBits(n) {
+    var c;
+    while (this.inputBits < n) {
+      if ((c = this.str.getByte()) == null) {
+        if (this.inputBits == 0)
+          return EOF;
+        return ((this.inputBuf << (n - this.inputBits)) &
+                (0xFFFF >> (16 - n)));
+      }
+      this.inputBuf = (this.inputBuf << 8) + c;
+      this.inputBits += 8;
+    }
+    return (this.inputBuf >> (this.inputBits - n)) & (0xFFFF >> (16 - n));
+  };
+
+  CCITTFaxStream.prototype.eatBits = function CCITTFaxStream_eatBits(n) {
+    if ((this.inputBits -= n) < 0)
+      this.inputBits = 0;
+  };
+
+  return CCITTFaxStream;
+})();
+
+var LZWStream = (function LZWStreamClosure() {
+  function LZWStream(str, earlyChange) {
+    this.str = str;
+    this.dict = str.dict;
+    this.cachedData = 0;
+    this.bitsCached = 0;
+
+    var maxLzwDictionarySize = 4096;
+    var lzwState = {
+      earlyChange: earlyChange,
+      codeLength: 9,
+      nextCode: 258,
+      dictionaryValues: new Uint8Array(maxLzwDictionarySize),
+      dictionaryLengths: new Uint16Array(maxLzwDictionarySize),
+      dictionaryPrevCodes: new Uint16Array(maxLzwDictionarySize),
+      currentSequence: new Uint8Array(maxLzwDictionarySize),
+      currentSequenceLength: 0
+    };
+    for (var i = 0; i < 256; ++i) {
+      lzwState.dictionaryValues[i] = i;
+      lzwState.dictionaryLengths[i] = 1;
+    }
+    this.lzwState = lzwState;
+
+    DecodeStream.call(this);
+  }
+
+  LZWStream.prototype = Object.create(DecodeStream.prototype);
+
+  LZWStream.prototype.readBits = function LZWStream_readBits(n) {
+    var bitsCached = this.bitsCached;
+    var cachedData = this.cachedData;
+    while (bitsCached < n) {
+      var c = this.str.getByte();
+      if (c == null) {
+        this.eof = true;
+        return null;
+      }
+      cachedData = (cachedData << 8) | c;
+      bitsCached += 8;
+    }
+    this.bitsCached = (bitsCached -= n);
+    this.cachedData = cachedData;
+    this.lastCode = null;
+    return (cachedData >>> bitsCached) & ((1 << n) - 1);
+  };
+
+  LZWStream.prototype.readBlock = function LZWStream_readBlock() {
+    var blockSize = 512;
+    var estimatedDecodedSize = blockSize * 2, decodedSizeDelta = blockSize;
+    var i, j, q;
+
+    var lzwState = this.lzwState;
+    if (!lzwState)
+      return; // eof was found
+
+    var earlyChange = lzwState.earlyChange;
+    var nextCode = lzwState.nextCode;
+    var dictionaryValues = lzwState.dictionaryValues;
+    var dictionaryLengths = lzwState.dictionaryLengths;
+    var dictionaryPrevCodes = lzwState.dictionaryPrevCodes;
+    var codeLength = lzwState.codeLength;
+    var prevCode = lzwState.prevCode;
+    var currentSequence = lzwState.currentSequence;
+    var currentSequenceLength = lzwState.currentSequenceLength;
+
+    var decodedLength = 0;
+    var currentBufferLength = this.bufferLength;
+    var buffer = this.ensureBuffer(this.bufferLength + estimatedDecodedSize);
+
+    for (i = 0; i < blockSize; i++) {
+      var code = this.readBits(codeLength);
+      var hasPrev = currentSequenceLength > 0;
+      if (code < 256) {
+        currentSequence[0] = code;
+        currentSequenceLength = 1;
+      } else if (code >= 258) {
+        if (code < nextCode) {
+          currentSequenceLength = dictionaryLengths[code];
+          for (j = currentSequenceLength - 1, q = code; j >= 0; j--) {
+            currentSequence[j] = dictionaryValues[q];
+            q = dictionaryPrevCodes[q];
+          }
+        } else {
+          currentSequence[currentSequenceLength++] = currentSequence[0];
+        }
+      } else if (code == 256) {
+        codeLength = 9;
+        nextCode = 258;
+        currentSequenceLength = 0;
+        continue;
+      } else {
+        this.eof = true;
+        delete this.lzwState;
+        break;
+      }
+
+      if (hasPrev) {
+        dictionaryPrevCodes[nextCode] = prevCode;
+        dictionaryLengths[nextCode] = dictionaryLengths[prevCode] + 1;
+        dictionaryValues[nextCode] = currentSequence[0];
+        nextCode++;
+        codeLength = (nextCode + earlyChange) & (nextCode + earlyChange - 1) ?
+          codeLength : Math.min(Math.log(nextCode + earlyChange) /
+          0.6931471805599453 + 1, 12) | 0;
+      }
+      prevCode = code;
+
+      decodedLength += currentSequenceLength;
+      if (estimatedDecodedSize < decodedLength) {
+        do {
+          estimatedDecodedSize += decodedSizeDelta;
+        } while (estimatedDecodedSize < decodedLength);
+        buffer = this.ensureBuffer(this.bufferLength + estimatedDecodedSize);
+      }
+      for (j = 0; j < currentSequenceLength; j++)
+        buffer[currentBufferLength++] = currentSequence[j];
+    }
+    lzwState.nextCode = nextCode;
+    lzwState.codeLength = codeLength;
+    lzwState.prevCode = prevCode;
+    lzwState.currentSequenceLength = currentSequenceLength;
 
-    params = params || new Dict();
+    this.bufferLength = currentBufferLength;
+  };
 
-    this.encoding = params.get('K') || 0;
-    this.eoline = params.get('EndOfLine') || false;
-    this.byteAlign = params.get('EncodedByteAlign') || false;
-    this.columns = params.get('Columns') || 1728;
-    this.rows = params.get('Rows') || 0;
-    var eoblock = params.get('EndOfBlock');
-    if (eoblock == null)
-      eoblock = true;
-    this.eoblock = eoblock;
-    this.black = params.get('BlackIs1') || false;
+  return LZWStream;
+})();
 
-    this.codingLine = new Uint32Array(this.columns + 1);
-    this.refLine = new Uint32Array(this.columns + 2);
+/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
 
-    this.codingLine[0] = this.columns;
-    this.codingPos = 0;
+'use strict';
 
-    this.row = 0;
-    this.nextLine2D = this.encoding < 0;
-    this.inputBits = 0;
-    this.inputBuf = 0;
-    this.outputBits = 0;
-    this.buf = EOF;
+function MessageHandler(name, comObj) {
+  this.name = name;
+  this.comObj = comObj;
+  this.callbackIndex = 1;
+  var callbacks = this.callbacks = {};
+  var ah = this.actionHandler = {};
 
-    var code1;
-    while ((code1 = this.lookBits(12)) == 0) {
-      this.eatBits(1);
+  ah['console_log'] = [function ahConsoleLog(data) {
+      console.log.apply(console, data);
+  }];
+  ah['console_error'] = [function ahConsoleError(data) {
+      console.error.apply(console, data);
+  }];
+
+  comObj.onmessage = function messageHandlerComObjOnMessage(event) {
+    var data = event.data;
+    if (data.isReply) {
+      var callbackId = data.callbackId;
+      if (data.callbackId in callbacks) {
+        var callback = callbacks[callbackId];
+        delete callbacks[callbackId];
+        callback(data.data);
+      } else {
+        error('Cannot resolve callback ' + callbackId);
+      }
+    } else if (data.action in ah) {
+      var action = ah[data.action];
+      if (data.callbackId) {
+        var promise = new Promise();
+        promise.then(function(resolvedData) {
+          comObj.postMessage({
+            isReply: true,
+            callbackId: data.callbackId,
+            data: resolvedData
+          });
+        });
+        action[0].call(action[1], data.data, promise);
+      } else {
+        action[0].call(action[1], data.data);
+      }
+    } else {
+      error('Unkown action from worker: ' + data.action);
     }
-    if (code1 == 1) {
-      this.eatBits(12);
+  };
+}
+
+MessageHandler.prototype = {
+  on: function messageHandlerOn(actionName, handler, scope) {
+    var ah = this.actionHandler;
+    if (ah[actionName]) {
+      error('There is already an actionName called "' + actionName + '"');
     }
-    if (this.encoding > 0) {
-      this.nextLine2D = !this.lookBits(1);
-      this.eatBits(1);
+    ah[actionName] = [handler, scope];
+  },
+  /**
+   * Sends a message to the comObj to invoke the action with the supplied data.
+   * @param {String} actionName Action to call.
+   * @param {JSON} data JSON data to send.
+   * @param {function} [callback] Optional callback that will handle a reply.
+   */
+  send: function messageHandlerSend(actionName, data, callback) {
+    var message = {
+      action: actionName,
+      data: data
+    };
+    if (callback) {
+      var callbackId = this.callbackIndex++;
+      this.callbacks[callbackId] = callback;
+      message.callbackId = callbackId;
     }
-
-    DecodeStream.call(this);
+    this.comObj.postMessage(message);
   }
+};
 
-  constructor.prototype = Object.create(DecodeStream.prototype);
+var WorkerMessageHandler = {
+  setup: function wphSetup(handler) {
+    var pdfModel = null;
 
-  constructor.prototype.readBlock = function ccittFaxStreamReadBlock() {
-    while (!this.eof) {
-      var c = this.lookChar();
-      this.buf = EOF;
-      this.ensureBuffer(this.bufferLength + 1);
-      this.buffer[this.bufferLength++] = c;
-    }
-  };
+    handler.on('test', function wphSetupTest(data) {
+      handler.send('test', data instanceof Uint8Array);
+    });
 
-  constructor.prototype.addPixels =
-    function ccittFaxStreamAddPixels(a1, blackPixels) {
-    var codingLine = this.codingLine;
-    var codingPos = this.codingPos;
+    handler.on('doc', function wphSetupDoc(data) {
+      // Create only the model of the PDFDoc, which is enough for
+      // processing the content of the pdf.
+      pdfModel = new PDFDocModel(new Stream(data));
+    });
 
-    if (a1 > codingLine[codingPos]) {
-      if (a1 > this.columns) {
-        warn('row is wrong length');
-        this.err = true;
-        a1 = this.columns;
-      }
-      if ((codingPos & 1) ^ blackPixels) {
-        ++codingPos;
-      }
+    handler.on('page_request', function wphSetupPageRequest(pageNum) {
+      pageNum = parseInt(pageNum);
 
-      codingLine[codingPos] = a1;
-    }
-    this.codingPos = codingPos;
-  };
 
-  constructor.prototype.addPixelsNeg =
-    function ccittFaxStreamAddPixelsNeg(a1, blackPixels) {
-    var codingLine = this.codingLine;
-    var codingPos = this.codingPos;
+      // The following code does quite the same as
+      // Page.prototype.startRendering, but stops at one point and sends the
+      // result back to the main thread.
+      var gfx = new CanvasGraphics(null);
 
-    if (a1 > codingLine[codingPos]) {
-      if (a1 > this.columns) {
-        warn('row is wrong length');
-        this.err = true;
-        a1 = this.columns;
+      var start = Date.now();
+
+      var dependency = [];
+      var operatorList = null;
+      try {
+        var page = pdfModel.getPage(pageNum);
+        // Pre compile the pdf page and fetch the fonts/images.
+        operatorList = page.getOperatorList(handler, dependency);
+      } catch (e) {
+        var minimumStackMessage =
+            'worker.js: while trying to getPage() and getOperatorList()';
+
+        // Turn the error into an obj that can be serialized
+        if (typeof e === 'string') {
+          e = {
+            message: e,
+            stack: minimumStackMessage
+          };
+        } else if (typeof e === 'object') {
+          e = {
+            message: e.message || e.toString(),
+            stack: e.stack || minimumStackMessage
+          };
+        } else {
+          e = {
+            message: 'Unknown exception type: ' + (typeof e),
+            stack: minimumStackMessage
+          };
+        }
+
+        handler.send('page_error', {
+          pageNum: pageNum,
+          error: e
+        });
+        return;
       }
-      if ((codingPos & 1) ^ blackPixels)
-        ++codingPos;
 
-      codingLine[codingPos] = a1;
-    } else if (a1 < codingLine[codingPos]) {
-      if (a1 < 0) {
-        warn('invalid code');
-        this.err = true;
-        a1 = 0;
+      console.log('page=%d - getOperatorList: time=%dms, len=%d', pageNum,
+                              Date.now() - start, operatorList.fnArray.length);
+
+      // Filter the dependecies for fonts.
+      var fonts = {};
+      for (var i = 0, ii = dependency.length; i < ii; i++) {
+        var dep = dependency[i];
+        if (dep.indexOf('font_') == 0) {
+          fonts[dep] = true;
+        }
       }
-      while (codingPos > 0 && a1 < codingLine[codingPos - 1])
-        --codingPos;
-      codingLine[codingPos] = a1;
-    }
 
-    this.codingPos = codingPos;
-  };
+      handler.send('page', {
+        pageNum: pageNum,
+        operatorList: operatorList,
+        depFonts: Object.keys(fonts)
+      });
+    }, this);
+  }
+};
 
-  constructor.prototype.lookChar = function ccittFaxStreamLookChar() {
-    if (this.buf != EOF)
-      return this.buf;
+var consoleTimer = {};
 
-    var refLine = this.refLine;
-    var codingLine = this.codingLine;
-    var columns = this.columns;
+var workerConsole = {
+  log: function log() {
+    var args = Array.prototype.slice.call(arguments);
+    postMessage({
+      action: 'console_log',
+      data: args
+    });
+  },
 
-    var refPos, blackPixels, bits;
+  error: function error() {
+    var args = Array.prototype.slice.call(arguments);
+    postMessage({
+      action: 'console_error',
+      data: args
+    });
+    throw 'pdf.js execution error';
+  },
 
-    if (this.outputBits == 0) {
-      if (this.eof)
-        return null;
+  time: function time(name) {
+    consoleTimer[name] = Date.now();
+  },
 
-      this.err = false;
+  timeEnd: function timeEnd(name) {
+    var time = consoleTimer[name];
+    if (time == null) {
+      error('Unkown timer name ' + name);
+    }
+    this.log('Timer:', name, Date.now() - time);
+  }
+};
 
-      var code1, code2, code3;
-      if (this.nextLine2D) {
-        for (var i = 0; codingLine[i] < columns; ++i)
-          refLine[i] = codingLine[i];
+// Worker thread?
+if (typeof window === 'undefined') {
+  globalScope.console = workerConsole;
+
+  var handler = new MessageHandler('worker_processor', this);
+  WorkerMessageHandler.setup(handler);
+}
+
+/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- /
+/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
+
+// - The JPEG specification can be found in the ITU CCITT Recommendation T.81
+//   (www.w3.org/Graphics/JPEG/itu-t81.pdf)
+// - The JFIF specification can be found in the JPEG File Interchange Format
+//   (www.w3.org/Graphics/JPEG/jfif3.pdf)
+// - The Adobe Application-Specific JPEG markers in the Supporting the DCT Filters
+//   in PostScript Level 2, Technical Note #5116
+//   (partners.adobe.com/public/developer/en/ps/sdk/5116.DCT_Filter.pdf)
+
+var JpegImage = (function jpegImage() {
+  "use strict";
+  var dctZigZag = new Int32Array([
+     0,
+     1,  8,
+    16,  9,  2,
+     3, 10, 17, 24,
+    32, 25, 18, 11, 4,
+     5, 12, 19, 26, 33, 40,
+    48, 41, 34, 27, 20, 13,  6,
+     7, 14, 21, 28, 35, 42, 49, 56,
+    57, 50, 43, 36, 29, 22, 15,
+    23, 30, 37, 44, 51, 58,
+    59, 52, 45, 38, 31,
+    39, 46, 53, 60,
+    61, 54, 47,
+    55, 62,
+    63
+  ]);
 
-        refLine[i++] = columns;
-        refLine[i] = columns;
-        codingLine[0] = 0;
-        this.codingPos = 0;
-        refPos = 0;
-        blackPixels = 0;
+  var dctCos1  =  4017   // cos(pi/16)
+  var dctSin1  =   799   // sin(pi/16)
+  var dctCos3  =  3406   // cos(3*pi/16)
+  var dctSin3  =  2276   // sin(3*pi/16)
+  var dctCos6  =  1567   // cos(6*pi/16)
+  var dctSin6  =  3784   // sin(6*pi/16)
+  var dctSqrt2 =  5793   // sqrt(2)
+  var dctSqrt1d2 = 2896  // sqrt(2) / 2
 
-        while (codingLine[this.codingPos] < columns) {
-          code1 = this.getTwoDimCode();
-          switch (code1) {
-            case twoDimPass:
-              this.addPixels(refLine[refPos + 1], blackPixels);
-              if (refLine[refPos + 1] < columns)
-                refPos += 2;
-              break;
-            case twoDimHoriz:
-              code1 = code2 = 0;
-              if (blackPixels) {
-                do {
-                  code1 += (code3 = this.getBlackCode());
-                } while (code3 >= 64);
-                do {
-                  code2 += (code3 = this.getWhiteCode());
-                } while (code3 >= 64);
-              } else {
-                do {
-                  code1 += (code3 = this.getWhiteCode());
-                } while (code3 >= 64);
-                do {
-                  code2 += (code3 = this.getBlackCode());
-                } while (code3 >= 64);
-              }
-              this.addPixels(codingLine[this.codingPos] +
-                             code1, blackPixels);
-              if (codingLine[this.codingPos] < columns) {
-                this.addPixels(codingLine[this.codingPos] + code2,
-                               blackPixels ^ 1);
-              }
-              while (refLine[refPos] <= codingLine[this.codingPos] &&
-                     refLine[refPos] < columns) {
-                refPos += 2;
-              }
-              break;
-            case twoDimVertR3:
-              this.addPixels(refLine[refPos] + 3, blackPixels);
-              blackPixels ^= 1;
-              if (codingLine[this.codingPos] < columns) {
-                ++refPos;
-                while (refLine[refPos] <= codingLine[this.codingPos] &&
-                       refLine[refPos] < columns)
-                  refPos += 2;
-              }
-              break;
-            case twoDimVertR2:
-              this.addPixels(refLine[refPos] + 2, blackPixels);
-              blackPixels ^= 1;
-              if (codingLine[this.codingPos] < columns) {
-                ++refPos;
-                while (refLine[refPos] <= codingLine[this.codingPos] &&
-                       refLine[refPos] < columns) {
-                  refPos += 2;
-                }
-              }
-              break;
-            case twoDimVertR1:
-              this.addPixels(refLine[refPos] + 1, blackPixels);
-              blackPixels ^= 1;
-              if (codingLine[this.codingPos] < columns) {
-                ++refPos;
-                while (refLine[refPos] <= codingLine[this.codingPos] &&
-                       refLine[refPos] < columns)
-                  refPos += 2;
-              }
-              break;
-            case twoDimVert0:
-              this.addPixels(refLine[refPos], blackPixels);
-              blackPixels ^= 1;
-              if (codingLine[this.codingPos] < columns) {
-                ++refPos;
-                while (refLine[refPos] <= codingLine[this.codingPos] &&
-                       refLine[refPos] < columns)
-                  refPos += 2;
-              }
-              break;
-            case twoDimVertL3:
-              this.addPixelsNeg(refLine[refPos] - 3, blackPixels);
-              blackPixels ^= 1;
-              if (codingLine[this.codingPos] < columns) {
-                if (refPos > 0)
-                  --refPos;
-                else
-                  ++refPos;
-                while (refLine[refPos] <= codingLine[this.codingPos] &&
-                       refLine[refPos] < columns)
-                  refPos += 2;
-              }
-              break;
-            case twoDimVertL2:
-              this.addPixelsNeg(refLine[refPos] - 2, blackPixels);
-              blackPixels ^= 1;
-              if (codingLine[this.codingPos] < columns) {
-                if (refPos > 0)
-                  --refPos;
-                else
-                  ++refPos;
-                while (refLine[refPos] <= codingLine[this.codingPos] &&
-                       refLine[refPos] < columns)
-                  refPos += 2;
-              }
-              break;
-            case twoDimVertL1:
-              this.addPixelsNeg(refLine[refPos] - 1, blackPixels);
-              blackPixels ^= 1;
-              if (codingLine[this.codingPos] < columns) {
-                if (refPos > 0)
-                  --refPos;
-                else
-                  ++refPos;
+  function constructor() {
+  }
 
-                while (refLine[refPos] <= codingLine[this.codingPos] &&
-                       refLine[refPos] < columns)
-                  refPos += 2;
-              }
-              break;
-            case EOF:
-              this.addPixels(columns, 0);
-              this.eof = true;
-              break;
-            default:
-              warn('bad 2d code');
-              this.addPixels(columns, 0);
-              this.err = true;
-          }
+  function buildHuffmanTable(codeLengths, values) {
+    var k = 0, code = [], i, j, length = 16;
+    while (length > 0 && !codeLengths[length - 1])
+      length--;
+    code.push({children: [], index: 0});
+    var p = code[0], q;
+    for (i = 0; i < length; i++) {
+      for (j = 0; j < codeLengths[i]; j++) {
+        p = code.pop();
+        p.children[p.index] = values[k];
+        while (p.index > 0) {
+          p = code.pop();
         }
-      } else {
-        codingLine[0] = 0;
-        this.codingPos = 0;
-        blackPixels = 0;
-        while (codingLine[this.codingPos] < columns) {
-          code1 = 0;
-          if (blackPixels) {
-            do {
-              code1 += (code3 = this.getBlackCode());
-            } while (code3 >= 64);
-          } else {
-            do {
-              code1 += (code3 = this.getWhiteCode());
-            } while (code3 >= 64);
-          }
-          this.addPixels(codingLine[this.codingPos] + code1, blackPixels);
-          blackPixels ^= 1;
+        p.index++;
+        code.push(p);
+        while (code.length <= i) {
+          code.push(q = {children: [], index: 0});
+          p.children[p.index] = q.children;
+          p = q;
         }
+        k++;
       }
+      if (i + 1 < length) {
+        // p here points to last code
+        code.push(q = {children: [], index: 0});
+        p.children[p.index] = q.children;
+        p = q;
+      }
+    }
+    return code[0].children;
+  }
 
-      if (this.byteAlign)
-        this.inputBits &= ~7;
-
-      var gotEOL = false;
+  function decodeScan(data, offset,
+                      frame, components, resetInterval,
+                      spectralStart, spectralEnd,
+                      successivePrev, successive) {
+    var precision = frame.precision;
+    var samplesPerLine = frame.samplesPerLine;
+    var scanLines = frame.scanLines;
+    var mcusPerLine = frame.mcusPerLine;
+    var progressive = frame.progressive;
+    var maxH = frame.maxH, maxV = frame.maxV;
 
-      if (!this.eoblock && this.row == this.rows - 1) {
-        this.eof = true;
-      } else {
-        code1 = this.lookBits(12);
-        while (code1 == 0) {
-          this.eatBits(1);
-          code1 = this.lookBits(12);
+    var startOffset = offset, bitsData = 0, bitsCount = 0;
+    function readBit() {
+      if (bitsCount > 0) {
+        bitsCount--;
+        return (bitsData >> bitsCount) & 1;
+      }
+      bitsData = data[offset++];
+      if (bitsData == 0xFF) {
+        var nextByte = data[offset++];
+        if (nextByte) {
+          throw "unexpected marker: " + ((bitsData << 8) | nextByte).toString(16);
         }
-        if (code1 == 1) {
-          this.eatBits(12);
-          gotEOL = true;
-        } else if (code1 == EOF) {
-          this.eof = true;
+        // unstuff 0
+      }
+      bitsCount = 7;
+      return bitsData >>> 7;
+    }
+    function decodeHuffman(tree) {
+      var node = tree, bit;
+      while ((bit = readBit()) !== null) {
+        node = node[bit];
+        if (typeof node === 'number')
+          return node;
+        if (typeof node !== 'object')
+          throw "invalid huffman sequence";
+      }
+      return null;
+    }
+    function receive(length) {
+      var n = 0;
+      while (length > 0) {
+        var bit = readBit();
+        if (bit === null) return;
+        n = (n << 1) | bit;
+        length--;
+      }
+      return n;
+    }
+    function receiveAndExtend(length) {
+      var n = receive(length);
+      if (n >= 1 << (length - 1))
+        return n;
+      return n + (-1 << length) + 1;
+    }
+    function decodeBaseline(component, zz) {
+      var t = decodeHuffman(component.huffmanTableDC);
+      var diff = t === 0 ? 0 : receiveAndExtend(t);
+      zz[0]= (component.pred += diff);
+      var k = 1;
+      while (k < 64) {
+        var rs = decodeHuffman(component.huffmanTableAC);
+        var s = rs & 15, r = rs >> 4;
+        if (s === 0) {
+          if (r < 15)
+            break;
+          k += 16;
+          continue;
         }
+        k += r;
+        var z = dctZigZag[k];
+        zz[z] = receiveAndExtend(s);
+        k++;
       }
-
-      if (!this.eof && this.encoding > 0) {
-        this.nextLine2D = !this.lookBits(1);
-        this.eatBits(1);
+    }
+    function decodeDCFirst(component, zz) {
+      var t = decodeHuffman(component.huffmanTableDC);
+      var diff = t === 0 ? 0 : (receiveAndExtend(t) << successive);
+      zz[0] = (component.pred += diff);
+    }
+    function decodeDCSuccessive(component, zz) {
+      zz[0] |= readBit() << successive;
+    }
+    var eobrun = 0;
+    function decodeACFirst(component, zz) {
+      if (eobrun > 0) {
+        eobrun--;
+        return;
       }
-
-      if (this.eoblock && gotEOL) {
-        code1 = this.lookBits(12);
-        if (code1 == 1) {
-          this.eatBits(12);
-          if (this.encoding > 0) {
-            this.lookBits(1);
-            this.eatBits(1);
+      var k = spectralStart, e = spectralEnd;
+      while (k <= e) {
+        var rs = decodeHuffman(component.huffmanTableAC);
+        var s = rs & 15, r = rs >> 4;
+        if (s === 0) {
+          if (r < 15) {
+            eobrun = receive(r) + (1 << r) - 1;
+            break;
           }
-          if (this.encoding >= 0) {
-            for (var i = 0; i < 4; ++i) {
-              code1 = this.lookBits(12);
-              if (code1 != 1)
-                warn('bad rtc code: ' + code1);
-              this.eatBits(12);
-              if (this.encoding > 0) {
-                this.lookBits(1);
-                this.eatBits(1);
-              }
+          k += 16;
+          continue;
+        }
+        k += r;
+        var z = dctZigZag[k];
+        zz[z] = receiveAndExtend(s) * (1 << successive);
+        k++;
+      }
+    }
+    var successiveACState = 0, successiveACNextValue;
+    function decodeACSuccessive(component, zz) {
+      var k = spectralStart, e = spectralEnd, r = 0;
+      while (k <= e) {
+        var z = dctZigZag[k];
+        switch (successiveACState) {
+        case 0: // initial state
+          var rs = decodeHuffman(component.huffmanTableAC);
+          var s = rs & 15, r = rs >> 4;
+          if (s === 0) {
+            if (r < 15) {
+              eobrun = receive(r) + (1 << r);
+              successiveACState = 4;
+            } else {
+              r = 16;
+              successiveACState = 1;
             }
+          } else {
+            if (s !== 1)
+              throw "invalid ACn encoding";
+            successiveACNextValue = receiveAndExtend(s);
+            successiveACState = r ? 2 : 3;
           }
-          this.eof = true;
-        }
-      } else if (this.err && this.eoline) {
-        while (true) {
-          code1 = this.lookBits(13);
-          if (code1 == EOF) {
-            this.eof = true;
-            return null;
+          continue;
+        case 1: // skipping r zero items
+        case 2:
+          if (zz[z])
+            zz[z] += (readBit() << successive);
+          else {
+            r--;
+            if (r === 0)
+              successiveACState = successiveACState == 2 ? 3 : 0;
           }
-          if ((code1 >> 1) == 1) {
-            break;
+          break;
+        case 3: // set value for a zero item
+          if (zz[z])
+            zz[z] += (readBit() << successive);
+          else {
+            zz[z] = successiveACNextValue << successive;
+            successiveACState = 0;
           }
-          this.eatBits(1);
-        }
-        this.eatBits(12);
-        if (this.encoding > 0) {
-          this.eatBits(1);
-          this.nextLine2D = !(code1 & 1);
+          break;
+        case 4: // eob
+          if (zz[z])
+            zz[z] += (readBit() << successive);
+          break;
         }
+        k++;
+      }
+      if (successiveACState === 4) {
+        eobrun--;
+        if (eobrun === 0)
+          successiveACState = 0;
       }
+    }
+    function decodeMcu(component, decode, mcu, row, col) {
+      var mcuRow = (mcu / mcusPerLine) | 0;
+      var mcuCol = mcu % mcusPerLine;
+      var blockRow = mcuRow * component.v + row;
+      var blockCol = mcuCol * component.h + col;
+      decode(component, component.blocks[blockRow][blockCol]);
+    }
+    function decodeBlock(component, decode, mcu) {
+      var blockRow = (mcu / component.blocksPerLine) | 0;
+      var blockCol = mcu % component.blocksPerLine;
+      decode(component, component.blocks[blockRow][blockCol]);
+    }
 
-      if (codingLine[0] > 0)
-        this.outputBits = codingLine[this.codingPos = 0];
+    var componentsLength = components.length;
+    var component, i, j, k, n;
+    var decodeFn;
+    if (progressive) {
+      if (spectralStart === 0)
+        decodeFn = successivePrev === 0 ? decodeDCFirst : decodeDCSuccessive;
       else
-        this.outputBits = codingLine[this.codingPos = 1];
-      this.row++;
+        decodeFn = successivePrev === 0 ? decodeACFirst : decodeACSuccessive;
+    } else {
+      decodeFn = decodeBaseline;
     }
 
-    if (this.outputBits >= 8) {
-      this.buf = (this.codingPos & 1) ? 0 : 0xFF;
-      this.outputBits -= 8;
-      if (this.outputBits == 0 && codingLine[this.codingPos] < columns) {
-        this.codingPos++;
-        this.outputBits = (codingLine[this.codingPos] -
-                           codingLine[this.codingPos - 1]);
-      }
+    var mcu = 0, marker;
+    var mcuExpected;
+    if (componentsLength == 1) {
+      mcuExpected = components[0].blocksPerLine * components[0].blocksPerColumn;
     } else {
-      var bits = 8;
-      this.buf = 0;
-      do {
-        if (this.outputBits > bits) {
-          this.buf <<= bits;
-          if (!(this.codingPos & 1)) {
-            this.buf |= 0xFF >> (8 - bits);
-          }
-          this.outputBits -= bits;
-          bits = 0;
-        } else {
-          this.buf <<= this.outputBits;
-          if (!(this.codingPos & 1)) {
-            this.buf |= 0xFF >> (8 - this.outputBits);
-          }
-          bits -= this.outputBits;
-          this.outputBits = 0;
-          if (codingLine[this.codingPos] < columns) {
-            this.codingPos++;
-            this.outputBits = (codingLine[this.codingPos] -
-                               codingLine[this.codingPos - 1]);
-          } else if (bits > 0) {
-            this.buf <<= bits;
-            bits = 0;
-          }
-        }
-      } while (bits);
-    }
-    if (this.black) {
-      this.buf ^= 0xFF;
+      mcuExpected = mcusPerLine * frame.mcusPerColumn;
     }
-    return this.buf;
-  };
+    if (!resetInterval) resetInterval = mcuExpected;
 
-  // This functions returns the code found from the table.
-  // The start and end parameters set the boundaries for searching the table.
-  // The limit parameter is optional. Function returns an array with three
-  // values. The first array element indicates whether a valid code is being
-  // returned. The second array element is the actual code. The third array
-  // element indicates whether EOF was reached.
-  var findTableCode = function ccittFaxStreamFindTableCode(start, end, table,
-                                                           limit) {
-    var limitValue = limit || 0;
+    var h, v;
+    while (mcu < mcuExpected) {
+      // reset interval stuff
+      for (i = 0; i < componentsLength; i++)
+        components[i].pred = 0;
+      eobrun = 0;
 
-    for (var i = start; i <= end; ++i) {
-      var code = this.lookBits(i);
-      if (code == EOF)
-        return [true, 1, false];
-      if (i < end)
-        code <<= end - i;
-      if (!limitValue || code >= limitValue) {
-        var p = table[code - limitValue];
-        if (p[0] == i) {
-          this.eatBits(i);
-          return [true, p[1], true];
+      if (componentsLength == 1) {
+        component = components[0];
+        for (n = 0; n < resetInterval; n++) {
+          decodeBlock(component, decodeFn, mcu);
+          mcu++;
+        }
+      } else {
+        for (n = 0; n < resetInterval; n++) {
+          for (i = 0; i < componentsLength; i++) {
+            component = components[i];
+            h = component.h;
+            v = component.v;
+            for (j = 0; j < v; j++) {
+              for (k = 0; k < h; k++) {
+                decodeMcu(component, decodeFn, mcu, j, k);
+              }
+            }
+          }
+          mcu++;
         }
       }
-    }
-    return [false, 0, false];
-  };
 
-  constructor.prototype.getTwoDimCode = function ccittFaxStreamGetTwoDimCode() {
-    var code = 0;
-    var p;
-    if (this.eoblock) {
-      code = this.lookBits(7);
-      p = twoDimTable[code];
-      if (p[0] > 0) {
-        this.eatBits(p[0]);
-        return p[1];
+      // find marker
+      bitsCount = 0;
+      marker = (data[offset] << 8) | data[offset + 1];
+      if (marker <= 0xFF00) {
+        throw "marker was not found";
+      }
+
+      if (marker >= 0xFFD0 && marker <= 0xFFD7) { // RSTx
+        offset += 2;
       }
-    } else {
-      var result = findTableCode(1, 7, twoDimTable);
-      if (result[0] && result[2])
-        return result[1];
+      else
+        break;
     }
-    warn('Bad two dim code');
-    return EOF;
-  };
 
-  constructor.prototype.getWhiteCode = function ccittFaxStreamGetWhiteCode() {
-    var code = 0;
-    var p;
-    var n;
-    if (this.eoblock) {
-      code = this.lookBits(12);
-      if (code == EOF)
-        return 1;
+    return offset - startOffset;
+  }
 
-      if ((code >> 5) == 0)
-        p = whiteTable1[code];
-      else
-        p = whiteTable2[code >> 3];
+  function buildComponentData(frame, component) {
+    var lines = [];
+    var blocksPerLine = component.blocksPerLine;
+    var blocksPerColumn = component.blocksPerColumn;
+    var samplesPerLine = blocksPerLine << 3;
+    var R = new Int32Array(64), r = new Uint8Array(64);
 
-      if (p[0] > 0) {
-        this.eatBits(p[0]);
-        return p[1];
-      }
-    } else {
-      var result = findTableCode(1, 9, whiteTable2);
-      if (result[0])
-        return result[1];
+    // A port of poppler's IDCT method which in turn is taken from:
+    //   Christoph Loeffler, Adriaan Ligtenberg, George S. Moschytz,
+    //   "Practical Fast 1-D DCT Algorithms with 11 Multiplications",
+    //   IEEE Intl. Conf. on Acoustics, Speech & Signal Processing, 1989,
+    //   988-991.
+    function quantizeAndInverse(zz, dataOut, dataIn) {
+      var qt = component.quantizationTable;
+      var v0, v1, v2, v3, v4, v5, v6, v7, t;
+      var p = dataIn;
+      var i;
 
-      result = findTableCode(11, 12, whiteTable1);
-      if (result[0])
-        return result[1];
-    }
-    warn('bad white code');
-    this.eatBits(1);
-    return 1;
-  };
+      // dequant
+      for (i = 0; i < 64; i++)
+        p[i] = zz[i] * qt[i];
 
-  constructor.prototype.getBlackCode = function ccittFaxStreamGetBlackCode() {
-    var code, p;
-    if (this.eoblock) {
-      code = this.lookBits(13);
-      if (code == EOF)
-        return 1;
-      if ((code >> 7) == 0)
-        p = blackTable1[code];
-      else if ((code >> 9) == 0 && (code >> 7) != 0)
-        p = blackTable2[(code >> 1) - 64];
-      else
-        p = blackTable3[code >> 7];
+      // inverse DCT on rows
+      for (i = 0; i < 8; ++i) {
+        var row = 8 * i;
 
-      if (p[0] > 0) {
-        this.eatBits(p[0]);
-        return p[1];
-      }
-    } else {
-      var result = findTableCode(2, 6, blackTable3);
-      if (result[0])
-        return result[1];
+        // check for all-zero AC coefficients
+        if (p[1 + row] == 0 && p[2 + row] == 0 && p[3 + row] == 0 &&
+            p[4 + row] == 0 && p[5 + row] == 0 && p[6 + row] == 0 &&
+            p[7 + row] == 0) {
+          t = (dctSqrt2 * p[0 + row] + 512) >> 10;
+          p[0 + row] = t;
+          p[1 + row] = t;
+          p[2 + row] = t;
+          p[3 + row] = t;
+          p[4 + row] = t;
+          p[5 + row] = t;
+          p[6 + row] = t;
+          p[7 + row] = t;
+          continue;
+        }
 
-      result = findTableCode(7, 12, blackTable2, 64);
-      if (result[0])
-        return result[1];
+        // stage 4
+        v0 = (dctSqrt2 * p[0 + row] + 128) >> 8;
+        v1 = (dctSqrt2 * p[4 + row] + 128) >> 8;
+        v2 = p[2 + row];
+        v3 = p[6 + row];
+        v4 = (dctSqrt1d2 * (p[1 + row] - p[7 + row]) + 128) >> 8;
+        v7 = (dctSqrt1d2 * (p[1 + row] + p[7 + row]) + 128) >> 8;
+        v5 = p[3 + row] << 4;
+        v6 = p[5 + row] << 4;
 
-      result = findTableCode(10, 13, blackTable1);
-      if (result[0])
-        return result[1];
-    }
-    warn('bad black code');
-    this.eatBits(1);
-    return 1;
-  };
+        // stage 3
+        t = (v0 - v1+ 1) >> 1;
+        v0 = (v0 + v1 + 1) >> 1;
+        v1 = t;
+        t = (v2 * dctSin6 + v3 * dctCos6 + 128) >> 8;
+        v2 = (v2 * dctCos6 - v3 * dctSin6 + 128) >> 8;
+        v3 = t;
+        t = (v4 - v6 + 1) >> 1;
+        v4 = (v4 + v6 + 1) >> 1;
+        v6 = t;
+        t = (v7 + v5 + 1) >> 1;
+        v5 = (v7 - v5 + 1) >> 1;
+        v7 = t;
 
-  constructor.prototype.lookBits = function ccittFaxStreamLookBits(n) {
-    var c;
-    while (this.inputBits < n) {
-      if ((c = this.str.getByte()) == null) {
-        if (this.inputBits == 0)
-          return EOF;
-        return ((this.inputBuf << (n - this.inputBits)) &
-                (0xFFFF >> (16 - n)));
+        // stage 2
+        t = (v0 - v3 + 1) >> 1;
+        v0 = (v0 + v3 + 1) >> 1;
+        v3 = t;
+        t = (v1 - v2 + 1) >> 1;
+        v1 = (v1 + v2 + 1) >> 1;
+        v2 = t;
+        t = (v4 * dctSin3 + v7 * dctCos3 + 2048) >> 12;
+        v4 = (v4 * dctCos3 - v7 * dctSin3 + 2048) >> 12;
+        v7 = t;
+        t = (v5 * dctSin1 + v6 * dctCos1 + 2048) >> 12;
+        v5 = (v5 * dctCos1 - v6 * dctSin1 + 2048) >> 12;
+        v6 = t;
+
+        // stage 1
+        p[0 + row] = v0 + v7;
+        p[7 + row] = v0 - v7;
+        p[1 + row] = v1 + v6;
+        p[6 + row] = v1 - v6;
+        p[2 + row] = v2 + v5;
+        p[5 + row] = v2 - v5;
+        p[3 + row] = v3 + v4;
+        p[4 + row] = v3 - v4;
       }
-      this.inputBuf = (this.inputBuf << 8) + c;
-      this.inputBits += 8;
-    }
-    return (this.inputBuf >> (this.inputBits - n)) & (0xFFFF >> (16 - n));
-  };
 
-  constructor.prototype.eatBits = function ccittFaxStreamEatBits(n) {
-    if ((this.inputBits -= n) < 0)
-      this.inputBits = 0;
-  };
+      // inverse DCT on columns
+      for (i = 0; i < 8; ++i) {
+        var col = i;
 
-  return constructor;
-})();
+        // check for all-zero AC coefficients
+        if (p[1*8 + col] == 0 && p[2*8 + col] == 0 && p[3*8 + col] == 0 &&
+            p[4*8 + col] == 0 && p[5*8 + col] == 0 && p[6*8 + col] == 0 &&
+            p[7*8 + col] == 0) {
+          t = (dctSqrt2 * dataIn[i+0] + 8192) >> 14;
+          p[0*8 + col] = t;
+          p[1*8 + col] = t;
+          p[2*8 + col] = t;
+          p[3*8 + col] = t;
+          p[4*8 + col] = t;
+          p[5*8 + col] = t;
+          p[6*8 + col] = t;
+          p[7*8 + col] = t;
+          continue;
+        }
 
-var LZWStream = (function lzwStream() {
-  function constructor(str, earlyChange) {
-    this.str = str;
-    this.dict = str.dict;
-    this.cachedData = 0;
-    this.bitsCached = 0;
+        // stage 4
+        v0 = (dctSqrt2 * p[0*8 + col] + 2048) >> 12;
+        v1 = (dctSqrt2 * p[4*8 + col] + 2048) >> 12;
+        v2 = p[2*8 + col];
+        v3 = p[6*8 + col];
+        v4 = (dctSqrt1d2 * (p[1*8 + col] - p[7*8 + col]) + 2048) >> 12;
+        v7 = (dctSqrt1d2 * (p[1*8 + col] + p[7*8 + col]) + 2048) >> 12;
+        v5 = p[3*8 + col];
+        v6 = p[5*8 + col];
 
-    var maxLzwDictionarySize = 4096;
-    var lzwState = {
-      earlyChange: earlyChange,
-      codeLength: 9,
-      nextCode: 258,
-      dictionaryValues: new Uint8Array(maxLzwDictionarySize),
-      dictionaryLengths: new Uint16Array(maxLzwDictionarySize),
-      dictionaryPrevCodes: new Uint16Array(maxLzwDictionarySize),
-      currentSequence: new Uint8Array(maxLzwDictionarySize),
-      currentSequenceLength: 0
-    };
-    for (var i = 0; i < 256; ++i) {
-      lzwState.dictionaryValues[i] = i;
-      lzwState.dictionaryLengths[i] = 1;
-    }
-    this.lzwState = lzwState;
+        // stage 3
+        t = (v0 - v1 + 1) >> 1;
+        v0 = (v0 + v1 + 1) >> 1;
+        v1 = t;
+        t = (v2 * dctSin6 + v3 * dctCos6 + 2048) >> 12;
+        v2 = (v2 * dctCos6 - v3 * dctSin6 + 2048) >> 12;
+        v3 = t;
+        t = (v4 - v6 + 1) >> 1;
+        v4 = (v4 + v6 + 1) >> 1;
+        v6 = t;
+        t = (v7 + v5 + 1) >> 1;
+        v5 = (v7 - v5 + 1) >> 1;
+        v7 = t;
 
-    DecodeStream.call(this);
-  }
+        // stage 2
+        t = (v0 - v3 + 1) >> 1;
+        v0 = (v0 + v3 + 1) >> 1;
+        v3 = t;
+        t = (v1 - v2 + 1) >> 1;
+        v1 = (v1 + v2 + 1) >> 1;
+        v2 = t;
+        t = (v4 * dctSin3 + v7 * dctCos3 + 2048) >> 12;
+        v4 = (v4 * dctCos3 - v7 * dctSin3 + 2048) >> 12;
+        v7 = t;
+        t = (v5 * dctSin1 + v6 * dctCos1 + 2048) >> 12;
+        v5 = (v5 * dctCos1 - v6 * dctSin1 + 2048) >> 12;
+        v6 = t;
 
-  constructor.prototype = Object.create(DecodeStream.prototype);
+        // stage 1
+        p[0*8 + col] = v0 + v7;
+        p[7*8 + col] = v0 - v7;
+        p[1*8 + col] = v1 + v6;
+        p[6*8 + col] = v1 - v6;
+        p[2*8 + col] = v2 + v5;
+        p[5*8 + col] = v2 - v5;
+        p[3*8 + col] = v3 + v4;
+        p[4*8 + col] = v3 - v4;
+      }
 
-  constructor.prototype.readBits = function lzwStreamReadBits(n) {
-    var bitsCached = this.bitsCached;
-    var cachedData = this.cachedData;
-    while (bitsCached < n) {
-      var c = this.str.getByte();
-      if (c == null) {
-        this.eof = true;
-        return null;
+      // convert to 8-bit integers
+      for (i = 0; i < 64; ++i) {
+        var sample = 128 + ((p[i] + 8) >> 4);
+        dataOut[i] = sample < 0 ? 0 : sample > 0xFF ? 0xFF : sample;
       }
-      cachedData = (cachedData << 8) | c;
-      bitsCached += 8;
     }
-    this.bitsCached = (bitsCached -= n);
-    this.cachedData = cachedData;
-    this.lastCode = null;
-    return (cachedData >>> bitsCached) & ((1 << n) - 1);
-  };
-
-  constructor.prototype.readBlock = function lzwStreamReadBlock() {
-    var blockSize = 512;
-    var estimatedDecodedSize = blockSize * 2, decodedSizeDelta = blockSize;
-    var i, j, q;
-
-    var lzwState = this.lzwState;
-    if (!lzwState)
-      return; // eof was found
-
-    var earlyChange = lzwState.earlyChange;
-    var nextCode = lzwState.nextCode;
-    var dictionaryValues = lzwState.dictionaryValues;
-    var dictionaryLengths = lzwState.dictionaryLengths;
-    var dictionaryPrevCodes = lzwState.dictionaryPrevCodes;
-    var codeLength = lzwState.codeLength;
-    var prevCode = lzwState.prevCode;
-    var currentSequence = lzwState.currentSequence;
-    var currentSequenceLength = lzwState.currentSequenceLength;
 
-    var decodedLength = 0;
-    var currentBufferLength = this.bufferLength;
-    var buffer = this.ensureBuffer(this.bufferLength + estimatedDecodedSize);
+    var i, j;
+    for (var blockRow = 0; blockRow < blocksPerColumn; blockRow++) {
+      var scanLine = blockRow << 3;
+      for (i = 0; i < 8; i++)
+        lines.push(new Uint8Array(samplesPerLine));
+      for (var blockCol = 0; blockCol < blocksPerLine; blockCol++) {
+        quantizeAndInverse(component.blocks[blockRow][blockCol], r, R);
 
-    for (i = 0; i < blockSize; i++) {
-      var code = this.readBits(codeLength);
-      var hasPrev = currentSequenceLength > 0;
-      if (code < 256) {
-        currentSequence[0] = code;
-        currentSequenceLength = 1;
-      } else if (code >= 258) {
-        if (code < nextCode) {
-          currentSequenceLength = dictionaryLengths[code];
-          for (j = currentSequenceLength - 1, q = code; j >= 0; j--) {
-            currentSequence[j] = dictionaryValues[q];
-            q = dictionaryPrevCodes[q];
-          }
-        } else {
-          currentSequence[currentSequenceLength++] = currentSequence[0];
+        var offset = 0, sample = blockCol << 3;
+        for (j = 0; j < 8; j++) {
+          var line = lines[scanLine + j];
+          for (i = 0; i < 8; i++)
+            line[sample + i] = r[offset++];
         }
-      } else if (code == 256) {
-        codeLength = 9;
-        nextCode = 258;
-        currentSequenceLength = 0;
-        continue;
-      } else {
-        this.eof = true;
-        delete this.lzwState;
-        break;
       }
+    }
+    return lines;
+  }
 
-      if (hasPrev) {
-        dictionaryPrevCodes[nextCode] = prevCode;
-        dictionaryLengths[nextCode] = dictionaryLengths[prevCode] + 1;
-        dictionaryValues[nextCode] = currentSequence[0];
-        nextCode++;
-        codeLength = (nextCode + earlyChange) & (nextCode + earlyChange - 1) ?
-          codeLength : Math.min(Math.log(nextCode + earlyChange) /
-          0.6931471805599453 + 1, 12) | 0;
+  constructor.prototype = {
+    load: function load(path) {
+      var xhr = new XMLHttpRequest();
+      xhr.open("GET", path, true);
+      xhr.responseType = "arraybuffer";
+      xhr.onload = (function() {
+        // TODO catch parse error
+        var data = new Uint8Array(xhr.response || xhr.mozResponseArrayBuffer);
+        this.parse(data);
+        if (this.onload)
+          this.onload();
+      }).bind(this);
+      xhr.send(null);
+    },
+    parse: function parse(data) {
+      var offset = 0, length = data.length;
+      function readUint16() {
+        var value = (data[offset] << 8) | data[offset + 1];
+        offset += 2;
+        return value;
       }
-      prevCode = code;
-
-      decodedLength += currentSequenceLength;
-      if (estimatedDecodedSize < decodedLength) {
-        do {
-          estimatedDecodedSize += decodedSizeDelta;
-        } while (estimatedDecodedSize < decodedLength);
-        buffer = this.ensureBuffer(this.bufferLength + estimatedDecodedSize);
+      function readDataBlock() {
+        var length = readUint16();
+        var array = data.subarray(offset, offset + length - 2);
+        offset += array.length;
+        return array;
+      }
+      function prepareComponents(frame) {
+        var maxH = 0, maxV = 0;
+        var component, componentId;
+        for (componentId in frame.components) {
+          if (frame.components.hasOwnProperty(componentId)) {
+            component = frame.components[componentId];
+            if (maxH < component.h) maxH = component.h;
+            if (maxV < component.v) maxV = component.v;
+          }
+        }
+        var mcusPerLine = Math.ceil(frame.samplesPerLine / 8 / maxH);
+        var mcusPerColumn = Math.ceil(frame.scanLines / 8 / maxV);
+        for (componentId in frame.components) {
+          if (frame.components.hasOwnProperty(componentId)) {
+            component = frame.components[componentId];
+            var blocksPerLine = Math.ceil(Math.ceil(frame.samplesPerLine / 8) * component.h / maxH);
+            var blocksPerColumn = Math.ceil(Math.ceil(frame.scanLines  / 8) * component.v / maxV);
+            var blocksPerLineForMcu = mcusPerLine * component.h;
+            var blocksPerColumnForMcu = mcusPerColumn * component.v;
+            var blocks = [];
+            for (var i = 0; i < blocksPerColumnForMcu; i++) {
+              var row = [];
+              for (var j = 0; j < blocksPerLineForMcu; j++)
+                row.push(new Int32Array(64));
+              blocks.push(row);
+            }
+            component.blocksPerLine = blocksPerLine;
+            component.blocksPerColumn = blocksPerColumn;
+            component.blocks = blocks;
+          }
+        }
+        frame.maxH = maxH;
+        frame.maxV = maxV;
+        frame.mcusPerLine = mcusPerLine;
+        frame.mcusPerColumn = mcusPerColumn;
+      }
+      var jfif = null;
+      var adobe = null;
+      var pixels = null;
+      var frame, resetInterval;
+      var quantizationTables = [], frames = [];
+      var huffmanTablesAC = [], huffmanTablesDC = [];
+      var fileMarker = readUint16();
+      if (fileMarker != 0xFFD8) { // SOI (Start of Image)
+        throw "SOI not found";
       }
-      for (j = 0; j < currentSequenceLength; j++)
-        buffer[currentBufferLength++] = currentSequence[j];
-    }
-    lzwState.nextCode = nextCode;
-    lzwState.codeLength = codeLength;
-    lzwState.prevCode = prevCode;
-    lzwState.currentSequenceLength = currentSequenceLength;
-
-    this.bufferLength = currentBufferLength;
-  };
 
-  return constructor;
-})();
+      fileMarker = readUint16();
+      while (fileMarker != 0xFFD9) { // EOI (End of image)
+        var i, j, l;
+        switch(fileMarker) {
+          case 0xFFE0: // APP0 (Application Specific)
+          case 0xFFE1: // APP1
+          case 0xFFE2: // APP2
+          case 0xFFE3: // APP3
+          case 0xFFE4: // APP4
+          case 0xFFE5: // APP5
+          case 0xFFE6: // APP6
+          case 0xFFE7: // APP7
+          case 0xFFE8: // APP8
+          case 0xFFE9: // APP9
+          case 0xFFEA: // APP10
+          case 0xFFEB: // APP11
+          case 0xFFEC: // APP12
+          case 0xFFED: // APP13
+          case 0xFFEE: // APP14
+          case 0xFFEF: // APP15
+          case 0xFFFE: // COM (Comment)
+            var appData = readDataBlock();
 
-/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
+            if (fileMarker === 0xFFE0) {
+              if (appData[0] === 0x4A && appData[1] === 0x46 && appData[2] === 0x49 &&
+                appData[3] === 0x46 && appData[4] === 0) { // 'JFIF\x00'
+                jfif = {
+                  version: { major: appData[5], minor: appData[6] },
+                  densityUnits: appData[7],
+                  xDensity: (appData[8] << 8) | appData[9],
+                  yDensity: (appData[10] << 8) | appData[11],
+                  thumbWidth: appData[12],
+                  thumbHeight: appData[13],
+                  thumbData: appData.subarray(14, 14 + 3 * appData[12] * appData[13])
+                };
+              }
+            }
+            // TODO APP1 - Exif
+            if (fileMarker === 0xFFEE) {
+              if (appData[0] === 0x41 && appData[1] === 0x64 && appData[2] === 0x6F &&
+                appData[3] === 0x62 && appData[4] === 0x65 && appData[5] === 0) { // 'Adobe\x00'
+                adobe = {
+                  version: appData[6],
+                  flags0: (appData[7] << 8) | appData[8],
+                  flags1: (appData[9] << 8) | appData[10],
+                  transformCode: appData[11]
+                };
+              }
+            }
+            break;
 
-'use strict';
+          case 0xFFDB: // DQT (Define Quantization Tables)
+            var quantizationTableCount = Math.floor((readUint16() - 2) / 65);
+            for (i = 0; i < quantizationTableCount; i++) {
+              var quantizationTableSpec = data[offset++];
+              var tableData = new Int32Array(64);
+              if ((quantizationTableSpec >> 4) === 0) { // 8 bit values
+                for (j = 0; j < 64; j++) {
+                  var z = dctZigZag[j];
+                  tableData[z] = data[offset++];
+                }
+              } else if ((quantizationTableSpec >> 4) === 1) { //16 bit
+                  tableData[j] = readUint16();
+              } else
+                throw "DQT: invalid table spec";
+              quantizationTables[quantizationTableSpec & 15] = tableData;
+            }
+            break;
 
-function MessageHandler(name, comObj) {
-  this.name = name;
-  this.comObj = comObj;
-  var ah = this.actionHandler = {};
+          case 0xFFC0: // SOF0 (Start of Frame, Baseline DCT)
+          case 0xFFC2: // SOF2 (Start of Frame, Progressive DCT)
+            readUint16(); // skip data length
+            frame = {};
+            frame.progressive = (fileMarker === 0xFFC2);
+            frame.precision = data[offset++];
+            frame.scanLines = readUint16();
+            frame.samplesPerLine = readUint16();
+            frame.components = [];
+            var componentsCount = data[offset++], componentId;
+            var maxH = 0, maxV = 0;
+            for (i = 0; i < componentsCount; i++) {
+              componentId = data[offset];
+              var h = data[offset + 1] >> 4;
+              var v = data[offset + 1] & 15;
+              var qId = data[offset + 2];
+              frame.components[componentId] = {
+                h: h,
+                v: v,
+                quantizationTable: quantizationTables[qId]
+              };
+              offset += 3;
+            }
+            prepareComponents(frame);
+            frames.push(frame);
+            break;
 
-  ah['console_log'] = [function ahConsoleLog(data) {
-      console.log.apply(console, data);
-  }];
-  ah['console_error'] = [function ahConsoleError(data) {
-      console.error.apply(console, data);
-  }];
+          case 0xFFC4: // DHT (Define Huffman Tables)
+            var huffmanLength = readUint16();
+            for (i = 2; i < huffmanLength;) {
+              var huffmanTableSpec = data[offset++];
+              var codeLengths = new Uint8Array(16);
+              var codeLengthSum = 0;
+              for (j = 0; j < 16; j++, offset++)
+                codeLengthSum += (codeLengths[j] = data[offset]);
+              var huffmanValues = new Uint8Array(codeLengthSum);
+              for (j = 0; j < codeLengthSum; j++, offset++)
+                huffmanValues[j] = data[offset];
+              i += 17 + codeLengthSum;
 
-  comObj.onmessage = function messageHandlerComObjOnMessage(event) {
-    var data = event.data;
-    if (data.action in ah) {
-      var action = ah[data.action];
-      action[0].call(action[1], data.data);
-    } else {
-      throw 'Unkown action from worker: ' + data.action;
-    }
-  };
-}
+              ((huffmanTableSpec >> 4) === 0 ? 
+                huffmanTablesDC : huffmanTablesAC)[huffmanTableSpec & 15] =
+                buildHuffmanTable(codeLengths, huffmanValues);
+            }
+            break;
 
-MessageHandler.prototype = {
-  on: function messageHandlerOn(actionName, handler, scope) {
-    var ah = this.actionHandler;
-    if (ah[actionName]) {
-      throw 'There is already an actionName called "' + actionName + '"';
-    }
-    ah[actionName] = [handler, scope];
-  },
+          case 0xFFDD: // DRI (Define Restart Interval)
+            readUint16(); // skip data length
+            resetInterval = readUint16();
+            break;
 
-  send: function messageHandlerSend(actionName, data) {
-    this.comObj.postMessage({
-      action: actionName,
-      data: data
-    });
-  }
-};
+          case 0xFFDA: // SOS (Start of Scan)
+            var scanLength = readUint16();
+            var selectorsCount = data[offset++];
+            var components = [], component;
+            for (i = 0; i < selectorsCount; i++) {
+              component = frame.components[data[offset++]];
+              var tableSpec = data[offset++];
+              component.huffmanTableDC = huffmanTablesDC[tableSpec >> 4];
+              component.huffmanTableAC = huffmanTablesAC[tableSpec & 15];
+              components.push(component);
+            }
+            var spectralStart = data[offset++];
+            var spectralEnd = data[offset++];
+            var successiveApproximation = data[offset++];
+            var processed = decodeScan(data, offset,
+              frame, components, resetInterval,
+              spectralStart, spectralEnd,
+              successiveApproximation >> 4, successiveApproximation & 15);
+            offset += processed;
+            break;
+          default:
+            throw "unknown JPEG marker " + fileMarker.toString(16);
+        }
+        fileMarker = readUint16();
+      }
+      if (frames.length != 1)
+        throw "only single frame JPEGs supported";
 
-var WorkerMessageHandler = {
-  setup: function wphSetup(handler) {
-    var pdfDoc = null;
+      this.width = frame.samplesPerLine;
+      this.height = frame.scanLines;
+      this.jfif = jfif;
+      this.adobe = adobe;
+      this.components = [];
+      for (var id in frame.components) {
+        if (frame.components.hasOwnProperty(id)) {
+          this.components.push({
+            lines: buildComponentData(frame, frame.components[id]),
+            scaleX: frame.components[id].h / frame.maxH,
+            scaleY: frame.components[id].v / frame.maxV
+          });
+        }
+      }
+    },
+    getData: function getData(width, height) {
+      function clampTo8bit(a) {
+        return a < 0 ? 0 : a > 255 ? 255 : a;
+      }
+      var scaleX = this.width / width, scaleY = this.height / height;
 
-    handler.on('test', function wphSetupTest(data) {
-      handler.send('test', data instanceof Uint8Array);
-    });
+      var component1, component2, component3, component4;
+      var component1Line, component2Line, component3Line, component4Line;
+      var x, y;
+      var offset = 0;
+      var Y, Cb, Cr, K, C, M, Ye, R, G, B;
+      var colorTransform;
+      var dataLength = width * height * this.components.length;
+      var data = new Uint8Array(dataLength);
+      switch (this.components.length) {
+        case 1:
+          component1 = this.components[0];
+          for (y = 0; y < height; y++) {
+            component1Line = component1.lines[0 | (y * component1.scaleY * scaleY)];
+            for (x = 0; x < width; x++) {
+              Y = component1Line[0 | (x * component1.scaleX * scaleX)];
 
-    handler.on('workerSrc', function wphSetupWorkerSrc(data) {
-      // In development, the `workerSrc` message is handled in the
-      // `worker_loader.js` file. In production the workerProcessHandler is
-      // called for this. This servers as a dummy to prevent calling an
-      // undefined action `workerSrc`.
-    });
+              data[offset++] = Y;
+            }
+          }
+          break;
+        case 3:
+          // The default transform for three components is true
+          colorTransform = true;
+          // The adobe transform marker overrides any previous setting
+          if (this.adobe && this.adobe.transformCode)
+            colorTransform = true;
+          else if (typeof this.colorTransform !== 'undefined')
+            colorTransform = !!this.colorTransform;
 
-    handler.on('doc', function wphSetupDoc(data) {
-      // Create only the model of the PDFDoc, which is enough for
-      // processing the content of the pdf.
-      pdfDoc = new PDFDocModel(new Stream(data));
-    });
+          component1 = this.components[0];
+          component2 = this.components[1];
+          component3 = this.components[2];
+          for (y = 0; y < height; y++) {
+            component1Line = component1.lines[0 | (y * component1.scaleY * scaleY)];
+            component2Line = component2.lines[0 | (y * component2.scaleY * scaleY)];
+            component3Line = component3.lines[0 | (y * component3.scaleY * scaleY)];
+            for (x = 0; x < width; x++) {
+              if (!colorTransform) {
+                R = component1Line[0 | (x * component1.scaleX * scaleX)];
+                G = component2Line[0 | (x * component2.scaleX * scaleX)];
+                B = component3Line[0 | (x * component3.scaleX * scaleX)];
+              } else {
+                Y = component1Line[0 | (x * component1.scaleX * scaleX)];
+                Cb = component2Line[0 | (x * component2.scaleX * scaleX)];
+                Cr = component3Line[0 | (x * component3.scaleX * scaleX)];
 
-    handler.on('page_request', function wphSetupPageRequest(pageNum) {
-      pageNum = parseInt(pageNum);
+                R = clampTo8bit(Y + 1.402 * (Cr - 128));
+                G = clampTo8bit(Y - 0.3441363 * (Cb - 128) - 0.71413636 * (Cr - 128));
+                B = clampTo8bit(Y + 1.772 * (Cb - 128));
+              }
 
-      var page = pdfDoc.getPage(pageNum);
+              data[offset++] = R;
+              data[offset++] = G;
+              data[offset++] = B;
+            }
+          }
+          break;
+        case 4:
+          if (!this.adobe)
+            throw 'Unsupported color mode (4 components)';
+          // The default transform for four components is false
+          colorTransform = false;
+          // The adobe transform marker overrides any previous setting
+          if (this.adobe && this.adobe.transformCode)
+            colorTransform = true;
+          else if (typeof this.colorTransform !== 'undefined')
+            colorTransform = !!this.colorTransform;
 
-      // The following code does quite the same as
-      // Page.prototype.startRendering, but stops at one point and sends the
-      // result back to the main thread.
-      var gfx = new CanvasGraphics(null);
+          component1 = this.components[0];
+          component2 = this.components[1];
+          component3 = this.components[2];
+          component4 = this.components[3];
+          for (y = 0; y < height; y++) {
+            component1Line = component1.lines[0 | (y * component1.scaleY * scaleY)];
+            component2Line = component2.lines[0 | (y * component2.scaleY * scaleY)];
+            component3Line = component3.lines[0 | (y * component3.scaleY * scaleY)];
+            component4Line = component4.lines[0 | (y * component4.scaleY * scaleY)];
+            for (x = 0; x < width; x++) {
+              if (!colorTransform) {
+                C = component1Line[0 | (x * component1.scaleX * scaleX)];
+                M = component2Line[0 | (x * component2.scaleX * scaleX)];
+                Ye = component3Line[0 | (x * component3.scaleX * scaleX)];
+                K = component4Line[0 | (x * component4.scaleX * scaleX)];
+              } else {
+                Y = component1Line[0 | (x * component1.scaleX * scaleX)];
+                Cb = component2Line[0 | (x * component2.scaleX * scaleX)];
+                Cr = component3Line[0 | (x * component3.scaleX * scaleX)];
+                K = component4Line[0 | (x * component4.scaleX * scaleX)];
 
-      var start = Date.now();
+                C = 255 - clampTo8bit(Y + 1.402 * (Cr - 128));
+                M = 255 - clampTo8bit(Y - 0.3441363 * (Cb - 128) - 0.71413636 * (Cr - 128));
+                Ye = 255 - clampTo8bit(Y + 1.772 * (Cb - 128));
+              }
+              data[offset++] = C;
+              data[offset++] = M;
+              data[offset++] = Ye;
+              data[offset++] = K;
+            }
+          }
+          break;
+        default:
+          throw 'Unsupported color mode';
+      }
+      return data;
+    },
+    copyToImageData: function copyToImageData(imageData) {
+      var width = imageData.width, height = imageData.height;
+      var imageDataArray = imageData.data;
+      var data = this.getData(width, height);
+      var i = 0, j = 0, x, y;
+      var Y, K, C, M, R, G, B;
+      switch (this.components.length) {
+        case 1:
+          for (y = 0; y < height; y++) {
+            for (x = 0; x < width; x++) {
+              Y = data[i++];
 
-      var dependency = [];
+              imageDataArray[j++] = Y;
+              imageDataArray[j++] = Y;
+              imageDataArray[j++] = Y;
+              imageDataArray[j++] = 255;
+            }
+          }
+          break;
+        case 3:
+          for (y = 0; y < height; y++) {
+            for (x = 0; x < width; x++) {
+              R = data[i++];
+              G = data[i++];
+              B = data[i++];
 
-      // Pre compile the pdf page and fetch the fonts/images.
-      var IRQueue = page.getIRQueue(handler, dependency);
+              imageDataArray[j++] = R;
+              imageDataArray[j++] = G;
+              imageDataArray[j++] = B;
+              imageDataArray[j++] = 255;
+            }
+          }
+          break;
+        case 4:
+          for (y = 0; y < height; y++) {
+            for (x = 0; x < width; x++) {
+              C = data[i++];
+              M = data[i++];
+              Y = data[i++];
+              K = data[i++];
 
-      console.log('page=%d - getIRQueue: time=%dms, len=%d', pageNum,
-                                  Date.now() - start, IRQueue.fnArray.length);
+              R = 255 - clampTo8bit(C * (1 - K / 255) + K);
+              G = 255 - clampTo8bit(M * (1 - K / 255) + K);
+              B = 255 - clampTo8bit(Y * (1 - K / 255) + K);
 
-      // Filter the dependecies for fonts.
-      var fonts = {};
-      for (var i = 0, ii = dependency.length; i < ii; i++) {
-        var dep = dependency[i];
-        if (dep.indexOf('font_') == 0) {
-          fonts[dep] = true;
-        }
+              imageDataArray[j++] = R;
+              imageDataArray[j++] = G;
+              imageDataArray[j++] = B;
+              imageDataArray[j++] = 255;
+            }
+          }
+          break;
+        default:
+          throw 'Unsupported color mode';
       }
+    }
+  };
 
-      handler.send('page', {
-        pageNum: pageNum,
-        IRQueue: IRQueue,
-        depFonts: Object.keys(fonts)
-      });
-    }, this);
+  return constructor;
+})();/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
 
-    handler.on('font', function wphSetupFont(data) {
-      var objId = data[0];
-      var name = data[1];
-      var file = data[2];
-      var properties = data[3];
+'use strict';
 
-      var font = {
-        name: name,
-        file: file,
-        properties: properties
-      };
+var JpxImage = (function JpxImageClosure() {
+  // Table E.1
+  var SubbandsGainLog2 = {
+    'LL': 0,
+    'LH': 1,
+    'HL': 1,
+    'HH': 2
+  };
+  function JpxImage() {
+    this.failOnCorruptedImage = false;
+  }
+  JpxImage.prototype = {
+    load: function JpxImage_load(url) {
+      var xhr = new XMLHttpRequest();
+      xhr.open('GET', url, true);
+      xhr.responseType = 'arraybuffer';
+      xhr.onload = (function() {
+        // TODO catch parse error
+        var data = new Uint8Array(xhr.response || xhr.mozResponseArrayBuffer);
+        this.parse(data);
+        if (this.onload)
+          this.onload();
+      }).bind(this);
+      xhr.send(null);
+    },
+    parse: function JpxImage_parse(data) {
+      function ReadUint(data, offset, bytes) {
+        var n = 0;
+        for (var i = 0; i < bytes; i++)
+          n = n * 256 + (data[offset + i] & 0xFF);
+        return n;
+      }
+      var position = 0, length = data.length;
+      while (position < length) {
+        var headerSize = 8;
+        var lbox = ReadUint(data, position, 4);
+        var tbox = ReadUint(data, position + 4, 4);
+        position += headerSize;
+        if (lbox == 1) {
+          lbox = ReadUint(data, position, 8);
+          position += 8;
+          headerSize += 8;
+        }
+        if (lbox == 0)
+          lbox = length - position + headerSize;
+        if (lbox < headerSize)
+          error('JPX error: Invalid box field size');
+        var dataLength = lbox - headerSize;
+        var jumpDataLength = true;
+        switch (tbox) {
+          case 0x6A501A1A: // 'jP\032\032'
+            // TODO
+            break;
+          case 0x6A703268: // 'jp2h'
+            jumpDataLength = false; // parsing child boxes
+            break;
+          case 0x636F6C72: // 'colr'
+            // TODO
+            break;
+          case 0x6A703263: // 'jp2c'
+            this.parseCodestream(data, position, position + dataLength);
+            break;
+        }
+        if (jumpDataLength)
+          position += dataLength;
+      }
+    },
+    parseCodestream: function JpxImage_parseCodestream(data, start, end) {
+      var context = {};
+      try {
+        var position = start;
+        while (position < end) {
+          var code = readUint16(data, position);
+          position += 2;
+
+          var length = 0, j;
+          switch (code) {
+            case 0xFF4F: // Start of codestream (SOC)
+              context.mainHeader = true;
+              break;
+            case 0xFFD9: // End of codestream (EOC)
+              break;
+            case 0xFF51: // Image and tile size (SIZ)
+              length = readUint16(data, position);
+              var siz = {};
+              siz.Xsiz = readUint32(data, position + 4);
+              siz.Ysiz = readUint32(data, position + 8);
+              siz.XOsiz = readUint32(data, position + 12);
+              siz.YOsiz = readUint32(data, position + 16);
+              siz.XTsiz = readUint32(data, position + 20);
+              siz.YTsiz = readUint32(data, position + 24);
+              siz.XTOsiz = readUint32(data, position + 28);
+              siz.YTOsiz = readUint32(data, position + 32);
+              var componentsCount = readUint16(data, position + 36);
+              siz.Csiz = componentsCount;
+              var components = [];
+              j = position + 38;
+              for (var i = 0; i < componentsCount; i++) {
+                var component = {
+                  precision: (data[j] & 0x7F) + 1,
+                  isSigned: !!(data[j] & 0x80),
+                  XRsiz: data[j + 1],
+                  YRsiz: data[j + 1]
+                };
+                calculateComponentDimensions(component, siz);
+                components.push(component);
+              }
+              context.SIZ = siz;
+              context.components = components;
+              calculateTileGrids(context, components);
+              context.QCC = [];
+              context.COC = [];
+              break;
+            case 0xFF5C: // Quantization default (QCD)
+              length = readUint16(data, position);
+              var qcd = {};
+              j = position + 2;
+              var sqcd = data[j++];
+              var spqcdSize, scalarExpounded;
+              switch (sqcd & 0x1F) {
+                case 0:
+                  spqcdSize = 8;
+                  scalarExpounded = true;
+                  break;
+                case 1:
+                  spqcdSize = 16;
+                  scalarExpounded = false;
+                  break;
+                case 2:
+                  spqcdSize = 16;
+                  scalarExpounded = true;
+                  break;
+                default:
+                  throw 'Invalid SQcd value ' + sqcd;
+              }
+              qcd.noQuantization = spqcdSize == 8;
+              qcd.scalarExpounded = scalarExpounded;
+              qcd.guardBits = sqcd >> 5;
+              var spqcds = [];
+              while (j < length + position) {
+                var spqcd = {};
+                if (spqcdSize == 8) {
+                  spqcd.epsilon = data[j++] >> 3;
+                  spqcd.mu = 0;
+                } else {
+                  spqcd.epsilon = data[j] >> 3;
+                  spqcd.mu = ((data[j] & 0x7) << 8) | data[j + 1];
+                  j += 2;
+                }
+                spqcds.push(spqcd);
+              }
+              qcd.SPqcds = spqcds;
+              if (context.mainHeader)
+                context.QCD = qcd;
+              else {
+                context.currentTile.QCD = qcd;
+                context.currentTile.QCC = [];
+              }
+              break;
+            case 0xFF5D: // Quantization component (QCC)
+              length = readUint16(data, position);
+              var qcc = {};
+              j = position + 2;
+              var cqcc;
+              if (context.SIZ.Csiz < 257)
+                cqcc = data[j++];
+              else {
+                cqcc = readUint16(data, j);
+                j += 2;
+              }
+              var sqcd = data[j++];
+              var spqcdSize, scalarExpounded;
+              switch (sqcd & 0x1F) {
+                case 0:
+                  spqcdSize = 8;
+                  scalarExpounded = true;
+                  break;
+                case 1:
+                  spqcdSize = 16;
+                  scalarExpounded = false;
+                  break;
+                case 2:
+                  spqcdSize = 16;
+                  scalarExpounded = true;
+                  break;
+                default:
+                  throw 'Invalid SQcd value ' + sqcd;
+              }
+              qcc.noQuantization = spqcdSize == 8;
+              qcc.scalarExpounded = scalarExpounded;
+              qcc.guardBits = sqcd >> 5;
+              var spqcds = [];
+              while (j < length + position) {
+                var spqcd = {};
+                if (spqcdSize == 8) {
+                  spqcd.epsilon = data[j++] >> 3;
+                  spqcd.mu = 0;
+                } else {
+                  spqcd.epsilon = data[j] >> 3;
+                  spqcd.mu = ((data[j] & 0x7) << 8) | data[j + 1];
+                  j += 2;
+                }
+                spqcds.push(spqcd);
+              }
+              qcc.SPqcds = spqcds;
+              if (context.mainHeader)
+                context.QCC[cqcc] = qcc;
+              else
+                context.currentTile.QCC[cqcc] = qcc;
+              break;
+            case 0xFF52: // Coding style default (COD)
+              length = readUint16(data, position);
+              var cod = {};
+              j = position + 2;
+              var scod = data[j++];
+              cod.entropyCoderWithCustomPrecincts = !!(scod & 1);
+              cod.sopMarkerUsed = !!(scod & 2);
+              cod.ephMarkerUsed = !!(scod & 4);
+              var codingStyle = {};
+              cod.progressionOrder = data[j++];
+              cod.layersCount = readUint16(data, j);
+              j += 2;
+              cod.multipleComponentTransform = data[j++];
+
+              cod.decompositionLevelsCount = data[j++];
+              cod.xcb = (data[j++] & 0xF) + 2;
+              cod.ycb = (data[j++] & 0xF) + 2;
+              var blockStyle = data[j++];
+              cod.selectiveArithmeticCodingBypass = !!(blockStyle & 1);
+              cod.resetContextProbabilities = !!(blockStyle & 2);
+              cod.terminationOnEachCodingPass = !!(blockStyle & 4);
+              cod.verticalyStripe = !!(blockStyle & 8);
+              cod.predictableTermination = !!(blockStyle & 16);
+              cod.segmentationSymbolUsed = !!(blockStyle & 32);
+              cod.transformation = data[j++];
+              if (cod.entropyCoderWithCustomPrecincts) {
+                var precinctsSizes = {};
+                while (j < length + position) {
+                  var precinctsSize = data[j];
+                  precinctsSizes.push({
+                    PPx: precinctsSize & 0xF,
+                    PPy: precinctsSize >> 4
+                  });
+                }
+                cod.precinctsSizes = precinctsSizes;
+              }
 
-      // Some fonts don't have a file, e.g. the build in ones like Arial.
-      if (file) {
-        var fontFileDict = new Dict();
-        fontFileDict.map = file.dict.map;
+              if (cod.sopMarkerUsed || cod.ephMarkerUsed ||
+                  cod.selectiveArithmeticCodingBypass ||
+                  cod.resetContextProbabilities ||
+                  cod.terminationOnEachCodingPass ||
+                  cod.verticalyStripe || cod.predictableTermination ||
+                  cod.segmentationSymbolUsed)
+                throw 'Unsupported COD options: ' + uneval(cod);
+
+              if (context.mainHeader)
+                context.COD = cod;
+              else {
+                context.currentTile.COD = cod;
+                context.currentTile.COC = [];
+              }
+              break;
+            case 0xFF90: // Start of tile-part (SOT)
+              length = readUint16(data, position);
+              var tile = {};
+              tile.index = readUint16(data, position + 2);
+              tile.length = readUint32(data, position + 4);
+              tile.dataEnd = tile.length + position - 2;
+              tile.partIndex = data[position + 8];
+              tile.partsCount = data[position + 9];
+
+              context.mainHeader = false;
+              if (tile.partIndex == 0) {
+                // reset component specific settings
+                tile.COD = context.COD;
+                tile.COC = context.COC.slice(0); // clone of the global COC
+                tile.QCD = context.QCD;
+                tile.QCC = context.QCC.slice(0); // clone of the global COC
+              }
+              context.currentTile = tile;
+              break;
+            case 0xFF93: // Start of data (SOD)
+              var tile = context.currentTile;
+              if (tile.partIndex == 0) {
+                initializeTile(context, tile.index);
+                buildPackets(context);
+              }
 
-        var fontFile = new Stream(file.bytes, file.start,
-                                  file.end - file.start, fontFileDict);
+              // moving to the end of the data
+              length = tile.dataEnd - position;
 
-        // Check if this is a FlateStream. Otherwise just use the created
-        // Stream one. This makes complex_ttf_font.pdf work.
-        var cmf = file.bytes[0];
-        if ((cmf & 0x0f) == 0x08) {
-          font.file = new FlateStream(fontFile);
-        } else {
-          font.file = fontFile;
+              parseTilePackets(context, data, position, length);
+              break;
+            case 0xFF64: // Comment (COM)
+              length = readUint16(data, position);
+              // skipping content
+              break;
+            default:
+              throw 'Unknown codestream code: ' + code.toString(16);
+          }
+          position += length;
         }
+      } catch (e) {
+        if (this.failOnCorruptedImage)
+          error('JPX error: ' + e);
+        else
+          warn('JPX error: ' + e + '. Trying to recover');
       }
-
-      var obj = new Font(font.name, font.file, font.properties);
-
-      var str = '';
-      var objData = obj.data;
-      if (objData) {
-        var length = objData.length;
-        for (var j = 0; j < length; ++j)
-          str += String.fromCharCode(objData[j]);
+      this.tiles = transformComponents(context);
+      this.width = context.SIZ.Xsiz - context.SIZ.XOsiz;
+      this.height = context.SIZ.Ysiz - context.SIZ.YOsiz;
+      this.componentsCount = context.SIZ.Csiz;
+    }
+  };
+  function readUint32(data, offset) {
+    return (data[offset] << 24) | (data[offset + 1] << 16) |
+      (data[offset + 2] << 8) | data[offset + 3];
+  }
+  function readUint16(data, offset) {
+    return (data[offset] << 8) | data[offset + 1];
+  }
+  function log2(x) {
+    var n = 1, i = 0;
+    while (x > n) {
+      n <<= 1;
+      i++;
+    }
+    return i;
+  }
+  function calculateComponentDimensions(component, siz) {
+    // Section B.2 Component mapping
+    component.x0 = Math.ceil(siz.XOsiz / component.XRsiz);
+    component.x1 = Math.ceil(siz.Xsiz / component.XRsiz);
+    component.y0 = Math.ceil(siz.YOsiz / component.YRsiz);
+    component.y1 = Math.ceil(siz.Ysiz / component.YRsiz);
+    component.width = component.x1 - component.x0;
+    component.height = component.y1 - component.y0;
+  }
+  function calculateTileGrids(context, components) {
+    var siz = context.SIZ;
+    // Section B.3 Division into tile and tile-components
+    var tiles = [];
+    var numXtiles = Math.ceil((siz.Xsiz - siz.XTOsiz) / siz.XTsiz);
+    var numYtiles = Math.ceil((siz.Ysiz - siz.YTOsiz) / siz.YTsiz);
+    for (var q = 0; q < numYtiles; q++) {
+      for (var p = 0; p < numXtiles; p++) {
+        var tile = {};
+        tile.tx0 = Math.max(siz.XTOsiz + p * siz.XTsiz, siz.XOsiz);
+        tile.ty0 = Math.max(siz.YTOsiz + q * siz.YTsiz, siz.YOsiz);
+        tile.tx1 = Math.min(siz.XTOsiz + (p + 1) * siz.XTsiz, siz.Xsiz);
+        tile.ty1 = Math.min(siz.YTOsiz + (q + 1) * siz.YTsiz, siz.Ysiz);
+        tile.width = tile.tx1 - tile.tx0;
+        tile.height = tile.ty1 - tile.ty0;
+        tile.components = [];
+        tiles.push(tile);
       }
-
-      obj.str = str;
-
-      // Remove the data array form the font object, as it's not needed
-      // anymore as we sent over the ready str.
-      delete obj.data;
-
-      handler.send('font_ready', [objId, obj]);
-    });
+    }
+    context.tiles = tiles;
+
+    var componentsCount = siz.Csiz;
+    for (var i = 0, ii = componentsCount; i < ii; i++) {
+      var component = components[i];
+      var tileComponents = [];
+      for (var j = 0, jj = tiles.length; j < jj; j++) {
+        var tileComponent = {}, tile = tiles[j];
+        tileComponent.tcx0 = Math.ceil(tile.tx0 / component.XRsiz);
+        tileComponent.tcy0 = Math.ceil(tile.ty0 / component.YRsiz);
+        tileComponent.tcx1 = Math.ceil(tile.tx1 / component.XRsiz);
+        tileComponent.tcy1 = Math.ceil(tile.ty1 / component.YRsiz);
+        tileComponent.width = tileComponent.tcx1 - tileComponent.tcx0;
+        tileComponent.height = tileComponent.tcy1 - tileComponent.tcy0;
+        tile.components[i] = tileComponent;
+      }
+    }
   }
-};
-
-var consoleTimer = {};
-
-var workerConsole = {
-  log: function log() {
-    var args = Array.prototype.slice.call(arguments);
-    postMessage({
-      action: 'console_log',
-      data: args
-    });
-  },
-
-  error: function error() {
-    var args = Array.prototype.slice.call(arguments);
-    postMessage({
-      action: 'console_error',
-      data: args
-    });
-  },
-
-  time: function time(name) {
-    consoleTimer[name] = Date.now();
-  },
-
-  timeEnd: function timeEnd(name) {
-    var time = consoleTimer[name];
-    if (time == null) {
-      throw 'Unkown timer name ' + name;
+  function getBlocksDimensions(context, component, r) {
+    var codOrCoc = component.codingStyleParameters;
+    var result = {};
+    if (!codOrCoc.entropyCoderWithCustomPrecincts) {
+      result.PPx = 15;
+      result.PPy = 15;
+    } else {
+      result.PPx = codOrCoc.precinctsSizes[r].PPx;
+      result.PPy = codOrCoc.precinctsSizes[r].PPy;
     }
-    this.log('Timer:', name, Date.now() - time);
+    // calculate codeblock size as described in section B.7
+    result.xcb_ = r > 0 ? Math.min(codOrCoc.xcb, result.PPx - 1) :
+      Math.min(codOrCoc.xcb, result.PPx);
+    result.ycb_ = r > 0 ? Math.min(codOrCoc.ycb, result.PPy - 1) :
+      Math.min(codOrCoc.ycb, result.PPy);
+    return result;
   }
-};
-
-// Worker thread?
-if (typeof window === 'undefined') {
-  globalScope.console = workerConsole;
+  function buildPrecincts(context, resolution, dimensions) {
+    // Section B.6 Division resolution to precincts
+    var precinctWidth = 1 << dimensions.PPx;
+    var precinctHeight = 1 << dimensions.PPy;
+    var numprecinctswide = resolution.trx1 > resolution.trx0 ?
+      Math.ceil(resolution.trx1 / precinctWidth) -
+      Math.floor(resolution.trx0 / precinctWidth) : 0;
+    var numprecinctshigh = resolution.try1 > resolution.try0 ?
+      Math.ceil(resolution.try1 / precinctHeight) -
+      Math.floor(resolution.try0 / precinctHeight) : 0;
+    var numprecincts = numprecinctswide * numprecinctshigh;
+    var precinctXOffset = Math.floor(resolution.trx0 / precinctWidth) *
+      precinctWidth;
+    var precinctYOffset = Math.floor(resolution.try0 / precinctHeight) *
+      precinctHeight;
+    resolution.precinctParameters = {
+      precinctXOffset: precinctXOffset,
+      precinctYOffset: precinctYOffset,
+      precinctWidth: precinctWidth,
+      precinctHeight: precinctHeight,
+      numprecinctswide: numprecinctswide,
+      numprecinctshigh: numprecinctshigh,
+      numprecincts: numprecincts
+    };
+  }
+  function buildCodeblocks(context, subband, dimensions) {
+    // Section B.7 Division sub-band into code-blocks
+    var xcb_ = dimensions.xcb_;
+    var ycb_ = dimensions.ycb_;
+    var codeblockWidth = 1 << xcb_;
+    var codeblockHeight = 1 << ycb_;
+    var cbx0 = Math.floor(subband.tbx0 / codeblockWidth);
+    var cby0 = Math.floor(subband.tby0 / codeblockHeight);
+    var cbx1 = Math.ceil(subband.tbx1 / codeblockWidth);
+    var cby1 = Math.ceil(subband.tby1 / codeblockHeight);
+    var precinctParameters = subband.resolution.precinctParameters;
+    var codeblocks = [];
+    var precincts = [];
+    for (var j = cby0; j < cby1; j++) {
+      for (var i = cbx0; i < cbx1; i++) {
+        var codeblock = {
+          cbx: i,
+          cby: j,
+          tbx0: codeblockWidth * i,
+          tby0: codeblockHeight * j,
+          tbx1: codeblockWidth * (i + 1),
+          tby1: codeblockHeight * (j + 1)
+        };
+        // calculate precinct number
+        var pi = Math.floor((codeblock.tbx0 -
+          precinctParameters.precinctXOffset) /
+          precinctParameters.precinctWidth);
+        var pj = Math.floor((codeblock.tby0 -
+          precinctParameters.precinctYOffset) /
+          precinctParameters.precinctHeight);
+        var precinctNumber = pj +
+          pi * precinctParameters.numprecinctswide;
+        codeblock.tbx0_ = Math.max(subband.tbx0, codeblock.tbx0);
+        codeblock.tby0_ = Math.max(subband.tby0, codeblock.tby0);
+        codeblock.tbx1_ = Math.min(subband.tbx1, codeblock.tbx1);
+        codeblock.tby1_ = Math.min(subband.tby1, codeblock.tby1);
+        codeblock.precinctNumber = precinctNumber;
+        codeblock.subbandType = subband.type;
+        var coefficientsLength = (codeblock.tbx1_ - codeblock.tbx0_) *
+          (codeblock.tby1_ - codeblock.tby0_);
+        codeblock.Lblock = 3;
+        codeblocks.push(codeblock);
+        // building precinct for the sub-band
+        var precinct;
+        if (precinctNumber in precincts) {
+          precinct = precincts[precinctNumber];
+          precinct.cbxMin = Math.min(precinct.cbxMin, i);
+          precinct.cbyMin = Math.min(precinct.cbyMin, j);
+          precinct.cbxMax = Math.max(precinct.cbxMax, i);
+          precinct.cbyMax = Math.max(precinct.cbyMax, j);
+        } else {
+          precincts[precinctNumber] = precinct = {
+            cbxMin: i,
+            cbyMin: j,
+            cbxMax: i,
+            cbyMax: j
+          };
+        }
+        codeblock.precinct = precinct;
+      }
+    }
+    subband.codeblockParameters = {
+      codeblockWidth: xcb_,
+      codeblockHeight: ycb_,
+      numcodeblockwide: cbx1 - cbx0 + 1,
+      numcodeblockhigh: cby1 - cby1 + 1
+    };
+    subband.codeblocks = codeblocks;
+    for (var i = 0, ii = codeblocks.length; i < ii; i++) {
+      var codeblock = codeblocks[i];
+      var precinctNumber = codeblock.precinctNumber;
+    }
+    subband.precincts = precincts;
+  }
+  function createPacket(resolution, precinctNumber, layerNumber) {
+    var precinctCodeblocks = [];
+    // Section B.10.8 Order of info in packet
+    var subbands = resolution.subbands;
+    // sub-bands already ordered in 'LL', 'HL', 'LH', and 'HH' sequence
+    for (var i = 0, ii = subbands.length; i < ii; i++) {
+      var subband = subbands[i];
+      var codeblocks = subband.codeblocks;
+      for (var j = 0, jj = codeblocks.length; j < jj; j++) {
+        var codeblock = codeblocks[j];
+        if (codeblock.precinctNumber != precinctNumber)
+          continue;
+        precinctCodeblocks.push(codeblock);
+      }
+    }
+    return {
+      layerNumber: layerNumber,
+      codeblocks: precinctCodeblocks
+    };
+  }
+  function LayerResolutionComponentPositionIterator(context) {
+    var siz = context.SIZ;
+    var tileIndex = context.currentTile.index;
+    var tile = context.tiles[tileIndex];
+    var layersCount = tile.codingStyleDefaultParameters.layersCount;
+    var componentsCount = siz.Csiz;
+    var maxDecompositionLevelsCount = 0;
+    for (var q = 0; q < componentsCount; q++) {
+      maxDecompositionLevelsCount = Math.max(maxDecompositionLevelsCount,
+        tile.components[q].codingStyleParameters.decompositionLevelsCount);
+    }
 
-  var handler = new MessageHandler('worker_processor', this);
-  WorkerMessageHandler.setup(handler);
-}
+    var l = 0, r = 0, i = 0, k = 0;
 
-/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- /
-/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
+    this.nextPacket = function JpxImage_nextPacket() {
+      // Section B.12.1.1 Layer-resolution-component-position
+      for (; l < layersCount; l++) {
+        for (; r <= maxDecompositionLevelsCount; r++) {
+          for (; i < componentsCount; i++) {
+            var component = tile.components[i];
+            if (r > component.codingStyleParameters.decompositionLevelsCount)
+              continue;
 
-// - The JPEG specification can be found in the ITU CCITT Recommendation T.81
-//   (www.w3.org/Graphics/JPEG/itu-t81.pdf)
-// - The JFIF specification can be found in the JPEG File Interchange Format
-//   (www.w3.org/Graphics/JPEG/jfif3.pdf)
-// - The Adobe Application-Specific JPEG markers in the Supporting the DCT Filters
-//   in PostScript Level 2, Technical Note #5116
-//   (partners.adobe.com/public/developer/en/ps/sdk/5116.DCT_Filter.pdf)
+            var resolution = component.resolutions[r];
+            var numprecincts = resolution.precinctParameters.numprecincts;
+            for (; k < numprecincts;) {
+              var packet = createPacket(resolution, k, l);
+              k++;
+              return packet;
+            }
+            k = 0;
+          }
+          i = 0;
+        }
+        r = 0;
+      }
+      throw 'Out of packets';
+    };
+  }
+  function ResolutionLayerComponentPositionIterator(context) {
+    var siz = context.SIZ;
+    var tileIndex = context.currentTile.index;
+    var tile = context.tiles[tileIndex];
+    var layersCount = tile.codingStyleDefaultParameters.layersCount;
+    var componentsCount = siz.Csiz;
+    var maxDecompositionLevelsCount = 0;
+    for (var q = 0; q < componentsCount; q++) {
+      maxDecompositionLevelsCount = Math.max(maxDecompositionLevelsCount,
+        tile.components[q].codingStyleParameters.decompositionLevelsCount);
+    }
 
-var JpegImage = (function jpegImage() {
-  "use strict";
-  var dctZigZag = new Int32Array([
-     0,
-     1,  8,
-    16,  9,  2,
-     3, 10, 17, 24,
-    32, 25, 18, 11, 4,
-     5, 12, 19, 26, 33, 40,
-    48, 41, 34, 27, 20, 13,  6,
-     7, 14, 21, 28, 35, 42, 49, 56,
-    57, 50, 43, 36, 29, 22, 15,
-    23, 30, 37, 44, 51, 58,
-    59, 52, 45, 38, 31,
-    39, 46, 53, 60,
-    61, 54, 47,
-    55, 62,
-    63
-  ]);
+    var r = 0, l = 0, i = 0, k = 0;
 
-  var dctCos1  =  4017   // cos(pi/16)
-  var dctSin1  =   799   // sin(pi/16)
-  var dctCos3  =  3406   // cos(3*pi/16)
-  var dctSin3  =  2276   // sin(3*pi/16)
-  var dctCos6  =  1567   // cos(6*pi/16)
-  var dctSin6  =  3784   // sin(6*pi/16)
-  var dctSqrt2 =  5793   // sqrt(2)
-  var dctSqrt1d2 = 2896  // sqrt(2) / 2
+    this.nextPacket = function JpxImage_nextPacket() {
+      // Section B.12.1.2 Resolution-layer-component-position
+      for (; r <= maxDecompositionLevelsCount; r++) {
+        for (; l < layersCount; l++) {
+          for (; i < componentsCount; i++) {
+            var component = tile.components[i];
+            if (r > component.codingStyleParameters.decompositionLevelsCount)
+              continue;
 
-  function constructor() {
+            var resolution = component.resolutions[r];
+            var numprecincts = resolution.precinctParameters.numprecincts;
+            for (; k < numprecincts;) {
+              var packet = createPacket(resolution, k, l);
+              k++;
+              return packet;
+            }
+            k = 0;
+          }
+          i = 0;
+        }
+        l = 0;
+      }
+      throw 'Out of packets';
+    };
+  }
+  function buildPackets(context) {
+    var siz = context.SIZ;
+    var tileIndex = context.currentTile.index;
+    var tile = context.tiles[tileIndex];
+    var componentsCount = siz.Csiz;
+    // Creating resolutions and sub-bands for each component
+    for (var c = 0; c < componentsCount; c++) {
+      var component = tile.components[c];
+      var decompositionLevelsCount =
+        component.codingStyleParameters.decompositionLevelsCount;
+      // Section B.5 Resolution levels and sub-bands
+      var resolutions = [];
+      var subbands = [];
+      for (var r = 0; r <= decompositionLevelsCount; r++) {
+        var blocksDimensions = getBlocksDimensions(context, component, r);
+        var resolution = {};
+        var scale = 1 << (decompositionLevelsCount - r);
+        resolution.trx0 = Math.ceil(component.tcx0 / scale);
+        resolution.try0 = Math.ceil(component.tcy0 / scale);
+        resolution.trx1 = Math.ceil(component.tcx1 / scale);
+        resolution.try1 = Math.ceil(component.tcy1 / scale);
+        buildPrecincts(context, resolution, blocksDimensions);
+        resolutions.push(resolution);
+
+        var subband;
+        if (r == 0) {
+          // one sub-band (LL) with last decomposition
+          subband = {};
+          subband.type = 'LL';
+          subband.tbx0 = Math.ceil(component.tcx0 / scale);
+          subband.tby0 = Math.ceil(component.tcy0 / scale);
+          subband.tbx1 = Math.ceil(component.tcx1 / scale);
+          subband.tby1 = Math.ceil(component.tcy1 / scale);
+          subband.resolution = resolution;
+          buildCodeblocks(context, subband, blocksDimensions);
+          subbands.push(subband);
+          resolution.subbands = [subband];
+        } else {
+          var bscale = 1 << (decompositionLevelsCount - r + 1);
+          var resolutionSubbands = [];
+          // three sub-bands (HL, LH and HH) with rest of decompositions
+          subband = {};
+          subband.type = 'HL';
+          subband.tbx0 = Math.ceil(component.tcx0 / bscale - 0.5);
+          subband.tby0 = Math.ceil(component.tcy0 / bscale);
+          subband.tbx1 = Math.ceil(component.tcx1 / bscale - 0.5);
+          subband.tby1 = Math.ceil(component.tcy1 / bscale);
+          subband.resolution = resolution;
+          buildCodeblocks(context, subband, blocksDimensions);
+          subbands.push(subband);
+          resolutionSubbands.push(subband);
+
+          subband = {};
+          subband.type = 'LH';
+          subband.tbx0 = Math.ceil(component.tcx0 / bscale);
+          subband.tby0 = Math.ceil(component.tcy0 / bscale - 0.5);
+          subband.tbx1 = Math.ceil(component.tcx1 / bscale);
+          subband.tby1 = Math.ceil(component.tcy1 / bscale - 0.5);
+          subband.resolution = resolution;
+          buildCodeblocks(context, subband, blocksDimensions);
+          subbands.push(subband);
+          resolutionSubbands.push(subband);
+
+          subband = {};
+          subband.type = 'HH';
+          subband.tbx0 = Math.ceil(component.tcx0 / bscale - 0.5);
+          subband.tby0 = Math.ceil(component.tcy0 / bscale - 0.5);
+          subband.tbx1 = Math.ceil(component.tcx1 / bscale - 0.5);
+          subband.tby1 = Math.ceil(component.tcy1 / bscale - 0.5);
+          subband.resolution = resolution;
+          buildCodeblocks(context, subband, blocksDimensions);
+          subbands.push(subband);
+          resolutionSubbands.push(subband);
+
+          resolution.subbands = resolutionSubbands;
+        }
+      }
+      component.resolutions = resolutions;
+      component.subbands = subbands;
+    }
+    // Generate the packets sequence
+    var progressionOrder = tile.codingStyleDefaultParameters.progressionOrder;
+    var packetsIterator;
+    switch (progressionOrder) {
+      case 0:
+        tile.packetsIterator =
+          new LayerResolutionComponentPositionIterator(context);
+        break;
+      case 1:
+        tile.packetsIterator =
+          new ResolutionLayerComponentPositionIterator(context);
+        break;
+      default:
+        throw 'Unsupported progression order ' + progressionOrder;
+    }
   }
+  function parseTilePackets(context, data, offset, dataLength) {
+    var position = 0;
+    var buffer, bufferSize = 0, skipNextBit = false;
+    function readBits(count) {
+      while (bufferSize < count) {
+        var b = data[offset + position];
+        position++;
+        if (skipNextBit) {
+          buffer = (buffer << 7) | b;
+          bufferSize += 7;
+          skipNextBit = false;
+        } else {
+          buffer = (buffer << 8) | b;
+          bufferSize += 8;
+        }
+        if (b == 0xFF) {
+          skipNextBit = true;
+        }
+      }
+      bufferSize -= count;
+      return (buffer >>> bufferSize) & ((1 << count) - 1);
+    }
+    function alignToByte() {
+      bufferSize = 0;
+      if (skipNextBit) {
+        position++;
+        skipNextBit = false;
+      }
+    }
+    function readCodingpasses() {
+      var value = readBits(1);
+      if (value == 0)
+        return 1;
+      value = (value << 1) | readBits(1);
+      if (value == 0x02)
+        return 2;
+      value = (value << 2) | readBits(2);
+      if (value <= 0x0E)
+        return (value & 0x03) + 3;
+      value = (value << 5) | readBits(5);
+      if (value <= 0x1FE)
+        return (value & 0x1F) + 6;
+      value = (value << 7) | readBits(7);
+      return (value & 0x7F) + 37;
+    }
+    var tileIndex = context.currentTile.index;
+    var tile = context.tiles[tileIndex];
+    var packetsIterator = tile.packetsIterator;
+    while (position < dataLength) {
+      var packet = packetsIterator.nextPacket();
+      if (!readBits(1)) {
+        alignToByte();
+        continue;
+      }
+      var layerNumber = packet.layerNumber;
+      var queue = [];
+      for (var i = 0, ii = packet.codeblocks.length; i < ii; i++) {
+        var codeblock = packet.codeblocks[i];
+        var precinct = codeblock.precinct;
+        var codeblockColumn = codeblock.cbx - precinct.cbxMin;
+        var codeblockRow = codeblock.cby - precinct.cbyMin;
+        var codeblockIncluded = false;
+        var firstTimeInclusion = false;
+        if ('included' in codeblock) {
+          codeblockIncluded = !!readBits(1);
+        } else {
+          // reading inclusion tree
+          var precinct = codeblock.precinct;
+          var inclusionTree, zeroBitPlanesTree;
+          if ('inclusionTree' in precinct) {
+            inclusionTree = precinct.inclusionTree;
+          } else {
+            // building inclusion and zero bit-planes trees
+            var width = precinct.cbxMax - precinct.cbxMin + 1;
+            var height = precinct.cbyMax - precinct.cbyMin + 1;
+            inclusionTree = new InclusionTree(width, height, layerNumber);
+            zeroBitPlanesTree = new TagTree(width, height);
+            precinct.inclusionTree = inclusionTree;
+            precinct.zeroBitPlanesTree = zeroBitPlanesTree;
+          }
 
-  function buildHuffmanTable(codeLengths, values) {
-    var k = 0, code = [], i, j, length = 16;
-    while (length > 0 && !codeLengths[length - 1])
-      length--;
-    code.push({children: [], index: 0});
-    var p = code[0], q;
-    for (i = 0; i < length; i++) {
-      for (j = 0; j < codeLengths[i]; j++) {
-        p = code.pop();
-        p.children[p.index] = values[k];
-        while (p.index > 0) {
-          p = code.pop();
+          if (inclusionTree.reset(codeblockColumn, codeblockRow, layerNumber)) {
+            while (true) {
+              if (readBits(1)) {
+                var valueReady = !inclusionTree.nextLevel();
+                if (valueReady) {
+                  codeblock.included = true;
+                  codeblockIncluded = firstTimeInclusion = true;
+                  break;
+                }
+              } else {
+                inclusionTree.incrementValue(layerNumber);
+                break;
+              }
+            }
+          }
         }
-        p.index++;
-        code.push(p);
-        while (code.length <= i) {
-          code.push(q = {children: [], index: 0});
-          p.children[p.index] = q.children;
-          p = q;
+        if (!codeblockIncluded)
+          continue;
+        if (firstTimeInclusion) {
+          zeroBitPlanesTree = precinct.zeroBitPlanesTree;
+          zeroBitPlanesTree.reset(codeblockColumn, codeblockRow);
+          while (true) {
+            if (readBits(1)) {
+              var valueReady = !zeroBitPlanesTree.nextLevel();
+              if (valueReady)
+                break;
+            } else
+              zeroBitPlanesTree.incrementValue();
+          }
+          codeblock.zeroBitPlanes = zeroBitPlanesTree.value;
         }
-        k++;
+        var codingpasses = readCodingpasses();
+        while (readBits(1))
+          codeblock.Lblock++;
+        var codingpassesLog2 = log2(codingpasses);
+        // rounding down log2
+        var bits = ((codingpasses < (1 << codingpassesLog2)) ?
+          codingpassesLog2 - 1 : codingpassesLog2) + codeblock.Lblock;
+        var codedDataLength = readBits(bits);
+        queue.push({
+          codeblock: codeblock,
+          codingpasses: codingpasses,
+          dataLength: codedDataLength
+        });
       }
-      if (i + 1 < length) {
-        // p here points to last code
-        code.push(q = {children: [], index: 0});
-        p.children[p.index] = q.children;
-        p = q;
+      alignToByte();
+      while (queue.length > 0) {
+        var packetItem = queue.shift();
+        var codeblock = packetItem.codeblock;
+        if (!('data' in codeblock))
+          codeblock.data = [];
+        codeblock.data.push({
+          data: data,
+          start: offset + position,
+          end: offset + position + packetItem.dataLength,
+          codingpasses: packetItem.codingpasses
+        });
+        position += packetItem.dataLength;
       }
     }
-    return code[0].children;
+    return position;
   }
+  function copyCoefficients(coefficients, x0, y0, width, height,
+                            delta, mb, codeblocks, transformation) {
+    var r = 0.5; // formula (E-6)
+    for (var i = 0, ii = codeblocks.length; i < ii; ++i) {
+      var codeblock = codeblocks[i];
+      var blockWidth = codeblock.tbx1_ - codeblock.tbx0_;
+      var blockHeight = codeblock.tby1_ - codeblock.tby0_;
+      if (blockWidth == 0 || blockHeight == 0)
+        continue;
+      if (!('data' in codeblock))
+        continue;
 
-  function decodeScan(data, offset,
-                      frame, components, resetInterval,
-                      spectralStart, spectralEnd,
-                      successivePrev, successive) {
-    var precision = frame.precision;
-    var samplesPerLine = frame.samplesPerLine;
-    var scanLines = frame.scanLines;
-    var mcusPerLine = frame.mcusPerLine;
-    var progressive = frame.progressive;
-    var maxH = frame.maxH, maxV = frame.maxV;
-
-    var startOffset = offset, bitsData = 0, bitsCount = 0;
-    function readBit() {
-      if (bitsCount > 0) {
-        bitsCount--;
-        return (bitsData >> bitsCount) & 1;
-      }
-      bitsData = data[offset++];
-      if (bitsData == 0xFF) {
-        var nextByte = data[offset++];
-        if (nextByte) {
-          throw "unexpected marker: " + ((bitsData << 8) | nextByte).toString(16);
+      var bitModel, currentCodingpassType;
+      bitModel = new BitModel(blockWidth, blockHeight, codeblock.subbandType,
+        codeblock.zeroBitPlanes);
+      currentCodingpassType = 2; // first bit plane starts from cleanup
+
+      // collect data
+      var data = codeblock.data, totalLength = 0, codingpasses = 0;
+      for (var q = 0, qq = data.length; q < qq; q++) {
+        var dataItem = data[q];
+        totalLength += dataItem.end - dataItem.start;
+        codingpasses += dataItem.codingpasses;
+      }
+      var encodedData = new Uint8Array(totalLength), k = 0;
+      for (var q = 0, qq = data.length; q < qq; q++) {
+        var dataItem = data[q];
+        var chunk = dataItem.data.subarray(dataItem.start, dataItem.end);
+        encodedData.set(chunk, k);
+        k += chunk.length;
+      }
+      // decoding the item
+      var decoder = new ArithmeticDecoder(encodedData, 0, totalLength);
+      bitModel.setDecoder(decoder);
+
+      for (var q = 0; q < codingpasses; q++) {
+        switch (currentCodingpassType) {
+          case 0:
+            bitModel.runSignificancePropogationPass();
+            break;
+          case 1:
+            bitModel.runMagnitudeRefinementPass();
+            break;
+          case 2:
+            bitModel.runCleanupPass();
+            break;
         }
-        // unstuff 0
+        currentCodingpassType = (currentCodingpassType + 1) % 3;
+      }
+
+      var offset = (codeblock.tbx0_ - x0) + (codeblock.tby0_ - y0) * width;
+      var position = 0;
+      for (var j = 0; j < blockHeight; j++) {
+        for (var k = 0; k < blockWidth; k++) {
+          var n = (bitModel.coefficentsSign[position] ? -1 : 1) *
+            bitModel.coefficentsMagnitude[position];
+          var nb = bitModel.bitsDecoded[position], correction;
+          if (transformation == 0 || mb > nb) {
+            // use r only if transformation is irreversible or
+            // not all bitplanes were decoded for reversible transformation
+            n += n < 0 ? n - r : n > 0 ? n + r : 0;
+            correction = 1 << (mb - nb);
+          } else
+            correction = 1;
+          coefficients[offset++] = n * correction * delta;
+          position++;
+        }
+        offset += width - blockWidth;
       }
-      bitsCount = 7;
-      return bitsData >>> 7;
     }
-    function decodeHuffman(tree) {
-      var node = tree, bit;
-      while ((bit = readBit()) !== null) {
-        node = node[bit];
-        if (typeof node === 'number')
-          return node;
-        if (typeof node !== 'object')
-          throw "invalid huffman sequence";
+  }
+  function transformTile(context, tile, c) {
+    var component = tile.components[c];
+    var codingStyleParameters = component.codingStyleParameters;
+    var quantizationParameters = component.quantizationParameters;
+    var decompositionLevelsCount =
+      codingStyleParameters.decompositionLevelsCount;
+    var spqcds = quantizationParameters.SPqcds;
+    var scalarExpounded = quantizationParameters.scalarExpounded;
+    var guardBits = quantizationParameters.guardBits;
+    var transformation = codingStyleParameters.transformation;
+    var precision = context.components[c].precision;
+
+    var subbandCoefficients = [];
+    var k = 0, b = 0;
+    for (var i = 0; i <= decompositionLevelsCount; i++) {
+      var resolution = component.resolutions[i];
+
+      for (var j = 0, jj = resolution.subbands.length; j < jj; j++) {
+        var mu, epsilon;
+        if (!scalarExpounded) {
+          // formula E-5
+          mu = spqcds[0].mu;
+          epsilon = spqcds[0].epsilon + (i > 0 ? 1 - i : 0);
+        } else {
+          mu = spqcds[b].mu;
+          epsilon = spqcds[b].epsilon;
+        }
+
+        var subband = resolution.subbands[j];
+        var width = subband.tbx1 - subband.tbx0;
+        var height = subband.tby1 - subband.tby0;
+        var gainLog2 = SubbandsGainLog2[subband.type];
+
+        // calulate quantization coefficient (Section E.1.1.1)
+        var delta = Math.pow(2, (precision + gainLog2) - epsilon) *
+          (1 + mu / 2048);
+        var mb = (guardBits + epsilon - 1);
+
+        var coefficients = new Float32Array(width * height);
+        copyCoefficients(coefficients, subband.tbx0, subband.tby0,
+          width, height, delta, mb, subband.codeblocks, transformation);
+
+        subbandCoefficients.push({
+          width: width,
+          height: height,
+          items: coefficients
+        });
+
+        b++;
       }
-      return null;
     }
-    function receive(length) {
-      var n = 0;
-      while (length > 0) {
-        var bit = readBit();
-        if (bit === null) return;
-        n = (n << 1) | bit;
-        length--;
+
+    var transformation = codingStyleParameters.transformation;
+    var transform = transformation == 0 ? new IrreversibleTransform() :
+      new ReversibleTransform();
+    var result = transform.calculate(subbandCoefficients,
+      component.tcx0, component.tcy0);
+    return {
+      left: component.tcx0,
+      top: component.tcy0,
+      width: result.width,
+      height: result.height,
+      items: result.items
+    };
+  }
+  function transformComponents(context) {
+    var siz = context.SIZ;
+    var components = context.components;
+    var componentsCount = siz.Csiz;
+    var resultImages = [];
+    for (var i = 0, ii = context.tiles.length; i < ii; i++) {
+      var tile = context.tiles[i];
+      var result = [];
+      for (var c = 0; c < componentsCount; c++) {
+        var image = transformTile(context, tile, c);
+        result.push(image);
+      }
+
+      // Section G.2.2 Inverse multi component transform
+      if (tile.codingStyleDefaultParameters.multipleComponentTransform) {
+        var y0items = result[0].items;
+        var y1items = result[1].items;
+        var y2items = result[2].items;
+        for (var j = 0, jj = y0items.length; j < jj; j++) {
+          var y0 = y0items[j], y1 = y1items[j], y2 = y2items[j];
+          var i1 = y0 - ((y2 + y1) >> 2);
+          y1items[j] = i1;
+          y0items[j] = y2 + i1;
+          y2items[j] = y1 + i1;
+        }
       }
-      return n;
-    }
-    function receiveAndExtend(length) {
-      var n = receive(length);
-      if (n >= 1 << (length - 1))
-        return n;
-      return n + (-1 << length) + 1;
-    }
-    function decodeBaseline(component, zz) {
-      var t = decodeHuffman(component.huffmanTableDC);
-      var diff = t === 0 ? 0 : receiveAndExtend(t);
-      zz[0]= (component.pred += diff);
-      var k = 1;
-      while (k < 64) {
-        var rs = decodeHuffman(component.huffmanTableAC);
-        var s = rs & 15, r = rs >> 4;
-        if (s === 0) {
-          if (r < 15)
-            break;
-          k += 16;
+
+      // Section G.1 DC level shifting to unsigned component values
+      for (var c = 0; c < componentsCount; c++) {
+        var component = components[c];
+        if (component.isSigned)
           continue;
+
+        var offset = 1 << (component.precision - 1);
+        var tileImage = result[c];
+        var items = tileImage.items;
+        for (var j = 0, jj = items.length; j < jj; j++)
+          items[j] += offset;
+      }
+
+      // To simplify things: shift and clamp output to 8 bit unsigned
+      for (var c = 0; c < componentsCount; c++) {
+        var component = components[c];
+        var offset = component.isSigned ? 128 : 0;
+        var shift = component.precision - 8;
+        var tileImage = result[c];
+        var items = tileImage.items;
+        var data = new Uint8Array(items.length);
+        for (var j = 0, jj = items.length; j < jj; j++) {
+          var value = (items[j] >> shift) + offset;
+          data[j] = value < 0 ? 0 : value > 255 ? 255 : value;
         }
-        k += r;
-        var z = dctZigZag[k];
-        zz[z] = receiveAndExtend(s);
-        k++;
+        result[c].items = data;
       }
+
+      resultImages.push(result);
     }
-    function decodeDCFirst(component, zz) {
-      var t = decodeHuffman(component.huffmanTableDC);
-      var diff = t === 0 ? 0 : (receiveAndExtend(t) << successive);
-      zz[0] = (component.pred += diff);
+    return resultImages;
+  }
+  function initializeTile(context, tileIndex) {
+    var siz = context.SIZ;
+    var componentsCount = siz.Csiz;
+    var tile = context.tiles[tileIndex];
+    var resultTiles = [];
+    for (var c = 0; c < componentsCount; c++) {
+      var component = tile.components[c];
+      var qcdOrQcc = c in context.currentTile.QCC ?
+        context.currentTile.QCC[c] : context.currentTile.QCD;
+      component.quantizationParameters = qcdOrQcc;
+      var codOrCoc = c in context.currentTile.COC ?
+        context.currentTile.COC[c] : context.currentTile.COD;
+      component.codingStyleParameters = codOrCoc;
     }
-    function decodeDCSuccessive(component, zz) {
-      zz[0] |= readBit() << successive;
+    tile.codingStyleDefaultParameters = context.currentTile.COD;
+  }
+
+  // Section B.10.2 Tag trees
+  var TagTree = (function TagTreeClosure() {
+    function TagTree(width, height) {
+      var levelsLength = log2(Math.max(width, height)) + 1;
+      this.levels = [];
+      for (var i = 0; i < levelsLength; i++) {
+        var level = {
+          width: width,
+          height: height,
+          items: []
+        };
+        this.levels.push(level);
+        width = Math.ceil(width / 2);
+        height = Math.ceil(height / 2);
+      }
     }
-    var eobrun = 0;
-    function decodeACFirst(component, zz) {
-      if (eobrun > 0) {
-        eobrun--;
-        return;
+    TagTree.prototype = {
+      reset: function TagTree_reset(i, j) {
+        var currentLevel = 0, value = 0;
+        while (currentLevel < this.levels.length) {
+          var level = this.levels[currentLevel];
+          var index = i + j * level.width;
+          if (index in level.items) {
+            value = level.items[index];
+            break;
+          }
+          level.index = index;
+          i >>= 1;
+          j >>= 1;
+          currentLevel++;
+        }
+        currentLevel--;
+        var level = this.levels[currentLevel];
+        level.items[level.index] = value;
+        this.currentLevel = currentLevel;
+        delete this.value;
+      },
+      incrementValue: function TagTree_incrementValue() {
+        var level = this.levels[this.currentLevel];
+        level.items[level.index]++;
+      },
+      nextLevel: function TagTree_nextLevel() {
+        var currentLevel = this.currentLevel;
+        var level = this.levels[currentLevel];
+        var value = level.items[level.index];
+        currentLevel--;
+        if (currentLevel < 0) {
+          this.value = value;
+          return false;
+        }
+
+        this.currentLevel = currentLevel;
+        var level = this.levels[currentLevel];
+        level.items[level.index] = value;
+        return true;
       }
-      var k = spectralStart, e = spectralEnd;
-      while (k <= e) {
-        var rs = decodeHuffman(component.huffmanTableAC);
-        var s = rs & 15, r = rs >> 4;
-        if (s === 0) {
-          if (r < 15) {
-            eobrun = receive(r) + (1 << r) - 1;
+    };
+    return TagTree;
+  })();
+
+  var InclusionTree = (function InclusionTreeClosure() {
+    function InclusionTree(width, height,  defaultValue) {
+      var levelsLength = log2(Math.max(width, height)) + 1;
+      this.levels = [];
+      for (var i = 0; i < levelsLength; i++) {
+        var items = new Uint8Array(width * height);
+        for (var j = 0, jj = items.length; j < jj; j++)
+          items[j] = defaultValue;
+
+        var level = {
+          width: width,
+          height: height,
+          items: items
+        };
+        this.levels.push(level);
+
+        width = Math.ceil(width / 2);
+        height = Math.ceil(height / 2);
+      }
+    }
+    InclusionTree.prototype = {
+      reset: function InclusionTree_reset(i, j, stopValue) {
+        var currentLevel = 0;
+        while (currentLevel < this.levels.length) {
+          var level = this.levels[currentLevel];
+          var index = i + j * level.width;
+          level.index = index;
+          var value = level.items[index];
+
+          if (value == 0xFF)
             break;
+
+          if (value > stopValue) {
+            this.currentLevel = currentLevel;
+            // already know about this one, propagating the value to top levels
+            this.propagateValues();
+            return false;
           }
-          k += 16;
-          continue;
+
+          i >>= 1;
+          j >>= 1;
+          currentLevel++;
         }
-        k += r;
-        var z = dctZigZag[k];
-        zz[z] = receiveAndExtend(s) * (1 << successive);
-        k++;
+        this.currentLevel = currentLevel - 1;
+        return true;
+      },
+      incrementValue: function InclusionTree_incrementValue(stopValue) {
+        var level = this.levels[this.currentLevel];
+        level.items[level.index] = stopValue + 1;
+        this.propagateValues();
+      },
+      propagateValues: function InclusionTree_propagateValues() {
+        var levelIndex = this.currentLevel;
+        var level = this.levels[levelIndex];
+        var currentValue = level.items[level.index];
+        while (--levelIndex >= 0) {
+          var level = this.levels[levelIndex];
+          level.items[level.index] = currentValue;
+        }
+      },
+      nextLevel: function InclusionTree_nextLevel() {
+        var currentLevel = this.currentLevel;
+        var level = this.levels[currentLevel];
+        var value = level.items[level.index];
+        level.items[level.index] = 0xFF;
+        currentLevel--;
+        if (currentLevel < 0)
+          return false;
+
+        this.currentLevel = currentLevel;
+        var level = this.levels[currentLevel];
+        level.items[level.index] = value;
+        return true;
       }
+    };
+    return InclusionTree;
+  })();
+
+  // Implements C.3. Arithmetic decoding procedures
+  var ArithmeticDecoder = (function ArithmeticDecoderClosure() {
+    var QeTable = [
+      {qe: 0x5601, nmps: 1, nlps: 1, switchFlag: 1},
+      {qe: 0x3401, nmps: 2, nlps: 6, switchFlag: 0},
+      {qe: 0x1801, nmps: 3, nlps: 9, switchFlag: 0},
+      {qe: 0x0AC1, nmps: 4, nlps: 12, switchFlag: 0},
+      {qe: 0x0521, nmps: 5, nlps: 29, switchFlag: 0},
+      {qe: 0x0221, nmps: 38, nlps: 33, switchFlag: 0},
+      {qe: 0x5601, nmps: 7, nlps: 6, switchFlag: 1},
+      {qe: 0x5401, nmps: 8, nlps: 14, switchFlag: 0},
+      {qe: 0x4801, nmps: 9, nlps: 14, switchFlag: 0},
+      {qe: 0x3801, nmps: 10, nlps: 14, switchFlag: 0},
+      {qe: 0x3001, nmps: 11, nlps: 17, switchFlag: 0},
+      {qe: 0x2401, nmps: 12, nlps: 18, switchFlag: 0},
+      {qe: 0x1C01, nmps: 13, nlps: 20, switchFlag: 0},
+      {qe: 0x1601, nmps: 29, nlps: 21, switchFlag: 0},
+      {qe: 0x5601, nmps: 15, nlps: 14, switchFlag: 1},
+      {qe: 0x5401, nmps: 16, nlps: 14, switchFlag: 0},
+      {qe: 0x5101, nmps: 17, nlps: 15, switchFlag: 0},
+      {qe: 0x4801, nmps: 18, nlps: 16, switchFlag: 0},
+      {qe: 0x3801, nmps: 19, nlps: 17, switchFlag: 0},
+      {qe: 0x3401, nmps: 20, nlps: 18, switchFlag: 0},
+      {qe: 0x3001, nmps: 21, nlps: 19, switchFlag: 0},
+      {qe: 0x2801, nmps: 22, nlps: 19, switchFlag: 0},
+      {qe: 0x2401, nmps: 23, nlps: 20, switchFlag: 0},
+      {qe: 0x2201, nmps: 24, nlps: 21, switchFlag: 0},
+      {qe: 0x1C01, nmps: 25, nlps: 22, switchFlag: 0},
+      {qe: 0x1801, nmps: 26, nlps: 23, switchFlag: 0},
+      {qe: 0x1601, nmps: 27, nlps: 24, switchFlag: 0},
+      {qe: 0x1401, nmps: 28, nlps: 25, switchFlag: 0},
+      {qe: 0x1201, nmps: 29, nlps: 26, switchFlag: 0},
+      {qe: 0x1101, nmps: 30, nlps: 27, switchFlag: 0},
+      {qe: 0x0AC1, nmps: 31, nlps: 28, switchFlag: 0},
+      {qe: 0x09C1, nmps: 32, nlps: 29, switchFlag: 0},
+      {qe: 0x08A1, nmps: 33, nlps: 30, switchFlag: 0},
+      {qe: 0x0521, nmps: 34, nlps: 31, switchFlag: 0},
+      {qe: 0x0441, nmps: 35, nlps: 32, switchFlag: 0},
+      {qe: 0x02A1, nmps: 36, nlps: 33, switchFlag: 0},
+      {qe: 0x0221, nmps: 37, nlps: 34, switchFlag: 0},
+      {qe: 0x0141, nmps: 38, nlps: 35, switchFlag: 0},
+      {qe: 0x0111, nmps: 39, nlps: 36, switchFlag: 0},
+      {qe: 0x0085, nmps: 40, nlps: 37, switchFlag: 0},
+      {qe: 0x0049, nmps: 41, nlps: 38, switchFlag: 0},
+      {qe: 0x0025, nmps: 42, nlps: 39, switchFlag: 0},
+      {qe: 0x0015, nmps: 43, nlps: 40, switchFlag: 0},
+      {qe: 0x0009, nmps: 44, nlps: 41, switchFlag: 0},
+      {qe: 0x0005, nmps: 45, nlps: 42, switchFlag: 0},
+      {qe: 0x0001, nmps: 45, nlps: 43, switchFlag: 0},
+      {qe: 0x5601, nmps: 46, nlps: 46, switchFlag: 0}
+    ];
+
+    function ArithmeticDecoder(data, start, end) {
+      this.data = data;
+      this.bp = start;
+      this.dataEnd = end;
+
+      this.chigh = data[start];
+      this.clow = 0;
+
+      this.byteIn();
+
+      this.chigh = ((this.chigh << 7) & 0xFFFF) | ((this.clow >> 9) & 0x7F);
+      this.clow = (this.clow << 7) & 0xFFFF;
+      this.ct -= 7;
+      this.a = 0x8000;
     }
-    var successiveACState = 0, successiveACNextValue;
-    function decodeACSuccessive(component, zz) {
-      var k = spectralStart, e = spectralEnd, r = 0;
-      while (k <= e) {
-        var z = dctZigZag[k];
-        switch (successiveACState) {
-        case 0: // initial state
-          var rs = decodeHuffman(component.huffmanTableAC);
-          var s = rs & 15, r = rs >> 4;
-          if (s === 0) {
-            if (r < 15) {
-              eobrun = receive(r) + (1 << r);
-              successiveACState = 4;
-            } else {
-              r = 16;
-              successiveACState = 1;
-            }
+
+    ArithmeticDecoder.prototype = {
+      byteIn: function ArithmeticDecoder_byteIn() {
+        var data = this.data;
+        var bp = this.bp;
+        if (data[bp] == 0xFF) {
+          var b1 = data[bp + 1];
+          if (b1 > 0x8F) {
+            this.clow += 0xFF00;
+            this.ct = 8;
           } else {
-            if (s !== 1)
-              throw "invalid ACn encoding";
-            successiveACNextValue = receiveAndExtend(s);
-            successiveACState = r ? 2 : 3;
+            bp++;
+            this.clow += (data[bp] << 9);
+            this.ct = 7;
+            this.bp = bp;
           }
-          continue;
-        case 1: // skipping r zero items
-        case 2:
-          if (zz[z])
-            zz[z] += (readBit() << successive);
-          else {
-            r--;
-            if (r === 0)
-              successiveACState = successiveACState == 2 ? 3 : 0;
+        } else {
+          bp++;
+          this.clow += bp < this.dataEnd ? (data[bp] << 8) : 0xFF00;
+          this.ct = 8;
+          this.bp = bp;
+        }
+        if (this.clow > 0xFFFF) {
+          this.chigh += (this.clow >> 16);
+          this.clow &= 0xFFFF;
+        }
+      },
+      readBit: function ArithmeticDecoder_readBit(cx) {
+        var qeIcx = QeTable[cx.index].qe;
+        this.a -= qeIcx;
+
+        if (this.chigh < qeIcx) {
+          var d = this.exchangeLps(cx);
+          this.renormD();
+          return d;
+        } else {
+          this.chigh -= qeIcx;
+          if ((this.a & 0x8000) == 0) {
+            var d = this.exchangeMps(cx);
+            this.renormD();
+            return d;
+          } else {
+            return cx.mps;
           }
-          break;
-        case 3: // set value for a zero item
-          if (zz[z])
-            zz[z] += (readBit() << successive);
-          else {
-            zz[z] = successiveACNextValue << successive;
-            successiveACState = 0;
+        }
+      },
+      renormD: function ArithmeticDecoder_renormD() {
+        do {
+          if (this.ct == 0)
+            this.byteIn();
+
+          this.a <<= 1;
+          this.chigh = ((this.chigh << 1) & 0xFFFF) | ((this.clow >> 15) & 1);
+          this.clow = (this.clow << 1) & 0xFFFF;
+          this.ct--;
+        } while ((this.a & 0x8000) == 0);
+      },
+      exchangeMps: function ArithmeticDecoder_exchangeMps(cx) {
+        var d;
+        var qeTableIcx = QeTable[cx.index];
+        if (this.a < qeTableIcx.qe) {
+          d = 1 - cx.mps;
+
+          if (qeTableIcx.switchFlag == 1) {
+            cx.mps = 1 - cx.mps;
           }
-          break;
-        case 4: // eob
-          if (zz[z])
-            zz[z] += (readBit() << successive);
-          break;
+          cx.index = qeTableIcx.nlps;
+        } else {
+          d = cx.mps;
+          cx.index = qeTableIcx.nmps;
         }
-        k++;
-      }
-      if (successiveACState === 4) {
-        eobrun--;
-        if (eobrun === 0)
-          successiveACState = 0;
+        return d;
+      },
+      exchangeLps: function ArithmeticDecoder_exchangeLps(cx) {
+        var d;
+        var qeTableIcx = QeTable[cx.index];
+        if (this.a < qeTableIcx.qe) {
+          this.a = qeTableIcx.qe;
+          d = cx.mps;
+          cx.index = qeTableIcx.nmps;
+        } else {
+          this.a = qeTableIcx.qe;
+          d = 1 - cx.mps;
+
+          if (qeTableIcx.switchFlag == 1) {
+            cx.mps = 1 - cx.mps;
+          }
+          cx.index = qeTableIcx.nlps;
+        }
+        return d;
       }
-    }
-    function decodeMcu(component, decode, mcu, row, col) {
-      var mcuRow = (mcu / mcusPerLine) | 0;
-      var mcuCol = mcu % mcusPerLine;
-      var blockRow = mcuRow * component.v + row;
-      var blockCol = mcuCol * component.h + col;
-      decode(component, component.blocks[blockRow][blockCol]);
-    }
-    function decodeBlock(component, decode, mcu) {
-      var blockRow = (mcu / component.blocksPerLine) | 0;
-      var blockCol = mcu % component.blocksPerLine;
-      decode(component, component.blocks[blockRow][blockCol]);
-    }
+    };
 
-    var componentsLength = components.length;
-    var component, i, j, k, n;
-    var decodeFn;
-    if (progressive) {
-      if (spectralStart === 0)
-        decodeFn = successivePrev === 0 ? decodeDCFirst : decodeDCSuccessive;
-      else
-        decodeFn = successivePrev === 0 ? decodeACFirst : decodeACSuccessive;
-    } else {
-      decodeFn = decodeBaseline;
+    return ArithmeticDecoder;
+  })();
+
+  // Section D. Coefficient bit modeling
+  var BitModel = (function BitModelClosure() {
+    // Table D-1
+    // The index is binary presentation: 0dddvvhh, ddd - sum of Di (0..4),
+    // vv - sum of Vi (0..2), and hh - sum of Hi (0..2)
+    var LLAndLHContextsLabel = new Uint8Array([
+      0, 5, 8, 0, 3, 7, 8, 0, 4, 7, 8, 0, 0, 0, 0, 0, 1, 6, 8, 0, 3, 7, 8, 0, 4,
+      7, 8, 0, 0, 0, 0, 0, 2, 6, 8, 0, 3, 7, 8, 0, 4, 7, 8, 0, 0, 0, 0, 0, 2, 6,
+      8, 0, 3, 7, 8, 0, 4, 7, 8, 0, 0, 0, 0, 0, 2, 6, 8, 0, 3, 7, 8, 0, 4, 7, 8
+    ]);
+    var HLContextLabel = new Uint8Array([
+      0, 3, 4, 0, 5, 7, 7, 0, 8, 8, 8, 0, 0, 0, 0, 0, 1, 3, 4, 0, 6, 7, 7, 0, 8,
+      8, 8, 0, 0, 0, 0, 0, 2, 3, 4, 0, 6, 7, 7, 0, 8, 8, 8, 0, 0, 0, 0, 0, 2, 3,
+      4, 0, 6, 7, 7, 0, 8, 8, 8, 0, 0, 0, 0, 0, 2, 3, 4, 0, 6, 7, 7, 0, 8, 8, 8
+    ]);
+    var HHContextLabel = new Uint8Array([
+      0, 1, 2, 0, 1, 2, 2, 0, 2, 2, 2, 0, 0, 0, 0, 0, 3, 4, 5, 0, 4, 5, 5, 0, 5,
+      5, 5, 0, 0, 0, 0, 0, 6, 7, 7, 0, 7, 7, 7, 0, 7, 7, 7, 0, 0, 0, 0, 0, 8, 8,
+      8, 0, 8, 8, 8, 0, 8, 8, 8, 0, 0, 0, 0, 0, 8, 8, 8, 0, 8, 8, 8, 0, 8, 8, 8
+    ]);
+
+    // Table D-2
+    function calcSignContribution(significance0, sign0, significance1, sign1) {
+      if (significance1) {
+        if (!sign1)
+          return significance0 ? (!sign0 ? 1 : 0) : 1;
+        else
+          return significance0 ? (!sign0 ? 0 : -1) : -1;
+      } else
+        return significance0 ? (!sign0 ? 1 : -1) : 0;
     }
+    // Table D-3
+    var SignContextLabels = [
+      {contextLabel: 13, xorBit: 0},
+      {contextLabel: 12, xorBit: 0},
+      {contextLabel: 11, xorBit: 0},
+      {contextLabel: 10, xorBit: 0},
+      {contextLabel: 9, xorBit: 0},
+      {contextLabel: 10, xorBit: 1},
+      {contextLabel: 11, xorBit: 1},
+      {contextLabel: 12, xorBit: 1},
+      {contextLabel: 13, xorBit: 1}
+    ];
 
-    var mcu = 0, marker;
-    var mcuExpected;
-    if (componentsLength == 1) {
-      mcuExpected = components[0].blocksPerLine * components[0].blocksPerColumn;
-    } else {
-      mcuExpected = mcusPerLine * frame.mcusPerColumn;
+    function BitModel(width, height, subband, zeroBitPlanes) {
+      this.width = width;
+      this.height = height;
+
+      this.contextLabelTable = subband == 'HH' ? HHContextLabel :
+        subband == 'HL' ? HLContextLabel : LLAndLHContextsLabel;
+
+      var coefficientCount = width * height;
+
+      // coefficients outside the encoding region treated as insignificant
+      // add border state cells for significanceState
+      this.neighborsSignificance = new Uint8Array(coefficientCount);
+      this.coefficentsSign = new Uint8Array(coefficientCount);
+      this.coefficentsMagnitude = new Uint32Array(coefficientCount);
+      this.processingFlags = new Uint8Array(coefficientCount);
+
+      var bitsDecoded = new Uint8Array(this.width * this.height);
+      for (var i = 0, ii = bitsDecoded.length; i < ii; i++)
+        bitsDecoded[i] = zeroBitPlanes;
+      this.bitsDecoded = bitsDecoded;
+
+      this.reset();
     }
-    if (!resetInterval) resetInterval = mcuExpected;
 
-    var h, v;
-    while (mcu < mcuExpected) {
-      // reset interval stuff
-      for (i = 0; i < componentsLength; i++)
-        components[i].pred = 0;
-      eobrun = 0;
+    BitModel.prototype = {
+      setDecoder: function BitModel_setDecoder(decoder) {
+        this.decoder = decoder;
+      },
+      reset: function BitModel_reset() {
+        this.uniformContext = {index: 46, mps: 0};
+        this.runLengthContext = {index: 3, mps: 0};
+        this.contexts = [];
+        this.contexts.push({index: 4, mps: 0});
+        for (var i = 1; i <= 16; i++)
+          this.contexts.push({index: 0, mps: 0});
+      },
+      setNeighborsSignificance:
+        function BitModel_setNeighborsSignificance(row, column) {
+        var neighborsSignificance = this.neighborsSignificance;
+        var width = this.width, height = this.height;
+        var index = row * width + column;
+        if (row > 0) {
+          if (column > 0)
+            neighborsSignificance[index - width - 1] += 0x10;
+          if (column + 1 < width)
+            neighborsSignificance[index - width + 1] += 0x10;
+          neighborsSignificance[index - width] += 0x04;
+        }
+        if (row + 1 < height) {
+          if (column > 0)
+            neighborsSignificance[index + width - 1] += 0x10;
+          if (column + 1 < width)
+            neighborsSignificance[index + width + 1] += 0x10;
+          neighborsSignificance[index + width] += 0x04;
+        }
+        if (column > 0)
+          neighborsSignificance[index - 1] += 0x01;
+        if (column + 1 < width)
+          neighborsSignificance[index + 1] += 0x01;
+        neighborsSignificance[index] |= 0x80;
+      },
+      runSignificancePropogationPass:
+        function BitModel_runSignificancePropogationPass() {
+        var decoder = this.decoder;
+        var width = this.width, height = this.height;
+        var coefficentsMagnitude = this.coefficentsMagnitude;
+        var coefficentsSign = this.coefficentsSign;
+        var contextLabels = this.contextLabels;
+        var neighborsSignificance = this.neighborsSignificance;
+        var processingFlags = this.processingFlags;
+        var contexts = this.contexts;
+        var labels = this.contextLabelTable;
+        var bitsDecoded = this.bitsDecoded;
+        // clear processed flag
+        var processedInverseMask = ~1;
+        var processedMask = 1;
+        var firstMagnitudeBitMask = 2;
+        for (var q = 0, qq = width * height; q < qq; q++)
+          processingFlags[q] &= processedInverseMask;
+
+        for (var i0 = 0; i0 < height; i0 += 4) {
+          for (var j = 0; j < width; j++) {
+            var index = i0 * width + j;
+            for (var i1 = 0; i1 < 4; i1++, index += width) {
+              var i = i0 + i1;
+              if (i >= height)
+                break;
 
-      if (componentsLength == 1) {
-        component = components[0];
-        for (n = 0; n < resetInterval; n++) {
-          decodeBlock(component, decodeFn, mcu);
-          mcu++;
+              if (coefficentsMagnitude[index] || !neighborsSignificance[index])
+                continue;
+
+              var contextLabel = labels[neighborsSignificance[index]];
+              var cx = contexts[contextLabel];
+              var decision = decoder.readBit(cx);
+              if (decision) {
+                var sign = this.decodeSignBit(i, j);
+                coefficentsSign[index] = sign;
+                coefficentsMagnitude[index] = 1;
+                this.setNeighborsSignificance(i, j);
+                processingFlags[index] |= firstMagnitudeBitMask;
+              }
+              bitsDecoded[index]++;
+              processingFlags[index] |= processedMask;
+            }
+          }
         }
-      } else {
-        for (n = 0; n < resetInterval; n++) {
-          for (i = 0; i < componentsLength; i++) {
-            component = components[i];
-            h = component.h;
-            v = component.v;
-            for (j = 0; j < v; j++) {
-              for (k = 0; k < h; k++) {
-                decodeMcu(component, decodeFn, mcu, j, k);
+      },
+      decodeSignBit: function BitModel_decodeSignBit(row, column) {
+        var width = this.width, height = this.height;
+        var index = row * width + column;
+        var coefficentsMagnitude = this.coefficentsMagnitude;
+        var coefficentsSign = this.coefficentsSign;
+        var horizontalContribution = calcSignContribution(
+          column > 0 && coefficentsMagnitude[index - 1],
+          coefficentsSign[index - 1],
+          column + 1 < width && coefficentsMagnitude[index + 1],
+          coefficentsSign[index + 1]);
+        var verticalContribution = calcSignContribution(
+          row > 0 && coefficentsMagnitude[index - width],
+          coefficentsSign[index - width],
+          row + 1 < height && coefficentsMagnitude[index + width],
+          coefficentsSign[index + width]);
+
+        var contextLabelAndXor = SignContextLabels[
+          3 * (1 - horizontalContribution) + (1 - verticalContribution)];
+        var contextLabel = contextLabelAndXor.contextLabel;
+        var cx = this.contexts[contextLabel];
+        var decoded = this.decoder.readBit(cx);
+        return decoded ^ contextLabelAndXor.xorBit;
+      },
+      runMagnitudeRefinementPass:
+        function BitModel_runMagnitudeRefinementPass() {
+        var decoder = this.decoder;
+        var width = this.width, height = this.height;
+        var coefficentsMagnitude = this.coefficentsMagnitude;
+        var neighborsSignificance = this.neighborsSignificance;
+        var contexts = this.contexts;
+        var bitsDecoded = this.bitsDecoded;
+        var processingFlags = this.processingFlags;
+        var processedMask = 1;
+        var firstMagnitudeBitMask = 2;
+        for (var i0 = 0; i0 < height; i0 += 4) {
+          for (var j = 0; j < width; j++) {
+            for (var i1 = 0; i1 < 4; i1++) {
+              var i = i0 + i1;
+              if (i >= height)
+                break;
+              var index = i * width + j;
+
+              // significant but not those that have just become
+              if (!coefficentsMagnitude[index] ||
+                (processingFlags[index] & processedMask) != 0)
+                continue;
+
+              var contextLabel = 16;
+              if ((processingFlags[index] &
+                firstMagnitudeBitMask) != 0) {
+                processingFlags[i * width + j] ^= firstMagnitudeBitMask;
+                // first refinement
+                var significance = neighborsSignificance[index];
+                var sumOfSignificance = (significance & 3) +
+                  ((significance >> 2) & 3) + ((significance >> 4) & 7);
+                contextLabel = sumOfSignificance >= 1 ? 15 : 14;
               }
+
+              var cx = contexts[contextLabel];
+              var bit = decoder.readBit(cx);
+              coefficentsMagnitude[index] =
+                (coefficentsMagnitude[index] << 1) | bit;
+              bitsDecoded[index]++;
+              processingFlags[index] |= processedMask;
             }
           }
-          mcu++;
         }
-      }
+      },
+      runCleanupPass: function BitModel_runCleanupPass() {
+        var decoder = this.decoder;
+        var width = this.width, height = this.height;
+        var neighborsSignificance = this.neighborsSignificance;
+        var significanceState = this.significanceState;
+        var coefficentsMagnitude = this.coefficentsMagnitude;
+        var coefficentsSign = this.coefficentsSign;
+        var contexts = this.contexts;
+        var labels = this.contextLabelTable;
+        var bitsDecoded = this.bitsDecoded;
+        var processingFlags = this.processingFlags;
+        var processedMask = 1;
+        var firstMagnitudeBitMask = 2;
+        var oneRowDown = width;
+        var twoRowsDown = width * 2;
+        var threeRowsDown = width * 3;
+        for (var i0 = 0; i0 < height; i0 += 4) {
+          for (var j = 0; j < width; j++) {
+            var index0 = i0 * width + j;
+            // using the property: labels[neighborsSignificance[index]] == 0
+            // when neighborsSignificance[index] == 0
+            var allEmpty = i0 + 3 < height &&
+              processingFlags[index0] == 0 &&
+              processingFlags[index0 + oneRowDown] == 0 &&
+              processingFlags[index0 + twoRowsDown] == 0 &&
+              processingFlags[index0 + threeRowsDown] == 0 &&
+              neighborsSignificance[index0] == 0 &&
+              neighborsSignificance[index0 + oneRowDown] == 0 &&
+              neighborsSignificance[index0 + twoRowsDown] == 0 &&
+              neighborsSignificance[index0 + threeRowsDown] == 0;
+            var i1 = 0, index = index0;
+            var cx, i;
+            if (allEmpty) {
+              cx = this.runLengthContext;
+              var hasSignificantCoefficent = decoder.readBit(cx);
+              if (!hasSignificantCoefficent) {
+                bitsDecoded[index0]++;
+                bitsDecoded[index0 + oneRowDown]++;
+                bitsDecoded[index0 + twoRowsDown]++;
+                bitsDecoded[index0 + threeRowsDown]++;
+                continue; // next column
+              }
+              cx = this.uniformContext;
+              i1 = (decoder.readBit(cx) << 1) | decoder.readBit(cx);
+              i = i0 + i1;
+              index += i1 * width;
+
+              var sign = this.decodeSignBit(i, j);
+              coefficentsSign[index] = sign;
+              coefficentsMagnitude[index] = 1;
+              this.setNeighborsSignificance(i, j);
+              processingFlags[index] |= firstMagnitudeBitMask;
+
+              index = index0;
+              for (var i2 = i0; i2 <= i; i2++, index += width)
+                bitsDecoded[index]++;
+
+              i1++;
+            }
+            for (; i1 < 4; i1++, index += width) {
+              i = i0 + i1;
+              if (i >= height)
+                break;
 
-      // find marker
-      bitsCount = 0;
-      marker = (data[offset] << 8) | data[offset + 1];
-      if (marker <= 0xFF00) {
-        throw "marker was not found";
+              if (coefficentsMagnitude[index] ||
+                (processingFlags[index] & processedMask) != 0)
+                continue;
+
+              var contextLabel = labels[neighborsSignificance[index]];
+              cx = contexts[contextLabel];
+              var decision = decoder.readBit(cx);
+              if (decision == 1) {
+                var sign = this.decodeSignBit(i, j);
+                coefficentsSign[index] = sign;
+                coefficentsMagnitude[index] = 1;
+                this.setNeighborsSignificance(i, j);
+                processingFlags[index] |= firstMagnitudeBitMask;
+              }
+              bitsDecoded[index]++;
+            }
+          }
+        }
       }
+    };
 
-      if (marker >= 0xFFD0 && marker <= 0xFFD7) { // RSTx
-        offset += 2;
+    return BitModel;
+  })();
+
+  // Section F, Discrete wavelet transofrmation
+  var Transform = (function TransformClosure() {
+    function Transform() {
+    }
+    Transform.prototype.calculate =
+      function transformCalculate(subbands, u0, v0) {
+      var ll = subbands[0];
+      for (var i = 1, ii = subbands.length, j = 1; i < ii; i += 3, j++) {
+        ll = this.iterate(ll, subbands[i], subbands[i + 1],
+                          subbands[i + 2], u0, v0);
+      }
+      return ll;
+    };
+    Transform.prototype.iterate = function Transform_iterate(ll, hl, lh, hh,
+                                                            u0, v0) {
+      var llWidth = ll.width, llHeight = ll.height, llItems = ll.items;
+      var hlWidth = hl.width, hlHeight = hl.height, hlItems = hl.items;
+      var lhWidth = lh.width, lhHeight = lh.height, lhItems = lh.items;
+      var hhWidth = hh.width, hhHeight = hh.height, hhItems = hh.items;
+
+      // Section F.3.3 interleave
+      var width = llWidth + hlWidth;
+      var height = llHeight + lhHeight;
+      var items = new Float32Array(width * height);
+      for (var i = 0, ii = llHeight; i < ii; i++) {
+        var k = i * llWidth, l = i * 2 * width;
+        for (var j = 0, jj = llWidth; j < jj; j++, k++, l += 2)
+          items[l] = llItems[k];
+      }
+      for (var i = 0, ii = hlHeight; i < ii; i++) {
+        var k = i * hlWidth, l = i * 2 * width + 1;
+        for (var j = 0, jj = hlWidth; j < jj; j++, k++, l += 2)
+          items[l] = hlItems[k];
+      }
+      for (var i = 0, ii = lhHeight; i < ii; i++) {
+        var k = i * lhWidth, l = (i * 2 + 1) * width;
+        for (var j = 0, jj = lhWidth; j < jj; j++, k++, l += 2)
+          items[l] = lhItems[k];
+      }
+      for (var i = 0, ii = hhHeight; i < ii; i++) {
+        var k = i * hhWidth, l = (i * 2 + 1) * width + 1;
+        for (var j = 0, jj = hhWidth; j < jj; j++, k++, l += 2)
+          items[l] = hhItems[k];
+      }
+
+      var bufferPadding = 4;
+      var bufferLength = new Float32Array(Math.max(width, height) +
+        2 * bufferPadding);
+      var buffer = new Float32Array(bufferLength);
+      var bufferOut = new Float32Array(bufferLength);
+
+      // Section F.3.4 HOR_SR
+      for (var v = 0; v < height; v++) {
+        if (width == 1) {
+          // if width = 1, when u0 even keep items as is, when odd divide by 2
+          if ((u0 % 1) != 0) {
+            items[v * width] /= 2;
+          }
+          continue;
+        }
+
+        var k = v * width;
+        var l = bufferPadding;
+        for (var u = 0; u < width; u++, k++, l++)
+          buffer[l] = items[k];
+
+        // Section F.3.7 extending... using max extension of 4
+        var i1 = bufferPadding - 1, j1 = bufferPadding + 1;
+        var i2 = bufferPadding + width - 2, j2 = bufferPadding + width;
+        buffer[i1--] = buffer[j1++];
+        buffer[j2++] = buffer[i2--];
+        buffer[i1--] = buffer[j1++];
+        buffer[j2++] = buffer[i2--];
+        buffer[i1--] = buffer[j1++];
+        buffer[j2++] = buffer[i2--];
+        buffer[i1--] = buffer[j1++];
+        buffer[j2++] = buffer[i2--];
+
+        this.filter(buffer, bufferPadding, width, u0, bufferOut);
+
+        k = v * width;
+        l = bufferPadding;
+        for (var u = 0; u < width; u++, k++, l++)
+          items[k] = bufferOut[l];
+      }
+
+      // Section F.3.5 VER_SR
+      for (var u = 0; u < width; u++) {
+        if (height == 1) {
+          // if height = 1, when v0 even keep items as is, when odd divide by 2
+          if ((v0 % 1) != 0) {
+            items[u] /= 2;
+          }
+          continue;
+        }
+
+        var k = u;
+        var l = bufferPadding;
+        for (var v = 0; v < height; v++, k += width, l++)
+          buffer[l] = items[k];
+
+        // Section F.3.7 extending... using max extension of 4
+        var i1 = bufferPadding - 1, j1 = bufferPadding + 1;
+        var i2 = bufferPadding + height - 2, j2 = bufferPadding + height;
+        buffer[i1--] = buffer[j1++];
+        buffer[j2++] = buffer[i2--];
+        buffer[i1--] = buffer[j1++];
+        buffer[j2++] = buffer[i2--];
+        buffer[i1--] = buffer[j1++];
+        buffer[j2++] = buffer[i2--];
+        buffer[i1--] = buffer[j1++];
+        buffer[j2++] = buffer[i2--];
+
+        this.filter(buffer, bufferPadding, height, v0, bufferOut);
+
+        k = u;
+        l = bufferPadding;
+        for (var v = 0; v < height; v++, k += width, l++)
+          items[k] = bufferOut[l];
       }
-      else
-        break;
+      return {
+        width: width,
+        height: height,
+        items: items
+      };
+    };
+    return Transform;
+  })();
+
+  // Section 3.8.2 Irreversible 9-7 filter
+  var IrreversibleTransform = (function IrreversibleTransformClosure() {
+    function IrreversibleTransform() {
+      Transform.call(this);
     }
 
-    return offset - startOffset;
-  }
+    IrreversibleTransform.prototype = Object.create(Transform.prototype);
+    IrreversibleTransform.prototype.filter =
+      function irreversibleTransformFilter(y, offset, length, i0, x) {
+      var i0_ = Math.floor(i0 / 2);
+      var i1_ = Math.floor((i0 + length) / 2);
+      var offset_ = offset - (i0 % 1);
+
+      var alpha = -1.586134342059924;
+      var beta = -0.052980118572961;
+      var gamma = 0.882911075530934;
+      var delta = 0.443506852043971;
+      var K = 1.230174104914001;
+      var K_ = 1 / K;
+
+      // step 1
+      var j = offset_ - 2;
+      for (var n = i0_ - 1, nn = i1_ + 2; n < nn; n++, j += 2)
+        x[j] = K * y[j];
+
+      // step 2
+      var j = offset_ - 3;
+      for (var n = i0_ - 2, nn = i1_ + 2; n < nn; n++, j += 2)
+        x[j] = K_ * y[j];
+
+      // step 3
+      var j = offset_ - 2;
+      for (var n = i0_ - 1, nn = i1_ + 2; n < nn; n++, j += 2)
+        x[j] -= delta * (x[j - 1] + x[j + 1]);
+
+      // step 4
+      var j = offset_ - 1;
+      for (var n = i0_ - 1, nn = i1_ + 1; n < nn; n++, j += 2)
+        x[j] -= gamma * (x[j - 1] + x[j + 1]);
+
+      // step 5
+      var j = offset_;
+      for (var n = i0_, nn = i1_ + 1; n < nn; n++, j += 2)
+        x[j] -= beta * (x[j - 1] + x[j + 1]);
+
+      // step 6
+      var j = offset_ + 1;
+      for (var n = i0_, nn = i1_; n < nn; n++, j += 2)
+        x[j] -= alpha * (x[j - 1] + x[j + 1]);
+    };
 
-  function buildComponentData(frame, component) {
-    var lines = [];
-    var blocksPerLine = component.blocksPerLine;
-    var blocksPerColumn = component.blocksPerColumn;
-    var samplesPerLine = blocksPerLine << 3;
-    var R = new Int32Array(64), r = new Uint8Array(64);
+    return IrreversibleTransform;
+  })();
 
-    // A port of poppler's IDCT method which in turn is taken from:
-    //   Christoph Loeffler, Adriaan Ligtenberg, George S. Moschytz,
-    //   "Practical Fast 1-D DCT Algorithms with 11 Multiplications",
-    //   IEEE Intl. Conf. on Acoustics, Speech & Signal Processing, 1989,
-    //   988-991.
-    function quantizeAndInverse(zz, dataOut, dataIn) {
-      var qt = component.quantizationTable;
-      var v0, v1, v2, v3, v4, v5, v6, v7, t;
-      var p = dataIn;
-      var i;
+  // Section 3.8.1 Reversible 5-3 filter
+  var ReversibleTransform = (function ReversibleTransformClosure() {
+    function ReversibleTransform() {
+      Transform.call(this);
+    }
 
-      // dequant
-      for (i = 0; i < 64; i++)
-        p[i] = zz[i] * qt[i];
+    ReversibleTransform.prototype = Object.create(Transform.prototype);
+    ReversibleTransform.prototype.filter =
+      function reversibleTransformFilter(y, offset, length, i0, x) {
+      var i0_ = Math.floor(i0 / 2);
+      var i1_ = Math.floor((i0 + length) / 2);
+      var offset_ = offset - (i0 % 1);
 
-      // inverse DCT on rows
-      for (i = 0; i < 8; ++i) {
-        var row = 8 * i;
+      for (var n = i0_, nn = i1_ + 1, j = offset_; n < nn; n++, j += 2)
+        x[j] = y[j] - Math.floor((y[j - 1] + y[j + 1] + 2) / 4);
 
-        // check for all-zero AC coefficients
-        if (p[1 + row] == 0 && p[2 + row] == 0 && p[3 + row] == 0 &&
-            p[4 + row] == 0 && p[5 + row] == 0 && p[6 + row] == 0 &&
-            p[7 + row] == 0) {
-          t = (dctSqrt2 * p[0 + row] + 512) >> 10;
-          p[0 + row] = t;
-          p[1 + row] = t;
-          p[2 + row] = t;
-          p[3 + row] = t;
-          p[4 + row] = t;
-          p[5 + row] = t;
-          p[6 + row] = t;
-          p[7 + row] = t;
-          continue;
-        }
+      for (var n = i0_, nn = i1_, j = offset_ + 1; n < nn; n++, j += 2)
+        x[j] = y[j] + Math.floor((x[j - 1] + x[j + 1]) / 2);
+    };
 
-        // stage 4
-        v0 = (dctSqrt2 * p[0 + row] + 128) >> 8;
-        v1 = (dctSqrt2 * p[4 + row] + 128) >> 8;
-        v2 = p[2 + row];
-        v3 = p[6 + row];
-        v4 = (dctSqrt1d2 * (p[1 + row] - p[7 + row]) + 128) >> 8;
-        v7 = (dctSqrt1d2 * (p[1 + row] + p[7 + row]) + 128) >> 8;
-        v5 = p[3 + row] << 4;
-        v6 = p[5 + row] << 4;
+    return ReversibleTransform;
+  })();
 
-        // stage 3
-        t = (v0 - v1+ 1) >> 1;
-        v0 = (v0 + v1 + 1) >> 1;
-        v1 = t;
-        t = (v2 * dctSin6 + v3 * dctCos6 + 128) >> 8;
-        v2 = (v2 * dctCos6 - v3 * dctSin6 + 128) >> 8;
-        v3 = t;
-        t = (v4 - v6 + 1) >> 1;
-        v4 = (v4 + v6 + 1) >> 1;
-        v6 = t;
-        t = (v7 + v5 + 1) >> 1;
-        v5 = (v7 - v5 + 1) >> 1;
-        v7 = t;
+  return JpxImage;
+})();
 
-        // stage 2
-        t = (v0 - v3 + 1) >> 1;
-        v0 = (v0 + v3 + 1) >> 1;
-        v3 = t;
-        t = (v1 - v2 + 1) >> 1;
-        v1 = (v1 + v2 + 1) >> 1;
-        v2 = t;
-        t = (v4 * dctSin3 + v7 * dctCos3 + 2048) >> 12;
-        v4 = (v4 * dctCos3 - v7 * dctSin3 + 2048) >> 12;
-        v7 = t;
-        t = (v5 * dctSin1 + v6 * dctCos1 + 2048) >> 12;
-        v5 = (v5 * dctCos1 - v6 * dctSin1 + 2048) >> 12;
-        v6 = t;
+/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
 
-        // stage 1
-        p[0 + row] = v0 + v7;
-        p[7 + row] = v0 - v7;
-        p[1 + row] = v1 + v6;
-        p[6 + row] = v1 - v6;
-        p[2 + row] = v2 + v5;
-        p[5 + row] = v2 - v5;
-        p[3 + row] = v3 + v4;
-        p[4 + row] = v3 - v4;
-      }
+'use strict';
 
-      // inverse DCT on columns
-      for (i = 0; i < 8; ++i) {
-        var col = i;
+var bidi = PDFJS.bidi = (function bidiClosure() {
+  // Character types for symbols from 0000 to 00FF.
+  var baseTypes = [
+    'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'S', 'B', 'S', 'WS',
+    'B', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN',
+    'BN', 'BN', 'B', 'B', 'B', 'S', 'WS', 'ON', 'ON', 'ET', 'ET', 'ET', 'ON',
+    'ON', 'ON', 'ON', 'ON', 'ON', 'CS', 'ON', 'CS', 'ON', 'EN', 'EN', 'EN',
+    'EN', 'EN', 'EN', 'EN', 'EN', 'EN', 'EN', 'ON', 'ON', 'ON', 'ON', 'ON',
+    'ON', 'ON', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L',
+    'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'ON', 'ON',
+    'ON', 'ON', 'ON', 'ON', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L',
+    'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L',
+    'L', 'ON', 'ON', 'ON', 'ON', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'B', 'BN',
+    'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN',
+    'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN',
+    'BN', 'CS', 'ON', 'ET', 'ET', 'ET', 'ET', 'ON', 'ON', 'ON', 'ON', 'L', 'ON',
+    'ON', 'ON', 'ON', 'ON', 'ET', 'ET', 'EN', 'EN', 'ON', 'L', 'ON', 'ON', 'ON',
+    'EN', 'L', 'ON', 'ON', 'ON', 'ON', 'ON', 'L', 'L', 'L', 'L', 'L', 'L', 'L',
+    'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L',
+    'L', 'ON', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L',
+    'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L',
+    'L', 'L', 'L', 'ON', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L'
+  ];
 
-        // check for all-zero AC coefficients
-        if (p[1*8 + col] == 0 && p[2*8 + col] == 0 && p[3*8 + col] == 0 &&
-            p[4*8 + col] == 0 && p[5*8 + col] == 0 && p[6*8 + col] == 0 &&
-            p[7*8 + col] == 0) {
-          t = (dctSqrt2 * dataIn[i+0] + 8192) >> 14;
-          p[0*8 + col] = t;
-          p[1*8 + col] = t;
-          p[2*8 + col] = t;
-          p[3*8 + col] = t;
-          p[4*8 + col] = t;
-          p[5*8 + col] = t;
-          p[6*8 + col] = t;
-          p[7*8 + col] = t;
-          continue;
-        }
+  // Character types for symbols from 0600 to 06FF
+  var arabicTypes = [
+    'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL',
+    'CS', 'AL', 'ON', 'ON', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'AL',
+    'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL',
+    'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL',
+    'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL',
+    'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL',
+    'AL', 'AL', 'AL', 'AL', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM',
+    'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'AL', 'AL', 'AL', 'AL',
+    'AL', 'AL', 'AL', 'AN', 'AN', 'AN', 'AN', 'AN', 'AN', 'AN', 'AN', 'AN',
+    'AN', 'ET', 'AN', 'AN', 'AL', 'AL', 'AL', 'NSM', 'AL', 'AL', 'AL', 'AL',
+    'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL',
+    'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL',
+    'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL',
+    'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL',
+    'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL',
+    'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL',
+    'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL',
+    'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL',
+    'AL', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM',
+    'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'ON', 'NSM',
+    'NSM', 'NSM', 'NSM', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL',
+    'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL'
+  ];
 
-        // stage 4
-        v0 = (dctSqrt2 * p[0*8 + col] + 2048) >> 12;
-        v1 = (dctSqrt2 * p[4*8 + col] + 2048) >> 12;
-        v2 = p[2*8 + col];
-        v3 = p[6*8 + col];
-        v4 = (dctSqrt1d2 * (p[1*8 + col] - p[7*8 + col]) + 2048) >> 12;
-        v7 = (dctSqrt1d2 * (p[1*8 + col] + p[7*8 + col]) + 2048) >> 12;
-        v5 = p[3*8 + col];
-        v6 = p[5*8 + col];
+  function isOdd(i) {
+    return (i & 1) != 0;
+  }
+
+  function isEven(i) {
+    return (i & 1) == 0;
+  }
+
+  function findUnequal(arr, start, value) {
+    var j;
+    for (var j = start, jj = arr.length; j < jj; ++j) {
+      if (arr[j] != value)
+        return j;
+    }
+    return j;
+  }
+
+  function setValues(arr, start, end, value) {
+    for (var j = start; j < end; ++j) {
+      arr[j] = value;
+    }
+  }
+
+  function reverseValues(arr, start, end) {
+    for (var i = start, j = end - 1; i < j; ++i, --j) {
+      var temp = arr[i];
+      arr[i] = arr[j];
+      arr[j] = temp;
+    }
+  }
+
+  function mirrorGlyphs(c) {
+    /*
+     # BidiMirroring-1.txt
+     0028; 0029 # LEFT PARENTHESIS
+     0029; 0028 # RIGHT PARENTHESIS
+     003C; 003E # LESS-THAN SIGN
+     003E; 003C # GREATER-THAN SIGN
+     005B; 005D # LEFT SQUARE BRACKET
+     005D; 005B # RIGHT SQUARE BRACKET
+     007B; 007D # LEFT CURLY BRACKET
+     007D; 007B # RIGHT CURLY BRACKET
+     00AB; 00BB # LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+     00BB; 00AB # RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+     */
+    switch (c) {
+      case '(':
+        return ')';
+      case ')':
+        return '(';
+      case '<':
+        return '>';
+      case '>':
+        return '<';
+      case ']':
+        return '[';
+      case '[':
+        return ']';
+      case '}':
+        return '{';
+      case '{':
+        return '}';
+      case '\u00AB':
+        return '\u00BB';
+      case '\u00BB':
+        return '\u00AB';
+      default:
+        return c;
+    }
+  }
+
+  function bidi(text, startLevel) {
+    var str = text.str;
+    var strLength = str.length;
+    if (strLength == 0)
+      return str;
+
+    // get types, fill arrays
+
+    var chars = [];
+    var types = [];
+    var oldtypes = [];
+    var numBidi = 0;
+
+    for (var i = 0; i < strLength; ++i) {
+      chars[i] = str.charAt(i);
+
+      var charCode = str.charCodeAt(i);
+      var charType = 'L';
+      if (charCode <= 0x00ff)
+        charType = baseTypes[charCode];
+      else if (0x0590 <= charCode && charCode <= 0x05f4)
+        charType = 'R';
+      else if (0x0600 <= charCode && charCode <= 0x06ff)
+        charType = arabicTypes[charCode & 0xff];
+      else if (0x0700 <= charCode && charCode <= 0x08AC)
+        charType = 'AL';
+
+      if (charType == 'R' || charType == 'AL' || charType == 'AN')
+        numBidi++;
 
-        // stage 3
-        t = (v0 - v1 + 1) >> 1;
-        v0 = (v0 + v1 + 1) >> 1;
-        v1 = t;
-        t = (v2 * dctSin6 + v3 * dctCos6 + 2048) >> 12;
-        v2 = (v2 * dctCos6 - v3 * dctSin6 + 2048) >> 12;
-        v3 = t;
-        t = (v4 - v6 + 1) >> 1;
-        v4 = (v4 + v6 + 1) >> 1;
-        v6 = t;
-        t = (v7 + v5 + 1) >> 1;
-        v5 = (v7 - v5 + 1) >> 1;
-        v7 = t;
+      oldtypes[i] = types[i] = charType;
+    }
 
-        // stage 2
-        t = (v0 - v3 + 1) >> 1;
-        v0 = (v0 + v3 + 1) >> 1;
-        v3 = t;
-        t = (v1 - v2 + 1) >> 1;
-        v1 = (v1 + v2 + 1) >> 1;
-        v2 = t;
-        t = (v4 * dctSin3 + v7 * dctCos3 + 2048) >> 12;
-        v4 = (v4 * dctCos3 - v7 * dctSin3 + 2048) >> 12;
-        v7 = t;
-        t = (v5 * dctSin1 + v6 * dctCos1 + 2048) >> 12;
-        v5 = (v5 * dctCos1 - v6 * dctSin1 + 2048) >> 12;
-        v6 = t;
+    // detect the bidi method
+    //  if there are no rtl characters then no bidi needed
+    //  if less than 30% chars are rtl then string is primarily ltr
+    //  if more than 30% chars are rtl then string is primarily rtl
+    if (numBidi == 0) {
+      text.direction = 'ltr';
+      return str;
+    }
 
-        // stage 1
-        p[0*8 + col] = v0 + v7;
-        p[7*8 + col] = v0 - v7;
-        p[1*8 + col] = v1 + v6;
-        p[6*8 + col] = v1 - v6;
-        p[2*8 + col] = v2 + v5;
-        p[5*8 + col] = v2 - v5;
-        p[3*8 + col] = v3 + v4;
-        p[4*8 + col] = v3 - v4;
+    if (startLevel == -1) {
+      if ((strLength / numBidi) < 0.3) {
+        text.direction = 'ltr';
+        startLevel = 0;
+      } else {
+        text.direction = 'rtl';
+        startLevel = 1;
       }
+    }
 
-      // convert to 8-bit integers
-      for (i = 0; i < 64; ++i) {
-        var sample = 128 + ((p[i] + 8) >> 4);
-        dataOut[i] = sample < 0 ? 0 : sample > 0xFF ? 0xFF : sample;
-      }
+    var levels = [];
+
+    for (var i = 0; i < strLength; ++i) {
+      levels[i] = startLevel;
     }
 
-    var i, j;
-    for (var blockRow = 0; blockRow < blocksPerColumn; blockRow++) {
-      var scanLine = blockRow << 3;
-      for (i = 0; i < 8; i++)
-        lines.push(new Uint8Array(samplesPerLine));
-      for (var blockCol = 0; blockCol < blocksPerLine; blockCol++) {
-        quantizeAndInverse(component.blocks[blockRow][blockCol], r, R);
+    /*
+     X1-X10: skip most of this, since we are NOT doing the embeddings.
+     */
 
-        var offset = 0, sample = blockCol << 3;
-        for (j = 0; j < 8; j++) {
-          var line = lines[scanLine + j];
-          for (i = 0; i < 8; i++)
-            line[sample + i] = r[offset++];
-        }
-      }
+    var e = isOdd(startLevel) ? 'R' : 'L';
+    var sor = e;
+    var eor = sor;
+
+    /*
+     W1. Examine each non-spacing mark (NSM) in the level run, and change the
+     type of the NSM to the type of the previous character. If the NSM is at the
+     start of the level run, it will get the type of sor.
+     */
+
+    var lastType = sor;
+    for (var i = 0; i < strLength; ++i) {
+      if (types[i] == 'NSM')
+        types[i] = lastType;
+      else
+        lastType = types[i];
     }
-    return lines;
-  }
 
-  constructor.prototype = {
-    load: function load(path) {
-      var xhr = new XMLHttpRequest();
-      xhr.open("GET", path, true);
-      xhr.responseType = "arraybuffer";
-      xhr.onload = (function() {
-        // TODO catch parse error
-        var data = new Uint8Array(xhr.response || xhr.mozResponseArrayBuffer);
-        this.parse(data);
-        if (this.onload)
-          this.onload();
-      }).bind(this);
-      xhr.send(null);
-    },
-    parse: function parse(data) {
-      var offset = 0, length = data.length;
-      function readUint16() {
-        var value = (data[offset] << 8) | data[offset + 1];
-        offset += 2;
-        return value;
-      }
-      function readDataBlock() {
-        var length = readUint16();
-        var array = data.subarray(offset, offset + length - 2);
-        offset += array.length;
-        return array;
-      }
-      function prepareComponents(frame) {
-        var maxH = 0, maxV = 0;
-        var component, componentId;
-        for (componentId in frame.components) {
-          if (frame.components.hasOwnProperty(componentId)) {
-            component = frame.components[componentId];
-            if (maxH < component.h) maxH = component.h;
-            if (maxV < component.v) maxV = component.v;
-          }
+    /*
+     W2. Search backwards from each instance of a European number until the
+     first strong type (R, L, AL, or sor) is found.  If an AL is found, change
+     the type of the European number to Arabic number.
+     */
+
+    var lastType = sor;
+    for (var i = 0; i < strLength; ++i) {
+      var t = types[i];
+      if (t == 'EN')
+        types[i] = (lastType == 'AL') ? 'AN' : 'EN';
+      else if (t == 'R' || t == 'L' || t == 'AL')
+        lastType = t;
+    }
+
+    /*
+     W3. Change all ALs to R.
+     */
+
+    for (var i = 0; i < strLength; ++i) {
+      var t = types[i];
+      if (t == 'AL')
+        types[i] = 'R';
+    }
+
+    /*
+     W4. A single European separator between two European numbers changes to a
+     European number. A single common separator between two numbers of the same
+     type changes to that type:
+     */
+
+    for (var i = 1; i < strLength - 1; ++i) {
+      if (types[i] == 'ES' && types[i - 1] == 'EN' && types[i + 1] == 'EN')
+        types[i] = 'EN';
+      if (types[i] == 'CS' && (types[i - 1] == 'EN' || types[i - 1] == 'AN') &&
+          types[i + 1] == types[i - 1])
+        types[i] = types[i - 1];
+    }
+
+    /*
+     W5. A sequence of European terminators adjacent to European numbers changes
+     to all European numbers:
+     */
+
+    for (var i = 0; i < strLength; ++i) {
+      if (types[i] == 'EN') {
+        // do before
+        for (var j = i - 1; j >= 0; --j) {
+          if (types[j] != 'ET')
+            break;
+          types[j] = 'EN';
         }
-        var mcusPerLine = Math.ceil(frame.samplesPerLine / 8 / maxH);
-        var mcusPerColumn = Math.ceil(frame.scanLines / 8 / maxV);
-        for (componentId in frame.components) {
-          if (frame.components.hasOwnProperty(componentId)) {
-            component = frame.components[componentId];
-            var blocksPerLine = Math.ceil(Math.ceil(frame.samplesPerLine / 8) * component.h / maxH);
-            var blocksPerColumn = Math.ceil(Math.ceil(frame.scanLines  / 8) * component.v / maxV);
-            var blocksPerLineForMcu = mcusPerLine * component.h;
-            var blocksPerColumnForMcu = mcusPerColumn * component.v;
-            var blocks = [];
-            for (var i = 0; i < blocksPerColumnForMcu; i++) {
-              var row = [];
-              for (var j = 0; j < blocksPerLineForMcu; j++)
-                row.push(new Int32Array(64));
-              blocks.push(row);
-            }
-            component.blocksPerLine = blocksPerLine;
-            component.blocksPerColumn = blocksPerColumn;
-            component.blocks = blocks;
-          }
+        // do after
+        for (var j = i + 1; j < strLength; --j) {
+          if (types[j] != 'ET')
+            break;
+          types[j] = 'EN';
         }
-        frame.maxH = maxH;
-        frame.maxV = maxV;
-        frame.mcusPerLine = mcusPerLine;
-        frame.mcusPerColumn = mcusPerColumn;
-      }
-      var jfif = null;
-      var adobe = null;
-      var pixels = null;
-      var frame, resetInterval;
-      var quantizationTables = [], frames = [];
-      var huffmanTablesAC = [], huffmanTablesDC = [];
-      var fileMarker = readUint16();
-      if (fileMarker != 0xFFD8) { // SOI (Start of Image)
-        throw "SOI not found";
       }
+    }
 
-      fileMarker = readUint16();
-      while (fileMarker != 0xFFD9) { // EOI (End of image)
-        var i, j, l;
-        switch(fileMarker) {
-          case 0xFFE0: // APP0 (Application Specific)
-          case 0xFFE1: // APP1
-          case 0xFFE2: // APP2
-          case 0xFFE3: // APP3
-          case 0xFFE4: // APP4
-          case 0xFFE5: // APP5
-          case 0xFFE6: // APP6
-          case 0xFFE7: // APP7
-          case 0xFFE8: // APP8
-          case 0xFFE9: // APP9
-          case 0xFFEA: // APP10
-          case 0xFFEB: // APP11
-          case 0xFFEC: // APP12
-          case 0xFFED: // APP13
-          case 0xFFEE: // APP14
-          case 0xFFEF: // APP15
-          case 0xFFFE: // COM (Comment)
-            var appData = readDataBlock();
+    /*
+     W6. Otherwise, separators and terminators change to Other Neutral:
+     */
 
-            if (fileMarker === 0xFFE0) {
-              if (appData[0] === 0x4A && appData[1] === 0x46 && appData[2] === 0x49 &&
-                appData[3] === 0x46 && appData[4] === 0) { // 'JFIF\x00'
-                jfif = {
-                  version: { major: appData[5], minor: appData[6] },
-                  densityUnits: appData[7],
-                  xDensity: (appData[8] << 8) | appData[9],
-                  yDensity: (appData[10] << 8) | appData[11],
-                  thumbWidth: appData[12],
-                  thumbHeight: appData[13],
-                  thumbData: appData.subarray(14, 14 + 3 * appData[12] * appData[13])
-                };
-              }
-            }
-            // TODO APP1 - Exif
-            if (fileMarker === 0xFFEE) {
-              if (appData[0] === 0x41 && appData[1] === 0x64 && appData[2] === 0x6F &&
-                appData[3] === 0x62 && appData[4] === 0x65 && appData[5] === 0) { // 'Adobe\x00'
-                adobe = {
-                  version: appData[6],
-                  flags0: (appData[7] << 8) | appData[8],
-                  flags1: (appData[9] << 8) | appData[10],
-                  transformCode: appData[11]
-                };
-              }
-            }
-            break;
+    for (var i = 0; i < strLength; ++i) {
+      var t = types[i];
+      if (t == 'WS' || t == 'ES' || t == 'ET' || t == 'CS')
+        types[i] = 'ON';
+    }
 
-          case 0xFFDB: // DQT (Define Quantization Tables)
-            var quantizationTableCount = Math.floor((readUint16() - 2) / 65);
-            for (i = 0; i < quantizationTableCount; i++) {
-              var quantizationTableSpec = data[offset++];
-              var tableData = new Int32Array(64);
-              if ((quantizationTableSpec >> 4) === 0) { // 8 bit values
-                for (j = 0; j < 64; j++) {
-                  var z = dctZigZag[j];
-                  tableData[z] = data[offset++];
-                }
-              } else if ((quantizationTableSpec >> 4) === 1) { //16 bit
-                  tableData[j] = readUint16();
-              } else
-                throw "DQT: invalid table spec";
-              quantizationTables[quantizationTableSpec & 15] = tableData;
-            }
-            break;
+    /*
+     W7. Search backwards from each instance of a European number until the
+     first strong type (R, L, or sor) is found. If an L is found,  then change
+     the type of the European number to L.
+     */
 
-          case 0xFFC0: // SOF0 (Start of Frame, Baseline DCT)
-          case 0xFFC2: // SOF2 (Start of Frame, Progressive DCT)
-            readUint16(); // skip data length
-            frame = {};
-            frame.progressive = (fileMarker === 0xFFC2);
-            frame.precision = data[offset++];
-            frame.scanLines = readUint16();
-            frame.samplesPerLine = readUint16();
-            frame.components = [];
-            var componentsCount = data[offset++], componentId;
-            var maxH = 0, maxV = 0;
-            for (i = 0; i < componentsCount; i++) {
-              componentId = data[offset];
-              var h = data[offset + 1] >> 4;
-              var v = data[offset + 1] & 15;
-              var qId = data[offset + 2];
-              frame.components[componentId] = {
-                h: h,
-                v: v,
-                quantizationTable: quantizationTables[qId]
-              };
-              offset += 3;
-            }
-            prepareComponents(frame);
-            frames.push(frame);
-            break;
+    var lastType = sor;
+    for (var i = 0; i < strLength; ++i) {
+      var t = types[i];
+      if (t == 'EN')
+        types[i] = (lastType == 'L') ? 'L' : 'EN';
+      else if (t == 'R' || t == 'L')
+        lastType = t;
+    }
+
+    /*
+     N1. A sequence of neutrals takes the direction of the surrounding strong
+     text if the text on both sides has the same direction. European and Arabic
+     numbers are treated as though they were R. Start-of-level-run (sor) and
+     end-of-level-run (eor) are used at level run boundaries.
+     */
+
+    for (var i = 0; i < strLength; ++i) {
+      if (types[i] == 'ON') {
+        var end = findUnequal(types, i + 1, 'ON');
+        var before = sor;
+        if (i > 0)
+          before = types[i - 1];
+        var after = eor;
+        if (end + 1 < strLength)
+          after = types[end + 1];
+        if (before != 'L')
+          before = 'R';
+        if (after != 'L')
+          after = 'R';
+        if (before == after)
+          setValues(types, i, end, before);
+        i = end - 1; // reset to end (-1 so next iteration is ok)
+      }
+    }
 
-          case 0xFFC4: // DHT (Define Huffman Tables)
-            var huffmanLength = readUint16();
-            for (i = 2; i < huffmanLength;) {
-              var huffmanTableSpec = data[offset++];
-              var codeLengths = new Uint8Array(16);
-              var codeLengthSum = 0;
-              for (j = 0; j < 16; j++, offset++)
-                codeLengthSum += (codeLengths[j] = data[offset]);
-              var huffmanValues = new Uint8Array(codeLengthSum);
-              for (j = 0; j < codeLengthSum; j++, offset++)
-                huffmanValues[j] = data[offset];
-              i += 17 + codeLengthSum;
+    /*
+     N2. Any remaining neutrals take the embedding direction.
+     */
 
-              ((huffmanTableSpec >> 4) === 0 ? 
-                huffmanTablesDC : huffmanTablesAC)[huffmanTableSpec & 15] =
-                buildHuffmanTable(codeLengths, huffmanValues);
-            }
-            break;
+    for (var i = 0; i < strLength; ++i) {
+      if (types[i] == 'ON')
+        types[i] = e;
+    }
 
-          case 0xFFDD: // DRI (Define Restart Interval)
-            readUint16(); // skip data length
-            resetInterval = readUint16();
-            break;
+    /*
+     I1. For all characters with an even (left-to-right) embedding direction,
+     those of type R go up one level and those of type AN or EN go up two
+     levels.
+     I2. For all characters with an odd (right-to-left) embedding direction,
+     those of type L, EN or AN go up one level.
+     */
 
-          case 0xFFDA: // SOS (Start of Scan)
-            var scanLength = readUint16();
-            var selectorsCount = data[offset++];
-            var components = [], component;
-            for (i = 0; i < selectorsCount; i++) {
-              component = frame.components[data[offset++]];
-              var tableSpec = data[offset++];
-              component.huffmanTableDC = huffmanTablesDC[tableSpec >> 4];
-              component.huffmanTableAC = huffmanTablesAC[tableSpec & 15];
-              components.push(component);
-            }
-            var spectralStart = data[offset++];
-            var spectralEnd = data[offset++];
-            var successiveApproximation = data[offset++];
-            var processed = decodeScan(data, offset,
-              frame, components, resetInterval,
-              spectralStart, spectralEnd,
-              successiveApproximation >> 4, successiveApproximation & 15);
-            offset += processed;
-            break;
-          default:
-            throw "unknown JPEG marker " + fileMarker.toString(16);
+    for (var i = 0; i < strLength; ++i) {
+      var t = types[i];
+      if (isEven(levels[i])) {
+        if (t == 'R') {
+          levels[i] += 1;
+        } else if (t == 'AN' || t == 'EN') {
+          levels[i] += 2;
+        }
+      } else { // isOdd, so
+        if (t == 'L' || t == 'AN' || t == 'EN') {
+          levels[i] += 1;
         }
-        fileMarker = readUint16();
       }
-      if (frames.length != 1)
-        throw "only single frame JPEGs supported";
+    }
 
-      this.width = frame.samplesPerLine;
-      this.height = frame.scanLines;
-      this.jfif = jfif;
-      this.adobe = adobe;
-      this.components = [];
-      for (var id in frame.components) {
-        if (frame.components.hasOwnProperty(id)) {
-          this.components.push({
-            lines: buildComponentData(frame, frame.components[id]),
-            scaleX: frame.components[id].h / frame.maxH,
-            scaleY: frame.components[id].v / frame.maxV
-          });
+    /*
+     L1. On each line, reset the embedding level of the following characters to
+     the paragraph embedding level:
+
+     segment separators,
+     paragraph separators,
+     any sequence of whitespace characters preceding a segment separator or
+     paragraph separator, and any sequence of white space characters at the end
+     of the line.
+     */
+
+    // don't bother as text is only single line
+
+    /*
+     L2. From the highest level found in the text to the lowest odd level on
+     each line, reverse any contiguous sequence of characters that are at that
+     level or higher.
+     */
+
+    // find highest level & lowest odd level
+
+    var highestLevel = -1;
+    var lowestOddLevel = 99;
+    for (var i = 0, ii = levels.length; i < ii; ++i) {
+      var level = levels[i];
+      if (highestLevel < level)
+        highestLevel = level;
+      if (lowestOddLevel > level && isOdd(level))
+        lowestOddLevel = level;
+    }
+
+    // now reverse between those limits
+
+    for (var level = highestLevel; level >= lowestOddLevel; --level) {
+      // find segments to reverse
+      var start = -1;
+      for (var i = 0, ii = levels.length; i < ii; ++i) {
+        if (levels[i] < level) {
+          if (start >= 0) {
+            reverseValues(chars, start, i);
+            start = -1;
+          }
+        } else if (start < 0) {
+          start = i;
         }
       }
-    },
-    getData: function getData(width, height) {
-      function clampTo8bit(a) {
-        return a < 0 ? 0 : a > 255 ? 255 : a;
+      if (start >= 0) {
+        reverseValues(chars, start, levels.length);
       }
-      var scaleX = this.width / width, scaleY = this.height / height;
+    }
 
-      var component1, component2, component3, component4;
-      var component1Line, component2Line, component3Line, component4Line;
-      var x, y;
-      var offset = 0;
-      var Y, Cb, Cr, K, C, M, Ye, R, G, B;
-      var colorTransform;
-      var dataLength = width * height * this.components.length;
-      var data = new Uint8Array(dataLength);
-      switch (this.components.length) {
-        case 1:
-          component1 = this.components[0];
-          for (y = 0; y < height; y++) {
-            component1Line = component1.lines[0 | (y * component1.scaleY * scaleY)];
-            for (x = 0; x < width; x++) {
-              Y = component1Line[0 | (x * component1.scaleX * scaleX)];
+    /*
+     L3. Combining marks applied to a right-to-left base character will at this
+     point precede their base character. If the rendering engine expects them to
+     follow the base characters in the final display process, then the ordering
+     of the marks and the base character must be reversed.
+     */
 
-              data[offset++] = Y;
-            }
-          }
-          break;
-        case 3:
-          // The default transform for three components is true
-          colorTransform = true;
-          // The adobe transform marker overrides any previous setting
-          if (this.adobe && this.adobe.transformCode)
-            colorTransform = true;
-          else if (typeof this.colorTransform !== 'undefined')
-            colorTransform = !!this.colorTransform;
+    // don't bother for now
 
-          component1 = this.components[0];
-          component2 = this.components[1];
-          component3 = this.components[2];
-          for (y = 0; y < height; y++) {
-            component1Line = component1.lines[0 | (y * component1.scaleY * scaleY)];
-            component2Line = component2.lines[0 | (y * component2.scaleY * scaleY)];
-            component3Line = component3.lines[0 | (y * component3.scaleY * scaleY)];
-            for (x = 0; x < width; x++) {
-              if (!colorTransform) {
-                R = component1Line[0 | (x * component1.scaleX * scaleX)];
-                G = component2Line[0 | (x * component2.scaleX * scaleX)];
-                B = component3Line[0 | (x * component3.scaleX * scaleX)];
-              } else {
-                Y = component1Line[0 | (x * component1.scaleX * scaleX)];
-                Cb = component2Line[0 | (x * component2.scaleX * scaleX)];
-                Cr = component3Line[0 | (x * component3.scaleX * scaleX)];
+    /*
+     L4. A character that possesses the mirrored property as specified by
+     Section 4.7, Mirrored, must be depicted by a mirrored glyph if the resolved
+     directionality of that character is R.
+     */
 
-                R = clampTo8bit(Y + 1.402 * (Cr - 128));
-                G = clampTo8bit(Y - 0.3441363 * (Cb - 128) - 0.71413636 * (Cr - 128));
-                B = clampTo8bit(Y + 1.772 * (Cb - 128));
-              }
+    // don't mirror as characters are already mirrored in the pdf
 
-              data[offset++] = R;
-              data[offset++] = G;
-              data[offset++] = B;
-            }
-          }
-          break;
-        case 4:
-          if (!this.adobe)
-            throw 'Unsupported color mode (4 components)';
-          // The default transform for four components is false
-          colorTransform = false;
-          // The adobe transform marker overrides any previous setting
-          if (this.adobe && this.adobe.transformCode)
-            colorTransform = true;
-          else if (typeof this.colorTransform !== 'undefined')
-            colorTransform = !!this.colorTransform;
+    // Finally, return string
 
-          component1 = this.components[0];
-          component2 = this.components[1];
-          component3 = this.components[2];
-          component4 = this.components[3];
-          for (y = 0; y < height; y++) {
-            component1Line = component1.lines[0 | (y * component1.scaleY * scaleY)];
-            component2Line = component2.lines[0 | (y * component2.scaleY * scaleY)];
-            component3Line = component3.lines[0 | (y * component3.scaleY * scaleY)];
-            component4Line = component4.lines[0 | (y * component4.scaleY * scaleY)];
-            for (x = 0; x < width; x++) {
-              if (!colorTransform) {
-                C = component1Line[0 | (x * component1.scaleX * scaleX)];
-                M = component2Line[0 | (x * component2.scaleX * scaleX)];
-                Ye = component3Line[0 | (x * component3.scaleX * scaleX)];
-                K = component4Line[0 | (x * component4.scaleX * scaleX)];
-              } else {
-                Y = component1Line[0 | (x * component1.scaleX * scaleX)];
-                Cb = component2Line[0 | (x * component2.scaleX * scaleX)];
-                Cr = component3Line[0 | (x * component3.scaleX * scaleX)];
-                K = component4Line[0 | (x * component4.scaleX * scaleX)];
+    var result = '';
+    for (var i = 0, ii = chars.length; i < ii; ++i) {
+      var ch = chars[i];
+      if (ch != '<' && ch != '>')
+        result += ch;
+    }
+    return result;
+  }
 
-                C = 255 - clampTo8bit(Y + 1.402 * (Cr - 128));
-                M = 255 - clampTo8bit(Y - 0.3441363 * (Cb - 128) - 0.71413636 * (Cr - 128));
-                Ye = 255 - clampTo8bit(Y + 1.772 * (Cb - 128));
-              }
-              data[offset++] = C;
-              data[offset++] = M;
-              data[offset++] = Ye;
-              data[offset++] = K;
-            }
-          }
-          break;
-        default:
-          throw 'Unsupported color mode';
+  return bidi;
+})();
+
+/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
+
+'use strict';
+
+var Metadata = PDFJS.Metadata = (function MetadataClosure() {
+  function Metadata(meta) {
+    if (typeof meta === 'string') {
+      var parser = new DOMParser();
+      meta = parser.parseFromString(meta, 'application/xml');
+    } else if (!(meta instanceof Document)) {
+      error('Metadata: Invalid metadata object');
+    }
+
+    this.metaDocument = meta;
+    this.metadata = {};
+    this.parse();
+  }
+
+  Metadata.prototype = {
+    parse: function Metadata_parse() {
+      var doc = this.metaDocument;
+      var rdf = doc.documentElement;
+
+      if (rdf.nodeName.toLowerCase() !== 'rdf:rdf') { // Wrapped in <xmpmeta>
+        rdf = rdf.firstChild;
+        while (rdf && rdf.nodeName.toLowerCase() !== 'rdf:rdf')
+          rdf = rdf.nextSibling;
       }
-      return data;
-    },
-    copyToImageData: function copyToImageData(imageData) {
-      var width = imageData.width, height = imageData.height;
-      var imageDataArray = imageData.data;
-      var data = this.getData(width, height);
-      var i = 0, j = 0, x, y;
-      var Y, K, C, M, R, G, B;
-      switch (this.components.length) {
-        case 1:
-          for (y = 0; y < height; y++) {
-            for (x = 0; x < width; x++) {
-              Y = data[i++];
 
-              imageDataArray[j++] = Y;
-              imageDataArray[j++] = Y;
-              imageDataArray[j++] = Y;
-              imageDataArray[j++] = 255;
-            }
-          }
-          break;
-        case 3:
-          for (y = 0; y < height; y++) {
-            for (x = 0; x < width; x++) {
-              R = data[i++];
-              G = data[i++];
-              B = data[i++];
+      var nodeName = (rdf) ? rdf.nodeName.toLowerCase() : null;
+      if (!rdf || nodeName !== 'rdf:rdf' || !rdf.hasChildNodes())
+        return;
 
-              imageDataArray[j++] = R;
-              imageDataArray[j++] = G;
-              imageDataArray[j++] = B;
-              imageDataArray[j++] = 255;
-            }
-          }
-          break;
-        case 4:
-          for (y = 0; y < height; y++) {
-            for (x = 0; x < width; x++) {
-              C = data[i++];
-              M = data[i++];
-              Y = data[i++];
-              K = data[i++];
+      var childNodes = rdf.childNodes, desc, namespace, entries, entry;
 
-              R = 255 - clampTo8bit(C * (1 - K / 255) + K);
-              G = 255 - clampTo8bit(M * (1 - K / 255) + K);
-              B = 255 - clampTo8bit(Y * (1 - K / 255) + K);
+      for (var i = 0, length = childNodes.length; i < length; i++) {
+        desc = childNodes[i];
+        if (desc.nodeName.toLowerCase() !== 'rdf:description')
+          continue;
 
-              imageDataArray[j++] = R;
-              imageDataArray[j++] = G;
-              imageDataArray[j++] = B;
-              imageDataArray[j++] = 255;
-            }
-          }
-          break;
-        default:
-          throw 'Unsupported color mode';
+        entries = [];
+        for (var ii = 0, iLength = desc.childNodes.length; ii < iLength; ii++) {
+          if (desc.childNodes[ii].nodeName.toLowerCase() !== '#text')
+            entries.push(desc.childNodes[ii]);
+        }
+
+        for (ii = 0, iLength = entries.length; ii < iLength; ii++) {
+          var entry = entries[ii];
+          var name = entry.nodeName.toLowerCase();
+          this.metadata[name] = entry.textContent.trim();
+        }
       }
+    },
+
+    get: function Metadata_get(name) {
+      return this.metadata[name] || null;
+    },
+
+    has: function Metadata_has(name) {
+      return typeof this.metadata[name] !== 'undefined';
     }
   };
 
-  return constructor;
+  return Metadata;
 })();
+
 }).call((typeof window === 'undefined') ? this : window);
diff --git a/apps/files_pdfviewer/js/pdfjs/src/bidi.js b/apps/files_pdfviewer/js/pdfjs/src/bidi.js
new file mode 100644
index 0000000000000000000000000000000000000000..5f18e53030df5347c7662b2a23ca951c60d8979a
--- /dev/null
+++ b/apps/files_pdfviewer/js/pdfjs/src/bidi.js
@@ -0,0 +1,432 @@
+/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
+
+'use strict';
+
+var bidi = PDFJS.bidi = (function bidiClosure() {
+  // Character types for symbols from 0000 to 00FF.
+  var baseTypes = [
+    'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'S', 'B', 'S', 'WS',
+    'B', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN',
+    'BN', 'BN', 'B', 'B', 'B', 'S', 'WS', 'ON', 'ON', 'ET', 'ET', 'ET', 'ON',
+    'ON', 'ON', 'ON', 'ON', 'ON', 'CS', 'ON', 'CS', 'ON', 'EN', 'EN', 'EN',
+    'EN', 'EN', 'EN', 'EN', 'EN', 'EN', 'EN', 'ON', 'ON', 'ON', 'ON', 'ON',
+    'ON', 'ON', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L',
+    'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'ON', 'ON',
+    'ON', 'ON', 'ON', 'ON', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L',
+    'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L',
+    'L', 'ON', 'ON', 'ON', 'ON', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'B', 'BN',
+    'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN',
+    'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN',
+    'BN', 'CS', 'ON', 'ET', 'ET', 'ET', 'ET', 'ON', 'ON', 'ON', 'ON', 'L', 'ON',
+    'ON', 'ON', 'ON', 'ON', 'ET', 'ET', 'EN', 'EN', 'ON', 'L', 'ON', 'ON', 'ON',
+    'EN', 'L', 'ON', 'ON', 'ON', 'ON', 'ON', 'L', 'L', 'L', 'L', 'L', 'L', 'L',
+    'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L',
+    'L', 'ON', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L',
+    'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L',
+    'L', 'L', 'L', 'ON', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L'
+  ];
+
+  // Character types for symbols from 0600 to 06FF
+  var arabicTypes = [
+    'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL',
+    'CS', 'AL', 'ON', 'ON', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'AL',
+    'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL',
+    'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL',
+    'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL',
+    'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL',
+    'AL', 'AL', 'AL', 'AL', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM',
+    'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'AL', 'AL', 'AL', 'AL',
+    'AL', 'AL', 'AL', 'AN', 'AN', 'AN', 'AN', 'AN', 'AN', 'AN', 'AN', 'AN',
+    'AN', 'ET', 'AN', 'AN', 'AL', 'AL', 'AL', 'NSM', 'AL', 'AL', 'AL', 'AL',
+    'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL',
+    'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL',
+    'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL',
+    'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL',
+    'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL',
+    'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL',
+    'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL',
+    'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL',
+    'AL', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM',
+    'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'ON', 'NSM',
+    'NSM', 'NSM', 'NSM', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL',
+    'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL'
+  ];
+
+  function isOdd(i) {
+    return (i & 1) != 0;
+  }
+
+  function isEven(i) {
+    return (i & 1) == 0;
+  }
+
+  function findUnequal(arr, start, value) {
+    var j;
+    for (var j = start, jj = arr.length; j < jj; ++j) {
+      if (arr[j] != value)
+        return j;
+    }
+    return j;
+  }
+
+  function setValues(arr, start, end, value) {
+    for (var j = start; j < end; ++j) {
+      arr[j] = value;
+    }
+  }
+
+  function reverseValues(arr, start, end) {
+    for (var i = start, j = end - 1; i < j; ++i, --j) {
+      var temp = arr[i];
+      arr[i] = arr[j];
+      arr[j] = temp;
+    }
+  }
+
+  function mirrorGlyphs(c) {
+    /*
+     # BidiMirroring-1.txt
+     0028; 0029 # LEFT PARENTHESIS
+     0029; 0028 # RIGHT PARENTHESIS
+     003C; 003E # LESS-THAN SIGN
+     003E; 003C # GREATER-THAN SIGN
+     005B; 005D # LEFT SQUARE BRACKET
+     005D; 005B # RIGHT SQUARE BRACKET
+     007B; 007D # LEFT CURLY BRACKET
+     007D; 007B # RIGHT CURLY BRACKET
+     00AB; 00BB # LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+     00BB; 00AB # RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+     */
+    switch (c) {
+      case '(':
+        return ')';
+      case ')':
+        return '(';
+      case '<':
+        return '>';
+      case '>':
+        return '<';
+      case ']':
+        return '[';
+      case '[':
+        return ']';
+      case '}':
+        return '{';
+      case '{':
+        return '}';
+      case '\u00AB':
+        return '\u00BB';
+      case '\u00BB':
+        return '\u00AB';
+      default:
+        return c;
+    }
+  }
+
+  function bidi(text, startLevel) {
+    var str = text.str;
+    var strLength = str.length;
+    if (strLength == 0)
+      return str;
+
+    // get types, fill arrays
+
+    var chars = [];
+    var types = [];
+    var oldtypes = [];
+    var numBidi = 0;
+
+    for (var i = 0; i < strLength; ++i) {
+      chars[i] = str.charAt(i);
+
+      var charCode = str.charCodeAt(i);
+      var charType = 'L';
+      if (charCode <= 0x00ff)
+        charType = baseTypes[charCode];
+      else if (0x0590 <= charCode && charCode <= 0x05f4)
+        charType = 'R';
+      else if (0x0600 <= charCode && charCode <= 0x06ff)
+        charType = arabicTypes[charCode & 0xff];
+      else if (0x0700 <= charCode && charCode <= 0x08AC)
+        charType = 'AL';
+
+      if (charType == 'R' || charType == 'AL' || charType == 'AN')
+        numBidi++;
+
+      oldtypes[i] = types[i] = charType;
+    }
+
+    // detect the bidi method
+    //  if there are no rtl characters then no bidi needed
+    //  if less than 30% chars are rtl then string is primarily ltr
+    //  if more than 30% chars are rtl then string is primarily rtl
+    if (numBidi == 0) {
+      text.direction = 'ltr';
+      return str;
+    }
+
+    if (startLevel == -1) {
+      if ((strLength / numBidi) < 0.3) {
+        text.direction = 'ltr';
+        startLevel = 0;
+      } else {
+        text.direction = 'rtl';
+        startLevel = 1;
+      }
+    }
+
+    var levels = [];
+
+    for (var i = 0; i < strLength; ++i) {
+      levels[i] = startLevel;
+    }
+
+    /*
+     X1-X10: skip most of this, since we are NOT doing the embeddings.
+     */
+
+    var e = isOdd(startLevel) ? 'R' : 'L';
+    var sor = e;
+    var eor = sor;
+
+    /*
+     W1. Examine each non-spacing mark (NSM) in the level run, and change the
+     type of the NSM to the type of the previous character. If the NSM is at the
+     start of the level run, it will get the type of sor.
+     */
+
+    var lastType = sor;
+    for (var i = 0; i < strLength; ++i) {
+      if (types[i] == 'NSM')
+        types[i] = lastType;
+      else
+        lastType = types[i];
+    }
+
+    /*
+     W2. Search backwards from each instance of a European number until the
+     first strong type (R, L, AL, or sor) is found.  If an AL is found, change
+     the type of the European number to Arabic number.
+     */
+
+    var lastType = sor;
+    for (var i = 0; i < strLength; ++i) {
+      var t = types[i];
+      if (t == 'EN')
+        types[i] = (lastType == 'AL') ? 'AN' : 'EN';
+      else if (t == 'R' || t == 'L' || t == 'AL')
+        lastType = t;
+    }
+
+    /*
+     W3. Change all ALs to R.
+     */
+
+    for (var i = 0; i < strLength; ++i) {
+      var t = types[i];
+      if (t == 'AL')
+        types[i] = 'R';
+    }
+
+    /*
+     W4. A single European separator between two European numbers changes to a
+     European number. A single common separator between two numbers of the same
+     type changes to that type:
+     */
+
+    for (var i = 1; i < strLength - 1; ++i) {
+      if (types[i] == 'ES' && types[i - 1] == 'EN' && types[i + 1] == 'EN')
+        types[i] = 'EN';
+      if (types[i] == 'CS' && (types[i - 1] == 'EN' || types[i - 1] == 'AN') &&
+          types[i + 1] == types[i - 1])
+        types[i] = types[i - 1];
+    }
+
+    /*
+     W5. A sequence of European terminators adjacent to European numbers changes
+     to all European numbers:
+     */
+
+    for (var i = 0; i < strLength; ++i) {
+      if (types[i] == 'EN') {
+        // do before
+        for (var j = i - 1; j >= 0; --j) {
+          if (types[j] != 'ET')
+            break;
+          types[j] = 'EN';
+        }
+        // do after
+        for (var j = i + 1; j < strLength; --j) {
+          if (types[j] != 'ET')
+            break;
+          types[j] = 'EN';
+        }
+      }
+    }
+
+    /*
+     W6. Otherwise, separators and terminators change to Other Neutral:
+     */
+
+    for (var i = 0; i < strLength; ++i) {
+      var t = types[i];
+      if (t == 'WS' || t == 'ES' || t == 'ET' || t == 'CS')
+        types[i] = 'ON';
+    }
+
+    /*
+     W7. Search backwards from each instance of a European number until the
+     first strong type (R, L, or sor) is found. If an L is found,  then change
+     the type of the European number to L.
+     */
+
+    var lastType = sor;
+    for (var i = 0; i < strLength; ++i) {
+      var t = types[i];
+      if (t == 'EN')
+        types[i] = (lastType == 'L') ? 'L' : 'EN';
+      else if (t == 'R' || t == 'L')
+        lastType = t;
+    }
+
+    /*
+     N1. A sequence of neutrals takes the direction of the surrounding strong
+     text if the text on both sides has the same direction. European and Arabic
+     numbers are treated as though they were R. Start-of-level-run (sor) and
+     end-of-level-run (eor) are used at level run boundaries.
+     */
+
+    for (var i = 0; i < strLength; ++i) {
+      if (types[i] == 'ON') {
+        var end = findUnequal(types, i + 1, 'ON');
+        var before = sor;
+        if (i > 0)
+          before = types[i - 1];
+        var after = eor;
+        if (end + 1 < strLength)
+          after = types[end + 1];
+        if (before != 'L')
+          before = 'R';
+        if (after != 'L')
+          after = 'R';
+        if (before == after)
+          setValues(types, i, end, before);
+        i = end - 1; // reset to end (-1 so next iteration is ok)
+      }
+    }
+
+    /*
+     N2. Any remaining neutrals take the embedding direction.
+     */
+
+    for (var i = 0; i < strLength; ++i) {
+      if (types[i] == 'ON')
+        types[i] = e;
+    }
+
+    /*
+     I1. For all characters with an even (left-to-right) embedding direction,
+     those of type R go up one level and those of type AN or EN go up two
+     levels.
+     I2. For all characters with an odd (right-to-left) embedding direction,
+     those of type L, EN or AN go up one level.
+     */
+
+    for (var i = 0; i < strLength; ++i) {
+      var t = types[i];
+      if (isEven(levels[i])) {
+        if (t == 'R') {
+          levels[i] += 1;
+        } else if (t == 'AN' || t == 'EN') {
+          levels[i] += 2;
+        }
+      } else { // isOdd, so
+        if (t == 'L' || t == 'AN' || t == 'EN') {
+          levels[i] += 1;
+        }
+      }
+    }
+
+    /*
+     L1. On each line, reset the embedding level of the following characters to
+     the paragraph embedding level:
+
+     segment separators,
+     paragraph separators,
+     any sequence of whitespace characters preceding a segment separator or
+     paragraph separator, and any sequence of white space characters at the end
+     of the line.
+     */
+
+    // don't bother as text is only single line
+
+    /*
+     L2. From the highest level found in the text to the lowest odd level on
+     each line, reverse any contiguous sequence of characters that are at that
+     level or higher.
+     */
+
+    // find highest level & lowest odd level
+
+    var highestLevel = -1;
+    var lowestOddLevel = 99;
+    for (var i = 0, ii = levels.length; i < ii; ++i) {
+      var level = levels[i];
+      if (highestLevel < level)
+        highestLevel = level;
+      if (lowestOddLevel > level && isOdd(level))
+        lowestOddLevel = level;
+    }
+
+    // now reverse between those limits
+
+    for (var level = highestLevel; level >= lowestOddLevel; --level) {
+      // find segments to reverse
+      var start = -1;
+      for (var i = 0, ii = levels.length; i < ii; ++i) {
+        if (levels[i] < level) {
+          if (start >= 0) {
+            reverseValues(chars, start, i);
+            start = -1;
+          }
+        } else if (start < 0) {
+          start = i;
+        }
+      }
+      if (start >= 0) {
+        reverseValues(chars, start, levels.length);
+      }
+    }
+
+    /*
+     L3. Combining marks applied to a right-to-left base character will at this
+     point precede their base character. If the rendering engine expects them to
+     follow the base characters in the final display process, then the ordering
+     of the marks and the base character must be reversed.
+     */
+
+    // don't bother for now
+
+    /*
+     L4. A character that possesses the mirrored property as specified by
+     Section 4.7, Mirrored, must be depicted by a mirrored glyph if the resolved
+     directionality of that character is R.
+     */
+
+    // don't mirror as characters are already mirrored in the pdf
+
+    // Finally, return string
+
+    var result = '';
+    for (var i = 0, ii = chars.length; i < ii; ++i) {
+      var ch = chars[i];
+      if (ch != '<' && ch != '>')
+        result += ch;
+    }
+    return result;
+  }
+
+  return bidi;
+})();
+
diff --git a/apps/files_pdfviewer/js/pdfjs/src/canvas.js b/apps/files_pdfviewer/js/pdfjs/src/canvas.js
old mode 100755
new mode 100644
index 9b3ed0ba9ad66d8e8d9347570ccb7ea074ff6497..8f29051fdad1d43d9702c620d224ed1bb3260ab8
--- a/apps/files_pdfviewer/js/pdfjs/src/canvas.js
+++ b/apps/files_pdfviewer/js/pdfjs/src/canvas.js
@@ -6,12 +6,145 @@
 // <canvas> contexts store most of the state we need natively.
 // However, PDF needs a bit more state, which we store here.
 
-var CanvasExtraState = (function canvasExtraState() {
-  function constructor(old) {
+var TextRenderingMode = {
+  FILL: 0,
+  STROKE: 1,
+  FILL_STROKE: 2,
+  INVISIBLE: 3,
+  FILL_ADD_TO_PATH: 4,
+  STROKE_ADD_TO_PATH: 5,
+  FILL_STROKE_ADD_TO_PATH: 6,
+  ADD_TO_PATH: 7
+};
+
+// Minimal font size that would be used during canvas fillText operations.
+var MIN_FONT_SIZE = 1;
+
+function createScratchCanvas(width, height) {
+  var canvas = document.createElement('canvas');
+  canvas.width = width;
+  canvas.height = height;
+  return canvas;
+}
+
+function addContextCurrentTransform(ctx) {
+  // If the context doesn't expose a `mozCurrentTransform`, add a JS based on.
+  if (!ctx.mozCurrentTransform) {
+    // Store the original context
+    ctx._originalSave = ctx.save;
+    ctx._originalRestore = ctx.restore;
+    ctx._originalRotate = ctx.rotate;
+    ctx._originalScale = ctx.scale;
+    ctx._originalTranslate = ctx.translate;
+    ctx._originalTransform = ctx.transform;
+
+    ctx._transformMatrix = [1, 0, 0, 1, 0, 0];
+    ctx._transformStack = [];
+
+    Object.defineProperty(ctx, 'mozCurrentTransform', {
+      get: function getCurrentTransform() {
+        return this._transformMatrix;
+      }
+    });
+
+    Object.defineProperty(ctx, 'mozCurrentTransformInverse', {
+      get: function getCurrentTransformInverse() {
+        // Calculation done using WolframAlpha:
+        // http://www.wolframalpha.com/input/?
+        //   i=Inverse+{{a%2C+c%2C+e}%2C+{b%2C+d%2C+f}%2C+{0%2C+0%2C+1}}
+
+        var m = this._transformMatrix;
+        var a = m[0], b = m[1], c = m[2], d = m[3], e = m[4], f = m[5];
+
+        var ad_bc = a * d - b * c;
+        var bc_ad = b * c - a * d;
+
+        return [
+          d / ad_bc,
+          b / bc_ad,
+          c / bc_ad,
+          a / ad_bc,
+          (d * e - c * f) / bc_ad,
+          (b * e - a * f) / ad_bc
+        ];
+      }
+    });
+
+    ctx.save = function ctxSave() {
+      var old = this._transformMatrix;
+      this._transformStack.push(old);
+      this._transformMatrix = old.slice(0, 6);
+
+      this._originalSave();
+    };
+
+    ctx.restore = function ctxRestore() {
+      var prev = this._transformStack.pop();
+      if (prev) {
+        this._transformMatrix = prev;
+        this._originalRestore();
+      }
+    };
+
+    ctx.translate = function ctxTranslate(x, y) {
+      var m = this._transformMatrix;
+      m[4] = m[0] * x + m[2] * y + m[4];
+      m[5] = m[1] * x + m[3] * y + m[5];
+
+      this._originalTranslate(x, y);
+    };
+
+    ctx.scale = function ctxScale(x, y) {
+      var m = this._transformMatrix;
+      m[0] = m[0] * x;
+      m[1] = m[1] * x;
+      m[2] = m[2] * y;
+      m[3] = m[3] * y;
+
+      this._originalScale(x, y);
+    };
+
+    ctx.transform = function ctxTransform(a, b, c, d, e, f) {
+      var m = this._transformMatrix;
+      this._transformMatrix = [
+        m[0] * a + m[2] * b,
+        m[1] * a + m[3] * b,
+        m[0] * c + m[2] * d,
+        m[1] * c + m[3] * d,
+        m[0] * e + m[2] * f + m[4],
+        m[1] * e + m[3] * f + m[5]
+      ];
+
+      ctx._originalTransform(a, b, c, d, e, f);
+    };
+
+    ctx.rotate = function ctxRotate(angle) {
+      var cosValue = Math.cos(angle);
+      var sinValue = Math.sin(angle);
+
+      var m = this._transformMatrix;
+      this._transformMatrix = [
+        m[0] * cosValue + m[2] * sinValue,
+        m[1] * cosValue + m[3] * sinValue,
+        m[0] * (-sinValue) + m[2] * cosValue,
+        m[1] * (-sinValue) + m[3] * cosValue,
+        m[4],
+        m[5]
+      ];
+
+      this._originalRotate(angle);
+    };
+  }
+}
+
+var CanvasExtraState = (function CanvasExtraStateClosure() {
+  function CanvasExtraState(old) {
     // Are soft masks and alpha values shapes or opacities?
     this.alphaIsShape = false;
     this.fontSize = 0;
+    this.fontSizeScale = 1;
     this.textMatrix = IDENTITY_MATRIX;
+    this.fontMatrix = IDENTITY_MATRIX;
     this.leading = 0;
     // Current point (in user coordinates)
     this.x = 0;
@@ -23,6 +156,7 @@ var CanvasExtraState = (function canvasExtraState() {
     this.charSpacing = 0;
     this.wordSpacing = 0;
     this.textHScale = 1;
+    this.textRenderingMode = TextRenderingMode.FILL;
     // Color spaces
     this.fillColorSpace = new DeviceGrayCS();
     this.fillColorSpaceObj = null;
@@ -36,47 +170,40 @@ var CanvasExtraState = (function canvasExtraState() {
     // Note: fill alpha applies to all non-stroking operations
     this.fillAlpha = 1;
     this.strokeAlpha = 1;
+    this.lineWidth = 1;
 
     this.old = old;
   }
 
-  constructor.prototype = {
-    clone: function canvasextra_clone() {
+  CanvasExtraState.prototype = {
+    clone: function CanvasExtraState_clone() {
       return Object.create(this);
     },
-    setCurrentPoint: function canvasextra_setCurrentPoint(x, y) {
+    setCurrentPoint: function CanvasExtraState_setCurrentPoint(x, y) {
       this.x = x;
       this.y = y;
     }
   };
-  return constructor;
+  return CanvasExtraState;
 })();
 
-function ScratchCanvas(width, height) {
-  var canvas = document.createElement('canvas');
-  canvas.width = width;
-  canvas.height = height;
-  return canvas;
-}
-
-var CanvasGraphics = (function canvasGraphics() {
-  // Defines the time the executeIRQueue is going to be executing
+var CanvasGraphics = (function CanvasGraphicsClosure() {
+  // Defines the time the executeOperatorList is going to be executing
   // before it stops and shedules a continue of execution.
-  var kExecutionTime = 50;
-
-  // Number of IR commands to execute before checking
-  // if we execute longer then `kExecutionTime`.
-  var kExecutionTimeCheck = 500;
+  var kExecutionTime = 15;
 
-  function constructor(canvasCtx, objs) {
+  function CanvasGraphics(canvasCtx, objs, textLayer) {
     this.ctx = canvasCtx;
     this.current = new CanvasExtraState();
     this.stateStack = [];
     this.pendingClip = null;
     this.res = null;
     this.xobjs = null;
-    this.ScratchCanvas = ScratchCanvas;
     this.objs = objs;
+    this.textLayer = textLayer;
+    if (canvasCtx) {
+      addContextCurrentTransform(canvasCtx);
+    }
   }
 
   var LINE_CAP_STYLES = ['butt', 'round', 'square'];
@@ -84,8 +211,37 @@ var CanvasGraphics = (function canvasGraphics() {
   var NORMAL_CLIP = {};
   var EO_CLIP = {};
 
-  constructor.prototype = {
-    beginDrawing: function canvasGraphicsBeginDrawing(mediaBox) {
+  CanvasGraphics.prototype = {
+    slowCommands: {
+      'stroke': true,
+      'closeStroke': true,
+      'fill': true,
+      'eoFill': true,
+      'fillStroke': true,
+      'eoFillStroke': true,
+      'closeFillStroke': true,
+      'closeEOFillStroke': true,
+      'showText': true,
+      'showSpacedText': true,
+      'setStrokeColorSpace': true,
+      'setFillColorSpace': true,
+      'setStrokeColor': true,
+      'setStrokeColorN': true,
+      'setFillColor': true,
+      'setFillColorN': true,
+      'setStrokeGray': true,
+      'setFillGray': true,
+      'setStrokeRGBColor': true,
+      'setFillRGBColor': true,
+      'setStrokeCMYKColor': true,
+      'setFillCMYKColor': true,
+      'paintJpegXObject': true,
+      'paintImageXObject': true,
+      'paintImageMaskXObject': true,
+      'shadingFill': true
+    },
+
+    beginDrawing: function CanvasGraphics_beginDrawing(mediaBox) {
       var cw = this.ctx.canvas.width, ch = this.ctx.canvas.height;
       this.ctx.save();
       switch (mediaBox.rotate) {
@@ -102,43 +258,63 @@ var CanvasGraphics = (function canvasGraphics() {
           this.ctx.transform(0, -1, -1, 0, cw, ch);
           break;
       }
+      // Scale so that canvas units are the same as PDF user space units
       this.ctx.scale(cw / mediaBox.width, ch / mediaBox.height);
+      // Move the media left-top corner to the (0,0) canvas position
+      this.ctx.translate(-mediaBox.x, -mediaBox.y);
+
+      if (this.textLayer)
+        this.textLayer.beginLayout();
     },
 
-    executeIRQueue: function canvasGraphicsExecuteIRQueue(codeIR,
-                                  executionStartIdx, continueCallback) {
-      var argsArray = codeIR.argsArray;
-      var fnArray = codeIR.fnArray;
+    executeOperatorList: function CanvasGraphics_executeOperatorList(
+                                    operatorList,
+                                    executionStartIdx, continueCallback,
+                                    stepper) {
+      var argsArray = operatorList.argsArray;
+      var fnArray = operatorList.fnArray;
       var i = executionStartIdx || 0;
       var argsArrayLen = argsArray.length;
 
+      // Sometimes the OperatorList to execute is empty.
+      if (argsArrayLen == i) {
+        return i;
+      }
+
       var executionEndIdx;
-      var startTime = Date.now();
+      var endTime = Date.now() + kExecutionTime;
 
       var objs = this.objs;
+      var fnName;
+      var slowCommands = this.slowCommands;
 
-      do {
-        executionEndIdx = Math.min(argsArrayLen, i + kExecutionTimeCheck);
-
-        for (i; i < executionEndIdx; i++) {
-          if (fnArray[i] !== 'dependency') {
-            this[fnArray[i]].apply(this, argsArray[i]);
-          } else {
-            var deps = argsArray[i];
-            for (var n = 0, nn = deps.length; n < nn; n++) {
-              var depObjId = deps[n];
-
-              // If the promise isn't resolved yet, add the continueCallback
-              // to the promise and bail out.
-              if (!objs.isResolved(depObjId)) {
-                objs.get(depObjId, continueCallback);
-                return i;
-              }
+      while (true) {
+        if (stepper && i === stepper.nextBreakPoint) {
+          stepper.breakIt(i, continueCallback);
+          return i;
+        }
+
+        fnName = fnArray[i];
+
+        if (fnName !== 'dependency') {
+          this[fnName].apply(this, argsArray[i]);
+        } else {
+          var deps = argsArray[i];
+          for (var n = 0, nn = deps.length; n < nn; n++) {
+            var depObjId = deps[n];
+
+            // If the promise isn't resolved yet, add the continueCallback
+            // to the promise and bail out.
+            if (!objs.isResolved(depObjId)) {
+              objs.get(depObjId, continueCallback);
+              return i;
             }
           }
         }
 
-        // If the entire IRQueue was executed, stop as were done.
+        i++;
+
+        // If the entire operatorList was executed, stop as were done.
         if (i == argsArrayLen) {
           return i;
         }
@@ -146,44 +322,50 @@ var CanvasGraphics = (function canvasGraphics() {
         // If the execution took longer then a certain amount of time, shedule
         // to continue exeution after a short delay.
         // However, this is only possible if a 'continueCallback' is passed in.
-        if (continueCallback && (Date.now() - startTime) > kExecutionTime) {
+        if (continueCallback && slowCommands[fnName] && Date.now() > endTime) {
           setTimeout(continueCallback, 0);
           return i;
         }
 
-        // If the IRQueue isn't executed completly yet OR the execution time
-        // was short enough, do another execution round.
-      } while (true);
+        // If the operatorList isn't executed completely yet OR the execution
+        // time was short enough, do another execution round.
+      }
     },
 
-    endDrawing: function canvasGraphicsEndDrawing() {
+    endDrawing: function CanvasGraphics_endDrawing() {
       this.ctx.restore();
+
+      if (this.textLayer)
+        this.textLayer.endLayout();
     },
 
     // Graphics state
-    setLineWidth: function canvasGraphicsSetLineWidth(width) {
+    setLineWidth: function CanvasGraphics_setLineWidth(width) {
+      this.current.lineWidth = width;
       this.ctx.lineWidth = width;
     },
-    setLineCap: function canvasGraphicsSetLineCap(style) {
+    setLineCap: function CanvasGraphics_setLineCap(style) {
       this.ctx.lineCap = LINE_CAP_STYLES[style];
     },
-    setLineJoin: function canvasGraphicsSetLineJoin(style) {
+    setLineJoin: function CanvasGraphics_setLineJoin(style) {
       this.ctx.lineJoin = LINE_JOIN_STYLES[style];
     },
-    setMiterLimit: function canvasGraphicsSetMiterLimit(limit) {
+    setMiterLimit: function CanvasGraphics_setMiterLimit(limit) {
       this.ctx.miterLimit = limit;
     },
-    setDash: function canvasGraphicsSetDash(dashArray, dashPhase) {
+    setDash: function CanvasGraphics_setDash(dashArray, dashPhase) {
       this.ctx.mozDash = dashArray;
       this.ctx.mozDashOffset = dashPhase;
+      this.ctx.webkitLineDash = dashArray;
+      this.ctx.webkitLineDashOffset = dashPhase;
     },
-    setRenderingIntent: function canvasGraphicsSetRenderingIntent(intent) {
+    setRenderingIntent: function CanvasGraphics_setRenderingIntent(intent) {
       TODO('set rendering intent: ' + intent);
     },
-    setFlatness: function canvasGraphicsSetFlatness(flatness) {
+    setFlatness: function CanvasGraphics_setFlatness(flatness) {
       TODO('set flatness: ' + flatness);
     },
-    setGState: function canvasGraphicsSetGState(states) {
+    setGState: function CanvasGraphics_setGState(states) {
       for (var i = 0, ii = states.length; i < ii; i++) {
         var state = states[i];
         var key = state[0];
@@ -224,55 +406,57 @@ var CanvasGraphics = (function canvasGraphics() {
         }
       }
     },
-    save: function canvasGraphicsSave() {
+    save: function CanvasGraphics_save() {
       this.ctx.save();
       var old = this.current;
       this.stateStack.push(old);
       this.current = old.clone();
     },
-    restore: function canvasGraphicsRestore() {
+    restore: function CanvasGraphics_restore() {
       var prev = this.stateStack.pop();
       if (prev) {
         this.current = prev;
         this.ctx.restore();
       }
     },
-    transform: function canvasGraphicsTransform(a, b, c, d, e, f) {
+    transform: function CanvasGraphics_transform(a, b, c, d, e, f) {
       this.ctx.transform(a, b, c, d, e, f);
     },
 
     // Path
-    moveTo: function canvasGraphicsMoveTo(x, y) {
+    moveTo: function CanvasGraphics_moveTo(x, y) {
       this.ctx.moveTo(x, y);
       this.current.setCurrentPoint(x, y);
     },
-    lineTo: function canvasGraphicsLineTo(x, y) {
+    lineTo: function CanvasGraphics_lineTo(x, y) {
       this.ctx.lineTo(x, y);
       this.current.setCurrentPoint(x, y);
     },
-    curveTo: function canvasGraphicsCurveTo(x1, y1, x2, y2, x3, y3) {
+    curveTo: function CanvasGraphics_curveTo(x1, y1, x2, y2, x3, y3) {
       this.ctx.bezierCurveTo(x1, y1, x2, y2, x3, y3);
       this.current.setCurrentPoint(x3, y3);
     },
-    curveTo2: function canvasGraphicsCurveTo2(x2, y2, x3, y3) {
+    curveTo2: function CanvasGraphics_curveTo2(x2, y2, x3, y3) {
       var current = this.current;
       this.ctx.bezierCurveTo(current.x, current.y, x2, y2, x3, y3);
       current.setCurrentPoint(x3, y3);
     },
-    curveTo3: function canvasGraphicsCurveTo3(x1, y1, x3, y3) {
+    curveTo3: function CanvasGraphics_curveTo3(x1, y1, x3, y3) {
       this.curveTo(x1, y1, x3, y3, x3, y3);
       this.current.setCurrentPoint(x3, y3);
     },
-    closePath: function canvasGraphicsClosePath() {
+    closePath: function CanvasGraphics_closePath() {
       this.ctx.closePath();
     },
-    rectangle: function canvasGraphicsRectangle(x, y, width, height) {
+    rectangle: function CanvasGraphics_rectangle(x, y, width, height) {
       this.ctx.rect(x, y, width, height);
     },
-    stroke: function canvasGraphicsStroke(consumePath) {
+    stroke: function CanvasGraphics_stroke(consumePath) {
       consumePath = typeof consumePath !== 'undefined' ? consumePath : true;
       var ctx = this.ctx;
       var strokeColor = this.current.strokeColor;
+      if (this.current.lineWidth === 0)
+        ctx.lineWidth = this.getSinglePixelWidth();
       // For stroke we want to temporarily change the global alpha to the
       // stroking alpha.
       ctx.globalAlpha = this.current.strokeAlpha;
@@ -292,11 +476,11 @@ var CanvasGraphics = (function canvasGraphics() {
       // Restore the global alpha to the fill alpha
       ctx.globalAlpha = this.current.fillAlpha;
     },
-    closeStroke: function canvasGraphicsCloseStroke() {
+    closeStroke: function CanvasGraphics_closeStroke() {
       this.closePath();
       this.stroke();
     },
-    fill: function canvasGraphicsFill(consumePath) {
+    fill: function CanvasGraphics_fill(consumePath) {
       consumePath = typeof consumePath !== 'undefined' ? consumePath : true;
       var ctx = this.ctx;
       var fillColor = this.current.fillColor;
@@ -313,126 +497,204 @@ var CanvasGraphics = (function canvasGraphics() {
       if (consumePath)
         this.consumePath();
     },
-    eoFill: function canvasGraphicsEoFill() {
+    eoFill: function CanvasGraphics_eoFill() {
       var savedFillRule = this.setEOFillRule();
       this.fill();
       this.restoreFillRule(savedFillRule);
     },
-    fillStroke: function canvasGraphicsFillStroke() {
+    fillStroke: function CanvasGraphics_fillStroke() {
       this.fill(false);
       this.stroke(false);
 
       this.consumePath();
     },
-    eoFillStroke: function canvasGraphicsEoFillStroke() {
+    eoFillStroke: function CanvasGraphics_eoFillStroke() {
       var savedFillRule = this.setEOFillRule();
       this.fillStroke();
       this.restoreFillRule(savedFillRule);
     },
-    closeFillStroke: function canvasGraphicsCloseFillStroke() {
+    closeFillStroke: function CanvasGraphics_closeFillStroke() {
       this.closePath();
       this.fillStroke();
     },
-    closeEOFillStroke: function canvasGraphicsCloseEOFillStroke() {
+    closeEOFillStroke: function CanvasGraphics_closeEOFillStroke() {
       var savedFillRule = this.setEOFillRule();
       this.closePath();
       this.fillStroke();
       this.restoreFillRule(savedFillRule);
     },
-    endPath: function canvasGraphicsEndPath() {
+    endPath: function CanvasGraphics_endPath() {
       this.consumePath();
     },
 
     // Clipping
-    clip: function canvasGraphicsClip() {
+    clip: function CanvasGraphics_clip() {
       this.pendingClip = NORMAL_CLIP;
     },
-    eoClip: function canvasGraphicsEoClip() {
+    eoClip: function CanvasGraphics_eoClip() {
       this.pendingClip = EO_CLIP;
     },
 
     // Text
-    beginText: function canvasGraphicsBeginText() {
+    beginText: function CanvasGraphics_beginText() {
       this.current.textMatrix = IDENTITY_MATRIX;
       this.current.x = this.current.lineX = 0;
       this.current.y = this.current.lineY = 0;
     },
-    endText: function canvasGraphicsEndText() {
+    endText: function CanvasGraphics_endText() {
     },
-    setCharSpacing: function canvasGraphicsSetCharSpacing(spacing) {
+    setCharSpacing: function CanvasGraphics_setCharSpacing(spacing) {
       this.current.charSpacing = spacing;
     },
-    setWordSpacing: function canvasGraphicsSetWordSpacing(spacing) {
+    setWordSpacing: function CanvasGraphics_setWordSpacing(spacing) {
       this.current.wordSpacing = spacing;
     },
-    setHScale: function canvasGraphicsSetHScale(scale) {
+    setHScale: function CanvasGraphics_setHScale(scale) {
       this.current.textHScale = scale / 100;
     },
-    setLeading: function canvasGraphicsSetLeading(leading) {
+    setLeading: function CanvasGraphics_setLeading(leading) {
       this.current.leading = -leading;
     },
-    setFont: function canvasGraphicsSetFont(fontRefName, size) {
-      var fontObj = this.objs.get(fontRefName).fontObj;
+    setFont: function CanvasGraphics_setFont(fontRefName, size) {
+      var fontObj = this.objs.get(fontRefName);
+      var current = this.current;
+
+      if (!fontObj)
+        error('Can\'t find font for ' + fontRefName);
+
+      // Slice-clone matrix so we can manipulate it without affecting original
+      if (fontObj.fontMatrix)
+        current.fontMatrix = fontObj.fontMatrix.slice(0);
+      else
+        current.fontMatrix = IDENTITY_MATRIX.slice(0);
 
-      if (!fontObj) {
-        throw 'Can\'t find font for ' + fontRefName;
+      // A valid matrix needs all main diagonal elements to be non-zero
+      // This also ensures we bypass FF bugzilla bug #719844.
+      if (current.fontMatrix[0] === 0 ||
+          current.fontMatrix[3] === 0) {
+        warn('Invalid font matrix for font ' + fontRefName);
       }
 
-      var name = fontObj.loadedName || 'sans-serif';
+      // The spec for Tf (setFont) says that 'size' specifies the font 'scale',
+      // and in some docs this can be negative (inverted x-y axes).
+      // We implement this condition with fontMatrix.
+      if (size < 0) {
+        size = -size;
+        current.fontMatrix[0] *= -1;
+        current.fontMatrix[3] *= -1;
+      }
 
       this.current.font = fontObj;
       this.current.fontSize = size;
 
+      if (fontObj.coded)
+        return; // we don't need ctx.font for Type3 fonts
+
       var name = fontObj.loadedName || 'sans-serif';
       var bold = fontObj.black ? (fontObj.bold ? 'bolder' : 'bold') :
                                  (fontObj.bold ? 'bold' : 'normal');
 
       var italic = fontObj.italic ? 'italic' : 'normal';
-      var serif = fontObj.serif ? 'serif' : 'sans-serif';
+      var serif = fontObj.isSerifFont ? 'serif' : 'sans-serif';
       var typeface = '"' + name + '", ' + serif;
-      var rule = italic + ' ' + bold + ' ' + size + 'px ' + typeface;
+
+      // Some font backends cannot handle fonts below certain size.
+      // Keeping the font at minimal size and using the fontSizeScale to change
+      // the current transformation matrix before the fillText/strokeText.
+      // See https://bugzilla.mozilla.org/show_bug.cgi?id=726227
+      var browserFontSize = size >= MIN_FONT_SIZE ? size : MIN_FONT_SIZE;
+      this.current.fontSizeScale = browserFontSize != MIN_FONT_SIZE ? 1.0 :
+                                   size / MIN_FONT_SIZE;
+
+      var rule = italic + ' ' + bold + ' ' + browserFontSize + 'px ' + typeface;
       this.ctx.font = rule;
     },
-    setTextRenderingMode: function canvasGraphicsSetTextRenderingMode(mode) {
-      TODO('text rendering mode: ' + mode);
+    setTextRenderingMode: function CanvasGraphics_setTextRenderingMode(mode) {
+      if (mode >= TextRenderingMode.FILL_ADD_TO_PATH)
+        TODO('unsupported text rendering mode: ' + mode);
+      this.current.textRenderingMode = mode;
     },
-    setTextRise: function canvasGraphicsSetTextRise(rise) {
+    setTextRise: function CanvasGraphics_setTextRise(rise) {
       TODO('text rise: ' + rise);
     },
-    moveText: function canvasGraphicsMoveText(x, y) {
+    moveText: function CanvasGraphics_moveText(x, y) {
       this.current.x = this.current.lineX += x;
       this.current.y = this.current.lineY += y;
     },
-    setLeadingMoveText: function canvasGraphicsSetLeadingMoveText(x, y) {
+    setLeadingMoveText: function CanvasGraphics_setLeadingMoveText(x, y) {
       this.setLeading(-y);
       this.moveText(x, y);
     },
-    setTextMatrix: function canvasGraphicsSetTextMatrix(a, b, c, d, e, f) {
+    setTextMatrix: function CanvasGraphics_setTextMatrix(a, b, c, d, e, f) {
       this.current.textMatrix = [a, b, c, d, e, f];
 
       this.current.x = this.current.lineX = 0;
       this.current.y = this.current.lineY = 0;
     },
-    nextLine: function canvasGraphicsNextLine() {
+    nextLine: function CanvasGraphics_nextLine() {
       this.moveText(0, this.current.leading);
     },
-    showText: function canvasGraphicsShowText(text) {
+    applyTextTransforms: function CanvasGraphics_applyTextTransforms() {
+      var ctx = this.ctx;
+      var current = this.current;
+      var textHScale = current.textHScale;
+      var fontMatrix = current.fontMatrix || IDENTITY_MATRIX;
+
+      ctx.transform.apply(ctx, current.textMatrix);
+      ctx.scale(1, -1);
+      ctx.translate(current.x, -1 * current.y);
+      ctx.transform.apply(ctx, fontMatrix);
+      ctx.scale(textHScale, 1);
+    },
+    getTextGeometry: function CanvasGraphics_getTextGeometry() {
+      var geometry = {};
+      var ctx = this.ctx;
+      var font = this.current.font;
+      var ctxMatrix = ctx.mozCurrentTransform;
+      if (ctxMatrix) {
+        var bl = Util.applyTransform([0, 0], ctxMatrix);
+        var tr = Util.applyTransform([1, 1], ctxMatrix);
+        geometry.x = bl[0];
+        geometry.y = bl[1];
+        geometry.hScale = tr[0] - bl[0];
+        geometry.vScale = tr[1] - bl[1];
+      }
+      geometry.spaceWidth = font.spaceWidth;
+      return geometry;
+    },
+
+    showText: function CanvasGraphics_showText(str, skipTextSelection) {
       var ctx = this.ctx;
       var current = this.current;
       var font = current.font;
-      var glyphs = font.charsToGlyphs(text);
+      var glyphs = font.charsToGlyphs(str);
       var fontSize = current.fontSize;
+      var fontSizeScale = current.fontSizeScale;
       var charSpacing = current.charSpacing;
       var wordSpacing = current.wordSpacing;
       var textHScale = current.textHScale;
+      var fontMatrix = current.fontMatrix || IDENTITY_MATRIX;
+      var textHScale2 = textHScale * fontMatrix[0];
       var glyphsLength = glyphs.length;
+      var textLayer = this.textLayer;
+      var text = {str: '', length: 0, canvasWidth: 0, geom: {}};
+      var textSelection = textLayer && !skipTextSelection ? true : false;
+      var textRenderingMode = current.textRenderingMode;
+
+      // Type3 fonts - each glyph is a "mini-PDF"
       if (font.coded) {
         ctx.save();
         ctx.transform.apply(ctx, current.textMatrix);
         ctx.translate(current.x, current.y);
 
-        var fontMatrix = font.fontMatrix || IDENTITY_MATRIX;
-        ctx.scale(1 / textHScale, 1);
+        ctx.scale(textHScale, 1);
+
+        if (textSelection) {
+          this.save();
+          ctx.scale(1, -1);
+          text.geom = this.getTextGeometry();
+          this.restore();
+        }
         for (var i = 0; i < glyphsLength; ++i) {
 
           var glyph = glyphs[i];
@@ -445,85 +707,183 @@ var CanvasGraphics = (function canvasGraphics() {
           this.save();
           ctx.scale(fontSize, fontSize);
           ctx.transform.apply(ctx, fontMatrix);
-          this.executeIRQueue(glyph.codeIRQueue);
+          this.executeOperatorList(glyph.operatorList);
           this.restore();
 
           var transformed = Util.applyTransform([glyph.width, 0], fontMatrix);
-          var width = transformed[0] * fontSize + charSpacing;
+          var width = transformed[0] * fontSize +
+              Util.sign(current.fontMatrix[0]) * charSpacing;
 
           ctx.translate(width, 0);
-          current.x += width;
+          current.x += width * textHScale;
 
+          text.str += glyph.unicode;
+          text.length++;
+          text.canvasWidth += width;
         }
         ctx.restore();
       } else {
         ctx.save();
-        ctx.transform.apply(ctx, current.textMatrix);
-        ctx.scale(1, -1);
-        ctx.translate(current.x, -1 * current.y);
-        ctx.transform.apply(ctx, font.fontMatrix || IDENTITY_MATRIX);
+        this.applyTextTransforms();
+
+        var lineWidth = current.lineWidth;
+        var scale = Math.abs(current.textMatrix[0] * fontMatrix[0]);
+        if (scale == 0 || lineWidth == 0)
+          lineWidth = this.getSinglePixelWidth();
+        else
+          lineWidth /= scale;
 
-        ctx.scale(1 / textHScale, 1);
+        if (textSelection)
+          text.geom = this.getTextGeometry();
 
-        var width = 0;
+        if (fontSizeScale != 1.0) {
+          ctx.scale(fontSizeScale, fontSizeScale);
+          lineWidth /= fontSizeScale;
+        }
+
+        ctx.lineWidth = lineWidth;
+
+        var x = 0;
         for (var i = 0; i < glyphsLength; ++i) {
           var glyph = glyphs[i];
           if (glyph === null) {
             // word break
-            width += wordSpacing;
+            x += Util.sign(current.fontMatrix[0]) * wordSpacing;
             continue;
           }
 
-          var unicode = glyph.unicode;
-          var char = (unicode >= 0x10000) ?
-            String.fromCharCode(0xD800 | ((unicode - 0x10000) >> 10),
-            0xDC00 | (unicode & 0x3FF)) : String.fromCharCode(unicode);
+          var character = glyph.fontChar;
+          var charWidth = glyph.width * fontSize * 0.001 +
+              Util.sign(current.fontMatrix[0]) * charSpacing;
+
+          if (!glyph.disabled) {
+            var scaledX = x / fontSizeScale;
+            switch (textRenderingMode) {
+              default: // other unsupported rendering modes
+              case TextRenderingMode.FILL:
+              case TextRenderingMode.FILL_ADD_TO_PATH:
+                ctx.fillText(character, scaledX, 0);
+                break;
+              case TextRenderingMode.STROKE:
+              case TextRenderingMode.STROKE_ADD_TO_PATH:
+                ctx.strokeText(character, scaledX, 0);
+                break;
+              case TextRenderingMode.FILL_STROKE:
+              case TextRenderingMode.FILL_STROKE_ADD_TO_PATH:
+                ctx.fillText(character, scaledX, 0);
+                ctx.strokeText(character, scaledX, 0);
+                break;
+              case TextRenderingMode.INVISIBLE:
+                break;
+            }
+          }
 
-          ctx.fillText(char, width, 0);
-          width += glyph.width * fontSize * 0.001 + charSpacing;
+          x += charWidth;
+
+          var glyphUnicode = glyph.unicode === ' ' ? '\u00A0' : glyph.unicode;
+          var glyphUnicodeLength = glyphUnicode.length;
+          //reverse an arabic ligature
+          if (glyphUnicodeLength > 1 &&
+              isRTLRangeFor(glyphUnicode.charCodeAt(0))) {
+            for (var ii = glyphUnicodeLength - 1; ii >= 0; ii--)
+              text.str += glyphUnicode[ii];
+          } else
+            text.str += glyphUnicode;
+          text.length += glyphUnicodeLength;
+          text.canvasWidth += charWidth;
         }
-        current.x += width;
-
+        current.x += x * textHScale2;
         ctx.restore();
       }
-    },
 
-    showSpacedText: function canvasGraphicsShowSpacedText(arr) {
+      if (textSelection)
+        this.textLayer.appendText(text, font.loadedName, fontSize);
+
+      return text;
+    },
+    showSpacedText: function CanvasGraphics_showSpacedText(arr) {
       var ctx = this.ctx;
       var current = this.current;
+      var font = current.font;
       var fontSize = current.fontSize;
       var textHScale = current.textHScale;
+      if (!font.coded)
+        textHScale *= (current.fontMatrix || IDENTITY_MATRIX)[0];
       var arrLength = arr.length;
+      var textLayer = this.textLayer;
+      var text = {str: '', length: 0, canvasWidth: 0, geom: {}};
+      var textSelection = textLayer ? true : false;
+
+      if (textSelection) {
+        ctx.save();
+        // Type3 fonts - each glyph is a "mini-PDF" (see also showText)
+        if (font.coded) {
+          ctx.transform.apply(ctx, current.textMatrix);
+          ctx.scale(1, -1);
+          ctx.translate(current.x, -1 * current.y);
+          ctx.scale(textHScale, 1);
+        } else
+          this.applyTextTransforms();
+        text.geom = this.getTextGeometry();
+        ctx.restore();
+      }
+
       for (var i = 0; i < arrLength; ++i) {
         var e = arr[i];
         if (isNum(e)) {
-          current.x -= e * 0.001 * fontSize * textHScale;
+          var spacingLength = -e * 0.001 * fontSize * textHScale;
+          current.x += spacingLength;
+
+          if (textSelection) {
+            // Emulate precise spacing via HTML spaces
+            text.canvasWidth += spacingLength;
+            if (e < 0 && text.geom.spaceWidth > 0) { // avoid div by zero
+              var numFakeSpaces = Math.round(-e / text.geom.spaceWidth);
+              if (numFakeSpaces > 0) {
+                text.str += '\u00A0';
+                text.length++;
+              }
+            }
+          }
         } else if (isString(e)) {
-          this.showText(e);
+          var shownText = this.showText(e, true);
+
+          if (textSelection) {
+            if (shownText.str === ' ') {
+              text.str += '\u00A0';
+            } else {
+              text.str += shownText.str;
+            }
+            text.canvasWidth += shownText.canvasWidth;
+            text.length += shownText.length;
+          }
         } else {
           malformed('TJ array element ' + e + ' is not string or num');
         }
       }
+
+      if (textSelection)
+        this.textLayer.appendText(text, font.loadedName, fontSize);
     },
-    nextLineShowText: function canvasGraphicsNextLineShowText(text) {
+    nextLineShowText: function CanvasGraphics_nextLineShowText(text) {
       this.nextLine();
       this.showText(text);
     },
     nextLineSetSpacingShowText:
-      function canvasGraphicsNextLineSetSpacingShowText(wordSpacing,
-                                                        charSpacing,
-                                                        text) {
+      function CanvasGraphics_nextLineSetSpacingShowText(wordSpacing,
+                                                         charSpacing,
+                                                         text) {
       this.setWordSpacing(wordSpacing);
       this.setCharSpacing(charSpacing);
       this.nextLineShowText(text);
     },
 
     // Type3 fonts
-    setCharWidth: function canvasGraphicsSetCharWidth(xWidth, yWidth) {
+    setCharWidth: function CanvasGraphics_setCharWidth(xWidth, yWidth) {
       // We can safely ignore this since the width should be the same
       // as the width in the Widths array.
     },
-    setCharWidthAndBounds: function canvasGraphicsSetCharWidthAndBounds(xWidth,
+    setCharWidthAndBounds: function CanvasGraphics_setCharWidthAndBounds(xWidth,
                                                                         yWidth,
                                                                         llx,
                                                                         lly,
@@ -537,20 +897,20 @@ var CanvasGraphics = (function canvasGraphics() {
     },
 
     // Color
-    setStrokeColorSpace: function canvasGraphicsSetStrokeColorSpace(raw) {
+    setStrokeColorSpace: function CanvasGraphics_setStrokeColorSpace(raw) {
       this.current.strokeColorSpace = ColorSpace.fromIR(raw);
     },
-    setFillColorSpace: function canvasGraphicsSetFillColorSpace(raw) {
+    setFillColorSpace: function CanvasGraphics_setFillColorSpace(raw) {
       this.current.fillColorSpace = ColorSpace.fromIR(raw);
     },
-    setStrokeColor: function canvasGraphicsSetStrokeColor(/*...*/) {
+    setStrokeColor: function CanvasGraphics_setStrokeColor(/*...*/) {
       var cs = this.current.strokeColorSpace;
-      var color = cs.getRgb(arguments);
-      var color = Util.makeCssRgb.apply(null, cs.getRgb(arguments));
+      var rgbColor = cs.getRgb(arguments);
+      var color = Util.makeCssRgb(rgbColor[0], rgbColor[1], rgbColor[2]);
       this.ctx.strokeStyle = color;
       this.current.strokeColor = color;
     },
-    getColorN_IR_Pattern: function canvasGraphicsGetColorN_IR_Pattern(IR, cs) {
+    getColorN_Pattern: function CanvasGraphics_getColorN_Pattern(IR, cs) {
       if (IR[0] == 'TilingPattern') {
         var args = IR[1];
         var base = cs.base;
@@ -566,37 +926,38 @@ var CanvasGraphics = (function canvasGraphics() {
         }
         var pattern = new TilingPattern(IR, color, this.ctx, this.objs);
       } else if (IR[0] == 'RadialAxial' || IR[0] == 'Dummy') {
-        var pattern = Pattern.shadingFromIR(this.ctx, IR);
+        var pattern = Pattern.shadingFromIR(IR);
       } else {
-        throw 'Unkown IR type';
+        error('Unkown IR type ' + IR[0]);
       }
       return pattern;
     },
-    setStrokeColorN_IR: function canvasGraphicsSetStrokeColorN(/*...*/) {
+    setStrokeColorN: function CanvasGraphics_setStrokeColorN(/*...*/) {
       var cs = this.current.strokeColorSpace;
 
       if (cs.name == 'Pattern') {
-        this.current.strokeColor = this.getColorN_IR_Pattern(arguments, cs);
+        this.current.strokeColor = this.getColorN_Pattern(arguments, cs);
       } else {
         this.setStrokeColor.apply(this, arguments);
       }
     },
-    setFillColor: function canvasGraphicsSetFillColor(/*...*/) {
+    setFillColor: function CanvasGraphics_setFillColor(/*...*/) {
       var cs = this.current.fillColorSpace;
-      var color = Util.makeCssRgb.apply(null, cs.getRgb(arguments));
+      var rgbColor = cs.getRgb(arguments);
+      var color = Util.makeCssRgb(rgbColor[0], rgbColor[1], rgbColor[2]);
       this.ctx.fillStyle = color;
       this.current.fillColor = color;
     },
-    setFillColorN_IR: function canvasGraphicsSetFillColorN(/*...*/) {
+    setFillColorN: function CanvasGraphics_setFillColorN(/*...*/) {
       var cs = this.current.fillColorSpace;
 
       if (cs.name == 'Pattern') {
-        this.current.fillColor = this.getColorN_IR_Pattern(arguments, cs);
+        this.current.fillColor = this.getColorN_Pattern(arguments, cs);
       } else {
         this.setFillColor.apply(this, arguments);
       }
     },
-    setStrokeGray: function canvasGraphicsSetStrokeGray(gray) {
+    setStrokeGray: function CanvasGraphics_setStrokeGray(gray) {
       if (!(this.current.strokeColorSpace instanceof DeviceGrayCS))
         this.current.strokeColorSpace = new DeviceGrayCS();
 
@@ -604,7 +965,7 @@ var CanvasGraphics = (function canvasGraphics() {
       this.ctx.strokeStyle = color;
       this.current.strokeColor = color;
     },
-    setFillGray: function canvasGraphicsSetFillGray(gray) {
+    setFillGray: function CanvasGraphics_setFillGray(gray) {
       if (!(this.current.fillColorSpace instanceof DeviceGrayCS))
         this.current.fillColorSpace = new DeviceGrayCS();
 
@@ -612,7 +973,7 @@ var CanvasGraphics = (function canvasGraphics() {
       this.ctx.fillStyle = color;
       this.current.fillColor = color;
     },
-    setStrokeRGBColor: function canvasGraphicsSetStrokeRGBColor(r, g, b) {
+    setStrokeRGBColor: function CanvasGraphics_setStrokeRGBColor(r, g, b) {
       if (!(this.current.strokeColorSpace instanceof DeviceRgbCS))
         this.current.strokeColorSpace = new DeviceRgbCS();
 
@@ -620,7 +981,7 @@ var CanvasGraphics = (function canvasGraphics() {
       this.ctx.strokeStyle = color;
       this.current.strokeColor = color;
     },
-    setFillRGBColor: function canvasGraphicsSetFillRGBColor(r, g, b) {
+    setFillRGBColor: function CanvasGraphics_setFillRGBColor(r, g, b) {
       if (!(this.current.fillColorSpace instanceof DeviceRgbCS))
         this.current.fillColorSpace = new DeviceRgbCS();
 
@@ -628,7 +989,7 @@ var CanvasGraphics = (function canvasGraphics() {
       this.ctx.fillStyle = color;
       this.current.fillColor = color;
     },
-    setStrokeCMYKColor: function canvasGraphicsSetStrokeCMYKColor(c, m, y, k) {
+    setStrokeCMYKColor: function CanvasGraphics_setStrokeCMYKColor(c, m, y, k) {
       if (!(this.current.strokeColorSpace instanceof DeviceCmykCS))
         this.current.strokeColorSpace = new DeviceCmykCS();
 
@@ -636,7 +997,7 @@ var CanvasGraphics = (function canvasGraphics() {
       this.ctx.strokeStyle = color;
       this.current.strokeColor = color;
     },
-    setFillCMYKColor: function canvasGraphicsSetFillCMYKColor(c, m, y, k) {
+    setFillCMYKColor: function CanvasGraphics_setFillCMYKColor(c, m, y, k) {
       if (!(this.current.fillColorSpace instanceof DeviceCmykCS))
         this.current.fillColorSpace = new DeviceCmykCS();
 
@@ -645,11 +1006,12 @@ var CanvasGraphics = (function canvasGraphics() {
       this.current.fillColor = color;
     },
 
-    shadingFill: function canvasGraphicsShadingFill(patternIR) {
+    shadingFill: function CanvasGraphics_shadingFill(patternIR) {
       var ctx = this.ctx;
 
       this.save();
-      ctx.fillStyle = Pattern.shadingFromIR(ctx, patternIR);
+      var pattern = Pattern.shadingFromIR(patternIR);
+      ctx.fillStyle = pattern.getPattern(ctx);
 
       var inv = ctx.mozCurrentTransformInverse;
       if (inv) {
@@ -658,9 +1020,9 @@ var CanvasGraphics = (function canvasGraphics() {
         var height = canvas.height;
 
         var bl = Util.applyTransform([0, 0], inv);
-        var br = Util.applyTransform([0, width], inv);
-        var ul = Util.applyTransform([height, 0], inv);
-        var ur = Util.applyTransform([height, width], inv);
+        var br = Util.applyTransform([0, height], inv);
+        var ul = Util.applyTransform([width, 0], inv);
+        var ur = Util.applyTransform([width, height], inv);
 
         var x0 = Math.min(bl[0], br[0], ul[0], ur[0]);
         var y0 = Math.min(bl[1], br[1], ul[1], ur[1]);
@@ -682,14 +1044,14 @@ var CanvasGraphics = (function canvasGraphics() {
     },
 
     // Images
-    beginInlineImage: function canvasGraphicsBeginInlineImage() {
+    beginInlineImage: function CanvasGraphics_beginInlineImage() {
       error('Should not call beginInlineImage');
     },
-    beginImageData: function canvasGraphicsBeginImageData() {
+    beginImageData: function CanvasGraphics_beginImageData() {
       error('Should not call beginImageData');
     },
 
-    paintFormXObjectBegin: function canvasGraphicsPaintFormXObjectBegin(matrix,
+    paintFormXObjectBegin: function CanvasGraphics_paintFormXObjectBegin(matrix,
                                                                         bbox) {
       this.save();
 
@@ -705,13 +1067,13 @@ var CanvasGraphics = (function canvasGraphics() {
       }
     },
 
-    paintFormXObjectEnd: function canvasGraphicsPaintFormXObjectEnd() {
+    paintFormXObjectEnd: function CanvasGraphics_paintFormXObjectEnd() {
       this.restore();
     },
 
-    paintJpegXObject: function canvasGraphicsPaintJpegXObject(objId, w, h) {
-      var image = this.objs.get(objId);
-      if (!image) {
+    paintJpegXObject: function CanvasGraphics_paintJpegXObject(objId, w, h) {
+      var domImage = this.objs.get(objId);
+      if (!domImage) {
         error('Dependent image isn\'t ready yet');
       }
 
@@ -721,14 +1083,13 @@ var CanvasGraphics = (function canvasGraphics() {
       // scale the image to the unit square
       ctx.scale(1 / w, -1 / h);
 
-      var domImage = image.getImage();
       ctx.drawImage(domImage, 0, 0, domImage.width, domImage.height,
                     0, -h, w, h);
 
       this.restore();
     },
 
-    paintImageMaskXObject: function canvasGraphicsPaintImageMaskXObject(
+    paintImageMaskXObject: function CanvasGraphics_paintImageMaskXObject(
                              imgArray, inverseDecode, width, height) {
       function applyStencilMask(buffer, inverseDecode) {
         var imgArrayPos = 0;
@@ -758,7 +1119,7 @@ var CanvasGraphics = (function canvasGraphics() {
       // scale the image to the unit square
       ctx.scale(1 / w, -1 / h);
 
-      var tmpCanvas = new this.ScratchCanvas(w, h);
+      var tmpCanvas = createScratchCanvas(w, h);
       var tmpCtx = tmpCanvas.getContext('2d');
 
       var fillColor = this.current.fillColor;
@@ -777,7 +1138,11 @@ var CanvasGraphics = (function canvasGraphics() {
       this.restore();
     },
 
-    paintImageXObject: function canvasGraphicsPaintImageXObject(imgData) {
+    paintImageXObject: function CanvasGraphics_paintImageXObject(objId) {
+      var imgData = this.objs.get(objId);
+      if (!imgData)
+        error('Dependent image isn\'t ready yet');
+
       this.save();
       var ctx = this.ctx;
       var w = imgData.width;
@@ -785,59 +1150,49 @@ var CanvasGraphics = (function canvasGraphics() {
       // scale the image to the unit square
       ctx.scale(1 / w, -1 / h);
 
-      var tmpCanvas = new this.ScratchCanvas(w, h);
+      var tmpCanvas = createScratchCanvas(w, h);
       var tmpCtx = tmpCanvas.getContext('2d');
-      var tmpImgData;
+      this.putBinaryImageData(tmpCtx, imgData, w, h);
 
-      // Some browsers can set an UInt8Array directly as imageData, some
-      // can't. As long as we don't have proper feature detection, just
-      // copy over each pixel and set the imageData that way.
-      tmpImgData = tmpCtx.getImageData(0, 0, w, h);
-
-      // Copy over the imageData.
-      var tmpImgDataPixels = tmpImgData.data;
-      var len = tmpImgDataPixels.length;
-
-      while (len--) {
-        tmpImgDataPixels[len] = imgData.data[len];
-      }
-
-      tmpCtx.putImageData(tmpImgData, 0, 0);
       ctx.drawImage(tmpCanvas, 0, -h);
       this.restore();
     },
 
+    putBinaryImageData: function CanvasGraphics_putBinaryImageData() {
+      //
+    },
+
     // Marked content
 
-    markPoint: function canvasGraphicsMarkPoint(tag) {
+    markPoint: function CanvasGraphics_markPoint(tag) {
       TODO('Marked content');
     },
-    markPointProps: function canvasGraphicsMarkPointProps(tag, properties) {
+    markPointProps: function CanvasGraphics_markPointProps(tag, properties) {
       TODO('Marked content');
     },
-    beginMarkedContent: function canvasGraphicsBeginMarkedContent(tag) {
+    beginMarkedContent: function CanvasGraphics_beginMarkedContent(tag) {
       TODO('Marked content');
     },
-    beginMarkedContentProps:
-      function canvasGraphicsBeginMarkedContentProps(tag, properties) {
+    beginMarkedContentProps: function CanvasGraphics_beginMarkedContentProps(
+                                        tag, properties) {
       TODO('Marked content');
     },
-    endMarkedContent: function canvasGraphicsEndMarkedContent() {
+    endMarkedContent: function CanvasGraphics_endMarkedContent() {
       TODO('Marked content');
     },
 
     // Compatibility
 
-    beginCompat: function canvasGraphicsBeginCompat() {
+    beginCompat: function CanvasGraphics_beginCompat() {
       TODO('ignore undefined operators (should we do that anyway?)');
     },
-    endCompat: function canvasGraphicsEndCompat() {
+    endCompat: function CanvasGraphics_endCompat() {
       TODO('stop ignoring undefined operators');
     },
 
     // Helper functions
 
-    consumePath: function canvasGraphicsConsumePath() {
+    consumePath: function CanvasGraphics_consumePath() {
       if (this.pendingClip) {
         var savedFillRule = null;
         if (this.pendingClip == EO_CLIP)
@@ -854,16 +1209,55 @@ var CanvasGraphics = (function canvasGraphics() {
     // We generally keep the canvas context set for
     // nonzero-winding, and just set evenodd for the operations
     // that need them.
-    setEOFillRule: function canvasGraphicsSetEOFillRule() {
+    setEOFillRule: function CanvasGraphics_setEOFillRule() {
       var savedFillRule = this.ctx.mozFillRule;
       this.ctx.mozFillRule = 'evenodd';
       return savedFillRule;
     },
-    restoreFillRule: function canvasGraphicsRestoreFillRule(rule) {
+    restoreFillRule: function CanvasGraphics_restoreFillRule(rule) {
       this.ctx.mozFillRule = rule;
+    },
+    getSinglePixelWidth: function CanvasGraphics_getSinglePixelWidth(scale) {
+      var inverse = this.ctx.mozCurrentTransformInverse;
+      return Math.abs(inverse[0] + inverse[2]);
     }
   };
 
-  return constructor;
+  return CanvasGraphics;
 })();
 
+if (!isWorker) {
+  // Feature detection if the browser can use an Uint8Array directly as imgData.
+  var canvas = document.createElement('canvas');
+  canvas.width = 1;
+  canvas.height = 1;
+  var ctx = canvas.getContext('2d');
+
+  try {
+    ctx.putImageData({
+      width: 1,
+      height: 1,
+      data: new Uint8Array(4)
+    }, 0, 0);
+
+    CanvasGraphics.prototype.putBinaryImageData =
+      function CanvasGraphicsPutBinaryImageDataNative(ctx, imgData) {
+        ctx.putImageData(imgData, 0, 0);
+      };
+  } catch (e) {
+    CanvasGraphics.prototype.putBinaryImageData =
+      function CanvasGraphicsPutBinaryImageDataShim(ctx, imgData, w, h) {
+        var tmpImgData = ctx.getImageData(0, 0, w, h);
+
+        // Copy over the imageData pixel by pixel.
+        var tmpImgDataPixels = tmpImgData.data;
+        var len = tmpImgDataPixels.length;
+
+        while (len--) {
+          tmpImgDataPixels[len] = imgData.data[len];
+        }
+
+        ctx.putImageData(tmpImgData, 0, 0);
+      };
+  }
+}
diff --git a/apps/files_pdfviewer/js/pdfjs/src/charsets.js b/apps/files_pdfviewer/js/pdfjs/src/charsets.js
old mode 100755
new mode 100644
diff --git a/apps/files_pdfviewer/js/pdfjs/src/cidmaps.js b/apps/files_pdfviewer/js/pdfjs/src/cidmaps.js
old mode 100755
new mode 100644
diff --git a/apps/files_pdfviewer/js/pdfjs/src/colorspace.js b/apps/files_pdfviewer/js/pdfjs/src/colorspace.js
old mode 100755
new mode 100644
index b369d0f884fe3f26d25b4840c656e4e2fa4c1e95..8d8290109decd1ca1868c5852db7338161a27601
--- a/apps/files_pdfviewer/js/pdfjs/src/colorspace.js
+++ b/apps/files_pdfviewer/js/pdfjs/src/colorspace.js
@@ -3,34 +3,34 @@
 
 'use strict';
 
-var ColorSpace = (function colorSpaceColorSpace() {
+var ColorSpace = (function ColorSpaceClosure() {
   // Constructor should define this.numComps, this.defaultColor, this.name
-  function constructor() {
+  function ColorSpace() {
     error('should not call ColorSpace constructor');
   }
 
-  constructor.prototype = {
+  ColorSpace.prototype = {
     // Input: array of size numComps representing color component values
     // Output: array of rgb values, each value ranging from [0.1]
-    getRgb: function colorSpaceGetRgb(color) {
+    getRgb: function ColorSpace_getRgb(color) {
       error('Should not call ColorSpace.getRgb: ' + color);
     },
     // Input: Uint8Array of component values, each value scaled to [0,255]
     // Output: Uint8Array of rgb values, each value scaled to [0,255]
-    getRgbBuffer: function colorSpaceGetRgbBuffer(input) {
+    getRgbBuffer: function ColorSpace_getRgbBuffer(input) {
       error('Should not call ColorSpace.getRgbBuffer: ' + input);
     }
   };
 
-  constructor.parse = function colorSpaceParse(cs, xref, res) {
-    var IR = constructor.parseToIR(cs, xref, res);
+  ColorSpace.parse = function ColorSpace_parse(cs, xref, res) {
+    var IR = ColorSpace.parseToIR(cs, xref, res);
     if (IR instanceof AlternateCS)
       return IR;
 
-    return constructor.fromIR(IR);
+    return ColorSpace.fromIR(IR);
   };
 
-  constructor.fromIR = function colorSpaceFromIR(IR) {
+  ColorSpace.fromIR = function ColorSpace_fromIR(IR) {
     var name = isArray(IR) ? IR[0] : IR;
 
     switch (name) {
@@ -57,15 +57,20 @@ var ColorSpace = (function colorSpaceColorSpace() {
 
         return new AlternateCS(numComps, ColorSpace.fromIR(alt),
                                 PDFFunction.fromIR(tintFnIR));
+      case 'LabCS':
+        var whitePoint = IR[1].WhitePoint;
+        var blackPoint = IR[1].BlackPoint;
+        var range = IR[1].Range;
+        return new LabCS(whitePoint, blackPoint, range);
       default:
         error('Unkown name ' + name);
     }
     return null;
   };
 
-  constructor.parseToIR = function colorSpaceParseToIR(cs, xref, res) {
+  ColorSpace.parseToIR = function ColorSpace_parseToIR(cs, xref, res) {
     if (isName(cs)) {
-      var colorSpaces = xref.fetchIfRef(res.get('ColorSpace'));
+      var colorSpaces = res.get('ColorSpace');
       if (isDict(colorSpaces)) {
         var refcs = colorSpaces.get(cs.name);
         if (refcs)
@@ -130,6 +135,7 @@ var ColorSpace = (function colorSpaceColorSpace() {
             basePatternCS = ColorSpace.parseToIR(basePatternCS, xref, res);
           return ['PatternCS', basePatternCS];
         case 'Indexed':
+        case 'I':
           var baseIndexedCS = ColorSpace.parseToIR(cs[1], xref, res);
           var hiVal = cs[2] + 1;
           var lookup = xref.fetchIfRef(cs[3]);
@@ -146,6 +152,8 @@ var ColorSpace = (function colorSpaceColorSpace() {
           var tintFnIR = PDFFunction.getIR(xref, xref.fetchIfRef(cs[3]));
           return ['AlternateCS', numComps, alt, tintFnIR];
         case 'Lab':
+          var params = cs[1].getAll();
+          return ['LabCS', params];
         default:
           error('unimplemented color space object "' + mode + '"');
       }
@@ -154,8 +162,31 @@ var ColorSpace = (function colorSpaceColorSpace() {
     }
     return null;
   };
+  /**
+   * Checks if a decode map matches the default decode map for a color space.
+   * This handles the general decode maps where there are two values per
+   * component. e.g. [0, 1, 0, 1, 0, 1] for a RGB color.
+   * This does not handle Lab, Indexed, or Pattern decode maps since they are
+   * slightly different.
+   * @param {Array} decode Decode map (usually from an image).
+   * @param {Number} n Number of components the color space has.
+   */
+  ColorSpace.isDefaultDecode = function ColorSpace_isDefaultDecode(decode, n) {
+    if (!decode)
+      return true;
+
+    if (n * 2 !== decode.length) {
+      warning('The decode map is not the correct length');
+      return true;
+    }
+    for (var i = 0, ii = decode.length; i < ii; i += 2) {
+      if (decode[i] != 0 || decode[i + 1] != 1)
+        return false;
+    }
+    return true;
+  };
 
-  return constructor;
+  return ColorSpace;
 })();
 
 /**
@@ -164,8 +195,8 @@ var ColorSpace = (function colorSpaceColorSpace() {
  * Both color spaces use a tinting function to convert colors to a base color
  * space.
  */
-var AlternateCS = (function alternateCS() {
-  function constructor(numComps, base, tintFn) {
+var AlternateCS = (function AlternateCSClosure() {
+  function AlternateCS(numComps, base, tintFn) {
     this.name = 'Alternate';
     this.numComps = numComps;
     this.defaultColor = [];
@@ -175,12 +206,12 @@ var AlternateCS = (function alternateCS() {
     this.tintFn = tintFn;
   }
 
-  constructor.prototype = {
-    getRgb: function altcs_getRgb(color) {
+  AlternateCS.prototype = {
+    getRgb: function AlternateCS_getRgb(color) {
       var tinted = this.tintFn(color);
       return this.base.getRgb(tinted);
     },
-    getRgbBuffer: function altcs_getRgbBuffer(input, bits) {
+    getRgbBuffer: function AlternateCS_getRgbBuffer(input, bits) {
       var tintFn = this.tintFn;
       var base = this.base;
       var scale = 1 / ((1 << bits) - 1);
@@ -189,7 +220,7 @@ var AlternateCS = (function alternateCS() {
       var baseNumComps = base.numComps;
       var baseBuf = new Uint8Array(baseNumComps * length);
       var numComps = this.numComps;
-      var scaled = new Array(numComps);
+      var scaled = [];
 
       for (var i = 0; i < length; i += numComps) {
         for (var z = 0; z < numComps; ++z)
@@ -200,24 +231,27 @@ var AlternateCS = (function alternateCS() {
           baseBuf[pos++] = 255 * tinted[j];
       }
       return base.getRgbBuffer(baseBuf, 8);
+    },
+    isDefaultDecode: function AlternateCS_isDefaultDecode(decodeMap) {
+      return ColorSpace.isDefaultDecode(decodeMap, this.numComps);
     }
   };
 
-  return constructor;
+  return AlternateCS;
 })();
 
-var PatternCS = (function patternCS() {
-  function constructor(baseCS) {
+var PatternCS = (function PatternCSClosure() {
+  function PatternCS(baseCS) {
     this.name = 'Pattern';
     this.base = baseCS;
   }
-  constructor.prototype = {};
+  PatternCS.prototype = {};
 
-  return constructor;
+  return PatternCS;
 })();
 
-var IndexedCS = (function indexedCS() {
-  function constructor(base, highVal, lookup) {
+var IndexedCS = (function IndexedCSClosure() {
+  function IndexedCS(base, highVal, lookup) {
     this.name = 'Indexed';
     this.numComps = 1;
     this.defaultColor = [0];
@@ -240,8 +274,8 @@ var IndexedCS = (function indexedCS() {
     this.lookup = lookupArray;
   }
 
-  constructor.prototype = {
-    getRgb: function indexcs_getRgb(color) {
+  IndexedCS.prototype = {
+    getRgb: function IndexedCS_getRgb(color) {
       var numComps = this.base.numComps;
       var start = color[0] * numComps;
       var c = [];
@@ -251,7 +285,7 @@ var IndexedCS = (function indexedCS() {
 
       return this.base.getRgb(c);
     },
-    getRgbBuffer: function indexcs_getRgbBuffer(input) {
+    getRgbBuffer: function IndexedCS_getRgbBuffer(input) {
       var base = this.base;
       var numComps = base.numComps;
       var lookup = this.lookup;
@@ -267,24 +301,28 @@ var IndexedCS = (function indexedCS() {
       }
 
       return base.getRgbBuffer(baseBuf, 8);
+    },
+    isDefaultDecode: function IndexedCS_isDefaultDecode(decodeMap) {
+      // indexed color maps shouldn't be changed
+      return true;
     }
   };
-  return constructor;
+  return IndexedCS;
 })();
 
-var DeviceGrayCS = (function deviceGrayCS() {
-  function constructor() {
+var DeviceGrayCS = (function DeviceGrayCSClosure() {
+  function DeviceGrayCS() {
     this.name = 'DeviceGray';
     this.numComps = 1;
     this.defaultColor = [0];
   }
 
-  constructor.prototype = {
-    getRgb: function graycs_getRgb(color) {
+  DeviceGrayCS.prototype = {
+    getRgb: function DeviceGrayCS_getRgb(color) {
       var c = color[0];
       return [c, c, c];
     },
-    getRgbBuffer: function graycs_getRgbBuffer(input, bits) {
+    getRgbBuffer: function DeviceGrayCS_getRgbBuffer(input, bits) {
       var scale = 255 / ((1 << bits) - 1);
       var length = input.length;
       var rgbBuf = new Uint8Array(length * 3);
@@ -295,22 +333,25 @@ var DeviceGrayCS = (function deviceGrayCS() {
         rgbBuf[j++] = c;
       }
       return rgbBuf;
+    },
+    isDefaultDecode: function DeviceGrayCS_isDefaultDecode(decodeMap) {
+      return ColorSpace.isDefaultDecode(decodeMap, this.numComps);
     }
   };
-  return constructor;
+  return DeviceGrayCS;
 })();
 
-var DeviceRgbCS = (function deviceRgbCS() {
-  function constructor() {
+var DeviceRgbCS = (function DeviceRgbCSClosure() {
+  function DeviceRgbCS() {
     this.name = 'DeviceRGB';
     this.numComps = 3;
     this.defaultColor = [0, 0, 0];
   }
-  constructor.prototype = {
-    getRgb: function rgbcs_getRgb(color) {
+  DeviceRgbCS.prototype = {
+    getRgb: function DeviceRgbCS_getRgb(color) {
       return color;
     },
-    getRgbBuffer: function rgbcs_getRgbBuffer(input, bits) {
+    getRgbBuffer: function DeviceRgbCS_getRgbBuffer(input, bits) {
       if (bits == 8)
         return input;
       var scale = 255 / ((1 << bits) - 1);
@@ -319,73 +360,37 @@ var DeviceRgbCS = (function deviceRgbCS() {
       for (i = 0; i < length; ++i)
         rgbBuf[i] = (scale * input[i]) | 0;
       return rgbBuf;
+    },
+    isDefaultDecode: function DeviceRgbCS_isDefaultDecode(decodeMap) {
+      return ColorSpace.isDefaultDecode(decodeMap, this.numComps);
     }
   };
-  return constructor;
+  return DeviceRgbCS;
 })();
 
-var DeviceCmykCS = (function deviceCmykCS() {
-  function constructor() {
+var DeviceCmykCS = (function DeviceCmykCSClosure() {
+  function DeviceCmykCS() {
     this.name = 'DeviceCMYK';
     this.numComps = 4;
     this.defaultColor = [0, 0, 0, 1];
   }
-  constructor.prototype = {
-    getRgb: function cmykcs_getRgb(color) {
+  DeviceCmykCS.prototype = {
+    getRgb: function DeviceCmykCS_getRgb(color) {
       var c = color[0], m = color[1], y = color[2], k = color[3];
-      var c1 = 1 - c, m1 = 1 - m, y1 = 1 - y, k1 = 1 - k;
-
-      var x, r, g, b;
-      // this is a matrix multiplication, unrolled for performance
-      // code is taken from the poppler implementation
-      x = c1 * m1 * y1 * k1; // 0 0 0 0
-      r = g = b = x;
-      x = c1 * m1 * y1 * k;  // 0 0 0 1
-      r += 0.1373 * x;
-      g += 0.1216 * x;
-      b += 0.1255 * x;
-      x = c1 * m1 * y * k1;  // 0 0 1 0
-      r += x;
-      g += 0.9490 * x;
-      x = c1 * m1 * y * k;   // 0 0 1 1
-      r += 0.1098 * x;
-      g += 0.1020 * x;
-      x = c1 * m * y1 * k1;  // 0 1 0 0
-      r += 0.9255 * x;
-      b += 0.5490 * x;
-      x = c1 * m * y1 * k;   // 0 1 0 1
-      r += 0.1412 * x;
-      x = c1 * m * y * k1;   // 0 1 1 0
-      r += 0.9294 * x;
-      g += 0.1098 * x;
-      b += 0.1412 * x;
-      x = c1 * m * y * k;    // 0 1 1 1
-      r += 0.1333 * x;
-      x = c * m1 * y1 * k1;  // 1 0 0 0
-      g += 0.6784 * x;
-      b += 0.9373 * x;
-      x = c * m1 * y1 * k;   // 1 0 0 1
-      g += 0.0588 * x;
-      b += 0.1412 * x;
-      x = c * m1 * y * k1;   // 1 0 1 0
-      g += 0.6510 * x;
-      b += 0.3137 * x;
-      x = c * m1 * y * k;    // 1 0 1 1
-      g += 0.0745 * x;
-      x = c * m * y1 * k1;   // 1 1 0 0
-      r += 0.1804 * x;
-      g += 0.1922 * x;
-      b += 0.5725 * x;
-      x = c * m * y1 * k;    // 1 1 0 1
-      b += 0.0078 * x;
-      x = c * m * y * k1;    // 1 1 1 0
-      r += 0.2118 * x;
-      g += 0.2119 * x;
-      b += 0.2235 * x;
+
+      // CMYK -> CMY: http://www.easyrgb.com/index.php?X=MATH&H=14#text14
+      c = (c * (1 - k) + k);
+      m = (m * (1 - k) + k);
+      y = (y * (1 - k) + k);
+
+      // CMY -> RGB: http://www.easyrgb.com/index.php?X=MATH&H=12#text12
+      var r = (1 - c);
+      var g = (1 - m);
+      var b = (1 - y);
 
       return [r, g, b];
     },
-    getRgbBuffer: function cmykcs_getRgbBuffer(colorBuf, bits) {
+    getRgbBuffer: function DeviceCmykCS_getRgbBuffer(colorBuf, bits) {
       var scale = 1 / ((1 << bits) - 1);
       var length = colorBuf.length / 4;
       var rgbBuf = new Uint8Array(length * 3);
@@ -403,9 +408,125 @@ var DeviceCmykCS = (function deviceCmykCS() {
       }
 
       return rgbBuf;
+    },
+    isDefaultDecode: function DeviceCmykCS_isDefaultDecode(decodeMap) {
+      return ColorSpace.isDefaultDecode(decodeMap, this.numComps);
     }
   };
 
-  return constructor;
+  return DeviceCmykCS;
 })();
 
+//
+// LabCS: Based on "PDF Reference, Sixth Ed", p.250
+//
+var LabCS = (function LabCSClosure() {
+  function LabCS(whitePoint, blackPoint, range) {
+    this.name = 'Lab';
+    this.numComps = 3;
+    this.defaultColor = [0, 0, 0];
+
+    if (!whitePoint)
+      error('WhitePoint missing - required for color space Lab');
+    blackPoint = blackPoint || [0, 0, 0];
+    range = range || [-100, 100, -100, 100];
+
+    // Translate args to spec variables
+    this.XW = whitePoint[0];
+    this.YW = whitePoint[1];
+    this.ZW = whitePoint[2];
+    this.amin = range[0];
+    this.amax = range[1];
+    this.bmin = range[2];
+    this.bmax = range[3];
+
+    // These are here just for completeness - the spec doesn't offer any
+    // formulas that use BlackPoint in Lab
+    this.XB = blackPoint[0];
+    this.YB = blackPoint[1];
+    this.ZB = blackPoint[2];
+
+    // Validate vars as per spec
+    if (this.XW < 0 || this.ZW < 0 || this.YW !== 1)
+      error('Invalid WhitePoint components, no fallback available');
+
+    if (this.XB < 0 || this.YB < 0 || this.ZB < 0) {
+      warn('Invalid BlackPoint, falling back to default');
+      this.XB = this.YB = this.ZB = 0;
+    }
+
+    if (this.amin > this.amax || this.bmin > this.bmax) {
+      warn('Invalid Range, falling back to defaults');
+      this.amin = -100;
+      this.amax = 100;
+      this.bmin = -100;
+      this.bmax = 100;
+    }
+  };
+
+  // Function g(x) from spec
+  function g(x) {
+    if (x >= 6 / 29)
+      return x * x * x;
+    else
+      return (108 / 841) * (x - 4 / 29);
+  }
+
+  LabCS.prototype = {
+    getRgb: function LabCS_getRgb(color) {
+      // Ls,as,bs <---> L*,a*,b* in the spec
+      var Ls = color[0], as = color[1], bs = color[2];
+
+      // Adjust limits of 'as' and 'bs'
+      as = as > this.amax ? this.amax : as;
+      as = as < this.amin ? this.amin : as;
+      bs = bs > this.bmax ? this.bmax : bs;
+      bs = bs < this.bmin ? this.bmin : bs;
+
+      // Computes intermediate variables X,Y,Z as per spec
+      var M = (Ls + 16) / 116;
+      var L = M + (as / 500);
+      var N = M - (bs / 200);
+      var X = this.XW * g(L);
+      var Y = this.YW * g(M);
+      var Z = this.ZW * g(N);
+
+      // XYZ to RGB 3x3 matrix, from:
+      // http://www.poynton.com/notes/colour_and_gamma/ColorFAQ.html#RTFToC18
+      var XYZtoRGB = [3.240479, -1.537150, -0.498535,
+                      -0.969256, 1.875992, 0.041556,
+                      0.055648, -0.204043, 1.057311];
+
+      return Util.apply3dTransform(XYZtoRGB, [X, Y, Z]);
+    },
+    getRgbBuffer: function LabCS_getRgbBuffer(input, bits) {
+      if (bits == 8)
+        return input;
+      var scale = 255 / ((1 << bits) - 1);
+      var i, length = input.length / 3;
+      var rgbBuf = new Uint8Array(length);
+
+      var j = 0;
+      for (i = 0; i < length; ++i) {
+        // Convert L*, a*, s* into RGB
+        var rgb = this.getRgb([input[i], input[i + 1], input[i + 2]]);
+        rgbBuf[j++] = rgb[0];
+        rgbBuf[j++] = rgb[1];
+        rgbBuf[j++] = rgb[2];
+      }
+
+      return rgbBuf;
+    },
+    isDefaultDecode: function LabCS_isDefaultDecode(decodeMap) {
+      // From Table 90 in Adobe's:
+      // "Document management - Portable document format", 1st ed, 2008
+      if (decodeMap[0] === 0 && decodeMap[1] === 100 &&
+          decodeMap[2] === this.amin && decodeMap[3] === this.amax &&
+          decodeMap[4] === this.bmin && decodeMap[5] === this.bmax)
+        return true;
+      else
+        return false;
+    }
+  };
+  return LabCS;
+})();
diff --git a/apps/files_pdfviewer/js/pdfjs/src/core.js b/apps/files_pdfviewer/js/pdfjs/src/core.js
old mode 100755
new mode 100644
index 3549eb906b6795d70d99572494a2351c66373bbf..15cd147e2c2938175278a48412c04ea224dab8c4
--- a/apps/files_pdfviewer/js/pdfjs/src/core.js
+++ b/apps/files_pdfviewer/js/pdfjs/src/core.js
@@ -5,6 +5,8 @@
 
 var globalScope = (typeof window === 'undefined') ? this : window;
 
+var isWorker = (typeof window == 'undefined');
+
 var ERRORS = 0, WARNINGS = 1, TODOS = 5;
 var verbosity = WARNINGS;
 
@@ -31,7 +33,9 @@ function getPdf(arg, callback) {
   var xhr = new XMLHttpRequest();
   xhr.open('GET', params.url);
   xhr.mozResponseType = xhr.responseType = 'arraybuffer';
-  xhr.expected = (document.URL.indexOf('file:') === 0) ? 0 : 200;
+  var protocol = params.url.indexOf(':') < 0 ? window.location.protocol :
+    params.url.substring(0, params.url.indexOf(':') + 1);
+  xhr.expected = (protocol === 'http:' || protocol === 'https:') ? 200 : 0;
 
   if ('progress' in params)
     xhr.onprogress = params.progress || undefined;
@@ -39,41 +43,43 @@ function getPdf(arg, callback) {
   if ('error' in params)
     xhr.onerror = params.error || undefined;
 
-  xhr.onreadystatechange = function getPdfOnreadystatechange() {
-    if (xhr.readyState === 4 && xhr.status === xhr.expected) {
-      var data = (xhr.mozResponseArrayBuffer || xhr.mozResponse ||
-                  xhr.responseArrayBuffer || xhr.response);
-      callback(data);
+  xhr.onreadystatechange = function getPdfOnreadystatechange(e) {
+    if (xhr.readyState === 4) {
+      if (xhr.status === xhr.expected) {
+        var data = (xhr.mozResponseArrayBuffer || xhr.mozResponse ||
+                    xhr.responseArrayBuffer || xhr.response);
+        callback(data);
+      } else if (params.error) {
+        params.error(e);
+      }
     }
   };
   xhr.send(null);
 }
 globalScope.PDFJS.getPdf = getPdf;
+globalScope.PDFJS.pdfBug = false;
 
-var Page = (function pagePage() {
-  function constructor(xref, pageNumber, pageDict, ref) {
+var Page = (function PageClosure() {
+  function Page(xref, pageNumber, pageDict, ref) {
     this.pageNumber = pageNumber;
     this.pageDict = pageDict;
-    this.stats = {
-      create: Date.now(),
-      compile: 0.0,
-      fonts: 0.0,
-      images: 0.0,
-      render: 0.0
-    };
+    this.stats = new StatTimer();
+    this.stats.enabled = !!globalScope.PDFJS.enableStats;
     this.xref = xref;
     this.ref = ref;
+
+    this.displayReadyPromise = null;
   }
 
-  constructor.prototype = {
-    getPageProp: function pageGetPageProp(key) {
-      return this.xref.fetchIfRef(this.pageDict.get(key));
+  Page.prototype = {
+    getPageProp: function Page_getPageProp(key) {
+      return this.pageDict.get(key);
     },
-    inheritPageProp: function pageInheritPageProp(key) {
+    inheritPageProp: function Page_inheritPageProp(key) {
       var dict = this.pageDict;
       var obj = dict.get(key);
       while (obj === undefined) {
-        dict = this.xref.fetchIfRef(dict.get('Parent'));
+        dict = dict.get('Parent');
         if (!dict)
           break;
         obj = dict.get(key);
@@ -94,23 +100,35 @@ var Page = (function pagePage() {
       return shadow(this, 'mediaBox', obj);
     },
     get view() {
-      var obj = this.inheritPageProp('CropBox');
+      var cropBox = this.inheritPageProp('CropBox');
       var view = {
         x: 0,
         y: 0,
         width: this.width,
         height: this.height
       };
-      if (isArray(obj) && obj.length == 4) {
-        var tl = this.rotatePoint(obj[0], obj[1]);
-        var br = this.rotatePoint(obj[2], obj[3]);
-        view.x = Math.min(tl.x, br.x);
-        view.y = Math.min(tl.y, br.y);
-        view.width = Math.abs(tl.x - br.x);
-        view.height = Math.abs(tl.y - br.y);
-      }
+      if (!isArray(cropBox) || cropBox.length !== 4)
+        return shadow(this, 'view', view);
 
-      return shadow(this, 'cropBox', view);
+      var mediaBox = this.mediaBox;
+      var offsetX = mediaBox[0], offsetY = mediaBox[1];
+
+      // From the spec, 6th ed., p.963:
+      // "The crop, bleed, trim, and art boxes should not ordinarily
+      // extend beyond the boundaries of the media box. If they do, they are
+      // effectively reduced to their intersection with the media box."
+      cropBox = Util.intersect(cropBox, mediaBox);
+      if (!cropBox)
+        return shadow(this, 'view', view);
+
+      var tl = this.rotatePoint(cropBox[0] - offsetX, cropBox[1] - offsetY);
+      var br = this.rotatePoint(cropBox[2] - offsetX, cropBox[3] - offsetY);
+      view.x = Math.min(tl.x, br.x);
+      view.y = Math.min(tl.y, br.y);
+      view.width = Math.abs(tl.x - br.x);
+      view.height = Math.abs(tl.y - br.y);
+
+      return shadow(this, 'view', view);
     },
     get annotations() {
       return shadow(this, 'annotations', this.inheritPageProp('Annots'));
@@ -152,77 +170,80 @@ var Page = (function pagePage() {
       return shadow(this, 'rotate', rotate);
     },
 
-    startRenderingFromIRQueue: function pageStartRenderingFromIRQueue(
-                                                IRQueue, fonts) {
+    startRenderingFromOperatorList:
+      function Page_startRenderingFromOperatorList(operatorList, fonts) {
       var self = this;
-      this.IRQueue = IRQueue;
-      var gfx = new CanvasGraphics(this.ctx, this.objs);
+      this.operatorList = operatorList;
 
       var displayContinuation = function pageDisplayContinuation() {
         // Always defer call to display() to work around bug in
         // Firefox error reporting from XHR callbacks.
         setTimeout(function pageSetTimeout() {
-          try {
-            self.display(gfx, self.callback);
-          } catch (e) {
-            if (self.callback) self.callback(e.toString());
-            throw e;
-          }
+          self.displayReadyPromise.resolve();
         });
       };
 
       this.ensureFonts(fonts,
-                       function pageStartRenderingFromIRQueueEnsureFonts() {
-        displayContinuation();
-      });
+        function pageStartRenderingFromOperatorListEnsureFonts() {
+          displayContinuation();
+        }
+      );
     },
 
-    getIRQueue: function pageGetIRQueue(handler, dependency) {
-      if (this.IRQueue) {
+    getOperatorList: function Page_getOperatorList(handler, dependency) {
+      if (this.operatorList) {
         // content was compiled
-        return this.IRQueue;
+        return this.operatorList;
       }
 
+      this.stats.time('Build IR Queue');
+
       var xref = this.xref;
-      var content = xref.fetchIfRef(this.content);
-      var resources = xref.fetchIfRef(this.resources);
+      var content = this.content;
+      var resources = this.resources;
       if (isArray(content)) {
         // fetching items
         var i, n = content.length;
         for (i = 0; i < n; ++i)
           content[i] = xref.fetchIfRef(content[i]);
         content = new StreamsSequenceStream(content);
+      } else if (!content) {
+        // replacing non-existent page content with empty one
+        content = new Stream(new Uint8Array(0));
       }
 
       var pe = this.pe = new PartialEvaluator(
                                 xref, handler, 'p' + this.pageNumber + '_');
-      var IRQueue = {};
-      return (this.IRQueue = pe.getIRQueue(content, resources, IRQueue,
-                                           dependency));
+
+      this.operatorList = pe.getOperatorList(content, resources, dependency);
+      this.stats.timeEnd('Build IR Queue');
+      return this.operatorList;
     },
 
-    ensureFonts: function pageEnsureFonts(fonts, callback) {
+    ensureFonts: function Page_ensureFonts(fonts, callback) {
+      this.stats.time('Font Loading');
       // Convert the font names to the corresponding font obj.
       for (var i = 0, ii = fonts.length; i < ii; i++) {
         fonts[i] = this.objs.objs[fonts[i]].data;
       }
 
       // Load all the fonts
-      var fontObjs = FontLoader.bind(
+      FontLoader.bind(
         fonts,
         function pageEnsureFontsFontObjs(fontObjs) {
-          this.stats.fonts = Date.now();
+          this.stats.timeEnd('Font Loading');
 
           callback.call(this);
-        }.bind(this),
-        this.objs
+        }.bind(this)
       );
     },
 
-    display: function pageDisplay(gfx, callback) {
+    display: function Page_display(gfx, callback) {
+      var stats = this.stats;
+      stats.time('Rendering');
       var xref = this.xref;
-      var resources = xref.fetchIfRef(this.resources);
-      var mediaBox = xref.fetchIfRef(this.mediaBox);
+      var resources = this.resources;
+      var mediaBox = this.mediaBox;
       assertWellFormed(isDict(resources), 'invalid page resources');
 
       gfx.xref = xref;
@@ -233,20 +254,29 @@ var Page = (function pagePage() {
             rotate: this.rotate });
 
       var startIdx = 0;
-      var length = this.IRQueue.fnArray.length;
-      var IRQueue = this.IRQueue;
+      var length = this.operatorList.fnArray.length;
+      var operatorList = this.operatorList;
+      var stepper = null;
+      if (PDFJS.pdfBug && StepperManager.enabled) {
+        stepper = StepperManager.create(this.pageNumber);
+        stepper.init(operatorList);
+        stepper.nextBreakPoint = stepper.getNextBreakPoint();
+      }
 
       var self = this;
       function next() {
-        startIdx = gfx.executeIRQueue(IRQueue, startIdx, next);
+        startIdx =
+          gfx.executeOperatorList(operatorList, startIdx, next, stepper);
         if (startIdx == length) {
-          self.stats.render = Date.now();
+          gfx.endDrawing();
+          stats.timeEnd('Rendering');
+          stats.timeEnd('Overall');
           if (callback) callback();
         }
       }
       next();
     },
-    rotatePoint: function pageRotatePoint(x, y, reverse) {
+    rotatePoint: function Page_rotatePoint(x, y, reverse) {
       var rotate = reverse ? (360 - this.rotate) : this.rotate;
       switch (rotate) {
         case 180:
@@ -261,58 +291,183 @@ var Page = (function pagePage() {
           return {x: x, y: this.height - y};
       }
     },
-    getLinks: function pageGetLinks() {
+    getLinks: function Page_getLinks() {
+      var links = [];
+      var annotations = pageGetAnnotations();
+      var i, n = annotations.length;
+      for (i = 0; i < n; ++i) {
+        if (annotations[i].type != 'Link')
+          continue;
+        links.push(annotations[i]);
+      }
+      return links;
+    },
+    getAnnotations: function Page_getAnnotations() {
       var xref = this.xref;
-      var annotations = xref.fetchIfRef(this.annotations) || [];
+      function getInheritableProperty(annotation, name) {
+        var item = annotation;
+        while (item && !item.has(name)) {
+          item = item.get('Parent');
+        }
+        if (!item)
+          return null;
+        return item.get(name);
+      }
+      function isValidUrl(url) {
+        if (!url)
+          return false;
+        var colon = url.indexOf(':');
+        if (colon < 0)
+          return false;
+        var protocol = url.substr(0, colon);
+        switch (protocol) {
+          case 'http':
+          case 'https':
+          case 'ftp':
+            return true;
+          default:
+            return false;
+        }
+      }
+
+      var annotations = this.annotations || [];
       var i, n = annotations.length;
-      var links = [];
+      var items = [];
       for (i = 0; i < n; ++i) {
-        var annotation = xref.fetch(annotations[i]);
+        var annotationRef = annotations[i];
+        var annotation = xref.fetch(annotationRef);
         if (!isDict(annotation))
           continue;
         var subtype = annotation.get('Subtype');
-        if (!isName(subtype) || subtype.name != 'Link')
+        if (!isName(subtype))
           continue;
         var rect = annotation.get('Rect');
         var topLeftCorner = this.rotatePoint(rect[0], rect[1]);
         var bottomRightCorner = this.rotatePoint(rect[2], rect[3]);
 
-        var link = {};
-        link.x = Math.min(topLeftCorner.x, bottomRightCorner.x);
-        link.y = Math.min(topLeftCorner.y, bottomRightCorner.y);
-        link.width = Math.abs(topLeftCorner.x - bottomRightCorner.x);
-        link.height = Math.abs(topLeftCorner.y - bottomRightCorner.y);
-        var a = this.xref.fetchIfRef(annotation.get('A'));
-        if (a) {
-          switch (a.get('S').name) {
-            case 'URI':
-              link.url = a.get('URI');
-              break;
-            case 'GoTo':
-              link.dest = a.get('D');
+        var item = {};
+        item.type = subtype.name;
+        item.x = Math.min(topLeftCorner.x, bottomRightCorner.x);
+        item.y = Math.min(topLeftCorner.y, bottomRightCorner.y);
+        item.width = Math.abs(topLeftCorner.x - bottomRightCorner.x);
+        item.height = Math.abs(topLeftCorner.y - bottomRightCorner.y);
+        switch (subtype.name) {
+          case 'Link':
+            var a = annotation.get('A');
+            if (a) {
+              switch (a.get('S').name) {
+                case 'URI':
+                  var url = a.get('URI');
+                  // TODO: pdf spec mentions urls can be relative to a Base
+                  // entry in the dictionary.
+                  if (!isValidUrl(url))
+                    url = '';
+                  item.url = url;
+                  break;
+                case 'GoTo':
+                  item.dest = a.get('D');
+                  break;
+                default:
+                  TODO('other link types');
+              }
+            } else if (annotation.has('Dest')) {
+              // simple destination link
+              var dest = annotation.get('Dest');
+              item.dest = isName(dest) ? dest.name : dest;
+            }
+            break;
+          case 'Widget':
+            var fieldType = getInheritableProperty(annotation, 'FT');
+            if (!isName(fieldType))
               break;
-            default:
-              TODO('other link types');
-          }
-        } else if (annotation.has('Dest')) {
-          // simple destination link
-          var dest = annotation.get('Dest');
-          link.dest = isName(dest) ? dest.name : dest;
+            item.fieldType = fieldType.name;
+            // Building the full field name by collecting the field and
+            // its ancestors 'T' properties and joining them using '.'.
+            var fieldName = [];
+            var namedItem = annotation, ref = annotationRef;
+            while (namedItem) {
+              var parent = namedItem.get('Parent');
+              var parentRef = namedItem.getRaw('Parent');
+              var name = namedItem.get('T');
+              if (name) {
+                fieldName.unshift(stringToPDFString(name));
+              } else {
+                // The field name is absent, that means more than one field
+                // with the same name may exist. Replacing the empty name
+                // with the '`' plus index in the parent's 'Kids' array.
+                // This is not in the PDF spec but necessary to id the
+                // the input controls.
+                var kids = parent.get('Kids');
+                var j, jj;
+                for (j = 0, jj = kids.length; j < jj; j++) {
+                  var kidRef = kids[j];
+                  if (kidRef.num == ref.num && kidRef.gen == ref.gen)
+                    break;
+                }
+                fieldName.unshift('`' + j);
+              }
+              namedItem = parent;
+              ref = parentRef;
+            }
+            item.fullName = fieldName.join('.');
+            var alternativeText = stringToPDFString(annotation.get('TU') || '');
+            item.alternativeText = alternativeText;
+            var da = getInheritableProperty(annotation, 'DA') || '';
+            var m = /([\d\.]+)\sTf/.exec(da);
+            if (m)
+              item.fontSize = parseFloat(m[1]);
+            item.textAlignment = getInheritableProperty(annotation, 'Q');
+            item.flags = getInheritableProperty(annotation, 'Ff') || 0;
+            break;
+          case 'Text':
+            var content = annotation.get('Contents');
+            var title = annotation.get('T');
+            item.content = stringToPDFString(content || '');
+            item.title = stringToPDFString(title || '');
+            item.name = annotation.get('Name').name;
+            break;
+          default:
+            TODO('unimplemented annotation type: ' + subtype.name);
+            break;
         }
-        links.push(link);
+        items.push(item);
       }
-      return links;
+      return items;
     },
-    startRendering: function pageStartRendering(ctx, callback)  {
-      this.ctx = ctx;
-      this.callback = callback;
+    startRendering: function Page_startRendering(ctx, callback, textLayer)  {
+      var stats = this.stats;
+      stats.time('Overall');
+      // If there is no displayReadyPromise yet, then the operatorList was never
+      // requested before. Make the request and create the promise.
+      if (!this.displayReadyPromise) {
+        this.pdf.startRendering(this);
+        this.displayReadyPromise = new Promise();
+      }
 
-      this.startRenderingTime = Date.now();
-      this.pdf.startRendering(this);
+      // Once the operatorList and fonts are loaded, do the actual rendering.
+      this.displayReadyPromise.then(
+        function pageDisplayReadyPromise() {
+          var gfx = new CanvasGraphics(ctx, this.objs, textLayer);
+          try {
+            this.display(gfx, callback);
+          } catch (e) {
+            if (callback)
+              callback(e);
+            else
+              error(e);
+          }
+        }.bind(this),
+        function pageDisplayReadPromiseError(reason) {
+          if (callback)
+            callback(reason);
+          else
+            error(reason);
+        }
+      );
     }
   };
 
-  return constructor;
+  return Page;
 })();
 
 /**
@@ -321,12 +476,9 @@ var Page = (function pagePage() {
  * Right now there exists one PDFDocModel on the main thread + one object
  * for each worker. If there is no worker support enabled, there are two
  * `PDFDocModel` objects on the main thread created.
- * TODO: Refactor the internal object structure, such that there is no
- * need for the `PDFDocModel` anymore and there is only one object on the
- * main thread and not one entire copy on each worker instance.
  */
-var PDFDocModel = (function pdfDoc() {
-  function constructor(arg, callback) {
+var PDFDocModel = (function PDFDocModelClosure() {
+  function PDFDocModel(arg, callback) {
     if (isStream(arg))
       init.call(this, arg);
     else if (isArrayBuffer(arg))
@@ -339,6 +491,7 @@ var PDFDocModel = (function pdfDoc() {
     assertWellFormed(stream.length > 0, 'stream must have data');
     this.stream = stream;
     this.setup();
+    this.acroForm = this.catalog.catDict.get('AcroForm');
   }
 
   function find(stream, needle, limit, backwards) {
@@ -357,7 +510,7 @@ var PDFDocModel = (function pdfDoc() {
     return true; /* found */
   }
 
-  constructor.prototype = {
+  PDFDocModel.prototype = {
     get linearization() {
       var length = this.stream.length;
       var linearization = false;
@@ -379,12 +532,17 @@ var PDFDocModel = (function pdfDoc() {
         if (find(stream, 'endobj', 1024))
           startXRef = stream.pos + 6;
       } else {
-        // Find startxref at the end of the file.
-        var start = stream.end - 1024;
-        if (start < 0)
-          start = 0;
-        stream.pos = start;
-        if (find(stream, 'startxref', 1024, true)) {
+        // Find startxref by jumping backward from the end of the file.
+        var step = 1024;
+        var found = false, pos = stream.end;
+        while (!found && pos > 0) {
+          pos -= step - 'startxref'.length;
+          if (pos < 0)
+            pos = 0;
+          stream.pos = pos;
+          found = find(stream, 'startxref', step, true);
+        }
+        if (found) {
           stream.skip(9);
           var ch;
           do {
@@ -413,7 +571,7 @@ var PDFDocModel = (function pdfDoc() {
     },
     // Find the header, remove leading garbage and setup the stream
     // starting from the header.
-    checkHeader: function pdfDocCheckHeader() {
+    checkHeader: function PDFDocModel_checkHeader() {
       var stream = this.stream;
       stream.reset();
       if (find(stream, '%PDF-', 1024)) {
@@ -423,12 +581,13 @@ var PDFDocModel = (function pdfDoc() {
       }
       // May not be a PDF file, continue anyway.
     },
-    setup: function pdfDocSetup(ownerPassword, userPassword) {
+    setup: function PDFDocModel_setup(ownerPassword, userPassword) {
       this.checkHeader();
-      this.xref = new XRef(this.stream,
-                           this.startXRef,
-                           this.mainXRefEntriesOffset);
-      this.catalog = new Catalog(this.xref);
+      var xref = new XRef(this.stream,
+                          this.startXRef,
+                          this.mainXRefEntriesOffset);
+      this.xref = xref;
+      this.catalog = new Catalog(xref);
     },
     get numPages() {
       var linearization = this.linearization;
@@ -436,16 +595,51 @@ var PDFDocModel = (function pdfDoc() {
       // shadow the prototype getter
       return shadow(this, 'numPages', num);
     },
-    getPage: function pdfDocGetPage(n) {
+    getDocumentInfo: function PDFDocModel_getDocumentInfo() {
+      var info;
+      if (this.xref.trailer.has('Info')) {
+        var infoDict = this.xref.trailer.get('Info');
+
+        info = {};
+        infoDict.forEach(function(key, value) {
+          info[key] = typeof value !== 'string' ? value :
+            stringToPDFString(value);
+        });
+      }
+
+      return shadow(this, 'getDocumentInfo', info);
+    },
+    getFingerprint: function PDFDocModel_getFingerprint() {
+      var xref = this.xref, fileID;
+      if (xref.trailer.has('ID')) {
+        fileID = '';
+        var id = xref.trailer.get('ID')[0];
+        id.split('').forEach(function(el) {
+          fileID += Number(el.charCodeAt(0)).toString(16);
+        });
+      } else {
+        // If we got no fileID, then we generate one,
+        // from the first 100 bytes of PDF
+        var data = this.stream.bytes.subarray(0, 100);
+        var hash = calculateMD5(data, 0, data.length);
+        fileID = '';
+        for (var i = 0, length = hash.length; i < length; i++) {
+          fileID += Number(hash[i]).toString(16);
+        }
+      }
+
+      return shadow(this, 'getFingerprint', fileID);
+    },
+    getPage: function PDFDocModel_getPage(n) {
       return this.catalog.getPage(n);
     }
   };
 
-  return constructor;
+  return PDFDocModel;
 })();
 
-var PDFDoc = (function pdfDoc() {
-  function constructor(arg, callback) {
+var PDFDoc = (function PDFDocClosure() {
+  function PDFDoc(arg, callback) {
     var stream = null;
     var data = null;
 
@@ -461,9 +655,10 @@ var PDFDoc = (function pdfDoc() {
 
     this.data = data;
     this.stream = stream;
-    this.pdf = new PDFDocModel(stream);
-
-    this.catalog = this.pdf.catalog;
+    this.pdfModel = new PDFDocModel(stream);
+    this.fingerprint = this.pdfModel.getFingerprint();
+    this.info = this.pdfModel.getDocumentInfo();
+    this.catalog = this.pdfModel.catalog;
     this.objs = new PDFObjects();
 
     this.pageCache = [];
@@ -478,49 +673,59 @@ var PDFDoc = (function pdfDoc() {
     if (!globalScope.PDFJS.disableWorker && typeof Worker !== 'undefined') {
       var workerSrc = PDFJS.workerSrc;
       if (typeof workerSrc === 'undefined') {
-        throw 'No PDFJS.workerSrc specified';
+        error('No PDFJS.workerSrc specified');
       }
 
-      var worker;
       try {
-        worker = new Worker(workerSrc);
-      } catch (e) {
-        // Some versions of FF can't create a worker on localhost, see:
-        // https://bugzilla.mozilla.org/show_bug.cgi?id=683280
-        globalScope.PDFJS.disableWorker = true;
-        this.setupFakeWorker();
-        return;
-      }
-
-      var messageHandler = new MessageHandler('main', worker);
-
-      // Tell the worker the file it was created from.
-      messageHandler.send('workerSrc', workerSrc);
-
-      messageHandler.on('test', function pdfDocTest(supportTypedArray) {
-        if (supportTypedArray) {
-          this.worker = worker;
-          this.setupMessageHandler(messageHandler);
+        var worker;
+        if (PDFJS.isFirefoxExtension) {
+          // The firefox extension can't load the worker from the resource://
+          // url so we have to inline the script and then use the blob loader.
+          var bb = new MozBlobBuilder();
+          bb.append(document.querySelector('#PDFJS_SCRIPT_TAG').textContent);
+          var blobUrl = window.URL.createObjectURL(bb.getBlob());
+          worker = new Worker(blobUrl);
         } else {
-          this.setupFakeWorker();
+          // Some versions of FF can't create a worker on localhost, see:
+          // https://bugzilla.mozilla.org/show_bug.cgi?id=683280
+          worker = new Worker(workerSrc);
         }
-      }.bind(this));
 
-      var testObj = new Uint8Array(1);
-      messageHandler.send('test', testObj);
-    } else {
-      this.setupFakeWorker();
+        var messageHandler = new MessageHandler('main', worker);
+
+        messageHandler.on('test', function pdfDocTest(supportTypedArray) {
+          if (supportTypedArray) {
+            this.worker = worker;
+            this.setupMessageHandler(messageHandler);
+          } else {
+            globalScope.PDFJS.disableWorker = true;
+            this.setupFakeWorker();
+          }
+        }.bind(this));
+
+        var testObj = new Uint8Array(1);
+        // Some versions of Opera throw a DATA_CLONE_ERR on
+        // serializing the typed array.
+        messageHandler.send('test', testObj);
+        return;
+      } catch (e) {
+        warn('The worker has been disabled.');
+      }
     }
+    // Either workers are disabled, not supported or have thrown an exception.
+    // Thus, we fallback to a faked worker.
+    globalScope.PDFJS.disableWorker = true;
+    this.setupFakeWorker();
   }
 
-  constructor.prototype = {
-    setupFakeWorker: function() {
+  PDFDoc.prototype = {
+    setupFakeWorker: function PDFDoc_setupFakeWorker() {
       // If we don't use a worker, just post/sendMessage to the main thread.
       var fakeWorker = {
-        postMessage: function pdfDocPostMessage(obj) {
+        postMessage: function PDFDoc_postMessage(obj) {
           fakeWorker.onmessage({data: obj});
         },
-        terminate: function pdfDocTerminate() {}
+        terminate: function PDFDoc_terminate() {}
       };
 
       var messageHandler = new MessageHandler('main', fakeWorker);
@@ -532,7 +737,7 @@ var PDFDoc = (function pdfDoc() {
     },
 
 
-    setupMessageHandler: function(messageHandler) {
+    setupMessageHandler: function PDFDoc_setupMessageHandler(messageHandler) {
       this.messageHandler = messageHandler;
 
       messageHandler.on('page', function pdfDocPage(data) {
@@ -540,7 +745,8 @@ var PDFDoc = (function pdfDoc() {
         var page = this.pageCache[pageNum];
         var depFonts = data.depFonts;
 
-        page.startRenderingFromIRQueue(data.IRQueue, depFonts);
+        page.stats.timeEnd('Page Request');
+        page.startRenderingFromOperatorList(data.operatorList, depFonts);
       }, this);
 
       messageHandler.on('obj', function pdfDocObj(data) {
@@ -549,8 +755,12 @@ var PDFDoc = (function pdfDoc() {
 
         switch (type) {
           case 'JpegStream':
-            var IR = data[2];
-            new JpegImageLoader(id, IR, this.objs);
+            var imageData = data[2];
+            loadJpegStream(id, imageData, this.objs);
+            break;
+          case 'Image':
+            var imageData = data[2];
+            this.objs.resolve(id, imageData);
             break;
           case 'Font':
             var name = data[2];
@@ -558,46 +768,63 @@ var PDFDoc = (function pdfDoc() {
             var properties = data[4];
 
             if (file) {
+              // Rewrap the ArrayBuffer in a stream.
               var fontFileDict = new Dict();
-              fontFileDict.map = file.dict.map;
-
-              var fontFile = new Stream(file.bytes, file.start,
-                                        file.end - file.start, fontFileDict);
-
-              // Check if this is a FlateStream. Otherwise just use the created
-              // Stream one. This makes complex_ttf_font.pdf work.
-              var cmf = file.bytes[0];
-              if ((cmf & 0x0f) == 0x08) {
-                file = new FlateStream(fontFile);
-              } else {
-                file = fontFile;
-              }
+              file = new Stream(file, 0, file.length, fontFileDict);
             }
 
-            // For now, resolve the font object here direclty. The real font
-            // object is then created in FontLoader.bind().
-            this.objs.resolve(id, {
-              name: name,
-              file: file,
-              properties: properties
-            });
+            // At this point, only the font object is created but the font is
+            // not yet attached to the DOM. This is done in `FontLoader.bind`.
+            var font = new Font(name, file, properties);
+            this.objs.resolve(id, font);
             break;
           default:
-            throw 'Got unkown object type ' + type;
+            error('Got unkown object type ' + type);
         }
       }, this);
 
-      messageHandler.on('font_ready', function pdfDocFontReady(data) {
-        var id = data[0];
-        var font = new FontShape(data[1]);
+      messageHandler.on('page_error', function pdfDocError(data) {
+        var page = this.pageCache[data.pageNum];
+        if (page.displayReadyPromise)
+          page.displayReadyPromise.reject(data.error);
+        else
+          error(data.error);
+      }, this);
 
-        // If there is no string, then there is nothing to attach to the DOM.
-        if (!font.str) {
-          this.objs.resolve(id, font);
-        } else {
-          this.objs.setData(id, font);
-        }
-      }.bind(this));
+      messageHandler.on('jpeg_decode', function(data, promise) {
+        var imageData = data[0];
+        var components = data[1];
+        if (components != 3 && components != 1)
+          error('Only 3 component or 1 component can be returned');
+
+        var img = new Image();
+        img.onload = (function messageHandler_onloadClosure() {
+          var width = img.width;
+          var height = img.height;
+          var size = width * height;
+          var rgbaLength = size * 4;
+          var buf = new Uint8Array(size * components);
+          var tmpCanvas = createScratchCanvas(width, height);
+          var tmpCtx = tmpCanvas.getContext('2d');
+          tmpCtx.drawImage(img, 0, 0);
+          var data = tmpCtx.getImageData(0, 0, width, height).data;
+
+          if (components == 3) {
+            for (var i = 0, j = 0; i < rgbaLength; i += 4, j += 3) {
+              buf[j] = data[i];
+              buf[j + 1] = data[i + 1];
+              buf[j + 2] = data[i + 2];
+            }
+          } else if (components == 1) {
+            for (var i = 0, j = 0; i < rgbaLength; i += 4, j++) {
+              buf[j] = data[i];
+            }
+          }
+          promise.resolve({ data: buf, width: width, height: height});
+        }).bind(this);
+        var src = 'data:image/jpeg;base64,' + window.btoa(imageData);
+        img.src = src;
+      });
 
       setTimeout(function pdfDocFontReadySetTimeout() {
         messageHandler.send('doc', this.data);
@@ -606,21 +833,22 @@ var PDFDoc = (function pdfDoc() {
     },
 
     get numPages() {
-      return this.pdf.numPages;
+      return this.pdfModel.numPages;
     },
 
-    startRendering: function pdfDocStartRendering(page) {
+    startRendering: function PDFDoc_startRendering(page) {
       // The worker might not be ready to receive the page request yet.
       this.workerReadyPromise.then(function pdfDocStartRenderingThen() {
+        page.stats.time('Page Request');
         this.messageHandler.send('page_request', page.pageNumber + 1);
       }.bind(this));
     },
 
-    getPage: function pdfDocGetPage(n) {
+    getPage: function PDFDoc_getPage(n) {
       if (this.pageCache[n])
         return this.pageCache[n];
 
-      var page = this.pdf.getPage(n);
+      var page = this.pdfModel.getPage(n);
       // Add a reference to the objects such that Page can forward the reference
       // to the CanvasGraphics and so on.
       page.objs = this.objs;
@@ -628,7 +856,7 @@ var PDFDoc = (function pdfDoc() {
       return (this.pageCache[n] = page);
     },
 
-    destroy: function pdfDocDestroy() {
+    destroy: function PDFDoc_destroy() {
       if (this.worker)
         this.worker.terminate();
 
@@ -645,7 +873,7 @@ var PDFDoc = (function pdfDoc() {
     }
   };
 
-  return constructor;
+  return PDFDoc;
 })();
 
 globalScope.PDFJS.PDFDoc = PDFDoc;
diff --git a/apps/files_pdfviewer/js/pdfjs/src/crypto.js b/apps/files_pdfviewer/js/pdfjs/src/crypto.js
old mode 100755
new mode 100644
index 95559864483c2f7d7278b839d674c53c306f64ca..038c0e3327fb77f66228eec9b19b8c9fb40cb5bd
--- a/apps/files_pdfviewer/js/pdfjs/src/crypto.js
+++ b/apps/files_pdfviewer/js/pdfjs/src/crypto.js
@@ -3,8 +3,8 @@
 
 'use strict';
 
-var ARCFourCipher = (function arcFourCipher() {
-  function constructor(key) {
+var ARCFourCipher = (function ARCFourCipherClosure() {
+  function ARCFourCipher(key) {
     this.a = 0;
     this.b = 0;
     var s = new Uint8Array(256);
@@ -20,8 +20,8 @@ var ARCFourCipher = (function arcFourCipher() {
     this.s = s;
   }
 
-  constructor.prototype = {
-    encryptBlock: function arcFourCipherEncryptBlock(data) {
+  ARCFourCipher.prototype = {
+    encryptBlock: function ARCFourCipher_encryptBlock(data) {
       var i, n = data.length, tmp, tmp2;
       var a = this.a, b = this.b, s = this.s;
       var output = new Uint8Array(n);
@@ -39,12 +39,12 @@ var ARCFourCipher = (function arcFourCipher() {
       return output;
     }
   };
-  constructor.prototype.decryptBlock = constructor.prototype.encryptBlock;
+  ARCFourCipher.prototype.decryptBlock = ARCFourCipher.prototype.encryptBlock;
 
-  return constructor;
+  return ARCFourCipher;
 })();
 
-var calculateMD5 = (function calculateMD5() {
+var calculateMD5 = (function calculateMD5Closure() {
   var r = new Uint8Array([
     7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22,
     5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20,
@@ -128,20 +128,20 @@ var calculateMD5 = (function calculateMD5() {
   return hash;
 })();
 
-var NullCipher = (function nullCipher() {
-  function constructor() {
+var NullCipher = (function NullCipherClosure() {
+  function NullCipher() {
   }
 
-  constructor.prototype = {
-    decryptBlock: function nullCipherDecryptBlock(data) {
+  NullCipher.prototype = {
+    decryptBlock: function NullCipher_decryptBlock(data) {
       return data;
     }
   };
 
-  return constructor;
+  return NullCipher;
 })();
 
-var AES128Cipher = (function aes128Cipher() {
+var AES128Cipher = (function AES128CipherClosure() {
   var rcon = new Uint8Array([
     0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c,
     0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a,
@@ -330,7 +330,7 @@ var AES128Cipher = (function aes128Cipher() {
     return state;
   }
 
-  function constructor(key) {
+  function AES128Cipher(key) {
     this.key = expandKey128(key);
     this.buffer = new Uint8Array(16);
     this.bufferPosition = 0;
@@ -370,8 +370,8 @@ var AES128Cipher = (function aes128Cipher() {
     return output;
   }
 
-  constructor.prototype = {
-    decryptBlock: function aes128CipherDecryptBlock(data) {
+  AES128Cipher.prototype = {
+    decryptBlock: function AES128Cipher_decryptBlock(data) {
       var i, sourceLength = data.length;
       var buffer = this.buffer, bufferLength = this.bufferPosition;
       // waiting for IV values -- they are at the start of the stream
@@ -391,16 +391,16 @@ var AES128Cipher = (function aes128Cipher() {
     }
   };
 
-  return constructor;
+  return AES128Cipher;
 })();
 
-var CipherTransform = (function cipherTransform() {
-  function constructor(stringCipherConstructor, streamCipherConstructor) {
+var CipherTransform = (function CipherTransformClosure() {
+  function CipherTransform(stringCipherConstructor, streamCipherConstructor) {
     this.stringCipherConstructor = stringCipherConstructor;
     this.streamCipherConstructor = streamCipherConstructor;
   }
-  constructor.prototype = {
-    createStream: function cipherTransformCreateStream(stream) {
+  CipherTransform.prototype = {
+    createStream: function CipherTransform_createStream(stream) {
       var cipher = new this.streamCipherConstructor();
       return new DecryptStream(stream,
         function cipherTransformDecryptStream(data) {
@@ -408,17 +408,17 @@ var CipherTransform = (function cipherTransform() {
         }
       );
     },
-    decryptString: function cipherTransformDecryptString(s) {
+    decryptString: function CipherTransform_decryptString(s) {
       var cipher = new this.stringCipherConstructor();
       var data = stringToBytes(s);
       data = cipher.decryptBlock(data);
       return bytesToString(data);
     }
   };
-  return constructor;
+  return CipherTransform;
 })();
 
-var CipherTransformFactory = (function cipherTransformFactory() {
+var CipherTransformFactory = (function CipherTransformFactoryClosure() {
   function prepareKeyData(fileId, password, ownerPassword, userPassword,
                           flags, revision, keyLength, encryptMetadata) {
     var defaultPasswordBytes = new Uint8Array([
@@ -490,7 +490,7 @@ var CipherTransformFactory = (function cipherTransformFactory() {
 
   var identityName = new Name('Identity');
 
-  function constructor(dict, fileId, password) {
+  function CipherTransformFactory(dict, fileId, password) {
     var filter = dict.get('Filter');
     if (!isName(filter) || filter.name != 'Standard')
       error('unknown encryption method');
@@ -570,12 +570,11 @@ var CipherTransformFactory = (function cipherTransformFactory() {
       };
     }
     error('Unknown crypto method');
-    return null;
   }
 
-  constructor.prototype = {
-    createCipherTransform: function buildCipherCreateCipherTransform(num,
-                                                                     gen) {
+  CipherTransformFactory.prototype = {
+    createCipherTransform:
+      function CipherTransformFactory_createCipherTransform(num, gen) {
       if (this.algorithm == 4) {
         return new CipherTransform(
           buildCipherConstructor(this.cf, this.stmf,
@@ -592,6 +591,6 @@ var CipherTransformFactory = (function cipherTransformFactory() {
     }
   };
 
-  return constructor;
+  return CipherTransformFactory;
 })();
 
diff --git a/apps/files_pdfviewer/js/pdfjs/src/evaluator.js b/apps/files_pdfviewer/js/pdfjs/src/evaluator.js
old mode 100755
new mode 100644
index a863a531ec57b17a14a8d9153b32f17b9c5a915d..350ab20b2c55a5f293dccca5ecf945a203d02246
--- a/apps/files_pdfviewer/js/pdfjs/src/evaluator.js
+++ b/apps/files_pdfviewer/js/pdfjs/src/evaluator.js
@@ -3,8 +3,8 @@
 
 'use strict';
 
-var PartialEvaluator = (function partialEvaluator() {
-  function constructor(xref, handler, uniquePrefix) {
+var PartialEvaluator = (function PartialEvaluatorClosure() {
+  function PartialEvaluator(xref, handler, uniquePrefix) {
     this.state = new EvalState();
     this.stateStack = [];
 
@@ -111,14 +111,27 @@ var PartialEvaluator = (function partialEvaluator() {
     EX: 'endCompat'
   };
 
-  constructor.prototype = {
-    getIRQueue: function partialEvaluatorGetIRQueue(stream, resources,
-                                    queue, dependency) {
+  function splitCombinedOperations(operations) {
+    // Two operations can be combined together, trying to find which two
+    // operations were concatenated.
+    for (var i = operations.length - 1; i > 0; i--) {
+      var op1 = operations.substring(0, i), op2 = operations.substring(i);
+      if (op1 in OP_MAP && op2 in OP_MAP)
+        return [op1, op2]; // operations found
+    }
+    return null;
+  }
+
+  PartialEvaluator.prototype = {
+    getOperatorList: function PartialEvaluator_getOperatorList(stream,
+                                                               resources,
+                                                               dependency,
+                                                               queue) {
 
       var self = this;
       var xref = this.xref;
       var handler = this.handler;
-      var uniquePrefix = this.uniquePrefix;
+      var uniquePrefix = this.uniquePrefix || '';
 
       function insertDependency(depList) {
         fnArray.push('dependency');
@@ -131,18 +144,14 @@ var PartialEvaluator = (function partialEvaluator() {
         }
       }
 
-      function handleSetFont(fontName, fontRef) {
+      function handleSetFont(fontName, font) {
         var loadedName = null;
 
         var fontRes = resources.get('Font');
 
-        // TODO: TOASK: Is it possible to get here? If so, what does
-        // args[0].name should be like???
         assert(fontRes, 'fontRes not available');
 
-        fontRes = xref.fetchIfRef(fontRes);
-        fontRef = fontRef || fontRes.get(fontName);
-        var font = xref.fetchIfRef(fontRef);
+        font = xref.fetchIfRef(font) || fontRes.get(fontName);
         assertWellFormed(isDict(font));
         if (!font.translated) {
           font.translated = self.translateFont(font, xref, resources,
@@ -155,6 +164,15 @@ var PartialEvaluator = (function partialEvaluator() {
             font.loadedName = loadedName;
 
             var translated = font.translated;
+            // Convert the file to an ArrayBuffer which will be turned back into
+            // a Stream in the main thread.
+            if (translated.file)
+              translated.file = translated.file.getBytes();
+            if (translated.properties.file) {
+              translated.properties.file =
+                  translated.properties.file.getBytes();
+            }
+
             handler.send('obj', [
                 loadedName,
                 'Font',
@@ -168,7 +186,7 @@ var PartialEvaluator = (function partialEvaluator() {
 
         // Ensure the font is ready before the font is set
         // and later on used for drawing.
-        // TODO: This should get insert to the IRQueue only once per
+        // OPTIMIZE: This should get insert to the operatorList only once per
         // page.
         insertDependency([loadedName]);
         return loadedName;
@@ -179,65 +197,60 @@ var PartialEvaluator = (function partialEvaluator() {
         var w = dict.get('Width', 'W');
         var h = dict.get('Height', 'H');
 
-        if (image instanceof JpegStream && image.isNative) {
-          var objId = 'img_' + uniquePrefix + (++self.objIdCounter);
-          handler.send('obj', [objId, 'JpegStream', image.getIR()]);
-
-          // Add the dependency on the image object.
-          insertDependency([objId]);
-
-          // The normal fn.
-          fn = 'paintJpegXObject';
-          args = [objId, w, h];
-
+        var imageMask = dict.get('ImageMask', 'IM') || false;
+        if (imageMask) {
+          // This depends on a tmpCanvas beeing filled with the
+          // current fillStyle, such that processing the pixel
+          // data can't be done here. Instead of creating a
+          // complete PDFImage, only read the information needed
+          // for later.
+
+          var width = dict.get('Width', 'W');
+          var height = dict.get('Height', 'H');
+          var bitStrideLength = (width + 7) >> 3;
+          var imgArray = image.getBytes(bitStrideLength * height);
+          var decode = dict.get('Decode', 'D');
+          var inverseDecode = !!decode && decode[0] > 0;
+
+          fn = 'paintImageMaskXObject';
+          args = [imgArray, inverseDecode, width, height];
           return;
         }
 
-        // Needs to be rendered ourself.
-
-        // Figure out if the image has an imageMask.
-        var imageMask = dict.get('ImageMask', 'IM') || false;
-
         // If there is no imageMask, create the PDFImage and a lot
         // of image processing can be done here.
-        if (!imageMask) {
-          var imageObj = new PDFImage(xref, resources, image, inline);
-
-          if (imageObj.imageMask) {
-            throw 'Can\'t handle this in the web worker :/';
-          }
-
-          var imgData = {
-            width: w,
-            height: h,
-            data: new Uint8Array(w * h * 4)
-          };
-          var pixels = imgData.data;
-          imageObj.fillRgbaBuffer(pixels, imageObj.decode);
-
-          fn = 'paintImageXObject';
-          args = [imgData];
+        var objId = 'img_' + uniquePrefix + (++self.objIdCounter);
+        insertDependency([objId]);
+        args = [objId, w, h];
+
+        var softMask = dict.get('SMask', 'IM') || false;
+        if (!softMask && image instanceof JpegStream &&
+            image.isNativelySupported(xref, resources)) {
+          // These JPEGs don't need any more processing so we can just send it.
+          fn = 'paintJpegXObject';
+          handler.send('obj', [objId, 'JpegStream', image.getIR()]);
           return;
         }
 
-        // This depends on a tmpCanvas beeing filled with the
-        // current fillStyle, such that processing the pixel
-        // data can't be done here. Instead of creating a
-        // complete PDFImage, only read the information needed
-        // for later.
-        fn = 'paintImageMaskXObject';
-
-        var width = dict.get('Width', 'W');
-        var height = dict.get('Height', 'H');
-        var bitStrideLength = (width + 7) >> 3;
-        var imgArray = image.getBytes(bitStrideLength * height);
-        var decode = dict.get('Decode', 'D');
-        var inverseDecode = !!decode && decode[0] > 0;
-
-        args = [imgArray, inverseDecode, width, height];
+        fn = 'paintImageXObject';
+
+        PDFImage.buildImage(function(imageObj) {
+            var drawWidth = imageObj.drawWidth;
+            var drawHeight = imageObj.drawHeight;
+            var imgData = {
+              width: drawWidth,
+              height: drawHeight,
+              data: new Uint8Array(drawWidth * drawHeight * 4)
+            };
+            var pixels = imgData.data;
+            imageObj.fillRgbaBuffer(pixels, drawWidth, drawHeight);
+            handler.send('obj', [objId, 'Image', imgData]);
+          }, handler, xref, resources, image, inline);
       }
 
-      uniquePrefix = uniquePrefix || '';
+      if (!queue)
+        queue = {};
+
       if (!queue.argsArray) {
         queue.argsArray = [];
       }
@@ -248,45 +261,48 @@ var PartialEvaluator = (function partialEvaluator() {
       var fnArray = queue.fnArray, argsArray = queue.argsArray;
       var dependencyArray = dependency || [];
 
-      resources = xref.fetchIfRef(resources) || new Dict();
-      var xobjs = xref.fetchIfRef(resources.get('XObject')) || new Dict();
-      var patterns = xref.fetchIfRef(resources.get('Pattern')) || new Dict();
-      var parser = new Parser(new Lexer(stream), false);
+      resources = resources || new Dict();
+      var xobjs = resources.get('XObject') || new Dict();
+      var patterns = resources.get('Pattern') || new Dict();
+      var parser = new Parser(new Lexer(stream), false, xref);
       var res = resources;
+      var hasNextObj = false, nextObj;
       var args = [], obj;
-      var getObjBt = function getObjBt() {
-        parser = this.oldParser;
-        return { name: 'BT' };
-      };
       var TILING_PATTERN = 1, SHADING_PATTERN = 2;
 
-      while (!isEOF(obj = parser.getObj())) {
+      while (true) {
+        if (hasNextObj) {
+          obj = nextObj;
+          hasNextObj = false;
+        } else {
+          obj = parser.getObj();
+          if (isEOF(obj))
+            break;
+        }
+
         if (isCmd(obj)) {
           var cmd = obj.cmd;
           var fn = OP_MAP[cmd];
           if (!fn) {
             // invalid content command, trying to recover
-            if (cmd.substr(-2) == 'BT') {
-              fn = OP_MAP[cmd.substr(0, cmd.length - 2)];
-              // feeding 'BT' on next interation
-              parser = {
-                getObj: getObjBt,
-                oldParser: parser
-              };
+            var cmds = splitCombinedOperations(cmd);
+            if (cmds) {
+              cmd = cmds[0];
+              fn = OP_MAP[cmd];
+              // feeding other command on the next interation
+              hasNextObj = true;
+              nextObj = Cmd.get(cmds[1]);
             }
           }
           assertWellFormed(fn, 'Unknown command "' + cmd + '"');
           // TODO figure out how to type-check vararg functions
 
           if ((cmd == 'SCN' || cmd == 'scn') && !args[args.length - 1].code) {
-            // Use the IR version for setStroke/FillColorN.
-            fn += '_IR';
-
             // compile tiling patterns
             var patternName = args[args.length - 1];
             // SCN/scn applies patterns along with normal colors
             if (isName(patternName)) {
-              var pattern = xref.fetchIfRef(patterns.get(patternName.name));
+              var pattern = patterns.get(patternName.name);
               if (pattern) {
                 var dict = isStream(pattern) ? pattern.dict : pattern;
                 var typeNum = dict.get('PatternType');
@@ -294,21 +310,20 @@ var PartialEvaluator = (function partialEvaluator() {
                 if (typeNum == TILING_PATTERN) {
                   // Create an IR of the pattern code.
                   var depIdx = dependencyArray.length;
-                  var queueObj = {};
-                  var codeIR = this.getIRQueue(pattern, dict.get('Resources'),
-                                               queueObj, dependencyArray);
+                  var operatorList = this.getOperatorList(pattern,
+                      dict.get('Resources') || resources, dependencyArray);
 
                   // Add the dependencies that are required to execute the
-                  // codeIR.
+                  // operatorList.
                   insertDependency(dependencyArray.slice(depIdx));
 
-                  args = TilingPattern.getIR(codeIR, dict, args);
+                  args = TilingPattern.getIR(operatorList, dict, args);
                 }
                 else if (typeNum == SHADING_PATTERN) {
-                  var shading = xref.fetchIfRef(dict.get('Shading'));
+                  var shading = dict.get('Shading');
                   var matrix = dict.get('Matrix');
-                  var pattern = Pattern.parseShading(shading, matrix, xref, res,
-                                                                  null /*ctx*/);
+                  var pattern = Pattern.parseShading(shading, matrix, xref,
+                                                     res);
                   args = pattern.getIR();
                 } else {
                   error('Unkown PatternType ' + typeNum);
@@ -320,7 +335,6 @@ var PartialEvaluator = (function partialEvaluator() {
             var name = args[0].name;
             var xobj = xobjs.get(name);
             if (xobj) {
-              xobj = xref.fetchIfRef(xobj);
               assertWellFormed(isStream(xobj), 'XObject should be a stream');
 
               var type = xobj.dict.get('Subtype');
@@ -336,14 +350,18 @@ var PartialEvaluator = (function partialEvaluator() {
                 fnArray.push('paintFormXObjectBegin');
                 argsArray.push([matrix, bbox]);
 
-                // This adds the IRQueue of the xObj to the current queue.
+                // This adds the operatorList of the xObj to the current queue.
                 var depIdx = dependencyArray.length;
 
-                this.getIRQueue(xobj, xobj.dict.get('Resources'), queue,
-                                dependencyArray);
+                // Pass in the current `queue` object. That means the `fnArray`
+                // and the `argsArray` in this scope is reused and new commands
+                // are added to them.
+                this.getOperatorList(xobj,
+                    xobj.dict.get('Resources') || resources,
+                    dependencyArray, queue);
 
                // Add the dependencies that are required to execute the
-               // codeIR.
+               // operatorList.
                insertDependency(dependencyArray.slice(depIdx));
 
                 fn = 'paintFormXObjectEnd';
@@ -367,28 +385,27 @@ var PartialEvaluator = (function partialEvaluator() {
               args = [ColorSpace.parseToIR(args[0], xref, resources)];
               break;
             case 'shadingFill':
-              var shadingRes = xref.fetchIfRef(res.get('Shading'));
+              var shadingRes = res.get('Shading');
               if (!shadingRes)
                 error('No shading resource found');
 
-              var shading = xref.fetchIfRef(shadingRes.get(args[0].name));
+              var shading = shadingRes.get(args[0].name);
               if (!shading)
                 error('No shading object found');
 
-              var shadingFill = Pattern.parseShading(shading, null, xref, res,
-                                                      null);
+              var shadingFill = Pattern.parseShading(shading, null, xref, res);
               var patternIR = shadingFill.getIR();
               args = [patternIR];
               fn = 'shadingFill';
               break;
             case 'setGState':
               var dictName = args[0];
-              var extGState = xref.fetchIfRef(resources.get('ExtGState'));
+              var extGState = resources.get('ExtGState');
 
               if (!isDict(extGState) || !extGState.has(dictName.name))
                 break;
 
-              var gsState = xref.fetchIfRef(extGState.get(dictName.name));
+              var gsState = extGState.get(dictName.name);
 
               // This array holds the converted/processed state data.
               var gsStateObj = [];
@@ -453,10 +470,7 @@ var PartialEvaluator = (function partialEvaluator() {
         }
       }
 
-      return {
-        fnArray: fnArray,
-        argsArray: argsArray
-      };
+      return queue;
     },
 
     extractDataStructures: function
@@ -470,7 +484,7 @@ var PartialEvaluator = (function partialEvaluator() {
 
       if (properties.composite) {
         // CIDSystemInfo helps to match CID to glyphs
-        var cidSystemInfo = xref.fetchIfRef(dict.get('CIDSystemInfo'));
+        var cidSystemInfo = dict.get('CIDSystemInfo');
         if (isDict(cidSystemInfo)) {
           properties.cidSystemInfo = {
             registry: cidSystemInfo.get('Registry'),
@@ -479,20 +493,24 @@ var PartialEvaluator = (function partialEvaluator() {
           };
         }
 
-        var cidToGidMap = xref.fetchIfRef(dict.get('CIDToGIDMap'));
+        var cidToGidMap = dict.get('CIDToGIDMap');
         if (isStream(cidToGidMap))
           properties.cidToGidMap = this.readCidToGidMap(cidToGidMap);
       }
 
+      var flags = properties.flags;
       var differences = [];
-      var baseEncoding = Encodings.StandardEncoding;
+      var baseEncoding = !!(flags & FontFlags.Symbolic) ?
+                         Encodings.symbolsEncoding : Encodings.StandardEncoding;
       var hasEncoding = dict.has('Encoding');
       if (hasEncoding) {
-        var encoding = xref.fetchIfRef(dict.get('Encoding'));
+        var encoding = dict.get('Encoding');
         if (isDict(encoding)) {
           var baseName = encoding.get('BaseEncoding');
           if (baseName)
             baseEncoding = Encodings[baseName.name];
+          else
+            hasEncoding = false; // base encoding was not provided
 
           // Load the differences between the base and original
           if (encoding.has('Differences')) {
@@ -512,14 +530,14 @@ var PartialEvaluator = (function partialEvaluator() {
           error('Encoding is not a Name nor a Dict');
         }
       }
+
       properties.differences = differences;
       properties.baseEncoding = baseEncoding;
       properties.hasEncoding = hasEncoding;
     },
 
-    readToUnicode:
-      function partialEvaluatorReadToUnicode(toUnicode, xref) {
-      var cmapObj = xref.fetchIfRef(toUnicode);
+    readToUnicode: function PartialEvaluator_readToUnicode(toUnicode, xref) {
+      var cmapObj = toUnicode;
       var charToUnicode = [];
       if (isName(cmapObj)) {
         var isIdentityMap = cmapObj.name.substr(0, 9) == 'Identity-';
@@ -532,9 +550,9 @@ var PartialEvaluator = (function partialEvaluator() {
 
         var cmap = cmapObj.getBytes(cmapObj.length);
         for (var i = 0, ii = cmap.length; i < ii; i++) {
-          var byte = cmap[i];
-          if (byte == 0x20 || byte == 0x0D || byte == 0x0A ||
-              byte == 0x3C || byte == 0x5B || byte == 0x5D) {
+          var octet = cmap[i];
+          if (octet == 0x20 || octet == 0x0D || octet == 0x0A ||
+              octet == 0x3C || octet == 0x5B || octet == 0x5D) {
             switch (token) {
               case 'usecmap':
                 error('usecmap is not implemented');
@@ -554,9 +572,21 @@ var PartialEvaluator = (function partialEvaluator() {
                   var startRange = tokens[j];
                   var endRange = tokens[j + 1];
                   var code = tokens[j + 2];
-                  while (startRange <= endRange) {
-                    charToUnicode[startRange] = code++;
-                    ++startRange;
+                  if (code == 0xFFFF) {
+                    // CMap is broken, assuming code == startRange
+                    code = startRange;
+                  }
+                  if (isArray(code)) {
+                    var codeindex = 0;
+                    while (startRange <= endRange) {
+                      charToUnicode[startRange] = code[codeindex++];
+                      ++startRange;
+                    }
+                  } else {
+                    while (startRange <= endRange) {
+                      charToUnicode[startRange] = code++;
+                      ++startRange;
+                    }
                   }
                 }
                 break;
@@ -579,7 +609,7 @@ var PartialEvaluator = (function partialEvaluator() {
                 tokens.push(token);
                 token = '';
             }
-            switch (byte) {
+            switch (octet) {
               case 0x5B:
                 // begin list parsing
                 tokens.push(beginArrayToken);
@@ -593,21 +623,39 @@ var PartialEvaluator = (function partialEvaluator() {
                 tokens.push(items);
                 break;
             }
-          } else if (byte == 0x3E) {
+          } else if (octet == 0x3E) {
             if (token.length) {
-              // parsing hex number
-              tokens.push(parseInt(token, 16));
-              token = '';
+              if (token.length <= 4) {
+                // parsing hex number
+                tokens.push(parseInt(token, 16));
+                token = '';
+              } else {
+                // parsing hex UTF-16BE numbers
+                var str = [];
+                for (var k = 0, kk = token.length; k < kk; k += 4) {
+                  var b = parseInt(token.substr(k, 4), 16);
+                  if (b <= 0x10) {
+                    k += 4;
+                    b = (b << 16) | parseInt(token.substr(k, 4), 16);
+                    b -= 0x10000;
+                    str.push(0xD800 | (b >> 10));
+                    str.push(0xDC00 | (b & 0x3FF));
+                    break;
+                  }
+                  str.push(b);
+                }
+                tokens.push(String.fromCharCode.apply(String, str));
+                token = '';
+              }
             }
           } else {
-            token += String.fromCharCode(byte);
+            token += String.fromCharCode(octet);
           }
         }
       }
       return charToUnicode;
     },
-    readCidToGidMap:
-      function partialEvaluatorReadCidToGidMap(cidToGidStream) {
+    readCidToGidMap: function PartialEvaluator_readCidToGidMap(cidToGidStream) {
       // Extract the encoding from the CIDToGIDMap
       var glyphsData = cidToGidStream.getBytes();
 
@@ -624,16 +672,16 @@ var PartialEvaluator = (function partialEvaluator() {
       return result;
     },
 
-    extractWidths: function partialEvaluatorWidths(dict,
+    extractWidths: function PartialEvaluator_extractWidths(dict,
                                                    xref,
                                                    descriptor,
                                                    properties) {
       var glyphsWidths = [];
       var defaultWidth = 0;
       if (properties.composite) {
-        defaultWidth = xref.fetchIfRef(dict.get('DW')) || 1000;
+        defaultWidth = dict.get('DW') || 1000;
 
-        var widths = xref.fetchIfRef(dict.get('W'));
+        var widths = dict.get('W');
         if (widths) {
           var start = 0, end = 0;
           for (var i = 0, ii = widths.length; i < ii; i++) {
@@ -654,7 +702,7 @@ var PartialEvaluator = (function partialEvaluator() {
         }
       } else {
         var firstChar = properties.firstChar;
-        var widths = xref.fetchIfRef(dict.get('Widths'));
+        var widths = dict.get('Widths');
         if (widths) {
           var j = firstChar;
           for (var i = 0, ii = widths.length; i < ii; i++)
@@ -676,7 +724,7 @@ var PartialEvaluator = (function partialEvaluator() {
       properties.widths = glyphsWidths;
     },
 
-    getBaseFontMetrics: function getBaseFontMetrics(name) {
+    getBaseFontMetrics: function PartialEvaluator_getBaseFontMetrics(name) {
       var defaultWidth = 0, widths = [];
       var glyphWidths = Metrics[stdFontMap[name] || name];
       if (isNum(glyphWidths)) {
@@ -691,8 +739,10 @@ var PartialEvaluator = (function partialEvaluator() {
       };
     },
 
-    translateFont: function partialEvaluatorTranslateFont(dict, xref, resources,
-                                                          dependency) {
+    translateFont: function PartialEvaluator_translateFont(dict,
+                                                           xref,
+                                                           resources,
+                                                           dependency) {
       var baseDict = dict;
       var type = dict.get('Subtype');
       assertWellFormed(isName(type), 'invalid font Subtype');
@@ -707,10 +757,7 @@ var PartialEvaluator = (function partialEvaluator() {
         if (!df)
           return null;
 
-        if (isRef(df))
-          df = xref.fetch(df);
-
-        dict = xref.fetchIfRef(isRef(df) ? df : df[0]);
+        dict = isArray(df) ? xref.fetchIfRef(df[0]) : df;
 
         type = dict.get('Subtype');
         assertWellFormed(isName(type), 'invalid font Subtype');
@@ -718,7 +765,7 @@ var PartialEvaluator = (function partialEvaluator() {
       }
       var maxCharIndex = composite ? 0xFFFF : 0xFF;
 
-      var descriptor = xref.fetchIfRef(dict.get('FontDescriptor'));
+      var descriptor = dict.get('FontDescriptor');
       if (!descriptor) {
         if (type.name == 'Type3') {
           // FontDescriptor is only required for Type3 fonts when the document
@@ -737,10 +784,18 @@ var PartialEvaluator = (function partialEvaluator() {
           baseFontName = baseFontName.name.replace(/[,_]/g, '-');
           var metrics = this.getBaseFontMetrics(baseFontName);
 
+          // Simulating descriptor flags attribute
+          var fontNameWoStyle = baseFontName.split('-')[0];
+          var flags = (serifFonts[fontNameWoStyle] ||
+            (fontNameWoStyle.search(/serif/gi) != -1) ? FontFlags.Serif : 0) |
+            (symbolsFonts[fontNameWoStyle] ? FontFlags.Symbolic :
+            FontFlags.Nonsymbolic);
+
           var properties = {
             type: type.name,
             widths: metrics.widths,
             defaultWidth: metrics.defaultWidth,
+            flags: flags,
             firstChar: 0,
             lastChar: maxCharIndex
           };
@@ -752,34 +807,31 @@ var PartialEvaluator = (function partialEvaluator() {
             properties: properties
           };
         }
-
       }
 
       // According to the spec if 'FontDescriptor' is declared, 'FirstChar',
-      // 'LastChar' and 'Widths' should exists too, but some PDF encoders seems
+      // 'LastChar' and 'Widths' should exist too, but some PDF encoders seem
       // to ignore this rule when a variant of a standart font is used.
       // TODO Fill the width array depending on which of the base font this is
       // a variant.
-      var firstChar = xref.fetchIfRef(dict.get('FirstChar')) || 0;
-      var lastChar = xref.fetchIfRef(dict.get('LastChar')) || maxCharIndex;
-      var fontName = xref.fetchIfRef(descriptor.get('FontName'));
+      var firstChar = dict.get('FirstChar') || 0;
+      var lastChar = dict.get('LastChar') || maxCharIndex;
+      var fontName = descriptor.get('FontName');
+      // Some bad pdf's have a string as the font name.
+      if (isString(fontName))
+        fontName = new Name(fontName);
       assertWellFormed(isName(fontName), 'invalid font name');
 
       var fontFile = descriptor.get('FontFile', 'FontFile2', 'FontFile3');
       if (fontFile) {
-        fontFile = xref.fetchIfRef(fontFile);
         if (fontFile.dict) {
           var subtype = fontFile.dict.get('Subtype');
           if (subtype)
             subtype = subtype.name;
 
           var length1 = fontFile.dict.get('Length1');
-          if (!isInt(length1))
-            length1 = xref.fetchIfRef(length1);
 
           var length2 = fontFile.dict.get('Length2');
-          if (!isInt(length2))
-            length2 = xref.fetchIfRef(length2);
         }
       }
 
@@ -808,15 +860,14 @@ var PartialEvaluator = (function partialEvaluator() {
 
       if (type.name === 'Type3') {
         properties.coded = true;
-        var charProcs = xref.fetchIfRef(dict.get('CharProcs'));
-        var fontResources = xref.fetchIfRef(dict.get('Resources')) || resources;
+        var charProcs = dict.get('CharProcs').getAll();
+        var fontResources = dict.get('Resources') || resources;
         properties.resources = fontResources;
-        properties.charProcIRQueues = {};
-        for (var key in charProcs.map) {
-          var glyphStream = xref.fetchIfRef(charProcs.map[key]);
-          var queueObj = {};
-          properties.charProcIRQueues[key] =
-            this.getIRQueue(glyphStream, fontResources, queueObj, dependency);
+        properties.charProcOperatorList = {};
+        for (var key in charProcs) {
+          var glyphStream = charProcs[key];
+          properties.charProcOperatorList[key] =
+            this.getOperatorList(glyphStream, fontResources, dependency);
         }
       }
 
@@ -829,11 +880,11 @@ var PartialEvaluator = (function partialEvaluator() {
     }
   };
 
-  return constructor;
+  return PartialEvaluator;
 })();
 
-var EvalState = (function evalState() {
-  function constructor() {
+var EvalState = (function EvalStateClosure() {
+  function EvalState() {
     // Are soft masks and alpha values shapes or opacities?
     this.alphaIsShape = false;
     this.fontSize = 0;
@@ -850,8 +901,8 @@ var EvalState = (function evalState() {
     this.fillColorSpace = null;
     this.strokeColorSpace = null;
   }
-  constructor.prototype = {
+  EvalState.prototype = {
   };
-  return constructor;
+  return EvalState;
 })();
 
diff --git a/apps/files_pdfviewer/js/pdfjs/src/fonts.js b/apps/files_pdfviewer/js/pdfjs/src/fonts.js
old mode 100755
new mode 100644
index 116bb4dfc71064a1e8f86d092d852628751117ec..7fdab8fbbf9f00740b40cd62b7f02bce75e07422
--- a/apps/files_pdfviewer/js/pdfjs/src/fonts.js
+++ b/apps/files_pdfviewer/js/pdfjs/src/fonts.js
@@ -3,8 +3,6 @@
 
 'use strict';
 
-var isWorker = (typeof window == 'undefined');
-
 /**
  * Maximum time to wait for a font to be loaded by font-face rules.
  */
@@ -13,6 +11,7 @@ var kMaxWaitForFontFace = 1000;
 // Unicode Private Use Area
 var kCmapGlyphOffset = 0xE000;
 var kSizeOfGlyphArea = 0x1900;
+var kSymbolicFontGlyphOffset = 0xF000;
 
 // PDF Glyph Space Units are one Thousandth of a TextSpace Unit
 // except for Type 3 fonts
@@ -21,269 +20,253 @@ var kPDFGlyphSpaceUnits = 1000;
 // Until hinting is fully supported this constant can be used
 var kHintingEnabled = false;
 
+var FontFlags = {
+  FixedPitch: 1,
+  Serif: 2,
+  Symbolic: 4,
+  Script: 8,
+  Nonsymbolic: 32,
+  Italic: 64,
+  AllCap: 65536,
+  SmallCap: 131072,
+  ForceBold: 262144
+};
+
 var Encodings = {
-  get ExpertEncoding() {
-    return shadow(this, 'ExpertEncoding', ['', '', '', '', '', '', '', '', '',
-      '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '',
-      '', '', '', '', '', 'space', 'exclamsmall', 'Hungarumlautsmall', '',
-      'dollaroldstyle', 'dollarsuperior', 'ampersandsmall', 'Acutesmall',
-      'parenleftsuperior', 'parenrightsuperior', 'twodotenleader',
-      'onedotenleader', 'comma', 'hyphen', 'period', 'fraction',
-      'zerooldstyle', 'oneoldstyle', 'twooldstyle', 'threeoldstyle',
-      'fouroldstyle', 'fiveoldstyle', 'sixoldstyle', 'sevenoldstyle',
-      'eightoldstyle', 'nineoldstyle', 'colon', 'semicolon', 'commasuperior',
-      'threequartersemdash', 'periodsuperior', 'questionsmall', '',
-      'asuperior', 'bsuperior', 'centsuperior', 'dsuperior', 'esuperior', '',
-      '', 'isuperior', '', '', 'lsuperior', 'msuperior', 'nsuperior',
-      'osuperior', '', '', 'rsuperior', 'ssuperior', 'tsuperior', '', 'ff',
-      'fi', 'fl', 'ffi', 'ffl', 'parenleftinferior', '', 'parenrightinferior',
-      'Circumflexsmall', 'hyphensuperior', 'Gravesmall', 'Asmall', 'Bsmall',
-      'Csmall', 'Dsmall', 'Esmall', 'Fsmall', 'Gsmall', 'Hsmall', 'Ismall',
-      'Jsmall', 'Ksmall', 'Lsmall', 'Msmall', 'Nsmall', 'Osmall', 'Psmall',
-      'Qsmall', 'Rsmall', 'Ssmall', 'Tsmall', 'Usmall', 'Vsmall', 'Wsmall',
-      'Xsmall', 'Ysmall', 'Zsmall', 'colonmonetary', 'onefitted', 'rupiah',
-      'Tildesmall', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '',
-      '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '',
-      '', 'exclamdownsmall', 'centoldstyle', 'Lslashsmall', '', '',
-      'Scaronsmall', 'Zcaronsmall', 'Dieresissmall', 'Brevesmall',
-      'Caronsmall', '', 'Dotaccentsmall', '', '', 'Macronsmall', '', '',
-      'figuredash', 'hypheninferior', '', '', 'Ogoneksmall', 'Ringsmall',
-      'Cedillasmall', '', '', '', 'onequarter', 'onehalf', 'threequarters',
-      'questiondownsmall', 'oneeighth', 'threeeighths', 'fiveeighths',
-      'seveneighths', 'onethird', 'twothirds', '', '', 'zerosuperior',
-      'onesuperior', 'twosuperior', 'threesuperior', 'foursuperior',
-      'fivesuperior', 'sixsuperior', 'sevensuperior', 'eightsuperior',
-      'ninesuperior', 'zeroinferior', 'oneinferior', 'twoinferior',
-      'threeinferior', 'fourinferior', 'fiveinferior', 'sixinferior',
-      'seveninferior', 'eightinferior', 'nineinferior', 'centinferior',
-      'dollarinferior', 'periodinferior', 'commainferior', 'Agravesmall',
-      'Aacutesmall', 'Acircumflexsmall', 'Atildesmall', 'Adieresissmall',
-      'Aringsmall', 'AEsmall', 'Ccedillasmall', 'Egravesmall', 'Eacutesmall',
-      'Ecircumflexsmall', 'Edieresissmall', 'Igravesmall', 'Iacutesmall',
-      'Icircumflexsmall', 'Idieresissmall', 'Ethsmall', 'Ntildesmall',
-      'Ogravesmall', 'Oacutesmall', 'Ocircumflexsmall', 'Otildesmall',
-      'Odieresissmall', 'OEsmall', 'Oslashsmall', 'Ugravesmall', 'Uacutesmall',
-      'Ucircumflexsmall', 'Udieresissmall', 'Yacutesmall', 'Thornsmall',
-      'Ydieresissmall'
-    ]);
-  },
-  get MacExpertEncoding() {
-    return shadow(this, 'MacExpertEncoding', ['', '', '', '', '', '', '', '',
-      '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '',
-      '', '', '', '', '', '', 'space', 'exclamsmall', 'Hungarumlautsmall',
-      'centoldstyle', 'dollaroldstyle', 'dollarsuperior', 'ampersandsmall',
-      'Acutesmall', 'parenleftsuperior', 'parenrightsuperior',
-      'twodotenleader', 'onedotenleader', 'comma', 'hyphen', 'period',
-      'fraction', 'zerooldstyle', 'oneoldstyle', 'twooldstyle',
-      'threeoldstyle', 'fouroldstyle', 'fiveoldstyle', 'sixoldstyle',
-      'sevenoldstyle', 'eightoldstyle', 'nineoldstyle', 'colon', 'semicolon',
-      '', 'threequartersemdash', '', 'questionsmall', '', '', '', '',
-      'Ethsmall', '', '', 'onequarter', 'onehalf', 'threequarters',
-      'oneeighth', 'threeeighths', 'fiveeighths', 'seveneighths', 'onethird',
-      'twothirds', '', '', '', '', '', '', 'ff', 'fi', 'fl', 'ffi', 'ffl',
-      'parenleftinferior', '', 'parenrightinferior', 'Circumflexsmall',
-      'hypheninferior', 'Gravesmall', 'Asmall', 'Bsmall', 'Csmall', 'Dsmall',
-      'Esmall', 'Fsmall', 'Gsmall', 'Hsmall', 'Ismall', 'Jsmall', 'Ksmall',
-      'Lsmall', 'Msmall', 'Nsmall', 'Osmall', 'Psmall', 'Qsmall', 'Rsmall',
-      'Ssmall', 'Tsmall', 'Usmall', 'Vsmall', 'Wsmall', 'Xsmall', 'Ysmall',
-      'Zsmall', 'colonmonetary', 'onefitted', 'rupiah', 'Tildesmall', '', '',
-      'asuperior', 'centsuperior', '', '', '', '', 'Aacutesmall',
-      'Agravesmall', 'Acircumflexsmall', 'Adieresissmall', 'Atildesmall',
-      'Aringsmall', 'Ccedillasmall', 'Eacutesmall', 'Egravesmall',
-      'Ecircumflexsmall', 'Edieresissmall', 'Iacutesmall', 'Igravesmall',
-      'Icircumflexsmall', 'Idieresissmall', 'Ntildesmall', 'Oacutesmall',
-      'Ogravesmall', 'Ocircumflexsmall', 'Odieresissmall', 'Otildesmall',
-      'Uacutesmall', 'Ugravesmall', 'Ucircumflexsmall', 'Udieresissmall', '',
-      'eightsuperior', 'fourinferior', 'threeinferior', 'sixinferior',
-      'eightinferior', 'seveninferior', 'Scaronsmall', '', 'centinferior',
-      'twoinferior', '', 'Dieresissmall', '', 'Caronsmall', 'osuperior',
-      'fiveinferior', '', 'commainferior', 'periodinferior', 'Yacutesmall', '',
-      'dollarinferior', '', 'Thornsmall', '', 'nineinferior', 'zeroinferior',
-      'Zcaronsmall', 'AEsmall', 'Oslashsmall', 'questiondownsmall',
-      'oneinferior', 'Lslashsmall', '', '', '', '', '', '', 'Cedillasmall', '',
-      '', '', '', '', 'OEsmall', 'figuredash', 'hyphensuperior', '', '', '',
-      '', 'exclamdownsmall', '', 'Ydieresissmall', '', 'onesuperior',
-      'twosuperior', 'threesuperior', 'foursuperior', 'fivesuperior',
-      'sixsuperior', 'sevensuperior', 'ninesuperior', 'zerosuperior', '',
-      'esuperior', 'rsuperior', 'tsuperior', '', '', 'isuperior', 'ssuperior',
-      'dsuperior', '', '', '', '', '', 'lsuperior', 'Ogoneksmall',
-      'Brevesmall', 'Macronsmall', 'bsuperior', 'nsuperior', 'msuperior',
-      'commasuperior', 'periodsuperior', 'Dotaccentsmall', 'Ringsmall'
-    ]);
-  },
-  get MacRomanEncoding() {
-    return shadow(this, 'MacRomanEncoding', ['', '', '', '', '', '', '', '',
-      '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '',
-      '', '', '', '', '', '', 'space', 'exclam', 'quotedbl', 'numbersign',
-      'dollar', 'percent', 'ampersand', 'quotesingle', 'parenleft',
-      'parenright', 'asterisk', 'plus', 'comma', 'hyphen', 'period', 'slash',
-      'zero', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight',
-      'nine', 'colon', 'semicolon', 'less', 'equal', 'greater', 'question',
-      'at', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
-      'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
-      'bracketleft', 'backslash', 'bracketright', 'asciicircum', 'underscore',
-      'grave', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
-      'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
-      'braceleft', 'bar', 'braceright', 'asciitilde', '', 'Adieresis', 'Aring',
-      'Ccedilla', 'Eacute', 'Ntilde', 'Odieresis', 'Udieresis', 'aacute',
-      'agrave', 'acircumflex', 'adieresis', 'atilde', 'aring', 'ccedilla',
-      'eacute', 'egrave', 'ecircumflex', 'edieresis', 'iacute', 'igrave',
-      'icircumflex', 'idieresis', 'ntilde', 'oacute', 'ograve', 'ocircumflex',
-      'odieresis', 'otilde', 'uacute', 'ugrave', 'ucircumflex', 'udieresis',
-      'dagger', 'degree', 'cent', 'sterling', 'section', 'bullet', 'paragraph',
-      'germandbls', 'registered', 'copyright', 'trademark', 'acute',
-      'dieresis', 'notequal', 'AE', 'Oslash', 'infinity', 'plusminus',
-      'lessequal', 'greaterequal', 'yen', 'mu', 'partialdiff', 'summation',
-      'product', 'pi', 'integral', 'ordfeminine', 'ordmasculine', 'Omega',
-      'ae', 'oslash', 'questiondown', 'exclamdown', 'logicalnot', 'radical',
-      'florin', 'approxequal', 'Delta', 'guillemotleft', 'guillemotright',
-      'ellipsis', 'space', 'Agrave', 'Atilde', 'Otilde', 'OE', 'oe', 'endash',
-      'emdash', 'quotedblleft', 'quotedblright', 'quoteleft', 'quoteright',
-      'divide', 'lozenge', 'ydieresis', 'Ydieresis', 'fraction', 'currency',
-      'guilsinglleft', 'guilsinglright', 'fi', 'fl', 'daggerdbl',
-      'periodcentered', 'quotesinglbase', 'quotedblbase', 'perthousand',
-      'Acircumflex', 'Ecircumflex', 'Aacute', 'Edieresis', 'Egrave', 'Iacute',
-      'Icircumflex', 'Idieresis', 'Igrave', 'Oacute', 'Ocircumflex', 'apple',
-      'Ograve', 'Uacute', 'Ucircumflex', 'Ugrave', 'dotlessi', 'circumflex',
-      'tilde', 'macron', 'breve', 'dotaccent', 'ring', 'cedilla',
-      'hungarumlaut', 'ogonek', 'caron'
-    ]);
-  },
-  get StandardEncoding() {
-    return shadow(this, 'StandardEncoding', ['', '', '', '', '', '', '', '',
-      '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '',
-      '', '', '', '', '', '', 'space', 'exclam', 'quotedbl', 'numbersign',
-      'dollar', 'percent', 'ampersand', 'quoteright', 'parenleft',
-      'parenright', 'asterisk', 'plus', 'comma', 'hyphen', 'period', 'slash',
-      'zero', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight',
-      'nine', 'colon', 'semicolon', 'less', 'equal', 'greater', 'question',
-      'at', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
-      'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
-      'bracketleft', 'backslash', 'bracketright', 'asciicircum', 'underscore',
-      'quoteleft', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l',
-      'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
-      'braceleft', 'bar', 'braceright', 'asciitilde', '', '', 'exclamdown',
-      'cent', 'sterling', 'fraction', 'yen', 'florin', 'section', 'currency',
-      'quotesingle', 'quotedblleft', 'guillemotleft', 'guilsinglleft',
-      'guilsinglright', 'fi', 'fl', '', 'endash', 'dagger', 'daggerdbl',
-      'periodcentered', '', 'paragraph', 'bullet', 'quotesinglbase',
-      'quotedblbase', 'quotedblright', 'guillemotright', 'ellipsis',
-      'perthousand', '', 'questiondown', '', 'grave', 'acute', 'circumflex',
-      'tilde', 'macron', 'breve', 'dotaccent', 'dieresis', '', 'ring',
-      'cedilla', '', 'hungarumlaut', 'ogonek', 'caron', 'emdash', '', '', '',
-      '', '', '', '', '', '', '', '', '', '', '', '', '', 'AE', '',
-      'ordfeminine', '', '', '', '', 'Lslash', 'Oslash', 'OE', 'ordmasculine',
-      '', '', '', '', '', 'ae', '', '', '', 'dotlessi', '', '', 'lslash',
-      'oslash', 'oe', 'germandbls'
-    ]);
-  },
-  get WinAnsiEncoding() {
-    return shadow(this, 'WinAnsiEncoding', ['', '', '', '', '', '', '', '', '',
-      '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '',
-      '', '', '', '', '', 'space', 'exclam', 'quotedbl', 'numbersign',
-      'dollar', 'percent', 'ampersand', 'quotesingle', 'parenleft',
-      'parenright', 'asterisk', 'plus', 'comma', 'hyphen', 'period', 'slash',
-      'zero', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight',
-      'nine', 'colon', 'semicolon', 'less', 'equal', 'greater', 'question',
-      'at', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
-      'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
-      'bracketleft', 'backslash', 'bracketright', 'asciicircum', 'underscore',
-      'grave', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
-      'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
-      'braceleft', 'bar', 'braceright', 'asciitilde', 'bullet', 'Euro',
-      'bullet', 'quotesinglbase', 'florin', 'quotedblbase', 'ellipsis',
-      'dagger', 'daggerdbl', 'circumflex', 'perthousand', 'Scaron',
-      'guilsinglleft', 'OE', 'bullet', 'Zcaron', 'bullet', 'bullet',
-      'quoteleft', 'quoteright', 'quotedblleft', 'quotedblright', 'bullet',
-      'endash', 'emdash', 'tilde', 'trademark', 'scaron', 'guilsinglright',
-      'oe', 'bullet', 'zcaron', 'Ydieresis', 'space', 'exclamdown', 'cent',
-      'sterling', 'currency', 'yen', 'brokenbar', 'section', 'dieresis',
-      'copyright', 'ordfeminine', 'guillemotleft', 'logicalnot', 'hyphen',
-      'registered', 'macron', 'degree', 'plusminus', 'twosuperior',
-      'threesuperior', 'acute', 'mu', 'paragraph', 'periodcentered',
-      'cedilla', 'onesuperior', 'ordmasculine', 'guillemotright', 'onequarter',
-      'onehalf', 'threequarters', 'questiondown', 'Agrave', 'Aacute',
-      'Acircumflex', 'Atilde', 'Adieresis', 'Aring', 'AE', 'Ccedilla',
-      'Egrave', 'Eacute', 'Ecircumflex', 'Edieresis', 'Igrave', 'Iacute',
-      'Icircumflex', 'Idieresis', 'Eth', 'Ntilde', 'Ograve', 'Oacute',
-      'Ocircumflex', 'Otilde', 'Odieresis', 'multiply', 'Oslash', 'Ugrave',
-      'Uacute', 'Ucircumflex', 'Udieresis', 'Yacute', 'Thorn', 'germandbls',
-      'agrave', 'aacute', 'acircumflex', 'atilde', 'adieresis', 'aring', 'ae',
-      'ccedilla', 'egrave', 'eacute', 'ecircumflex', 'edieresis', 'igrave',
-      'iacute', 'icircumflex', 'idieresis', 'eth', 'ntilde', 'ograve',
-      'oacute', 'ocircumflex', 'otilde', 'odieresis', 'divide', 'oslash',
-      'ugrave', 'uacute', 'ucircumflex', 'udieresis', 'yacute', 'thorn',
-      'ydieresis'
-    ]);
-  },
-  get symbolsEncoding() {
-    return shadow(this, 'symbolsEncoding', ['', '', '', '', '', '', '', '', '',
-      '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '',
-      '', '', '', '', '', 'space', 'exclam', 'universal', 'numbersign',
-      'existential', 'percent', 'ampersand', 'suchthat', 'parenleft',
-      'parenright', 'asteriskmath', 'plus', 'comma', 'minus', 'period',
-      'slash', 'zero', 'one', 'two', 'three', 'four', 'five', 'six', 'seven',
-      'eight', 'nine', 'colon', 'semicolon', 'less', 'equal', 'greater',
-      'question', 'congruent', 'Alpha', 'Beta', 'Chi', 'Delta', 'Epsilon',
-      'Phi', 'Gamma', 'Eta', 'Iota', 'theta1', 'Kappa', 'Lambda', 'Mu', 'Nu',
-      'Omicron', 'Pi', 'Theta', 'Rho', 'Sigma', 'Tau', 'Upsilon', 'sigma1',
-      'Omega', 'Xi', 'Psi', 'Zeta', 'bracketleft', 'therefore', 'bracketright',
-      'perpendicular', 'underscore', 'radicalex', 'alpha', 'beta', 'chi',
-      'delta', 'epsilon', 'phi', 'gamma', 'eta', 'iota', 'phi1', 'kappa',
-      'lambda', 'mu', 'nu', 'omicron', 'pi', 'theta', 'rho', 'sigma', 'tau',
-      'upsilon', 'omega1', 'omega', 'xi', 'psi', 'zeta', 'braceleft', 'bar',
-      'braceright', 'similar', '', '', '', '', '', '', '', '', '', '', '', '',
-      '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '',
-      '', '', '', 'Euro', 'Upsilon1', 'minute', 'lessequal', 'fraction',
-      'infinity', 'florin', 'club', 'diamond', 'heart', 'spade', 'arrowboth',
-      'arrowleft', 'arrowup', 'arrowright', 'arrowdown', 'degree', 'plusminus',
-      'second', 'greaterequal', 'multiply', 'proportional', 'partialdiff',
-      'bullet', 'divide', 'notequal', 'equivalence', 'approxequal', 'ellipsis',
-      'arrowvertex', 'arrowhorizex', 'carriagereturn', 'aleph', 'Ifraktur',
-      'Rfraktur', 'weierstrass', 'circlemultiply', 'circleplus', 'emptyset',
-      'intersection', 'union', 'propersuperset', 'reflexsuperset', 'notsubset',
-      'propersubset', 'reflexsubset', 'element', 'notelement', 'angle',
-      'gradient', 'registerserif', 'copyrightserif', 'trademarkserif',
-      'product', 'radical', 'dotmath', 'logicalnot', 'logicaland', 'logicalor',
-      'arrowdblboth', 'arrowdblleft', 'arrowdblup', 'arrowdblright',
-      'arrowdbldown', 'lozenge', 'angleleft', 'registersans', 'copyrightsans',
-      'trademarksans', 'summation', 'parenlefttp', 'parenleftex',
-      'parenleftbt', 'bracketlefttp', 'bracketleftex', 'bracketleftbt',
-      'bracelefttp', 'braceleftmid', 'braceleftbt', 'braceex', '',
-      'angleright', 'integral', 'integraltp', 'integralex', 'integralbt',
-      'parenrighttp', 'parenrightex', 'parenrightbt', 'bracketrighttp',
-      'bracketrightex', 'bracketrightbt', 'bracerighttp', 'bracerightmid',
-      'bracerightbt'
-    ]);
-  },
-  get zapfDingbatsEncoding() {
-    return shadow(this, 'zapfDingbatsEncoding', ['', '', '', '', '', '', '',
-      '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '',
-      '', '', '', '', '', '', '', 'space', 'a1', 'a2', 'a202', 'a3', 'a4',
-      'a5', 'a119', 'a118', 'a117', 'a11', 'a12', 'a13', 'a14', 'a15', 'a16',
-      'a105', 'a17', 'a18', 'a19', 'a20', 'a21', 'a22', 'a23', 'a24', 'a25',
-      'a26', 'a27', 'a28', 'a6', 'a7', 'a8', 'a9', 'a10', 'a29', 'a30', 'a31',
-      'a32', 'a33', 'a34', 'a35', 'a36', 'a37', 'a38', 'a39', 'a40', 'a41',
-      'a42', 'a43', 'a44', 'a45', 'a46', 'a47', 'a48', 'a49', 'a50', 'a51',
-      'a52', 'a53', 'a54', 'a55', 'a56', 'a57', 'a58', 'a59', 'a60', 'a61',
-      'a62', 'a63', 'a64', 'a65', 'a66', 'a67', 'a68', 'a69', 'a70', 'a71',
-      'a72', 'a73', 'a74', 'a203', 'a75', 'a204', 'a76', 'a77', 'a78', 'a79',
-      'a81', 'a82', 'a83', 'a84', 'a97', 'a98', 'a99', 'a100', '', '', '', '',
-      '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '',
-      '', '', '', '', '', '', '', '', '', '', '', '', 'a101', 'a102', 'a103',
-      'a104', 'a106', 'a107', 'a108', 'a112', 'a111', 'a110', 'a109', 'a120',
-      'a121', 'a122', 'a123', 'a124', 'a125', 'a126', 'a127', 'a128', 'a129',
-      'a130', 'a131', 'a132', 'a133', 'a134', 'a135', 'a136', 'a137', 'a138',
-      'a139', 'a140', 'a141', 'a142', 'a143', 'a144', 'a145', 'a146', 'a147',
-      'a148', 'a149', 'a150', 'a151', 'a152', 'a153', 'a154', 'a155', 'a156',
-      'a157', 'a158', 'a159', 'a160', 'a161', 'a163', 'a164', 'a196', 'a165',
-      'a192', 'a166', 'a167', 'a168', 'a169', 'a170', 'a171', 'a172', 'a173',
-      'a162', 'a174', 'a175', 'a176', 'a177', 'a178', 'a179', 'a193', 'a180',
-      'a199', 'a181', 'a200', 'a182', '', 'a201', 'a183', 'a184', 'a197',
-      'a185', 'a194', 'a198', 'a186', 'a195', 'a187', 'a188', 'a189', 'a190',
-      'a191'
-    ]);
-  }
+  ExpertEncoding: ['', '', '', '', '', '', '', '', '', '', '', '', '', '', '',
+    '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '',
+    'space', 'exclamsmall', 'Hungarumlautsmall', '', 'dollaroldstyle',
+    'dollarsuperior', 'ampersandsmall', 'Acutesmall', 'parenleftsuperior',
+    'parenrightsuperior', 'twodotenleader', 'onedotenleader', 'comma',
+    'hyphen', 'period', 'fraction', 'zerooldstyle', 'oneoldstyle',
+    'twooldstyle', 'threeoldstyle', 'fouroldstyle', 'fiveoldstyle',
+    'sixoldstyle', 'sevenoldstyle', 'eightoldstyle', 'nineoldstyle', 'colon',
+    'semicolon', 'commasuperior', 'threequartersemdash', 'periodsuperior',
+    'questionsmall', '', 'asuperior', 'bsuperior', 'centsuperior', 'dsuperior',
+    'esuperior', '', '', 'isuperior', '', '', 'lsuperior', 'msuperior',
+    'nsuperior', 'osuperior', '', '', 'rsuperior', 'ssuperior', 'tsuperior',
+    '', 'ff', 'fi', 'fl', 'ffi', 'ffl', 'parenleftinferior', '',
+    'parenrightinferior', 'Circumflexsmall', 'hyphensuperior', 'Gravesmall',
+    'Asmall', 'Bsmall', 'Csmall', 'Dsmall', 'Esmall', 'Fsmall', 'Gsmall',
+    'Hsmall', 'Ismall', 'Jsmall', 'Ksmall', 'Lsmall', 'Msmall', 'Nsmall',
+    'Osmall', 'Psmall', 'Qsmall', 'Rsmall', 'Ssmall', 'Tsmall', 'Usmall',
+    'Vsmall', 'Wsmall', 'Xsmall', 'Ysmall', 'Zsmall', 'colonmonetary',
+    'onefitted', 'rupiah', 'Tildesmall', '', '', '', '', '', '', '', '', '',
+    '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '',
+    '', '', '', '', '', '', 'exclamdownsmall', 'centoldstyle', 'Lslashsmall',
+    '', '', 'Scaronsmall', 'Zcaronsmall', 'Dieresissmall', 'Brevesmall',
+    'Caronsmall', '', 'Dotaccentsmall', '', '', 'Macronsmall', '', '',
+    'figuredash', 'hypheninferior', '', '', 'Ogoneksmall', 'Ringsmall',
+    'Cedillasmall', '', '', '', 'onequarter', 'onehalf', 'threequarters',
+    'questiondownsmall', 'oneeighth', 'threeeighths', 'fiveeighths',
+    'seveneighths', 'onethird', 'twothirds', '', '', 'zerosuperior',
+    'onesuperior', 'twosuperior', 'threesuperior', 'foursuperior',
+    'fivesuperior', 'sixsuperior', 'sevensuperior', 'eightsuperior',
+    'ninesuperior', 'zeroinferior', 'oneinferior', 'twoinferior',
+    'threeinferior', 'fourinferior', 'fiveinferior', 'sixinferior',
+    'seveninferior', 'eightinferior', 'nineinferior', 'centinferior',
+    'dollarinferior', 'periodinferior', 'commainferior', 'Agravesmall',
+    'Aacutesmall', 'Acircumflexsmall', 'Atildesmall', 'Adieresissmall',
+    'Aringsmall', 'AEsmall', 'Ccedillasmall', 'Egravesmall', 'Eacutesmall',
+    'Ecircumflexsmall', 'Edieresissmall', 'Igravesmall', 'Iacutesmall',
+    'Icircumflexsmall', 'Idieresissmall', 'Ethsmall', 'Ntildesmall',
+    'Ogravesmall', 'Oacutesmall', 'Ocircumflexsmall', 'Otildesmall',
+    'Odieresissmall', 'OEsmall', 'Oslashsmall', 'Ugravesmall', 'Uacutesmall',
+    'Ucircumflexsmall', 'Udieresissmall', 'Yacutesmall', 'Thornsmall',
+    'Ydieresissmall'],
+  MacExpertEncoding: ['', '', '', '', '', '', '', '', '', '', '', '', '', '',
+    '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '',
+    'space', 'exclamsmall', 'Hungarumlautsmall', 'centoldstyle',
+    'dollaroldstyle', 'dollarsuperior', 'ampersandsmall', 'Acutesmall',
+    'parenleftsuperior', 'parenrightsuperior', 'twodotenleader',
+    'onedotenleader', 'comma', 'hyphen', 'period', 'fraction', 'zerooldstyle',
+    'oneoldstyle', 'twooldstyle', 'threeoldstyle', 'fouroldstyle',
+    'fiveoldstyle', 'sixoldstyle', 'sevenoldstyle', 'eightoldstyle',
+    'nineoldstyle', 'colon', 'semicolon', '', 'threequartersemdash', '',
+    'questionsmall', '', '', '', '', 'Ethsmall', '', '', 'onequarter',
+    'onehalf', 'threequarters', 'oneeighth', 'threeeighths', 'fiveeighths',
+    'seveneighths', 'onethird', 'twothirds', '', '', '', '', '', '', 'ff',
+    'fi', 'fl', 'ffi', 'ffl', 'parenleftinferior', '', 'parenrightinferior',
+    'Circumflexsmall', 'hypheninferior', 'Gravesmall', 'Asmall', 'Bsmall',
+    'Csmall', 'Dsmall', 'Esmall', 'Fsmall', 'Gsmall', 'Hsmall', 'Ismall',
+    'Jsmall', 'Ksmall', 'Lsmall', 'Msmall', 'Nsmall', 'Osmall', 'Psmall',
+    'Qsmall', 'Rsmall', 'Ssmall', 'Tsmall', 'Usmall', 'Vsmall', 'Wsmall',
+    'Xsmall', 'Ysmall', 'Zsmall', 'colonmonetary', 'onefitted', 'rupiah',
+    'Tildesmall', '', '', 'asuperior', 'centsuperior', '', '', '', '',
+    'Aacutesmall', 'Agravesmall', 'Acircumflexsmall', 'Adieresissmall',
+    'Atildesmall', 'Aringsmall', 'Ccedillasmall', 'Eacutesmall', 'Egravesmall',
+    'Ecircumflexsmall', 'Edieresissmall', 'Iacutesmall', 'Igravesmall',
+    'Icircumflexsmall', 'Idieresissmall', 'Ntildesmall', 'Oacutesmall',
+    'Ogravesmall', 'Ocircumflexsmall', 'Odieresissmall', 'Otildesmall',
+    'Uacutesmall', 'Ugravesmall', 'Ucircumflexsmall', 'Udieresissmall', '',
+    'eightsuperior', 'fourinferior', 'threeinferior', 'sixinferior',
+    'eightinferior', 'seveninferior', 'Scaronsmall', '', 'centinferior',
+    'twoinferior', '', 'Dieresissmall', '', 'Caronsmall', 'osuperior',
+    'fiveinferior', '', 'commainferior', 'periodinferior', 'Yacutesmall', '',
+    'dollarinferior', '', 'Thornsmall', '', 'nineinferior', 'zeroinferior',
+    'Zcaronsmall', 'AEsmall', 'Oslashsmall', 'questiondownsmall',
+    'oneinferior', 'Lslashsmall', '', '', '', '', '', '', 'Cedillasmall', '',
+    '', '', '', '', 'OEsmall', 'figuredash', 'hyphensuperior', '', '', '', '',
+    'exclamdownsmall', '', 'Ydieresissmall', '', 'onesuperior', 'twosuperior',
+    'threesuperior', 'foursuperior', 'fivesuperior', 'sixsuperior',
+    'sevensuperior', 'ninesuperior', 'zerosuperior', '', 'esuperior',
+    'rsuperior', 'tsuperior', '', '', 'isuperior', 'ssuperior', 'dsuperior',
+    '', '', '', '', '', 'lsuperior', 'Ogoneksmall', 'Brevesmall',
+    'Macronsmall', 'bsuperior', 'nsuperior', 'msuperior', 'commasuperior',
+    'periodsuperior', 'Dotaccentsmall', 'Ringsmall'],
+  MacRomanEncoding: ['', '', '', '', '', '', '', '', '', '', '', '', '', '', '',
+    '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '',
+    'space', 'exclam', 'quotedbl', 'numbersign', 'dollar', 'percent',
+    'ampersand', 'quotesingle', 'parenleft', 'parenright', 'asterisk', 'plus',
+    'comma', 'hyphen', 'period', 'slash', 'zero', 'one', 'two', 'three',
+    'four', 'five', 'six', 'seven', 'eight', 'nine', 'colon', 'semicolon',
+    'less', 'equal', 'greater', 'question', 'at', 'A', 'B', 'C', 'D', 'E', 'F',
+    'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U',
+    'V', 'W', 'X', 'Y', 'Z', 'bracketleft', 'backslash', 'bracketright',
+    'asciicircum', 'underscore', 'grave', 'a', 'b', 'c', 'd', 'e', 'f', 'g',
+    'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
+    'w', 'x', 'y', 'z', 'braceleft', 'bar', 'braceright', 'asciitilde', '',
+    'Adieresis', 'Aring', 'Ccedilla', 'Eacute', 'Ntilde', 'Odieresis',
+    'Udieresis', 'aacute', 'agrave', 'acircumflex', 'adieresis', 'atilde',
+    'aring', 'ccedilla', 'eacute', 'egrave', 'ecircumflex', 'edieresis',
+    'iacute', 'igrave', 'icircumflex', 'idieresis', 'ntilde', 'oacute',
+    'ograve', 'ocircumflex', 'odieresis', 'otilde', 'uacute', 'ugrave',
+    'ucircumflex', 'udieresis', 'dagger', 'degree', 'cent', 'sterling',
+    'section', 'bullet', 'paragraph', 'germandbls', 'registered', 'copyright',
+    'trademark', 'acute', 'dieresis', 'notequal', 'AE', 'Oslash', 'infinity',
+    'plusminus', 'lessequal', 'greaterequal', 'yen', 'mu', 'partialdiff',
+    'summation', 'product', 'pi', 'integral', 'ordfeminine', 'ordmasculine',
+    'Omega', 'ae', 'oslash', 'questiondown', 'exclamdown', 'logicalnot',
+    'radical', 'florin', 'approxequal', 'Delta', 'guillemotleft',
+    'guillemotright', 'ellipsis', '', 'Agrave', 'Atilde', 'Otilde', 'OE',
+    'oe', 'endash', 'emdash', 'quotedblleft', 'quotedblright', 'quoteleft',
+    'quoteright', 'divide', 'lozenge', 'ydieresis', 'Ydieresis', 'fraction',
+    'currency', 'guilsinglleft', 'guilsinglright', 'fi', 'fl', 'daggerdbl',
+    'periodcentered', 'quotesinglbase', 'quotedblbase', 'perthousand',
+    'Acircumflex', 'Ecircumflex', 'Aacute', 'Edieresis', 'Egrave', 'Iacute',
+    'Icircumflex', 'Idieresis', 'Igrave', 'Oacute', 'Ocircumflex', 'apple',
+    'Ograve', 'Uacute', 'Ucircumflex', 'Ugrave', 'dotlessi', 'circumflex',
+    'tilde', 'macron', 'breve', 'dotaccent', 'ring', 'cedilla', 'hungarumlaut',
+    'ogonek', 'caron'],
+  StandardEncoding: ['', '', '', '', '', '', '', '', '', '', '', '', '', '', '',
+    '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '',
+    'space', 'exclam', 'quotedbl', 'numbersign', 'dollar', 'percent',
+    'ampersand', 'quoteright', 'parenleft', 'parenright', 'asterisk', 'plus',
+    'comma', 'hyphen', 'period', 'slash', 'zero', 'one', 'two', 'three',
+    'four', 'five', 'six', 'seven', 'eight', 'nine', 'colon', 'semicolon',
+    'less', 'equal', 'greater', 'question', 'at', 'A', 'B', 'C', 'D', 'E', 'F',
+    'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U',
+    'V', 'W', 'X', 'Y', 'Z', 'bracketleft', 'backslash', 'bracketright',
+    'asciicircum', 'underscore', 'quoteleft', 'a', 'b', 'c', 'd', 'e', 'f',
+    'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u',
+    'v', 'w', 'x', 'y', 'z', 'braceleft', 'bar', 'braceright', 'asciitilde',
+    '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '',
+    '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', 'exclamdown',
+    'cent', 'sterling', 'fraction', 'yen', 'florin', 'section', 'currency',
+    'quotesingle', 'quotedblleft', 'guillemotleft', 'guilsinglleft',
+    'guilsinglright', 'fi', 'fl', '', 'endash', 'dagger', 'daggerdbl',
+    'periodcentered', '', 'paragraph', 'bullet', 'quotesinglbase',
+    'quotedblbase', 'quotedblright', 'guillemotright', 'ellipsis',
+    'perthousand', '', 'questiondown', '', 'grave', 'acute', 'circumflex',
+    'tilde', 'macron', 'breve', 'dotaccent', 'dieresis', '', 'ring', 'cedilla',
+    '', 'hungarumlaut', 'ogonek', 'caron', 'emdash', '', '', '', '', '', '',
+    '', '', '', '', '', '', '', '', '', '', 'AE', '', 'ordfeminine', '', '',
+    '', '', 'Lslash', 'Oslash', 'OE', 'ordmasculine', '', '', '', '', '', 'ae',
+    '', '', '', 'dotlessi', '', '', 'lslash', 'oslash', 'oe', 'germandbls'],
+  WinAnsiEncoding: ['', '', '', '', '', '', '', '', '', '', '', '', '', '', '',
+    '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '',
+    'space', 'exclam', 'quotedbl', 'numbersign', 'dollar', 'percent',
+    'ampersand', 'quotesingle', 'parenleft', 'parenright', 'asterisk', 'plus',
+    'comma', 'hyphen', 'period', 'slash', 'zero', 'one', 'two', 'three',
+    'four', 'five', 'six', 'seven', 'eight', 'nine', 'colon', 'semicolon',
+    'less', 'equal', 'greater', 'question', 'at', 'A', 'B', 'C', 'D', 'E', 'F',
+    'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U',
+    'V', 'W', 'X', 'Y', 'Z', 'bracketleft', 'backslash', 'bracketright',
+    'asciicircum', 'underscore', 'grave', 'a', 'b', 'c', 'd', 'e', 'f', 'g',
+    'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
+    'w', 'x', 'y', 'z', 'braceleft', 'bar', 'braceright', 'asciitilde',
+    'bullet', 'Euro', 'bullet', 'quotesinglbase', 'florin', 'quotedblbase',
+    'ellipsis', 'dagger', 'daggerdbl', 'circumflex', 'perthousand', 'Scaron',
+    'guilsinglleft', 'OE', 'bullet', 'Zcaron', 'bullet', 'bullet', 'quoteleft',
+    'quoteright', 'quotedblleft', 'quotedblright', 'bullet', 'endash',
+    'emdash', 'tilde', 'trademark', 'scaron', 'guilsinglright', 'oe', 'bullet',
+    'zcaron', 'Ydieresis', '', 'exclamdown', 'cent', 'sterling',
+    'currency', 'yen', 'brokenbar', 'section', 'dieresis', 'copyright',
+    'ordfeminine', 'guillemotleft', 'logicalnot', 'hyphen', 'registered',
+    'macron', 'degree', 'plusminus', 'twosuperior', 'threesuperior', 'acute',
+    'mu', 'paragraph', 'periodcentered', 'cedilla', 'onesuperior',
+    'ordmasculine', 'guillemotright', 'onequarter', 'onehalf', 'threequarters',
+    'questiondown', 'Agrave', 'Aacute', 'Acircumflex', 'Atilde', 'Adieresis',
+    'Aring', 'AE', 'Ccedilla', 'Egrave', 'Eacute', 'Ecircumflex', 'Edieresis',
+    'Igrave', 'Iacute', 'Icircumflex', 'Idieresis', 'Eth', 'Ntilde', 'Ograve',
+    'Oacute', 'Ocircumflex', 'Otilde', 'Odieresis', 'multiply', 'Oslash',
+    'Ugrave', 'Uacute', 'Ucircumflex', 'Udieresis', 'Yacute', 'Thorn',
+    'germandbls', 'agrave', 'aacute', 'acircumflex', 'atilde', 'adieresis',
+    'aring', 'ae', 'ccedilla', 'egrave', 'eacute', 'ecircumflex', 'edieresis',
+    'igrave', 'iacute', 'icircumflex', 'idieresis', 'eth', 'ntilde', 'ograve',
+    'oacute', 'ocircumflex', 'otilde', 'odieresis', 'divide', 'oslash',
+    'ugrave', 'uacute', 'ucircumflex', 'udieresis', 'yacute', 'thorn',
+    'ydieresis'],
+  symbolsEncoding: ['', '', '', '', '', '', '', '', '', '', '', '', '', '', '',
+    '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '',
+    'space', 'exclam', 'universal', 'numbersign', 'existential', 'percent',
+    'ampersand', 'suchthat', 'parenleft', 'parenright', 'asteriskmath', 'plus',
+    'comma', 'minus', 'period', 'slash', 'zero', 'one', 'two', 'three', 'four',
+    'five', 'six', 'seven', 'eight', 'nine', 'colon', 'semicolon', 'less',
+    'equal', 'greater', 'question', 'congruent', 'Alpha', 'Beta', 'Chi',
+    'Delta', 'Epsilon', 'Phi', 'Gamma', 'Eta', 'Iota', 'theta1', 'Kappa',
+    'Lambda', 'Mu', 'Nu', 'Omicron', 'Pi', 'Theta', 'Rho', 'Sigma', 'Tau',
+    'Upsilon', 'sigma1', 'Omega', 'Xi', 'Psi', 'Zeta', 'bracketleft',
+    'therefore', 'bracketright', 'perpendicular', 'underscore', 'radicalex',
+    'alpha', 'beta', 'chi', 'delta', 'epsilon', 'phi', 'gamma', 'eta', 'iota',
+    'phi1', 'kappa', 'lambda', 'mu', 'nu', 'omicron', 'pi', 'theta', 'rho',
+    'sigma', 'tau', 'upsilon', 'omega1', 'omega', 'xi', 'psi', 'zeta',
+    'braceleft', 'bar', 'braceright', 'similar', '', '', '', '', '', '', '',
+    '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '',
+    '', '', '', '', '', '', '', 'Euro', 'Upsilon1', 'minute', 'lessequal',
+    'fraction', 'infinity', 'florin', 'club', 'diamond', 'heart', 'spade',
+    'arrowboth', 'arrowleft', 'arrowup', 'arrowright', 'arrowdown', 'degree',
+    'plusminus', 'second', 'greaterequal', 'multiply', 'proportional',
+    'partialdiff', 'bullet', 'divide', 'notequal', 'equivalence',
+    'approxequal', 'ellipsis', 'arrowvertex', 'arrowhorizex', 'carriagereturn',
+    'aleph', 'Ifraktur', 'Rfraktur', 'weierstrass', 'circlemultiply',
+    'circleplus', 'emptyset', 'intersection', 'union', 'propersuperset',
+    'reflexsuperset', 'notsubset', 'propersubset', 'reflexsubset', 'element',
+    'notelement', 'angle', 'gradient', 'registerserif', 'copyrightserif',
+    'trademarkserif', 'product', 'radical', 'dotmath', 'logicalnot',
+    'logicaland', 'logicalor', 'arrowdblboth', 'arrowdblleft', 'arrowdblup',
+    'arrowdblright', 'arrowdbldown', 'lozenge', 'angleleft', 'registersans',
+    'copyrightsans', 'trademarksans', 'summation', 'parenlefttp',
+    'parenleftex', 'parenleftbt', 'bracketlefttp', 'bracketleftex',
+    'bracketleftbt', 'bracelefttp', 'braceleftmid', 'braceleftbt', 'braceex',
+    '', 'angleright', 'integral', 'integraltp', 'integralex', 'integralbt',
+    'parenrighttp', 'parenrightex', 'parenrightbt', 'bracketrighttp',
+    'bracketrightex', 'bracketrightbt', 'bracerighttp', 'bracerightmid',
+    'bracerightbt'],
+  zapfDingbatsEncoding: ['', '', '', '', '', '', '', '', '', '', '', '', '', '',
+    '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '',
+    'space', 'a1', 'a2', 'a202', 'a3', 'a4', 'a5', 'a119', 'a118', 'a117',
+    'a11', 'a12', 'a13', 'a14', 'a15', 'a16', 'a105', 'a17', 'a18', 'a19',
+    'a20', 'a21', 'a22', 'a23', 'a24', 'a25', 'a26', 'a27', 'a28', 'a6', 'a7',
+    'a8', 'a9', 'a10', 'a29', 'a30', 'a31', 'a32', 'a33', 'a34', 'a35', 'a36',
+    'a37', 'a38', 'a39', 'a40', 'a41', 'a42', 'a43', 'a44', 'a45', 'a46',
+    'a47', 'a48', 'a49', 'a50', 'a51', 'a52', 'a53', 'a54', 'a55', 'a56',
+    'a57', 'a58', 'a59', 'a60', 'a61', 'a62', 'a63', 'a64', 'a65', 'a66',
+    'a67', 'a68', 'a69', 'a70', 'a71', 'a72', 'a73', 'a74', 'a203', 'a75',
+    'a204', 'a76', 'a77', 'a78', 'a79', 'a81', 'a82', 'a83', 'a84', 'a97',
+    'a98', 'a99', 'a100', '', '', '', '', '', '', '', '', '', '', '', '', '',
+    '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '',
+    '', '', 'a101', 'a102', 'a103', 'a104', 'a106', 'a107', 'a108', 'a112',
+    'a111', 'a110', 'a109', 'a120', 'a121', 'a122', 'a123', 'a124', 'a125',
+    'a126', 'a127', 'a128', 'a129', 'a130', 'a131', 'a132', 'a133', 'a134',
+    'a135', 'a136', 'a137', 'a138', 'a139', 'a140', 'a141', 'a142', 'a143',
+    'a144', 'a145', 'a146', 'a147', 'a148', 'a149', 'a150', 'a151', 'a152',
+    'a153', 'a154', 'a155', 'a156', 'a157', 'a158', 'a159', 'a160', 'a161',
+    'a163', 'a164', 'a196', 'a165', 'a192', 'a166', 'a167', 'a168', 'a169',
+    'a170', 'a171', 'a172', 'a173', 'a162', 'a174', 'a175', 'a176', 'a177',
+    'a178', 'a179', 'a193', 'a180', 'a199', 'a181', 'a200', 'a182', '', 'a201',
+    'a183', 'a184', 'a197', 'a185', 'a194', 'a198', 'a186', 'a195', 'a187',
+    'a188', 'a189', 'a190', 'a191']
 };
 
 /**
@@ -341,6 +324,21 @@ var stdFontMap = {
   'TimesNewRomanPSMT-Italic': 'Times-Italic'
 };
 
+/**
+ * Holds the map of the non-standard fonts that might be included as a standard
+ * fonts without glyph data.
+ */
+var nonStdFontMap = {
+  'ComicSansMS': 'Comic Sans MS',
+  'ComicSansMS-Bold': 'Comic Sans MS-Bold',
+  'ComicSansMS-BoldItalic': 'Comic Sans MS-BoldItalic',
+  'ComicSansMS-Italic': 'Comic Sans MS-Italic',
+  'LucidaConsole': 'Courier',
+  'LucidaConsole-Bold': 'Courier-Bold',
+  'LucidaConsole-BoldItalic': 'Courier-BoldOblique',
+  'LucidaConsole-Italic': 'Courier-Oblique'
+};
+
 var serifFonts = {
   'Adobe Jenson': true, 'Adobe Text': true, 'Albertus': true,
   'Aldus': true, 'Alexandria': true, 'Algerian': true,
@@ -388,13 +386,30 @@ var serifFonts = {
   'Wide Latin': true, 'Windsor': true, 'XITS': true
 };
 
+var symbolsFonts = {
+  'Dingbats': true, 'Symbol': true, 'ZapfDingbats': true
+};
+
+// Some characters, e.g. copyrightserif, mapped to the private use area and
+// might not be displayed using standard fonts. Mapping/hacking well-known chars
+// to the similar equivalents in the normal characters range.
+function mapPrivateUseChars(code) {
+  switch (code) {
+    case 0xF8E9: // copyrightsans
+    case 0xF6D9: // copyrightserif
+      return 0x00A9; // copyright
+    default:
+      return code;
+  }
+}
+
 var FontLoader = {
   listeningForFontLoad: false,
 
   bind: function fontLoaderBind(fonts, callback) {
     function checkFontsLoaded() {
-      for (var i = 0, ii = objs.length; i < ii; i++) {
-        var fontObj = objs[i];
+      for (var i = 0, ii = fonts.length; i < ii; i++) {
+        var fontObj = fonts[i];
         if (fontObj.loading) {
           return false;
         }
@@ -407,52 +422,45 @@ var FontLoader = {
       return true;
     }
 
-    var rules = [], names = [], objs = [];
+    var rules = [], names = [], fontsToLoad = [];
+    var fontCreateTimer = 0;
 
     for (var i = 0, ii = fonts.length; i < ii; i++) {
       var font = fonts[i];
 
-      // If there is already a fontObj on the font, then it was loaded/attached
-      // to the page already and we don't have to do anything for this font
-      // here future.
-      if (font.fontObj) {
+      // Add the font to the DOM only once or skip if the font
+      // is already loaded.
+      if (font.attached || font.loading == false) {
         continue;
       }
+      font.attached = true;
 
-      var obj = new Font(font.name, font.file, font.properties);
-
-      // Store the fontObj on the font such that `setFont` in CanvasGraphics
-      // can reuse it later again.
-      font.fontObj = obj;
-
-      objs.push(obj);
+      fontsToLoad.push(font);
 
       var str = '';
-      var data = obj.data;
+      var data = font.data;
       if (data) {
         var length = data.length;
         for (var j = 0; j < length; j++)
           str += String.fromCharCode(data[j]);
 
-        var rule = isWorker ? obj.bindWorker(str) : obj.bindDOM(str);
+        var rule = font.bindDOM(str);
         if (rule) {
           rules.push(rule);
-          names.push(obj.loadedName);
+          names.push(font.loadedName);
         }
       }
     }
 
     this.listeningForFontLoad = false;
     if (!isWorker && rules.length) {
-      FontLoader.prepareFontLoadEvent(rules, names, objs);
+      FontLoader.prepareFontLoadEvent(rules, names, fontsToLoad);
     }
 
     if (!checkFontsLoaded()) {
       document.documentElement.addEventListener(
         'pdfjsFontLoad', checkFontsLoaded, false);
     }
-
-    return objs;
   },
   // Set things up so that at least one pdfjsFontLoad event is
   // dispatched when all the @font-face |rules| for |names| have been
@@ -460,7 +468,7 @@ var FontLoader = {
   // has already started in this (outer) document, so that they should
   // be ordered before the load in the subdocument.
   prepareFontLoadEvent: function fontLoaderPrepareFontLoadEvent(rules, names,
-                                                                objs) {
+                                                                fonts) {
       /** Hack begin */
       // There's no event when a font has finished downloading so the
       // following code is a dirty hack to 'guess' when a font is
@@ -484,6 +492,15 @@ var FontLoader = {
       // The postMessage() hackery was added to work around chrome bug
       // 82402.
 
+      // Validate the names parameter -- the values can used to construct HTML.
+      if (!/^\w+$/.test(names.join(''))) {
+        error('Invalid font name(s): ' + names.join());
+
+        // Normally the error-function throws. But if a malicious code
+        // intercepts the function call then the return is needed.
+        return;
+      }
+
       var div = document.createElement('div');
       div.setAttribute('style',
                        'visibility: hidden;' +
@@ -501,8 +518,8 @@ var FontLoader = {
           'message',
           function fontLoaderMessage(e) {
             var fontNames = JSON.parse(e.data);
-            for (var i = 0, ii = objs.length; i < ii; ++i) {
-              var font = objs[i];
+            for (var i = 0, ii = fonts.length; i < ii; ++i) {
+              var font = fonts[i];
               font.loading = false;
             }
             var evt = document.createEvent('Events');
@@ -530,7 +547,8 @@ var FontLoader = {
       src += '  window.onload = function fontLoaderOnload() {\n';
       src += '    parent.postMessage(JSON.stringify(fontNames), "*");\n';
       src += '  }';
-      src += '</script></head><body>';
+      // Hack so the end script tag isn't counted if this is inline JS.
+      src += '</scr' + 'ipt></head><body>';
       for (var i = 0, ii = names.length; i < ii; ++i) {
         src += '<p style="font-family:\'' + names[i] + '\'">Hi</p>';
       }
@@ -719,20 +737,20 @@ function getUnicodeRangeFor(value) {
   return -1;
 }
 
-function adaptUnicode(unicode) {
-  return (unicode <= 0x1F || (unicode >= 127 && unicode < kSizeOfGlyphArea)) ?
-    unicode + kCmapGlyphOffset : unicode;
-}
-
-function isAdaptedUnicode(unicode) {
-  return unicode >= kCmapGlyphOffset &&
-    unicode < kCmapGlyphOffset + kSizeOfGlyphArea;
+function isRTLRangeFor(value) {
+  var range = UnicodeRanges[13];
+  if (value >= range.begin && value < range.end)
+    return true;
+  range = UnicodeRanges[11];
+  if (value >= range.begin && value < range.end)
+    return true;
+  return false;
 }
 
 function isSpecialUnicode(unicode) {
   return (unicode <= 0x1F || (unicode >= 127 && unicode < kSizeOfGlyphArea)) ||
-    unicode >= kCmapGlyphOffset &&
-    unicode < kCmapGlyphOffset + kSizeOfGlyphArea;
+    (unicode >= kCmapGlyphOffset &&
+    unicode < kCmapGlyphOffset + kSizeOfGlyphArea);
 }
 
 /**
@@ -743,18 +761,19 @@ function isSpecialUnicode(unicode) {
  *   var type1Font = new Font("MyFontName", binaryFile, propertiesObject);
  *   type1Font.bind();
  */
-var Font = (function Font() {
-  var constructor = function font_constructor(name, file, properties) {
+var Font = (function FontClosure() {
+  function Font(name, file, properties) {
     this.name = name;
     this.coded = properties.coded;
-    this.charProcIRQueues = properties.charProcIRQueues;
+    this.charProcOperatorList = properties.charProcOperatorList;
     this.resources = properties.resources;
     this.sizes = [];
 
     var names = name.split('+');
     names = names.length > 1 ? names[1] : names[0];
     names = names.split(/[-,_]/g)[0];
-    this.serif = serifFonts[names] || (name.search(/serif/gi) != -1);
+    this.isSerifFont = !!(properties.flags & FontFlags.Serif);
+    this.isSymbolicFont = !!(properties.flags & FontFlags.Symbolic);
 
     var type = properties.type;
     this.type = type;
@@ -762,7 +781,7 @@ var Font = (function Font() {
     // If the font is to be ignored, register it like an already loaded font
     // to avoid the cost of waiting for it be be loaded by the platform.
     if (properties.ignore) {
-      this.loadedName = this.serif ? 'serif' : 'sans-serif';
+      this.loadedName = this.isSerifFont ? 'serif' : 'sans-serif';
       this.loading = false;
       return;
     }
@@ -771,21 +790,30 @@ var Font = (function Font() {
     this.widths = properties.widths;
     this.defaultWidth = properties.defaultWidth;
     this.composite = properties.composite;
-    this.toUnicode = properties.toUnicode;
     this.hasEncoding = properties.hasEncoding;
 
     this.fontMatrix = properties.fontMatrix;
-    if (properties.type == 'Type3')
+    this.widthMultiplier = 1.0;
+    if (properties.type == 'Type3') {
+      this.encoding = properties.baseEncoding;
       return;
+    }
 
     // Trying to fix encoding using glyph CIDSystemInfo.
     this.loadCidToUnicode(properties);
 
+    if (properties.toUnicode)
+      this.toUnicode = properties.toUnicode;
+    else
+      this.rebuildToUnicode(properties);
+
+    this.toFontChar = this.buildToFontChar(this.toUnicode);
+
     if (!file) {
       // The file data is not specified. Trying to fix the font name
       // to be used with the canvas.font.
       var fontName = name.replace(/[,_]/g, '-');
-      fontName = stdFontMap[fontName] || fontName;
+      fontName = stdFontMap[fontName] || nonStdFontMap[fontName] || fontName;
 
       this.bold = (fontName.search(/bold/gi) != -1);
       this.italic = (fontName.search(/oblique/gi) != -1) ||
@@ -810,7 +838,7 @@ var Font = (function Font() {
 
         var subtype = properties.subtype;
         var cff = (subtype == 'Type1C' || subtype == 'CIDFontType0C') ?
-          new Type2CFF(file, properties) : new CFF(name, file, properties);
+          new CFFFont(file, properties) : new Type1Font(name, file, properties);
 
         // Wrap the CFF data inside an OTF font file
         data = this.convert(name, cff, properties);
@@ -832,9 +860,10 @@ var Font = (function Font() {
 
     this.data = data;
     this.fontMatrix = properties.fontMatrix;
+    this.widthMultiplier = !properties.fontMatrix ? 1.0 :
+      1.0 / properties.fontMatrix[0];
     this.encoding = properties.baseEncoding;
-    this.hasShortCmap = properties.hasShortCmap;
-    this.loadedName = getUniqueName();
+    this.loadedName = properties.loadedName;
     this.loading = true;
   };
 
@@ -887,6 +916,13 @@ var Font = (function Font() {
            String.fromCharCode(value & 0xff);
   };
 
+  function safeString16(value) {
+    // clamp value to the 16-bit int range
+    value = value > 0x7FFF ? 0x7FFF : value < -0x8000 ? -0x8000 : value;
+    return String.fromCharCode((value >> 8) & 0xff) +
+           String.fromCharCode(value & 0xff);
+  };
+
   function string32(value) {
     return String.fromCharCode((value >> 24) & 0xff) +
            String.fromCharCode((value >> 16) & 0xff) +
@@ -961,15 +997,15 @@ var Font = (function Font() {
     var ranges = [];
     for (var n = 0; n < length; ) {
       var start = codes[n].unicode;
-      var startCode = codes[n].code;
+      var codeIndices = [codes[n].code];
       ++n;
       var end = start;
       while (n < length && end + 1 == codes[n].unicode) {
+        codeIndices.push(codes[n].code);
         ++end;
         ++n;
       }
-      var endCode = codes[n - 1].code;
-      ranges.push([start, end, startCode, endCode]);
+      ranges.push([start, end, codeIndices]);
     }
 
     return ranges;
@@ -1012,17 +1048,16 @@ var Font = (function Font() {
         idDeltas += string16(0);
         idRangeOffsets += string16(offset);
 
-        var startCode = range[2];
-        var endCode = range[3];
-        for (var j = startCode; j <= endCode; ++j)
-          glyphsIds += string16(deltas[j]);
+        var codes = range[2];
+        for (var j = 0, jj = codes.length; j < jj; ++j)
+          glyphsIds += string16(deltas[codes[j]]);
       }
     } else {
       for (var i = 0; i < segCount - 1; i++) {
         var range = ranges[i];
         var start = range[0];
         var end = range[1];
-        var startCode = range[2];
+        var startCode = range[2][0];
 
         startCount += string16(start);
         endCount += string16(end);
@@ -1226,13 +1261,13 @@ var Font = (function Font() {
     return nameTable;
   }
 
-  constructor.prototype = {
+  Font.prototype = {
     name: null,
     font: null,
     mimetype: null,
     encoding: null,
 
-    checkAndRepair: function font_checkAndRepair(name, font, properties) {
+    checkAndRepair: function Font_checkAndRepair(name, font, properties) {
       function readTableEntry(file) {
         var tag = file.getBytes(4);
         tag = String.fromCharCode(tag[0]) +
@@ -1299,7 +1334,7 @@ var Font = (function Font() {
           properties.baseEncoding = encoding;
       }
 
-      function replaceCMapTable(cmap, font, properties) {
+      function readCMapTable(cmap, font) {
         var start = (font.start ? font.start : 0) + cmap.offset;
         font.pos = start;
 
@@ -1316,7 +1351,7 @@ var Font = (function Font() {
         }
 
         // Check that table are sorted by platformID then encodingID,
-        records.sort(function fontReplaceCMapTableSort(a, b) {
+        records.sort(function fontReadCMapTableSort(a, b) {
           return ((a.platformID << 16) + a.encodingID) -
                  ((b.platformID << 16) + b.encodingID);
         });
@@ -1371,16 +1406,15 @@ var Font = (function Font() {
             for (var j = 0; j < 256; j++) {
               var index = font.getByte();
               if (index) {
-                var unicode = adaptUnicode(j);
-                glyphs.push({ unicode: unicode, code: j });
+                glyphs.push({ unicode: j, code: j });
                 ids.push(index);
               }
             }
-
-            properties.hasShortCmap = true;
-
-            createGlyphNameMap(glyphs, ids, properties);
-            return cmap.data = createCMapTable(glyphs, ids);
+            return {
+              glyphs: glyphs,
+              ids: ids,
+              hasShortCmap: true
+            };
           } else if (format == 4) {
             // re-creating the table in format 4 since the encoding
             // might be changed
@@ -1432,17 +1466,18 @@ var Font = (function Font() {
                 var glyphCode = offsetIndex < 0 ? j :
                   offsets[offsetIndex + j - start];
                 glyphCode = (glyphCode + delta) & 0xFFFF;
-                if (glyphCode == 0 || isAdaptedUnicode(j))
+                if (glyphCode == 0)
                   continue;
 
-                var unicode = adaptUnicode(j);
-                glyphs.push({ unicode: unicode, code: j });
+                glyphs.push({ unicode: j, code: j });
                 ids.push(glyphCode);
               }
             }
 
-            createGlyphNameMap(glyphs, ids, properties);
-            return cmap.data = createCMapTable(glyphs, ids);
+            return {
+              glyphs: glyphs,
+              ids: ids
+            };
           } else if (format == 6) {
             // Format 6 is a 2-bytes dense mapping, which means the font data
             // lives glue together even if they are pretty far in the unicode
@@ -1457,19 +1492,18 @@ var Font = (function Font() {
             for (var j = 0; j < entryCount; j++) {
               var glyphCode = int16(font.getBytes(2));
               var code = firstCode + j;
-              if (isAdaptedUnicode(glyphCode))
-                continue;
 
-              var unicode = adaptUnicode(code);
-              glyphs.push({ unicode: unicode, code: code });
+              glyphs.push({ unicode: code, code: code });
               ids.push(glyphCode);
             }
 
-            createGlyphNameMap(glyphs, ids, properties);
-            return cmap.data = createCMapTable(glyphs, ids);
+            return {
+              glyphs: glyphs,
+              ids: ids
+            };
           }
         }
-        return cmap.data;
+        error('Unsupported cmap table format');
       };
 
       function sanitizeMetrics(font, header, metrics, numGlyphs) {
@@ -1505,6 +1539,61 @@ var Font = (function Font() {
         }
       };
 
+      function sanitizeGlyph(source, sourceStart, sourceEnd, dest, destStart) {
+        if (sourceEnd - sourceStart <= 12) {
+          // glyph with data less than 12 is invalid one
+          return 0;
+        }
+        var glyf = source.subarray(sourceStart, sourceEnd);
+        var contoursCount = (glyf[0] << 8) | glyf[1];
+        if (contoursCount & 0x8000) {
+          // complex glyph, writing as is
+          dest.set(glyf, destStart);
+          return glyf.length;
+        }
+
+        var j = 10, flagsCount = 0;
+        for (var i = 0; i < contoursCount; i++) {
+          var endPoint = (glyf[j] << 8) | glyf[j + 1];
+          flagsCount = endPoint + 1;
+          j += 2;
+        }
+        // skipping instructions
+        var instructionsLength = (glyf[j] << 8) | glyf[j + 1];
+        j += 2 + instructionsLength;
+        // validating flags
+        var coordinatesLength = 0;
+        for (var i = 0; i < flagsCount; i++) {
+          var flag = glyf[j++];
+          if (flag & 0xC0) {
+            // reserved flags must be zero, rejecting
+            return 0;
+          }
+          var xyLength = ((flag & 2) ? 1 : (flag & 16) ? 0 : 2) +
+                         ((flag & 4) ? 1 : (flag & 32) ? 0 : 2);
+          coordinatesLength += xyLength;
+          if (flag & 8) {
+            var repeat = glyf[j++];
+            i += repeat;
+            coordinatesLength += repeat * xyLength;
+          }
+        }
+        var glyphDataLength = j + coordinatesLength;
+        if (glyphDataLength > glyf.length) {
+          // not enough data for coordinates
+          return 0;
+        }
+        if (glyf.length - glyphDataLength > 3) {
+          // truncating and aligning to 4 bytes the long glyph data
+          glyphDataLength = (glyphDataLength + 3) & ~3;
+          dest.set(glyf.subarray(0, glyphDataLength), destStart);
+          return glyphDataLength;
+        }
+        // glyph data is fine
+        dest.set(glyf, destStart);
+        return glyf.length;
+      }
+
       function sanitizeGlyphLocations(loca, glyf, numGlyphs,
                                       isGlyphLocationsLong) {
         var itemSize, itemDecode, itemEncode;
@@ -1531,20 +1620,64 @@ var Font = (function Font() {
           };
         }
         var locaData = loca.data;
+        // removing the invalid glyphs
+        var oldGlyfData = glyf.data;
+        var oldGlyfDataLength = oldGlyfData.length;
+        var newGlyfData = new Uint8Array(oldGlyfDataLength);
         var startOffset = itemDecode(locaData, 0);
-        var firstOffset = itemDecode(locaData, itemSize);
-        if (firstOffset - startOffset < 12 || startOffset > 0) {
-          // removing first glyph
-          glyf.data = glyf.data.subarray(firstOffset);
-          glyf.length -= firstOffset;
-
-          itemEncode(locaData, 0, 0);
-          var i, pos = itemSize;
-          for (i = 1; i <= numGlyphs; ++i) {
-            itemEncode(locaData, pos,
-              itemDecode(locaData, pos) - firstOffset);
-            pos += itemSize;
+        var writeOffset = 0;
+        itemEncode(locaData, 0, writeOffset);
+        for (var i = 0, j = itemSize; i < numGlyphs; i++, j += itemSize) {
+          var endOffset = itemDecode(locaData, j);
+          if (endOffset > oldGlyfDataLength) {
+            // glyph end offset points outside glyf data, rejecting the glyph
+            itemEncode(locaData, j, writeOffset);
+            startOffset = endOffset;
+            continue;
           }
+
+          var newLength = sanitizeGlyph(oldGlyfData, startOffset, endOffset,
+                                        newGlyfData, writeOffset);
+          writeOffset += newLength;
+          itemEncode(locaData, j, writeOffset);
+          startOffset = endOffset;
+        }
+
+        if (writeOffset == 0) {
+          // glyf table cannot be empty -- redoing the glyf and loca tables
+          // to have single glyph with one point
+          var simpleGlyph = new Uint8Array(
+            [0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 0]);
+          for (var i = 0, j = itemSize; i < numGlyphs; i++, j += itemSize)
+            itemEncode(locaData, j, simpleGlyph.length);
+          glyf.data = simpleGlyph;
+          return;
+        }
+
+        glyf.data = newGlyfData.subarray(0, writeOffset);
+      }
+
+      function findEmptyGlyphs(locaTable, isGlyphLocationsLong, emptyGlyphIds) {
+        var itemSize, itemDecode;
+        if (isGlyphLocationsLong) {
+          itemSize = 4;
+          itemDecode = function fontItemDecodeLong(data, offset) {
+            return (data[offset] << 24) | (data[offset + 1] << 16) |
+                   (data[offset + 2] << 8) | data[offset + 3];
+          };
+        } else {
+          itemSize = 2;
+          itemDecode = function fontItemDecode(data, offset) {
+            return (data[offset] << 9) | (data[offset + 1] << 1);
+          };
+        }
+        var data = locaTable.data, length = data.length;
+        var lastOffset = itemDecode(data, 0);
+        for (var i = itemSize, j = 0; i < length; i += itemSize, j++) {
+          var offset = itemDecode(data, i);
+          if (offset == lastOffset)
+            emptyGlyphIds[j] = true;
+          lastOffset = offset;
         }
       }
 
@@ -1674,11 +1807,15 @@ var Font = (function Font() {
       sanitizeMetrics(font, hhea, hmtx, numGlyphs);
       sanitizeMetrics(font, vhea, vmtx, numGlyphs);
 
+      var isGlyphLocationsLong = int16([head.data[50], head.data[51]]);
       if (head && loca && glyf) {
-        var isGlyphLocationsLong = int16([head.data[50], head.data[51]]);
         sanitizeGlyphLocations(loca, glyf, numGlyphs, isGlyphLocationsLong);
       }
 
+      var emptyGlyphIds = [];
+      if (glyf)
+        findEmptyGlyphs(loca, isGlyphLocationsLong, emptyGlyphIds);
+
       // Sanitizer reduces the glyph advanceWidth to the maxAdvanceWidth
       // Sometimes it's 0. That needs to be fixed
       if (hhea.data[10] == 0 && hhea.data[11] == 0) {
@@ -1691,8 +1828,9 @@ var Font = (function Font() {
         readGlyphNameMap(post, properties);
       }
 
-      // Replace the old CMAP table with a shiny new one
+      var glyphs, ids;
       if (properties.type == 'CIDFontType2') {
+        // Replace the old CMAP table with a shiny new one
         // Type2 composite fonts map characters directly to glyphs so the cmap
         // table must be replaced.
         // canvas fillText will reencode some characters even if the font has a
@@ -1708,19 +1846,236 @@ var Font = (function Font() {
           tables.push(cmap);
         }
 
-        var glyphs = [];
-        for (i = 1; i < numGlyphs; i++) {
-          if (isAdaptedUnicode(i))
-            continue;
+        var cidToGidMap = properties.cidToGidMap || [];
+        var gidToCidMap = [0];
+        if (cidToGidMap.length > 0) {
+          for (var j = cidToGidMap.length - 1; j >= 0; j--) {
+            var gid = cidToGidMap[j];
+            if (gid)
+              gidToCidMap[gid] = j;
+          }
+          // filling the gaps using CID above the CIDs currently used in font
+          var nextCid = cidToGidMap.length;
+          for (var i = 1; i < numGlyphs; i++) {
+            if (!gidToCidMap[i])
+              gidToCidMap[i] = nextCid++;
+          }
+        }
 
-          glyphs.push({ unicode: adaptUnicode(i) });
+        glyphs = [];
+        ids = [];
+
+        var usedUnicodes = [];
+        var unassignedUnicodeItems = [];
+        for (var i = 1; i < numGlyphs; i++) {
+          var cid = gidToCidMap[i] || i;
+          var unicode = this.toFontChar[cid];
+          if (!unicode || typeof unicode !== 'number' ||
+              isSpecialUnicode(unicode) || unicode in usedUnicodes) {
+            unassignedUnicodeItems.push(i);
+            continue;
+          }
+          usedUnicodes[unicode] = true;
+          glyphs.push({ unicode: unicode, code: cid });
+          ids.push(i);
+        }
+        // trying to fit as many unassigned symbols as we can
+        // in the range allocated for the user defined symbols
+        var unusedUnicode = kCmapGlyphOffset;
+        for (var j = 0, jj = unassignedUnicodeItems.length; j < jj; j++) {
+          var i = unassignedUnicodeItems[j];
+          var cid = gidToCidMap[i] || i;
+          while (unusedUnicode in usedUnicodes)
+            unusedUnicode++;
+          if (unusedUnicode >= kCmapGlyphOffset + kSizeOfGlyphArea)
+            break;
+          var unicode = unusedUnicode++;
+          this.toFontChar[cid] = unicode;
+          usedUnicodes[unicode] = true;
+          glyphs.push({ unicode: unicode, code: cid });
+          ids.push(i);
         }
-        cmap.data = createCMapTable(glyphs);
       } else {
-        replaceCMapTable(cmap, font, properties);
+        var cmapTable = readCMapTable(cmap, font);
+
+        glyphs = cmapTable.glyphs;
+        ids = cmapTable.ids;
+
+        var hasShortCmap = !!cmapTable.hasShortCmap;
+        var toFontChar = this.toFontChar;
+
+        if (hasShortCmap && ids.length == numGlyphs) {
+          // Fixes the short cmap tables -- some generators use incorrect
+          // glyph id.
+          for (var i = 0, ii = ids.length; i < ii; i++)
+            ids[i] = i;
+        }
+
+        var unusedUnicode = kCmapGlyphOffset;
+        var glyphNames = properties.glyphNames || [];
+        var encoding = properties.baseEncoding;
+        var differences = properties.differences;
+        if (toFontChar && toFontChar.length > 0) {
+          // checking if cmap is just identity map
+          var isIdentity = true;
+          for (var i = 0, ii = glyphs.length; i < ii; i++) {
+            if (glyphs[i].unicode != i + 1) {
+              isIdentity = false;
+              break;
+            }
+          }
+          // if it is, replacing with meaningful toUnicode values
+          if (isIdentity && !this.isSymbolicFont) {
+            var usedUnicodes = [], unassignedUnicodeItems = [];
+            for (var i = 0, ii = glyphs.length; i < ii; i++) {
+              var unicode = toFontChar[i + 1];
+              if (!unicode || typeof unicode !== 'number' ||
+                  unicode in usedUnicodes) {
+                unassignedUnicodeItems.push(i);
+                continue;
+              }
+              glyphs[i].unicode = unicode;
+              usedUnicodes[unicode] = true;
+            }
+            for (var j = 0, jj = unassignedUnicodeItems.length; j < jj; j++) {
+              var i = unassignedUnicodeItems[j];
+              while (unusedUnicode in usedUnicodes)
+                unusedUnicode++;
+              var cid = i + 1;
+              // override only if unicode mapping is not specified
+              if (!(cid in toFontChar))
+                toFontChar[cid] = unusedUnicode;
+              glyphs[i].unicode = unusedUnicode++;
+            }
+            this.useToFontChar = true;
+          }
+        }
+
+        // remove glyph references outside range of avaialable glyphs or empty
+        var glyphsRemoved = 0;
+        for (var i = ids.length - 1; i >= 0; i--) {
+          if (ids[i] < numGlyphs &&
+              (!emptyGlyphIds[ids[i]] || this.isSymbolicFont))
+            continue;
+          ids.splice(i, 1);
+          glyphs.splice(i, 1);
+          glyphsRemoved++;
+        }
+
+        // checking if it's a "true" symbolic font
+        if (this.isSymbolicFont) {
+          var minUnicode = 0xFFFF, maxUnicode = 0;
+          for (var i = 0, ii = glyphs.length; i < ii; i++) {
+            var unicode = glyphs[i].unicode;
+            minUnicode = Math.min(minUnicode, unicode);
+            maxUnicode = Math.max(maxUnicode, unicode);
+          }
+          // high byte must be the same for min and max unicodes
+          if ((maxUnicode & 0xFF00) != (minUnicode & 0xFF00))
+            this.isSymbolicFont = false;
+        }
+
+        // heuristics: if removed more than 2 glyphs encoding WinAnsiEncoding
+        // does not set properly
+        if (glyphsRemoved > 2) {
+          warn('Switching TrueType encoding to MacRomanEncoding for ' +
+               this.name + ' font');
+          encoding = Encodings.MacRomanEncoding;
+        }
+
+        if (hasShortCmap && this.hasEncoding && !this.isSymbolicFont) {
+          // Re-encode short map encoding to unicode -- that simplifies the
+          // resolution of MacRoman encoded glyphs logic for TrueType fonts:
+          // copying all characters to private use area, all mapping all known
+          // glyphs to the unicodes. The glyphs and ids arrays will grow.
+          var usedUnicodes = [];
+          for (var i = 0, ii = glyphs.length; i < ii; i++) {
+            var code = glyphs[i].unicode;
+            var gid = ids[i];
+            glyphs[i].unicode += kCmapGlyphOffset;
+            toFontChar[code] = glyphs[i].unicode;
+
+            var glyphName = glyphNames[gid] || encoding[code];
+            if (glyphName in GlyphsUnicode) {
+              var unicode = GlyphsUnicode[glyphName];
+              if (unicode in usedUnicodes)
+                continue;
+
+              usedUnicodes[unicode] = true;
+              glyphs.push({
+                unicode: unicode,
+                code: glyphs[i].code
+              });
+              ids.push(gid);
+              toFontChar[code] = unicode;
+            }
+          }
+          this.useToFontChar = true;
+        } else if (!this.isSymbolicFont && (this.hasEncoding ||
+                    properties.glyphNames || differences.length > 0)) {
+          // Re-encode cmap encoding to unicode, based on the 'post' table data
+          // diffrence array or base encoding
+          var reverseMap = [];
+          for (var i = 0, ii = glyphs.length; i < ii; i++)
+            reverseMap[glyphs[i].unicode] = i;
+
+          var newGlyphUnicodes = [];
+          for (var i = 0, ii = glyphs.length; i < ii; i++) {
+            var code = glyphs[i].unicode;
+            var changeCode = false;
+            var gid = ids[i];
+
+            var glyphName = glyphNames[gid];
+            if (!glyphName) {
+              glyphName = differences[code] || encoding[code];
+              changeCode = true;
+            }
+            if (glyphName in GlyphsUnicode) {
+              var unicode = GlyphsUnicode[glyphName];
+              if (!unicode || reverseMap[unicode] === i)
+                continue; // unknown glyph name or in its own place
+
+              newGlyphUnicodes[i] = unicode;
+              if (changeCode)
+                toFontChar[code] = unicode;
+              delete reverseMap[code];
+            }
+          }
+          for (var index in newGlyphUnicodes) {
+            var unicode = newGlyphUnicodes[index];
+            if (reverseMap[unicode]) {
+              // avoiding assigning to the same unicode
+              glyphs[index].unicode = unusedUnicode++;
+              continue;
+            }
+            glyphs[index].unicode = unicode;
+            reverseMap[unicode] = index;
+          }
+          this.useToFontChar = true;
+        }
+
+        // Moving all symbolic font glyphs into 0xF000 - 0xF0FF range.
+        if (this.isSymbolicFont) {
+          for (var i = 0, ii = glyphs.length; i < ii; i++) {
+            var code = glyphs[i].unicode & 0xFF;
+            var fontCharCode = kSymbolicFontGlyphOffset | code;
+            glyphs[i].unicode = toFontChar[code] = fontCharCode;
+          }
+          this.useToFontChar = true;
+        }
+
+        createGlyphNameMap(glyphs, ids, properties);
         this.glyphNameMap = properties.glyphNameMap;
       }
 
+      // Converting glyphs and ids into font's cmap table
+      cmap.data = createCMapTable(glyphs, ids);
+      var unicodeIsEnabled = [];
+      for (var i = 0, ii = glyphs.length; i < ii; i++) {
+        unicodeIsEnabled[glyphs[i].unicode] = true;
+      }
+      this.unicodeIsEnabled = unicodeIsEnabled;
+
       // Rewrite the 'post' table if needed
       if (requiredTables.indexOf('post') != -1) {
         tables.push({
@@ -1767,7 +2122,7 @@ var Font = (function Font() {
       return stringToArray(ttf.file);
     },
 
-    convert: function font_convert(fontName, font, properties) {
+    convert: function Font_convert(fontName, font, properties) {
       function isFixedPitch(glyphs) {
         for (var i = 0, ii = glyphs.length - 1; i < ii; i++) {
           if (glyphs[i] != glyphs[i + 1])
@@ -1808,6 +2163,14 @@ var Font = (function Font() {
         }
         properties.baseEncoding = encoding;
       }
+      if (properties.subtype == 'CIDFontType0C') {
+        var toFontChar = [];
+        for (var i = 0; i < charstrings.length; ++i) {
+          var charstring = charstrings[i];
+          toFontChar[charstring.code] = charstring.unicode;
+        }
+        this.toFontChar = toFontChar;
+      }
 
       var fields = {
         // PostScript Font Program
@@ -1832,9 +2195,9 @@ var Font = (function Font() {
               '\x00\x00\x00\x00\x9e\x0b\x7e\x27' + // creation date
               '\x00\x00\x00\x00\x9e\x0b\x7e\x27' + // modifification date
               '\x00\x00' + // xMin
-              string16(properties.descent) + // yMin
+              safeString16(properties.descent) + // yMin
               '\x0F\xFF' + // xMax
-              string16(properties.ascent) + // yMax
+              safeString16(properties.ascent) + // yMax
               string16(properties.italicAngle ? 2 : 0) + // macStyle
               '\x00\x11' + // lowestRecPPEM
               '\x00\x00' + // fontDirectionHint
@@ -1846,15 +2209,15 @@ var Font = (function Font() {
         'hhea': (function fontFieldsHhea() {
           return stringToArray(
               '\x00\x01\x00\x00' + // Version number
-              string16(properties.ascent) + // Typographic Ascent
-              string16(properties.descent) + // Typographic Descent
+              safeString16(properties.ascent) + // Typographic Ascent
+              safeString16(properties.descent) + // Typographic Descent
               '\x00\x00' + // Line Gap
               '\xFF\xFF' + // advanceWidthMax
               '\x00\x00' + // minLeftSidebearing
               '\x00\x00' + // minRightSidebearing
               '\x00\x00' + // xMaxExtent
-              string16(properties.capHeight) + // caretSlopeRise
-              string16(Math.tan(properties.italicAngle) *
+              safeString16(properties.capHeight) + // caretSlopeRise
+              safeString16(Math.tan(properties.italicAngle) *
                        properties.xHeight) + // caretSlopeRun
               '\x00\x00' + // caretOffset
               '\x00\x00' + // -reserved-
@@ -1868,8 +2231,11 @@ var Font = (function Font() {
         // Horizontal metrics
         'hmtx': (function fontFieldsHmtx() {
           var hmtx = '\x00\x00\x00\x00'; // Fake .notdef
-          for (var i = 0, ii = charstrings.length; i < ii; i++)
-            hmtx += string16(charstrings[i].width) + string16(0);
+          for (var i = 0, ii = charstrings.length; i < ii; i++) {
+            var charstring = charstrings[i];
+            var width = 'width' in charstring ? charstring.width : 0;
+            hmtx += string16(width) + string16(0);
+          }
           return stringToArray(hmtx);
         })(),
 
@@ -1898,17 +2264,48 @@ var Font = (function Font() {
       return stringToArray(otf.file);
     },
 
-    loadCidToUnicode: function font_loadCidToUnicode(properties) {
-      if (properties.cidToGidMap) {
-        this.cidToUnicode = properties.cidToGidMap;
-        return;
+    buildToFontChar: function Font_buildToFontChar(toUnicode) {
+      var result = [];
+      var unusedUnicode = kCmapGlyphOffset;
+      for (var i = 0, ii = toUnicode.length; i < ii; i++) {
+        var unicode = toUnicode[i];
+        var fontCharCode = typeof unicode === 'object' ? unusedUnicode++ :
+          unicode;
+        if (typeof unicode !== 'undefined')
+          result[i] = fontCharCode;
+      }
+      return result;
+    },
+
+    rebuildToUnicode: function Font_rebuildToUnicode(properties) {
+      var firstChar = properties.firstChar, lastChar = properties.lastChar;
+      var map = [];
+      if (properties.composite) {
+        var isIdentityMap = this.cidToUnicode.length == 0;
+        for (var i = firstChar, ii = lastChar; i <= ii; i++) {
+          // TODO missing map the character according font's CMap
+          var cid = i;
+          map[i] = isIdentityMap ? cid : this.cidToUnicode[cid];
+        }
+      } else {
+        for (var i = firstChar, ii = lastChar; i <= ii; i++) {
+          var glyph = properties.differences[i];
+          if (!glyph)
+            glyph = properties.baseEncoding[i];
+          if (!!glyph && (glyph in GlyphsUnicode))
+            map[i] = GlyphsUnicode[glyph];
+        }
       }
+      this.toUnicode = map;
+    },
 
+    loadCidToUnicode: function Font_loadCidToUnicode(properties) {
       if (!properties.cidSystemInfo)
         return;
 
-      var cidToUnicodeMap = [];
+      var cidToUnicodeMap = [], unicodeToCIDMap = [];
       this.cidToUnicode = cidToUnicodeMap;
+      this.unicodeToCID = unicodeToCIDMap;
 
       var cidSystemInfo = properties.cidSystemInfo;
       var cidToUnicode;
@@ -1920,43 +2317,38 @@ var Font = (function Font() {
       if (!cidToUnicode)
         return; // identity encoding
 
-      var glyph = 1, i, j, k, ii;
+      var cid = 1, i, j, k, ii;
       for (i = 0, ii = cidToUnicode.length; i < ii; ++i) {
         var unicode = cidToUnicode[i];
         if (isArray(unicode)) {
           var length = unicode.length;
-          for (j = 0; j < length; j++)
-            cidToUnicodeMap[unicode[j]] = glyph;
-          glyph++;
+          for (j = 0; j < length; j++) {
+            cidToUnicodeMap[cid] = unicode[j];
+            unicodeToCIDMap[unicode[j]] = cid;
+          }
+          cid++;
         } else if (typeof unicode === 'object') {
           var fillLength = unicode.f;
           if (fillLength) {
             k = unicode.c;
             for (j = 0; j < fillLength; ++j) {
-              cidToUnicodeMap[k] = glyph++;
+              cidToUnicodeMap[cid] = k;
+              unicodeToCIDMap[k] = cid;
+              cid++;
               k++;
             }
           } else
-            glyph += unicode.s;
+            cid += unicode.s;
         } else if (unicode) {
-          cidToUnicodeMap[unicode] = glyph++;
+          cidToUnicodeMap[cid] = unicode;
+          unicodeToCIDMap[unicode] = cid;
+          cid++;
         } else
-          glyph++;
+          cid++;
       }
     },
 
-    bindWorker: function font_bindWorker(data) {
-      postMessage({
-        action: 'font',
-        data: {
-          raw: data,
-          fontName: this.loadedName,
-          mimetype: this.mimetype
-        }
-      });
-    },
-
-    bindDOM: function font_bindDom(data) {
+    bindDOM: function Font_bindDOM(data) {
       var fontName = this.loadedName;
 
       // Add the font-face rule to the document
@@ -1964,89 +2356,137 @@ var Font = (function Font() {
                  window.btoa(data) + ');');
       var rule = "@font-face { font-family:'" + fontName + "';src:" + url + '}';
 
-      document.documentElement.firstChild.appendChild(
-        document.createElement('style'));
+      var styleElement = document.createElement('style');
+      document.documentElement.getElementsByTagName('head')[0].appendChild(
+        styleElement);
 
-      var styleSheet = document.styleSheets[document.styleSheets.length - 1];
+      var styleSheet = styleElement.sheet;
       styleSheet.insertRule(rule, styleSheet.cssRules.length);
 
+      if (PDFJS.pdfBug && FontInspector.enabled)
+        FontInspector.fontAdded(this, url);
+
       return rule;
     },
 
-    charToGlyph: function fonts_charToGlyph(charcode) {
-      var unicode, width, codeIRQueue;
+    get spaceWidth() {
+      // trying to estimate space character width
+      var possibleSpaceReplacements = ['space', 'minus', 'one', 'i'];
+      var width;
+      for (var i = 0, ii = possibleSpaceReplacements.length; i < ii; i++) {
+        var glyphName = possibleSpaceReplacements[i];
+        // if possible, getting width by glyph name
+        if (glyphName in this.widths) {
+          width = this.widths[glyphName];
+          break;
+        }
+        var glyphUnicode = GlyphsUnicode[glyphName];
+        // finding the charcode via unicodeToCID map
+        var charcode = 0;
+        if (this.composite)
+          charcode = this.unicodeToCID[glyphUnicode];
+        // ... via toUnicode map
+        if (!charcode && 'toUnicode' in this)
+          charcode = this.toUnicode.indexOf(glyphUnicode);
+        // setting it to unicode if negative or undefined
+        if (!(charcode > 0))
+          charcode = glyphUnicode;
+        // trying to get width via charcode
+        width = this.widths[charcode];
+        if (width)
+          break; // the non-zero width found
+      }
+      width = (width || this.defaultWidth) * this.widthMultiplier;
+      return shadow(this, 'spaceWidth', width);
+    },
+
+    charToGlyph: function Font_charToGlyph(charcode) {
+      var fontCharCode, width, operatorList, disabled;
 
       var width = this.widths[charcode];
 
       switch (this.type) {
         case 'CIDFontType0':
           if (this.noUnicodeAdaptation) {
-            width = this.widths[this.cidToUnicode[charcode]];
-            unicode = charcode;
+            width = this.widths[this.unicodeToCID[charcode] || charcode];
+            fontCharCode = mapPrivateUseChars(charcode);
             break;
           }
-          unicode = adaptUnicode(this.cidToUnicode[charcode] || charcode);
+          fontCharCode = this.toFontChar[charcode] || charcode;
           break;
         case 'CIDFontType2':
           if (this.noUnicodeAdaptation) {
-            width = this.widths[this.cidToUnicode[charcode]];
-            unicode = charcode;
+            width = this.widths[this.unicodeToCID[charcode] || charcode];
+            fontCharCode = mapPrivateUseChars(charcode);
             break;
           }
-          unicode = adaptUnicode(this.cidToUnicode[charcode] || charcode);
+          fontCharCode = this.toFontChar[charcode] || charcode;
           break;
         case 'Type1':
           var glyphName = this.differences[charcode] || this.encoding[charcode];
+          if (!isNum(width))
+            width = this.widths[glyphName];
           if (this.noUnicodeAdaptation) {
-            if (!isNum(width))
-              width = this.widths[glyphName];
-            unicode = GlyphsUnicode[glyphName] || charcode;
+            fontCharCode = mapPrivateUseChars(GlyphsUnicode[glyphName] ||
+              charcode);
             break;
           }
-          unicode = this.glyphNameMap[glyphName] ||
-            adaptUnicode(GlyphsUnicode[glyphName] || charcode);
+          fontCharCode = this.glyphNameMap[glyphName] ||
+            GlyphsUnicode[glyphName] || charcode;
           break;
         case 'Type3':
           var glyphName = this.differences[charcode] || this.encoding[charcode];
-          codeIRQueue = this.charProcIRQueues[glyphName];
-          unicode = charcode;
+          operatorList = this.charProcOperatorList[glyphName];
+          fontCharCode = charcode;
           break;
         case 'TrueType':
+          if (this.useToFontChar) {
+            fontCharCode = this.toFontChar[charcode] || charcode;
+            break;
+          }
           var glyphName = this.differences[charcode] || this.encoding[charcode];
           if (!glyphName)
             glyphName = Encodings.StandardEncoding[charcode];
           if (!isNum(width))
             width = this.widths[glyphName];
           if (this.noUnicodeAdaptation) {
-            unicode = GlyphsUnicode[glyphName] || charcode;
+            fontCharCode = GlyphsUnicode[glyphName] || charcode;
             break;
           }
-          if (!this.hasEncoding) {
-            unicode = adaptUnicode(charcode);
+          if (!this.hasEncoding || this.isSymbolicFont) {
+            fontCharCode = this.useToFontChar ? this.toFontChar[charcode] :
+              charcode;
             break;
           }
-          if (this.hasShortCmap) {
-            var j = Encodings.MacRomanEncoding.indexOf(glyphName);
-            unicode = j >= 0 && !isSpecialUnicode(j) ? j :
-              this.glyphNameMap[glyphName];
-          } else {
-            unicode = glyphName in GlyphsUnicode ?
-              adaptUnicode(GlyphsUnicode[glyphName]) :
-              this.glyphNameMap[glyphName];
-          }
+
+          // MacRoman encoding address by re-encoding the cmap table
+          fontCharCode = glyphName in this.glyphNameMap ?
+            this.glyphNameMap[glyphName] : GlyphsUnicode[glyphName];
           break;
         default:
           warn('Unsupported font type: ' + this.type);
           break;
       }
+
+      var unicodeChars = !('toUnicode' in this) ? charcode :
+        this.toUnicode[charcode] || charcode;
+      if (typeof unicodeChars === 'number')
+        unicodeChars = String.fromCharCode(unicodeChars);
+
+      width = (isNum(width) ? width : this.defaultWidth) * this.widthMultiplier;
+      disabled = this.unicodeIsEnabled ?
+        !this.unicodeIsEnabled[fontCharCode] : false;
+
       return {
-        unicode: unicode,
-        width: isNum(width) ? width : this.defaultWidth,
-        codeIRQueue: codeIRQueue
+        fontChar: String.fromCharCode(fontCharCode),
+        unicode: unicodeChars,
+        width: width,
+        disabled: disabled,
+        operatorList: operatorList
       };
     },
 
-    charsToGlyphs: function fonts_chars2Glyphs(chars) {
+    charsToGlyphs: function Font_charsToGlyphs(chars) {
       var charsCache = this.charsCache;
       var glyphs;
 
@@ -2094,7 +2534,7 @@ var Font = (function Font() {
     }
   };
 
-  return constructor;
+  return Font;
 })();
 
 /*
@@ -2381,7 +2821,13 @@ var Type1Parser = function type1Parser() {
     while (str[index++] != ']')
       count++;
 
-    var array = str.substr(start, count).split(' ');
+    str = str.substr(start, count);
+
+    str = str.trim();
+    // Remove adjacent spaces
+    str = str.replace(/\s+/g, ' ');
+
+    var array = str.split(' ');
     for (var i = 0, ii = array.length; i < ii; i++)
       array[i] = parseFloat(array[i] || 0);
     return array;
@@ -2404,7 +2850,7 @@ var Type1Parser = function type1Parser() {
     return c == ' ' || c == '\n' || c == '\x0d';
   }
 
-  this.extractFontProgram = function t1_extractFontProgram(stream) {
+  this.extractFontProgram = function Type1Parser_extractFontProgram(stream) {
     var eexec = decrypt(stream, kEexecEncryptionKey, 4);
     var eexecStr = '';
     for (var i = 0, ii = eexec.length; i < ii; i++)
@@ -2415,7 +2861,7 @@ var Type1Parser = function type1Parser() {
       subrs: [],
       charstrings: [],
       properties: {
-        'private': {
+        'privateData': {
           'lenIV': 4
         }
       }
@@ -2444,7 +2890,7 @@ var Type1Parser = function type1Parser() {
           (token == 'RD' || token == '-|')) {
         i++;
         var data = eexec.slice(i, i + length);
-        var lenIV = program.properties.private['lenIV'];
+        var lenIV = program.properties.privateData['lenIV'];
         var encoded = decrypt(data, kCharStringsEncryptionKey, lenIV);
         var str = decodeCharString(encoded);
 
@@ -2484,7 +2930,7 @@ var Type1Parser = function type1Parser() {
                 var length = parseInt(getToken(), 10);
                 getToken(); // read in 'RD'
                 var data = eexec.slice(i + 1, i + 1 + length);
-                var lenIV = program.properties.private['lenIV'];
+                var lenIV = program.properties.privateData['lenIV'];
                 var encoded = decrypt(data, kCharStringsEncryptionKey, lenIV);
                 var str = decodeCharString(encoded);
                 i = i + 1 + length;
@@ -2500,12 +2946,12 @@ var Type1Parser = function type1Parser() {
             case '/FamilyOtherBlues':
             case '/StemSnapH':
             case '/StemSnapV':
-              program.properties.private[token.substring(1)] =
+              program.properties.privateData[token.substring(1)] =
                 readNumberArray(eexecStr, i + 1);
               break;
             case '/StdHW':
             case '/StdVW':
-              program.properties.private[token.substring(1)] =
+              program.properties.privateData[token.substring(1)] =
                 readNumberArray(eexecStr, i + 2)[0];
               break;
             case '/BlueShift':
@@ -2514,7 +2960,7 @@ var Type1Parser = function type1Parser() {
             case '/BlueScale':
             case '/LanguageGroup':
             case '/ExpansionFactor':
-              program.properties.private[token.substring(1)] =
+              program.properties.privateData[token.substring(1)] =
                 readNumber(eexecStr, i + 1);
               break;
           }
@@ -2529,7 +2975,8 @@ var Type1Parser = function type1Parser() {
     return program;
   };
 
-  this.extractFontHeader = function t1_extractFontHeader(stream, properties) {
+  this.extractFontHeader = function Type1Parser_extractFontHeader(stream,
+                                                                  properties) {
     var headerString = '';
     for (var i = 0, ii = stream.length; i < ii; i++)
       headerString += String.fromCharCode(stream[i]);
@@ -2538,14 +2985,14 @@ var Type1Parser = function type1Parser() {
     var count = headerString.length;
     for (var i = 0; i < count; i++) {
       var getToken = function getToken() {
-        var char = headerString[i];
-        while (i < count && (isSeparator(char) || char == '/'))
-          char = headerString[++i];
+        var character = headerString[i];
+        while (i < count && (isSeparator(character) || character == '/'))
+          character = headerString[++i];
 
         var token = '';
-        while (i < count && !(isSeparator(char) || char == '/')) {
-          token += char;
-          char = headerString[++i];
+        while (i < count && !(isSeparator(character) || character == '/')) {
+          token += character;
+          character = headerString[++i];
         }
 
         return token;
@@ -2605,7 +3052,7 @@ var Type1Parser = function type1Parser() {
  * The CFF class takes a Type1 file and wrap it into a
  * 'Compact Font Format' which itself embed Type2 charstrings.
  */
-var CFFStrings = [
+var CFFStandardStrings = [
   '.notdef', 'space', 'exclam', 'quotedbl', 'numbersign', 'dollar', 'percent',
   'ampersand', 'quoteright', 'parenleft', 'parenright', 'asterisk', 'plus',
   'comma', 'hyphen', 'period', 'slash', 'zero', 'one', 'two', 'three', 'four',
@@ -2675,7 +3122,8 @@ var CFFStrings = [
 
 var type1Parser = new Type1Parser();
 
-var CFF = function cffCFF(name, file, properties) {
+// Type1Font is also a CIDFontType0.
+var Type1Font = function Type1Font(name, file, properties) {
   // Get the data block containing glyphs and subrs informations
   var headerBlock = file.getBytes(properties.length1);
   type1Parser.extractFontHeader(headerBlock, properties);
@@ -2695,8 +3143,9 @@ var CFF = function cffCFF(name, file, properties) {
                         subrs, properties);
 };
 
-CFF.prototype = {
-  createCFFIndexHeader: function cff_createCFFIndexHeader(objects, isByte) {
+Type1Font.prototype = {
+  createCFFIndexHeader: function Type1Font_createCFFIndexHeader(objects,
+                                                                isByte) {
     // First 2 bytes contains the number of objects contained into this index
     var count = objects.length;
 
@@ -2732,7 +3181,7 @@ CFF.prototype = {
     return data;
   },
 
-  encodeNumber: function cff_encodeNumber(value) {
+  encodeNumber: function Type1Font_encodeNumber(value) {
     // some of the fonts has ouf-of-range values
     // they are just arithmetic overflows
     // make sanitizer happy
@@ -2750,25 +3199,16 @@ CFF.prototype = {
     }
   },
 
-  getOrderedCharStrings: function cff_getOrderedCharStrings(glyphs,
+  getOrderedCharStrings: function Type1Font_getOrderedCharStrings(glyphs,
                                                             properties) {
     var charstrings = [];
-    var reverseMapping = {};
-    var encoding = properties.baseEncoding;
     var i, length, glyphName;
-    for (i = 0, length = encoding.length; i < length; ++i) {
-      glyphName = encoding[i];
-      if (!glyphName || isSpecialUnicode(i))
-        continue;
-      reverseMapping[glyphName] = i;
-    }
-    reverseMapping['.notdef'] = 0;
     var unusedUnicode = kCmapGlyphOffset;
     for (i = 0, length = glyphs.length; i < length; i++) {
       var item = glyphs[i];
       var glyphName = item.glyph;
-      var unicode = glyphName in reverseMapping ?
-        reverseMapping[glyphName] : unusedUnicode++;
+      var unicode = glyphName in GlyphsUnicode ?
+        GlyphsUnicode[glyphName] : unusedUnicode++;
       charstrings.push({
         glyph: glyphName,
         unicode: unicode,
@@ -2785,7 +3225,8 @@ CFF.prototype = {
     return charstrings;
   },
 
-  getType2Charstrings: function cff_getType2Charstrings(type1Charstrings) {
+  getType2Charstrings: function Type1Font_getType2Charstrings(
+                                  type1Charstrings) {
     var type2Charstrings = [];
     var count = type1Charstrings.length;
     for (var i = 0; i < count; i++) {
@@ -2796,7 +3237,7 @@ CFF.prototype = {
     return type2Charstrings;
   },
 
-  getType2Subrs: function cff_getType2Subrs(type1Subrs) {
+  getType2Subrs: function Type1Font_getType2Subrs(type1Subrs) {
     var bias = 0;
     var count = type1Subrs.length;
     if (count < 1240)
@@ -2848,7 +3289,7 @@ CFF.prototype = {
     'hvcurveto': 31
   },
 
-  flattenCharstring: function flattenCharstring(charstring, map) {
+  flattenCharstring: function Type1Font_flattenCharstring(charstring, map) {
     // charstring changes size - can't cache .length in loop
     for (var i = 0; i < charstring.length; i++) {
       var command = charstring[i];
@@ -2875,7 +3316,7 @@ CFF.prototype = {
     return charstring;
   },
 
-  wrap: function wrap(name, glyphs, charstrings, subrs, properties) {
+  wrap: function Type1Font_wrap(name, glyphs, charstrings, subrs, properties) {
     var fields = {
       // major version, minor version, header size, offset size
       'header': '\x01\x00\x04\x04',
@@ -2919,7 +3360,7 @@ CFF.prototype = {
           dict += self.encodeNumber(offset) + '\x11'; // Charstrings
 
           offset = offset + fields.charstrings.length;
-          dict += self.encodeNumber(fields.private.length);
+          dict += self.encodeNumber(fields.privateData.length);
           dict += self.encodeNumber(offset) + '\x12'; // Private
 
           return header + String.fromCharCode(dict.length + 1) + dict;
@@ -2944,7 +3385,7 @@ CFF.prototype = {
 
         var count = glyphs.length;
         for (var i = 0; i < count; i++) {
-          var index = CFFStrings.indexOf(charstrings[i].glyph);
+          var index = CFFStandardStrings.indexOf(charstrings[i].glyph);
           // Some characters like asterikmath && circlecopyrt are
           // missing from the original strings, for the moment let's
           // map them to .notdef and see later if it cause any
@@ -2960,7 +3401,7 @@ CFF.prototype = {
       'charstrings': this.createCFFIndexHeader([[0x8B, 0x0E]].concat(glyphs),
                                                true),
 
-      'private': (function cffWrapPrivate(self) {
+      'privateData': (function cffWrapPrivate(self) {
         var data =
             '\x8b\x14' + // defaultWidth
             '\x8b\x15';  // nominalWidth
@@ -2978,9 +3419,9 @@ CFF.prototype = {
           ExpansionFactor: '\x0c\x18'
         };
         for (var field in fieldMap) {
-          if (!properties.private.hasOwnProperty(field))
+          if (!properties.privateData.hasOwnProperty(field))
             continue;
-          var value = properties.private[field];
+          var value = properties.privateData[field];
 
           if (isArray(value)) {
             data += self.encodeNumber(value[0]);
@@ -3013,106 +3454,31 @@ CFF.prototype = {
   }
 };
 
-var Type2CFF = (function type2CFF() {
-  // TODO: replace parsing code with the Type2Parser in font_utils.js
-  function constructor(file, properties) {
-    var bytes = file.getBytes();
-    this.bytes = bytes;
+var CFFFont = (function CFFFontClosure() {
+  function CFFFont(file, properties) {
     this.properties = properties;
 
-    this.data = this.parse();
+    var parser = new CFFParser(file, properties);
+    var cff = parser.parse();
+    var compiler = new CFFCompiler(cff);
+    this.readExtra(cff);
+    try {
+      this.data = compiler.compile();
+    } catch (e) {
+      warn('Failed to compile font ' + properties.loadedName);
+      // There may have just been an issue with the compiler, set the data
+      // anyway and hope the font loaded.
+      this.data = file;
+    }
   }
 
-  constructor.prototype = {
-    parse: function cff_parse() {
-      var header = this.parseHeader();
-      var properties = this.properties;
-      var nameIndex = this.parseIndex(header.endPos);
-
-      var dictIndex = this.parseIndex(nameIndex.endPos);
-      if (dictIndex.length != 1)
-        error('CFF contains more than 1 font');
-
-      var stringIndex = this.parseIndex(dictIndex.endPos);
-      var gsubrIndex = this.parseIndex(stringIndex.endPos);
-
-      var strings = this.getStrings(stringIndex);
-
-      var baseDict = this.parseDict(dictIndex.get(0).data);
-      var topDict = this.getTopDict(baseDict, strings);
-
-      var bytes = this.bytes;
-
-      var privateDict = {};
-      var privateInfo = topDict.Private;
-      if (privateInfo) {
-        var privOffset = privateInfo[1], privLength = privateInfo[0];
-        var privBytes = bytes.subarray(privOffset, privOffset + privLength);
-        baseDict = this.parseDict(privBytes);
-        privateDict = this.getPrivDict(baseDict, strings);
-      } else {
-        privateDict.defaultWidthX = properties.defaultWidth;
-      }
-
-      var charStrings = this.parseIndex(topDict.CharStrings);
-      var charset = this.parseCharsets(topDict.charset,
-                                       charStrings.length, strings);
-      var encoding = this.parseEncoding(topDict.Encoding, properties,
-                                             strings, charset);
-
-      var charset, encoding;
-      var isCIDFont = properties.subtype == 'CIDFontType0C';
-      if (isCIDFont) {
-        charset = [];
-        charset.length = charStrings.length;
-        encoding = this.parseCidMap(topDict.charset,
-                                    charStrings.length);
-      } else {
-        charset = this.parseCharsets(topDict.charset,
-                                     charStrings.length, strings);
-        encoding = this.parseEncoding(topDict.Encoding, properties,
-                                      strings, charset);
-      }
-
-      // The font sanitizer does not support CFF encoding with a
-      // supplement, since the encoding is not really use to map
-      // between gid to glyph, let's overwrite what is declared in
-      // the top dictionary to let the sanitizer think the font use
-      // StandardEncoding, that's a lie but that's ok.
-      if (encoding.hasSupplement)
-        bytes[topDict.Encoding] &= 0x7F;
-
-      // The CFF specification state that the 'dotsection' command
-      // (12, 0) is deprecated and treated as a no-op, but all Type2
-      // charstrings processors should support them. Unfortunately
-      // the font sanitizer don't. As a workaround the sequence (12, 0)
-      // is replaced by a useless (0, hmoveto).
-      var count = charStrings.length;
-      for (var i = 0; i < count; i++) {
-        var charstring = charStrings.get(i);
-
-        var start = charstring.start;
-        var data = charstring.data;
-        var length = data.length;
-        for (var j = 0; j <= length; j) {
-          var value = data[j++];
-          if (value == 12 && data[j++] == 0) {
-              bytes[start + j - 2] = 139;
-              bytes[start + j - 1] = 22;
-          } else if (value === 28) {
-            j += 2;
-          } else if (value >= 247 && value <= 254) {
-            j++;
-          } else if (value == 255) {
-            j += 4;
-          }
-        }
-      }
-
+  CFFFont.prototype = {
+    readExtra: function CFFFont_readExtra(cff) {
       // charstrings contains info about glyphs (one element per glyph
       // containing mappings for {unicode, width})
-      var charstrings = this.getCharStrings(charset, encoding.encoding,
-                                            privateDict, this.properties);
+      var charset = cff.charset.charset;
+      var encoding = cff.encoding ? cff.encoding.encoding : null;
+      var charstrings = this.getCharStrings(charset, encoding);
 
       // create the mapping between charstring and glyph id
       var glyphIds = [];
@@ -3121,301 +3487,127 @@ var Type2CFF = (function type2CFF() {
 
       this.charstrings = charstrings;
       this.glyphIds = glyphIds;
-
-      var data = [];
-      for (var i = 0, ii = bytes.length; i < ii; ++i)
-        data.push(bytes[i]);
-      return data;
     },
-
-    getCharStrings: function cff_charstrings(charsets, encoding,
-                                             privateDict, properties) {
+    getCharStrings: function CFFFont_getCharStrings(charsets, encoding) {
       var charstrings = [];
       var unicodeUsed = [];
       var unassignedUnicodeItems = [];
+      var inverseEncoding = [];
+      // CID fonts don't have an encoding.
+      if (encoding !== null)
+        for (var charcode in encoding)
+          inverseEncoding[encoding[charcode]] = charcode | 0;
+      else
+        inverseEncoding = charsets;
       for (var i = 0, ii = charsets.length; i < ii; i++) {
         var glyph = charsets[i];
-        var encodingFound = false;
-        for (var charcode in encoding) {
-          if (encoding[charcode] == i) {
-            var code = charcode | 0;
-            charstrings.push({
-              unicode: adaptUnicode(code),
-              code: code,
-              gid: i,
-              glyph: glyph
-            });
-            unicodeUsed[code] = true;
-            encodingFound = true;
-            break;
-          }
-        }
-        if (!encodingFound) {
+        if (glyph == '.notdef')
+          continue;
+
+        var code = inverseEncoding[i];
+        if (!code || isSpecialUnicode(code)) {
           unassignedUnicodeItems.push(i);
+          continue;
         }
+        charstrings.push({
+          unicode: code,
+          code: code,
+          gid: i,
+          glyph: glyph
+        });
+        unicodeUsed[code] = true;
       }
 
-      var nextUnusedUnicode = 0x21;
+      var nextUnusedUnicode = kCmapGlyphOffset;
       for (var j = 0, jj = unassignedUnicodeItems.length; j < jj; ++j) {
         var i = unassignedUnicodeItems[j];
         // giving unicode value anyway
-        while (unicodeUsed[nextUnusedUnicode])
+        while (nextUnusedUnicode in unicodeUsed)
           nextUnusedUnicode++;
-        var code = nextUnusedUnicode++;
+        var unicode = nextUnusedUnicode++;
         charstrings.push({
-          unicode: adaptUnicode(code),
-          code: code,
+          unicode: unicode,
+          code: inverseEncoding[i] || 0,
           gid: i,
           glyph: charsets[i]
         });
       }
 
       // sort the array by the unicode value (again)
-      charstrings.sort(function type2CFFGetCharStringsSort(a, b) {
+      charstrings.sort(function getCharStringsSort(a, b) {
         return a.unicode - b.unicode;
       });
       return charstrings;
-    },
+    }
+  };
 
-    parseEncoding: function cff_parseencoding(pos, properties, strings,
-                                              charset) {
-      var encoding = {};
-      var bytes = this.bytes;
-      var result = {
-        encoding: encoding,
-        hasSupplement: false
-      };
+  return CFFFont;
+})();
 
-      function readSupplement() {
-        var supplementsCount = bytes[pos++];
-        for (var i = 0; i < supplementsCount; i++) {
-          var code = bytes[pos++];
-          var sid = (bytes[pos++] << 8) + (bytes[pos++] & 0xff);
-          encoding[code] = properties.differences.indexOf(strings[sid]);
-        }
-      }
+var CFFParser = (function CFFParserClosure() {
+  function CFFParser(file, properties) {
+    this.bytes = file.getBytes();
+    this.properties = properties;
+  }
+  CFFParser.prototype = {
+    parse: function CFFParser_parse() {
+      var properties = this.properties;
+      var cff = new CFF();
+      this.cff = cff;
 
-      if (pos == 0 || pos == 1) {
-        var gid = 1;
-        var baseEncoding = pos ? Encodings.ExpertEncoding :
-                                 Encodings.StandardEncoding;
-        for (var i = 0, ii = charset.length; i < ii; i++) {
-          var index = baseEncoding.indexOf(charset[i]);
-          if (index != -1)
-            encoding[index] = gid++;
+      // The first five sections must be in order, all the others are reached
+      // via offsets contained in one of the below.
+      var header = this.parseHeader();
+      var nameIndex = this.parseIndex(header.endPos);
+      var topDictIndex = this.parseIndex(nameIndex.endPos);
+      var stringIndex = this.parseIndex(topDictIndex.endPos);
+      var globalSubrIndex = this.parseIndex(stringIndex.endPos);
+
+      var topDictParsed = this.parseDict(topDictIndex.obj.get(0));
+      var topDict = this.createDict(CFFTopDict, topDictParsed, cff.strings);
+
+      cff.header = header.obj;
+      cff.names = this.parseNameIndex(nameIndex.obj);
+      cff.strings = this.parseStringIndex(stringIndex.obj);
+      cff.topDict = topDict;
+      cff.globalSubrIndex = globalSubrIndex.obj;
+
+      this.parsePrivateDict(cff.topDict);
+
+      cff.isCIDFont = topDict.hasName('ROS');
+
+      var charStringOffset = topDict.getByName('CharStrings');
+      cff.charStrings = this.parseCharStrings(charStringOffset);
+
+      var charset, encoding;
+      if (cff.isCIDFont) {
+        var fdArrayIndex = this.parseIndex(topDict.getByName('FDArray')).obj;
+        for (var i = 0, ii = fdArrayIndex.count; i < ii; ++i) {
+          var dictRaw = fdArrayIndex.get(i);
+          var fontDict = this.createDict(CFFTopDict, this.parseDict(dictRaw),
+                                         cff.strings);
+          this.parsePrivateDict(fontDict);
+          cff.fdArray.push(fontDict);
         }
+        // cid fonts don't have an encoding
+        encoding = null;
+        charset = this.parseCharsets(topDict.getByName('charset'),
+                                     cff.charStrings.count, cff.strings, true);
+        cff.fdSelect = this.parseFDSelect(topDict.getByName('FDSelect'),
+                                             cff.charStrings.count);
       } else {
-        var format = bytes[pos++];
-        switch (format & 0x7f) {
-          case 0:
-            var glyphsCount = bytes[pos++];
-            for (var i = 1; i <= glyphsCount; i++)
-              encoding[bytes[pos++]] = i;
-            break;
-
-          case 1:
-            var rangesCount = bytes[pos++];
-            var gid = 1;
-            for (var i = 0; i < rangesCount; i++) {
-              var start = bytes[pos++];
-              var left = bytes[pos++];
-              for (var j = start; j <= start + left; j++)
-                encoding[j] = gid++;
-            }
-            break;
-
-          default:
-            error('Unknow encoding format: ' + format + ' in CFF');
-            break;
-        }
-        if (format & 0x80) {
-          readSupplement();
-          result.hasSupplement = true;
-        }
-      }
-      return result;
-    },
-
-    parseCharsets: function cff_parsecharsets(pos, length, strings) {
-      if (pos == 0) {
-        return ISOAdobeCharset.slice();
-      } else if (pos == 1) {
-        return ExpertCharset.slice();
-      } else if (pos == 2) {
-        return ExpertSubsetCharset.slice();
+        charset = this.parseCharsets(topDict.getByName('charset'),
+                                     cff.charStrings.count, cff.strings, false);
+        encoding = this.parseEncoding(topDict.getByName('Encoding'),
+                                      properties,
+                                      cff.strings, charset.charset);
       }
+      cff.charset = charset;
+      cff.encoding = encoding;
 
-      var bytes = this.bytes;
-      var format = bytes[pos++];
-      var charset = ['.notdef'];
-
-      // subtract 1 for the .notdef glyph
-      length -= 1;
-
-      switch (format) {
-        case 0:
-          for (var i = 0; i < length; i++) {
-            var sid = (bytes[pos++] << 8) | bytes[pos++];
-            charset.push(strings[sid]);
-          }
-          break;
-        case 1:
-          while (charset.length <= length) {
-            var sid = (bytes[pos++] << 8) | bytes[pos++];
-            var count = bytes[pos++];
-            for (var i = 0; i <= count; i++)
-              charset.push(strings[sid++]);
-          }
-          break;
-        case 2:
-          while (charset.length <= length) {
-            var sid = (bytes[pos++] << 8) | bytes[pos++];
-            var count = (bytes[pos++] << 8) | bytes[pos++];
-            for (var i = 0; i <= count; i++)
-              charset.push(strings[sid++]);
-          }
-          break;
-        default:
-          error('Unknown charset format');
-      }
-      return charset;
+      return cff;
     },
-
-    parseCidMap: function cff_parsecharsets(pos, length) {
-      var bytes = this.bytes;
-      var format = bytes[pos++];
-
-      var encoding = {};
-      var map = {encoding: encoding};
-
-      encoding[0] = 0;
-
-      var gid = 1;
-      switch (format) {
-        case 0:
-          while (gid < length) {
-            var cid = (bytes[pos++] << 8) | bytes[pos++];
-            encoding[cid] = gid++;
-          }
-          break;
-        case 1:
-          while (gid < length) {
-            var cid = (bytes[pos++] << 8) | bytes[pos++];
-            var count = bytes[pos++];
-            for (var i = 0; i <= count; i++)
-              encoding[cid++] = gid++;
-          }
-          break;
-        case 2:
-          while (gid < length) {
-            var cid = (bytes[pos++] << 8) | bytes[pos++];
-            var count = (bytes[pos++] << 8) | bytes[pos++];
-            for (var i = 0; i <= count; i++)
-              encoding[cid++] = gid++;
-          }
-          break;
-        default:
-          error('Unknown charset format');
-      }
-      return map;
-    },
-
-    getPrivDict: function cff_getprivdict(baseDict, strings) {
-      var dict = {};
-
-      // default values
-      dict['defaultWidthX'] = 0;
-      dict['nominalWidthX'] = 0;
-
-      for (var i = 0, ii = baseDict.length; i < ii; ++i) {
-        var pair = baseDict[i];
-        var key = pair[0];
-        var value = pair[1];
-        switch (key) {
-          case 20:
-            dict['defaultWidthX'] = value[0];
-          case 21:
-            dict['nominalWidthX'] = value[0];
-          default:
-            TODO('interpret top dict key: ' + key);
-        }
-      }
-      return dict;
-    },
-    getTopDict: function cff_gettopdict(baseDict, strings) {
-      var dict = {};
-
-      // default values
-      dict['Encoding'] = 0;
-      dict['charset'] = 0;
-
-      for (var i = 0, ii = baseDict.length; i < ii; ++i) {
-        var pair = baseDict[i];
-        var key = pair[0];
-        var value = pair[1];
-        switch (key) {
-          case 1:
-            dict['Notice'] = strings[value[0]];
-            break;
-          case 4:
-            dict['Weight'] = strings[value[0]];
-            break;
-          case 3094:
-            dict['BaseFontName'] = strings[value[0]];
-            break;
-          case 5:
-            dict['FontBBox'] = value;
-            break;
-          case 13:
-            dict['UniqueID'] = value[0];
-            break;
-          case 15:
-            dict['charset'] = value[0];
-            break;
-          case 16:
-            dict['Encoding'] = value[0];
-            break;
-          case 17:
-            dict['CharStrings'] = value[0];
-            break;
-          case 18:
-            dict['Private'] = value;
-            break;
-          case 3102:
-          case 3103:
-          case 3104:
-          case 3105:
-          case 3106:
-          case 3107:
-          case 3108:
-          case 3109:
-          case 3110:
-            dict['cidOperatorPresent'] = true;
-            break;
-          default:
-            TODO('interpret top dict key');
-        }
-      }
-      return dict;
-    },
-    getStrings: function cff_getStrings(stringIndex) {
-      function bytesToString(bytesArray) {
-        var str = '';
-        for (var i = 0, ii = bytesArray.length; i < ii; i++)
-          str += String.fromCharCode(bytesArray[i]);
-        return str;
-      }
-
-      var stringArray = [];
-      for (var i = 0, ii = CFFStrings.length; i < ii; i++)
-        stringArray.push(CFFStrings[i]);
-
-      for (var i = 0, ii = stringIndex.length; i < ii; i++)
-        stringArray.push(bytesToString(stringIndex.get(i).data));
-
-      return stringArray;
-    },
-    parseHeader: function cff_parseHeader() {
+    parseHeader: function CFFParser_parseHeader() {
       var bytes = this.bytes;
       var offset = 0;
 
@@ -3423,17 +3615,18 @@ var Type2CFF = (function type2CFF() {
         ++offset;
 
       if (offset != 0) {
-        warning('cff data is shifted');
+        warn('cff data is shifted');
         bytes = bytes.subarray(offset);
         this.bytes = bytes;
       }
-
-      return {
-        endPos: bytes[2],
-        offsetSize: bytes[3]
-      };
+      var major = bytes[0];
+      var minor = bytes[1];
+      var hdrSize = bytes[2];
+      var offSize = bytes[3];
+      var header = new CFFHeader(major, minor, hdrSize, offSize);
+      return {obj: header, endPos: hdrSize};
     },
-    parseDict: function cff_parseDict(dict) {
+    parseDict: function CFFParser_parseDict(dict) {
       var pos = 0;
 
       function parseOperand() {
@@ -3450,11 +3643,11 @@ var Type2CFF = (function type2CFF() {
           value = (value << 8) | dict[pos++];
           value = (value << 8) | dict[pos++];
           return value;
-        } else if (value <= 246) {
+        } else if (value >= 32 && value <= 246) {
           return value - 139;
-        } else if (value <= 250) {
+        } else if (value >= 247 && value <= 250) {
           return ((value - 247) * 256) + dict[pos++] + 108;
-        } else if (value <= 254) {
+        } else if (value >= 251 && value <= 254) {
           return -((value - 251) * 256) - dict[pos++] - 108;
         } else {
           error('255 is not a valid DICT command');
@@ -3492,27 +3685,8 @@ var Type2CFF = (function type2CFF() {
       while (pos < end) {
         var b = dict[pos];
         if (b <= 21) {
-          if (b === 12) {
-            ++pos;
-            var op = dict[pos];
-            if ((op > 14 && op < 17) ||
-                (op > 23 && op < 30) || op > 38) {
-              warn('Invalid CFF dictionary key: ' + op);
-              // trying to replace it with initialRandomSeed
-              // to pass sanitizer
-              dict[pos] = 19;
-            }
-            var b = (b << 8) | op;
-          }
-          if (!operands.length && b == 8 &&
-              dict[pos + 1] == 9) {
-            // no operands for FamilyBlues, removing the key
-            // and next one is FamilyOtherBlues - skipping them
-            // also replacing FamilyBlues to pass sanitizer
-            dict[pos] = 139;
-            pos += 2;
-            continue;
-          }
+          if (b === 12)
+            b = (b << 8) | dict[++pos];
           entries.push([b, operands]);
           operands = [];
           ++pos;
@@ -3522,10 +3696,12 @@ var Type2CFF = (function type2CFF() {
       }
       return entries;
     },
-    parseIndex: function cff_parseIndex(pos) {
+    parseIndex: function CFFParser_parseIndex(pos) {
+      var cffIndex = new CFFIndex();
       var bytes = this.bytes;
-      var count = bytes[pos++] << 8 | bytes[pos++];
+      var count = (bytes[pos++] << 8) | bytes[pos++];
       var offsets = [];
+      var start = pos;
       var end = pos;
 
       if (count != 0) {
@@ -3543,26 +3719,947 @@ var Type2CFF = (function type2CFF() {
         }
         end = offsets[count];
       }
+      for (var i = 0, ii = offsets.length - 1; i < ii; ++i) {
+        var offsetStart = offsets[i];
+        var offsetEnd = offsets[i + 1];
+        cffIndex.add(bytes.subarray(offsetStart, offsetEnd));
+      }
+      return {obj: cffIndex, endPos: end};
+    },
+    parseNameIndex: function CFFParser_parseNameIndex(index) {
+      var names = [];
+      for (var i = 0, ii = index.count; i < ii; ++i) {
+        var name = index.get(i);
+        // OTS doesn't allow names to be over 127 characters.
+        var length = Math.min(name.length, 127);
+        var data = [];
+        // OTS also only permits certain characters in the name.
+        for (var j = 0; j < length; ++j) {
+          var c = name[j];
+          if (j === 0 && c === 0) {
+            data[j] = c;
+            continue;
+          }
+          if ((c < 33 || c > 126) || c === 91 /* [ */ || c === 93 /* ] */ ||
+              c === 40 /* ( */ || c === 41 /* ) */ || c === 123 /* { */ ||
+              c === 125 /* } */ || c === 60 /* < */ || c === 62 /* > */ ||
+              c === 47 /* / */ || c === 37 /* % */) {
+            data[j] = 95;
+            continue;
+          }
+          data[j] = c;
+        }
+        names.push(String.fromCharCode.apply(null, data));
+      }
+      return names;
+    },
+    parseStringIndex: function CFFParser_parseStringIndex(index) {
+      var strings = new CFFStrings();
+      for (var i = 0, ii = index.count; i < ii; ++i) {
+        var data = index.get(i);
+        strings.add(String.fromCharCode.apply(null, data));
+      }
+      return strings;
+    },
+    createDict: function CFFParser_createDict(type, dict, strings) {
+      var cffDict = new type(strings);
+      var types = cffDict.types;
+
+      for (var i = 0, ii = dict.length; i < ii; ++i) {
+        var pair = dict[i];
+        var key = pair[0];
+        var value = pair[1];
+        cffDict.setByKey(key, value);
+      }
+      return cffDict;
+    },
+    parseCharStrings: function CFFParser_parseCharStrings(charStringOffset) {
+      var charStrings = this.parseIndex(charStringOffset).obj;
+      // The CFF specification state that the 'dotsection' command
+      // (12, 0) is deprecated and treated as a no-op, but all Type2
+      // charstrings processors should support them. Unfortunately
+      // the font sanitizer don't. As a workaround the sequence (12, 0)
+      // is replaced by a useless (0, hmoveto).
+      var count = charStrings.count;
+      for (var i = 0; i < count; i++) {
+        var charstring = charStrings.get(i);
+
+        var data = charstring;
+        var length = data.length;
+        for (var j = 0; j <= length; j) {
+          var value = data[j++];
+          if (value == 12 && data[j++] == 0) {
+              data[j - 2] = 139;
+              data[j - 1] = 22;
+          } else if (value === 28) {
+            j += 2;
+          } else if (value >= 247 && value <= 254) {
+            j++;
+          } else if (value == 255) {
+            j += 4;
+          }
+        }
+      }
+      return charStrings;
+    },
+    parsePrivateDict: function CFFParser_parsePrivateDict(parentDict) {
+      // no private dict, do nothing
+      if (!parentDict.hasName('Private'))
+        return;
+      var privateOffset = parentDict.getByName('Private');
+      // make sure the params are formatted correctly
+      if (!isArray(privateOffset) || privateOffset.length !== 2) {
+        parentDict.removeByName('Private');
+        return;
+      }
+      var size = privateOffset[0];
+      var offset = privateOffset[1];
+      // remove empty dicts or ones that refer to invalid location
+      if (size === 0 || offset >= this.bytes.length) {
+        parentDict.removeByName('Private');
+        return;
+      }
+
+      var privateDictEnd = offset + size;
+      var dictData = this.bytes.subarray(offset, privateDictEnd);
+      var dict = this.parseDict(dictData);
+      var privateDict = this.createDict(CFFPrivateDict, dict,
+                                        parentDict.strings);
+      parentDict.privateDict = privateDict;
+
+      // Parse the Subrs index also since it's relative to the private dict.
+      if (!privateDict.getByName('Subrs'))
+        return;
+      var subrsOffset = privateDict.getByName('Subrs');
+      var relativeOffset = offset + subrsOffset;
+      // Validate the offset.
+      if (subrsOffset === 0 || relativeOffset >= this.bytes.length) {
+        privateDict.removeByName('Subrs');
+        return;
+      }
+      var subrsIndex = this.parseIndex(relativeOffset);
+      privateDict.subrsIndex = subrsIndex.obj;
+    },
+    parseCharsets: function CFFParser_parseCharsets(pos, length, strings, cid) {
+      if (pos == 0) {
+        return new CFFCharset(true, CFFCharsetPredefinedTypes.ISO_ADOBE,
+                              ISOAdobeCharset);
+      } else if (pos == 1) {
+        return new CFFCharset(true, CFFCharsetPredefinedTypes.EXPERT,
+                              ExpertCharset);
+      } else if (pos == 2) {
+        return new CFFCharset(true, CFFCharsetPredefinedTypes.EXPERT_SUBSET,
+                              ExpertSubsetCharset);
+      }
+
+      var bytes = this.bytes;
+      var start = pos;
+      var format = bytes[pos++];
+      var charset = ['.notdef'];
 
+      // subtract 1 for the .notdef glyph
+      length -= 1;
+
+      switch (format) {
+        case 0:
+          for (var i = 0; i < length; i++) {
+            var id = (bytes[pos++] << 8) | bytes[pos++];
+            charset.push(cid ? id : strings.get(id));
+          }
+          break;
+        case 1:
+          while (charset.length <= length) {
+            var id = (bytes[pos++] << 8) | bytes[pos++];
+            var count = bytes[pos++];
+            for (var i = 0; i <= count; i++)
+              charset.push(cid ? id++ : strings.get(id++));
+          }
+          break;
+        case 2:
+          while (charset.length <= length) {
+            var id = (bytes[pos++] << 8) | bytes[pos++];
+            var count = (bytes[pos++] << 8) | bytes[pos++];
+            for (var i = 0; i <= count; i++)
+              charset.push(cid ? id++ : strings.get(id++));
+          }
+          break;
+        default:
+          error('Unknown charset format');
+      }
+      // Raw won't be needed if we actually compile the charset.
+      var end = pos;
+      var raw = bytes.subarray(start, end);
+
+      return new CFFCharset(false, format, charset, raw);
+    },
+    parseEncoding: function CFFParser_parseEncoding(pos,
+                                                    properties,
+                                                    strings,
+                                                    charset) {
+      var encoding = {};
+      var bytes = this.bytes;
+      var predefined = false;
+      var hasSupplement = false;
+      var format;
+      var raw = null;
+
+      function readSupplement() {
+        var supplementsCount = bytes[pos++];
+        for (var i = 0; i < supplementsCount; i++) {
+          var code = bytes[pos++];
+          var sid = (bytes[pos++] << 8) + (bytes[pos++] & 0xff);
+          encoding[code] = properties.differences.indexOf(strings.get(sid));
+        }
+      }
+
+      if (pos == 0 || pos == 1) {
+        predefined = true;
+        format = pos;
+        var gid = 1;
+        var baseEncoding = pos ? Encodings.ExpertEncoding :
+                                 Encodings.StandardEncoding;
+        for (var i = 0, ii = charset.length; i < ii; i++) {
+          var index = baseEncoding.indexOf(charset[i]);
+          if (index != -1)
+            encoding[index] = gid++;
+        }
+      } else {
+        var dataStart = pos;
+        var format = bytes[pos++];
+        switch (format & 0x7f) {
+          case 0:
+            var glyphsCount = bytes[pos++];
+            for (var i = 1; i <= glyphsCount; i++)
+              encoding[bytes[pos++]] = i;
+            break;
+
+          case 1:
+            var rangesCount = bytes[pos++];
+            var gid = 1;
+            for (var i = 0; i < rangesCount; i++) {
+              var start = bytes[pos++];
+              var left = bytes[pos++];
+              for (var j = start; j <= start + left; j++)
+                encoding[j] = gid++;
+            }
+            break;
+
+          default:
+            error('Unknow encoding format: ' + format + ' in CFF');
+            break;
+        }
+        var dataEnd = pos;
+        if (format & 0x80) {
+          // The font sanitizer does not support CFF encoding with a
+          // supplement, since the encoding is not really used to map
+          // between gid to glyph, let's overwrite what is declared in
+          // the top dictionary to let the sanitizer think the font use
+          // StandardEncoding, that's a lie but that's ok.
+          bytes[dataStart] &= 0x7f;
+          readSupplement();
+          hasSupplement = true;
+        }
+        raw = bytes.subarray(dataStart, dataEnd);
+      }
+      format = format & 0x7f;
+      return new CFFEncoding(predefined, format, encoding, raw);
+    },
+    parseFDSelect: function CFFParser_parseFDSelect(pos, length) {
+      var start = pos;
+      var bytes = this.bytes;
+      var format = bytes[pos++];
+      var fdSelect = [];
+      switch (format) {
+        case 0:
+          for (var i = 0; i < length; ++i) {
+            var id = bytes[pos++];
+            fdSelect.push(id);
+          }
+          break;
+        case 3:
+          var rangesCount = (bytes[pos++] << 8) | bytes[pos++];
+          for (var i = 0; i < rangesCount; ++i) {
+            var first = (bytes[pos++] << 8) | bytes[pos++];
+            var fdIndex = bytes[pos++];
+            var next = (bytes[pos] << 8) | bytes[pos + 1];
+            for (var j = first; j < next; ++j)
+              fdSelect.push(fdIndex);
+          }
+          // Advance past the sentinel(next).
+          pos += 2;
+          break;
+        default:
+          error('Unknown fdselect format ' + format);
+          break;
+      }
+      var end = pos;
+      return new CFFFDSelect(fdSelect, bytes.subarray(start, end));
+    }
+  };
+  return CFFParser;
+})();
+
+// Compact Font Format
+var CFF = (function CFFClosure() {
+  function CFF() {
+    this.header = null;
+    this.names = [];
+    this.topDict = null;
+    this.strings = new CFFStrings();
+    this.globalSubrIndex = null;
+
+    // The following could really be per font, but since we only have one font
+    // store them here.
+    this.encoding = null;
+    this.charset = null;
+    this.charStrings = null;
+    this.fdArray = [];
+    this.fdSelect = null;
+
+    this.isCIDFont = false;
+  }
+  return CFF;
+})();
+
+var CFFHeader = (function CFFHeaderClosure() {
+  function CFFHeader(major, minor, hdrSize, offSize) {
+    this.major = major;
+    this.minor = minor;
+    this.hdrSize = hdrSize;
+    this.offSize = offSize;
+  }
+  return CFFHeader;
+})();
+
+var CFFStrings = (function CFFStringsClosure() {
+  function CFFStrings() {
+    this.strings = [];
+  }
+  CFFStrings.prototype = {
+    get: function CFFStrings_get(index) {
+      if (index >= 0 && index <= 390)
+        return CFFStandardStrings[index];
+      if (index - 391 <= this.strings.length)
+        return this.strings[index - 391];
+      return CFFStandardStrings[0];
+    },
+    add: function CFFStrings_add(value) {
+      this.strings.push(value);
+    },
+    get count() {
+      return this.strings.length;
+    }
+  };
+  return CFFStrings;
+})();
+
+var CFFIndex = (function CFFIndexClosure() {
+  function CFFIndex() {
+    this.objects = [];
+    this.length = 0;
+  }
+  CFFIndex.prototype = {
+    add: function CFFIndex_add(data) {
+      this.length += data.length;
+      this.objects.push(data);
+    },
+    get: function CFFIndex_get(index) {
+      return this.objects[index];
+    },
+    get count() {
+      return this.objects.length;
+    }
+  };
+  return CFFIndex;
+})();
+
+var CFFDict = (function CFFDictClosure() {
+  function CFFDict(tables, strings) {
+    this.keyToNameMap = tables.keyToNameMap;
+    this.nameToKeyMap = tables.nameToKeyMap;
+    this.defaults = tables.defaults;
+    this.types = tables.types;
+    this.opcodes = tables.opcodes;
+    this.order = tables.order;
+    this.strings = strings;
+    this.values = {};
+  }
+  CFFDict.prototype = {
+    // value should always be an array
+    setByKey: function CFFDict_setByKey(key, value) {
+      if (!(key in this.keyToNameMap))
+        return false;
+      // ignore empty values
+      if (value.length === 0)
+        return true;
+      var type = this.types[key];
+      // remove the array wrapping these types of values
+      if (type === 'num' || type === 'sid' || type === 'offset')
+        value = value[0];
+      this.values[key] = value;
+      return true;
+    },
+    hasName: function CFFDict_hasName(name) {
+      return this.nameToKeyMap[name] in this.values;
+    },
+    getByName: function CFFDict_getByName(name) {
+      if (!(name in this.nameToKeyMap))
+        error('Invalid dictionary name "' + name + '"');
+      var key = this.nameToKeyMap[name];
+      if (!(key in this.values))
+        return this.defaults[key];
+      return this.values[key];
+    },
+    removeByName: function CFFDict_removeByName(name) {
+      delete this.values[this.nameToKeyMap[name]];
+    }
+  };
+  CFFDict.createTables = function CFFDict_createTables(layout) {
+    var tables = {
+      keyToNameMap: {},
+      nameToKeyMap: {},
+      defaults: {},
+      types: {},
+      opcodes: {},
+      order: []
+    };
+    for (var i = 0, ii = layout.length; i < ii; ++i) {
+      var entry = layout[i];
+      var key = isArray(entry[0]) ? (entry[0][0] << 8) + entry[0][1] : entry[0];
+      tables.keyToNameMap[key] = entry[1];
+      tables.nameToKeyMap[entry[1]] = key;
+      tables.types[key] = entry[2];
+      tables.defaults[key] = entry[3];
+      tables.opcodes[key] = isArray(entry[0]) ? entry[0] : [entry[0]];
+      tables.order.push(key);
+    }
+    return tables;
+  };
+  return CFFDict;
+})();
+
+var CFFTopDict = (function CFFTopDictClosure() {
+  var layout = [
+    [[12, 30], 'ROS', ['sid', 'sid', 'num'], null],
+    [[12, 20], 'SyntheticBase', 'num', null],
+    [0, 'version', 'sid', null],
+    [1, 'Notice', 'sid', null],
+    [[12, 0], 'Copyright', 'sid', null],
+    [2, 'FullName', 'sid', null],
+    [3, 'FamilyName', 'sid', null],
+    [4, 'Weight', 'sid', null],
+    [[12, 1], 'isFixedPitch', 'num', 0],
+    [[12, 2], 'ItalicAngle', 'num', 0],
+    [[12, 3], 'UnderlinePosition', 'num', -100],
+    [[12, 4], 'UnderlineThickness', 'num', 50],
+    [[12, 5], 'PaintType', 'num', 0],
+    [[12, 6], 'CharstringType', 'num', 2],
+    [[12, 7], 'FontMatrix', ['num', 'num', 'num', 'num', 'num', 'num'],
+                            [.001, 0, 0, .001, 0, 0]],
+    [13, 'UniqueID', 'num', null],
+    [5, 'FontBBox', ['num', 'num', 'num', 'num'], [0, 0, 0, 0]],
+    [[12, 8], 'StrokeWidth', 'num', 0],
+    [14, 'XUID', 'array', null],
+    [15, 'charset', 'offset', 0],
+    [16, 'Encoding', 'offset', 0],
+    [17, 'CharStrings', 'offset', 0],
+    [18, 'Private', ['offset', 'offset'], null],
+    [[12, 21], 'PostScript', 'sid', null],
+    [[12, 22], 'BaseFontName', 'sid', null],
+    [[12, 23], 'BaseFontBlend', 'delta', null],
+    [[12, 31], 'CIDFontVersion', 'num', 0],
+    [[12, 32], 'CIDFontRevision', 'num', 0],
+    [[12, 33], 'CIDFontType', 'num', 0],
+    [[12, 34], 'CIDCount', 'num', 8720],
+    [[12, 35], 'UIDBase', 'num', null],
+    [[12, 36], 'FDArray', 'offset', null],
+    [[12, 37], 'FDSelect', 'offset', null],
+    [[12, 38], 'FontName', 'sid', null]];
+  var tables = null;
+  function CFFTopDict(strings) {
+    if (tables === null)
+      tables = CFFDict.createTables(layout);
+    CFFDict.call(this, tables, strings);
+    this.privateDict = null;
+  }
+  CFFTopDict.prototype = Object.create(CFFDict.prototype);
+  return CFFTopDict;
+})();
+
+var CFFPrivateDict = (function CFFPrivateDictClosure() {
+  var layout = [
+    [6, 'BlueValues', 'delta', null],
+    [7, 'OtherBlues', 'delta', null],
+    [8, 'FamilyBlues', 'delta', null],
+    [9, 'FamilyOtherBlues', 'delta', null],
+    [[12, 9], 'BlueScale', 'num', 0.039625],
+    [[12, 10], 'BlueShift', 'num', 7],
+    [[12, 11], 'BlueFuzz', 'num', 1],
+    [10, 'StdHW', 'num', null],
+    [11, 'StdVW', 'num', null],
+    [[12, 12], 'StemSnapH', 'delta', null],
+    [[12, 13], 'StemSnapV', 'delta', null],
+    [[12, 14], 'ForceBold', 'num', 0],
+    [[12, 17], 'LanguageGroup', 'num', 0],
+    [[12, 18], 'ExpansionFactor', 'num', 0.06],
+    [[12, 19], 'initialRandomSeed', 'num', 0],
+    [19, 'Subrs', 'offset', null],
+    [20, 'defaultWidthX', 'num', 0],
+    [21, 'nominalWidthX', 'num', 0]
+  ];
+  var tables = null;
+  function CFFPrivateDict(strings) {
+    if (tables === null)
+      tables = CFFDict.createTables(layout);
+    CFFDict.call(this, tables, strings);
+    this.subrsIndex = null;
+  }
+  CFFPrivateDict.prototype = Object.create(CFFDict.prototype);
+  return CFFPrivateDict;
+})();
+
+var CFFCharsetPredefinedTypes = {
+  ISO_ADOBE: 0,
+  EXPERT: 1,
+  EXPERT_SUBSET: 2
+};
+var CFFCharsetEmbeddedTypes = {
+  FORMAT0: 0,
+  FORMAT1: 1,
+  FORMAT2: 2
+};
+var CFFCharset = (function CFFCharsetClosure() {
+  function CFFCharset(predefined, format, charset, raw) {
+    this.predefined = predefined;
+    this.format = format;
+    this.charset = charset;
+    this.raw = raw;
+  }
+  return CFFCharset;
+})();
+
+var CFFEncodingPredefinedTypes = {
+  STANDARD: 0,
+  EXPERT: 1
+};
+var CFFCharsetEmbeddedTypes = {
+  FORMAT0: 0,
+  FORMAT1: 1
+};
+var CFFEncoding = (function CFFEncodingClosure() {
+  function CFFEncoding(predefined, format, encoding, raw) {
+    this.predefined = predefined;
+    this.format = format;
+    this.encoding = encoding;
+    this.raw = raw;
+  }
+  return CFFEncoding;
+})();
+
+var CFFFDSelect = (function CFFFDSelectClosure() {
+  function CFFFDSelect(fdSelect, raw) {
+    this.fdSelect = fdSelect;
+    this.raw = raw;
+  }
+  return CFFFDSelect;
+})();
+
+// Helper class to keep track of where an offset is within the data and helps
+// filling in that offset once it's known.
+var CFFOffsetTracker = (function CFFOffsetTrackerClosure() {
+  function CFFOffsetTracker() {
+    this.offsets = {};
+  }
+  CFFOffsetTracker.prototype = {
+    isTracking: function CFFOffsetTracker_isTracking(key) {
+      return key in this.offsets;
+    },
+    track: function CFFOffsetTracker_track(key, location) {
+      if (key in this.offsets)
+        error('Already tracking location of ' + key);
+      this.offsets[key] = location;
+    },
+    offset: function CFFOffsetTracker_offset(value) {
+      for (var key in this.offsets) {
+        this.offsets[key] += value;
+      }
+    },
+    setEntryLocation: function CFFOffsetTracker_setEntryLocation(key,
+                                                                 values,
+                                                                 output) {
+      if (!(key in this.offsets))
+        error('Not tracking location of ' + key);
+      var data = output.data;
+      var dataOffset = this.offsets[key];
+      var size = 5;
+      for (var i = 0, ii = values.length; i < ii; ++i) {
+        var offset0 = i * size + dataOffset;
+        var offset1 = offset0 + 1;
+        var offset2 = offset0 + 2;
+        var offset3 = offset0 + 3;
+        var offset4 = offset0 + 4;
+        // It's easy to screw up offsets so perform this sanity check.
+        if (data[offset0] !== 0x1d || data[offset1] !== 0 ||
+            data[offset2] !== 0 || data[offset3] !== 0 || data[offset4] !== 0)
+          error('writing to an offset that is not empty');
+        var value = values[i];
+        data[offset0] = 0x1d;
+        data[offset1] = (value >> 24) & 0xFF;
+        data[offset2] = (value >> 16) & 0xFF;
+        data[offset3] = (value >> 8) & 0xFF;
+        data[offset4] = value & 0xFF;
+      }
+    }
+  };
+  return CFFOffsetTracker;
+})();
+
+// Takes a CFF and converts it to the binary representation.
+var CFFCompiler = (function CFFCompilerClosure() {
+  function stringToArray(str) {
+    var array = [];
+    for (var i = 0, ii = str.length; i < ii; ++i)
+      array[i] = str.charCodeAt(i);
+
+    return array;
+  };
+  function CFFCompiler(cff) {
+    this.cff = cff;
+  }
+  CFFCompiler.prototype = {
+    compile: function CFFCompiler_compile() {
+      var cff = this.cff;
+      var output = {
+        data: [],
+        length: 0,
+        add: function CFFCompiler_add(data) {
+          this.data = this.data.concat(data);
+          this.length = this.data.length;
+        }
+      };
+
+      // Compile the five entries that must be in order.
+      var header = this.compileHeader(cff.header);
+      output.add(header);
+
+      var nameIndex = this.compileNameIndex(cff.names);
+      output.add(nameIndex);
+
+      var compiled = this.compileTopDicts([cff.topDict], output.length);
+      output.add(compiled.output);
+      var topDictTracker = compiled.trackers[0];
+
+      var stringIndex = this.compileStringIndex(cff.strings.strings);
+      output.add(stringIndex);
+
+      var globalSubrIndex = this.compileIndex(cff.globalSubrIndex);
+      output.add(globalSubrIndex);
+
+      // Now start on the other entries that have no specfic order.
+      if (cff.encoding && cff.topDict.hasName('Encoding')) {
+        if (cff.encoding.predefined) {
+          topDictTracker.setEntryLocation('Encoding', [cff.encoding.format],
+                                          output);
+        } else {
+          var encoding = this.compileEncoding(cff.encoding);
+          topDictTracker.setEntryLocation('Encoding', [output.length], output);
+          output.add(encoding);
+        }
+      }
+
+      if (cff.charset && cff.topDict.hasName('charset')) {
+        if (cff.charset.predefined) {
+          topDictTracker.setEntryLocation('charset', [cff.charset.format],
+                                          output);
+        } else {
+          var charset = this.compileCharset(cff.charset);
+          topDictTracker.setEntryLocation('charset', [output.length], output);
+          output.add(charset);
+        }
+      }
+
+      var charStrings = this.compileCharStrings(cff.charStrings);
+      topDictTracker.setEntryLocation('CharStrings', [output.length], output);
+      output.add(charStrings);
+
+      if (cff.isCIDFont) {
+        // For some reason FDSelect must be in front of FDArray on windows. OSX
+        // and linux don't seem to care.
+        topDictTracker.setEntryLocation('FDSelect', [output.length], output);
+        var fdSelect = this.compileFDSelect(cff.fdSelect.raw);
+        output.add(fdSelect);
+
+        var compiled = this.compileTopDicts(cff.fdArray, output.length);
+        topDictTracker.setEntryLocation('FDArray', [output.length], output);
+        output.add(compiled.output);
+        var fontDictTrackers = compiled.trackers;
+
+        this.compilePrivateDicts(cff.fdArray, fontDictTrackers, output);
+      }
+
+      this.compilePrivateDicts([cff.topDict], [topDictTracker], output);
+
+      return output.data;
+    },
+    encodeNumber: function CFFCompiler_encodeNumber(value) {
+      if (parseFloat(value) == parseInt(value) && !isNaN(value)) // isInt
+        return this.encodeInteger(value);
+      else
+        return this.encodeFloat(value);
+    },
+    encodeFloat: function CFFCompiler_encodeFloat(value) {
+      value = value.toString();
+      // Strip off the any leading zeros.
+      if (value.substr(0, 2) === '0.')
+        value = value.substr(1);
+      else if (value.substr(0, 3) === '-0.')
+        value = '-' + value.substr(2);
+      var nibbles = [];
+      for (var i = 0, ii = value.length; i < ii; ++i) {
+        var a = value.charAt(i), b = value.charAt(i + 1);
+        var nibble;
+        if (a === 'e' && b === '-') {
+          nibble = 0xc;
+          ++i;
+        } else if (a === '.') {
+          nibble = 0xa;
+        } else if (a === 'E') {
+          nibble = 0xb;
+        } else if (a === '-') {
+          nibble = 0xe;
+        } else {
+          nibble = a;
+        }
+        nibbles.push(nibble);
+      }
+      nibbles.push(0xf);
+      if (nibbles.length % 2)
+        nibbles.push(0xf);
+      var out = [30];
+      for (var i = 0, ii = nibbles.length; i < ii; i += 2)
+        out.push(nibbles[i] << 4 | nibbles[i + 1]);
+      return out;
+    },
+    encodeInteger: function CFFCompiler_encodeInteger(value) {
+      var code;
+      if (value >= -107 && value <= 107) {
+        code = [value + 139];
+      } else if (value >= 108 && value <= 1131) {
+        value = [value - 108];
+        code = [(value >> 8) + 247, value & 0xFF];
+      } else if (value >= -1131 && value <= -108) {
+        value = -value - 108;
+        code = [(value >> 8) + 251, value & 0xFF];
+      } else if (value >= -32768 && value <= 32767) {
+        code = [0x1c, (value >> 8) & 0xFF, value & 0xFF];
+      } else {
+        code = [0x1d,
+                (value >> 24) & 0xFF,
+                (value >> 16) & 0xFF,
+                (value >> 8) & 0xFF,
+                 value & 0xFF];
+      }
+      return code;
+    },
+    compileHeader: function CFFCompiler_compileHeader(header) {
+      return [
+        header.major,
+        header.minor,
+        header.hdrSize,
+        header.offSize
+      ];
+    },
+    compileNameIndex: function CFFCompiler_compileNameIndex(names) {
+      var nameIndex = new CFFIndex();
+      for (var i = 0, ii = names.length; i < ii; ++i)
+        nameIndex.add(stringToArray(names[i]));
+      return this.compileIndex(nameIndex);
+    },
+    compileTopDicts: function CFFCompiler_compileTopDicts(dicts, length) {
+      var fontDictTrackers = [];
+      var fdArrayIndex = new CFFIndex();
+      for (var i = 0, ii = dicts.length; i < ii; ++i) {
+        var fontDict = dicts[i];
+        var fontDictTracker = new CFFOffsetTracker();
+        var fontDictData = this.compileDict(fontDict, fontDictTracker);
+        fontDictTrackers.push(fontDictTracker);
+        fdArrayIndex.add(fontDictData);
+        fontDictTracker.offset(length);
+      }
+      fdArrayIndex = this.compileIndex(fdArrayIndex, fontDictTrackers);
       return {
-        get: function index_get(index) {
-          if (index >= count)
-            return null;
-
-          var start = offsets[index];
-          var end = offsets[index + 1];
-          return {
-            start: start,
-            end: end,
-            data: bytes.subarray(start, end)
-          };
-        },
-        length: count,
-        endPos: end
+        trackers: fontDictTrackers,
+        output: fdArrayIndex
       };
+    },
+    compilePrivateDicts: function CFFCompiler_compilePrivateDicts(dicts,
+                                                                  trackers,
+                                                                  output) {
+      for (var i = 0, ii = dicts.length; i < ii; ++i) {
+        var fontDict = dicts[i];
+        if (!fontDict.privateDict || !fontDict.hasName('Private'))
+          continue;
+        var privateDict = fontDict.privateDict;
+        var privateDictTracker = new CFFOffsetTracker();
+        var privateDictData = this.compileDict(privateDict, privateDictTracker);
+
+        privateDictTracker.offset(output.length);
+        trackers[i].setEntryLocation('Private',
+                                     [privateDictData.length, output.length],
+                                     output);
+        output.add(privateDictData);
+
+        if (privateDict.subrsIndex && privateDict.hasName('Subrs')) {
+          var subrs = this.compileIndex(privateDict.subrsIndex);
+          privateDictTracker.setEntryLocation('Subrs', [privateDictData.length],
+                                              output);
+          output.add(subrs);
+        }
+      }
+    },
+    compileDict: function CFFCompiler_compileDict(dict, offsetTracker) {
+      var out = [];
+      // The dictionary keys must be in a certain order.
+      var order = dict.order;
+      for (var i = 0; i < order.length; ++i) {
+        var key = order[i];
+        if (!(key in dict.values))
+          continue;
+        var values = dict.values[key];
+        var types = dict.types[key];
+        if (!isArray(types)) types = [types];
+        if (!isArray(values)) values = [values];
+
+        // Remove any empty dict values.
+        if (values.length === 0)
+          continue;
+
+        for (var j = 0, jj = types.length; j < jj; ++j) {
+          var type = types[j];
+          var value = values[j];
+          switch (type) {
+            case 'num':
+            case 'sid':
+              out = out.concat(this.encodeNumber(value));
+              break;
+            case 'offset':
+              // For offsets we just insert a 32bit integer so we don't have to
+              // deal with figuring out the length of the offset when it gets
+              // replaced later on by the compiler.
+              var name = dict.keyToNameMap[key];
+              // Some offsets have the offset and the length, so just record the
+              // position of the first one.
+              if (!offsetTracker.isTracking(name))
+                offsetTracker.track(name, out.length);
+              out = out.concat([0x1d, 0, 0, 0, 0]);
+              break;
+            case 'array':
+            case 'delta':
+              out = out.concat(this.encodeNumber(value));
+              for (var k = 1, kk = values.length; k < kk; ++k)
+                out = out.concat(this.encodeNumber(values[k]));
+              break;
+            default:
+              error('Unknown data type of ' + type);
+              break;
+          }
+        }
+        out = out.concat(dict.opcodes[key]);
+      }
+      return out;
+    },
+    compileStringIndex: function CFFCompiler_compileStringIndex(strings) {
+      var stringIndex = new CFFIndex();
+      for (var i = 0, ii = strings.length; i < ii; ++i)
+        stringIndex.add(stringToArray(strings[i]));
+      return this.compileIndex(stringIndex);
+    },
+    compileGlobalSubrIndex: function CFFCompiler_compileGlobalSubrIndex() {
+      var globalSubrIndex = this.cff.globalSubrIndex;
+      this.out.writeByteArray(this.compileIndex(globalSubrIndex));
+    },
+    compileCharStrings: function CFFCompiler_compileCharStrings(charStrings) {
+      return this.compileIndex(charStrings);
+    },
+    compileCharset: function CFFCompiler_compileCharset(charset) {
+      return this.compileTypedArray(charset.raw);
+    },
+    compileEncoding: function CFFCompiler_compileEncoding(encoding) {
+      return this.compileTypedArray(encoding.raw);
+    },
+    compileFDSelect: function CFFCompiler_compileFDSelect(fdSelect) {
+      return this.compileTypedArray(fdSelect);
+    },
+    compileTypedArray: function CFFCompiler_compileTypedArray(data) {
+      var out = [];
+      for (var i = 0, ii = data.length; i < ii; ++i)
+        out[i] = data[i];
+      return out;
+    },
+    compileIndex: function CFFCompiler_compileIndex(index, trackers) {
+      trackers = trackers || [];
+      var objects = index.objects;
+      // First 2 bytes contains the number of objects contained into this index
+      var count = objects.length;
+
+      // If there is no object, just create an index. This technically
+      // should just be [0, 0] but OTS has an issue with that.
+      if (count == 0)
+        return [0, 0, 0];
+
+      var data = [(count >> 8) & 0xFF, count & 0xff];
+
+      var lastOffset = 1;
+      for (var i = 0; i < count; ++i)
+        lastOffset += objects[i].length;
+
+      var offsetSize;
+      if (lastOffset < 0x100)
+        offsetSize = 1;
+      else if (lastOffset < 0x10000)
+        offsetSize = 2;
+      else if (lastOffset < 0x1000000)
+        offsetSize = 3;
+      else
+        offsetSize = 4;
+
+      // Next byte contains the offset size use to reference object in the file
+      data.push(offsetSize);
+
+      // Add another offset after this one because we need a new offset
+      var relativeOffset = 1;
+      for (var i = 0; i < count + 1; i++) {
+        if (offsetSize === 1) {
+          data.push(relativeOffset & 0xFF);
+        } else if (offsetSize === 2) {
+          data.push((relativeOffset >> 8) & 0xFF,
+                     relativeOffset & 0xFF);
+        } else if (offsetSize === 3) {
+          data.push((relativeOffset >> 16) & 0xFF,
+                    (relativeOffset >> 8) & 0xFF,
+                     relativeOffset & 0xFF);
+        } else {
+          data.push((relativeOffset >>> 24) & 0xFF,
+                    (relativeOffset >> 16) & 0xFF,
+                    (relativeOffset >> 8) & 0xFF,
+                     relativeOffset & 0xFF);
+        }
+
+        if (objects[i])
+          relativeOffset += objects[i].length;
+      }
+      var offset = data.length;
+
+      for (var i = 0; i < count; i++) {
+        // Notify the tracker where the object will be offset in the data.
+        if (trackers[i])
+          trackers[i].offset(data.length);
+        for (var j = 0, jj = objects[i].length; j < jj; j++)
+          data.push(objects[i][j]);
+      }
+      return data;
     }
   };
-
-  return constructor;
+  return CFFCompiler;
 })();
 
diff --git a/apps/files_pdfviewer/js/pdfjs/src/function.js b/apps/files_pdfviewer/js/pdfjs/src/function.js
old mode 100755
new mode 100644
index ef24736c135468c83352cc5842982fc38d5cc009..2e7ad45e6ea3842a7c4563eb9176542a93f16b71
--- a/apps/files_pdfviewer/js/pdfjs/src/function.js
+++ b/apps/files_pdfviewer/js/pdfjs/src/function.js
@@ -3,14 +3,14 @@
 
 'use strict';
 
-var PDFFunction = (function pdfFunction() {
+var PDFFunction = (function PDFFunctionClosure() {
   var CONSTRUCT_SAMPLED = 0;
   var CONSTRUCT_INTERPOLATED = 2;
   var CONSTRUCT_STICHED = 3;
   var CONSTRUCT_POSTSCRIPT = 4;
 
   return {
-    getSampleArray: function pdfFunctionGetSampleArray(size, outputSize, bps,
+    getSampleArray: function PDFFunction_getSampleArray(size, outputSize, bps,
                                                        str) {
       var length = 1;
       for (var i = 0, ii = size.length; i < ii; i++)
@@ -38,7 +38,7 @@ var PDFFunction = (function pdfFunction() {
       return array;
     },
 
-    getIR: function pdfFunctionGetIR(xref, fn) {
+    getIR: function PDFFunction_getIR(xref, fn) {
       var dict = fn.dict;
       if (!dict)
         dict = fn;
@@ -57,7 +57,7 @@ var PDFFunction = (function pdfFunction() {
       return typeFn.call(this, fn, dict, xref);
     },
 
-    fromIR: function pdfFunctionFromIR(IR) {
+    fromIR: function PDFFunction_fromIR(IR) {
       var type = IR[0];
       switch (type) {
         case CONSTRUCT_SAMPLED:
@@ -72,16 +72,16 @@ var PDFFunction = (function pdfFunction() {
       }
     },
 
-    parse: function pdfFunctionParse(xref, fn) {
+    parse: function PDFFunction_parse(xref, fn) {
       var IR = this.getIR(xref, fn);
       return this.fromIR(IR);
     },
 
-    constructSampled: function pdfFunctionConstructSampled(str, dict) {
+    constructSampled: function PDFFunction_constructSampled(str, dict) {
       function toMultiArray(arr) {
         var inputLength = arr.length;
         var outputLength = arr.length / 2;
-        var out = new Array(outputLength);
+        var out = [];
         var index = 0;
         for (var i = 0; i < inputLength; i += 2) {
           out[index] = [arr[i], arr[i + 1]];
@@ -125,114 +125,104 @@ var PDFFunction = (function pdfFunction() {
       else
         decode = toMultiArray(decode);
 
-      // Precalc the multipliers
-      var inputMul = new Float64Array(inputSize);
-      for (var i = 0; i < inputSize; ++i) {
-        inputMul[i] = (encode[i][1] - encode[i][0]) /
-                  (domain[i][1] - domain[i][0]);
-      }
-
-      var idxMul = new Int32Array(inputSize);
-      idxMul[0] = outputSize;
-      for (i = 1; i < inputSize; ++i) {
-        idxMul[i] = idxMul[i - 1] * size[i - 1];
-      }
-
-      var nSamples = outputSize;
-      for (i = 0; i < inputSize; ++i)
-          nSamples *= size[i];
-
       var samples = this.getSampleArray(size, outputSize, bps, str);
 
       return [
         CONSTRUCT_SAMPLED, inputSize, domain, encode, decode, samples, size,
-        outputSize, bps, range, inputMul, idxMul, nSamples
+        outputSize, Math.pow(2, bps) - 1, range
       ];
     },
 
-    constructSampledFromIR: function pdfFunctionConstructSampledFromIR(IR) {
-      var inputSize = IR[1];
-      var domain = IR[2];
-      var encode = IR[3];
-      var decode = IR[4];
-      var samples = IR[5];
-      var size = IR[6];
-      var outputSize = IR[7];
-      var bps = IR[8];
-      var range = IR[9];
-      var inputMul = IR[10];
-      var idxMul = IR[11];
-      var nSamples = IR[12];
+    constructSampledFromIR: function PDFFunction_constructSampledFromIR(IR) {
+      // See chapter 3, page 109 of the PDF reference
+      function interpolate(x, xmin, xmax, ymin, ymax) {
+        return ymin + ((x - xmin) * ((ymax - ymin) / (xmax - xmin)));
+      }
 
       return function constructSampledFromIRResult(args) {
-        if (inputSize != args.length)
+        // See chapter 3, page 110 of the PDF reference.
+        var m = IR[1];
+        var domain = IR[2];
+        var encode = IR[3];
+        var decode = IR[4];
+        var samples = IR[5];
+        var size = IR[6];
+        var n = IR[7];
+        var mask = IR[8];
+        var range = IR[9];
+
+        if (m != args.length)
           error('Incorrect number of arguments: ' + inputSize + ' != ' +
                 args.length);
-        // Most of the below is a port of Poppler's implementation.
-        // TODO: There's a few other ways to do multilinear interpolation such
-        // as piecewise, which is much faster but an approximation.
-        var out = new Float64Array(outputSize);
-        var x;
-        var e = new Array(inputSize);
-        var efrac0 = new Float64Array(inputSize);
-        var efrac1 = new Float64Array(inputSize);
-        var sBuf = new Float64Array(1 << inputSize);
-        var i, j, k, idx, t;
-
-        // map input values into sample array
-        for (i = 0; i < inputSize; ++i) {
-          x = (args[i] - domain[i][0]) * inputMul[i] + encode[i][0];
-          if (x < 0) {
-            x = 0;
-          } else if (x > size[i] - 1) {
-            x = size[i] - 1;
-          }
-          e[i] = [Math.floor(x), 0];
-          if ((e[i][1] = e[i][0] + 1) >= size[i]) {
-            // this happens if in[i] = domain[i][1]
-            e[i][1] = e[i][0];
-          }
-          efrac1[i] = x - e[i][0];
-          efrac0[i] = 1 - efrac1[i];
-        }
 
-        // for each output, do m-linear interpolation
-        for (i = 0; i < outputSize; ++i) {
-
-          // pull 2^m values out of the sample array
-          for (j = 0; j < (1 << inputSize); ++j) {
-            idx = i;
-            for (k = 0, t = j; k < inputSize; ++k, t >>= 1) {
-              idx += idxMul[k] * (e[k][t & 1]);
-            }
-            if (idx >= 0 && idx < nSamples) {
-              sBuf[j] = samples[idx];
+        var x = args;
+
+        // Building the cube vertices: its part and sample index
+        // http://rjwagner49.com/Mathematics/Interpolation.pdf
+        var cubeVertices = 1 << m;
+        var cubeN = new Float64Array(cubeVertices);
+        var cubeVertex = new Uint32Array(cubeVertices);
+        for (var j = 0; j < cubeVertices; j++)
+          cubeN[j] = 1;
+
+        var k = n, pos = 1;
+        // Map x_i to y_j for 0 <= i < m using the sampled function.
+        for (var i = 0; i < m; ++i) {
+          // x_i' = min(max(x_i, Domain_2i), Domain_2i+1)
+          var domain_2i = domain[i][0];
+          var domain_2i_1 = domain[i][1];
+          var xi = Math.min(Math.max(x[i], domain_2i), domain_2i_1);
+
+          // e_i = Interpolate(x_i', Domain_2i, Domain_2i+1,
+          //                   Encode_2i, Encode_2i+1)
+          var e = interpolate(xi, domain_2i, domain_2i_1,
+                              encode[i][0], encode[i][1]);
+
+          // e_i' = min(max(e_i, 0), Size_i - 1)
+          var size_i = size[i];
+          e = Math.min(Math.max(e, 0), size_i - 1);
+
+          // Adjusting the cube: N and vertex sample index
+          var e0 = e < size_i - 1 ? Math.floor(e) : e - 1; // e1 = e0 + 1;
+          var n0 = e0 + 1 - e; // (e1 - e) / (e1 - e0);
+          var n1 = e - e0; // (e - e0) / (e1 - e0);
+          var offset0 = e0 * k;
+          var offset1 = offset0 + k; // e1 * k
+          for (var j = 0; j < cubeVertices; j++) {
+            if (j & pos) {
+              cubeN[j] *= n1;
+              cubeVertex[j] += offset1;
             } else {
-              sBuf[j] = 0; // TODO Investigate if this is what Adobe does
+              cubeN[j] *= n0;
+              cubeVertex[j] += offset0;
             }
           }
 
-          // do m sets of interpolations
-          for (j = 0, t = (1 << inputSize); j < inputSize; ++j, t >>= 1) {
-            for (k = 0; k < t; k += 2) {
-              sBuf[k >> 1] = efrac0[j] * sBuf[k] + efrac1[j] * sBuf[k + 1];
-            }
-          }
+          k *= size_i;
+          pos <<= 1;
+        }
 
-          // map output value to range
-          out[i] = (sBuf[0] * (decode[i][1] - decode[i][0]) + decode[i][0]);
-          if (out[i] < range[i][0]) {
-            out[i] = range[i][0];
-          } else if (out[i] > range[i][1]) {
-            out[i] = range[i][1];
-          }
+        var y = new Float64Array(n);
+        for (var j = 0; j < n; ++j) {
+          // Sum all cube vertices' samples portions
+          var rj = 0;
+          for (var i = 0; i < cubeVertices; i++)
+            rj += samples[cubeVertex[i] + j] * cubeN[i];
+
+          // r_j' = Interpolate(r_j, 0, 2^BitsPerSample - 1,
+          //                    Decode_2j, Decode_2j+1)
+          rj = interpolate(rj, 0, 1, decode[j][0], decode[j][1]);
+
+          // y_j = min(max(r_j, range_2j), range_2j+1)
+          y[j] = Math.min(Math.max(rj, range[j][0]), range[j][1]);
         }
-        return out;
+
+        return y;
       }
     },
 
-    constructInterpolated:
-    function pdfFunctionConstructInterpolated(str, dict) {
+    constructInterpolated: function PDFFunction_constructInterpolated(str,
+                                                                      dict) {
       var c0 = dict.get('C0') || [0];
       var c1 = dict.get('C1') || [1];
       var n = dict.get('N');
@@ -249,7 +239,7 @@ var PDFFunction = (function pdfFunction() {
     },
 
     constructInterpolatedFromIR:
-    function pdfFunctionconstructInterpolatedFromIR(IR) {
+      function PDFFunction_constructInterpolatedFromIR(IR) {
       var c0 = IR[1];
       var diff = IR[2];
       var n = IR[3];
@@ -268,9 +258,8 @@ var PDFFunction = (function pdfFunction() {
       }
     },
 
-    constructStiched: function pdfFunctionConstructStiched(fn, dict, xref) {
+    constructStiched: function PDFFunction_constructStiched(fn, dict, xref) {
       var domain = dict.get('Domain');
-      var range = dict.get('Range');
 
       if (!domain)
         error('No domain');
@@ -290,7 +279,7 @@ var PDFFunction = (function pdfFunction() {
       return [CONSTRUCT_STICHED, domain, bounds, encode, fns];
     },
 
-    constructStichedFromIR: function pdfFunctionConstructStichedFromIR(IR) {
+    constructStichedFromIR: function PDFFunction_constructStichedFromIR(IR) {
       var domain = IR[1];
       var bounds = IR[2];
       var encode = IR[3];
@@ -336,16 +325,550 @@ var PDFFunction = (function pdfFunction() {
       };
     },
 
-    constructPostScript: function pdfFunctionConstructPostScript() {
-      return [CONSTRUCT_POSTSCRIPT];
+    constructPostScript: function PDFFunction_constructPostScript(fn, dict,
+                                                                  xref) {
+      var domain = dict.get('Domain');
+      var range = dict.get('Range');
+
+      if (!domain)
+        error('No domain.');
+
+      if (!range)
+        error('No range.');
+
+      var lexer = new PostScriptLexer(fn);
+      var parser = new PostScriptParser(lexer);
+      var code = parser.parse();
+
+      return [CONSTRUCT_POSTSCRIPT, domain, range, code];
     },
 
-    constructPostScriptFromIR: function pdfFunctionConstructPostScriptFromIR() {
-      TODO('unhandled type of function');
-      return function constructPostScriptFromIRResult() {
-        return [255, 105, 180];
+    constructPostScriptFromIR: function PDFFunction_constructPostScriptFromIR(
+                                          IR) {
+      var domain = IR[1];
+      var range = IR[2];
+      var code = IR[3];
+      var numOutputs = range.length / 2;
+      var evaluator = new PostScriptEvaluator(code);
+      // Cache the values for a big speed up, the cache size is limited though
+      // since the number of possible values can be huge from a PS function.
+      var cache = new FunctionCache();
+      return function constructPostScriptFromIRResult(args) {
+        var initialStack = [];
+        for (var i = 0, ii = (domain.length / 2); i < ii; ++i) {
+          initialStack.push(args[i]);
+        }
+
+        var key = initialStack.join('_');
+        if (cache.has(key))
+          return cache.get(key);
+
+        var stack = evaluator.execute(initialStack);
+        var transformed = [];
+        for (i = numOutputs - 1; i >= 0; --i) {
+          var out = stack.pop();
+          var rangeIndex = 2 * i;
+          if (out < range[rangeIndex])
+            out = range[rangeIndex];
+          else if (out > range[rangeIndex + 1])
+            out = range[rangeIndex + 1];
+          transformed[i] = out;
+        }
+        cache.set(key, transformed);
+        return transformed;
       };
     }
   };
 })();
 
+var FunctionCache = (function FunctionCacheClosure() {
+  // Of 10 PDF's with type4 functions the maxium number of distinct values seen
+  // was 256. This still may need some tweaking in the future though.
+  var MAX_CACHE_SIZE = 1024;
+  function FunctionCache() {
+    this.cache = {};
+    this.total = 0;
+  }
+  FunctionCache.prototype = {
+    has: function FunctionCache_has(key) {
+      return key in this.cache;
+    },
+    get: function FunctionCache_get(key) {
+      return this.cache[key];
+    },
+    set: function FunctionCache_set(key, value) {
+      if (this.total < MAX_CACHE_SIZE) {
+        this.cache[key] = value;
+        this.total++;
+      }
+    }
+  };
+  return FunctionCache;
+})();
+
+var PostScriptStack = (function PostScriptStackClosure() {
+  var MAX_STACK_SIZE = 100;
+  function PostScriptStack(initialStack) {
+    this.stack = initialStack || [];
+  }
+
+  PostScriptStack.prototype = {
+    push: function PostScriptStack_push(value) {
+      if (this.stack.length >= MAX_STACK_SIZE)
+        error('PostScript function stack overflow.');
+      this.stack.push(value);
+    },
+    pop: function PostScriptStack_pop() {
+      if (this.stack.length <= 0)
+        error('PostScript function stack underflow.');
+      return this.stack.pop();
+    },
+    copy: function PostScriptStack_copy(n) {
+      if (this.stack.length + n >= MAX_STACK_SIZE)
+        error('PostScript function stack overflow.');
+      var stack = this.stack;
+      for (var i = stack.length - n, j = n - 1; j >= 0; j--, i++)
+        stack.push(stack[i]);
+    },
+    index: function PostScriptStack_index(n) {
+      this.push(this.stack[this.stack.length - n - 1]);
+    },
+    // rotate the last n stack elements p times
+    roll: function PostScriptStack_roll(n, p) {
+      var stack = this.stack;
+      var l = stack.length - n;
+      var r = stack.length - 1, c = l + (p - Math.floor(p / n) * n), i, j, t;
+      for (i = l, j = r; i < j; i++, j--) {
+        t = stack[i]; stack[i] = stack[j]; stack[j] = t;
+      }
+      for (i = l, j = c - 1; i < j; i++, j--) {
+        t = stack[i]; stack[i] = stack[j]; stack[j] = t;
+      }
+      for (i = c, j = r; i < j; i++, j--) {
+        t = stack[i]; stack[i] = stack[j]; stack[j] = t;
+      }
+    }
+  };
+  return PostScriptStack;
+})();
+var PostScriptEvaluator = (function PostScriptEvaluatorClosure() {
+  function PostScriptEvaluator(operators, operands) {
+    this.operators = operators;
+    this.operands = operands;
+  }
+  PostScriptEvaluator.prototype = {
+    execute: function PostScriptEvaluator_execute(initialStack) {
+      var stack = new PostScriptStack(initialStack);
+      var counter = 0;
+      var operators = this.operators;
+      var length = operators.length;
+      var operator, a, b;
+      while (counter < length) {
+        operator = operators[counter++];
+        if (typeof operator == 'number') {
+          // Operator is really an operand and should be pushed to the stack.
+          stack.push(operator);
+          continue;
+        }
+        switch (operator) {
+          // non standard ps operators
+          case 'jz': // jump if false
+            b = stack.pop();
+            a = stack.pop();
+            if (!a)
+              counter = b;
+            break;
+          case 'j': // jump
+            a = stack.pop();
+            counter = a;
+            break;
+
+          // all ps operators in alphabetical order (excluding if/ifelse)
+          case 'abs':
+            a = stack.pop();
+            stack.push(Math.abs(a));
+            break;
+          case 'add':
+            b = stack.pop();
+            a = stack.pop();
+            stack.push(a + b);
+            break;
+          case 'and':
+            b = stack.pop();
+            a = stack.pop();
+            if (isBool(a) && isBool(b))
+              stack.push(a && b);
+            else
+              stack.push(a & b);
+            break;
+          case 'atan':
+            a = stack.pop();
+            stack.push(Math.atan(a));
+            break;
+          case 'bitshift':
+            b = stack.pop();
+            a = stack.pop();
+            if (a > 0)
+              stack.push(a << b);
+            else
+              stack.push(a >> b);
+            break;
+          case 'ceiling':
+            a = stack.pop();
+            stack.push(Math.ceil(a));
+            break;
+          case 'copy':
+            a = stack.pop();
+            stack.copy(a);
+            break;
+          case 'cos':
+            a = stack.pop();
+            stack.push(Math.cos(a));
+            break;
+          case 'cvi':
+            a = stack.pop() | 0;
+            stack.push(a);
+            break;
+          case 'cvr':
+            // noop
+            break;
+          case 'div':
+            b = stack.pop();
+            a = stack.pop();
+            stack.push(a / b);
+            break;
+          case 'dup':
+            stack.copy(1);
+            break;
+          case 'eq':
+            b = stack.pop();
+            a = stack.pop();
+            stack.push(a == b);
+            break;
+          case 'exch':
+            stack.roll(2, 1);
+            break;
+          case 'exp':
+            b = stack.pop();
+            a = stack.pop();
+            stack.push(Math.pow(a, b));
+            break;
+          case 'false':
+            stack.push(false);
+            break;
+          case 'floor':
+            a = stack.pop();
+            stack.push(Math.floor(a));
+            break;
+          case 'ge':
+            b = stack.pop();
+            a = stack.pop();
+            stack.push(a >= b);
+            break;
+          case 'gt':
+            b = stack.pop();
+            a = stack.pop();
+            stack.push(a > b);
+            break;
+          case 'idiv':
+            b = stack.pop();
+            a = stack.pop();
+            stack.push((a / b) | 0);
+            break;
+          case 'index':
+            a = stack.pop();
+            stack.index(a);
+            break;
+          case 'le':
+            b = stack.pop();
+            a = stack.pop();
+            stack.push(a <= b);
+            break;
+          case 'ln':
+            a = stack.pop();
+            stack.push(Math.log(a));
+            break;
+          case 'log':
+            a = stack.pop();
+            stack.push(Math.log(a) / Math.LN10);
+            break;
+          case 'lt':
+            b = stack.pop();
+            a = stack.pop();
+            stack.push(a < b);
+            break;
+          case 'mod':
+            b = stack.pop();
+            a = stack.pop();
+            stack.push(a % b);
+            break;
+          case 'mul':
+            b = stack.pop();
+            a = stack.pop();
+            stack.push(a * b);
+            break;
+          case 'ne':
+            b = stack.pop();
+            a = stack.pop();
+            stack.push(a != b);
+            break;
+          case 'neg':
+            a = stack.pop();
+            stack.push(-b);
+            break;
+          case 'not':
+            a = stack.pop();
+            if (isBool(a) && isBool(b))
+              stack.push(a && b);
+            else
+              stack.push(a & b);
+            break;
+          case 'or':
+            b = stack.pop();
+            a = stack.pop();
+            if (isBool(a) && isBool(b))
+              stack.push(a || b);
+            else
+              stack.push(a | b);
+            break;
+          case 'pop':
+            stack.pop();
+            break;
+          case 'roll':
+            b = stack.pop();
+            a = stack.pop();
+            stack.roll(a, b);
+            break;
+          case 'round':
+            a = stack.pop();
+            stack.push(Math.round(a));
+            break;
+          case 'sin':
+            a = stack.pop();
+            stack.push(Math.sin(a));
+            break;
+          case 'sqrt':
+            a = stack.pop();
+            stack.push(Math.sqrt(a));
+            break;
+          case 'sub':
+            b = stack.pop();
+            a = stack.pop();
+            stack.push(a - b);
+            break;
+          case 'true':
+            stack.push(true);
+            break;
+          case 'truncate':
+            a = stack.pop();
+            a = a < 0 ? Math.ceil(a) : Math.floor(a);
+            stack.push(a);
+            break;
+          case 'xor':
+            b = stack.pop();
+            a = stack.pop();
+            if (isBool(a) && isBool(b))
+              stack.push(a != b);
+            else
+              stack.push(a ^ b);
+            break;
+          default:
+            error('Unknown operator ' + operator);
+            break;
+        }
+      }
+      return stack.stack;
+    }
+  };
+  return PostScriptEvaluator;
+})();
+
+var PostScriptParser = (function PostScriptParserClosure() {
+  function PostScriptParser(lexer) {
+    this.lexer = lexer;
+    this.operators = [];
+    this.token;
+    this.prev;
+  }
+  PostScriptParser.prototype = {
+    nextToken: function PostScriptParser_nextToken() {
+      this.prev = this.token;
+      this.token = this.lexer.getToken();
+    },
+    accept: function PostScriptParser_accept(type) {
+      if (this.token.type == type) {
+        this.nextToken();
+        return true;
+      }
+      return false;
+    },
+    expect: function PostScriptParser_expect(type) {
+      if (this.accept(type))
+        return true;
+      error('Unexpected symbol: found ' + this.token.type + ' expected ' +
+            type + '.');
+    },
+    parse: function PostScriptParser_parse() {
+      this.nextToken();
+      this.expect(PostScriptTokenTypes.LBRACE);
+      this.parseBlock();
+      this.expect(PostScriptTokenTypes.RBRACE);
+      return this.operators;
+    },
+    parseBlock: function PostScriptParser_parseBlock() {
+      while (true) {
+        if (this.accept(PostScriptTokenTypes.NUMBER)) {
+          this.operators.push(this.prev.value);
+        } else if (this.accept(PostScriptTokenTypes.OPERATOR)) {
+          this.operators.push(this.prev.value);
+        } else if (this.accept(PostScriptTokenTypes.LBRACE)) {
+          this.parseCondition();
+        } else {
+          return;
+        }
+      }
+    },
+    parseCondition: function PostScriptParser_parseCondition() {
+      // Add two place holders that will be updated later
+      var conditionLocation = this.operators.length;
+      this.operators.push(null, null);
+
+      this.parseBlock();
+      this.expect(PostScriptTokenTypes.RBRACE);
+      if (this.accept(PostScriptTokenTypes.IF)) {
+        // The true block is right after the 'if' so it just falls through on
+        // true else it jumps and skips the true block.
+        this.operators[conditionLocation] = this.operators.length;
+        this.operators[conditionLocation + 1] = 'jz';
+      } else if (this.accept(PostScriptTokenTypes.LBRACE)) {
+        var jumpLocation = this.operators.length;
+        this.operators.push(null, null);
+        var endOfTrue = this.operators.length;
+        this.parseBlock();
+        this.expect(PostScriptTokenTypes.RBRACE);
+        this.expect(PostScriptTokenTypes.IFELSE);
+        // The jump is added at the end of the true block to skip the false
+        // block.
+        this.operators[jumpLocation] = this.operators.length;
+        this.operators[jumpLocation + 1] = 'j';
+
+        this.operators[conditionLocation] = endOfTrue;
+        this.operators[conditionLocation + 1] = 'jz';
+      } else {
+        error('PS Function: error parsing conditional.');
+      }
+    }
+  };
+  return PostScriptParser;
+})();
+
+var PostScriptTokenTypes = {
+  LBRACE: 0,
+  RBRACE: 1,
+  NUMBER: 2,
+  OPERATOR: 3,
+  IF: 4,
+  IFELSE: 5
+};
+
+var PostScriptToken = (function PostScriptTokenClosure() {
+  function PostScriptToken(type, value) {
+    this.type = type;
+    this.value = value;
+  }
+
+  var opCache = {};
+
+  PostScriptToken.getOperator = function PostScriptToken_getOperator(op) {
+    var opValue = opCache[op];
+    if (opValue)
+      return opValue;
+
+    return opCache[op] = new PostScriptToken(PostScriptTokenTypes.OPERATOR, op);
+  };
+
+  PostScriptToken.LBRACE = new PostScriptToken(PostScriptTokenTypes.LBRACE,
+                                                '{');
+  PostScriptToken.RBRACE = new PostScriptToken(PostScriptTokenTypes.RBRACE,
+                                                '}');
+  PostScriptToken.IF = new PostScriptToken(PostScriptTokenTypes.IF, 'IF');
+  PostScriptToken.IFELSE = new PostScriptToken(PostScriptTokenTypes.IFELSE,
+                                                'IFELSE');
+  return PostScriptToken;
+})();
+
+var PostScriptLexer = (function PostScriptLexerClosure() {
+  function PostScriptLexer(stream) {
+    this.stream = stream;
+  }
+  PostScriptLexer.prototype = {
+    getToken: function PostScriptLexer_getToken() {
+      var s = '';
+      var ch;
+      var comment = false;
+      var stream = this.stream;
+
+      // skip comments
+      while (true) {
+        if (!(ch = stream.getChar()))
+          return EOF;
+
+        if (comment) {
+          if (ch == '\x0a' || ch == '\x0d')
+            comment = false;
+        } else if (ch == '%') {
+          comment = true;
+        } else if (!Lexer.isSpace(ch)) {
+          break;
+        }
+      }
+      switch (ch) {
+        case '0': case '1': case '2': case '3': case '4':
+        case '5': case '6': case '7': case '8': case '9':
+        case '+': case '-': case '.':
+          return new PostScriptToken(PostScriptTokenTypes.NUMBER,
+                                      this.getNumber(ch));
+        case '{':
+          return PostScriptToken.LBRACE;
+        case '}':
+          return PostScriptToken.RBRACE;
+      }
+      // operator
+      var str = ch.toLowerCase();
+      while (true) {
+        ch = stream.lookChar().toLowerCase();
+        if (ch >= 'a' && ch <= 'z')
+          str += ch;
+        else
+          break;
+        stream.skip();
+      }
+      switch (str) {
+        case 'if':
+          return PostScriptToken.IF;
+        case 'ifelse':
+          return PostScriptToken.IFELSE;
+        default:
+          return PostScriptToken.getOperator(str);
+      }
+    },
+    getNumber: function PostScriptLexer_getNumber(ch) {
+      var str = ch;
+      var stream = this.stream;
+      while (true) {
+        ch = stream.lookChar();
+        if ((ch >= '0' && ch <= '9') || ch == '-' || ch == '.')
+          str += ch;
+        else
+          break;
+        stream.skip();
+      }
+      var value = parseFloat(str);
+      if (isNaN(value))
+        error('Invalid floating point number: ' + value);
+      return value;
+    }
+  };
+  return PostScriptLexer;
+})();
+
diff --git a/apps/files_pdfviewer/js/pdfjs/src/glyphlist.js b/apps/files_pdfviewer/js/pdfjs/src/glyphlist.js
old mode 100755
new mode 100644
index 5691f85461ea9dfb2aa64c485bfc20b92f87f870..694134840e680206c53568f8c7941fc8224190d6
--- a/apps/files_pdfviewer/js/pdfjs/src/glyphlist.js
+++ b/apps/files_pdfviewer/js/pdfjs/src/glyphlist.js
@@ -1508,27 +1508,7 @@ var GlyphsUnicode = {
   dalet: 0x05D3,
   daletdagesh: 0xFB33,
   daletdageshhebrew: 0xFB33,
-  dalethatafpatah: 0x05D305B2,
-  dalethatafpatahhebrew: 0x05D305B2,
-  dalethatafsegol: 0x05D305B1,
-  dalethatafsegolhebrew: 0x05D305B1,
   dalethebrew: 0x05D3,
-  dalethiriq: 0x05D305B4,
-  dalethiriqhebrew: 0x05D305B4,
-  daletholam: 0x05D305B9,
-  daletholamhebrew: 0x05D305B9,
-  daletpatah: 0x05D305B7,
-  daletpatahhebrew: 0x05D305B7,
-  daletqamats: 0x05D305B8,
-  daletqamatshebrew: 0x05D305B8,
-  daletqubuts: 0x05D305BB,
-  daletqubutshebrew: 0x05D305BB,
-  daletsegol: 0x05D305B6,
-  daletsegolhebrew: 0x05D305B6,
-  daletsheva: 0x05D305B0,
-  daletshevahebrew: 0x05D305B0,
-  dalettsere: 0x05D305B5,
-  dalettserehebrew: 0x05D305B5,
   dalfinalarabic: 0xFEAA,
   dammaarabic: 0x064F,
   dammalowarabic: 0x064F,
@@ -1845,10 +1825,6 @@ var GlyphsUnicode = {
   finalkafdagesh: 0xFB3A,
   finalkafdageshhebrew: 0xFB3A,
   finalkafhebrew: 0x05DA,
-  finalkafqamats: 0x05DA05B8,
-  finalkafqamatshebrew: 0x05DA05B8,
-  finalkafsheva: 0x05DA05B0,
-  finalkafshevahebrew: 0x05DA05B0,
   finalmem: 0x05DD,
   finalmemhebrew: 0x05DD,
   finalnun: 0x05DF,
@@ -2037,14 +2013,7 @@ var GlyphsUnicode = {
   hakatakanahalfwidth: 0xFF8A,
   halantgurmukhi: 0x0A4D,
   hamzaarabic: 0x0621,
-  hamzadammaarabic: 0x0621064F,
-  hamzadammatanarabic: 0x0621064C,
-  hamzafathaarabic: 0x0621064E,
-  hamzafathatanarabic: 0x0621064B,
   hamzalowarabic: 0x0621,
-  hamzalowkasraarabic: 0x06210650,
-  hamzalowkasratanarabic: 0x0621064D,
-  hamzasukunarabic: 0x06210652,
   hangulfiller: 0x3164,
   hardsigncyrillic: 0x044A,
   harpoonleftbarbup: 0x21BC,
@@ -2476,10 +2445,6 @@ var GlyphsUnicode = {
   lameddagesh: 0xFB3C,
   lameddageshhebrew: 0xFB3C,
   lamedhebrew: 0x05DC,
-  lamedholam: 0x05DC05B9,
-  lamedholamdagesh: '05DC 05B9 05BC',
-  lamedholamdageshhebrew: '05DC 05B9 05BC',
-  lamedholamhebrew: 0x05DC05B9,
   lamfinalarabic: 0xFEDE,
   lamhahinitialarabic: 0xFCCA,
   laminitialarabic: 0xFEDF,
@@ -2489,8 +2454,6 @@ var GlyphsUnicode = {
   lammedialarabic: 0xFEE0,
   lammeemhahinitialarabic: 0xFD88,
   lammeeminitialarabic: 0xFCCC,
-  lammeemjeeminitialarabic: 'FEDF FEE4 FEA0',
-  lammeemkhahinitialarabic: 'FEDF FEE4 FEA8',
   largecircle: 0x25EF,
   lbar: 0x019A,
   lbelt: 0x026C,
@@ -2787,7 +2750,6 @@ var GlyphsUnicode = {
   noonfinalarabic: 0xFEE6,
   noonghunnaarabic: 0x06BA,
   noonghunnafinalarabic: 0xFB9F,
-  noonhehinitialarabic: 0xFEE7FEEC,
   nooninitialarabic: 0xFEE7,
   noonjeeminitialarabic: 0xFCD2,
   noonjeemisolatedarabic: 0xFC4B,
@@ -3159,27 +3121,7 @@ var GlyphsUnicode = {
   qof: 0x05E7,
   qofdagesh: 0xFB47,
   qofdageshhebrew: 0xFB47,
-  qofhatafpatah: 0x05E705B2,
-  qofhatafpatahhebrew: 0x05E705B2,
-  qofhatafsegol: 0x05E705B1,
-  qofhatafsegolhebrew: 0x05E705B1,
   qofhebrew: 0x05E7,
-  qofhiriq: 0x05E705B4,
-  qofhiriqhebrew: 0x05E705B4,
-  qofholam: 0x05E705B9,
-  qofholamhebrew: 0x05E705B9,
-  qofpatah: 0x05E705B7,
-  qofpatahhebrew: 0x05E705B7,
-  qofqamats: 0x05E705B8,
-  qofqamatshebrew: 0x05E705B8,
-  qofqubuts: 0x05E705BB,
-  qofqubutshebrew: 0x05E705BB,
-  qofsegol: 0x05E705B6,
-  qofsegolhebrew: 0x05E705B6,
-  qofsheva: 0x05E705B0,
-  qofshevahebrew: 0x05E705B0,
-  qoftsere: 0x05E705B5,
-  qoftserehebrew: 0x05E705B5,
   qparen: 0x24AC,
   quarternote: 0x2669,
   qubuts: 0x05BB,
@@ -3253,32 +3195,11 @@ var GlyphsUnicode = {
   reharmenian: 0x0580,
   rehfinalarabic: 0xFEAE,
   rehiragana: 0x308C,
-  rehyehaleflamarabic: '0631 FEF3 FE8E 0644',
   rekatakana: 0x30EC,
   rekatakanahalfwidth: 0xFF9A,
   resh: 0x05E8,
   reshdageshhebrew: 0xFB48,
-  reshhatafpatah: 0x05E805B2,
-  reshhatafpatahhebrew: 0x05E805B2,
-  reshhatafsegol: 0x05E805B1,
-  reshhatafsegolhebrew: 0x05E805B1,
   reshhebrew: 0x05E8,
-  reshhiriq: 0x05E805B4,
-  reshhiriqhebrew: 0x05E805B4,
-  reshholam: 0x05E805B9,
-  reshholamhebrew: 0x05E805B9,
-  reshpatah: 0x05E805B7,
-  reshpatahhebrew: 0x05E805B7,
-  reshqamats: 0x05E805B8,
-  reshqamatshebrew: 0x05E805B8,
-  reshqubuts: 0x05E805BB,
-  reshqubutshebrew: 0x05E805BB,
-  reshsegol: 0x05E805B6,
-  reshsegolhebrew: 0x05E805B6,
-  reshsheva: 0x05E805B0,
-  reshshevahebrew: 0x05E805B0,
-  reshtsere: 0x05E805B5,
-  reshtserehebrew: 0x05E805B5,
   reversedtilde: 0x223D,
   reviahebrew: 0x0597,
   reviamugrashhebrew: 0x0597,
@@ -3477,7 +3398,6 @@ var GlyphsUnicode = {
   shaddadammaarabic: 0xFC61,
   shaddadammatanarabic: 0xFC5E,
   shaddafathaarabic: 0xFC60,
-  shaddafathatanarabic: 0x0651064B,
   shaddakasraarabic: 0xFC62,
   shaddakasratanarabic: 0xFC5F,
   shade: 0x2592,
@@ -3674,7 +3594,6 @@ var GlyphsUnicode = {
   tchehfinalarabic: 0xFB7B,
   tchehinitialarabic: 0xFB7C,
   tchehmedialarabic: 0xFB7D,
-  tchehmeeminitialarabic: 0xFB7CFEE4,
   tcircle: 0x24E3,
   tcircumflexbelow: 0x1E71,
   tcommaaccent: 0x0163,
@@ -4287,6 +4206,7 @@ var GlyphsUnicode = {
   zretroflexhook: 0x0290,
   zstroke: 0x01B6,
   zuhiragana: 0x305A,
-  zukatakana: 0x30BA
+  zukatakana: 0x30BA,
+  '.notdef': 0x0000
 };
 
diff --git a/apps/files_pdfviewer/js/pdfjs/src/image.js b/apps/files_pdfviewer/js/pdfjs/src/image.js
old mode 100755
new mode 100644
index 17ef7b06d822e69dfbb6877b112be44ae43f40cc..035e2f754be0bb6b74b9d49ace5f20222d25f15f
--- a/apps/files_pdfviewer/js/pdfjs/src/image.js
+++ b/apps/files_pdfviewer/js/pdfjs/src/image.js
@@ -3,8 +3,37 @@
 
 'use strict';
 
-var PDFImage = (function pdfImage() {
-  function constructor(xref, res, image, inline) {
+var PDFImage = (function PDFImageClosure() {
+  /**
+   * Decode the image in the main thread if it supported. Resovles the promise
+   * when the image data is ready.
+   */
+  function handleImageData(handler, xref, res, image, promise) {
+    if (image instanceof JpegStream && image.isNativelyDecodable(xref, res)) {
+      // For natively supported jpegs send them to the main thread for decoding.
+      var dict = image.dict;
+      var colorSpace = dict.get('ColorSpace', 'CS');
+      colorSpace = ColorSpace.parse(colorSpace, xref, res);
+      var numComps = colorSpace.numComps;
+      handler.send('jpeg_decode', [image.getIR(), numComps], function(message) {
+        var data = message.data;
+        var stream = new Stream(data, 0, data.length, image.dict);
+        promise.resolve(stream);
+      });
+    } else {
+      promise.resolve(image);
+    }
+  }
+  /**
+   * Decode and clamp a value. The formula is different from the spec because we
+   * don't decode to float range [0,1], we decode it in the [0,max] range.
+   */
+  function decodeAndClamp(value, addend, coefficient, max) {
+    value = addend + value * coefficient;
+    // Clamp the value to the range
+    return value < 0 ? 0 : value > max ? max : value;
+  }
+  function PDFImage(xref, res, image, inline, smask) {
     this.image = image;
     if (image.getParams) {
       // JPX/JPEG2000 streams directly contain bits per component
@@ -49,34 +78,143 @@ var PDFImage = (function pdfImage() {
     }
 
     this.decode = dict.get('Decode', 'D');
+    this.needsDecode = false;
+    if (this.decode && this.colorSpace &&
+        !this.colorSpace.isDefaultDecode(this.decode)) {
+      this.needsDecode = true;
+      // Do some preprocessing to avoid more math.
+      var max = (1 << bitsPerComponent) - 1;
+      this.decodeCoefficients = [];
+      this.decodeAddends = [];
+      for (var i = 0, j = 0; i < this.decode.length; i += 2, ++j) {
+        var dmin = this.decode[i];
+        var dmax = this.decode[i + 1];
+        this.decodeCoefficients[j] = dmax - dmin;
+        this.decodeAddends[j] = max * dmin;
+      }
+    }
 
-    var mask = xref.fetchIfRef(dict.get('Mask'));
-    var smask = xref.fetchIfRef(dict.get('SMask'));
+    var mask = dict.get('Mask');
 
     if (mask) {
       TODO('masked images');
     } else if (smask) {
-      this.smask = new PDFImage(xref, res, smask);
+      this.smask = new PDFImage(xref, res, smask, false);
     }
   }
+  /**
+   * Handles processing of image data and calls the callback with an argument
+   * of a PDFImage when the image is ready to be used.
+   */
+  PDFImage.buildImage = function PDFImage_buildImage(callback, handler, xref,
+                                                     res, image, inline) {
+    var imageDataPromise = new Promise();
+    var smaskPromise = new Promise();
+    // The image data and smask data may not be ready yet, wait till both are
+    // resolved.
+    Promise.all([imageDataPromise, smaskPromise]).then(function(results) {
+      var imageData = results[0], smaskData = results[1];
+      var image = new PDFImage(xref, res, imageData, inline, smaskData);
+      callback(image);
+    });
+
+    handleImageData(handler, xref, res, image, imageDataPromise);
+
+    var smask = image.dict.get('SMask');
+    if (smask)
+      handleImageData(handler, xref, res, smask, smaskPromise);
+    else
+      smaskPromise.resolve(null);
+  };
+
+  /**
+   * Resize an image using the nearest neighbor algorithm.  Currently only
+   * supports one and three component images.
+   * @param {TypedArray} pixels The original image with one component.
+   * @param {Number} bpc Number of bits per component.
+   * @param {Number} components Number of color components, 1 or 3 is supported.
+   * @param {Number} w1 Original width.
+   * @param {Number} h1 Original height.
+   * @param {Number} w2 New width.
+   * @param {Number} h2 New height.
+   * @return {TypedArray} Resized image data.
+   */
+  PDFImage.resize = function PDFImage_resize(pixels, bpc, components,
+                                             w1, h1, w2, h2) {
+    var length = w2 * h2 * components;
+    var temp = bpc <= 8 ? new Uint8Array(length) :
+        bpc <= 16 ? new Uint16Array(length) : new Uint32Array(length);
+    var xRatio = w1 / w2;
+    var yRatio = h1 / h2;
+    var px, py, newIndex, oldIndex;
+    for (var i = 0; i < h2; i++) {
+      for (var j = 0; j < w2; j++) {
+        px = Math.floor(j * xRatio);
+        py = Math.floor(i * yRatio);
+        newIndex = (i * w2) + j;
+        oldIndex = ((py * w1) + px);
+        if (components === 1) {
+          temp[newIndex] = pixels[oldIndex];
+        } else if (components === 3) {
+          newIndex *= 3;
+          oldIndex *= 3;
+          temp[newIndex] = pixels[oldIndex];
+          temp[newIndex + 1] = pixels[oldIndex + 1];
+          temp[newIndex + 2] = pixels[oldIndex + 2];
+        }
+      }
+    }
+    return temp;
+  };
 
-  constructor.prototype = {
-    getComponents: function getComponents(buffer, decodeMap) {
+  PDFImage.prototype = {
+    get drawWidth() {
+      if (!this.smask)
+        return this.width;
+      return Math.max(this.width, this.smask.width);
+    },
+    get drawHeight() {
+      if (!this.smask)
+        return this.height;
+      return Math.max(this.height, this.smask.height);
+    },
+    getComponents: function PDFImage_getComponents(buffer) {
       var bpc = this.bpc;
-      if (bpc == 8)
+      var needsDecode = this.needsDecode;
+      var decodeMap = this.decode;
+
+      // This image doesn't require any extra work.
+      if (bpc == 8 && !needsDecode)
         return buffer;
 
+      var bufferLength = buffer.length;
       var width = this.width;
       var height = this.height;
       var numComps = this.numComps;
 
-      var length = width * height;
+      var length = width * height * numComps;
       var bufferPos = 0;
       var output = bpc <= 8 ? new Uint8Array(length) :
         bpc <= 16 ? new Uint16Array(length) : new Uint32Array(length);
       var rowComps = width * numComps;
+      var decodeAddends, decodeCoefficients;
+      if (needsDecode) {
+        decodeAddends = this.decodeAddends;
+        decodeCoefficients = this.decodeCoefficients;
+      }
+      var max = (1 << bpc) - 1;
 
-      if (bpc == 1) {
+      if (bpc == 8) {
+        // Optimization for reading 8 bpc images that have a decode.
+        for (var i = 0, ii = length; i < ii; ++i) {
+          var compIndex = i % numComps;
+          var value = buffer[i];
+          value = decodeAndClamp(value, decodeAddends[compIndex],
+                          decodeCoefficients[compIndex], max);
+          output[i] = value;
+        }
+      } else if (bpc == 1) {
+        // Optimization for reading 1 bpc images.
         var valueZero = 0, valueOne = 1;
         if (decodeMap) {
           valueZero = decodeMap[0] ? 1 : 0;
@@ -101,8 +239,7 @@ var PDFImage = (function pdfImage() {
           output[i] = !(buf & mask) ? valueZero : valueOne;
         }
       } else {
-        if (decodeMap != null)
-          TODO('interpolate component values');
+        // The general case that handles all other bpc values.
         var bits = 0, buf = 0;
         for (var i = 0, ii = length; i < ii; ++i) {
           if (i % rowComps == 0) {
@@ -116,51 +253,44 @@ var PDFImage = (function pdfImage() {
           }
 
           var remainingBits = bits - bpc;
-          output[i] = buf >> remainingBits;
+          var value = buf >> remainingBits;
+          if (needsDecode) {
+            var compIndex = i % numComps;
+            value = decodeAndClamp(value, decodeAddends[compIndex],
+                            decodeCoefficients[compIndex], max);
+          }
+          output[i] = value;
           buf = buf & ((1 << remainingBits) - 1);
           bits = remainingBits;
         }
       }
       return output;
     },
-    getOpacity: function getOpacity() {
+    getOpacity: function PDFImage_getOpacity(width, height) {
       var smask = this.smask;
-      var width = this.width;
-      var height = this.height;
-      var buf = new Uint8Array(width * height);
+      var originalWidth = this.width;
+      var originalHeight = this.height;
+      var buf;
 
       if (smask) {
-        if (smask.image.getImage) {
-          // smask is a DOM image
-          var tempCanvas = new ScratchCanvas(width, height);
-          var tempCtx = tempCanvas.getContext('2d');
-          var domImage = smask.image.getImage();
-          tempCtx.drawImage(domImage, 0, 0, domImage.width, domImage.height,
-            0, 0, width, height);
-          var data = tempCtx.getImageData(0, 0, width, height).data;
-          for (var i = 0, j = 0, ii = width * height; i < ii; ++i, j += 4)
-            buf[i] = data[j]; // getting first component value
-          return buf;
-        }
         var sw = smask.width;
         var sh = smask.height;
-        if (sw != this.width || sh != this.height)
-          error('smask dimensions do not match image dimensions: ' + sw +
-                ' != ' + this.width + ', ' + sh + ' != ' + this.height);
-
+        buf = new Uint8Array(sw * sh);
         smask.fillGrayBuffer(buf);
-        return buf;
+        if (sw != width || sh != height)
+          buf = PDFImage.resize(buf, smask.bps, 1, sw, sh, width, height);
       } else {
+        buf = new Uint8Array(width * height);
         for (var i = 0, ii = width * height; i < ii; ++i)
           buf[i] = 255;
       }
       return buf;
     },
-    applyStencilMask: function applyStencilMask(buffer, inverseDecode) {
+    applyStencilMask: function PDFImage_applyStencilMask(buffer,
+                                                         inverseDecode) {
       var width = this.width, height = this.height;
       var bitStrideLength = (width + 7) >> 3;
-      this.image.reset();
-      var imgArray = this.image.getBytes(bitStrideLength * height);
+      var imgArray = this.getImageBytes(bitStrideLength * height);
       var imgArrayPos = 0;
       var i, j, mask, buf;
       // removing making non-masked pixels transparent
@@ -180,21 +310,23 @@ var PDFImage = (function pdfImage() {
         }
       }
     },
-    fillRgbaBuffer: function fillRgbaBuffer(buffer, decodeMap) {
+    fillRgbaBuffer: function PDFImage_fillRgbaBuffer(buffer, width, height) {
       var numComps = this.numComps;
-      var width = this.width;
-      var height = this.height;
+      var originalWidth = this.width;
+      var originalHeight = this.height;
       var bpc = this.bpc;
 
       // rows start at byte boundary;
-      var rowBytes = (width * numComps * bpc + 7) >> 3;
-      this.image.reset();
-      var imgArray = this.image.getBytes(height * rowBytes);
+      var rowBytes = (originalWidth * numComps * bpc + 7) >> 3;
+      var imgArray = this.getImageBytes(originalHeight * rowBytes);
 
       var comps = this.colorSpace.getRgbBuffer(
-        this.getComponents(imgArray, decodeMap), bpc);
+        this.getComponents(imgArray), bpc);
+      if (originalWidth != width || originalHeight != height)
+        comps = PDFImage.resize(comps, this.bpc, 3, originalWidth,
+                                originalHeight, width, height);
       var compsPos = 0;
-      var opacity = this.getOpacity();
+      var opacity = this.getOpacity(width, height);
       var opacityPos = 0;
       var length = width * height * 4;
 
@@ -205,7 +337,7 @@ var PDFImage = (function pdfImage() {
         buffer[i + 3] = opacity[opacityPos++];
       }
     },
-    fillGrayBuffer: function fillGrayBuffer(buffer) {
+    fillGrayBuffer: function PDFImage_fillGrayBuffer(buffer) {
       var numComps = this.numComps;
       if (numComps != 1)
         error('Reading gray scale from a color image: ' + numComps);
@@ -216,42 +348,28 @@ var PDFImage = (function pdfImage() {
 
       // rows start at byte boundary;
       var rowBytes = (width * numComps * bpc + 7) >> 3;
-      this.image.reset();
-      var imgArray = this.image.getBytes(height * rowBytes);
+      var imgArray = this.getImageBytes(height * rowBytes);
 
       var comps = this.getComponents(imgArray);
       var length = width * height;
-
+      // we aren't using a colorspace so we need to scale the value
+      var scale = 255 / ((1 << bpc) - 1);
       for (var i = 0; i < length; ++i)
-        buffer[i] = comps[i];
+        buffer[i] = (scale * comps[i]) | 0;
+    },
+    getImageBytes: function PDFImage_getImageBytes(length) {
+      this.image.reset();
+      return this.image.getBytes(length);
     }
   };
-  return constructor;
+  return PDFImage;
 })();
 
-var JpegImageLoader = (function jpegImage() {
-  function JpegImageLoader(objId, imageData, objs) {
-    var src = 'data:image/jpeg;base64,' + window.btoa(imageData);
-
-    var img = new Image();
-    img.onload = (function jpegImageLoaderOnload() {
-      this.loaded = true;
-
-      objs.resolve(objId, this);
-
-      if (this.onLoad)
-        this.onLoad();
-    }).bind(this);
-    img.src = src;
-    this.domImage = img;
-  }
-
-  JpegImageLoader.prototype = {
-    getImage: function jpegImageLoaderGetImage() {
-      return this.domImage;
-    }
-  };
-
-  return JpegImageLoader;
-})();
+function loadJpegStream(id, imageData, objs) {
+  var img = new Image();
+  img.onload = (function loadJpegStream_onloadClosure() {
+    objs.resolve(id, img);
+  });
+  img.src = 'data:image/jpeg;base64,' + window.btoa(imageData);
+}
 
diff --git a/apps/files_pdfviewer/js/pdfjs/src/jpx.js b/apps/files_pdfviewer/js/pdfjs/src/jpx.js
new file mode 100644
index 0000000000000000000000000000000000000000..63193753d2a1de08a9e6261810629dff7c06b4c2
--- /dev/null
+++ b/apps/files_pdfviewer/js/pdfjs/src/jpx.js
@@ -0,0 +1,1862 @@
+/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
+
+'use strict';
+
+var JpxImage = (function JpxImageClosure() {
+  // Table E.1
+  var SubbandsGainLog2 = {
+    'LL': 0,
+    'LH': 1,
+    'HL': 1,
+    'HH': 2
+  };
+  function JpxImage() {
+    this.failOnCorruptedImage = false;
+  }
+  JpxImage.prototype = {
+    load: function JpxImage_load(url) {
+      var xhr = new XMLHttpRequest();
+      xhr.open('GET', url, true);
+      xhr.responseType = 'arraybuffer';
+      xhr.onload = (function() {
+        // TODO catch parse error
+        var data = new Uint8Array(xhr.response || xhr.mozResponseArrayBuffer);
+        this.parse(data);
+        if (this.onload)
+          this.onload();
+      }).bind(this);
+      xhr.send(null);
+    },
+    parse: function JpxImage_parse(data) {
+      function ReadUint(data, offset, bytes) {
+        var n = 0;
+        for (var i = 0; i < bytes; i++)
+          n = n * 256 + (data[offset + i] & 0xFF);
+        return n;
+      }
+      var position = 0, length = data.length;
+      while (position < length) {
+        var headerSize = 8;
+        var lbox = ReadUint(data, position, 4);
+        var tbox = ReadUint(data, position + 4, 4);
+        position += headerSize;
+        if (lbox == 1) {
+          lbox = ReadUint(data, position, 8);
+          position += 8;
+          headerSize += 8;
+        }
+        if (lbox == 0)
+          lbox = length - position + headerSize;
+        if (lbox < headerSize)
+          error('JPX error: Invalid box field size');
+        var dataLength = lbox - headerSize;
+        var jumpDataLength = true;
+        switch (tbox) {
+          case 0x6A501A1A: // 'jP\032\032'
+            // TODO
+            break;
+          case 0x6A703268: // 'jp2h'
+            jumpDataLength = false; // parsing child boxes
+            break;
+          case 0x636F6C72: // 'colr'
+            // TODO
+            break;
+          case 0x6A703263: // 'jp2c'
+            this.parseCodestream(data, position, position + dataLength);
+            break;
+        }
+        if (jumpDataLength)
+          position += dataLength;
+      }
+    },
+    parseCodestream: function JpxImage_parseCodestream(data, start, end) {
+      var context = {};
+      try {
+        var position = start;
+        while (position < end) {
+          var code = readUint16(data, position);
+          position += 2;
+
+          var length = 0, j;
+          switch (code) {
+            case 0xFF4F: // Start of codestream (SOC)
+              context.mainHeader = true;
+              break;
+            case 0xFFD9: // End of codestream (EOC)
+              break;
+            case 0xFF51: // Image and tile size (SIZ)
+              length = readUint16(data, position);
+              var siz = {};
+              siz.Xsiz = readUint32(data, position + 4);
+              siz.Ysiz = readUint32(data, position + 8);
+              siz.XOsiz = readUint32(data, position + 12);
+              siz.YOsiz = readUint32(data, position + 16);
+              siz.XTsiz = readUint32(data, position + 20);
+              siz.YTsiz = readUint32(data, position + 24);
+              siz.XTOsiz = readUint32(data, position + 28);
+              siz.YTOsiz = readUint32(data, position + 32);
+              var componentsCount = readUint16(data, position + 36);
+              siz.Csiz = componentsCount;
+              var components = [];
+              j = position + 38;
+              for (var i = 0; i < componentsCount; i++) {
+                var component = {
+                  precision: (data[j] & 0x7F) + 1,
+                  isSigned: !!(data[j] & 0x80),
+                  XRsiz: data[j + 1],
+                  YRsiz: data[j + 1]
+                };
+                calculateComponentDimensions(component, siz);
+                components.push(component);
+              }
+              context.SIZ = siz;
+              context.components = components;
+              calculateTileGrids(context, components);
+              context.QCC = [];
+              context.COC = [];
+              break;
+            case 0xFF5C: // Quantization default (QCD)
+              length = readUint16(data, position);
+              var qcd = {};
+              j = position + 2;
+              var sqcd = data[j++];
+              var spqcdSize, scalarExpounded;
+              switch (sqcd & 0x1F) {
+                case 0:
+                  spqcdSize = 8;
+                  scalarExpounded = true;
+                  break;
+                case 1:
+                  spqcdSize = 16;
+                  scalarExpounded = false;
+                  break;
+                case 2:
+                  spqcdSize = 16;
+                  scalarExpounded = true;
+                  break;
+                default:
+                  throw 'Invalid SQcd value ' + sqcd;
+              }
+              qcd.noQuantization = spqcdSize == 8;
+              qcd.scalarExpounded = scalarExpounded;
+              qcd.guardBits = sqcd >> 5;
+              var spqcds = [];
+              while (j < length + position) {
+                var spqcd = {};
+                if (spqcdSize == 8) {
+                  spqcd.epsilon = data[j++] >> 3;
+                  spqcd.mu = 0;
+                } else {
+                  spqcd.epsilon = data[j] >> 3;
+                  spqcd.mu = ((data[j] & 0x7) << 8) | data[j + 1];
+                  j += 2;
+                }
+                spqcds.push(spqcd);
+              }
+              qcd.SPqcds = spqcds;
+              if (context.mainHeader)
+                context.QCD = qcd;
+              else {
+                context.currentTile.QCD = qcd;
+                context.currentTile.QCC = [];
+              }
+              break;
+            case 0xFF5D: // Quantization component (QCC)
+              length = readUint16(data, position);
+              var qcc = {};
+              j = position + 2;
+              var cqcc;
+              if (context.SIZ.Csiz < 257)
+                cqcc = data[j++];
+              else {
+                cqcc = readUint16(data, j);
+                j += 2;
+              }
+              var sqcd = data[j++];
+              var spqcdSize, scalarExpounded;
+              switch (sqcd & 0x1F) {
+                case 0:
+                  spqcdSize = 8;
+                  scalarExpounded = true;
+                  break;
+                case 1:
+                  spqcdSize = 16;
+                  scalarExpounded = false;
+                  break;
+                case 2:
+                  spqcdSize = 16;
+                  scalarExpounded = true;
+                  break;
+                default:
+                  throw 'Invalid SQcd value ' + sqcd;
+              }
+              qcc.noQuantization = spqcdSize == 8;
+              qcc.scalarExpounded = scalarExpounded;
+              qcc.guardBits = sqcd >> 5;
+              var spqcds = [];
+              while (j < length + position) {
+                var spqcd = {};
+                if (spqcdSize == 8) {
+                  spqcd.epsilon = data[j++] >> 3;
+                  spqcd.mu = 0;
+                } else {
+                  spqcd.epsilon = data[j] >> 3;
+                  spqcd.mu = ((data[j] & 0x7) << 8) | data[j + 1];
+                  j += 2;
+                }
+                spqcds.push(spqcd);
+              }
+              qcc.SPqcds = spqcds;
+              if (context.mainHeader)
+                context.QCC[cqcc] = qcc;
+              else
+                context.currentTile.QCC[cqcc] = qcc;
+              break;
+            case 0xFF52: // Coding style default (COD)
+              length = readUint16(data, position);
+              var cod = {};
+              j = position + 2;
+              var scod = data[j++];
+              cod.entropyCoderWithCustomPrecincts = !!(scod & 1);
+              cod.sopMarkerUsed = !!(scod & 2);
+              cod.ephMarkerUsed = !!(scod & 4);
+              var codingStyle = {};
+              cod.progressionOrder = data[j++];
+              cod.layersCount = readUint16(data, j);
+              j += 2;
+              cod.multipleComponentTransform = data[j++];
+
+              cod.decompositionLevelsCount = data[j++];
+              cod.xcb = (data[j++] & 0xF) + 2;
+              cod.ycb = (data[j++] & 0xF) + 2;
+              var blockStyle = data[j++];
+              cod.selectiveArithmeticCodingBypass = !!(blockStyle & 1);
+              cod.resetContextProbabilities = !!(blockStyle & 2);
+              cod.terminationOnEachCodingPass = !!(blockStyle & 4);
+              cod.verticalyStripe = !!(blockStyle & 8);
+              cod.predictableTermination = !!(blockStyle & 16);
+              cod.segmentationSymbolUsed = !!(blockStyle & 32);
+              cod.transformation = data[j++];
+              if (cod.entropyCoderWithCustomPrecincts) {
+                var precinctsSizes = {};
+                while (j < length + position) {
+                  var precinctsSize = data[j];
+                  precinctsSizes.push({
+                    PPx: precinctsSize & 0xF,
+                    PPy: precinctsSize >> 4
+                  });
+                }
+                cod.precinctsSizes = precinctsSizes;
+              }
+
+              if (cod.sopMarkerUsed || cod.ephMarkerUsed ||
+                  cod.selectiveArithmeticCodingBypass ||
+                  cod.resetContextProbabilities ||
+                  cod.terminationOnEachCodingPass ||
+                  cod.verticalyStripe || cod.predictableTermination ||
+                  cod.segmentationSymbolUsed)
+                throw 'Unsupported COD options: ' + uneval(cod);
+
+              if (context.mainHeader)
+                context.COD = cod;
+              else {
+                context.currentTile.COD = cod;
+                context.currentTile.COC = [];
+              }
+              break;
+            case 0xFF90: // Start of tile-part (SOT)
+              length = readUint16(data, position);
+              var tile = {};
+              tile.index = readUint16(data, position + 2);
+              tile.length = readUint32(data, position + 4);
+              tile.dataEnd = tile.length + position - 2;
+              tile.partIndex = data[position + 8];
+              tile.partsCount = data[position + 9];
+
+              context.mainHeader = false;
+              if (tile.partIndex == 0) {
+                // reset component specific settings
+                tile.COD = context.COD;
+                tile.COC = context.COC.slice(0); // clone of the global COC
+                tile.QCD = context.QCD;
+                tile.QCC = context.QCC.slice(0); // clone of the global COC
+              }
+              context.currentTile = tile;
+              break;
+            case 0xFF93: // Start of data (SOD)
+              var tile = context.currentTile;
+              if (tile.partIndex == 0) {
+                initializeTile(context, tile.index);
+                buildPackets(context);
+              }
+
+              // moving to the end of the data
+              length = tile.dataEnd - position;
+
+              parseTilePackets(context, data, position, length);
+              break;
+            case 0xFF64: // Comment (COM)
+              length = readUint16(data, position);
+              // skipping content
+              break;
+            default:
+              throw 'Unknown codestream code: ' + code.toString(16);
+          }
+          position += length;
+        }
+      } catch (e) {
+        if (this.failOnCorruptedImage)
+          error('JPX error: ' + e);
+        else
+          warn('JPX error: ' + e + '. Trying to recover');
+      }
+      this.tiles = transformComponents(context);
+      this.width = context.SIZ.Xsiz - context.SIZ.XOsiz;
+      this.height = context.SIZ.Ysiz - context.SIZ.YOsiz;
+      this.componentsCount = context.SIZ.Csiz;
+    }
+  };
+  function readUint32(data, offset) {
+    return (data[offset] << 24) | (data[offset + 1] << 16) |
+      (data[offset + 2] << 8) | data[offset + 3];
+  }
+  function readUint16(data, offset) {
+    return (data[offset] << 8) | data[offset + 1];
+  }
+  function log2(x) {
+    var n = 1, i = 0;
+    while (x > n) {
+      n <<= 1;
+      i++;
+    }
+    return i;
+  }
+  function calculateComponentDimensions(component, siz) {
+    // Section B.2 Component mapping
+    component.x0 = Math.ceil(siz.XOsiz / component.XRsiz);
+    component.x1 = Math.ceil(siz.Xsiz / component.XRsiz);
+    component.y0 = Math.ceil(siz.YOsiz / component.YRsiz);
+    component.y1 = Math.ceil(siz.Ysiz / component.YRsiz);
+    component.width = component.x1 - component.x0;
+    component.height = component.y1 - component.y0;
+  }
+  function calculateTileGrids(context, components) {
+    var siz = context.SIZ;
+    // Section B.3 Division into tile and tile-components
+    var tiles = [];
+    var numXtiles = Math.ceil((siz.Xsiz - siz.XTOsiz) / siz.XTsiz);
+    var numYtiles = Math.ceil((siz.Ysiz - siz.YTOsiz) / siz.YTsiz);
+    for (var q = 0; q < numYtiles; q++) {
+      for (var p = 0; p < numXtiles; p++) {
+        var tile = {};
+        tile.tx0 = Math.max(siz.XTOsiz + p * siz.XTsiz, siz.XOsiz);
+        tile.ty0 = Math.max(siz.YTOsiz + q * siz.YTsiz, siz.YOsiz);
+        tile.tx1 = Math.min(siz.XTOsiz + (p + 1) * siz.XTsiz, siz.Xsiz);
+        tile.ty1 = Math.min(siz.YTOsiz + (q + 1) * siz.YTsiz, siz.Ysiz);
+        tile.width = tile.tx1 - tile.tx0;
+        tile.height = tile.ty1 - tile.ty0;
+        tile.components = [];
+        tiles.push(tile);
+      }
+    }
+    context.tiles = tiles;
+
+    var componentsCount = siz.Csiz;
+    for (var i = 0, ii = componentsCount; i < ii; i++) {
+      var component = components[i];
+      var tileComponents = [];
+      for (var j = 0, jj = tiles.length; j < jj; j++) {
+        var tileComponent = {}, tile = tiles[j];
+        tileComponent.tcx0 = Math.ceil(tile.tx0 / component.XRsiz);
+        tileComponent.tcy0 = Math.ceil(tile.ty0 / component.YRsiz);
+        tileComponent.tcx1 = Math.ceil(tile.tx1 / component.XRsiz);
+        tileComponent.tcy1 = Math.ceil(tile.ty1 / component.YRsiz);
+        tileComponent.width = tileComponent.tcx1 - tileComponent.tcx0;
+        tileComponent.height = tileComponent.tcy1 - tileComponent.tcy0;
+        tile.components[i] = tileComponent;
+      }
+    }
+  }
+  function getBlocksDimensions(context, component, r) {
+    var codOrCoc = component.codingStyleParameters;
+    var result = {};
+    if (!codOrCoc.entropyCoderWithCustomPrecincts) {
+      result.PPx = 15;
+      result.PPy = 15;
+    } else {
+      result.PPx = codOrCoc.precinctsSizes[r].PPx;
+      result.PPy = codOrCoc.precinctsSizes[r].PPy;
+    }
+    // calculate codeblock size as described in section B.7
+    result.xcb_ = r > 0 ? Math.min(codOrCoc.xcb, result.PPx - 1) :
+      Math.min(codOrCoc.xcb, result.PPx);
+    result.ycb_ = r > 0 ? Math.min(codOrCoc.ycb, result.PPy - 1) :
+      Math.min(codOrCoc.ycb, result.PPy);
+    return result;
+  }
+  function buildPrecincts(context, resolution, dimensions) {
+    // Section B.6 Division resolution to precincts
+    var precinctWidth = 1 << dimensions.PPx;
+    var precinctHeight = 1 << dimensions.PPy;
+    var numprecinctswide = resolution.trx1 > resolution.trx0 ?
+      Math.ceil(resolution.trx1 / precinctWidth) -
+      Math.floor(resolution.trx0 / precinctWidth) : 0;
+    var numprecinctshigh = resolution.try1 > resolution.try0 ?
+      Math.ceil(resolution.try1 / precinctHeight) -
+      Math.floor(resolution.try0 / precinctHeight) : 0;
+    var numprecincts = numprecinctswide * numprecinctshigh;
+    var precinctXOffset = Math.floor(resolution.trx0 / precinctWidth) *
+      precinctWidth;
+    var precinctYOffset = Math.floor(resolution.try0 / precinctHeight) *
+      precinctHeight;
+    resolution.precinctParameters = {
+      precinctXOffset: precinctXOffset,
+      precinctYOffset: precinctYOffset,
+      precinctWidth: precinctWidth,
+      precinctHeight: precinctHeight,
+      numprecinctswide: numprecinctswide,
+      numprecinctshigh: numprecinctshigh,
+      numprecincts: numprecincts
+    };
+  }
+  function buildCodeblocks(context, subband, dimensions) {
+    // Section B.7 Division sub-band into code-blocks
+    var xcb_ = dimensions.xcb_;
+    var ycb_ = dimensions.ycb_;
+    var codeblockWidth = 1 << xcb_;
+    var codeblockHeight = 1 << ycb_;
+    var cbx0 = Math.floor(subband.tbx0 / codeblockWidth);
+    var cby0 = Math.floor(subband.tby0 / codeblockHeight);
+    var cbx1 = Math.ceil(subband.tbx1 / codeblockWidth);
+    var cby1 = Math.ceil(subband.tby1 / codeblockHeight);
+    var precinctParameters = subband.resolution.precinctParameters;
+    var codeblocks = [];
+    var precincts = [];
+    for (var j = cby0; j < cby1; j++) {
+      for (var i = cbx0; i < cbx1; i++) {
+        var codeblock = {
+          cbx: i,
+          cby: j,
+          tbx0: codeblockWidth * i,
+          tby0: codeblockHeight * j,
+          tbx1: codeblockWidth * (i + 1),
+          tby1: codeblockHeight * (j + 1)
+        };
+        // calculate precinct number
+        var pi = Math.floor((codeblock.tbx0 -
+          precinctParameters.precinctXOffset) /
+          precinctParameters.precinctWidth);
+        var pj = Math.floor((codeblock.tby0 -
+          precinctParameters.precinctYOffset) /
+          precinctParameters.precinctHeight);
+        var precinctNumber = pj +
+          pi * precinctParameters.numprecinctswide;
+        codeblock.tbx0_ = Math.max(subband.tbx0, codeblock.tbx0);
+        codeblock.tby0_ = Math.max(subband.tby0, codeblock.tby0);
+        codeblock.tbx1_ = Math.min(subband.tbx1, codeblock.tbx1);
+        codeblock.tby1_ = Math.min(subband.tby1, codeblock.tby1);
+        codeblock.precinctNumber = precinctNumber;
+        codeblock.subbandType = subband.type;
+        var coefficientsLength = (codeblock.tbx1_ - codeblock.tbx0_) *
+          (codeblock.tby1_ - codeblock.tby0_);
+        codeblock.Lblock = 3;
+        codeblocks.push(codeblock);
+        // building precinct for the sub-band
+        var precinct;
+        if (precinctNumber in precincts) {
+          precinct = precincts[precinctNumber];
+          precinct.cbxMin = Math.min(precinct.cbxMin, i);
+          precinct.cbyMin = Math.min(precinct.cbyMin, j);
+          precinct.cbxMax = Math.max(precinct.cbxMax, i);
+          precinct.cbyMax = Math.max(precinct.cbyMax, j);
+        } else {
+          precincts[precinctNumber] = precinct = {
+            cbxMin: i,
+            cbyMin: j,
+            cbxMax: i,
+            cbyMax: j
+          };
+        }
+        codeblock.precinct = precinct;
+      }
+    }
+    subband.codeblockParameters = {
+      codeblockWidth: xcb_,
+      codeblockHeight: ycb_,
+      numcodeblockwide: cbx1 - cbx0 + 1,
+      numcodeblockhigh: cby1 - cby1 + 1
+    };
+    subband.codeblocks = codeblocks;
+    for (var i = 0, ii = codeblocks.length; i < ii; i++) {
+      var codeblock = codeblocks[i];
+      var precinctNumber = codeblock.precinctNumber;
+    }
+    subband.precincts = precincts;
+  }
+  function createPacket(resolution, precinctNumber, layerNumber) {
+    var precinctCodeblocks = [];
+    // Section B.10.8 Order of info in packet
+    var subbands = resolution.subbands;
+    // sub-bands already ordered in 'LL', 'HL', 'LH', and 'HH' sequence
+    for (var i = 0, ii = subbands.length; i < ii; i++) {
+      var subband = subbands[i];
+      var codeblocks = subband.codeblocks;
+      for (var j = 0, jj = codeblocks.length; j < jj; j++) {
+        var codeblock = codeblocks[j];
+        if (codeblock.precinctNumber != precinctNumber)
+          continue;
+        precinctCodeblocks.push(codeblock);
+      }
+    }
+    return {
+      layerNumber: layerNumber,
+      codeblocks: precinctCodeblocks
+    };
+  }
+  function LayerResolutionComponentPositionIterator(context) {
+    var siz = context.SIZ;
+    var tileIndex = context.currentTile.index;
+    var tile = context.tiles[tileIndex];
+    var layersCount = tile.codingStyleDefaultParameters.layersCount;
+    var componentsCount = siz.Csiz;
+    var maxDecompositionLevelsCount = 0;
+    for (var q = 0; q < componentsCount; q++) {
+      maxDecompositionLevelsCount = Math.max(maxDecompositionLevelsCount,
+        tile.components[q].codingStyleParameters.decompositionLevelsCount);
+    }
+
+    var l = 0, r = 0, i = 0, k = 0;
+
+    this.nextPacket = function JpxImage_nextPacket() {
+      // Section B.12.1.1 Layer-resolution-component-position
+      for (; l < layersCount; l++) {
+        for (; r <= maxDecompositionLevelsCount; r++) {
+          for (; i < componentsCount; i++) {
+            var component = tile.components[i];
+            if (r > component.codingStyleParameters.decompositionLevelsCount)
+              continue;
+
+            var resolution = component.resolutions[r];
+            var numprecincts = resolution.precinctParameters.numprecincts;
+            for (; k < numprecincts;) {
+              var packet = createPacket(resolution, k, l);
+              k++;
+              return packet;
+            }
+            k = 0;
+          }
+          i = 0;
+        }
+        r = 0;
+      }
+      throw 'Out of packets';
+    };
+  }
+  function ResolutionLayerComponentPositionIterator(context) {
+    var siz = context.SIZ;
+    var tileIndex = context.currentTile.index;
+    var tile = context.tiles[tileIndex];
+    var layersCount = tile.codingStyleDefaultParameters.layersCount;
+    var componentsCount = siz.Csiz;
+    var maxDecompositionLevelsCount = 0;
+    for (var q = 0; q < componentsCount; q++) {
+      maxDecompositionLevelsCount = Math.max(maxDecompositionLevelsCount,
+        tile.components[q].codingStyleParameters.decompositionLevelsCount);
+    }
+
+    var r = 0, l = 0, i = 0, k = 0;
+
+    this.nextPacket = function JpxImage_nextPacket() {
+      // Section B.12.1.2 Resolution-layer-component-position
+      for (; r <= maxDecompositionLevelsCount; r++) {
+        for (; l < layersCount; l++) {
+          for (; i < componentsCount; i++) {
+            var component = tile.components[i];
+            if (r > component.codingStyleParameters.decompositionLevelsCount)
+              continue;
+
+            var resolution = component.resolutions[r];
+            var numprecincts = resolution.precinctParameters.numprecincts;
+            for (; k < numprecincts;) {
+              var packet = createPacket(resolution, k, l);
+              k++;
+              return packet;
+            }
+            k = 0;
+          }
+          i = 0;
+        }
+        l = 0;
+      }
+      throw 'Out of packets';
+    };
+  }
+  function buildPackets(context) {
+    var siz = context.SIZ;
+    var tileIndex = context.currentTile.index;
+    var tile = context.tiles[tileIndex];
+    var componentsCount = siz.Csiz;
+    // Creating resolutions and sub-bands for each component
+    for (var c = 0; c < componentsCount; c++) {
+      var component = tile.components[c];
+      var decompositionLevelsCount =
+        component.codingStyleParameters.decompositionLevelsCount;
+      // Section B.5 Resolution levels and sub-bands
+      var resolutions = [];
+      var subbands = [];
+      for (var r = 0; r <= decompositionLevelsCount; r++) {
+        var blocksDimensions = getBlocksDimensions(context, component, r);
+        var resolution = {};
+        var scale = 1 << (decompositionLevelsCount - r);
+        resolution.trx0 = Math.ceil(component.tcx0 / scale);
+        resolution.try0 = Math.ceil(component.tcy0 / scale);
+        resolution.trx1 = Math.ceil(component.tcx1 / scale);
+        resolution.try1 = Math.ceil(component.tcy1 / scale);
+        buildPrecincts(context, resolution, blocksDimensions);
+        resolutions.push(resolution);
+
+        var subband;
+        if (r == 0) {
+          // one sub-band (LL) with last decomposition
+          subband = {};
+          subband.type = 'LL';
+          subband.tbx0 = Math.ceil(component.tcx0 / scale);
+          subband.tby0 = Math.ceil(component.tcy0 / scale);
+          subband.tbx1 = Math.ceil(component.tcx1 / scale);
+          subband.tby1 = Math.ceil(component.tcy1 / scale);
+          subband.resolution = resolution;
+          buildCodeblocks(context, subband, blocksDimensions);
+          subbands.push(subband);
+          resolution.subbands = [subband];
+        } else {
+          var bscale = 1 << (decompositionLevelsCount - r + 1);
+          var resolutionSubbands = [];
+          // three sub-bands (HL, LH and HH) with rest of decompositions
+          subband = {};
+          subband.type = 'HL';
+          subband.tbx0 = Math.ceil(component.tcx0 / bscale - 0.5);
+          subband.tby0 = Math.ceil(component.tcy0 / bscale);
+          subband.tbx1 = Math.ceil(component.tcx1 / bscale - 0.5);
+          subband.tby1 = Math.ceil(component.tcy1 / bscale);
+          subband.resolution = resolution;
+          buildCodeblocks(context, subband, blocksDimensions);
+          subbands.push(subband);
+          resolutionSubbands.push(subband);
+
+          subband = {};
+          subband.type = 'LH';
+          subband.tbx0 = Math.ceil(component.tcx0 / bscale);
+          subband.tby0 = Math.ceil(component.tcy0 / bscale - 0.5);
+          subband.tbx1 = Math.ceil(component.tcx1 / bscale);
+          subband.tby1 = Math.ceil(component.tcy1 / bscale - 0.5);
+          subband.resolution = resolution;
+          buildCodeblocks(context, subband, blocksDimensions);
+          subbands.push(subband);
+          resolutionSubbands.push(subband);
+
+          subband = {};
+          subband.type = 'HH';
+          subband.tbx0 = Math.ceil(component.tcx0 / bscale - 0.5);
+          subband.tby0 = Math.ceil(component.tcy0 / bscale - 0.5);
+          subband.tbx1 = Math.ceil(component.tcx1 / bscale - 0.5);
+          subband.tby1 = Math.ceil(component.tcy1 / bscale - 0.5);
+          subband.resolution = resolution;
+          buildCodeblocks(context, subband, blocksDimensions);
+          subbands.push(subband);
+          resolutionSubbands.push(subband);
+
+          resolution.subbands = resolutionSubbands;
+        }
+      }
+      component.resolutions = resolutions;
+      component.subbands = subbands;
+    }
+    // Generate the packets sequence
+    var progressionOrder = tile.codingStyleDefaultParameters.progressionOrder;
+    var packetsIterator;
+    switch (progressionOrder) {
+      case 0:
+        tile.packetsIterator =
+          new LayerResolutionComponentPositionIterator(context);
+        break;
+      case 1:
+        tile.packetsIterator =
+          new ResolutionLayerComponentPositionIterator(context);
+        break;
+      default:
+        throw 'Unsupported progression order ' + progressionOrder;
+    }
+  }
+  function parseTilePackets(context, data, offset, dataLength) {
+    var position = 0;
+    var buffer, bufferSize = 0, skipNextBit = false;
+    function readBits(count) {
+      while (bufferSize < count) {
+        var b = data[offset + position];
+        position++;
+        if (skipNextBit) {
+          buffer = (buffer << 7) | b;
+          bufferSize += 7;
+          skipNextBit = false;
+        } else {
+          buffer = (buffer << 8) | b;
+          bufferSize += 8;
+        }
+        if (b == 0xFF) {
+          skipNextBit = true;
+        }
+      }
+      bufferSize -= count;
+      return (buffer >>> bufferSize) & ((1 << count) - 1);
+    }
+    function alignToByte() {
+      bufferSize = 0;
+      if (skipNextBit) {
+        position++;
+        skipNextBit = false;
+      }
+    }
+    function readCodingpasses() {
+      var value = readBits(1);
+      if (value == 0)
+        return 1;
+      value = (value << 1) | readBits(1);
+      if (value == 0x02)
+        return 2;
+      value = (value << 2) | readBits(2);
+      if (value <= 0x0E)
+        return (value & 0x03) + 3;
+      value = (value << 5) | readBits(5);
+      if (value <= 0x1FE)
+        return (value & 0x1F) + 6;
+      value = (value << 7) | readBits(7);
+      return (value & 0x7F) + 37;
+    }
+    var tileIndex = context.currentTile.index;
+    var tile = context.tiles[tileIndex];
+    var packetsIterator = tile.packetsIterator;
+    while (position < dataLength) {
+      var packet = packetsIterator.nextPacket();
+      if (!readBits(1)) {
+        alignToByte();
+        continue;
+      }
+      var layerNumber = packet.layerNumber;
+      var queue = [];
+      for (var i = 0, ii = packet.codeblocks.length; i < ii; i++) {
+        var codeblock = packet.codeblocks[i];
+        var precinct = codeblock.precinct;
+        var codeblockColumn = codeblock.cbx - precinct.cbxMin;
+        var codeblockRow = codeblock.cby - precinct.cbyMin;
+        var codeblockIncluded = false;
+        var firstTimeInclusion = false;
+        if ('included' in codeblock) {
+          codeblockIncluded = !!readBits(1);
+        } else {
+          // reading inclusion tree
+          var precinct = codeblock.precinct;
+          var inclusionTree, zeroBitPlanesTree;
+          if ('inclusionTree' in precinct) {
+            inclusionTree = precinct.inclusionTree;
+          } else {
+            // building inclusion and zero bit-planes trees
+            var width = precinct.cbxMax - precinct.cbxMin + 1;
+            var height = precinct.cbyMax - precinct.cbyMin + 1;
+            inclusionTree = new InclusionTree(width, height, layerNumber);
+            zeroBitPlanesTree = new TagTree(width, height);
+            precinct.inclusionTree = inclusionTree;
+            precinct.zeroBitPlanesTree = zeroBitPlanesTree;
+          }
+
+          if (inclusionTree.reset(codeblockColumn, codeblockRow, layerNumber)) {
+            while (true) {
+              if (readBits(1)) {
+                var valueReady = !inclusionTree.nextLevel();
+                if (valueReady) {
+                  codeblock.included = true;
+                  codeblockIncluded = firstTimeInclusion = true;
+                  break;
+                }
+              } else {
+                inclusionTree.incrementValue(layerNumber);
+                break;
+              }
+            }
+          }
+        }
+        if (!codeblockIncluded)
+          continue;
+        if (firstTimeInclusion) {
+          zeroBitPlanesTree = precinct.zeroBitPlanesTree;
+          zeroBitPlanesTree.reset(codeblockColumn, codeblockRow);
+          while (true) {
+            if (readBits(1)) {
+              var valueReady = !zeroBitPlanesTree.nextLevel();
+              if (valueReady)
+                break;
+            } else
+              zeroBitPlanesTree.incrementValue();
+          }
+          codeblock.zeroBitPlanes = zeroBitPlanesTree.value;
+        }
+        var codingpasses = readCodingpasses();
+        while (readBits(1))
+          codeblock.Lblock++;
+        var codingpassesLog2 = log2(codingpasses);
+        // rounding down log2
+        var bits = ((codingpasses < (1 << codingpassesLog2)) ?
+          codingpassesLog2 - 1 : codingpassesLog2) + codeblock.Lblock;
+        var codedDataLength = readBits(bits);
+        queue.push({
+          codeblock: codeblock,
+          codingpasses: codingpasses,
+          dataLength: codedDataLength
+        });
+      }
+      alignToByte();
+      while (queue.length > 0) {
+        var packetItem = queue.shift();
+        var codeblock = packetItem.codeblock;
+        if (!('data' in codeblock))
+          codeblock.data = [];
+        codeblock.data.push({
+          data: data,
+          start: offset + position,
+          end: offset + position + packetItem.dataLength,
+          codingpasses: packetItem.codingpasses
+        });
+        position += packetItem.dataLength;
+      }
+    }
+    return position;
+  }
+  function copyCoefficients(coefficients, x0, y0, width, height,
+                            delta, mb, codeblocks, transformation) {
+    var r = 0.5; // formula (E-6)
+    for (var i = 0, ii = codeblocks.length; i < ii; ++i) {
+      var codeblock = codeblocks[i];
+      var blockWidth = codeblock.tbx1_ - codeblock.tbx0_;
+      var blockHeight = codeblock.tby1_ - codeblock.tby0_;
+      if (blockWidth == 0 || blockHeight == 0)
+        continue;
+      if (!('data' in codeblock))
+        continue;
+
+      var bitModel, currentCodingpassType;
+      bitModel = new BitModel(blockWidth, blockHeight, codeblock.subbandType,
+        codeblock.zeroBitPlanes);
+      currentCodingpassType = 2; // first bit plane starts from cleanup
+
+      // collect data
+      var data = codeblock.data, totalLength = 0, codingpasses = 0;
+      for (var q = 0, qq = data.length; q < qq; q++) {
+        var dataItem = data[q];
+        totalLength += dataItem.end - dataItem.start;
+        codingpasses += dataItem.codingpasses;
+      }
+      var encodedData = new Uint8Array(totalLength), k = 0;
+      for (var q = 0, qq = data.length; q < qq; q++) {
+        var dataItem = data[q];
+        var chunk = dataItem.data.subarray(dataItem.start, dataItem.end);
+        encodedData.set(chunk, k);
+        k += chunk.length;
+      }
+      // decoding the item
+      var decoder = new ArithmeticDecoder(encodedData, 0, totalLength);
+      bitModel.setDecoder(decoder);
+
+      for (var q = 0; q < codingpasses; q++) {
+        switch (currentCodingpassType) {
+          case 0:
+            bitModel.runSignificancePropogationPass();
+            break;
+          case 1:
+            bitModel.runMagnitudeRefinementPass();
+            break;
+          case 2:
+            bitModel.runCleanupPass();
+            break;
+        }
+        currentCodingpassType = (currentCodingpassType + 1) % 3;
+      }
+
+      var offset = (codeblock.tbx0_ - x0) + (codeblock.tby0_ - y0) * width;
+      var position = 0;
+      for (var j = 0; j < blockHeight; j++) {
+        for (var k = 0; k < blockWidth; k++) {
+          var n = (bitModel.coefficentsSign[position] ? -1 : 1) *
+            bitModel.coefficentsMagnitude[position];
+          var nb = bitModel.bitsDecoded[position], correction;
+          if (transformation == 0 || mb > nb) {
+            // use r only if transformation is irreversible or
+            // not all bitplanes were decoded for reversible transformation
+            n += n < 0 ? n - r : n > 0 ? n + r : 0;
+            correction = 1 << (mb - nb);
+          } else
+            correction = 1;
+          coefficients[offset++] = n * correction * delta;
+          position++;
+        }
+        offset += width - blockWidth;
+      }
+    }
+  }
+  function transformTile(context, tile, c) {
+    var component = tile.components[c];
+    var codingStyleParameters = component.codingStyleParameters;
+    var quantizationParameters = component.quantizationParameters;
+    var decompositionLevelsCount =
+      codingStyleParameters.decompositionLevelsCount;
+    var spqcds = quantizationParameters.SPqcds;
+    var scalarExpounded = quantizationParameters.scalarExpounded;
+    var guardBits = quantizationParameters.guardBits;
+    var transformation = codingStyleParameters.transformation;
+    var precision = context.components[c].precision;
+
+    var subbandCoefficients = [];
+    var k = 0, b = 0;
+    for (var i = 0; i <= decompositionLevelsCount; i++) {
+      var resolution = component.resolutions[i];
+
+      for (var j = 0, jj = resolution.subbands.length; j < jj; j++) {
+        var mu, epsilon;
+        if (!scalarExpounded) {
+          // formula E-5
+          mu = spqcds[0].mu;
+          epsilon = spqcds[0].epsilon + (i > 0 ? 1 - i : 0);
+        } else {
+          mu = spqcds[b].mu;
+          epsilon = spqcds[b].epsilon;
+        }
+
+        var subband = resolution.subbands[j];
+        var width = subband.tbx1 - subband.tbx0;
+        var height = subband.tby1 - subband.tby0;
+        var gainLog2 = SubbandsGainLog2[subband.type];
+
+        // calulate quantization coefficient (Section E.1.1.1)
+        var delta = Math.pow(2, (precision + gainLog2) - epsilon) *
+          (1 + mu / 2048);
+        var mb = (guardBits + epsilon - 1);
+
+        var coefficients = new Float32Array(width * height);
+        copyCoefficients(coefficients, subband.tbx0, subband.tby0,
+          width, height, delta, mb, subband.codeblocks, transformation);
+
+        subbandCoefficients.push({
+          width: width,
+          height: height,
+          items: coefficients
+        });
+
+        b++;
+      }
+    }
+
+    var transformation = codingStyleParameters.transformation;
+    var transform = transformation == 0 ? new IrreversibleTransform() :
+      new ReversibleTransform();
+    var result = transform.calculate(subbandCoefficients,
+      component.tcx0, component.tcy0);
+    return {
+      left: component.tcx0,
+      top: component.tcy0,
+      width: result.width,
+      height: result.height,
+      items: result.items
+    };
+  }
+  function transformComponents(context) {
+    var siz = context.SIZ;
+    var components = context.components;
+    var componentsCount = siz.Csiz;
+    var resultImages = [];
+    for (var i = 0, ii = context.tiles.length; i < ii; i++) {
+      var tile = context.tiles[i];
+      var result = [];
+      for (var c = 0; c < componentsCount; c++) {
+        var image = transformTile(context, tile, c);
+        result.push(image);
+      }
+
+      // Section G.2.2 Inverse multi component transform
+      if (tile.codingStyleDefaultParameters.multipleComponentTransform) {
+        var y0items = result[0].items;
+        var y1items = result[1].items;
+        var y2items = result[2].items;
+        for (var j = 0, jj = y0items.length; j < jj; j++) {
+          var y0 = y0items[j], y1 = y1items[j], y2 = y2items[j];
+          var i1 = y0 - ((y2 + y1) >> 2);
+          y1items[j] = i1;
+          y0items[j] = y2 + i1;
+          y2items[j] = y1 + i1;
+        }
+      }
+
+      // Section G.1 DC level shifting to unsigned component values
+      for (var c = 0; c < componentsCount; c++) {
+        var component = components[c];
+        if (component.isSigned)
+          continue;
+
+        var offset = 1 << (component.precision - 1);
+        var tileImage = result[c];
+        var items = tileImage.items;
+        for (var j = 0, jj = items.length; j < jj; j++)
+          items[j] += offset;
+      }
+
+      // To simplify things: shift and clamp output to 8 bit unsigned
+      for (var c = 0; c < componentsCount; c++) {
+        var component = components[c];
+        var offset = component.isSigned ? 128 : 0;
+        var shift = component.precision - 8;
+        var tileImage = result[c];
+        var items = tileImage.items;
+        var data = new Uint8Array(items.length);
+        for (var j = 0, jj = items.length; j < jj; j++) {
+          var value = (items[j] >> shift) + offset;
+          data[j] = value < 0 ? 0 : value > 255 ? 255 : value;
+        }
+        result[c].items = data;
+      }
+
+      resultImages.push(result);
+    }
+    return resultImages;
+  }
+  function initializeTile(context, tileIndex) {
+    var siz = context.SIZ;
+    var componentsCount = siz.Csiz;
+    var tile = context.tiles[tileIndex];
+    var resultTiles = [];
+    for (var c = 0; c < componentsCount; c++) {
+      var component = tile.components[c];
+      var qcdOrQcc = c in context.currentTile.QCC ?
+        context.currentTile.QCC[c] : context.currentTile.QCD;
+      component.quantizationParameters = qcdOrQcc;
+      var codOrCoc = c in context.currentTile.COC ?
+        context.currentTile.COC[c] : context.currentTile.COD;
+      component.codingStyleParameters = codOrCoc;
+    }
+    tile.codingStyleDefaultParameters = context.currentTile.COD;
+  }
+
+  // Section B.10.2 Tag trees
+  var TagTree = (function TagTreeClosure() {
+    function TagTree(width, height) {
+      var levelsLength = log2(Math.max(width, height)) + 1;
+      this.levels = [];
+      for (var i = 0; i < levelsLength; i++) {
+        var level = {
+          width: width,
+          height: height,
+          items: []
+        };
+        this.levels.push(level);
+        width = Math.ceil(width / 2);
+        height = Math.ceil(height / 2);
+      }
+    }
+    TagTree.prototype = {
+      reset: function TagTree_reset(i, j) {
+        var currentLevel = 0, value = 0;
+        while (currentLevel < this.levels.length) {
+          var level = this.levels[currentLevel];
+          var index = i + j * level.width;
+          if (index in level.items) {
+            value = level.items[index];
+            break;
+          }
+          level.index = index;
+          i >>= 1;
+          j >>= 1;
+          currentLevel++;
+        }
+        currentLevel--;
+        var level = this.levels[currentLevel];
+        level.items[level.index] = value;
+        this.currentLevel = currentLevel;
+        delete this.value;
+      },
+      incrementValue: function TagTree_incrementValue() {
+        var level = this.levels[this.currentLevel];
+        level.items[level.index]++;
+      },
+      nextLevel: function TagTree_nextLevel() {
+        var currentLevel = this.currentLevel;
+        var level = this.levels[currentLevel];
+        var value = level.items[level.index];
+        currentLevel--;
+        if (currentLevel < 0) {
+          this.value = value;
+          return false;
+        }
+
+        this.currentLevel = currentLevel;
+        var level = this.levels[currentLevel];
+        level.items[level.index] = value;
+        return true;
+      }
+    };
+    return TagTree;
+  })();
+
+  var InclusionTree = (function InclusionTreeClosure() {
+    function InclusionTree(width, height,  defaultValue) {
+      var levelsLength = log2(Math.max(width, height)) + 1;
+      this.levels = [];
+      for (var i = 0; i < levelsLength; i++) {
+        var items = new Uint8Array(width * height);
+        for (var j = 0, jj = items.length; j < jj; j++)
+          items[j] = defaultValue;
+
+        var level = {
+          width: width,
+          height: height,
+          items: items
+        };
+        this.levels.push(level);
+
+        width = Math.ceil(width / 2);
+        height = Math.ceil(height / 2);
+      }
+    }
+    InclusionTree.prototype = {
+      reset: function InclusionTree_reset(i, j, stopValue) {
+        var currentLevel = 0;
+        while (currentLevel < this.levels.length) {
+          var level = this.levels[currentLevel];
+          var index = i + j * level.width;
+          level.index = index;
+          var value = level.items[index];
+
+          if (value == 0xFF)
+            break;
+
+          if (value > stopValue) {
+            this.currentLevel = currentLevel;
+            // already know about this one, propagating the value to top levels
+            this.propagateValues();
+            return false;
+          }
+
+          i >>= 1;
+          j >>= 1;
+          currentLevel++;
+        }
+        this.currentLevel = currentLevel - 1;
+        return true;
+      },
+      incrementValue: function InclusionTree_incrementValue(stopValue) {
+        var level = this.levels[this.currentLevel];
+        level.items[level.index] = stopValue + 1;
+        this.propagateValues();
+      },
+      propagateValues: function InclusionTree_propagateValues() {
+        var levelIndex = this.currentLevel;
+        var level = this.levels[levelIndex];
+        var currentValue = level.items[level.index];
+        while (--levelIndex >= 0) {
+          var level = this.levels[levelIndex];
+          level.items[level.index] = currentValue;
+        }
+      },
+      nextLevel: function InclusionTree_nextLevel() {
+        var currentLevel = this.currentLevel;
+        var level = this.levels[currentLevel];
+        var value = level.items[level.index];
+        level.items[level.index] = 0xFF;
+        currentLevel--;
+        if (currentLevel < 0)
+          return false;
+
+        this.currentLevel = currentLevel;
+        var level = this.levels[currentLevel];
+        level.items[level.index] = value;
+        return true;
+      }
+    };
+    return InclusionTree;
+  })();
+
+  // Implements C.3. Arithmetic decoding procedures
+  var ArithmeticDecoder = (function ArithmeticDecoderClosure() {
+    var QeTable = [
+      {qe: 0x5601, nmps: 1, nlps: 1, switchFlag: 1},
+      {qe: 0x3401, nmps: 2, nlps: 6, switchFlag: 0},
+      {qe: 0x1801, nmps: 3, nlps: 9, switchFlag: 0},
+      {qe: 0x0AC1, nmps: 4, nlps: 12, switchFlag: 0},
+      {qe: 0x0521, nmps: 5, nlps: 29, switchFlag: 0},
+      {qe: 0x0221, nmps: 38, nlps: 33, switchFlag: 0},
+      {qe: 0x5601, nmps: 7, nlps: 6, switchFlag: 1},
+      {qe: 0x5401, nmps: 8, nlps: 14, switchFlag: 0},
+      {qe: 0x4801, nmps: 9, nlps: 14, switchFlag: 0},
+      {qe: 0x3801, nmps: 10, nlps: 14, switchFlag: 0},
+      {qe: 0x3001, nmps: 11, nlps: 17, switchFlag: 0},
+      {qe: 0x2401, nmps: 12, nlps: 18, switchFlag: 0},
+      {qe: 0x1C01, nmps: 13, nlps: 20, switchFlag: 0},
+      {qe: 0x1601, nmps: 29, nlps: 21, switchFlag: 0},
+      {qe: 0x5601, nmps: 15, nlps: 14, switchFlag: 1},
+      {qe: 0x5401, nmps: 16, nlps: 14, switchFlag: 0},
+      {qe: 0x5101, nmps: 17, nlps: 15, switchFlag: 0},
+      {qe: 0x4801, nmps: 18, nlps: 16, switchFlag: 0},
+      {qe: 0x3801, nmps: 19, nlps: 17, switchFlag: 0},
+      {qe: 0x3401, nmps: 20, nlps: 18, switchFlag: 0},
+      {qe: 0x3001, nmps: 21, nlps: 19, switchFlag: 0},
+      {qe: 0x2801, nmps: 22, nlps: 19, switchFlag: 0},
+      {qe: 0x2401, nmps: 23, nlps: 20, switchFlag: 0},
+      {qe: 0x2201, nmps: 24, nlps: 21, switchFlag: 0},
+      {qe: 0x1C01, nmps: 25, nlps: 22, switchFlag: 0},
+      {qe: 0x1801, nmps: 26, nlps: 23, switchFlag: 0},
+      {qe: 0x1601, nmps: 27, nlps: 24, switchFlag: 0},
+      {qe: 0x1401, nmps: 28, nlps: 25, switchFlag: 0},
+      {qe: 0x1201, nmps: 29, nlps: 26, switchFlag: 0},
+      {qe: 0x1101, nmps: 30, nlps: 27, switchFlag: 0},
+      {qe: 0x0AC1, nmps: 31, nlps: 28, switchFlag: 0},
+      {qe: 0x09C1, nmps: 32, nlps: 29, switchFlag: 0},
+      {qe: 0x08A1, nmps: 33, nlps: 30, switchFlag: 0},
+      {qe: 0x0521, nmps: 34, nlps: 31, switchFlag: 0},
+      {qe: 0x0441, nmps: 35, nlps: 32, switchFlag: 0},
+      {qe: 0x02A1, nmps: 36, nlps: 33, switchFlag: 0},
+      {qe: 0x0221, nmps: 37, nlps: 34, switchFlag: 0},
+      {qe: 0x0141, nmps: 38, nlps: 35, switchFlag: 0},
+      {qe: 0x0111, nmps: 39, nlps: 36, switchFlag: 0},
+      {qe: 0x0085, nmps: 40, nlps: 37, switchFlag: 0},
+      {qe: 0x0049, nmps: 41, nlps: 38, switchFlag: 0},
+      {qe: 0x0025, nmps: 42, nlps: 39, switchFlag: 0},
+      {qe: 0x0015, nmps: 43, nlps: 40, switchFlag: 0},
+      {qe: 0x0009, nmps: 44, nlps: 41, switchFlag: 0},
+      {qe: 0x0005, nmps: 45, nlps: 42, switchFlag: 0},
+      {qe: 0x0001, nmps: 45, nlps: 43, switchFlag: 0},
+      {qe: 0x5601, nmps: 46, nlps: 46, switchFlag: 0}
+    ];
+
+    function ArithmeticDecoder(data, start, end) {
+      this.data = data;
+      this.bp = start;
+      this.dataEnd = end;
+
+      this.chigh = data[start];
+      this.clow = 0;
+
+      this.byteIn();
+
+      this.chigh = ((this.chigh << 7) & 0xFFFF) | ((this.clow >> 9) & 0x7F);
+      this.clow = (this.clow << 7) & 0xFFFF;
+      this.ct -= 7;
+      this.a = 0x8000;
+    }
+
+    ArithmeticDecoder.prototype = {
+      byteIn: function ArithmeticDecoder_byteIn() {
+        var data = this.data;
+        var bp = this.bp;
+        if (data[bp] == 0xFF) {
+          var b1 = data[bp + 1];
+          if (b1 > 0x8F) {
+            this.clow += 0xFF00;
+            this.ct = 8;
+          } else {
+            bp++;
+            this.clow += (data[bp] << 9);
+            this.ct = 7;
+            this.bp = bp;
+          }
+        } else {
+          bp++;
+          this.clow += bp < this.dataEnd ? (data[bp] << 8) : 0xFF00;
+          this.ct = 8;
+          this.bp = bp;
+        }
+        if (this.clow > 0xFFFF) {
+          this.chigh += (this.clow >> 16);
+          this.clow &= 0xFFFF;
+        }
+      },
+      readBit: function ArithmeticDecoder_readBit(cx) {
+        var qeIcx = QeTable[cx.index].qe;
+        this.a -= qeIcx;
+
+        if (this.chigh < qeIcx) {
+          var d = this.exchangeLps(cx);
+          this.renormD();
+          return d;
+        } else {
+          this.chigh -= qeIcx;
+          if ((this.a & 0x8000) == 0) {
+            var d = this.exchangeMps(cx);
+            this.renormD();
+            return d;
+          } else {
+            return cx.mps;
+          }
+        }
+      },
+      renormD: function ArithmeticDecoder_renormD() {
+        do {
+          if (this.ct == 0)
+            this.byteIn();
+
+          this.a <<= 1;
+          this.chigh = ((this.chigh << 1) & 0xFFFF) | ((this.clow >> 15) & 1);
+          this.clow = (this.clow << 1) & 0xFFFF;
+          this.ct--;
+        } while ((this.a & 0x8000) == 0);
+      },
+      exchangeMps: function ArithmeticDecoder_exchangeMps(cx) {
+        var d;
+        var qeTableIcx = QeTable[cx.index];
+        if (this.a < qeTableIcx.qe) {
+          d = 1 - cx.mps;
+
+          if (qeTableIcx.switchFlag == 1) {
+            cx.mps = 1 - cx.mps;
+          }
+          cx.index = qeTableIcx.nlps;
+        } else {
+          d = cx.mps;
+          cx.index = qeTableIcx.nmps;
+        }
+        return d;
+      },
+      exchangeLps: function ArithmeticDecoder_exchangeLps(cx) {
+        var d;
+        var qeTableIcx = QeTable[cx.index];
+        if (this.a < qeTableIcx.qe) {
+          this.a = qeTableIcx.qe;
+          d = cx.mps;
+          cx.index = qeTableIcx.nmps;
+        } else {
+          this.a = qeTableIcx.qe;
+          d = 1 - cx.mps;
+
+          if (qeTableIcx.switchFlag == 1) {
+            cx.mps = 1 - cx.mps;
+          }
+          cx.index = qeTableIcx.nlps;
+        }
+        return d;
+      }
+    };
+
+    return ArithmeticDecoder;
+  })();
+
+  // Section D. Coefficient bit modeling
+  var BitModel = (function BitModelClosure() {
+    // Table D-1
+    // The index is binary presentation: 0dddvvhh, ddd - sum of Di (0..4),
+    // vv - sum of Vi (0..2), and hh - sum of Hi (0..2)
+    var LLAndLHContextsLabel = new Uint8Array([
+      0, 5, 8, 0, 3, 7, 8, 0, 4, 7, 8, 0, 0, 0, 0, 0, 1, 6, 8, 0, 3, 7, 8, 0, 4,
+      7, 8, 0, 0, 0, 0, 0, 2, 6, 8, 0, 3, 7, 8, 0, 4, 7, 8, 0, 0, 0, 0, 0, 2, 6,
+      8, 0, 3, 7, 8, 0, 4, 7, 8, 0, 0, 0, 0, 0, 2, 6, 8, 0, 3, 7, 8, 0, 4, 7, 8
+    ]);
+    var HLContextLabel = new Uint8Array([
+      0, 3, 4, 0, 5, 7, 7, 0, 8, 8, 8, 0, 0, 0, 0, 0, 1, 3, 4, 0, 6, 7, 7, 0, 8,
+      8, 8, 0, 0, 0, 0, 0, 2, 3, 4, 0, 6, 7, 7, 0, 8, 8, 8, 0, 0, 0, 0, 0, 2, 3,
+      4, 0, 6, 7, 7, 0, 8, 8, 8, 0, 0, 0, 0, 0, 2, 3, 4, 0, 6, 7, 7, 0, 8, 8, 8
+    ]);
+    var HHContextLabel = new Uint8Array([
+      0, 1, 2, 0, 1, 2, 2, 0, 2, 2, 2, 0, 0, 0, 0, 0, 3, 4, 5, 0, 4, 5, 5, 0, 5,
+      5, 5, 0, 0, 0, 0, 0, 6, 7, 7, 0, 7, 7, 7, 0, 7, 7, 7, 0, 0, 0, 0, 0, 8, 8,
+      8, 0, 8, 8, 8, 0, 8, 8, 8, 0, 0, 0, 0, 0, 8, 8, 8, 0, 8, 8, 8, 0, 8, 8, 8
+    ]);
+
+    // Table D-2
+    function calcSignContribution(significance0, sign0, significance1, sign1) {
+      if (significance1) {
+        if (!sign1)
+          return significance0 ? (!sign0 ? 1 : 0) : 1;
+        else
+          return significance0 ? (!sign0 ? 0 : -1) : -1;
+      } else
+        return significance0 ? (!sign0 ? 1 : -1) : 0;
+    }
+    // Table D-3
+    var SignContextLabels = [
+      {contextLabel: 13, xorBit: 0},
+      {contextLabel: 12, xorBit: 0},
+      {contextLabel: 11, xorBit: 0},
+      {contextLabel: 10, xorBit: 0},
+      {contextLabel: 9, xorBit: 0},
+      {contextLabel: 10, xorBit: 1},
+      {contextLabel: 11, xorBit: 1},
+      {contextLabel: 12, xorBit: 1},
+      {contextLabel: 13, xorBit: 1}
+    ];
+
+    function BitModel(width, height, subband, zeroBitPlanes) {
+      this.width = width;
+      this.height = height;
+
+      this.contextLabelTable = subband == 'HH' ? HHContextLabel :
+        subband == 'HL' ? HLContextLabel : LLAndLHContextsLabel;
+
+      var coefficientCount = width * height;
+
+      // coefficients outside the encoding region treated as insignificant
+      // add border state cells for significanceState
+      this.neighborsSignificance = new Uint8Array(coefficientCount);
+      this.coefficentsSign = new Uint8Array(coefficientCount);
+      this.coefficentsMagnitude = new Uint32Array(coefficientCount);
+      this.processingFlags = new Uint8Array(coefficientCount);
+
+      var bitsDecoded = new Uint8Array(this.width * this.height);
+      for (var i = 0, ii = bitsDecoded.length; i < ii; i++)
+        bitsDecoded[i] = zeroBitPlanes;
+      this.bitsDecoded = bitsDecoded;
+
+      this.reset();
+    }
+
+    BitModel.prototype = {
+      setDecoder: function BitModel_setDecoder(decoder) {
+        this.decoder = decoder;
+      },
+      reset: function BitModel_reset() {
+        this.uniformContext = {index: 46, mps: 0};
+        this.runLengthContext = {index: 3, mps: 0};
+        this.contexts = [];
+        this.contexts.push({index: 4, mps: 0});
+        for (var i = 1; i <= 16; i++)
+          this.contexts.push({index: 0, mps: 0});
+      },
+      setNeighborsSignificance:
+        function BitModel_setNeighborsSignificance(row, column) {
+        var neighborsSignificance = this.neighborsSignificance;
+        var width = this.width, height = this.height;
+        var index = row * width + column;
+        if (row > 0) {
+          if (column > 0)
+            neighborsSignificance[index - width - 1] += 0x10;
+          if (column + 1 < width)
+            neighborsSignificance[index - width + 1] += 0x10;
+          neighborsSignificance[index - width] += 0x04;
+        }
+        if (row + 1 < height) {
+          if (column > 0)
+            neighborsSignificance[index + width - 1] += 0x10;
+          if (column + 1 < width)
+            neighborsSignificance[index + width + 1] += 0x10;
+          neighborsSignificance[index + width] += 0x04;
+        }
+        if (column > 0)
+          neighborsSignificance[index - 1] += 0x01;
+        if (column + 1 < width)
+          neighborsSignificance[index + 1] += 0x01;
+        neighborsSignificance[index] |= 0x80;
+      },
+      runSignificancePropogationPass:
+        function BitModel_runSignificancePropogationPass() {
+        var decoder = this.decoder;
+        var width = this.width, height = this.height;
+        var coefficentsMagnitude = this.coefficentsMagnitude;
+        var coefficentsSign = this.coefficentsSign;
+        var contextLabels = this.contextLabels;
+        var neighborsSignificance = this.neighborsSignificance;
+        var processingFlags = this.processingFlags;
+        var contexts = this.contexts;
+        var labels = this.contextLabelTable;
+        var bitsDecoded = this.bitsDecoded;
+        // clear processed flag
+        var processedInverseMask = ~1;
+        var processedMask = 1;
+        var firstMagnitudeBitMask = 2;
+        for (var q = 0, qq = width * height; q < qq; q++)
+          processingFlags[q] &= processedInverseMask;
+
+        for (var i0 = 0; i0 < height; i0 += 4) {
+          for (var j = 0; j < width; j++) {
+            var index = i0 * width + j;
+            for (var i1 = 0; i1 < 4; i1++, index += width) {
+              var i = i0 + i1;
+              if (i >= height)
+                break;
+
+              if (coefficentsMagnitude[index] || !neighborsSignificance[index])
+                continue;
+
+              var contextLabel = labels[neighborsSignificance[index]];
+              var cx = contexts[contextLabel];
+              var decision = decoder.readBit(cx);
+              if (decision) {
+                var sign = this.decodeSignBit(i, j);
+                coefficentsSign[index] = sign;
+                coefficentsMagnitude[index] = 1;
+                this.setNeighborsSignificance(i, j);
+                processingFlags[index] |= firstMagnitudeBitMask;
+              }
+              bitsDecoded[index]++;
+              processingFlags[index] |= processedMask;
+            }
+          }
+        }
+      },
+      decodeSignBit: function BitModel_decodeSignBit(row, column) {
+        var width = this.width, height = this.height;
+        var index = row * width + column;
+        var coefficentsMagnitude = this.coefficentsMagnitude;
+        var coefficentsSign = this.coefficentsSign;
+        var horizontalContribution = calcSignContribution(
+          column > 0 && coefficentsMagnitude[index - 1],
+          coefficentsSign[index - 1],
+          column + 1 < width && coefficentsMagnitude[index + 1],
+          coefficentsSign[index + 1]);
+        var verticalContribution = calcSignContribution(
+          row > 0 && coefficentsMagnitude[index - width],
+          coefficentsSign[index - width],
+          row + 1 < height && coefficentsMagnitude[index + width],
+          coefficentsSign[index + width]);
+
+        var contextLabelAndXor = SignContextLabels[
+          3 * (1 - horizontalContribution) + (1 - verticalContribution)];
+        var contextLabel = contextLabelAndXor.contextLabel;
+        var cx = this.contexts[contextLabel];
+        var decoded = this.decoder.readBit(cx);
+        return decoded ^ contextLabelAndXor.xorBit;
+      },
+      runMagnitudeRefinementPass:
+        function BitModel_runMagnitudeRefinementPass() {
+        var decoder = this.decoder;
+        var width = this.width, height = this.height;
+        var coefficentsMagnitude = this.coefficentsMagnitude;
+        var neighborsSignificance = this.neighborsSignificance;
+        var contexts = this.contexts;
+        var bitsDecoded = this.bitsDecoded;
+        var processingFlags = this.processingFlags;
+        var processedMask = 1;
+        var firstMagnitudeBitMask = 2;
+        for (var i0 = 0; i0 < height; i0 += 4) {
+          for (var j = 0; j < width; j++) {
+            for (var i1 = 0; i1 < 4; i1++) {
+              var i = i0 + i1;
+              if (i >= height)
+                break;
+              var index = i * width + j;
+
+              // significant but not those that have just become
+              if (!coefficentsMagnitude[index] ||
+                (processingFlags[index] & processedMask) != 0)
+                continue;
+
+              var contextLabel = 16;
+              if ((processingFlags[index] &
+                firstMagnitudeBitMask) != 0) {
+                processingFlags[i * width + j] ^= firstMagnitudeBitMask;
+                // first refinement
+                var significance = neighborsSignificance[index];
+                var sumOfSignificance = (significance & 3) +
+                  ((significance >> 2) & 3) + ((significance >> 4) & 7);
+                contextLabel = sumOfSignificance >= 1 ? 15 : 14;
+              }
+
+              var cx = contexts[contextLabel];
+              var bit = decoder.readBit(cx);
+              coefficentsMagnitude[index] =
+                (coefficentsMagnitude[index] << 1) | bit;
+              bitsDecoded[index]++;
+              processingFlags[index] |= processedMask;
+            }
+          }
+        }
+      },
+      runCleanupPass: function BitModel_runCleanupPass() {
+        var decoder = this.decoder;
+        var width = this.width, height = this.height;
+        var neighborsSignificance = this.neighborsSignificance;
+        var significanceState = this.significanceState;
+        var coefficentsMagnitude = this.coefficentsMagnitude;
+        var coefficentsSign = this.coefficentsSign;
+        var contexts = this.contexts;
+        var labels = this.contextLabelTable;
+        var bitsDecoded = this.bitsDecoded;
+        var processingFlags = this.processingFlags;
+        var processedMask = 1;
+        var firstMagnitudeBitMask = 2;
+        var oneRowDown = width;
+        var twoRowsDown = width * 2;
+        var threeRowsDown = width * 3;
+        for (var i0 = 0; i0 < height; i0 += 4) {
+          for (var j = 0; j < width; j++) {
+            var index0 = i0 * width + j;
+            // using the property: labels[neighborsSignificance[index]] == 0
+            // when neighborsSignificance[index] == 0
+            var allEmpty = i0 + 3 < height &&
+              processingFlags[index0] == 0 &&
+              processingFlags[index0 + oneRowDown] == 0 &&
+              processingFlags[index0 + twoRowsDown] == 0 &&
+              processingFlags[index0 + threeRowsDown] == 0 &&
+              neighborsSignificance[index0] == 0 &&
+              neighborsSignificance[index0 + oneRowDown] == 0 &&
+              neighborsSignificance[index0 + twoRowsDown] == 0 &&
+              neighborsSignificance[index0 + threeRowsDown] == 0;
+            var i1 = 0, index = index0;
+            var cx, i;
+            if (allEmpty) {
+              cx = this.runLengthContext;
+              var hasSignificantCoefficent = decoder.readBit(cx);
+              if (!hasSignificantCoefficent) {
+                bitsDecoded[index0]++;
+                bitsDecoded[index0 + oneRowDown]++;
+                bitsDecoded[index0 + twoRowsDown]++;
+                bitsDecoded[index0 + threeRowsDown]++;
+                continue; // next column
+              }
+              cx = this.uniformContext;
+              i1 = (decoder.readBit(cx) << 1) | decoder.readBit(cx);
+              i = i0 + i1;
+              index += i1 * width;
+
+              var sign = this.decodeSignBit(i, j);
+              coefficentsSign[index] = sign;
+              coefficentsMagnitude[index] = 1;
+              this.setNeighborsSignificance(i, j);
+              processingFlags[index] |= firstMagnitudeBitMask;
+
+              index = index0;
+              for (var i2 = i0; i2 <= i; i2++, index += width)
+                bitsDecoded[index]++;
+
+              i1++;
+            }
+            for (; i1 < 4; i1++, index += width) {
+              i = i0 + i1;
+              if (i >= height)
+                break;
+
+              if (coefficentsMagnitude[index] ||
+                (processingFlags[index] & processedMask) != 0)
+                continue;
+
+              var contextLabel = labels[neighborsSignificance[index]];
+              cx = contexts[contextLabel];
+              var decision = decoder.readBit(cx);
+              if (decision == 1) {
+                var sign = this.decodeSignBit(i, j);
+                coefficentsSign[index] = sign;
+                coefficentsMagnitude[index] = 1;
+                this.setNeighborsSignificance(i, j);
+                processingFlags[index] |= firstMagnitudeBitMask;
+              }
+              bitsDecoded[index]++;
+            }
+          }
+        }
+      }
+    };
+
+    return BitModel;
+  })();
+
+  // Section F, Discrete wavelet transofrmation
+  var Transform = (function TransformClosure() {
+    function Transform() {
+    }
+    Transform.prototype.calculate =
+      function transformCalculate(subbands, u0, v0) {
+      var ll = subbands[0];
+      for (var i = 1, ii = subbands.length, j = 1; i < ii; i += 3, j++) {
+        ll = this.iterate(ll, subbands[i], subbands[i + 1],
+                          subbands[i + 2], u0, v0);
+      }
+      return ll;
+    };
+    Transform.prototype.iterate = function Transform_iterate(ll, hl, lh, hh,
+                                                            u0, v0) {
+      var llWidth = ll.width, llHeight = ll.height, llItems = ll.items;
+      var hlWidth = hl.width, hlHeight = hl.height, hlItems = hl.items;
+      var lhWidth = lh.width, lhHeight = lh.height, lhItems = lh.items;
+      var hhWidth = hh.width, hhHeight = hh.height, hhItems = hh.items;
+
+      // Section F.3.3 interleave
+      var width = llWidth + hlWidth;
+      var height = llHeight + lhHeight;
+      var items = new Float32Array(width * height);
+      for (var i = 0, ii = llHeight; i < ii; i++) {
+        var k = i * llWidth, l = i * 2 * width;
+        for (var j = 0, jj = llWidth; j < jj; j++, k++, l += 2)
+          items[l] = llItems[k];
+      }
+      for (var i = 0, ii = hlHeight; i < ii; i++) {
+        var k = i * hlWidth, l = i * 2 * width + 1;
+        for (var j = 0, jj = hlWidth; j < jj; j++, k++, l += 2)
+          items[l] = hlItems[k];
+      }
+      for (var i = 0, ii = lhHeight; i < ii; i++) {
+        var k = i * lhWidth, l = (i * 2 + 1) * width;
+        for (var j = 0, jj = lhWidth; j < jj; j++, k++, l += 2)
+          items[l] = lhItems[k];
+      }
+      for (var i = 0, ii = hhHeight; i < ii; i++) {
+        var k = i * hhWidth, l = (i * 2 + 1) * width + 1;
+        for (var j = 0, jj = hhWidth; j < jj; j++, k++, l += 2)
+          items[l] = hhItems[k];
+      }
+
+      var bufferPadding = 4;
+      var bufferLength = new Float32Array(Math.max(width, height) +
+        2 * bufferPadding);
+      var buffer = new Float32Array(bufferLength);
+      var bufferOut = new Float32Array(bufferLength);
+
+      // Section F.3.4 HOR_SR
+      for (var v = 0; v < height; v++) {
+        if (width == 1) {
+          // if width = 1, when u0 even keep items as is, when odd divide by 2
+          if ((u0 % 1) != 0) {
+            items[v * width] /= 2;
+          }
+          continue;
+        }
+
+        var k = v * width;
+        var l = bufferPadding;
+        for (var u = 0; u < width; u++, k++, l++)
+          buffer[l] = items[k];
+
+        // Section F.3.7 extending... using max extension of 4
+        var i1 = bufferPadding - 1, j1 = bufferPadding + 1;
+        var i2 = bufferPadding + width - 2, j2 = bufferPadding + width;
+        buffer[i1--] = buffer[j1++];
+        buffer[j2++] = buffer[i2--];
+        buffer[i1--] = buffer[j1++];
+        buffer[j2++] = buffer[i2--];
+        buffer[i1--] = buffer[j1++];
+        buffer[j2++] = buffer[i2--];
+        buffer[i1--] = buffer[j1++];
+        buffer[j2++] = buffer[i2--];
+
+        this.filter(buffer, bufferPadding, width, u0, bufferOut);
+
+        k = v * width;
+        l = bufferPadding;
+        for (var u = 0; u < width; u++, k++, l++)
+          items[k] = bufferOut[l];
+      }
+
+      // Section F.3.5 VER_SR
+      for (var u = 0; u < width; u++) {
+        if (height == 1) {
+          // if height = 1, when v0 even keep items as is, when odd divide by 2
+          if ((v0 % 1) != 0) {
+            items[u] /= 2;
+          }
+          continue;
+        }
+
+        var k = u;
+        var l = bufferPadding;
+        for (var v = 0; v < height; v++, k += width, l++)
+          buffer[l] = items[k];
+
+        // Section F.3.7 extending... using max extension of 4
+        var i1 = bufferPadding - 1, j1 = bufferPadding + 1;
+        var i2 = bufferPadding + height - 2, j2 = bufferPadding + height;
+        buffer[i1--] = buffer[j1++];
+        buffer[j2++] = buffer[i2--];
+        buffer[i1--] = buffer[j1++];
+        buffer[j2++] = buffer[i2--];
+        buffer[i1--] = buffer[j1++];
+        buffer[j2++] = buffer[i2--];
+        buffer[i1--] = buffer[j1++];
+        buffer[j2++] = buffer[i2--];
+
+        this.filter(buffer, bufferPadding, height, v0, bufferOut);
+
+        k = u;
+        l = bufferPadding;
+        for (var v = 0; v < height; v++, k += width, l++)
+          items[k] = bufferOut[l];
+      }
+      return {
+        width: width,
+        height: height,
+        items: items
+      };
+    };
+    return Transform;
+  })();
+
+  // Section 3.8.2 Irreversible 9-7 filter
+  var IrreversibleTransform = (function IrreversibleTransformClosure() {
+    function IrreversibleTransform() {
+      Transform.call(this);
+    }
+
+    IrreversibleTransform.prototype = Object.create(Transform.prototype);
+    IrreversibleTransform.prototype.filter =
+      function irreversibleTransformFilter(y, offset, length, i0, x) {
+      var i0_ = Math.floor(i0 / 2);
+      var i1_ = Math.floor((i0 + length) / 2);
+      var offset_ = offset - (i0 % 1);
+
+      var alpha = -1.586134342059924;
+      var beta = -0.052980118572961;
+      var gamma = 0.882911075530934;
+      var delta = 0.443506852043971;
+      var K = 1.230174104914001;
+      var K_ = 1 / K;
+
+      // step 1
+      var j = offset_ - 2;
+      for (var n = i0_ - 1, nn = i1_ + 2; n < nn; n++, j += 2)
+        x[j] = K * y[j];
+
+      // step 2
+      var j = offset_ - 3;
+      for (var n = i0_ - 2, nn = i1_ + 2; n < nn; n++, j += 2)
+        x[j] = K_ * y[j];
+
+      // step 3
+      var j = offset_ - 2;
+      for (var n = i0_ - 1, nn = i1_ + 2; n < nn; n++, j += 2)
+        x[j] -= delta * (x[j - 1] + x[j + 1]);
+
+      // step 4
+      var j = offset_ - 1;
+      for (var n = i0_ - 1, nn = i1_ + 1; n < nn; n++, j += 2)
+        x[j] -= gamma * (x[j - 1] + x[j + 1]);
+
+      // step 5
+      var j = offset_;
+      for (var n = i0_, nn = i1_ + 1; n < nn; n++, j += 2)
+        x[j] -= beta * (x[j - 1] + x[j + 1]);
+
+      // step 6
+      var j = offset_ + 1;
+      for (var n = i0_, nn = i1_; n < nn; n++, j += 2)
+        x[j] -= alpha * (x[j - 1] + x[j + 1]);
+    };
+
+    return IrreversibleTransform;
+  })();
+
+  // Section 3.8.1 Reversible 5-3 filter
+  var ReversibleTransform = (function ReversibleTransformClosure() {
+    function ReversibleTransform() {
+      Transform.call(this);
+    }
+
+    ReversibleTransform.prototype = Object.create(Transform.prototype);
+    ReversibleTransform.prototype.filter =
+      function reversibleTransformFilter(y, offset, length, i0, x) {
+      var i0_ = Math.floor(i0 / 2);
+      var i1_ = Math.floor((i0 + length) / 2);
+      var offset_ = offset - (i0 % 1);
+
+      for (var n = i0_, nn = i1_ + 1, j = offset_; n < nn; n++, j += 2)
+        x[j] = y[j] - Math.floor((y[j - 1] + y[j + 1] + 2) / 4);
+
+      for (var n = i0_, nn = i1_, j = offset_ + 1; n < nn; n++, j += 2)
+        x[j] = y[j] + Math.floor((x[j - 1] + x[j + 1]) / 2);
+    };
+
+    return ReversibleTransform;
+  })();
+
+  return JpxImage;
+})();
+
diff --git a/apps/files_pdfviewer/js/pdfjs/src/metadata.js b/apps/files_pdfviewer/js/pdfjs/src/metadata.js
new file mode 100644
index 0000000000000000000000000000000000000000..f3805616866b8070abc9745c907d2ea2fa7c28c9
--- /dev/null
+++ b/apps/files_pdfviewer/js/pdfjs/src/metadata.js
@@ -0,0 +1,66 @@
+/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
+
+'use strict';
+
+var Metadata = PDFJS.Metadata = (function MetadataClosure() {
+  function Metadata(meta) {
+    if (typeof meta === 'string') {
+      var parser = new DOMParser();
+      meta = parser.parseFromString(meta, 'application/xml');
+    } else if (!(meta instanceof Document)) {
+      error('Metadata: Invalid metadata object');
+    }
+
+    this.metaDocument = meta;
+    this.metadata = {};
+    this.parse();
+  }
+
+  Metadata.prototype = {
+    parse: function Metadata_parse() {
+      var doc = this.metaDocument;
+      var rdf = doc.documentElement;
+
+      if (rdf.nodeName.toLowerCase() !== 'rdf:rdf') { // Wrapped in <xmpmeta>
+        rdf = rdf.firstChild;
+        while (rdf && rdf.nodeName.toLowerCase() !== 'rdf:rdf')
+          rdf = rdf.nextSibling;
+      }
+
+      var nodeName = (rdf) ? rdf.nodeName.toLowerCase() : null;
+      if (!rdf || nodeName !== 'rdf:rdf' || !rdf.hasChildNodes())
+        return;
+
+      var childNodes = rdf.childNodes, desc, namespace, entries, entry;
+
+      for (var i = 0, length = childNodes.length; i < length; i++) {
+        desc = childNodes[i];
+        if (desc.nodeName.toLowerCase() !== 'rdf:description')
+          continue;
+
+        entries = [];
+        for (var ii = 0, iLength = desc.childNodes.length; ii < iLength; ii++) {
+          if (desc.childNodes[ii].nodeName.toLowerCase() !== '#text')
+            entries.push(desc.childNodes[ii]);
+        }
+
+        for (ii = 0, iLength = entries.length; ii < iLength; ii++) {
+          var entry = entries[ii];
+          var name = entry.nodeName.toLowerCase();
+          this.metadata[name] = entry.textContent.trim();
+        }
+      }
+    },
+
+    get: function Metadata_get(name) {
+      return this.metadata[name] || null;
+    },
+
+    has: function Metadata_has(name) {
+      return typeof this.metadata[name] !== 'undefined';
+    }
+  };
+
+  return Metadata;
+})();
diff --git a/apps/files_pdfviewer/js/pdfjs/src/metrics.js b/apps/files_pdfviewer/js/pdfjs/src/metrics.js
old mode 100755
new mode 100644
index c21b4aed1ceaaf6553be76659b8b8f190a1d26c2..e64961aa78a9b1c454d0af52a5af3b5eae7d3a64
--- a/apps/files_pdfviewer/js/pdfjs/src/metrics.js
+++ b/apps/files_pdfviewer/js/pdfjs/src/metrics.js
@@ -3,6 +3,9 @@
 
 'use strict';
 
+// The Metrics object contains glyph widths (in glyph space units).
+// As per PDF spec, for most fonts (Type 3 being an exception) a glyph
+// space unit corresponds to 1/1000th of text space unit.
 var Metrics = {
   'Courier': 600,
   'Courier-Bold': 600,
diff --git a/apps/files_pdfviewer/js/pdfjs/src/obj.js b/apps/files_pdfviewer/js/pdfjs/src/obj.js
old mode 100755
new mode 100644
index 7aebb732ad2af81010471addd1efeaa4cba991c6..200b40a7f9823cb2d30af5958fd31be276f4884b
--- a/apps/files_pdfviewer/js/pdfjs/src/obj.js
+++ b/apps/files_pdfviewer/js/pdfjs/src/obj.js
@@ -3,121 +3,157 @@
 
 'use strict';
 
-var Name = (function nameName() {
-  function constructor(name) {
+var Name = (function NameClosure() {
+  function Name(name) {
     this.name = name;
   }
 
-  constructor.prototype = {
-  };
+  Name.prototype = {};
 
-  return constructor;
+  return Name;
 })();
 
-var Cmd = (function cmdCmd() {
-  function constructor(cmd) {
+var Cmd = (function CmdClosure() {
+  function Cmd(cmd) {
     this.cmd = cmd;
   }
 
-  constructor.prototype = {
+  Cmd.prototype = {};
+
+  var cmdCache = {};
+
+  Cmd.get = function Cmd_get(cmd) {
+    var cmdValue = cmdCache[cmd];
+    if (cmdValue)
+      return cmdValue;
+
+    return cmdCache[cmd] = new Cmd(cmd);
   };
 
-  return constructor;
+  return Cmd;
 })();
 
-var Dict = (function dictDict() {
-  function constructor() {
+var Dict = (function DictClosure() {
+  // xref is optional
+  function Dict(xref) {
+    // Map should only be used internally, use functions below to access.
     this.map = Object.create(null);
+    this.xref = xref;
   }
 
-  constructor.prototype = {
-    get: function dictGet(key1, key2, key3) {
+  Dict.prototype = {
+    // automatically dereferences Ref objects
+    get: function Dict_get(key1, key2, key3) {
       var value;
+      var xref = this.xref;
       if (typeof (value = this.map[key1]) != 'undefined' || key1 in this.map ||
           typeof key2 == 'undefined') {
-        return value;
+        return xref ? this.xref.fetchIfRef(value) : value;
       }
       if (typeof (value = this.map[key2]) != 'undefined' || key2 in this.map ||
           typeof key3 == 'undefined') {
-        return value;
+        return xref ? this.xref.fetchIfRef(value) : value;
       }
-
-      return this.map[key3] || null;
+      value = this.map[key3] || null;
+      return xref ? this.xref.fetchIfRef(value) : value;
+    },
+    // no dereferencing
+    getRaw: function Dict_getRaw(key) {
+      return this.map[key];
+    },
+    // creates new map and dereferences all Refs
+    getAll: function Dict_getAll() {
+      var all = {};
+      for (var key in this.map)
+        all[key] = this.get(key);
+      return all;
     },
 
-    set: function dictSet(key, value) {
+    set: function Dict_set(key, value) {
       this.map[key] = value;
     },
 
-    has: function dictHas(key) {
+    has: function Dict_has(key) {
       return key in this.map;
     },
 
-    forEach: function dictForEach(callback) {
+    forEach: function Dict_forEach(callback) {
       for (var key in this.map) {
-        callback(key, this.map[key]);
+        callback(key, this.get(key));
       }
     }
   };
 
-  return constructor;
+  return Dict;
 })();
 
-var Ref = (function refRef() {
-  function constructor(num, gen) {
+var Ref = (function RefClosure() {
+  function Ref(num, gen) {
     this.num = num;
     this.gen = gen;
   }
 
-  constructor.prototype = {
-  };
+  Ref.prototype = {};
 
-  return constructor;
+  return Ref;
 })();
 
 // The reference is identified by number and generation,
 // this structure stores only one instance of the reference.
-var RefSet = (function refSet() {
-  function constructor() {
+var RefSet = (function RefSetClosure() {
+  function RefSet() {
     this.dict = {};
   }
 
-  constructor.prototype = {
-    has: function refSetHas(ref) {
+  RefSet.prototype = {
+    has: function RefSet_has(ref) {
       return !!this.dict['R' + ref.num + '.' + ref.gen];
     },
 
-    put: function refSetPut(ref) {
+    put: function RefSet_put(ref) {
       this.dict['R' + ref.num + '.' + ref.gen] = ref;
     }
   };
 
-  return constructor;
+  return RefSet;
 })();
 
-var Catalog = (function catalogCatalog() {
-  function constructor(xref) {
+var Catalog = (function CatalogClosure() {
+  function Catalog(xref) {
     this.xref = xref;
     var obj = xref.getCatalogObj();
     assertWellFormed(isDict(obj), 'catalog object is not a dictionary');
     this.catDict = obj;
   }
 
-  constructor.prototype = {
+  Catalog.prototype = {
+    get metadata() {
+      var stream = this.catDict.get('Metadata');
+      var metadata;
+      if (stream && isDict(stream.dict)) {
+        var type = stream.dict.get('Type');
+        var subtype = stream.dict.get('Subtype');
+
+        if (isName(type) && isName(subtype) &&
+            type.name === 'Metadata' && subtype.name === 'XML') {
+          metadata = stringToPDFString(bytesToString(stream.getBytes()));
+        }
+      }
+
+      return shadow(this, 'metadata', metadata);
+    },
     get toplevelPagesDict() {
       var pagesObj = this.catDict.get('Pages');
-      assertWellFormed(isRef(pagesObj), 'invalid top-level pages reference');
-      var xrefObj = this.xref.fetch(pagesObj);
-      assertWellFormed(isDict(xrefObj), 'invalid top-level pages dictionary');
+      assertWellFormed(isDict(pagesObj), 'invalid top-level pages dictionary');
       // shadow the prototype getter
-      return shadow(this, 'toplevelPagesDict', xrefObj);
+      return shadow(this, 'toplevelPagesDict', pagesObj);
     },
     get documentOutline() {
-      var obj = this.catDict.get('Outlines');
       var xref = this.xref;
+      var obj = this.catDict.get('Outlines');
       var root = { items: [] };
-      if (isRef(obj)) {
-        obj = xref.fetch(obj).get('First');
+      if (isDict(obj)) {
+        obj = obj.getRaw('First');
         var processed = new RefSet();
         if (isRef(obj)) {
           var queue = [{obj: obj, parent: root}];
@@ -126,18 +162,20 @@ var Catalog = (function catalogCatalog() {
           processed.put(obj);
           while (queue.length > 0) {
             var i = queue.shift();
-            var outlineDict = xref.fetch(i.obj);
+            var outlineDict = xref.fetchIfRef(i.obj);
+            if (outlineDict === null)
+              continue;
             if (!outlineDict.has('Title'))
               error('Invalid outline item');
             var dest = outlineDict.get('A');
             if (dest)
-              dest = xref.fetchIfRef(dest).get('D');
+              dest = dest.get('D');
             else if (outlineDict.has('Dest')) {
-              dest = outlineDict.get('Dest');
+              dest = outlineDict.getRaw('Dest');
               if (isName(dest))
                 dest = dest.name;
             }
-            var title = xref.fetchIfRef(outlineDict.get('Title'));
+            var title = outlineDict.get('Title');
             var outlineItem = {
               dest: dest,
               title: stringToPDFString(title),
@@ -148,12 +186,12 @@ var Catalog = (function catalogCatalog() {
               items: []
             };
             i.parent.items.push(outlineItem);
-            obj = outlineDict.get('First');
+            obj = outlineDict.getRaw('First');
             if (isRef(obj) && !processed.has(obj)) {
               queue.push({obj: obj, parent: outlineItem});
               processed.put(obj);
             }
-            obj = outlineDict.get('Next');
+            obj = outlineDict.getRaw('Next');
             if (isRef(obj) && !processed.has(obj)) {
               queue.push({obj: obj, parent: i.parent});
               processed.put(obj);
@@ -173,7 +211,7 @@ var Catalog = (function catalogCatalog() {
       // shadow the prototype getter
       return shadow(this, 'num', obj);
     },
-    traverseKids: function catalogTraverseKids(pagesDict) {
+    traverseKids: function Catalog_traverseKids(pagesDict) {
       var pageCache = this.pageCache;
       var kids = pagesDict.get('Kids');
       assertWellFormed(isArray(kids),
@@ -181,7 +219,7 @@ var Catalog = (function catalogCatalog() {
       for (var i = 0, ii = kids.length; i < ii; ++i) {
         var kid = kids[i];
         assertWellFormed(isRef(kid),
-                         'page dictionary kid is not a reference');
+                        'page dictionary kid is not a reference');
         var obj = this.xref.fetch(kid);
         if (isDict(obj, 'Page') || (isDict(obj) && !obj.has('Kids'))) {
           pageCache.push(new Page(this.xref, pageCache.length, obj, kid));
@@ -195,8 +233,7 @@ var Catalog = (function catalogCatalog() {
       }
     },
     get destinations() {
-      function fetchDestination(xref, ref) {
-        var dest = xref.fetchIfRef(ref);
+      function fetchDestination(dest) {
         return isDict(dest) ? dest.get('D') : dest;
       }
 
@@ -204,16 +241,16 @@ var Catalog = (function catalogCatalog() {
       var dests = {}, nameTreeRef, nameDictionaryRef;
       var obj = this.catDict.get('Names');
       if (obj)
-        nameTreeRef = xref.fetchIfRef(obj).get('Dests');
+        nameTreeRef = obj.getRaw('Dests');
       else if (this.catDict.has('Dests'))
         nameDictionaryRef = this.catDict.get('Dests');
 
       if (nameDictionaryRef) {
         // reading simple destination dictionary
-        obj = xref.fetchIfRef(nameDictionaryRef);
+        obj = nameDictionaryRef;
         obj.forEach(function catalogForEach(key, value) {
           if (!value) return;
-          dests[key] = fetchDestination(xref, value);
+          dests[key] = fetchDestination(value);
         });
       }
       if (nameTreeRef) {
@@ -237,13 +274,13 @@ var Catalog = (function catalogCatalog() {
           }
           var names = obj.get('Names');
           for (i = 0, n = names.length; i < n; i += 2) {
-            dests[names[i]] = fetchDestination(xref, names[i + 1]);
+            dests[names[i]] = fetchDestination(xref.fetchIfRef(names[i + 1]));
           }
         }
       }
       return shadow(this, 'destinations', dests);
     },
-    getPage: function catalogGetPage(n) {
+    getPage: function Catalog_getPage(n) {
       var pageCache = this.pageCache;
       if (!pageCache) {
         pageCache = this.pageCache = [];
@@ -253,105 +290,101 @@ var Catalog = (function catalogCatalog() {
     }
   };
 
-  return constructor;
+  return Catalog;
 })();
 
-var XRef = (function xRefXRef() {
-  function constructor(stream, startXRef, mainXRefEntriesOffset) {
+var XRef = (function XRefClosure() {
+  function XRef(stream, startXRef, mainXRefEntriesOffset) {
     this.stream = stream;
     this.entries = [];
     this.xrefstms = {};
     var trailerDict = this.readXRef(startXRef);
-
+    trailerDict.xref = this;
+    this.trailer = trailerDict;
     // prepare the XRef cache
     this.cache = [];
 
     var encrypt = trailerDict.get('Encrypt');
     if (encrypt) {
       var fileId = trailerDict.get('ID');
-      this.encrypt = new CipherTransformFactory(this.fetch(encrypt),
+      this.encrypt = new CipherTransformFactory(encrypt,
                                                 fileId[0] /*, password */);
     }
 
     // get the root dictionary (catalog) object
-    if (!isRef(this.root = trailerDict.get('Root')))
+    if (!(this.root = trailerDict.get('Root')))
       error('Invalid root reference');
   }
 
-  constructor.prototype = {
-    readXRefTable: function readXRefTable(parser) {
+  XRef.prototype = {
+    readXRefTable: function XRef_readXRefTable(parser) {
+      // Example of cross-reference table:
+      // xref
+      // 0 1                    <-- subsection header (first obj #, obj count)
+      // 0000000000 65535 f     <-- actual object (offset, generation #, f/n)
+      // 23 2                   <-- subsection header ... and so on ...
+      // 0000025518 00002 n
+      // 0000025635 00000 n
+      // trailer
+      // ...
+
+      // Outer loop is over subsection headers
       var obj;
-      while (true) {
-        if (isCmd(obj = parser.getObj(), 'trailer'))
-          break;
-        if (!isInt(obj))
-          error('Invalid XRef table');
-        var first = obj;
-        if (!isInt(obj = parser.getObj()))
-          error('Invalid XRef table');
-        var n = obj;
-        if (first < 0 || n < 0 || (first + n) != ((first + n) | 0))
-          error('Invalid XRef table: ' + first + ', ' + n);
-        for (var i = first; i < first + n; ++i) {
+      while (!isCmd(obj = parser.getObj(), 'trailer')) {
+        var first = obj,
+            count = parser.getObj();
+
+        if (!isInt(first) || !isInt(count))
+          error('Invalid XRef table: wrong types in subsection header');
+
+        // Inner loop is over objects themselves
+        for (var i = 0; i < count; i++) {
           var entry = {};
-          if (!isInt(obj = parser.getObj()))
-            error('Invalid XRef table: ' + first + ', ' + n);
-          entry.offset = obj;
-          if (!isInt(obj = parser.getObj()))
-            error('Invalid XRef table: ' + first + ', ' + n);
-          entry.gen = obj;
-          obj = parser.getObj();
-          if (isCmd(obj, 'n')) {
-            entry.uncompressed = true;
-          } else if (isCmd(obj, 'f')) {
+          entry.offset = parser.getObj();
+          entry.gen = parser.getObj();
+          var type = parser.getObj();
+
+          if (isCmd(type, 'f'))
             entry.free = true;
-          } else {
-            error('Invalid XRef table: ' + first + ', ' + n);
-          }
-          if (!this.entries[i]) {
-            // In some buggy PDF files the xref table claims to start at 1
-            // instead of 0.
-            if (i == 1 && first == 1 &&
-                entry.offset == 0 && entry.gen == 65535 && entry.free) {
-              i = first = 0;
-            }
-            this.entries[i] = entry;
-          }
-        }
-      }
+          else if (isCmd(type, 'n'))
+            entry.uncompressed = true;
 
-      // read the trailer dictionary
-      var dict;
-      if (!isDict(dict = parser.getObj()))
-        error('Invalid XRef table');
-
-      // get the 'Prev' pointer
-      var prev;
-      obj = dict.get('Prev');
-      if (isInt(obj)) {
-        prev = obj;
-      } else if (isRef(obj)) {
-        // certain buggy PDF generators generate "/Prev NNN 0 R" instead
-        // of "/Prev NNN"
-        prev = obj.num;
-      }
-      if (prev) {
-        this.readXRef(prev);
-      }
+          // Validate entry obj
+          if (!isInt(entry.offset) || !isInt(entry.gen) ||
+              !(entry.free || entry.uncompressed)) {
+            error('Invalid entry in XRef subsection: ' + first + ', ' + count);
+          }
 
-      // check for 'XRefStm' key
-      if (isInt(obj = dict.get('XRefStm'))) {
-        var pos = obj;
-        // ignore previously loaded xref streams (possible infinite recursion)
-        if (!(pos in this.xrefstms)) {
-          this.xrefstms[pos] = 1;
-          this.readXRef(pos);
+          if (!this.entries[i + first])
+            this.entries[i + first] = entry;
         }
       }
 
+      // Sanity check: as per spec, first object must have these properties
+      if (this.entries[0] &&
+          !(this.entries[0].gen === 65535 && this.entries[0].free))
+        error('Invalid XRef table: unexpected first object');
+
+      // Sanity check
+      if (!isCmd(obj, 'trailer'))
+        error('Invalid XRef table: could not find trailer dictionary');
+
+      // Read trailer dictionary, e.g.
+      // trailer
+      //    << /Size 22
+      //      /Root 20R
+      //      /Info 10R
+      //      /ID [ <81b14aafa313db63dbd6f981e49f94f4> ]
+      //    >>
+      // The parser goes through the entire stream << ... >> and provides
+      // a getter interface for the key-value table
+      var dict = parser.getObj();
+      if (!isDict(dict))
+        error('Invalid XRef table: could not parse trailer dictionary');
+
       return dict;
     },
-    readXRefStream: function readXRefStream(stream) {
+    readXRefStream: function XRef_readXRefStream(stream) {
       var streamParameters = stream.parameters;
       var byteWidths = streamParameters.get('W');
       var range = streamParameters.get('Index');
@@ -400,12 +433,9 @@ var XRef = (function xRefXRef() {
         }
         range.splice(0, 2);
       }
-      var prev = streamParameters.get('Prev');
-      if (isInt(prev))
-        this.readXRef(prev);
       return streamParameters;
     },
-    indexObjects: function indexObjects() {
+    indexObjects: function XRef_indexObjects() {
       // Simple scan through the PDF content to find objects,
       // trailers and XRef streams.
       function readToken(data, offset) {
@@ -497,7 +527,7 @@ var XRef = (function xRefXRef() {
       var dict;
       for (var i = 0, ii = trailers.length; i < ii; ++i) {
         stream.pos = trailers[i];
-        var parser = new Parser(new Lexer(stream), true);
+        var parser = new Parser(new Lexer(stream), true, null);
         var obj = parser.getObj();
         if (!isCmd(obj, 'trailer'))
           continue;
@@ -513,50 +543,88 @@ var XRef = (function xRefXRef() {
         return dict;
       // nothing helps
       error('Invalid PDF structure');
-      return null;
     },
-    readXRef: function readXref(startXRef) {
+    readXRef: function XRef_readXRef(startXRef) {
       var stream = this.stream;
       stream.pos = startXRef;
-      var parser = new Parser(new Lexer(stream), true);
-      var obj = parser.getObj();
-      // parse an old-style xref table
-      if (isCmd(obj, 'xref'))
-        return this.readXRefTable(parser);
-      // parse an xref stream
-      if (isInt(obj)) {
-        if (!isInt(parser.getObj()) ||
-            !isCmd(parser.getObj(), 'obj') ||
-            !isStream(obj = parser.getObj())) {
-          error('Invalid XRef stream');
+
+      try {
+        var parser = new Parser(new Lexer(stream), true, null);
+        var obj = parser.getObj();
+        var dict;
+
+        // Get dictionary
+        if (isCmd(obj, 'xref')) {
+          // Parse end-of-file XRef
+          dict = this.readXRefTable(parser);
+
+          // Recursively get other XRefs 'XRefStm', if any
+          obj = dict.get('XRefStm');
+          if (isInt(obj)) {
+            var pos = obj;
+            // ignore previously loaded xref streams
+            // (possible infinite recursion)
+            if (!(pos in this.xrefstms)) {
+              this.xrefstms[pos] = 1;
+              this.readXRef(pos);
+            }
+          }
+        } else if (isInt(obj)) {
+          // Parse in-stream XRef
+          if (!isInt(parser.getObj()) ||
+              !isCmd(parser.getObj(), 'obj') ||
+              !isStream(obj = parser.getObj())) {
+            error('Invalid XRef stream');
+          }
+          dict = this.readXRefStream(obj);
+        }
+
+        // Recursively get previous dictionary, if any
+        obj = dict.get('Prev');
+        if (isInt(obj))
+          this.readXRef(obj);
+        else if (isRef(obj)) {
+          // The spec says Prev must not be a reference, i.e. "/Prev NNN"
+          // This is a fallback for non-compliant PDFs, i.e. "/Prev NNN 0 R"
+          this.readXRef(obj.num);
         }
-        return this.readXRefStream(obj);
+
+        return dict;
+      } catch (e) {
+        log('(while reading XRef): ' + e);
       }
+
+      warn('Indexing all PDF objects');
       return this.indexObjects();
     },
-    getEntry: function xRefGetEntry(i) {
+    getEntry: function XRef_getEntry(i) {
       var e = this.entries[i];
-      if (e.free)
-        error('reading an XRef stream not implemented yet');
-      return e;
+      if (e === null)
+        return null;
+      return e.free ? null : e; // returns null is the entry is free
     },
-    fetchIfRef: function xRefFetchIfRef(obj) {
+    fetchIfRef: function XRef_fetchIfRef(obj) {
       if (!isRef(obj))
         return obj;
       return this.fetch(obj);
     },
-    fetch: function xRefFetch(ref, suppressEncryption) {
+    fetch: function XRef_fetch(ref, suppressEncryption) {
+      assertWellFormed(isRef(ref), 'ref object is not a reference');
       var num = ref.num;
-      var e = this.cache[num];
-      if (e)
-        return e;
+      if (num in this.cache)
+        return this.cache[num];
+
+      var e = this.getEntry(num);
+
+      // the referenced entry can be free
+      if (e === null)
+        return (this.cache[num] = e);
 
-      e = this.getEntry(num);
       var gen = ref.gen;
       var stream, parser;
       if (e.uncompressed) {
         if (e.gen != gen)
-          throw ('inconsistent generation in XRef');
+          error('inconsistent generation in XRef');
         stream = this.stream.makeSubStream(e.offset);
         parser = new Parser(new Lexer(stream), true, this);
         var obj1 = parser.getObj();
@@ -589,7 +657,7 @@ var XRef = (function xRefXRef() {
           e = parser.getObj();
         }
         // Don't cache streams since they are mutable (except images).
-        if (!isStream(e) || e.getImage)
+        if (!isStream(e) || e instanceof JpegStream)
           this.cache[num] = e;
         return e;
       }
@@ -603,7 +671,7 @@ var XRef = (function xRefXRef() {
       if (!isInt(first) || !isInt(n)) {
         error('invalid first and n parameters for ObjStm stream');
       }
-      parser = new Parser(new Lexer(stream), false);
+      parser = new Parser(new Lexer(stream), false, this);
       var i, entries = [], nums = [];
       // read the object numbers to populate cache
       for (i = 0; i < n; ++i) {
@@ -628,12 +696,12 @@ var XRef = (function xRefXRef() {
       }
       return e;
     },
-    getCatalogObj: function xRefGetCatalogObj() {
-      return this.fetch(this.root);
+    getCatalogObj: function XRef_getCatalogObj() {
+      return this.root;
     }
   };
 
-  return constructor;
+  return XRef;
 })();
 
 /**
@@ -642,7 +710,7 @@ var XRef = (function xRefXRef() {
  * inside of a worker. The `PDFObjects` implements some basic functions to
  * manage these objects.
  */
-var PDFObjects = (function pdfObjects() {
+var PDFObjects = (function PDFObjectsClosure() {
   function PDFObjects() {
     this.objs = {};
   }
@@ -655,7 +723,7 @@ var PDFObjects = (function pdfObjects() {
      * Ensures there is an object defined for `objId`. Stores `data` on the
      * object *if* it is created.
      */
-    ensureObj: function pdfObjectsEnsureObj(objId, data) {
+    ensureObj: function PDFObjects_ensureObj(objId, data) {
       if (this.objs[objId])
         return this.objs[objId];
       return this.objs[objId] = new Promise(objId, data);
@@ -670,7 +738,7 @@ var PDFObjects = (function pdfObjects() {
      * function and the object is already resolved, the callback gets called
      * right away.
      */
-    get: function pdfObjectsGet(objId, callback) {
+    get: function PDFObjects_get(objId, callback) {
       // If there is a callback, then the get can be async and the object is
       // not required to be resolved right now
       if (callback) {
@@ -684,18 +752,16 @@ var PDFObjects = (function pdfObjects() {
 
       // If there isn't an object yet or the object isn't resolved, then the
       // data isn't ready yet!
-      if (!obj || !obj.isResolved) {
-        throw 'Requesting object that isn\'t resolved yet ' + objId;
-        return null;
-      } else {
-        return obj.data;
-      }
+      if (!obj || !obj.isResolved)
+        error('Requesting object that isn\'t resolved yet ' + objId);
+
+      return obj.data;
     },
 
     /**
      * Resolves the object `objId` with optional `data`.
      */
-    resolve: function pdfObjectsResolve(objId, data) {
+    resolve: function PDFObjects_resolve(objId, data) {
       var objs = this.objs;
 
       // In case there is a promise already on this object, just resolve it.
@@ -706,11 +772,11 @@ var PDFObjects = (function pdfObjects() {
       }
     },
 
-    onData: function pdfObjectsOnData(objId, callback) {
+    onData: function PDFObjects_onData(objId, callback) {
       this.ensureObj(objId).onData(callback);
     },
 
-    isResolved: function pdfObjectsIsResolved(objId) {
+    isResolved: function PDFObjects_isResolved(objId) {
       var objs = this.objs;
       if (!objs[objId]) {
         return false;
@@ -719,7 +785,7 @@ var PDFObjects = (function pdfObjects() {
       }
     },
 
-    hasData: function pdfObjectsHasData(objId) {
+    hasData: function PDFObjects_hasData(objId) {
       var objs = this.objs;
       if (!objs[objId]) {
         return false;
@@ -731,7 +797,7 @@ var PDFObjects = (function pdfObjects() {
     /**
      * Sets the data of an object but *doesn't* resolve it.
      */
-    setData: function pdfObjectsSetData(objId, data) {
+    setData: function PDFObjects_setData(objId, data) {
       // Watchout! If you call `this.ensureObj(objId, data)` you're going to
       // create a *resolved* promise which shouldn't be the case!
       this.ensureObj(objId).data = data;
diff --git a/apps/files_pdfviewer/js/pdfjs/src/parser.js b/apps/files_pdfviewer/js/pdfjs/src/parser.js
old mode 100755
new mode 100644
index 93a3f21b52a74755bce05a1020fbb39c9bf79124..1c50d0f5f95ac0bc06969644fb478a29e90c45c2
--- a/apps/files_pdfviewer/js/pdfjs/src/parser.js
+++ b/apps/files_pdfviewer/js/pdfjs/src/parser.js
@@ -9,8 +9,8 @@ function isEOF(v) {
   return v == EOF;
 }
 
-var Parser = (function parserParser() {
-  function constructor(lexer, allowStreams, xref) {
+var Parser = (function ParserClosure() {
+  function Parser(lexer, allowStreams, xref) {
     this.lexer = lexer;
     this.allowStreams = allowStreams;
     this.xref = xref;
@@ -18,12 +18,12 @@ var Parser = (function parserParser() {
     this.refill();
   }
 
-  constructor.prototype = {
-    refill: function parserRefill() {
+  Parser.prototype = {
+    refill: function Parser_refill() {
       this.buf1 = this.lexer.getObj();
       this.buf2 = this.lexer.getObj();
     },
-    shift: function parserShift() {
+    shift: function Parser_shift() {
       if (isCmd(this.buf2, 'ID')) {
         this.buf1 = this.buf2;
         this.buf2 = null;
@@ -34,7 +34,7 @@ var Parser = (function parserParser() {
         this.buf2 = this.lexer.getObj();
       }
     },
-    getObj: function parserGetObj(cipherTransform) {
+    getObj: function Parser_getObj(cipherTransform) {
       if (isCmd(this.buf1, 'BI')) { // inline image
         this.shift();
         return this.makeInlineImage(cipherTransform);
@@ -51,17 +51,16 @@ var Parser = (function parserParser() {
       }
       if (isCmd(this.buf1, '<<')) { // dictionary or stream
         this.shift();
-        var dict = new Dict();
+        var dict = new Dict(this.xref);
         while (!isCmd(this.buf1, '>>') && !isEOF(this.buf1)) {
-          if (!isName(this.buf1)) {
+          if (!isName(this.buf1))
             error('Dictionary key must be a name object');
-          } else {
-            var key = this.buf1.name;
-            this.shift();
-            if (isEOF(this.buf1))
-              break;
-            dict.set(key, this.getObj(cipherTransform));
-          }
+
+          var key = this.buf1.name;
+          this.shift();
+          if (isEOF(this.buf1))
+            break;
+          dict.set(key, this.getObj(cipherTransform));
         }
         if (isEOF(this.buf1))
           error('End of file inside dictionary');
@@ -99,38 +98,37 @@ var Parser = (function parserParser() {
       this.shift();
       return obj;
     },
-    makeInlineImage: function parserMakeInlineImage(cipherTransform) {
+    makeInlineImage: function Parser_makeInlineImage(cipherTransform) {
       var lexer = this.lexer;
       var stream = lexer.stream;
 
       // parse dictionary
       var dict = new Dict();
       while (!isCmd(this.buf1, 'ID') && !isEOF(this.buf1)) {
-        if (!isName(this.buf1)) {
+        if (!isName(this.buf1))
           error('Dictionary key must be a name object');
-        } else {
-          var key = this.buf1.name;
-          this.shift();
-          if (isEOF(this.buf1))
-            break;
-          dict.set(key, this.getObj(cipherTransform));
-        }
+
+        var key = this.buf1.name;
+        this.shift();
+        if (isEOF(this.buf1))
+          break;
+        dict.set(key, this.getObj(cipherTransform));
       }
 
       // parse image stream
       var startPos = stream.pos;
 
-      // searching for the /\sEI\s/
+      // searching for the /EI\s/
       var state = 0, ch;
       while (state != 4 && (ch = stream.getByte()) != null) {
         switch (ch) {
           case 0x20:
           case 0x0D:
           case 0x0A:
-            state = state === 3 ? 4 : 1;
+            state = state === 3 ? 4 : 0;
             break;
           case 0x45:
-            state = state === 1 ? 2 : 0;
+            state = 2;
             break;
           case 0x49:
             state = state === 2 ? 3 : 0;
@@ -157,12 +155,16 @@ var Parser = (function parserParser() {
       imageStream = this.filter(imageStream, dict, length);
       imageStream.parameters = dict;
 
-      this.buf2 = new Cmd('EI');
+      this.buf2 = Cmd.get('EI');
       this.shift();
 
       return imageStream;
     },
-    makeStream: function parserMakeStream(dict, cipherTransform) {
+    fetchIfRef: function Parser_fetchIfRef(obj) {
+      // not relying on the xref.fetchIfRef -- xref might not be set
+      return isRef(obj) ? this.xref.fetch(obj) : obj;
+    },
+    makeStream: function Parser_makeStream(dict, cipherTransform) {
       var lexer = this.lexer;
       var stream = lexer.stream;
 
@@ -171,14 +173,9 @@ var Parser = (function parserParser() {
       var pos = stream.pos;
 
       // get length
-      var length = dict.get('Length');
-      var xref = this.xref;
-      if (xref)
-        length = xref.fetchIfRef(length);
-      if (!isInt(length)) {
+      var length = this.fetchIfRef(dict.get('Length'));
+      if (!isInt(length))
         error('Bad ' + length + ' attribute in stream');
-        length = 0;
-      }
 
       // skip over the stream data
       stream.pos = pos + length;
@@ -195,9 +192,9 @@ var Parser = (function parserParser() {
       stream.parameters = dict;
       return stream;
     },
-    filter: function parserFilter(stream, dict, length) {
-      var filter = dict.get('Filter', 'F');
-      var params = dict.get('DecodeParms', 'DP');
+    filter: function Parser_filter(stream, dict, length) {
+      var filter = this.fetchIfRef(dict.get('Filter', 'F'));
+      var params = this.fetchIfRef(dict.get('DecodeParms', 'DP'));
       if (isName(filter))
         return this.makeFilter(stream, filter.name, length, params);
       if (isArray(filter)) {
@@ -207,25 +204,25 @@ var Parser = (function parserParser() {
           filter = filterArray[i];
           if (!isName(filter))
             error('Bad filter name: ' + filter);
-          else {
-            params = null;
-            if (isArray(paramsArray) && (i in paramsArray))
-              params = paramsArray[i];
-            stream = this.makeFilter(stream, filter.name, length, params);
-            // after the first stream the length variable is invalid
-            length = null;
-          }
+
+          params = null;
+          if (isArray(paramsArray) && (i in paramsArray))
+            params = paramsArray[i];
+          stream = this.makeFilter(stream, filter.name, length, params);
+          // after the first stream the length variable is invalid
+          length = null;
         }
       }
       return stream;
     },
-    makeFilter: function parserMakeFilter(stream, name, length, params) {
+    makeFilter: function Parser_makeFilter(stream, name, length, params) {
       if (name == 'FlateDecode' || name == 'Fl') {
         if (params) {
           return new PredictorStream(new FlateStream(stream), params);
         }
         return new FlateStream(stream);
-      } else if (name == 'LZWDecode' || name == 'LZW') {
+      }
+      if (name == 'LZWDecode' || name == 'LZW') {
         var earlyChange = 1;
         if (params) {
           if (params.has('EarlyChange'))
@@ -234,31 +231,41 @@ var Parser = (function parserParser() {
             new LZWStream(stream, earlyChange), params);
         }
         return new LZWStream(stream, earlyChange);
-      } else if (name == 'DCTDecode' || name == 'DCT') {
+      }
+      if (name == 'DCTDecode' || name == 'DCT') {
         var bytes = stream.getBytes(length);
         return new JpegStream(bytes, stream.dict, this.xref);
-      } else if (name == 'ASCII85Decode' || name == 'A85') {
+      }
+      if (name == 'JPXDecode' || name == 'JPX') {
+        var bytes = stream.getBytes(length);
+        return new JpxStream(bytes, stream.dict);
+      }
+      if (name == 'ASCII85Decode' || name == 'A85') {
         return new Ascii85Stream(stream);
-      } else if (name == 'ASCIIHexDecode' || name == 'AHx') {
+      }
+      if (name == 'ASCIIHexDecode' || name == 'AHx') {
         return new AsciiHexStream(stream);
-      } else if (name == 'CCITTFaxDecode' || name == 'CCF') {
+      }
+      if (name == 'CCITTFaxDecode' || name == 'CCF') {
         return new CCITTFaxStream(stream, params);
-      } else {
-        TODO('filter "' + name + '" not supported yet');
       }
+      if (name == 'RunLengthDecode') {
+        return new RunLengthStream(stream);
+      }
+      warn('filter "' + name + '" not supported yet');
       return stream;
     }
   };
 
-  return constructor;
+  return Parser;
 })();
 
-var Lexer = (function lexer() {
-  function constructor(stream) {
+var Lexer = (function LexerClosure() {
+  function Lexer(stream) {
     this.stream = stream;
   }
 
-  constructor.isSpace = function lexerIsSpace(ch) {
+  Lexer.isSpace = function Lexer_isSpace(ch) {
     return ch == ' ' || ch == '\t' || ch == '\x0d' || ch == '\x0a';
   };
 
@@ -292,8 +299,8 @@ var Lexer = (function lexer() {
     return -1;
   }
 
-  constructor.prototype = {
-    getNumber: function lexerGetNumber(ch) {
+  Lexer.prototype = {
+    getNumber: function Lexer_getNumber(ch) {
       var floating = false;
       var str = ch;
       var stream = this.stream;
@@ -321,7 +328,7 @@ var Lexer = (function lexer() {
         error('Invalid floating point number: ' + value);
       return value;
     },
-    getString: function lexerGetString() {
+    getString: function Lexer_getString() {
       var numParen = 1;
       var done = false;
       var str = '';
@@ -405,7 +412,7 @@ var Lexer = (function lexer() {
       } while (!done);
       return str;
     },
-    getName: function lexerGetName(ch) {
+    getName: function Lexer_getName(ch) {
       var str = '';
       var stream = this.stream;
       while (!!(ch = stream.lookChar()) && !specialChars[ch.charCodeAt(0)]) {
@@ -432,7 +439,7 @@ var Lexer = (function lexer() {
               str.length);
       return new Name(str);
     },
-    getHexString: function lexerGetHexString(ch) {
+    getHexString: function Lexer_getHexString(ch) {
       var str = '';
       var stream = this.stream;
       for (;;) {
@@ -461,7 +468,7 @@ var Lexer = (function lexer() {
       }
       return str;
     },
-    getObj: function lexerGetObj() {
+    getObj: function Lexer_getObj() {
       // skip whitespace and comments
       var comment = false;
       var stream = this.stream;
@@ -492,14 +499,14 @@ var Lexer = (function lexer() {
         // array punctuation
         case '[':
         case ']':
-          return new Cmd(ch);
+          return Cmd.get(ch);
         // hex string or dict punctuation
         case '<':
           ch = stream.lookChar();
           if (ch == '<') {
             // dict punctuation
             stream.skip();
-            return new Cmd('<<');
+            return Cmd.get('<<');
           }
           return this.getHexString(ch);
         // dict punctuation
@@ -507,25 +514,23 @@ var Lexer = (function lexer() {
           ch = stream.lookChar();
           if (ch == '>') {
             stream.skip();
-            return new Cmd('>>');
+            return Cmd.get('>>');
           }
         case '{':
         case '}':
-          return new Cmd(ch);
+          return Cmd.get(ch);
         // fall through
         case ')':
           error('Illegal character: ' + ch);
-          return Error;
       }
 
       // command
       var str = ch;
       while (!!(ch = stream.lookChar()) && !specialChars[ch.charCodeAt(0)]) {
         stream.skip();
-        if (str.length == 128) {
+        if (str.length == 128)
           error('Command token too long: ' + str.length);
-          break;
-        }
+
         str += ch;
       }
       if (str == 'true')
@@ -534,9 +539,9 @@ var Lexer = (function lexer() {
         return false;
       if (str == 'null')
         return null;
-      return new Cmd(str);
+      return Cmd.get(str);
     },
-    skipToNextLine: function lexerSkipToNextLine() {
+    skipToNextLine: function Lexer_skipToNextLine() {
       var stream = this.stream;
       while (true) {
         var ch = stream.getChar();
@@ -549,17 +554,17 @@ var Lexer = (function lexer() {
         }
       }
     },
-    skip: function lexerSkip() {
+    skip: function Lexer_skip() {
       this.stream.skip();
     }
   };
 
-  return constructor;
+  return Lexer;
 })();
 
-var Linearization = (function linearizationLinearization() {
-  function constructor(stream) {
-    this.parser = new Parser(new Lexer(stream), false);
+var Linearization = (function LinearizationClosure() {
+  function Linearization(stream) {
+    this.parser = new Parser(new Lexer(stream), false, null);
     var obj1 = this.parser.getObj();
     var obj2 = this.parser.getObj();
     var obj3 = this.parser.getObj();
@@ -572,8 +577,8 @@ var Linearization = (function linearizationLinearization() {
     }
   }
 
-  constructor.prototype = {
-    getInt: function linearizationGetInt(name) {
+  Linearization.prototype = {
+    getInt: function Linearization_getInt(name) {
       var linDict = this.linDict;
       var obj;
       if (isDict(linDict) &&
@@ -582,9 +587,8 @@ var Linearization = (function linearizationLinearization() {
         return obj;
       }
       error('"' + name + '" field in linearization table is invalid');
-      return 0;
     },
-    getHint: function linearizationGetHint(index) {
+    getHint: function Linearization_getHint(index) {
       var linDict = this.linDict;
       var obj1, obj2;
       if (isDict(linDict) &&
@@ -595,7 +599,6 @@ var Linearization = (function linearizationLinearization() {
         return obj2;
       }
       error('Hints table in linearization table is invalid: ' + index);
-      return 0;
     },
     get length() {
       if (!isDict(this.linDict))
@@ -631,6 +634,6 @@ var Linearization = (function linearizationLinearization() {
     }
   };
 
-  return constructor;
+  return Linearization;
 })();
 
diff --git a/apps/files_pdfviewer/js/pdfjs/src/pattern.js b/apps/files_pdfviewer/js/pdfjs/src/pattern.js
old mode 100755
new mode 100644
index 72d13d896b24566710a6feb418749149519c2fd6..7659f54363c18cea76ee7fc4eea271ce4fb53e57
--- a/apps/files_pdfviewer/js/pdfjs/src/pattern.js
+++ b/apps/files_pdfviewer/js/pdfjs/src/pattern.js
@@ -3,48 +3,53 @@
 
 'use strict';
 
-var Pattern = (function patternPattern() {
+var PatternType = {
+  AXIAL: 2,
+  RADIAL: 3
+};
+
+var Pattern = (function PatternClosure() {
   // Constructor should define this.getPattern
-  function constructor() {
+  function Pattern() {
     error('should not call Pattern constructor');
   }
 
-  constructor.prototype = {
+  Pattern.prototype = {
     // Input: current Canvas context
     // Output: the appropriate fillStyle or strokeStyle
-    getPattern: function pattern_getStyle(ctx) {
+    getPattern: function Pattern_getPattern(ctx) {
       error('Should not call Pattern.getStyle: ' + ctx);
     }
   };
 
-  constructor.shadingFromIR = function pattern_shadingFromIR(ctx, raw) {
-    return Shadings[raw[0]].fromIR(ctx, raw);
+  Pattern.shadingFromIR = function Pattern_shadingFromIR(raw) {
+    return Shadings[raw[0]].fromIR(raw);
   };
 
-  constructor.parseShading = function pattern_shading(shading, matrix, xref,
-                                                      res, ctx) {
+  Pattern.parseShading = function Pattern_parseShading(shading, matrix, xref,
+                                                       res) {
 
     var dict = isStream(shading) ? shading.dict : shading;
     var type = dict.get('ShadingType');
 
     switch (type) {
-      case 2:
-      case 3:
-        // both radial and axial shadings are handled by RadialAxial shading
-        return new Shadings.RadialAxial(dict, matrix, xref, res, ctx);
+      case PatternType.AXIAL:
+      case PatternType.RADIAL:
+        // Both radial and axial shadings are handled by RadialAxial shading.
+        return new Shadings.RadialAxial(dict, matrix, xref, res);
       default:
         return new Shadings.Dummy();
     }
   };
-  return constructor;
+  return Pattern;
 })();
 
 var Shadings = {};
 
 // Radial and axial shading have very similar implementations
 // If needed, the implementations can be broken into two classes
-Shadings.RadialAxial = (function radialAxialShading() {
-  function constructor(dict, matrix, xref, res, ctx) {
+Shadings.RadialAxial = (function RadialAxialClosure() {
+  function RadialAxial(dict, matrix, xref, res, ctx) {
     this.matrix = matrix;
     this.coordsArr = dict.get('Coords');
     this.shadingType = dict.get('ShadingType');
@@ -74,10 +79,9 @@ Shadings.RadialAxial = (function radialAxialShading() {
     this.extendEnd = extendEnd;
 
     var fnObj = dict.get('Function');
-    fnObj = xref.fetchIfRef(fnObj);
     if (isArray(fnObj))
       error('No support for array of functions');
-    else if (!isPDFFunction(fnObj))
+    if (!isPDFFunction(fnObj))
       error('Invalid function');
     var fn = PDFFunction.parse(xref, fnObj);
 
@@ -89,56 +93,60 @@ Shadings.RadialAxial = (function radialAxialShading() {
 
     var colorStops = [];
     for (var i = t0; i <= t1; i += step) {
-      var color = fn([i]);
-      var rgbColor = Util.makeCssRgb.apply(this, cs.getRgb(color));
-      colorStops.push([(i - t0) / diff, rgbColor]);
+      var rgbColor = cs.getRgb(fn([i]));
+      var cssColor = Util.makeCssRgb(rgbColor[0], rgbColor[1], rgbColor[2]);
+      colorStops.push([(i - t0) / diff, cssColor]);
     }
 
     this.colorStops = colorStops;
   }
 
-  constructor.fromIR = function radialAxialShadingGetIR(ctx, raw) {
+  RadialAxial.fromIR = function RadialAxial_fromIR(raw) {
     var type = raw[1];
     var colorStops = raw[2];
     var p0 = raw[3];
     var p1 = raw[4];
     var r0 = raw[5];
     var r1 = raw[6];
-
-    var curMatrix = ctx.mozCurrentTransform;
-    if (curMatrix) {
-      var userMatrix = ctx.mozCurrentTransformInverse;
-
-      p0 = Util.applyTransform(p0, curMatrix);
-      p0 = Util.applyTransform(p0, userMatrix);
-
-      p1 = Util.applyTransform(p1, curMatrix);
-      p1 = Util.applyTransform(p1, userMatrix);
-    }
-
-    var grad;
-    if (type == 2)
-      grad = ctx.createLinearGradient(p0[0], p0[1], p1[0], p1[1]);
-    else if (type == 3)
-      grad = ctx.createRadialGradient(p0[0], p0[1], r0, p1[0], p1[1], r1);
-
-    for (var i = 0, ii = colorStops.length; i < ii; ++i) {
-      var c = colorStops[i];
-      grad.addColorStop(c[0], c[1]);
-    }
-    return grad;
+    return {
+      type: 'Pattern',
+      getPattern: function(ctx) {
+        var curMatrix = ctx.mozCurrentTransform;
+        if (curMatrix) {
+          var userMatrix = ctx.mozCurrentTransformInverse;
+
+          p0 = Util.applyTransform(p0, curMatrix);
+          p0 = Util.applyTransform(p0, userMatrix);
+
+          p1 = Util.applyTransform(p1, curMatrix);
+          p1 = Util.applyTransform(p1, userMatrix);
+        }
+
+        var grad;
+        if (type == PatternType.AXIAL)
+          grad = ctx.createLinearGradient(p0[0], p0[1], p1[0], p1[1]);
+        else if (type == PatternType.RADIAL)
+          grad = ctx.createRadialGradient(p0[0], p0[1], r0, p1[0], p1[1], r1);
+
+        for (var i = 0, ii = colorStops.length; i < ii; ++i) {
+          var c = colorStops[i];
+          grad.addColorStop(c[0], c[1]);
+        }
+        return grad;
+      }
+    };
   };
 
-  constructor.prototype = {
-    getIR: function radialAxialShadingGetIR() {
+  RadialAxial.prototype = {
+    getIR: function RadialAxial_getIR() {
       var coordsArr = this.coordsArr;
       var type = this.shadingType;
-      if (type == 2) {
+      if (type == PatternType.AXIAL) {
         var p0 = [coordsArr[0], coordsArr[1]];
         var p1 = [coordsArr[2], coordsArr[3]];
         var r0 = null;
         var r1 = null;
-      } else if (type == 3) {
+      } else if (type == PatternType.RADIAL) {
         var p0 = [coordsArr[0], coordsArr[1]];
         var p1 = [coordsArr[3], coordsArr[4]];
         var r0 = coordsArr[2];
@@ -157,31 +165,35 @@ Shadings.RadialAxial = (function radialAxialShading() {
     }
   };
 
-  return constructor;
+  return RadialAxial;
 })();
 
-Shadings.Dummy = (function dummyShading() {
-  function constructor() {
+Shadings.Dummy = (function DummyClosure() {
+  function Dummy() {
     this.type = 'Pattern';
   }
 
-  constructor.fromIR = function dummyShadingFromIR() {
+  Dummy.fromIR = function Dummy_fromIR() {
     return 'hotpink';
   };
 
-  constructor.prototype = {
-    getIR: function dummyShadingGetIR() {
+  Dummy.prototype = {
+    getIR: function Dummy_getIR() {
       return ['Dummy'];
     }
   };
-  return constructor;
+  return Dummy;
 })();
 
-var TilingPattern = (function tilingPattern() {
-  var PAINT_TYPE_COLORED = 1, PAINT_TYPE_UNCOLORED = 2;
+var TilingPattern = (function TilingPatternClosure() {
+  var PaintType = {
+    COLORED: 1,
+    UNCOLORED: 2
+  };
+  var MAX_PATTERN_SIZE = 512;
 
   function TilingPattern(IR, color, ctx, objs) {
-    var IRQueue = IR[2];
+    var operatorList = IR[2];
     this.matrix = IR[3];
     var bbox = IR[4];
     var xstep = IR[5];
@@ -204,30 +216,30 @@ var TilingPattern = (function tilingPattern() {
     var width = botRight[0] - topLeft[0];
     var height = botRight[1] - topLeft[1];
 
-    // TODO: hack to avoid OOM, we would idealy compute the tiling
+    // TODO: hack to avoid OOM, we would ideally compute the tiling
     // pattern to be only as large as the acual size in device space
     // This could be computed with .mozCurrentTransform, but still
     // needs to be implemented
-    while (Math.abs(width) > 512 || Math.abs(height) > 512) {
-      width = 512;
-      height = 512;
+    while (Math.abs(width) > MAX_PATTERN_SIZE ||
+           Math.abs(height) > MAX_PATTERN_SIZE) {
+      width = height = MAX_PATTERN_SIZE;
     }
 
-    var tmpCanvas = new ScratchCanvas(width, height);
+    var tmpCanvas = createScratchCanvas(width, height);
 
     // set the new canvas element context as the graphics context
     var tmpCtx = tmpCanvas.getContext('2d');
     var graphics = new CanvasGraphics(tmpCtx, objs);
 
     switch (paintType) {
-      case PAINT_TYPE_COLORED:
+      case PaintType.COLORED:
         tmpCtx.fillStyle = ctx.fillStyle;
         tmpCtx.strokeStyle = ctx.strokeStyle;
         break;
-      case PAINT_TYPE_UNCOLORED:
-        color = Util.makeCssRgb.apply(this, color);
-        tmpCtx.fillStyle = color;
-        tmpCtx.strokeStyle = color;
+      case PaintType.UNCOLORED:
+        var cssColor = Util.makeCssRgb(this, color[0], color[1], color[2]);
+        tmpCtx.fillStyle = cssColor;
+        tmpCtx.strokeStyle = cssColor;
         break;
       default:
         error('Unsupported paint type: ' + paintType);
@@ -250,12 +262,12 @@ var TilingPattern = (function tilingPattern() {
       graphics.endPath();
     }
 
-    graphics.executeIRQueue(IRQueue);
+    graphics.executeOperatorList(operatorList);
 
     this.canvas = tmpCanvas;
   }
 
-  TilingPattern.getIR = function tiling_getIR(codeIR, dict, args) {
+  TilingPattern.getIR = function TilingPattern_getIR(operatorList, dict, args) {
     var matrix = dict.get('Matrix');
     var bbox = dict.get('BBox');
     var xstep = dict.get('XStep');
@@ -263,12 +275,12 @@ var TilingPattern = (function tilingPattern() {
     var paintType = dict.get('PaintType');
 
     return [
-      'TilingPattern', args, codeIR, matrix, bbox, xstep, ystep, paintType
+      'TilingPattern', args, operatorList, matrix, bbox, xstep, ystep, paintType
     ];
   };
 
   TilingPattern.prototype = {
-    getPattern: function tiling_getPattern() {
+    getPattern: function TilingPattern_getPattern() {
       var matrix = this.matrix;
       var curMatrix = this.curMatrix;
       var ctx = this.ctx;
diff --git a/apps/files_pdfviewer/js/pdfjs/src/pdf.js b/apps/files_pdfviewer/js/pdfjs/src/pdf.js
old mode 100755
new mode 100644
diff --git a/apps/files_pdfviewer/js/pdfjs/src/stream.js b/apps/files_pdfviewer/js/pdfjs/src/stream.js
old mode 100755
new mode 100644
index 559fb2ca22ee0e2b805a144202e651856cb53120..48c462fb2c37250fcb215f1ed8e917fad4455f1c
--- a/apps/files_pdfviewer/js/pdfjs/src/stream.js
+++ b/apps/files_pdfviewer/js/pdfjs/src/stream.js
@@ -3,8 +3,8 @@
 
 'use strict';
 
-var Stream = (function streamStream() {
-  function constructor(arrayBuffer, start, length, dict) {
+var Stream = (function StreamClosure() {
+  function Stream(arrayBuffer, start, length, dict) {
     this.bytes = new Uint8Array(arrayBuffer);
     this.start = start || 0;
     this.pos = this.start;
@@ -14,18 +14,18 @@ var Stream = (function streamStream() {
 
   // required methods for a stream. if a particular stream does not
   // implement these, an error should be thrown
-  constructor.prototype = {
+  Stream.prototype = {
     get length() {
       return this.end - this.start;
     },
-    getByte: function stream_getByte() {
+    getByte: function Stream_getByte() {
       if (this.pos >= this.end)
         return null;
       return this.bytes[this.pos++];
     },
     // returns subarray of original buffer
     // should only be read
-    getBytes: function stream_getBytes(length) {
+    getBytes: function Stream_getBytes(length) {
       var bytes = this.bytes;
       var pos = this.pos;
       var strEnd = this.end;
@@ -40,38 +40,38 @@ var Stream = (function streamStream() {
       this.pos = end;
       return bytes.subarray(pos, end);
     },
-    lookChar: function stream_lookChar() {
+    lookChar: function Stream_lookChar() {
       if (this.pos >= this.end)
         return null;
       return String.fromCharCode(this.bytes[this.pos]);
     },
-    getChar: function stream_getChar() {
+    getChar: function Stream_getChar() {
       if (this.pos >= this.end)
         return null;
       return String.fromCharCode(this.bytes[this.pos++]);
     },
-    skip: function stream_skip(n) {
+    skip: function Stream_skip(n) {
       if (!n)
         n = 1;
       this.pos += n;
     },
-    reset: function stream_reset() {
+    reset: function Stream_reset() {
       this.pos = this.start;
     },
-    moveStart: function stream_moveStart() {
+    moveStart: function Stream_moveStart() {
       this.start = this.pos;
     },
-    makeSubStream: function stream_makeSubstream(start, length, dict) {
+    makeSubStream: function Stream_makeSubStream(start, length, dict) {
       return new Stream(this.bytes.buffer, start, length, dict);
     },
     isStream: true
   };
 
-  return constructor;
+  return Stream;
 })();
 
-var StringStream = (function stringStream() {
-  function constructor(str) {
+var StringStream = (function StringStreamClosure() {
+  function StringStream(str) {
     var length = str.length;
     var bytes = new Uint8Array(length);
     for (var n = 0; n < length; ++n)
@@ -79,22 +79,22 @@ var StringStream = (function stringStream() {
     Stream.call(this, bytes);
   }
 
-  constructor.prototype = Stream.prototype;
+  StringStream.prototype = Stream.prototype;
 
-  return constructor;
+  return StringStream;
 })();
 
 // super class for the decoding streams
-var DecodeStream = (function decodeStream() {
-  function constructor() {
+var DecodeStream = (function DecodeStreamClosure() {
+  function DecodeStream() {
     this.pos = 0;
     this.bufferLength = 0;
     this.eof = false;
     this.buffer = null;
   }
 
-  constructor.prototype = {
-    ensureBuffer: function decodestream_ensureBuffer(requested) {
+  DecodeStream.prototype = {
+    ensureBuffer: function DecodeStream_ensureBuffer(requested) {
       var buffer = this.buffer;
       var current = buffer ? buffer.byteLength : 0;
       if (requested < current)
@@ -107,7 +107,7 @@ var DecodeStream = (function decodeStream() {
         buffer2[i] = buffer[i];
       return (this.buffer = buffer2);
     },
-    getByte: function decodestream_getByte() {
+    getByte: function DecodeStream_getByte() {
       var pos = this.pos;
       while (this.bufferLength <= pos) {
         if (this.eof)
@@ -116,7 +116,7 @@ var DecodeStream = (function decodeStream() {
       }
       return this.buffer[this.pos++];
     },
-    getBytes: function decodestream_getBytes(length) {
+    getBytes: function DecodeStream_getBytes(length) {
       var end, pos = this.pos;
 
       if (length) {
@@ -144,7 +144,7 @@ var DecodeStream = (function decodeStream() {
       this.pos = end;
       return this.buffer.subarray(pos, end);
     },
-    lookChar: function decodestream_lookChar() {
+    lookChar: function DecodeStream_lookChar() {
       var pos = this.pos;
       while (this.bufferLength <= pos) {
         if (this.eof)
@@ -153,7 +153,7 @@ var DecodeStream = (function decodeStream() {
       }
       return String.fromCharCode(this.buffer[this.pos]);
     },
-    getChar: function decodestream_getChar() {
+    getChar: function DecodeStream_getChar() {
       var pos = this.pos;
       while (this.bufferLength <= pos) {
         if (this.eof)
@@ -162,40 +162,40 @@ var DecodeStream = (function decodeStream() {
       }
       return String.fromCharCode(this.buffer[this.pos++]);
     },
-    makeSubStream: function decodestream_makeSubstream(start, length, dict) {
+    makeSubStream: function DecodeStream_makeSubStream(start, length, dict) {
       var end = start + length;
       while (this.bufferLength <= end && !this.eof)
         this.readBlock();
       return new Stream(this.buffer, start, length, dict);
     },
-    skip: function decodestream_skip(n) {
+    skip: function DecodeStream_skip(n) {
       if (!n)
         n = 1;
       this.pos += n;
     },
-    reset: function decodestream_reset() {
+    reset: function DecodeStream_reset() {
       this.pos = 0;
     }
   };
 
-  return constructor;
+  return DecodeStream;
 })();
 
-var FakeStream = (function fakeStream() {
-  function constructor(stream) {
+var FakeStream = (function FakeStreamClosure() {
+  function FakeStream(stream) {
     this.dict = stream.dict;
     DecodeStream.call(this);
   }
 
-  constructor.prototype = Object.create(DecodeStream.prototype);
-  constructor.prototype.readBlock = function fakeStreamReadBlock() {
+  FakeStream.prototype = Object.create(DecodeStream.prototype);
+  FakeStream.prototype.readBlock = function FakeStream_readBlock() {
     var bufferLength = this.bufferLength;
     bufferLength += 1024;
     var buffer = this.ensureBuffer(bufferLength);
     this.bufferLength = bufferLength;
   };
 
-  constructor.prototype.getBytes = function fakeStreamGetBytes(length) {
+  FakeStream.prototype.getBytes = function FakeStream_getBytes(length) {
     var end, pos = this.pos;
 
     if (length) {
@@ -217,18 +217,20 @@ var FakeStream = (function fakeStream() {
     return this.buffer.subarray(pos, end);
   };
 
-  return constructor;
+  return FakeStream;
 })();
 
-var StreamsSequenceStream = (function streamSequenceStream() {
-  function constructor(streams) {
+var StreamsSequenceStream = (function StreamsSequenceStreamClosure() {
+  function StreamsSequenceStream(streams) {
     this.streams = streams;
     DecodeStream.call(this);
   }
 
-  constructor.prototype = Object.create(DecodeStream.prototype);
+  StreamsSequenceStream.prototype = Object.create(DecodeStream.prototype);
+
+  StreamsSequenceStream.prototype.readBlock =
+    function streamSequenceStreamReadBlock() {
 
-  constructor.prototype.readBlock = function streamSequenceStreamReadBlock() {
     var streams = this.streams;
     if (streams.length == 0) {
       this.eof = true;
@@ -243,10 +245,10 @@ var StreamsSequenceStream = (function streamSequenceStream() {
     this.bufferLength = newLength;
   };
 
-  return constructor;
+  return StreamsSequenceStream;
 })();
 
-var FlateStream = (function flateStream() {
+var FlateStream = (function FlateStreamClosure() {
   var codeLenCodeMap = new Uint32Array([
     16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15
   ]);
@@ -339,7 +341,7 @@ var FlateStream = (function flateStream() {
     0x50003, 0x50013, 0x5000b, 0x5001b, 0x50007, 0x50017, 0x5000f, 0x00000
   ]), 5];
 
-  function constructor(stream) {
+  function FlateStream(stream) {
     var bytes = stream.getBytes();
     var bytesPos = 0;
 
@@ -364,9 +366,9 @@ var FlateStream = (function flateStream() {
     DecodeStream.call(this);
   }
 
-  constructor.prototype = Object.create(DecodeStream.prototype);
+  FlateStream.prototype = Object.create(DecodeStream.prototype);
 
-  constructor.prototype.getBits = function flateStreamGetBits(bits) {
+  FlateStream.prototype.getBits = function FlateStream_getBits(bits) {
     var codeSize = this.codeSize;
     var codeBuf = this.codeBuf;
     var bytes = this.bytes;
@@ -386,7 +388,7 @@ var FlateStream = (function flateStream() {
     return b;
   };
 
-  constructor.prototype.getCode = function flateStreamGetCode(table) {
+  FlateStream.prototype.getCode = function FlateStream_getCode(table) {
     var codes = table[0];
     var maxLen = table[1];
     var codeSize = this.codeSize;
@@ -412,7 +414,7 @@ var FlateStream = (function flateStream() {
     return codeVal;
   };
 
-  constructor.prototype.generateHuffmanTable =
+  FlateStream.prototype.generateHuffmanTable =
     function flateStreamGenerateHuffmanTable(lengths) {
     var n = lengths.length;
 
@@ -451,7 +453,7 @@ var FlateStream = (function flateStream() {
     return [codes, maxLen];
   };
 
-  constructor.prototype.readBlock = function flateStreamReadBlock() {
+  FlateStream.prototype.readBlock = function FlateStream_readBlock() {
     // read block header
     var hdr = this.getBits(3);
     if (hdr & 1)
@@ -582,11 +584,11 @@ var FlateStream = (function flateStream() {
     }
   };
 
-  return constructor;
+  return FlateStream;
 })();
 
-var PredictorStream = (function predictorStream() {
-  function constructor(stream, params) {
+var PredictorStream = (function PredictorStreamClosure() {
+  function PredictorStream(stream, params) {
     var predictor = this.predictor = params.get('Predictor') || 1;
 
     if (predictor <= 1)
@@ -613,15 +615,14 @@ var PredictorStream = (function predictorStream() {
     return this;
   }
 
-  constructor.prototype = Object.create(DecodeStream.prototype);
+  PredictorStream.prototype = Object.create(DecodeStream.prototype);
 
-  constructor.prototype.readBlockTiff =
+  PredictorStream.prototype.readBlockTiff =
     function predictorStreamReadBlockTiff() {
     var rowBytes = this.rowBytes;
 
     var bufferLength = this.bufferLength;
     var buffer = this.ensureBuffer(bufferLength + rowBytes);
-    var currentRow = buffer.subarray(bufferLength, bufferLength + rowBytes);
 
     var bits = this.bits;
     var colors = this.colors;
@@ -630,6 +631,7 @@ var PredictorStream = (function predictorStream() {
 
     var inbuf = 0, outbuf = 0;
     var inbits = 0, outbits = 0;
+    var pos = bufferLength;
 
     if (bits === 1) {
       for (var i = 0; i < rowBytes; ++i) {
@@ -637,19 +639,21 @@ var PredictorStream = (function predictorStream() {
         inbuf = (inbuf << 8) | c;
         // bitwise addition is exclusive or
         // first shift inbuf and then add
-        currentRow[i] = (c ^ (inbuf >> colors)) & 0xFF;
+        buffer[pos++] = (c ^ (inbuf >> colors)) & 0xFF;
         // truncate inbuf (assumes colors < 16)
         inbuf &= 0xFFFF;
       }
     } else if (bits === 8) {
       for (var i = 0; i < colors; ++i)
-        currentRow[i] = rawBytes[i];
-      for (; i < rowBytes; ++i)
-        currentRow[i] = currentRow[i - colors] + rawBytes[i];
+        buffer[pos++] = rawBytes[i];
+      for (; i < rowBytes; ++i) {
+        buffer[pos] = buffer[pos - colors] + rawBytes[i];
+        pos++;
+      }
     } else {
       var compArray = new Uint8Array(colors + 1);
       var bitMask = (1 << bits) - 1;
-      var j = 0, k = 0;
+      var j = 0, k = bufferLength;
       var columns = this.columns;
       for (var i = 0; i < columns; ++i) {
         for (var kk = 0; kk < colors; ++kk) {
@@ -663,20 +667,22 @@ var PredictorStream = (function predictorStream() {
           outbuf = (outbuf << bits) | compArray[kk];
           outbits += bits;
           if (outbits >= 8) {
-            currentRow[k++] = (outbuf >> (outbits - 8)) & 0xFF;
+            buffer[k++] = (outbuf >> (outbits - 8)) & 0xFF;
             outbits -= 8;
           }
         }
       }
       if (outbits > 0) {
-        currentRow[k++] = (outbuf << (8 - outbits)) +
+        buffer[k++] = (outbuf << (8 - outbits)) +
         (inbuf & ((1 << (8 - outbits)) - 1));
       }
     }
     this.bufferLength += rowBytes;
   };
 
-  constructor.prototype.readBlockPng = function predictorStreamReadBlockPng() {
+  PredictorStream.prototype.readBlockPng =
+    function predictorStreamReadBlockPng() {
+
     var rowBytes = this.rowBytes;
     var pixBytes = this.pixBytes;
 
@@ -686,32 +692,35 @@ var PredictorStream = (function predictorStream() {
     var bufferLength = this.bufferLength;
     var buffer = this.ensureBuffer(bufferLength + rowBytes);
 
-    var currentRow = buffer.subarray(bufferLength, bufferLength + rowBytes);
     var prevRow = buffer.subarray(bufferLength - rowBytes, bufferLength);
     if (prevRow.length == 0)
       prevRow = new Uint8Array(rowBytes);
 
+    var j = bufferLength;
     switch (predictor) {
       case 0:
         for (var i = 0; i < rowBytes; ++i)
-          currentRow[i] = rawBytes[i];
+          buffer[j++] = rawBytes[i];
         break;
       case 1:
         for (var i = 0; i < pixBytes; ++i)
-          currentRow[i] = rawBytes[i];
-        for (; i < rowBytes; ++i)
-          currentRow[i] = (currentRow[i - pixBytes] + rawBytes[i]) & 0xFF;
+          buffer[j++] = rawBytes[i];
+        for (; i < rowBytes; ++i) {
+          buffer[j] = (buffer[j - pixBytes] + rawBytes[i]) & 0xFF;
+          j++;
+        }
         break;
       case 2:
         for (var i = 0; i < rowBytes; ++i)
-          currentRow[i] = (prevRow[i] + rawBytes[i]) & 0xFF;
+          buffer[j++] = (prevRow[i] + rawBytes[i]) & 0xFF;
         break;
       case 3:
         for (var i = 0; i < pixBytes; ++i)
-          currentRow[i] = (prevRow[i] >> 1) + rawBytes[i];
+          buffer[j++] = (prevRow[i] >> 1) + rawBytes[i];
         for (; i < rowBytes; ++i) {
-          currentRow[i] = (((prevRow[i] + currentRow[i - pixBytes]) >> 1) +
+          buffer[j] = (((prevRow[i] + buffer[j - pixBytes]) >> 1) +
                            rawBytes[i]) & 0xFF;
+          j++;
         }
         break;
       case 4:
@@ -720,12 +729,12 @@ var PredictorStream = (function predictorStream() {
         for (var i = 0; i < pixBytes; ++i) {
           var up = prevRow[i];
           var c = rawBytes[i];
-          currentRow[i] = up + c;
+          buffer[j++] = up + c;
         }
         for (; i < rowBytes; ++i) {
           var up = prevRow[i];
           var upLeft = prevRow[i - pixBytes];
-          var left = currentRow[i - pixBytes];
+          var left = buffer[j - pixBytes];
           var p = left + up - upLeft;
 
           var pa = p - left;
@@ -740,11 +749,11 @@ var PredictorStream = (function predictorStream() {
 
           var c = rawBytes[i];
           if (pa <= pb && pa <= pc)
-            currentRow[i] = left + c;
+            buffer[j++] = left + c;
           else if (pb <= pc)
-            currentRow[i] = up + c;
+            buffer[j++] = up + c;
           else
-            currentRow[i] = upLeft + c;
+            buffer[j++] = upLeft + c;
         }
         break;
       default:
@@ -753,7 +762,7 @@ var PredictorStream = (function predictorStream() {
     this.bufferLength += rowBytes;
   };
 
-  return constructor;
+  return PredictorStream;
 })();
 
 /**
@@ -763,7 +772,7 @@ var PredictorStream = (function predictorStream() {
  * a library to decode these images and the stream behaves like all the other
  * DecodeStreams.
  */
-var JpegStream = (function jpegStream() {
+var JpegStream = (function JpegStreamClosure() {
   function isAdobeImage(bytes) {
     var maxBytesScanned = Math.max(bytes.length - 16, 1024);
     // Looking for APP14, 'Adobe'
@@ -794,63 +803,184 @@ var JpegStream = (function jpegStream() {
     return newBytes;
   }
 
-  function constructor(bytes, dict, xref) {
+  function JpegStream(bytes, dict, xref) {
     // TODO: per poppler, some images may have 'junk' before that
     // need to be removed
     this.dict = dict;
 
-    // Flag indicating wether the image can be natively loaded.
-    this.isNative = true;
-
-    this.colorTransform = -1;
+    this.isAdobeImage = false;
+    this.colorTransform = dict.get('ColorTransform') || -1;
 
     if (isAdobeImage(bytes)) {
-      // when bug 674619 land, let's check if browser can do
-      // normal cmyk and then we won't have to the following
-      var cs = xref.fetchIfRef(dict.get('ColorSpace'));
-
-      // DeviceRGB and DeviceGray are the only Adobe images that work natively
-      if (isName(cs) && (cs.name === 'DeviceRGB' || cs.name === 'DeviceGray')) {
-        bytes = fixAdobeImage(bytes);
-        this.src = bytesToString(bytes);
-      } else {
-        this.colorTransform = dict.get('ColorTransform');
-        this.isNative = false;
-        this.bytes = bytes;
-      }
-    } else {
-      this.src = bytesToString(bytes);
+      this.isAdobeImage = true;
+      bytes = fixAdobeImage(bytes);
     }
 
+    this.bytes = bytes;
+
     DecodeStream.call(this);
   }
 
-  constructor.prototype = Object.create(DecodeStream.prototype);
+  JpegStream.prototype = Object.create(DecodeStream.prototype);
 
-  constructor.prototype.ensureBuffer = function jpegStreamEnsureBuffer(req) {
+  JpegStream.prototype.ensureBuffer = function JpegStream_ensureBuffer(req) {
     if (this.bufferLength)
       return;
-    var jpegImage = new JpegImage();
-    jpegImage.colorTransform = this.colorTransform;
-    jpegImage.parse(this.bytes);
-    var width = jpegImage.width;
-    var height = jpegImage.height;
-    var data = jpegImage.getData(width, height);
+    try {
+      var jpegImage = new JpegImage();
+      if (this.colorTransform != -1)
+        jpegImage.colorTransform = this.colorTransform;
+      jpegImage.parse(this.bytes);
+      var width = jpegImage.width;
+      var height = jpegImage.height;
+      var data = jpegImage.getData(width, height);
+      this.buffer = data;
+      this.bufferLength = data.length;
+    } catch (e) {
+      error('JPEG error: ' + e);
+    }
+  };
+  JpegStream.prototype.getIR = function JpegStream_getIR() {
+    return bytesToString(this.bytes);
+  };
+  JpegStream.prototype.getChar = function JpegStream_getChar() {
+    error('internal error: getChar is not valid on JpegStream');
+  };
+  /**
+   * Checks if the image can be decoded and displayed by the browser without any
+   * further processing such as color space conversions.
+   */
+  JpegStream.prototype.isNativelySupported =
+    function JpegStream_isNativelySupported(xref, res) {
+    var cs = ColorSpace.parse(this.dict.get('ColorSpace'), xref, res);
+    // when bug 674619 lands, let's check if browser can do
+    // normal cmyk and then we won't need to decode in JS
+    if (cs.name === 'DeviceGray' || cs.name === 'DeviceRGB')
+      return true;
+    if (cs.name === 'DeviceCMYK' && !this.isAdobeImage &&
+        this.colorTransform < 1)
+      return true;
+    return false;
+  };
+  /**
+   * Checks if the image can be decoded by the browser.
+   */
+  JpegStream.prototype.isNativelyDecodable =
+    function JpegStream_isNativelyDecodable(xref, res) {
+    var cs = ColorSpace.parse(this.dict.get('ColorSpace'), xref, res);
+    var numComps = cs.numComps;
+    if (numComps == 1 || numComps == 3)
+      return true;
+
+    return false;
+  };
+
+  return JpegStream;
+})();
+
+/**
+ * For JPEG 2000's we use a library to decode these images and
+ * the stream behaves like all the other DecodeStreams.
+ */
+var JpxStream = (function JpxStreamClosure() {
+  function JpxStream(bytes, dict) {
+    this.dict = dict;
+    this.bytes = bytes;
+
+    DecodeStream.call(this);
+  }
+
+  JpxStream.prototype = Object.create(DecodeStream.prototype);
+
+  JpxStream.prototype.ensureBuffer = function JpxStream_ensureBuffer(req) {
+    if (this.bufferLength)
+      return;
+
+    var jpxImage = new JpxImage();
+    jpxImage.parse(this.bytes);
+
+    var width = jpxImage.width;
+    var height = jpxImage.height;
+    var componentsCount = jpxImage.componentsCount;
+    if (componentsCount != 1 && componentsCount != 3 && componentsCount != 4)
+      error('JPX with ' + componentsCount + ' components is not supported');
+
+    var data = new Uint8Array(width * height * componentsCount);
+
+    for (var k = 0, kk = jpxImage.tiles.length; k < kk; k++) {
+      var tileCompoments = jpxImage.tiles[k];
+      var tileWidth = tileCompoments[0].width;
+      var tileHeight = tileCompoments[0].height;
+      var tileLeft = tileCompoments[0].left;
+      var tileTop = tileCompoments[0].top;
+
+      var dataPosition, sourcePosition, data0, data1, data2, data3, rowFeed;
+      switch (componentsCount) {
+        case 1:
+          data0 = tileCompoments[0].items;
+
+          dataPosition = width * tileTop + tileLeft;
+          rowFeed = width - tileWidth;
+          sourcePosition = 0;
+          for (var j = 0; j < tileHeight; j++) {
+            for (var i = 0; i < tileWidth; i++)
+              data[dataPosition++] = data0[sourcePosition++];
+            dataPosition += rowFeed;
+          }
+          break;
+        case 3:
+          data0 = tileCompoments[0].items;
+          data1 = tileCompoments[1].items;
+          data2 = tileCompoments[2].items;
+
+          dataPosition = (width * tileTop + tileLeft) * 3;
+          rowFeed = (width - tileWidth) * 3;
+          sourcePosition = 0;
+          for (var j = 0; j < tileHeight; j++) {
+            for (var i = 0; i < tileWidth; i++) {
+              data[dataPosition++] = data0[sourcePosition];
+              data[dataPosition++] = data1[sourcePosition];
+              data[dataPosition++] = data2[sourcePosition];
+              sourcePosition++;
+            }
+            dataPosition += rowFeed;
+          }
+          break;
+        case 4:
+          data0 = tileCompoments[0].items;
+          data1 = tileCompoments[1].items;
+          data2 = tileCompoments[2].items;
+          data3 = tileCompoments[3].items;
+
+          dataPosition = (width * tileTop + tileLeft) * 4;
+          rowFeed = (width - tileWidth) * 4;
+          sourcePosition = 0;
+          for (var j = 0; j < tileHeight; j++) {
+            for (var i = 0; i < tileWidth; i++) {
+              data[dataPosition++] = data0[sourcePosition];
+              data[dataPosition++] = data1[sourcePosition];
+              data[dataPosition++] = data2[sourcePosition];
+              data[dataPosition++] = data3[sourcePosition];
+              sourcePosition++;
+            }
+            dataPosition += rowFeed;
+          }
+          break;
+      }
+    }
+
     this.buffer = data;
     this.bufferLength = data.length;
   };
-  constructor.prototype.getIR = function jpegStreamGetIR() {
-    return this.src;
-  };
-  constructor.prototype.getChar = function jpegStreamGetChar() {
-      error('internal error: getChar is not valid on JpegStream');
+  JpxStream.prototype.getChar = function JpxStream_getChar() {
+    error('internal error: getChar is not valid on JpxStream');
   };
 
-  return constructor;
+  return JpxStream;
 })();
 
-var DecryptStream = (function decryptStream() {
-  function constructor(str, decrypt) {
+var DecryptStream = (function DecryptStreamClosure() {
+  function DecryptStream(str, decrypt) {
     this.str = str;
     this.dict = str.dict;
     this.decrypt = decrypt;
@@ -860,9 +990,9 @@ var DecryptStream = (function decryptStream() {
 
   var chunkSize = 512;
 
-  constructor.prototype = Object.create(DecodeStream.prototype);
+  DecryptStream.prototype = Object.create(DecodeStream.prototype);
 
-  constructor.prototype.readBlock = function decryptStreamReadBlock() {
+  DecryptStream.prototype.readBlock = function DecryptStream_readBlock() {
     var chunk = this.str.getBytes(chunkSize);
     if (!chunk || chunk.length == 0) {
       this.eof = true;
@@ -879,11 +1009,11 @@ var DecryptStream = (function decryptStream() {
     this.bufferLength = bufferLength;
   };
 
-  return constructor;
+  return DecryptStream;
 })();
 
-var Ascii85Stream = (function ascii85Stream() {
-  function constructor(str) {
+var Ascii85Stream = (function Ascii85StreamClosure() {
+  function Ascii85Stream(str) {
     this.str = str;
     this.dict = str.dict;
     this.input = new Uint8Array(5);
@@ -891,9 +1021,9 @@ var Ascii85Stream = (function ascii85Stream() {
     DecodeStream.call(this);
   }
 
-  constructor.prototype = Object.create(DecodeStream.prototype);
+  Ascii85Stream.prototype = Object.create(DecodeStream.prototype);
 
-  constructor.prototype.readBlock = function ascii85StreamReadBlock() {
+  Ascii85Stream.prototype.readBlock = function Ascii85Stream_readBlock() {
     var tildaCode = '~'.charCodeAt(0);
     var zCode = 'z'.charCodeAt(0);
     var str = this.str;
@@ -948,11 +1078,11 @@ var Ascii85Stream = (function ascii85Stream() {
     }
   };
 
-  return constructor;
+  return Ascii85Stream;
 })();
 
-var AsciiHexStream = (function asciiHexStream() {
-  function constructor(str) {
+var AsciiHexStream = (function AsciiHexStreamClosure() {
+  function AsciiHexStream(str) {
     this.str = str;
     this.dict = str.dict;
 
@@ -986,9 +1116,9 @@ var AsciiHexStream = (function asciiHexStream() {
       102: 15
   };
 
-  constructor.prototype = Object.create(DecodeStream.prototype);
+  AsciiHexStream.prototype = Object.create(DecodeStream.prototype);
 
-  constructor.prototype.readBlock = function asciiHexStreamReadBlock() {
+  AsciiHexStream.prototype.readBlock = function AsciiHexStream_readBlock() {
     var gtCode = '>'.charCodeAt(0), bytes = this.str.getBytes(), c, n,
         decodeLength, buffer, bufferLength, i, length;
 
@@ -1018,10 +1148,55 @@ var AsciiHexStream = (function asciiHexStream() {
     this.eof = true;
   };
 
-  return constructor;
+  return AsciiHexStream;
+})();
+
+var RunLengthStream = (function RunLengthStreamClosure() {
+  function RunLengthStream(str) {
+    this.str = str;
+    this.dict = str.dict;
+
+    DecodeStream.call(this);
+  }
+
+  RunLengthStream.prototype = Object.create(DecodeStream.prototype);
+
+  RunLengthStream.prototype.readBlock = function RunLengthStream_readBlock() {
+    // The repeatHeader has following format. The first byte defines type of run
+    // and amount of bytes to repeat/copy: n = 0 through 127 - copy next n bytes
+    // (in addition to the second byte from the header), n = 129 through 255 -
+    // duplicate the second byte from the header (257 - n) times, n = 128 - end.
+    var repeatHeader = this.str.getBytes(2);
+    if (!repeatHeader || repeatHeader.length < 2 || repeatHeader[0] == 128) {
+      this.eof = true;
+      return;
+    }
+
+    var bufferLength = this.bufferLength;
+    var n = repeatHeader[0];
+    if (n < 128) {
+      // copy n bytes
+      var buffer = this.ensureBuffer(bufferLength + n + 1);
+      buffer[bufferLength++] = repeatHeader[1];
+      if (n > 0) {
+        var source = this.str.getBytes(n);
+        buffer.set(source, bufferLength);
+        bufferLength += n;
+      }
+    } else {
+      n = 257 - n;
+      var b = repeatHeader[1];
+      var buffer = this.ensureBuffer(bufferLength + n + 1);
+      for (var i = 0; i < n; i++)
+        buffer[bufferLength++] = b;
+    }
+    this.bufferLength = bufferLength;
+  };
+
+  return RunLengthStream;
 })();
 
-var CCITTFaxStream = (function ccittFaxStream() {
+var CCITTFaxStream = (function CCITTFaxStreamClosure() {
 
   var ccittEOL = -2;
   var twoDimPass = 0;
@@ -1449,7 +1624,7 @@ var CCITTFaxStream = (function ccittFaxStream() {
     [2, 2], [2, 2], [2, 2], [2, 2]
   ];
 
-  function constructor(str, params) {
+  function CCITTFaxStream(str, params) {
     this.str = str;
     this.dict = str.dict;
 
@@ -1494,9 +1669,9 @@ var CCITTFaxStream = (function ccittFaxStream() {
     DecodeStream.call(this);
   }
 
-  constructor.prototype = Object.create(DecodeStream.prototype);
+  CCITTFaxStream.prototype = Object.create(DecodeStream.prototype);
 
-  constructor.prototype.readBlock = function ccittFaxStreamReadBlock() {
+  CCITTFaxStream.prototype.readBlock = function CCITTFaxStream_readBlock() {
     while (!this.eof) {
       var c = this.lookChar();
       this.buf = EOF;
@@ -1505,7 +1680,7 @@ var CCITTFaxStream = (function ccittFaxStream() {
     }
   };
 
-  constructor.prototype.addPixels =
+  CCITTFaxStream.prototype.addPixels =
     function ccittFaxStreamAddPixels(a1, blackPixels) {
     var codingLine = this.codingLine;
     var codingPos = this.codingPos;
@@ -1525,7 +1700,7 @@ var CCITTFaxStream = (function ccittFaxStream() {
     this.codingPos = codingPos;
   };
 
-  constructor.prototype.addPixelsNeg =
+  CCITTFaxStream.prototype.addPixelsNeg =
     function ccittFaxStreamAddPixelsNeg(a1, blackPixels) {
     var codingLine = this.codingLine;
     var codingPos = this.codingPos;
@@ -1554,7 +1729,7 @@ var CCITTFaxStream = (function ccittFaxStream() {
     this.codingPos = codingPos;
   };
 
-  constructor.prototype.lookChar = function ccittFaxStreamLookChar() {
+  CCITTFaxStream.prototype.lookChar = function CCITTFaxStream_lookChar() {
     if (this.buf != EOF)
       return this.buf;
 
@@ -1852,10 +2027,10 @@ var CCITTFaxStream = (function ccittFaxStream() {
   // values. The first array element indicates whether a valid code is being
   // returned. The second array element is the actual code. The third array
   // element indicates whether EOF was reached.
-  var findTableCode = function ccittFaxStreamFindTableCode(start, end, table,
-                                                           limit) {
-    var limitValue = limit || 0;
+  CCITTFaxStream.prototype.findTableCode =
+    function ccittFaxStreamFindTableCode(start, end, table, limit) {
 
+    var limitValue = limit || 0;
     for (var i = start; i <= end; ++i) {
       var code = this.lookBits(i);
       if (code == EOF)
@@ -1873,18 +2048,20 @@ var CCITTFaxStream = (function ccittFaxStream() {
     return [false, 0, false];
   };
 
-  constructor.prototype.getTwoDimCode = function ccittFaxStreamGetTwoDimCode() {
+  CCITTFaxStream.prototype.getTwoDimCode =
+    function ccittFaxStreamGetTwoDimCode() {
+
     var code = 0;
     var p;
     if (this.eoblock) {
       code = this.lookBits(7);
       p = twoDimTable[code];
-      if (p[0] > 0) {
+      if (p && p[0] > 0) {
         this.eatBits(p[0]);
         return p[1];
       }
     } else {
-      var result = findTableCode(1, 7, twoDimTable);
+      var result = this.findTableCode(1, 7, twoDimTable);
       if (result[0] && result[2])
         return result[1];
     }
@@ -1892,7 +2069,9 @@ var CCITTFaxStream = (function ccittFaxStream() {
     return EOF;
   };
 
-  constructor.prototype.getWhiteCode = function ccittFaxStreamGetWhiteCode() {
+  CCITTFaxStream.prototype.getWhiteCode =
+    function ccittFaxStreamGetWhiteCode() {
+
     var code = 0;
     var p;
     var n;
@@ -1911,11 +2090,11 @@ var CCITTFaxStream = (function ccittFaxStream() {
         return p[1];
       }
     } else {
-      var result = findTableCode(1, 9, whiteTable2);
+      var result = this.findTableCode(1, 9, whiteTable2);
       if (result[0])
         return result[1];
 
-      result = findTableCode(11, 12, whiteTable1);
+      result = this.findTableCode(11, 12, whiteTable1);
       if (result[0])
         return result[1];
     }
@@ -1924,7 +2103,9 @@ var CCITTFaxStream = (function ccittFaxStream() {
     return 1;
   };
 
-  constructor.prototype.getBlackCode = function ccittFaxStreamGetBlackCode() {
+  CCITTFaxStream.prototype.getBlackCode =
+    function ccittFaxStreamGetBlackCode() {
+
     var code, p;
     if (this.eoblock) {
       code = this.lookBits(13);
@@ -1942,15 +2123,15 @@ var CCITTFaxStream = (function ccittFaxStream() {
         return p[1];
       }
     } else {
-      var result = findTableCode(2, 6, blackTable3);
+      var result = this.findTableCode(2, 6, blackTable3);
       if (result[0])
         return result[1];
 
-      result = findTableCode(7, 12, blackTable2, 64);
+      result = this.findTableCode(7, 12, blackTable2, 64);
       if (result[0])
         return result[1];
 
-      result = findTableCode(10, 13, blackTable1);
+      result = this.findTableCode(10, 13, blackTable1);
       if (result[0])
         return result[1];
     }
@@ -1959,7 +2140,7 @@ var CCITTFaxStream = (function ccittFaxStream() {
     return 1;
   };
 
-  constructor.prototype.lookBits = function ccittFaxStreamLookBits(n) {
+  CCITTFaxStream.prototype.lookBits = function CCITTFaxStream_lookBits(n) {
     var c;
     while (this.inputBits < n) {
       if ((c = this.str.getByte()) == null) {
@@ -1974,16 +2155,16 @@ var CCITTFaxStream = (function ccittFaxStream() {
     return (this.inputBuf >> (this.inputBits - n)) & (0xFFFF >> (16 - n));
   };
 
-  constructor.prototype.eatBits = function ccittFaxStreamEatBits(n) {
+  CCITTFaxStream.prototype.eatBits = function CCITTFaxStream_eatBits(n) {
     if ((this.inputBits -= n) < 0)
       this.inputBits = 0;
   };
 
-  return constructor;
+  return CCITTFaxStream;
 })();
 
-var LZWStream = (function lzwStream() {
-  function constructor(str, earlyChange) {
+var LZWStream = (function LZWStreamClosure() {
+  function LZWStream(str, earlyChange) {
     this.str = str;
     this.dict = str.dict;
     this.cachedData = 0;
@@ -2009,9 +2190,9 @@ var LZWStream = (function lzwStream() {
     DecodeStream.call(this);
   }
 
-  constructor.prototype = Object.create(DecodeStream.prototype);
+  LZWStream.prototype = Object.create(DecodeStream.prototype);
 
-  constructor.prototype.readBits = function lzwStreamReadBits(n) {
+  LZWStream.prototype.readBits = function LZWStream_readBits(n) {
     var bitsCached = this.bitsCached;
     var cachedData = this.cachedData;
     while (bitsCached < n) {
@@ -2029,7 +2210,7 @@ var LZWStream = (function lzwStream() {
     return (cachedData >>> bitsCached) & ((1 << n) - 1);
   };
 
-  constructor.prototype.readBlock = function lzwStreamReadBlock() {
+  LZWStream.prototype.readBlock = function LZWStream_readBlock() {
     var blockSize = 512;
     var estimatedDecodedSize = blockSize * 2, decodedSizeDelta = blockSize;
     var i, j, q;
@@ -2108,6 +2289,6 @@ var LZWStream = (function lzwStream() {
     this.bufferLength = currentBufferLength;
   };
 
-  return constructor;
+  return LZWStream;
 })();
 
diff --git a/apps/files_pdfviewer/js/pdfjs/src/util.js b/apps/files_pdfviewer/js/pdfjs/src/util.js
old mode 100755
new mode 100644
index 4fb96f062a87ff7344871dd25b2ad5e2c88a7ae5..de7f3c1d548e31fc9fd8dc717d6a0e4176e38756
--- a/apps/files_pdfviewer/js/pdfjs/src/util.js
+++ b/apps/files_pdfviewer/js/pdfjs/src/util.js
@@ -76,24 +76,102 @@ function stringToBytes(str) {
 
 var IDENTITY_MATRIX = [1, 0, 0, 1, 0, 0];
 
-var Util = (function utilUtil() {
-  function constructor() {}
-  constructor.makeCssRgb = function makergb(r, g, b) {
+var Util = (function UtilClosure() {
+  function Util() {}
+
+  Util.makeCssRgb = function Util_makeCssRgb(r, g, b) {
     var ri = (255 * r) | 0, gi = (255 * g) | 0, bi = (255 * b) | 0;
     return 'rgb(' + ri + ',' + gi + ',' + bi + ')';
   };
-  constructor.makeCssCmyk = function makecmyk(c, m, y, k) {
+
+  Util.makeCssCmyk = function Util_makeCssCmyk(c, m, y, k) {
     c = (new DeviceCmykCS()).getRgb([c, m, y, k]);
     var ri = (255 * c[0]) | 0, gi = (255 * c[1]) | 0, bi = (255 * c[2]) | 0;
     return 'rgb(' + ri + ',' + gi + ',' + bi + ')';
   };
-  constructor.applyTransform = function apply(p, m) {
+
+  // For 2d affine transforms
+  Util.applyTransform = function Util_applyTransform(p, m) {
     var xt = p[0] * m[0] + p[1] * m[2] + m[4];
     var yt = p[0] * m[1] + p[1] * m[3] + m[5];
     return [xt, yt];
   };
 
-  return constructor;
+  // Apply a generic 3d matrix M on a 3-vector v:
+  //   | a b c |   | X |
+  //   | d e f | x | Y |
+  //   | g h i |   | Z |
+  // M is assumed to be serialized as [a,b,c,d,e,f,g,h,i],
+  // with v as [X,Y,Z]
+  Util.apply3dTransform = function Util_apply3dTransform(m, v) {
+    return [
+      m[0] * v[0] + m[1] * v[1] + m[2] * v[2],
+      m[3] * v[0] + m[4] * v[1] + m[5] * v[2],
+      m[6] * v[0] + m[7] * v[1] + m[8] * v[2]
+    ];
+  }
+
+  // Normalize rectangle rect=[x1, y1, x2, y2] so that (x1,y1) < (x2,y2)
+  // For coordinate systems whose origin lies in the bottom-left, this
+  // means normalization to (BL,TR) ordering. For systems with origin in the
+  // top-left, this means (TL,BR) ordering.
+  Util.normalizeRect = function Util_normalizeRect(rect) {
+    var r = rect.slice(0); // clone rect
+    if (rect[0] > rect[2]) {
+      r[0] = rect[2];
+      r[2] = rect[0];
+    }
+    if (rect[1] > rect[3]) {
+      r[1] = rect[3];
+      r[3] = rect[1];
+    }
+    return r;
+  }
+
+  // Returns a rectangle [x1, y1, x2, y2] corresponding to the
+  // intersection of rect1 and rect2. If no intersection, returns 'false'
+  // The rectangle coordinates of rect1, rect2 should be [x1, y1, x2, y2]
+  Util.intersect = function Util_intersect(rect1, rect2) {
+    function compare(a, b) {
+      return a - b;
+    };
+
+    // Order points along the axes
+    var orderedX = [rect1[0], rect1[2], rect2[0], rect2[2]].sort(compare),
+        orderedY = [rect1[1], rect1[3], rect2[1], rect2[3]].sort(compare),
+        result = [];
+
+    rect1 = Util.normalizeRect(rect1);
+    rect2 = Util.normalizeRect(rect2);
+
+    // X: first and second points belong to different rectangles?
+    if ((orderedX[0] === rect1[0] && orderedX[1] === rect2[0]) ||
+        (orderedX[0] === rect2[0] && orderedX[1] === rect1[0])) {
+      // Intersection must be between second and third points
+      result[0] = orderedX[1];
+      result[2] = orderedX[2];
+    } else {
+      return false;
+    }
+
+    // Y: first and second points belong to different rectangles?
+    if ((orderedY[0] === rect1[1] && orderedY[1] === rect2[1]) ||
+        (orderedY[0] === rect2[1] && orderedY[1] === rect1[1])) {
+      // Intersection must be between second and third points
+      result[1] = orderedY[1];
+      result[3] = orderedY[2];
+    } else {
+      return false;
+    }
+
+    return result;
+  }
+
+  Util.sign = function Util_sign(num) {
+    return num < 0 ? -1 : 1;
+  };
+
+  return Util;
 })();
 
 var PDFStringTranslateTable = [
@@ -197,7 +275,7 @@ function isPDFFunction(v) {
  * can be set. If any of these happens twice or the data is required before
  * it was set, an exception is throw.
  */
-var Promise = (function promise() {
+var Promise = (function PromiseClosure() {
   var EMPTY_PROMISE = {};
 
   /**
@@ -206,6 +284,8 @@ var Promise = (function promise() {
    */
   function Promise(name, data) {
     this.name = name;
+    this.isRejected = false;
+    this.error = null;
     // If you build a promise and pass in some data it's already resolved.
     if (data != null) {
       this.isResolved = true;
@@ -216,8 +296,35 @@ var Promise = (function promise() {
       this._data = EMPTY_PROMISE;
     }
     this.callbacks = [];
+    this.errbacks = [];
+  };
+  /**
+   * Builds a promise that is resolved when all the passed in promises are
+   * resolved.
+   * @param {Promise[]} promises Array of promises to wait for.
+   * @return {Promise} New dependant promise.
+   */
+  Promise.all = function Promise_all(promises) {
+    var deferred = new Promise();
+    var unresolved = promises.length;
+    var results = [];
+    if (unresolved === 0) {
+      deferred.resolve(results);
+      return deferred;
+    }
+    for (var i = 0; i < unresolved; ++i) {
+      var promise = promises[i];
+      promise.then((function(i) {
+        return function(value) {
+          results[i] = value;
+          unresolved--;
+          if (unresolved === 0)
+            deferred.resolve(results);
+        };
+      })(i));
+    }
+    return deferred;
   };
-
   Promise.prototype = {
     hasData: false,
 
@@ -226,8 +333,8 @@ var Promise = (function promise() {
         return;
       }
       if (this._data !== EMPTY_PROMISE) {
-        throw 'Promise ' + this.name +
-                                ': Cannot set the data of a promise twice';
+        error('Promise ' + this.name +
+              ': Cannot set the data of a promise twice');
       }
       this._data = value;
       this.hasData = true;
@@ -239,12 +346,12 @@ var Promise = (function promise() {
 
     get data() {
       if (this._data === EMPTY_PROMISE) {
-        throw 'Promise ' + this.name + ': Cannot get data that isn\'t set';
+        error('Promise ' + this.name + ': Cannot get data that isn\'t set');
       }
       return this._data;
     },
 
-    onData: function promiseOnData(callback) {
+    onData: function Promise_onData(callback) {
       if (this._data !== EMPTY_PROMISE) {
         callback(this._data);
       } else {
@@ -252,13 +359,16 @@ var Promise = (function promise() {
       }
     },
 
-    resolve: function promiseResolve(data) {
+    resolve: function Promise_resolve(data) {
       if (this.isResolved) {
-        throw 'A Promise can be resolved only once ' + this.name;
+        error('A Promise can be resolved only once ' + this.name);
+      }
+      if (this.isRejected) {
+        error('The Promise was already rejected ' + this.name);
       }
 
       this.isResolved = true;
-      this.data = data;
+      this.data = data || null;
       var callbacks = this.callbacks;
 
       for (var i = 0, ii = callbacks.length; i < ii; i++) {
@@ -266,17 +376,39 @@ var Promise = (function promise() {
       }
     },
 
-    then: function promiseThen(callback) {
+    reject: function Promise_reject(reason) {
+      if (this.isRejected) {
+        error('A Promise can be rejected only once ' + this.name);
+      }
+      if (this.isResolved) {
+        error('The Promise was already resolved ' + this.name);
+      }
+
+      this.isRejected = true;
+      this.error = reason || null;
+      var errbacks = this.errbacks;
+
+      for (var i = 0, ii = errbacks.length; i < ii; i++) {
+        errbacks[i].call(null, reason);
+      }
+    },
+
+    then: function Promise_then(callback, errback) {
       if (!callback) {
-        throw 'Requiring callback' + this.name;
+        error('Requiring callback' + this.name);
       }
 
       // If the promise is already resolved, call the callback directly.
       if (this.isResolved) {
         var data = this.data;
         callback.call(null, data);
+      } else if (this.isRejected && errback) {
+        var error = this.error;
+        errback.call(null, error);
       } else {
         this.callbacks.push(callback);
+        if (errback)
+          this.errbacks.push(errback);
       }
     }
   };
@@ -284,3 +416,55 @@ var Promise = (function promise() {
   return Promise;
 })();
 
+var StatTimer = (function StatTimerClosure() {
+  function rpad(str, pad, length) {
+    while (str.length < length)
+      str += pad;
+    return str;
+  }
+  function StatTimer() {
+    this.started = {};
+    this.times = [];
+    this.enabled = true;
+  }
+  StatTimer.prototype = {
+    time: function StatTimer_time(name) {
+      if (!this.enabled)
+        return;
+      if (name in this.started)
+        throw 'Timer is already running for ' + name;
+      this.started[name] = Date.now();
+    },
+    timeEnd: function StatTimer_timeEnd(name) {
+      if (!this.enabled)
+        return;
+      if (!(name in this.started))
+        throw 'Timer has not been started for ' + name;
+      this.times.push({
+        'name': name,
+        'start': this.started[name],
+        'end': Date.now()
+      });
+      // Remove timer from started so it can be called again.
+      delete this.started[name];
+    },
+    toString: function StatTimer_toString() {
+      var times = this.times;
+      var out = '';
+      // Find the longest name for padding purposes.
+      var longest = 0;
+      for (var i = 0, ii = times.length; i < ii; ++i) {
+        var name = times[i]['name'];
+        if (name.length > longest)
+          longest = name.length;
+      }
+      for (var i = 0, ii = times.length; i < ii; ++i) {
+        var span = times[i];
+        var duration = span.end - span.start;
+        out += rpad(span['name'], ' ', longest) + ' ' + duration + 'ms\n';
+      }
+      return out;
+    }
+  };
+  return StatTimer;
+})();
diff --git a/apps/files_pdfviewer/js/pdfjs/src/utils/cffStandardStrings.js b/apps/files_pdfviewer/js/pdfjs/src/utils/cffStandardStrings.js
old mode 100755
new mode 100644
diff --git a/apps/files_pdfviewer/js/pdfjs/src/utils/fonts_utils.js b/apps/files_pdfviewer/js/pdfjs/src/utils/fonts_utils.js
old mode 100755
new mode 100644
index 2a1f0ea72ae02d17c78f2be40e8b1172d11fd415..65c02fce2772550181f630e0f9f94204136f28c7
--- a/apps/files_pdfviewer/js/pdfjs/src/utils/fonts_utils.js
+++ b/apps/files_pdfviewer/js/pdfjs/src/utils/fonts_utils.js
@@ -122,9 +122,9 @@ function readFontDictData(aString, aMap) {
       token = '';
       var parsed = false;
       while (!parsed) {
-        var byte = aString[i++];
+        var octet = aString[i++];
 
-        var nibbles = [parseInt(byte / 16, 10), parseInt(byte % 16, 10)];
+        var nibbles = [parseInt(octet / 16, 10), parseInt(octet % 16, 10)];
         for (var j = 0; j < nibbles.length; j++) {
           var nibble = nibbles[j];
           switch (nibble) {
@@ -336,7 +336,7 @@ var Type2Parser = function type2Parser(aFilePath) {
     var privateDict = [];
     for (var i = 0; i < priv.size; i++)
       privateDict.push(aStream.getByte());
-    dump('private:' + privateDict);
+    dump('privateData:' + privateDict);
     parseAsToken(privateDict, CFFDictPrivateDataMap);
 
     for (var p in font.map)
diff --git a/apps/files_pdfviewer/js/pdfjs/src/worker.js b/apps/files_pdfviewer/js/pdfjs/src/worker.js
old mode 100755
new mode 100644
index 67f1bf658e10e6366d0a3e63d56477c728afc94d..42bd610503f7721a9becffabfc1c2dcc324d2ff3
--- a/apps/files_pdfviewer/js/pdfjs/src/worker.js
+++ b/apps/files_pdfviewer/js/pdfjs/src/worker.js
@@ -6,6 +6,8 @@
 function MessageHandler(name, comObj) {
   this.name = name;
   this.comObj = comObj;
+  this.callbackIndex = 1;
+  var callbacks = this.callbacks = {};
   var ah = this.actionHandler = {};
 
   ah['console_log'] = [function ahConsoleLog(data) {
@@ -17,11 +19,32 @@ function MessageHandler(name, comObj) {
 
   comObj.onmessage = function messageHandlerComObjOnMessage(event) {
     var data = event.data;
-    if (data.action in ah) {
+    if (data.isReply) {
+      var callbackId = data.callbackId;
+      if (data.callbackId in callbacks) {
+        var callback = callbacks[callbackId];
+        delete callbacks[callbackId];
+        callback(data.data);
+      } else {
+        error('Cannot resolve callback ' + callbackId);
+      }
+    } else if (data.action in ah) {
       var action = ah[data.action];
-      action[0].call(action[1], data.data);
+      if (data.callbackId) {
+        var promise = new Promise();
+        promise.then(function(resolvedData) {
+          comObj.postMessage({
+            isReply: true,
+            callbackId: data.callbackId,
+            data: resolvedData
+          });
+        });
+        action[0].call(action[1], data.data, promise);
+      } else {
+        action[0].call(action[1], data.data);
+      }
     } else {
-      throw 'Unkown action from worker: ' + data.action;
+      error('Unkown action from worker: ' + data.action);
     }
   };
 }
@@ -30,44 +53,47 @@ MessageHandler.prototype = {
   on: function messageHandlerOn(actionName, handler, scope) {
     var ah = this.actionHandler;
     if (ah[actionName]) {
-      throw 'There is already an actionName called "' + actionName + '"';
+      error('There is already an actionName called "' + actionName + '"');
     }
     ah[actionName] = [handler, scope];
   },
-
-  send: function messageHandlerSend(actionName, data) {
-    this.comObj.postMessage({
+  /**
+   * Sends a message to the comObj to invoke the action with the supplied data.
+   * @param {String} actionName Action to call.
+   * @param {JSON} data JSON data to send.
+   * @param {function} [callback] Optional callback that will handle a reply.
+   */
+  send: function messageHandlerSend(actionName, data, callback) {
+    var message = {
       action: actionName,
       data: data
-    });
+    };
+    if (callback) {
+      var callbackId = this.callbackIndex++;
+      this.callbacks[callbackId] = callback;
+      message.callbackId = callbackId;
+    }
+    this.comObj.postMessage(message);
   }
 };
 
 var WorkerMessageHandler = {
   setup: function wphSetup(handler) {
-    var pdfDoc = null;
+    var pdfModel = null;
 
     handler.on('test', function wphSetupTest(data) {
       handler.send('test', data instanceof Uint8Array);
     });
 
-    handler.on('workerSrc', function wphSetupWorkerSrc(data) {
-      // In development, the `workerSrc` message is handled in the
-      // `worker_loader.js` file. In production the workerProcessHandler is
-      // called for this. This servers as a dummy to prevent calling an
-      // undefined action `workerSrc`.
-    });
-
     handler.on('doc', function wphSetupDoc(data) {
       // Create only the model of the PDFDoc, which is enough for
       // processing the content of the pdf.
-      pdfDoc = new PDFDocModel(new Stream(data));
+      pdfModel = new PDFDocModel(new Stream(data));
     });
 
     handler.on('page_request', function wphSetupPageRequest(pageNum) {
       pageNum = parseInt(pageNum);
 
-      var page = pdfDoc.getPage(pageNum);
 
       // The following code does quite the same as
       // Page.prototype.startRendering, but stops at one point and sends the
@@ -77,12 +103,42 @@ var WorkerMessageHandler = {
       var start = Date.now();
 
       var dependency = [];
+      var operatorList = null;
+      try {
+        var page = pdfModel.getPage(pageNum);
+        // Pre compile the pdf page and fetch the fonts/images.
+        operatorList = page.getOperatorList(handler, dependency);
+      } catch (e) {
+        var minimumStackMessage =
+            'worker.js: while trying to getPage() and getOperatorList()';
+
+        // Turn the error into an obj that can be serialized
+        if (typeof e === 'string') {
+          e = {
+            message: e,
+            stack: minimumStackMessage
+          };
+        } else if (typeof e === 'object') {
+          e = {
+            message: e.message || e.toString(),
+            stack: e.stack || minimumStackMessage
+          };
+        } else {
+          e = {
+            message: 'Unknown exception type: ' + (typeof e),
+            stack: minimumStackMessage
+          };
+        }
 
-      // Pre compile the pdf page and fetch the fonts/images.
-      var IRQueue = page.getIRQueue(handler, dependency);
+        handler.send('page_error', {
+          pageNum: pageNum,
+          error: e
+        });
+        return;
+      }
 
-      console.log('page=%d - getIRQueue: time=%dms, len=%d', pageNum,
-                                  Date.now() - start, IRQueue.fnArray.length);
+      console.log('page=%d - getOperatorList: time=%dms, len=%d', pageNum,
+                              Date.now() - start, operatorList.fnArray.length);
 
       // Filter the dependecies for fonts.
       var fonts = {};
@@ -95,59 +151,10 @@ var WorkerMessageHandler = {
 
       handler.send('page', {
         pageNum: pageNum,
-        IRQueue: IRQueue,
+        operatorList: operatorList,
         depFonts: Object.keys(fonts)
       });
     }, this);
-
-    handler.on('font', function wphSetupFont(data) {
-      var objId = data[0];
-      var name = data[1];
-      var file = data[2];
-      var properties = data[3];
-
-      var font = {
-        name: name,
-        file: file,
-        properties: properties
-      };
-
-      // Some fonts don't have a file, e.g. the build in ones like Arial.
-      if (file) {
-        var fontFileDict = new Dict();
-        fontFileDict.map = file.dict.map;
-
-        var fontFile = new Stream(file.bytes, file.start,
-                                  file.end - file.start, fontFileDict);
-
-        // Check if this is a FlateStream. Otherwise just use the created
-        // Stream one. This makes complex_ttf_font.pdf work.
-        var cmf = file.bytes[0];
-        if ((cmf & 0x0f) == 0x08) {
-          font.file = new FlateStream(fontFile);
-        } else {
-          font.file = fontFile;
-        }
-      }
-
-      var obj = new Font(font.name, font.file, font.properties);
-
-      var str = '';
-      var objData = obj.data;
-      if (objData) {
-        var length = objData.length;
-        for (var j = 0; j < length; ++j)
-          str += String.fromCharCode(objData[j]);
-      }
-
-      obj.str = str;
-
-      // Remove the data array form the font object, as it's not needed
-      // anymore as we sent over the ready str.
-      delete obj.data;
-
-      handler.send('font_ready', [objId, obj]);
-    });
   }
 };
 
@@ -168,6 +175,7 @@ var workerConsole = {
       action: 'console_error',
       data: args
     });
+    throw 'pdf.js execution error';
   },
 
   time: function time(name) {
@@ -177,7 +185,7 @@ var workerConsole = {
   timeEnd: function timeEnd(name) {
     var time = consoleTimer[name];
     if (time == null) {
-      throw 'Unkown timer name ' + name;
+      error('Unkown timer name ' + name);
     }
     this.log('Timer:', name, Date.now() - time);
   }
diff --git a/apps/files_pdfviewer/js/pdfjs/src/worker_loader.js b/apps/files_pdfviewer/js/pdfjs/src/worker_loader.js
old mode 100755
new mode 100644
index 7141fa3e39d7f02b463ab7cda7f0a80bde395241..69eb1414f0bd79d694885e4a33d44d7821bb833e
--- a/apps/files_pdfviewer/js/pdfjs/src/worker_loader.js
+++ b/apps/files_pdfviewer/js/pdfjs/src/worker_loader.js
@@ -3,51 +3,32 @@
 
 'use strict';
 
-function onMessageLoader(evt) {
-  // Reset the `onmessage` function as it was only set to call
-  // this function the first time a message is passed to the worker
-  // but shouldn't get called anytime afterwards.
-  this.onmessage = null;
-
-  if (evt.data.action !== 'workerSrc') {
-    throw 'Worker expects first message to be `workerSrc`';
-  }
-
-  // Content of `PDFJS.workerSrc` as defined on the main thread.
-  var workerSrc = evt.data.data;
-
-  // Extract the directory that contains the source files to load.
-  // Assuming the source files have the same relative possition as the
-  // `workerSrc` file.
-  var dir = workerSrc.substring(0, workerSrc.lastIndexOf('/') + 1);
-
-  // List of files to include;
-  var files = [
-    'core.js',
-    'util.js',
-    'canvas.js',
-    'obj.js',
-    'function.js',
-    'charsets.js',
-    'cidmaps.js',
-    'colorspace.js',
-    'crypto.js',
-    'evaluator.js',
-    'fonts.js',
-    'glyphlist.js',
-    'image.js',
-    'metrics.js',
-    'parser.js',
-    'pattern.js',
-    'stream.js',
-    'worker.js',
-    '../external/jpgjs/jpg.js'
-  ];
-
-  // Load all the files.
-  for (var i = 0; i < files.length; i++) {
-    importScripts(dir + files[i]);
-  }
+// List of files to include;
+var files = [
+  'core.js',
+  'util.js',
+  'canvas.js',
+  'obj.js',
+  'function.js',
+  'charsets.js',
+  'cidmaps.js',
+  'colorspace.js',
+  'crypto.js',
+  'evaluator.js',
+  'fonts.js',
+  'glyphlist.js',
+  'image.js',
+  'metrics.js',
+  'parser.js',
+  'pattern.js',
+  'stream.js',
+  'worker.js',
+  '../external/jpgjs/jpg.js',
+  'jpx.js',
+  'bidi.js'
+];
+
+// Load all the files.
+for (var i = 0; i < files.length; i++) {
+  importScripts(files[i]);
 }
-
-this.onmessage = onMessageLoader;
diff --git a/apps/files_pdfviewer/js/pdfjs/web/images/bookmark.svg b/apps/files_pdfviewer/js/pdfjs/web/images/bookmark.svg
old mode 100755
new mode 100644
index 2c1fa130d174e9d0883476bc29291e41c264c28f..bee6efefdfb418ca5741a65f510b297f0642621a
--- a/apps/files_pdfviewer/js/pdfjs/web/images/bookmark.svg
+++ b/apps/files_pdfviewer/js/pdfjs/web/images/bookmark.svg
@@ -20,7 +20,8 @@
    height="48.000000px"
    width="48.000000px"
    inkscape:output_extension="org.inkscape.output.svg.inkscape"
-   version="1.1">
+   version="1.1"
+   viewbox="0 0 48 48">
   <defs
      id="defs3">
     <inkscape:perspective
diff --git a/apps/files_pdfviewer/js/pdfjs/web/images/check.svg b/apps/files_pdfviewer/js/pdfjs/web/images/check.svg
new file mode 100644
index 0000000000000000000000000000000000000000..e0e1590a937c5232633e3ff226a1098cd52097e3
--- /dev/null
+++ b/apps/files_pdfviewer/js/pdfjs/web/images/check.svg
@@ -0,0 +1,3 @@
+<svg height="40" width="40" xmlns="http://www.w3.org/2000/svg">
+  <path d="M2.379,14.729 5.208,11.899 12.958,19.648 25.877,6.733 28.707,9.561 12.958,25.308z" fill="#333333"></path>
+</svg>
diff --git a/apps/files_pdfviewer/js/pdfjs/web/images/comment.svg b/apps/files_pdfviewer/js/pdfjs/web/images/comment.svg
new file mode 100644
index 0000000000000000000000000000000000000000..84feef1c89f7f077e42748028c37f6ed45029b3c
--- /dev/null
+++ b/apps/files_pdfviewer/js/pdfjs/web/images/comment.svg
@@ -0,0 +1,3 @@
+<svg height="40" width="40" xmlns="http://www.w3.org/2000/svg">
+  <path d="M16,5.333c-7.732,0-14,4.701-14,10.5c0,1.982,0.741,3.833,2.016,5.414L2,25.667l5.613-1.441c2.339,1.317,5.237,2.107,8.387,2.107c7.732,0,14-4.701,14-10.5C30,10.034,23.732,5.333,16,5.333z" fill="#333333"></path>
+</svg>
diff --git a/apps/files_pdfviewer/js/pdfjs/web/images/document-print.svg b/apps/files_pdfviewer/js/pdfjs/web/images/document-print.svg
old mode 100755
new mode 100644
index 0b8837ba1df643c64257b24ebaa0b6c5394a78c2..4d062fbb69a9a225a68dec936e1995079e2aaaac
--- a/apps/files_pdfviewer/js/pdfjs/web/images/document-print.svg
+++ b/apps/files_pdfviewer/js/pdfjs/web/images/document-print.svg
@@ -16,7 +16,8 @@
    id="svg2994"
    height="48px"
    width="48px"
-   inkscape:output_extension="org.inkscape.output.svg.inkscape">
+   inkscape:output_extension="org.inkscape.output.svg.inkscape"
+   viewbox="0 0 48 48">
   <defs
      id="defs3">
     <inkscape:perspective
diff --git a/apps/files_pdfviewer/js/pdfjs/web/images/download.svg b/apps/files_pdfviewer/js/pdfjs/web/images/download.svg
old mode 100755
new mode 100644
index 2922c4331a7f566ada86784b0b96be5d44035d7c..884e3deed553e1990b9f2b5e433f5d90e26d90ce
--- a/apps/files_pdfviewer/js/pdfjs/web/images/download.svg
+++ b/apps/files_pdfviewer/js/pdfjs/web/images/download.svg
@@ -16,7 +16,8 @@
    id="svg2913"
    height="48px"
    width="48px"
-   inkscape:output_extension="org.inkscape.output.svg.inkscape">
+   inkscape:output_extension="org.inkscape.output.svg.inkscape"
+   viewbox="0 0 48 48">
   <defs
      id="defs3">
     <inkscape:perspective
diff --git a/apps/files_pdfviewer/js/pdfjs/web/images/go-down.svg b/apps/files_pdfviewer/js/pdfjs/web/images/go-down.svg
old mode 100755
new mode 100644
index 95b82afd11f63166b2f07d335b8a35951f667b14..655fdba16dcde0423686d3dfb00ad21eff4c4fdb
--- a/apps/files_pdfviewer/js/pdfjs/web/images/go-down.svg
+++ b/apps/files_pdfviewer/js/pdfjs/web/images/go-down.svg
@@ -19,7 +19,8 @@
    inkscape:export-filename="/home/jimmac/Desktop/wi-fi.png"
    inkscape:export-xdpi="90.000000"
    inkscape:export-ydpi="90.000000"
-   inkscape:output_extension="org.inkscape.output.svg.inkscape">
+   inkscape:output_extension="org.inkscape.output.svg.inkscape"
+   viewbox="0 0 48 48">
   <defs
      id="defs3">
     <inkscape:perspective
diff --git a/apps/files_pdfviewer/js/pdfjs/web/images/go-up.svg b/apps/files_pdfviewer/js/pdfjs/web/images/go-up.svg
old mode 100755
new mode 100644
index 54263df3e53745c408e187863ac8ad67aa803f11..5e2f9a2c645bdfabc0f7f4a5ce5eb6f8f0ee23ca
--- a/apps/files_pdfviewer/js/pdfjs/web/images/go-up.svg
+++ b/apps/files_pdfviewer/js/pdfjs/web/images/go-up.svg
@@ -19,7 +19,8 @@
    inkscape:export-filename="/home/jimmac/Desktop/wi-fi.png"
    inkscape:export-xdpi="90.000000"
    inkscape:export-ydpi="90.000000"
-   inkscape:output_extension="org.inkscape.output.svg.inkscape">
+   inkscape:output_extension="org.inkscape.output.svg.inkscape"
+   viewbox="0 0 48 48">
   <defs
      id="defs3">
     <inkscape:perspective
diff --git a/apps/files_pdfviewer/js/pdfjs/web/images/nav-outline.svg b/apps/files_pdfviewer/js/pdfjs/web/images/nav-outline.svg
old mode 100755
new mode 100644
diff --git a/apps/files_pdfviewer/js/pdfjs/web/images/nav-thumbs.svg b/apps/files_pdfviewer/js/pdfjs/web/images/nav-thumbs.svg
old mode 100755
new mode 100644
diff --git a/apps/files_pdfviewer/js/pdfjs/web/images/pin-down.svg b/apps/files_pdfviewer/js/pdfjs/web/images/pin-down.svg
new file mode 100644
index 0000000000000000000000000000000000000000..357667600b30ebef6191c1501caf7398e0e8acc1
--- /dev/null
+++ b/apps/files_pdfviewer/js/pdfjs/web/images/pin-down.svg
@@ -0,0 +1,297 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:xlink="http://www.w3.org/1999/xlink"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="48"
+   height="48"
+   id="svg3075"
+   version="1.1"
+   inkscape:version="0.48.1 r9760"
+   sodipodi:docname="pin-down.svg"
+   viewPort="0 0 48 48">
+  <defs
+     id="defs3077">
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient3804">
+      <stop
+         style="stop-color:#000000;stop-opacity:1;"
+         offset="0"
+         id="stop3806" />
+      <stop
+         style="stop-color:#000000;stop-opacity:0;"
+         offset="1"
+         id="stop3808" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient3965">
+      <stop
+         id="stop3967"
+         offset="0"
+         style="stop-color:#ffffff;stop-opacity:1;" />
+      <stop
+         style="stop-color:#ffffff;stop-opacity:0"
+         offset="1"
+         id="stop3969" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient3885">
+      <stop
+         style="stop-color:#a8b5e9;stop-opacity:1;"
+         offset="0"
+         id="stop3889" />
+      <stop
+         id="stop3891"
+         offset="1"
+         style="stop-color:#1d4488;stop-opacity:1;" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient3865">
+      <stop
+         style="stop-color:#0e0ec3;stop-opacity:0"
+         offset="0"
+         id="stop3867" />
+      <stop
+         id="stop3883"
+         offset="0.5"
+         style="stop-color:#95b1e4;stop-opacity:1;" />
+      <stop
+         style="stop-color:#0d29c0;stop-opacity:1;"
+         offset="1"
+         id="stop3869" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient3853">
+      <stop
+         style="stop-color:#717171;stop-opacity:1;"
+         offset="0"
+         id="stop3855" />
+      <stop
+         id="stop3861"
+         offset="0.5"
+         style="stop-color:#ffffff;stop-opacity:1;" />
+      <stop
+         style="stop-color:#818181;stop-opacity:1;"
+         offset="1"
+         id="stop3857" />
+    </linearGradient>
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3885"
+       id="radialGradient3792"
+       cx="13.508819"
+       cy="30.521608"
+       fx="13.508819"
+       fy="30.521608"
+       r="13.254341"
+       gradientTransform="matrix(1,0,0,1.045977,0,-1.4434017)"
+       gradientUnits="userSpaceOnUse" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3885"
+       id="linearGradient3802"
+       x1="15.306904"
+       y1="13.407407"
+       x2="29.35461"
+       y2="30.15519"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1.2304178,0,0,1.1235308,-2.1158755,998.83747)" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3804"
+       id="radialGradient3812"
+       cx="20.111172"
+       cy="28.238274"
+       fx="20.111172"
+       fy="28.238274"
+       r="7.6291947"
+       gradientTransform="matrix(1.2304178,0,0,1.1452771,-2.1158755,998.22337)"
+       gradientUnits="userSpaceOnUse" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3885"
+       id="radialGradient3822"
+       cx="23.985939"
+       cy="24.847366"
+       fx="23.985939"
+       fy="24.847366"
+       r="10.593476"
+       gradientTransform="matrix(0.63682384,0.44303926,-1.1714282,1.6838088,35.523491,-26.055439)"
+       gradientUnits="userSpaceOnUse" />
+    <filter
+       inkscape:collect="always"
+       id="filter3856"
+       x="-0.30370581"
+       width="1.6074116"
+       y="-0.32771564"
+       height="1.6554313">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="4.7808869"
+         id="feGaussianBlur3858" />
+    </filter>
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3885"
+       id="radialGradient3865"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1,0,0,1.045977,0,-1.4434017)"
+       cx="13.508819"
+       cy="30.521608"
+       fx="13.508819"
+       fy="30.521608"
+       r="13.254341" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3885"
+       id="linearGradient3867"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1.2304178,0,0,1.1235308,-2.1158755,998.83747)"
+       x1="15.306904"
+       y1="13.407407"
+       x2="29.35461"
+       y2="30.15519" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3804"
+       id="radialGradient3869"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1.2304178,0,0,1.1452771,-2.1158755,998.22337)"
+       cx="20.111172"
+       cy="28.238274"
+       fx="20.111172"
+       fy="28.238274"
+       r="7.6291947" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3885"
+       id="radialGradient3871"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.63682384,0.44303926,-1.1714282,1.6838088,35.523491,-26.055439)"
+       cx="23.985939"
+       cy="24.847366"
+       fx="23.985939"
+       fy="24.847366"
+       r="10.593476" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3885"
+       id="linearGradient3875"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.98683814,0,0,0.9524914,3.4991888,1004.1467)"
+       x1="15.306904"
+       y1="13.407407"
+       x2="29.35461"
+       y2="30.15519" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3804"
+       id="radialGradient3877"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1.195641,0.23932984,-0.18533175,0.95255553,4.5333676,999.33159)"
+       cx="20.111172"
+       cy="28.238274"
+       fx="20.111172"
+       fy="28.238274"
+       r="7.6291947" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3885"
+       id="radialGradient3880"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1.5847553,0.52693722,-0.99805104,2.7064773,14.11088,-45.304477)"
+       cx="18.133854"
+       cy="19.778509"
+       fx="18.133854"
+       fy="19.778509"
+       r="10.593476" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3885"
+       id="radialGradient3882"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1,0,0,1.045977,0,-1.4434017)"
+       cx="13.508819"
+       cy="30.521608"
+       fx="13.508819"
+       fy="30.521608"
+       r="13.254341" />
+  </defs>
+  <sodipodi:namedview
+     id="base"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageopacity="0.0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="4.9558805"
+     inkscape:cx="3.0237013"
+     inkscape:cy="17.287267"
+     inkscape:document-units="px"
+     inkscape:current-layer="layer1"
+     showgrid="false"
+     inkscape:window-width="1291"
+     inkscape:window-height="776"
+     inkscape:window-x="16"
+     inkscape:window-y="0"
+     inkscape:window-maximized="0" />
+  <metadata
+     id="metadata3080">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title />
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <g
+     inkscape:label="Layer 1"
+     inkscape:groupmode="layer"
+     id="layer1"
+     transform="translate(0,-1004.3622)">
+    <path
+       style="fill:#ffffff;fill-opacity:1;stroke:none;filter:url(#filter3856)"
+       d="m 14.326415,1019.2702 c -8.3327876,4.0675 -9.8235436,10.8833 -8.8783416,15.1336 4.6840646,7.9754 8.3608166,13.8165 24.0118786,12.9139 9.657617,-3.7312 12.9762,-9.3269 13.519293,-15.7389 -0.547269,-4.3839 -1.957958,-9.3396 -5.649854,-14.9317 -3.965534,-2.471 -6.300859,-4.4246 -10.290805,-4.2374 -8.25193,0.5026 -8.752485,4.4502 -12.712171,6.8605 z"
+       id="path3826"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="ccccccc"
+       transform="matrix(0.69099294,0,0,0.75978808,7.3427938,249.11025)" />
+    <path
+       sodipodi:type="arc"
+       style="fill:url(#radialGradient3882);fill-opacity:1;stroke:none"
+       id="path3011"
+       sodipodi:cx="21.176477"
+       sodipodi:cy="31.393986"
+       sodipodi:rx="13.254341"
+       sodipodi:ry="13.863736"
+       d="m 34.430819,31.393986 a 13.254341,13.863736 0 1 1 -26.5086827,0 13.254341,13.863736 0 1 1 26.5086827,0 z"
+       transform="matrix(0.98683814,0,0,0.83062636,2.696034,1005.3655)" />
+    <path
+       style="fill:url(#linearGradient3875);fill-opacity:1;stroke:url(#radialGradient3877);stroke-width:0.9695127;stroke-opacity:1"
+       d="m 17.246758,1026.7905 c -1.7156,4.5052 -2.482464,10.6205 8.726963,10.7476 4.849099,-1.8941 3.522783,-5.3561 6.021544,-11.8282 l -10.973104,-1.5977 z"
+       id="path3794"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="ccccc" />
+    <path
+       sodipodi:type="arc"
+       style="fill:url(#radialGradient3880);fill-opacity:1;stroke:none"
+       id="path3814"
+       sodipodi:cx="24.718111"
+       sodipodi:cy="23.38278"
+       sodipodi:rx="10.593476"
+       sodipodi:ry="9.6854639"
+       d="m 35.311587,23.38278 a 10.593476,9.6854639 0 1 1 -21.186952,0 10.593476,9.6854639 0 1 1 21.186952,0 z"
+       transform="matrix(0.85425691,0,0,0.84187503,3.9779774,1006.7561)" />
+  </g>
+</svg>
diff --git a/apps/files_pdfviewer/js/pdfjs/web/images/pin-up.svg b/apps/files_pdfviewer/js/pdfjs/web/images/pin-up.svg
new file mode 100644
index 0000000000000000000000000000000000000000..e55cec7a044b3e3230452f3bed86d6c37c3fad38
--- /dev/null
+++ b/apps/files_pdfviewer/js/pdfjs/web/images/pin-up.svg
@@ -0,0 +1,230 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:xlink="http://www.w3.org/1999/xlink"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="48"
+   height="48"
+   id="svg3075"
+   version="1.1"
+   inkscape:version="0.48.1 r9760"
+   sodipodi:docname="pin-up.svg"
+   viewPort="0 0 48 48">
+  <defs
+     id="defs3077">
+    <linearGradient
+       id="linearGradient3965">
+      <stop
+         id="stop3967"
+         offset="0"
+         style="stop-color:#ffffff;stop-opacity:1;" />
+      <stop
+         style="stop-color:#ffffff;stop-opacity:0"
+         offset="1"
+         id="stop3969" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient3885">
+      <stop
+         style="stop-color:#a8b5e9;stop-opacity:1;"
+         offset="0"
+         id="stop3889" />
+      <stop
+         id="stop3891"
+         offset="1"
+         style="stop-color:#1d4488;stop-opacity:1;" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient3865">
+      <stop
+         style="stop-color:#0e0ec3;stop-opacity:1;"
+         offset="0"
+         id="stop3867" />
+      <stop
+         id="stop3883"
+         offset="0.5"
+         style="stop-color:#95b1e4;stop-opacity:1;" />
+      <stop
+         style="stop-color:#0d29c0;stop-opacity:1;"
+         offset="1"
+         id="stop3869" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient3853">
+      <stop
+         style="stop-color:#717171;stop-opacity:1;"
+         offset="0"
+         id="stop3855" />
+      <stop
+         id="stop3861"
+         offset="0.5"
+         style="stop-color:#ffffff;stop-opacity:1;" />
+      <stop
+         style="stop-color:#818181;stop-opacity:1;"
+         offset="1"
+         id="stop3857" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3853"
+       id="linearGradient3859"
+       x1="7.7696066"
+       y1="34.979828"
+       x2="11.854106"
+       y2="39.107044"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="translate(4.8388015,1001.6582)" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3885"
+       id="radialGradient3871"
+       cx="14.801222"
+       cy="1030.6609"
+       fx="14.801222"
+       fy="1030.6609"
+       r="10.177785"
+       gradientTransform="matrix(1,0,0,1.0108042,4.8388015,-13.880529)"
+       gradientUnits="userSpaceOnUse" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3865"
+       id="linearGradient3881"
+       x1="15.012629"
+       y1="11.922465"
+       x2="31.098303"
+       y2="28.858271"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1,0,0,0.97315436,4.8388015,1002.4769)" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3885"
+       id="radialGradient3909"
+       cx="16.437693"
+       cy="22.596292"
+       fx="16.437693"
+       fy="22.596292"
+       r="1.7789712"
+       gradientTransform="matrix(1,0,0,8.3599999,0,-166.30871)"
+       gradientUnits="userSpaceOnUse" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3865"
+       id="linearGradient3927"
+       x1="26.47109"
+       y1="1010.7343"
+       x2="35.294788"
+       y2="1019.8425"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="translate(4.5541661,-2.1347654)" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3965"
+       id="radialGradient3995"
+       cx="23.189369"
+       cy="25.704245"
+       fx="23.189369"
+       fy="25.704245"
+       r="37.336674"
+       gradientTransform="matrix(1,0,0,1.0332422,0,-0.85446479)"
+       gradientUnits="userSpaceOnUse" />
+    <filter
+       inkscape:collect="always"
+       id="filter4009"
+       x="-0.19299152"
+       width="1.385983"
+       y="-0.18351803"
+       height="1.3670361">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="3.8667902"
+         id="feGaussianBlur4011" />
+    </filter>
+  </defs>
+  <sodipodi:namedview
+     id="base"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageopacity="0.0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="3.2819435"
+     inkscape:cx="18.697469"
+     inkscape:cy="17.287267"
+     inkscape:document-units="px"
+     inkscape:current-layer="layer1"
+     showgrid="false"
+     inkscape:window-width="970"
+     inkscape:window-height="778"
+     inkscape:window-x="284"
+     inkscape:window-y="0"
+     inkscape:window-maximized="0" />
+  <metadata
+     id="metadata3080">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title></dc:title>
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <g
+     inkscape:label="Layer 1"
+     inkscape:groupmode="layer"
+     id="layer1"
+     transform="translate(0,-1004.3622)">
+    <path
+       style="fill:url(#radialGradient3995);stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;fill-opacity:1.0;filter:url(#filter4009)"
+       d="M -0.85390618,50.988672 14.231769,27.790888 C 12.21393,25.133052 9.5514307,24.605255 9.9622384,18.824874 13.947134,14.236899 17.362759,16.258973 21.347654,16.54779 l 8.966014,-8.6813789 c 1.467204,-2.4778468 -1.023584,-4.6422045 0.569271,-7.25820222 4.802307,-0.84764718 6.662499,1.15219542 11.527733,6.26197842 4.061691,4.1873637 5.648882,7.0611607 4.411848,9.5352857 -1.075122,2.776443 -4.518349,-0.692782 -5.835025,0.56927 l -9.108332,10.104556 c -0.418785,3.74872 2.078647,7.861968 -1.280859,11.243098 -4.132171,0.818036 -6.734336,-1.933944 -9.819921,-3.557942 z"
+       id="path3955"
+       inkscape:connector-curvature="0"
+       transform="translate(0,1004.3622)"
+       sodipodi:nodetypes="ccccccccccccc" />
+    <g
+       id="g3929">
+      <path
+         sodipodi:nodetypes="cccc"
+         inkscape:connector-curvature="0"
+         id="path3083"
+         d="m 3.2884874,1051.0662 c 3.1862139,-6.2911 11.3693156,-15.19 15.4471616,-20.0327 l 2.86533,3.0086 c -3.476851,3.6575 -10.192375,10.8664 -18.3124916,17.0241 z"
+         style="fill:url(#linearGradient3859);fill-opacity:1;stroke:#a5a5a5;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+      <path
+         sodipodi:nodetypes="ccccc"
+         inkscape:connector-curvature="0"
+         id="path3863"
+         d="m 11.10078,1023.3294 c 5.038264,10.1095 11.83652,14.8875 18.358981,18.2167 1.196291,-2.5422 1.454996,-5.6203 0,-9.6776 l -8.539061,-8.6814 c -3.704654,-1.8936 -6.871076,-1.3652 -9.81992,0.1423 z"
+         style="fill:url(#radialGradient3871);fill-opacity:1;stroke:none" />
+      <path
+         sodipodi:nodetypes="ccccc"
+         inkscape:connector-curvature="0"
+         id="path3873"
+         d="m 33.729292,1011.5171 -13.235545,11.4952 c 2.869602,4.2703 6.221839,7.4544 9.108332,9.1408 l 11.385416,-13.0187 z"
+         style="fill:url(#linearGradient3881);fill-opacity:1;stroke:none" />
+      <path
+         sodipodi:nodetypes="ccccc"
+         inkscape:connector-curvature="0"
+         id="path3893"
+         d="m 33.228885,1011.6148 c 1.843189,2.7806 3.431654,5.6597 7.19852,7.6953 l 5.398891,1.7423 c -7.6738,-4.7914 -10.989683,-9.5828 -13.947133,-14.3741 z"
+         style="fill:url(#linearGradient3927);fill-opacity:1;stroke:none" />
+      <path
+         transform="matrix(0.68275275,-0.5590416,0.45791123,0.47036287,17.42507,1012.2127)"
+         d="m 18.216664,22.596292 a 1.7789712,14.872199 0 1 1 -3.557943,0 1.7789712,14.872199 0 1 1 3.557943,0 z"
+         sodipodi:ry="14.872199"
+         sodipodi:rx="1.7789712"
+         sodipodi:cy="22.596292"
+         sodipodi:cx="16.437693"
+         id="path3901"
+         style="fill:url(#radialGradient3909);fill-opacity:1;stroke:none"
+         sodipodi:type="arc" />
+    </g>
+  </g>
+</svg>
diff --git a/apps/files_pdfviewer/js/pdfjs/web/images/zoom-in.svg b/apps/files_pdfviewer/js/pdfjs/web/images/zoom-in.svg
old mode 100755
new mode 100644
index 6eaed4481100ca184d947978663789e4770627b5..48ee42dd9b801cdf6ed7df6b55fa0279a816add8
--- a/apps/files_pdfviewer/js/pdfjs/web/images/zoom-in.svg
+++ b/apps/files_pdfviewer/js/pdfjs/web/images/zoom-in.svg
@@ -16,7 +16,8 @@
    inkscape:version="0.46"
    sodipodi:docbase="/home/jimmac/src/cvs/tango-icon-theme/scalable/actions"
    sodipodi:docname="list-add.svg"
-   inkscape:output_extension="org.inkscape.output.svg.inkscape">
+   inkscape:output_extension="org.inkscape.output.svg.inkscape"
+   viewbox="0 0 48 48">
   <defs
      id="defs6433">
     <inkscape:perspective
@@ -418,12 +419,12 @@
        d="M 33.278212 34.94062 A 10.31934 2.320194 0 1 1  12.639532,34.94062 A 10.31934 2.320194 0 1 1  33.278212 34.94062 z"
        transform="matrix(1.550487,0,0,1.978714,-12.4813,-32.49103)" />
     <path
-       style="font-size:59.901077px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:125.00000%;writing-mode:lr-tb;text-anchor:start;fill:#75a1d0;fill-opacity:1.0000000;stroke:#3465a4;stroke-width:1.0000004px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans"
+       style="fill:#75a1d0;fill-opacity:1.0000000;stroke:#3465a4;stroke-width:1.0000004px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000"
        d="M 27.514356,37.542682 L 27.514356,28.515722 L 37.492820,28.475543 L 37.492820,21.480219 L 27.523285,21.480219 L 27.514356,11.520049 L 20.498082,11.531210 L 20.502546,21.462362 L 10.512920,21.536022 L 10.477206,28.504561 L 20.511475,28.475543 L 20.518171,37.515896 L 27.514356,37.542682 z "
        id="text1314"
        sodipodi:nodetypes="ccccccccccccc" />
     <path
-       style="font-size:59.901077px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:125.00000%;writing-mode:lr-tb;text-anchor:start;opacity:0.40860215;fill:url(#linearGradient4975);fill-opacity:1.0000000;stroke:url(#linearGradient7922);stroke-width:1.0000006px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans"
+       style="opacity:0.40860215;fill:url(#linearGradient4975);fill-opacity:1.0000000;stroke:url(#linearGradient7922);stroke-width:1.0000006px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000"
        d="M 26.498702,36.533920 L 26.498702,27.499738 L 36.501304,27.499738 L 36.494607,22.475309 L 26.507630,22.475309 L 26.507630,12.480335 L 21.512796,12.498193 L 21.521725,22.475309 L 11.495536,22.493166 L 11.468750,27.466256 L 21.533143,27.475185 L 21.519750,36.502670 L 26.498702,36.533920 z "
        id="path7076"
        sodipodi:nodetypes="ccccccccccccc" />
diff --git a/apps/files_pdfviewer/js/pdfjs/web/images/zoom-out.svg b/apps/files_pdfviewer/js/pdfjs/web/images/zoom-out.svg
old mode 100755
new mode 100644
index 5f109a05c38f37c98d181d6cebe8c40aa56dbe04..eb13b60e376c6d148f63117d82ae5b70451ee963
--- a/apps/files_pdfviewer/js/pdfjs/web/images/zoom-out.svg
+++ b/apps/files_pdfviewer/js/pdfjs/web/images/zoom-out.svg
@@ -16,7 +16,8 @@
    inkscape:version="0.46"
    sodipodi:docbase="/home/jimmac/src/cvs/tango-icon-theme/scalable/actions"
    sodipodi:docname="list-remove.svg"
-   inkscape:output_extension="org.inkscape.output.svg.inkscape">
+   inkscape:output_extension="org.inkscape.output.svg.inkscape"
+   viewbox="0 0 48 48">
   <defs
      id="defs6433">
     <inkscape:perspective
@@ -406,12 +407,12 @@
      inkscape:label="Layer 1"
      inkscape:groupmode="layer">
     <path
-       style="font-size:59.901077px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:125.00000%;writing-mode:lr-tb;text-anchor:start;fill:#75a1d0;fill-opacity:1.0000000;stroke:#3465a4;stroke-width:1.0000004px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans"
+       style="fill:#75a1d0;fill-opacity:1.0000000;stroke:#3465a4;stroke-width:1.0000004px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000"
        d="M 27.514356,28.359472 L 39.633445,28.475543 L 39.633445,21.480219 L 27.523285,21.480219 L 20.502546,21.462362 L 8.5441705,21.489147 L 8.5084565,28.457686 L 20.511475,28.475543 L 27.514356,28.359472 z "
        id="text1314"
        sodipodi:nodetypes="ccccccccc" />
     <path
-       style="font-size:59.901077px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:125.00000%;writing-mode:lr-tb;text-anchor:start;opacity:0.40860215;fill:url(#linearGradient4975);fill-opacity:1.0000000;stroke:url(#linearGradient7922);stroke-width:1.0000006px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans"
+       style="opacity:0.40860215;fill:url(#linearGradient4975);fill-opacity:1.0000000;stroke:url(#linearGradient7922);stroke-width:1.0000006px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000"
        d="M 38.579429,27.484113 L 38.588357,22.475309 L 9.5267863,22.493166 L 9.5000003,27.466256 L 38.579429,27.484113 z "
        id="path7076"
        sodipodi:nodetypes="ccccc" />
diff --git a/apps/files_pdfviewer/js/pdfview.js b/apps/files_pdfviewer/js/pdfview.js
old mode 100755
new mode 100644
diff --git a/apps/files_pdfviewer/js/viewer.js b/apps/files_pdfviewer/js/viewer.js
old mode 100755
new mode 100644
diff --git a/apps/files_sharing/ajax/email.php b/apps/files_sharing/ajax/email.php
new file mode 100755
index 0000000000000000000000000000000000000000..9eba203465e0f17b3e9f918c2d7a2d47bebd0ec9
--- /dev/null
+++ b/apps/files_sharing/ajax/email.php
@@ -0,0 +1,12 @@
+<?php
+OCP\JSON::checkLoggedIn();
+OCP\JSON::checkAppEnabled('files_sharing');
+$user = OCP\USER::getUser();
+// TODO translations
+$subject = $user + ' ' + 'shared a file with you';
+$link = $_POST['link'] + '&f=' + $_POST['f'];
+$text = $user + ' ' + 'shared the file' + ' ' + $_POST['f'] + ' ' + 'with you.' + ' ' + 'It is available for download here:' + ' ' + $link;
+$fromaddress = OCP\Config::getUserValue($user, 'settings', 'email', 'sharing-noreply@'.$_SERVER['HTTP_HOST']);
+OC_Mail::send($_POST['toaddress'], $_POST['toaddress'], $subject, $text, $fromaddress, $user);
+
+?>
\ No newline at end of file
diff --git a/apps/files_sharing/ajax/getitem.php b/apps/files_sharing/ajax/getitem.php
old mode 100644
new mode 100755
index ba01adffb9a6fa1e45fc95790db7af9e55edf1b6..d9404f7e3b4113e35136c31309855f305c929699
--- a/apps/files_sharing/ajax/getitem.php
+++ b/apps/files_sharing/ajax/getitem.php
@@ -1,11 +1,11 @@
 <?php
 //$RUNTIME_NOAPPS = true;
 
-require_once('../../../lib/base.php');
-OC_JSON::checkAppEnabled('files_sharing');
-require_once('../lib_share.php');
+ 
+OCP\JSON::checkAppEnabled('files_sharing');
+require_once(OC::$APPSROOT . '/apps/files_sharing/lib_share.php');
 
-$userDirectory = "/".OC_User::getUser()."/files";
+$userDirectory = "/".OCP\USER::getUser()."/files";
 $source = $userDirectory.$_GET['source'];
 $path = $source;
 $users = array();
@@ -32,5 +32,5 @@ while ($source != "" && $source != "/" && $source != "." && $source != $userDire
 	$source = dirname($source);
 }
 if (!empty($users)) {
-	OC_JSON::encodedPrint($users);
+	OCP\JSON::encodedPrint($users);
 }
diff --git a/apps/files_sharing/ajax/setpermissions.php b/apps/files_sharing/ajax/setpermissions.php
old mode 100644
new mode 100755
index 200202c704c0da0b95cb5a466240fc2bf5e82bbf..73f59d73db2d49d9f79399705538c60404b8d1ca
--- a/apps/files_sharing/ajax/setpermissions.php
+++ b/apps/files_sharing/ajax/setpermissions.php
@@ -1,11 +1,11 @@
 <?php
 //$RUNTIME_NOAPPS = true;
 
-require_once('../../../lib/base.php');
-OC_JSON::checkAppEnabled('files_sharing');
-require_once('../lib_share.php');
+ 
+OCP\JSON::checkAppEnabled('files_sharing');
+require_once(OC::$APPSROOT . '/apps/files_sharing/lib_share.php');
 
-$source = "/".OC_User::getUser()."/files".$_GET['source'];
+$source = "/".OCP\USER::getUser()."/files".$_GET['source'];
 $uid_shared_with = $_GET['uid_shared_with'];
 $permissions = $_GET['permissions'];
 OC_Share::setPermissions($source, $uid_shared_with, $permissions);
diff --git a/apps/files_sharing/ajax/share.php b/apps/files_sharing/ajax/share.php
old mode 100644
new mode 100755
index 9b10260da5a0e10945f300b6d69559d3182c7064..4863170f57cf6e18083c5d1d9a7f6870d58251fc
--- a/apps/files_sharing/ajax/share.php
+++ b/apps/files_sharing/ajax/share.php
@@ -1,11 +1,11 @@
 <?php
 //$RUNTIME_NOAPPS = true;
 
-require_once('../../../lib/base.php');
-OC_JSON::checkAppEnabled('files_sharing');
-require_once('../lib_share.php');
+ 
+OCP\JSON::checkAppEnabled('files_sharing');
+require_once(OC::$APPSROOT . '/apps/files_sharing/lib_share.php');
 
-$userDirectory = "/".OC_User::getUser()."/files";
+$userDirectory = "/".OCP\USER::getUser()."/files";
 $sources = explode(";", $_POST['sources']);
 $uid_shared_with = $_POST['uid_shared_with'];
 $permissions = $_POST['permissions'];
@@ -15,7 +15,7 @@ foreach ($sources as $source) {
 		$source = $userDirectory.$source;
 	// If the file doesn't exist, it may be shared with the current user
 	} else if (!$source = OC_Share::getSource($userDirectory.$source)) {
-		OC_Log::write('files_sharing',"Shared file doesn't exists :".$source,OC_Log::ERROR);
+		OCP\Util::writeLog('files_sharing',"Shared file doesn't exists :".$source,OCP\Util::ERROR);
 		echo "false";
 	}
 	try {
@@ -24,7 +24,7 @@ foreach ($sources as $source) {
 			echo $shared->getToken();
 		}
 	} catch (Exception $exception) {
-		OC_Log::write('files_sharing',"Unexpected Error : ".$exception->getMessage(),OC_Log::ERROR);
+		OCP\Util::writeLog('files_sharing',"Unexpected Error : ".$exception->getMessage(),OCP\Util::ERROR);
 		echo "false";
 	}
 }
diff --git a/apps/files_sharing/ajax/toggleresharing.php b/apps/files_sharing/ajax/toggleresharing.php
new file mode 100755
index 0000000000000000000000000000000000000000..673f00c5d18e57d5b483191f9cf0db0968f5adf7
--- /dev/null
+++ b/apps/files_sharing/ajax/toggleresharing.php
@@ -0,0 +1,11 @@
+<?php
+
+OCP\JSON::checkAppEnabled('files_sharing');
+OCP\JSON::checkAdminUser();
+if ($_POST['resharing'] == true) {
+	OCP\Config::setAppValue('files_sharing', 'resharing', 'yes');
+} else {
+	OCP\Config::setAppValue('files_sharing', 'resharing', 'no');
+}
+
+?>
diff --git a/apps/files_sharing/ajax/unshare.php b/apps/files_sharing/ajax/unshare.php
old mode 100644
new mode 100755
index d8a72a00efe4317dd41dffa672f550cefe122378..5056c59a3d45aa336ea3c547ebfd9de0f5394327
--- a/apps/files_sharing/ajax/unshare.php
+++ b/apps/files_sharing/ajax/unshare.php
@@ -1,11 +1,11 @@
 <?php
 //$RUNTIME_NOAPPS = true;
 
-require_once('../../../lib/base.php');
-OC_JSON::checkAppEnabled('files_sharing');
-require_once('../lib_share.php');
+ 
+OCP\JSON::checkAppEnabled('files_sharing');
+require_once(OC::$APPSROOT . '/apps/files_sharing/lib_share.php');
 
-$source = "/".OC_User::getUser()."/files".$_GET['source'];
+$source = "/".OCP\USER::getUser()."/files".$_GET['source'];
 $uid_shared_with = $_GET['uid_shared_with'];
 OC_Share::unshare($source, $uid_shared_with);
 
diff --git a/apps/files_sharing/ajax/userautocomplete.php b/apps/files_sharing/ajax/userautocomplete.php
old mode 100644
new mode 100755
index 38b673ee51b585ebccbf7f9145a3d26a530fef94..73b5f126984dcd3251fb0fda9f42cdca2ba6bb38
--- a/apps/files_sharing/ajax/userautocomplete.php
+++ b/apps/files_sharing/ajax/userautocomplete.php
@@ -1,14 +1,14 @@
 <?php
 //$RUNTIME_NOAPPS = true;
 
-require_once('../../../lib/base.php');
+ 
 
-OC_JSON::checkLoggedIn();
-OC_JSON::checkAppEnabled('files_sharing');
+OCP\JSON::checkLoggedIn();
+OCP\JSON::checkAppEnabled('files_sharing');
 
 $users = array();
 $groups = array();
-$self = OC_User::getUser();
+$self = OCP\USER::getUser();
 $userGroups = OC_Group::getUserGroups($self);
 $users[] = "<optgroup label='Users'>";
 $groups[] = "<optgroup label='Groups'>";
@@ -24,6 +24,6 @@ foreach ($userGroups as $group) {
 $users[] = "</optgroup>";
 $groups[] = "</optgroup>";
 $users = array_merge($users, $groups);
-OC_JSON::encodedPrint($users);
+OCP\JSON::encodedPrint($users);
 
 ?>
diff --git a/apps/files_sharing/appinfo/app.php b/apps/files_sharing/appinfo/app.php
old mode 100644
new mode 100755
index 8049e9b0ae3cbcde3564f008c351ff8087642953..f80bdb9e195085c3ca7f9a96a3eebbe0805dc275
--- a/apps/files_sharing/appinfo/app.php
+++ b/apps/files_sharing/appinfo/app.php
@@ -3,12 +3,19 @@
 require_once('apps/files_sharing/sharedstorage.php');
 
 OC::$CLASSPATH['OC_Share'] = "apps/files_sharing/lib_share.php";
+OCP\App::registerAdmin('files_sharing', 'settings');
 OC_Hook::connect("OC_Filesystem", "post_delete", "OC_Share", "deleteItem");
 OC_Hook::connect("OC_Filesystem", "post_rename", "OC_Share", "renameItem");
 OC_Hook::connect("OC_Filesystem", "post_write", "OC_Share", "updateItem");
-OC_Util::addScript("files_sharing", "share");
-OC_Util::addScript("3rdparty", "chosen/chosen.jquery.min");
-OC_Util::addStyle( 'files_sharing', 'sharing' );
-OC_Util::addStyle("3rdparty", "chosen/chosen");
+OC_Hook::connect('OC_User', 'post_deleteUser', 'OC_Share', 'removeUser');
+OC_Hook::connect('OC_User', 'post_addToGroup', 'OC_Share', 'addToGroupShare');
+OC_Hook::connect('OC_User', 'post_removeFromGroup', 'OC_Share', 'removeFromGroupShare');
+$dir = isset($_GET['dir']) ? $_GET['dir'] : '/';
+if ($dir != '/Shared' || OCP\Config::getAppValue('files_sharing', 'resharing', 'yes') == 'yes') {
+	OCP\Util::addscript("files_sharing", "share");
+}
+OCP\Util::addscript("3rdparty", "chosen/chosen.jquery.min");
+OCP\Util::addStyle( 'files_sharing', 'sharing' );
+OCP\Util::addStyle("3rdparty", "chosen/chosen");
 
-?>
\ No newline at end of file
+?>
diff --git a/apps/files_sharing/appinfo/info.xml b/apps/files_sharing/appinfo/info.xml
index 8fda775520b602ae4b217b975aeeb0fb221f811c..490ffaca890829334254cef4f9e6b0574c0dfbf8 100644
--- a/apps/files_sharing/appinfo/info.xml
+++ b/apps/files_sharing/appinfo/info.xml
@@ -3,7 +3,6 @@
 	<id>files_sharing</id>
 	<name>Share Files</name>
 	<description>File sharing between users</description>
-	<version>0.1</version>
 	<licence>AGPL</licence>
 	<author>Michael Gapczynski</author>
 	<require>2</require>
diff --git a/apps/files_sharing/appinfo/version b/apps/files_sharing/appinfo/version
new file mode 100644
index 0000000000000000000000000000000000000000..ceab6e11ece0bcec917c12e11d350946f085d549
--- /dev/null
+++ b/apps/files_sharing/appinfo/version
@@ -0,0 +1 @@
+0.1
\ No newline at end of file
diff --git a/apps/files_sharing/css/sharing.css b/apps/files_sharing/css/sharing.css
index db59a3d340b608f67ff895c2392a0ee48d2732a1..5acd9af589ad03a5461578783ad69865635dd28c 100644
--- a/apps/files_sharing/css/sharing.css
+++ b/apps/files_sharing/css/sharing.css
@@ -1,3 +1,7 @@
+/* Copyright (c) 2011, Jan-Christoph Borchardt, http://jancborchardt.net
+ This file is licensed under the Affero General Public License version 3 or later.
+ See the COPYING-README file. */
+
 #dropdown { display:block;  position:absolute; z-index:100; width:16em; right:0; margin-right:7em; background:#eee; padding:1em;
 -moz-box-shadow:0 1px 1px #777; -webkit-box-shadow:0 1px 1px #777; box-shadow:0 1px 1px #777;
 -moz-border-radius-bottomleft:1em; -webkit-border-bottom-left-radius:1em; border-bottom-left-radius:1em;
@@ -6,4 +10,4 @@
 #public { border-top:1px solid #ddd; padding-top:0.5em; }
 a.unshare { float:right; display:inline; margin:0 .5em; padding:.3em .3em 0 .3em !important; opacity:.5; }
 a.unshare:hover { opacity:1; }
-#share_with { width: 16em; }
\ No newline at end of file
+#share_with { width: 16em; }
diff --git a/apps/files_sharing/get.php b/apps/files_sharing/get.php
old mode 100644
new mode 100755
index fa3535fd14457a35d5bed9b7ca86bb09f043961e..de3bc5f46dcfbbdd4b83c77ec8a2eac734140ea4
--- a/apps/files_sharing/get.php
+++ b/apps/files_sharing/get.php
@@ -1,8 +1,7 @@
 <?php
 $RUNTIME_NOSETUPFS=true; //don't setup the fs yet
 
-require_once '../../lib/base.php';
-OC_JSON::checkAppEnabled('files_sharing');
+OCP\JSON::checkAppEnabled('files_sharing');
 require_once 'lib_share.php';
 
 //get the path of the shared file
@@ -27,11 +26,11 @@ if ($source !== false) {
 		$files = array();
 		$rootLength = strlen($root);
 		foreach (OC_Files::getdirectorycontent($source) as $i) {
-			$i['date'] = OC_Util::formatDate($i['mtime'] );
+			$i['date'] = OCP\Util::formatDate($i['mtime'] );
 			if ($i['type'] == 'file') {
 				$fileinfo = pathinfo($i['name']);
 				$i['basename'] = $fileinfo['filename'];
-				$i['extention'] = isset($fileinfo['extension']) ? ('.'.$fileinfo['extension']) : '';
+				$i['extension'] = isset($fileinfo['extension']) ? ('.'.$fileinfo['extension']) : '';
 			}
 			$i['directory'] = substr($i['directory'], $rootLength);
 			if ($i['directory'] == "/") {
@@ -49,14 +48,14 @@ if ($source !== false) {
 			}
 		}
 		// Load the files we need
-		OC_Util::addStyle("files", "files");
+		OCP\Util::addStyle("files", "files");
 		$breadcrumbNav = new OC_Template("files", "part.breadcrumb", "");
 		$breadcrumbNav->assign("breadcrumb", $breadcrumb);
-		$breadcrumbNav->assign("baseURL", OC_Helper::linkTo("files_sharing", "get.php")."?token=".$token."&path=");
+		$breadcrumbNav->assign("baseURL", OCP\Util::linkTo("files_sharing", "get.php")."?token=".$token."&path=");
 		$list = new OC_Template("files", "part.list", "");
 		$list->assign("files", $files);
-		$list->assign("baseURL", OC_Helper::linkTo("files_sharing", "get.php")."?token=".$token."&path=");
-		$list->assign("downloadURL", OC_Helper::linkTo("files_sharing", "get.php")."?token=".$token."&path=");
+		$list->assign("baseURL", OCP\Util::linkTo("files_sharing", "get.php")."?token=".$token."&path=");
+		$list->assign("downloadURL", OCP\Util::linkTo("files_sharing", "get.php")."?token=".$token."&path=");
 		$list->assign("readonly", true);
 		$tmpl = new OC_Template("files", "index", "user");
 		$tmpl->assign("fileList", $list->fetchPage());
@@ -69,7 +68,7 @@ if ($source !== false) {
 		//get time mimetype and set the headers
 		$mimetype = OC_Filesystem::getMimeType($source);
 		header("Content-Transfer-Encoding: binary");
-		OC_Response::disableCaching();
+		OCP\Response::disableCaching();
 		header('Content-Disposition: filename="'.basename($source).'"');
 		header("Content-Type: " . $mimetype);
 		header("Content-Length: " . OC_Filesystem::filesize($source));
diff --git a/apps/files_sharing/js/settings.js b/apps/files_sharing/js/settings.js
new file mode 100644
index 0000000000000000000000000000000000000000..bb7d79fecbb24a2de090c0424c6a183b15018f97
--- /dev/null
+++ b/apps/files_sharing/js/settings.js
@@ -0,0 +1,9 @@
+$(document).ready(function() {
+	$('#allowResharing').bind('change', function() {
+		var checked = 1;
+		if (!this.checked) {
+			checked = 0;
+		}
+		$.post(OC.filePath('files_sharing','ajax','toggleresharing.php'), 'resharing='+checked);
+	});
+});
\ No newline at end of file
diff --git a/apps/files_sharing/js/share.js b/apps/files_sharing/js/share.js
index 54d749d833e5e7c94d5e6ee3b3dada6e866b04bc..4125fd14d2584ea5cd9ef532ddb4c7f91dbd51a9 100644
--- a/apps/files_sharing/js/share.js
+++ b/apps/files_sharing/js/share.js
@@ -163,6 +163,9 @@ $(document).ready(function() {
 				data: data,
 				success: function(){
 					$('#link').hide('blind');
+					$('#emailBreak').remove();
+					$('#email').hide('blind');
+					$('#emailButton').hide('blind');
 				}
 			});
 		}
@@ -172,6 +175,14 @@ $(document).ready(function() {
 		$(this).focus();
 		$(this).select();
 	});
+
+	$('#emailButton').live('click', function() {
+		$('#email').css('font-weight', 'bold');
+		$('#email').animate({ fontWeight: 'normal' }, 2000, function() {
+			$(this).val('');
+		}).val('Email sent');
+		$.post(OC.filePath('files_sharing','ajax','email.php'), 'toaddress='+$('#email').val()+'&link='+$('#link').val());
+	});
 });
 
 function createDropdown(filename, files) {
@@ -183,10 +194,12 @@ function createDropdown(filename, files) {
 	html += '<ul id="shared_list"></ul>';
 	html += '</div>';
 	html += '<div id="public">';
-	html += '<input type="checkbox" name="makelink" id="makelink" value="1" /><label for="makelink">make public</label>';
+	html += '<input type="checkbox" name="makelink" id="makelink" value="1" /><label for="makelink">Share with private link</label>';
 	//html += '<input type="checkbox" name="public_link_write" id="public_link_write" value="1" /><label for="public_link_write">allow upload</label>';
 	html += '<br />';
 	html += '<input id="link" style="display:none; width:90%;" />';
+	html += '<input id="email" style="display:none; width:65%;" value="" placeholder="Email link to person" />';
+	html += '<input id="emailButton" style="display:none;" type="submit" value="Send" />';
 	html += '</div>';
 	if (filename) {
 		$('tr').filterAttr('data-file',filename).addClass('mouseOver');
@@ -241,5 +254,9 @@ function showPublicLink(token, file) {
 	$('#makelink').attr('checked', true);
 	$('#link').data('token', token);
 	$('#link').val(parent.location.protocol+'//'+location.host+OC.linkTo('files_sharing','get.php')+'?token='+token+'&f='+file);
-	$('#link').show('blind');
+	$('#link').show('blind', function() {
+		$('#link').after('<br id="emailBreak" />');
+		$('#email').show('blind');
+		$('#emailButton').show('blind');
+	});
 }
diff --git a/apps/files_sharing/lib_share.php b/apps/files_sharing/lib_share.php
old mode 100644
new mode 100755
index 673984f393b6fe28f20f7983c6f6ec9f21c899fb..fe8aa64fa813a7765ee7a6bc4bf217a4e0c620ae
--- a/apps/files_sharing/lib_share.php
+++ b/apps/files_sharing/lib_share.php
@@ -39,8 +39,8 @@ class OC_Share {
 	 * @param $permissions The permissions, use the constants WRITE and DELETE
 	 */
 	public function __construct($source, $uid_shared_with, $permissions) {
-		$uid_owner = OC_User::getUser();
-		$query = OC_DB::prepare("INSERT INTO *PREFIX*sharing VALUES(?,?,?,?,?)");
+		$uid_owner = OCP\USER::getUser();
+		$query = OCP\DB::prepare("INSERT INTO *PREFIX*sharing VALUES(?,?,?,?,?)");
 		if ($uid_shared_with == self::PUBLICLINK) {
 			$token = sha1("$uid_shared_with-$source");
 			$query->execute(array($uid_owner, self::PUBLICLINK, $source, $token, $permissions));
@@ -51,7 +51,7 @@ class OC_Share {
 				$uid_shared_with = OC_Group::usersInGroup($gid);
 				// Remove the owner from the list of users in the group
 				$uid_shared_with = array_diff($uid_shared_with, array($uid_owner));
-			} else if (OC_User::userExists($uid_shared_with)) {
+			} else if (OCP\User::userExists($uid_shared_with)) {
 				$userGroups = OC_Group::getUserGroups($uid_owner);
 				// Check if the user is in one of the owner's groups
 				foreach ($userGroups as $group) {
@@ -69,7 +69,7 @@ class OC_Share {
 			}
 			foreach ($uid_shared_with as $uid) {
 				// Check if this item is already shared with the user
-				$checkSource = OC_DB::prepare("SELECT source FROM *PREFIX*sharing WHERE source = ? AND uid_shared_with ".self::getUsersAndGroups($uid));
+				$checkSource = OCP\DB::prepare("SELECT source FROM *PREFIX*sharing WHERE source = ? AND uid_shared_with ".self::getUsersAndGroups($uid));
 				$resultCheckSource = $checkSource->execute(array($source))->fetchAll();
 				// TODO Check if the source is inside a folder
 				if (count($resultCheckSource) > 0 && !isset($gid)) {
@@ -99,13 +99,13 @@ class OC_Share {
 				}
 				$query->execute(array($uid_owner, $uid, $source, $target, $permissions));
 				// Add file to filesystem cache
-				$userDirectory = "/".OC_User::getUser()."/files";
+				$userDirectory = "/".OCP\USER::getUser()."/files";
 				$data = OC_Filecache::get(substr($source, strlen($userDirectory)));
-				$parentQuery = OC_DB::prepare('SELECT id FROM *PREFIX*fscache WHERE path=?');
+				$parentQuery = OCP\DB::prepare('SELECT id FROM *PREFIX*fscache WHERE path=?');
 				$parentResult = $parentQuery->execute(array($sharedFolder))->fetchRow();
 				$parent = $parentResult['id'];
 				$is_writeable = $permissions & OC_Share::WRITE;
-				$cacheQuery = OC_DB::prepare('INSERT INTO *PREFIX*fscache(parent, name, path, size, mtime, ctime, mimetype, mimepart, user, writable) VALUES(?,?,?,?,?,?,?,?,?,?)');
+				$cacheQuery = OCP\DB::prepare('INSERT INTO *PREFIX*fscache(parent, name, path, size, mtime, ctime, mimetype, mimepart, user, writable) VALUES(?,?,?,?,?,?,?,?,?,?)');
 				$cacheQuery->execute(array($parent, basename($target), $target, $data['size'], $data['mtime'], $data['ctime'], $data['mimetype'], dirname($data['mimetype']), $uid, $is_writeable));
 			}
 		}
@@ -145,7 +145,7 @@ class OC_Share {
 				$in .= ", '".$uid."@".$group."'";
 			}
 		} else {
-			$uid = OC_User::getUser();
+			$uid = OCP\USER::getUser();
 			$in .= "'".$uid."'";
 			$groups = OC_Group::getUserGroups($uid);
 			foreach ($groups as $group) {
@@ -169,8 +169,8 @@ class OC_Share {
 		$folders = self::getParentFolders($oldTarget);
 		$source = $folders['source'].substr($oldTarget, strlen($folders['target']));
 		$item = self::getItem($folders['target']);
-		$query = OC_DB::prepare("INSERT INTO *PREFIX*sharing VALUES(?,?,?,?,?)");
-		$query->execute(array($item[0]['uid_owner'], OC_User::getUser(), $source, $newTarget, $item[0]['permissions']));
+		$query = OCP\DB::prepare("INSERT INTO *PREFIX*sharing VALUES(?,?,?,?,?)");
+		$query->execute(array($item[0]['uid_owner'], OCP\USER::getUser(), $source, $newTarget, $item[0]['permissions']));
 	}
 
 	/**
@@ -180,8 +180,8 @@ class OC_Share {
 	 */
 	public static function getItem($target) {
 		$target = self::cleanPath($target);
-		$query = OC_DB::prepare("SELECT uid_owner, source, permissions FROM *PREFIX*sharing WHERE target = ? AND uid_shared_with = ? LIMIT 1");
-		return $query->execute(array($target, OC_User::getUser()))->fetchAll();
+		$query = OCP\DB::prepare("SELECT uid_owner, source, permissions FROM *PREFIX*sharing WHERE target = ? AND uid_shared_with = ? LIMIT 1");
+		return $query->execute(array($target, OCP\USER::getUser()))->fetchAll();
 	}
 
 	 /**
@@ -191,12 +191,12 @@ class OC_Share {
 	 */
 	public static function getMySharedItem($source) {
 		$source = self::cleanPath($source);
-		$query = OC_DB::prepare("SELECT uid_shared_with, permissions FROM *PREFIX*sharing WHERE source = ? AND uid_owner = ?");
-		$result = $query->execute(array($source, OC_User::getUser()))->fetchAll();
+		$query = OCP\DB::prepare("SELECT uid_shared_with, permissions FROM *PREFIX*sharing WHERE source = ? AND uid_owner = ?");
+		$result = $query->execute(array($source, OCP\USER::getUser()))->fetchAll();
 		if (count($result) > 0) {
 			return $result;
 		} else if ($originalSource = self::getSource($source)) {
-			return $query->execute(array($originalSource, OC_User::getUser()))->fetchAll();
+			return $query->execute(array($originalSource, OCP\USER::getUser()))->fetchAll();
 		} else {
 			return false;
 		}
@@ -207,8 +207,8 @@ class OC_Share {
 	 * @return An array with all items the user is sharing
 	 */
 	public static function getMySharedItems() {
-		$query = OC_DB::prepare("SELECT uid_shared_with, source, permissions FROM *PREFIX*sharing WHERE uid_owner = ?");
-		return $query->execute(array(OC_User::getUser()))->fetchAll();
+		$query = OCP\DB::prepare("SELECT uid_shared_with, source, permissions FROM *PREFIX*sharing WHERE uid_owner = ?");
+		return $query->execute(array(OCP\USER::getUser()))->fetchAll();
 	}
 
 	/**
@@ -226,7 +226,7 @@ class OC_Share {
 			$folder .= "/";
 		}
 		$length = strlen($folder);
-		$query = OC_DB::prepare("SELECT uid_owner, source, target, permissions FROM *PREFIX*sharing WHERE SUBSTR(source, 1, ?) = ? OR SUBSTR(target, 1, ?) = ? AND uid_shared_with ".self::getUsersAndGroups());
+		$query = OCP\DB::prepare("SELECT uid_owner, source, target, permissions FROM *PREFIX*sharing WHERE SUBSTR(source, 1, ?) = ? OR SUBSTR(target, 1, ?) = ? AND uid_shared_with ".self::getUsersAndGroups());
 		return $query->execute(array($length, $folder, $length, $folder))->fetchAll();
 	}
 
@@ -237,7 +237,7 @@ class OC_Share {
 	 */
 	public static function getParentFolders($target) {
 		$target = self::cleanPath($target);
-		$query = OC_DB::prepare("SELECT source FROM *PREFIX*sharing WHERE target = ? AND uid_shared_with".self::getUsersAndGroups()." LIMIT 1");
+		$query = OCP\DB::prepare("SELECT source FROM *PREFIX*sharing WHERE target = ? AND uid_shared_with".self::getUsersAndGroups()." LIMIT 1");
 		// Prevent searching for user directory e.g. '/MTGap/files'
 		$userDirectory = substr($target, 0, strpos($target, "files") + 5);
 		$target = dirname($target);
@@ -265,7 +265,7 @@ class OC_Share {
 	 */
 	public static function getSource($target) {
 		$target = self::cleanPath($target);
-		$query = OC_DB::prepare("SELECT source FROM *PREFIX*sharing WHERE target = ? AND uid_shared_with ".self::getUsersAndGroups()." LIMIT 1");
+		$query = OCP\DB::prepare("SELECT source FROM *PREFIX*sharing WHERE target = ? AND uid_shared_with ".self::getUsersAndGroups()." LIMIT 1");
 		$result = $query->execute(array($target))->fetchAll();
 		if (count($result) > 0) {
 			return $result[0]['source'];
@@ -281,8 +281,8 @@ class OC_Share {
 
 	public static function getTarget($source) {
 		$source = self::cleanPath($source);
-		$query = OC_DB::prepare("SELECT target FROM *PREFIX*sharing WHERE source = ? AND uid_owner = ? LIMIT 1");
-		$result = $query->execute(array($source, OC_User::getUser()))->fetchAll();
+		$query = OCP\DB::prepare("SELECT target FROM *PREFIX*sharing WHERE source = ? AND uid_owner = ? LIMIT 1");
+		$result = $query->execute(array($source, OCP\USER::getUser()))->fetchAll();
 		if (count($result) > 0) {
 			return $result[0]['target'];
 		} else {
@@ -298,7 +298,7 @@ class OC_Share {
 	 */
 	public static function getPermissions($target) {
 		$target = self::cleanPath($target);
-		$query = OC_DB::prepare("SELECT permissions FROM *PREFIX*sharing WHERE target = ? AND uid_shared_with ".self::getUsersAndGroups()." LIMIT 1");
+		$query = OCP\DB::prepare("SELECT permissions FROM *PREFIX*sharing WHERE target = ? AND uid_shared_with ".self::getUsersAndGroups()." LIMIT 1");
 		$result = $query->execute(array($target))->fetchAll();
 		if (count($result) > 0) {
 			return $result[0]['permissions'];
@@ -310,7 +310,7 @@ class OC_Share {
 					return $result[0]['permissions'];
 				}
 			} else {
-				OC_Log::write('files_sharing',"Not existing parent folder : ".$target,OC_Log::ERROR);
+				OCP\Util::writeLog('files_sharing',"Not existing parent folder : ".$target,OCP\Util::ERROR);
 				return false;
 			}
 		}
@@ -330,8 +330,8 @@ class OC_Share {
 	 * @return The token of the public link, a sha1 hash
 	 */
 	public static function getTokenFromSource($source) {
-		$query = OC_DB::prepare("SELECT target FROM *PREFIX*sharing WHERE source = ? AND uid_shared_with = ? AND uid_owner = ? LIMIT 1");
-		$result = $query->execute(array($source, self::PUBLICLINK, OC_User::getUser()))->fetchAll();
+		$query = OCP\DB::prepare("SELECT target FROM *PREFIX*sharing WHERE source = ? AND uid_shared_with = ? AND uid_owner = ? LIMIT 1");
+		$result = $query->execute(array($source, self::PUBLICLINK, OCP\USER::getUser()))->fetchAll();
 		if (count($result) > 0) {
 			return $result[0]['target'];
 		} else {
@@ -350,7 +350,7 @@ class OC_Share {
 	public static function setTarget($oldTarget, $newTarget) {
 		$oldTarget = self::cleanPath($oldTarget);
 		$newTarget = self::cleanPath($newTarget);
-		$query = OC_DB::prepare("UPDATE *PREFIX*sharing SET target = REPLACE(target, ?, ?) WHERE uid_shared_with ".self::getUsersAndGroups());
+		$query = OCP\DB::prepare("UPDATE *PREFIX*sharing SET target = REPLACE(target, ?, ?) WHERE uid_shared_with ".self::getUsersAndGroups());
 		$query->execute(array($oldTarget, $newTarget));
 	}
 
@@ -365,8 +365,8 @@ class OC_Share {
 	*/
 	public static function setPermissions($source, $uid_shared_with, $permissions) {
 		$source = self::cleanPath($source);
-		$query = OC_DB::prepare("UPDATE *PREFIX*sharing SET permissions = ? WHERE SUBSTR(source, 1, ?) = ? AND uid_owner = ? AND uid_shared_with ".self::getUsersAndGroups($uid_shared_with));
-		$query->execute(array($permissions, strlen($source), $source, OC_User::getUser()));
+		$query = OCP\DB::prepare("UPDATE *PREFIX*sharing SET permissions = ? WHERE SUBSTR(source, 1, ?) = ? AND uid_owner = ? AND uid_shared_with ".self::getUsersAndGroups($uid_shared_with));
+		$query->execute(array($permissions, strlen($source), $source, OCP\USER::getUser()));
 	}
 
 	/**
@@ -379,8 +379,8 @@ class OC_Share {
 	*/
 	public static function unshare($source, $uid_shared_with) {
 		$source = self::cleanPath($source);
-		$query = OC_DB::prepare("DELETE FROM *PREFIX*sharing WHERE SUBSTR(source, 1, ?) = ? AND uid_owner = ? AND uid_shared_with ".self::getUsersAndGroups($uid_shared_with));
-		$query->execute(array(strlen($source), $source, OC_User::getUser()));
+		$query = OCP\DB::prepare("DELETE FROM *PREFIX*sharing WHERE SUBSTR(source, 1, ?) = ? AND uid_owner = ? AND uid_shared_with ".self::getUsersAndGroups($uid_shared_with));
+		$query->execute(array(strlen($source), $source, OCP\USER::getUser()));
 	}
 
 	/**
@@ -394,10 +394,10 @@ class OC_Share {
 	public static function unshareFromMySelf($target, $delete = true) {
 		$target = self::cleanPath($target);
 		if ($delete) {
-			$query = OC_DB::prepare("DELETE FROM *PREFIX*sharing WHERE SUBSTR(target, 1, ?) = ? AND uid_shared_with ".self::getUsersAndGroups());
+			$query = OCP\DB::prepare("DELETE FROM *PREFIX*sharing WHERE SUBSTR(target, 1, ?) = ? AND uid_shared_with ".self::getUsersAndGroups());
 			$query->execute(array(strlen($target), $target));
 		} else {
-			$query = OC_DB::prepare("UPDATE *PREFIX*sharing SET permissions = ? WHERE SUBSTR(target, 1, ?) = ? AND uid_shared_with ".self::getUsersAndGroups());
+			$query = OCP\DB::prepare("UPDATE *PREFIX*sharing SET permissions = ? WHERE SUBSTR(target, 1, ?) = ? AND uid_shared_with ".self::getUsersAndGroups());
 			$query->execute(array(self::UNSHARED, strlen($target), $target));
 		}
 	}
@@ -407,12 +407,12 @@ class OC_Share {
 	* @param $arguments Array of arguments passed from OC_Hook
 	*/
 	public static function deleteItem($arguments) {
-		$source = "/".OC_User::getUser()."/files".self::cleanPath($arguments['path']);
+		$source = "/".OCP\USER::getUser()."/files".self::cleanPath($arguments['path']);
 		if ($target = self::getTarget($source)) {
 			// Forward hook to notify of changes to target file
 			OC_Hook::emit("OC_Filesystem", "post_delete", array('path' => $target));
-			$query = OC_DB::prepare("DELETE FROM *PREFIX*sharing WHERE SUBSTR(source, 1, ?) = ? AND uid_owner = ?");
-			$query->execute(array(strlen($source), $source, OC_User::getUser()));
+			$query = OCP\DB::prepare("DELETE FROM *PREFIX*sharing WHERE SUBSTR(source, 1, ?) = ? AND uid_owner = ?");
+			$query->execute(array(strlen($source), $source, OCP\USER::getUser()));
 		}
 		
 	}
@@ -422,20 +422,48 @@ class OC_Share {
 	* @param $arguments Array of arguments passed from OC_Hook
 	*/
 	public static function renameItem($arguments) {
-		$oldSource = "/".OC_User::getUser()."/files".self::cleanPath($arguments['oldpath']);
-		$newSource = "/".OC_User::getUser()."/files".self::cleanPath($arguments['newpath']);
-		$query = OC_DB::prepare("UPDATE *PREFIX*sharing SET source = REPLACE(source, ?, ?) WHERE uid_owner = ?");
-		$query->execute(array($oldSource, $newSource, OC_User::getUser()));
+		$oldSource = "/".OCP\USER::getUser()."/files".self::cleanPath($arguments['oldpath']);
+		$newSource = "/".OCP\USER::getUser()."/files".self::cleanPath($arguments['newpath']);
+		$query = OCP\DB::prepare("UPDATE *PREFIX*sharing SET source = REPLACE(source, ?, ?) WHERE uid_owner = ?");
+		$query->execute(array($oldSource, $newSource, OCP\USER::getUser()));
 	}
 
 	public static function updateItem($arguments) {
-		$source = "/".OC_User::getUser()."/files".self::cleanPath($arguments['path']);
+		$source = "/".OCP\USER::getUser()."/files".self::cleanPath($arguments['path']);
 		if ($target = self::getTarget($source)) {
 			// Forward hook to notify of changes to target file
 			OC_Hook::emit("OC_Filesystem", "post_write", array('path' => $target));
 		}
 	}
 
+	public static function removeUser($arguments) {
+		$query = OCP\DB::prepare('DELETE FROM *PREFIX*sharing WHERE uid_owner = ? OR uid_shared_with '.self::getUsersAndGroups($arguments['uid']));
+		$query->execute(array($arguments['uid']));
+	}
+
+	public static function addToGroupShare($arguments) {
+		$length = -strlen($arguments['gid']) - 1;
+		$query = OCP\DB::prepare('SELECT uid_owner, source, permissions FROM *PREFIX*sharing WHERE SUBSTR(uid_shared_with, '.$length.') = ?');
+		$gid = '@'.$arguments['gid'];
+		$result = $query->execute(array($gid))->fetchAll();
+		if (count($result) > 0) {
+			$query = OCP\DB::prepare('INSERT INTO *PREFIX*sharing VALUES(?,?,?,?,?)');
+			$sharedFolder = '/'.$arguments['uid'].'/files/Shared/';
+			$lastSource = '';
+			for ($i = 0; $i < count($result) - 1; $i++) {
+				if ($result[$i]['source'] != $lastSource) {
+					$query->execute(array($result[$i]['uid_owner'], $arguments['uid'].'@'.$arguments['gid'], $result[$i]['source'], $sharedFolder.basename($result[$i]['source']), $result[$i]['permissions']));
+					$lastSource = $result[$i]['source'];
+				}
+			}
+		}
+	}
+
+	public static function removeFromGroupShare($arguments) {
+		$query = OCP\DB::prepare('DELETE FROM *PREFIX*sharing WHERE uid_shared_with = ?');
+		$query->execute(array($arguments['uid'].'@'.$arguments['gid']));
+	}
+
 }
 
 ?>
diff --git a/apps/files_sharing/list.php b/apps/files_sharing/list.php
old mode 100644
new mode 100755
index 721620dc92253b3c8313272380972d5e8c0f0288..2fe6bc88e63f1622a1251d7023b552e7bbeed93c
--- a/apps/files_sharing/list.php
+++ b/apps/files_sharing/list.php
@@ -20,15 +20,15 @@
  *
  */
 
-require_once('../../lib/base.php');
+
 require_once('lib_share.php');
 
-OC_Util::checkLoggedIn();
-OC_Util::checkAppEnabled('files_sharing');
+OCP\User::checkLoggedIn();
+OCP\App::checkAppEnabled('files_sharing');
 
-OC_App::setActiveNavigationEntry("files_sharing_list");
+OCP\App::setActiveNavigationEntry("files_sharing_list");
 
-OC_Util::addScript("files_sharing", "list");
+OCP\Util::addscript("files_sharing", "list");
 
 $tmpl = new OC_Template("files_sharing", "list", "user");
 $tmpl->assign("shared_items", OC_Share::getMySharedItems());
diff --git a/apps/files_sharing/settings.php b/apps/files_sharing/settings.php
new file mode 100755
index 0000000000000000000000000000000000000000..a7bdf7b91957da07a08f439f4ba15f4b79b27764
--- /dev/null
+++ b/apps/files_sharing/settings.php
@@ -0,0 +1,9 @@
+<?php
+
+OCP\User::checkAdminUser();
+OCP\Util::addscript('files_sharing', 'settings');
+$tmpl = new OC_Template('files_sharing', 'settings');
+$tmpl->assign('allowResharing', OCP\Config::getAppValue('files_sharing', 'resharing', 'yes'));
+return $tmpl->fetchPage();
+
+?>
\ No newline at end of file
diff --git a/apps/files_sharing/sharedstorage.php b/apps/files_sharing/sharedstorage.php
old mode 100644
new mode 100755
index 845659588efc325865dda15b5cd5c147ab7e1e53..c7c2131f8723e4a7f4c298790f57fef846e0117a
--- a/apps/files_sharing/sharedstorage.php
+++ b/apps/files_sharing/sharedstorage.php
@@ -25,7 +25,7 @@ require_once( 'lib_share.php' );
 if (OC_Filesystem::$loaded and !OC_Filesystem::is_dir('/Shared')) {
 	OC_Filesystem::mkdir('/Shared');
 }
-OC_Filesystem::mount('OC_Filestorage_Shared',array('datadir'=>'/'.OC_User::getUser().'/files/Shared'),'/'.OC_User::getUser().'/files/Shared/');
+OC_Filesystem::mount('OC_Filestorage_Shared',array('datadir'=>'/'.OCP\USER::getUser().'/files/Shared'),'/'.OCP\USER::getUser().'/files/Shared/');
 
 /**
  * Convert target path to source path and pass the function call to the correct storage provider
@@ -227,7 +227,7 @@ class OC_Filestorage_Shared extends OC_Filestorage {
 			}
 			if ($size > 0) {
 				$dbpath = rtrim($this->datadir.$path, "/");
-// 				$query = OC_DB::prepare("INSERT INTO *PREFIX*foldersize VALUES(?,?)");
+// 				$query = OCP\DB::prepare("INSERT INTO *PREFIX*foldersize VALUES(?,?)");
 // 				$result = $query->execute(array($dbpath, $size));
 			}
 		}
@@ -241,7 +241,7 @@ class OC_Filestorage_Shared extends OC_Filestorage {
 			$path = dirname($path);
 		}
 		$dbpath = rtrim($this->datadir.$path, "/");
-// 		$query = OC_DB::prepare("DELETE FROM *PREFIX*/*foldersize*/ WHERE path = ?");
+// 		$query = OCP\DB::prepare("DELETE FROM *PREFIX*/*foldersize*/ WHERE path = ?");
 // 		$result = $query->execute(array($dbpath));
 		if ($path != "/" && $path != "") {
 			$parts = explode("/", $path);
diff --git a/apps/files_sharing/templates/settings.php b/apps/files_sharing/templates/settings.php
new file mode 100644
index 0000000000000000000000000000000000000000..5b6ba5f33ee1d0766e7da1adfdaf0ff640602a42
--- /dev/null
+++ b/apps/files_sharing/templates/settings.php
@@ -0,0 +1,6 @@
+<form id="resharing">
+	<fieldset class="personalblock">
+	<input type="checkbox" name="allowResharing" id="allowResharing" value="1" <?php if ($_['allowResharing'] == 'yes') echo ' checked="checked"'; ?> /> <label for="allowResharing"><?php echo $l->t('Enable Resharing'); ?></label> <br/>
+	<em><?php echo $l->t('Allow users to reshare files they don\'t own');?></em>
+	</fieldset>
+</form>
\ No newline at end of file
diff --git a/apps/files_texteditor/ajax/loadfile.php b/apps/files_texteditor/ajax/loadfile.php
old mode 100644
new mode 100755
index 8ece844aa29fdf2d32a8345c45b5a3c3a0b565c4..c263306e71917b5805795f8d62ac7e44746e318f
--- a/apps/files_texteditor/ajax/loadfile.php
+++ b/apps/files_texteditor/ajax/loadfile.php
@@ -21,11 +21,11 @@
  */
 
 // Init owncloud
-require_once('../../../lib/base.php');
+ 
 
 
 // Check if we are a user
-OC_JSON::checkLoggedIn();
+OCP\JSON::checkLoggedIn();
 
 // Set the session key for the file we are about to edit.
 $dir = isset($_GET['dir']) ? $_GET['dir'] : '';
@@ -37,14 +37,14 @@ if(!empty($filename))
 	{
 		$mtime = OC_Filesystem::filemtime($path);
 		$filecontents = OC_Filesystem::file_get_contents($path);
-		OC_JSON::success(array('data' => array('filecontents' => $filecontents, 'write' => 'true', 'mtime' => $mtime)));
+		OCP\JSON::success(array('data' => array('filecontents' => $filecontents, 'write' => 'true', 'mtime' => $mtime)));
 	}
 	else
 	{
 		$mtime = OC_Filesystem::filemtime($path);
 		$filecontents = OC_Filesystem::file_get_contents($path);
-		OC_JSON::success(array('data' => array('filecontents' => $filecontents, 'write' => 'false', 'mtime' => $mtime)));	
+		OCP\JSON::success(array('data' => array('filecontents' => $filecontents, 'write' => 'false', 'mtime' => $mtime)));	
 	}	
 } else {
-	OC_JSON::error(array('data' => array( 'message' => 'Invalid file path supplied.')));	
+	OCP\JSON::error(array('data' => array( 'message' => 'Invalid file path supplied.')));	
 }
\ No newline at end of file
diff --git a/apps/files_texteditor/ajax/mtime.php b/apps/files_texteditor/ajax/mtime.php
old mode 100644
new mode 100755
index df90a68ca7a37af3ad16a20b1d12894f1172fb2f..ee683722adddf2a56ff2ee999225e12ed94b3fb1
--- a/apps/files_texteditor/ajax/mtime.php
+++ b/apps/files_texteditor/ajax/mtime.php
@@ -21,11 +21,11 @@
  */
 
 // Init owncloud
-require_once('../../../lib/base.php');
+ 
 
 
 // Check if we are a user
-OC_JSON::checkLoggedIn();
+OCP\JSON::checkLoggedIn();
 
 // Get the path from GET
 $path = isset($_GEt['path']) ? $_GET['path'] : '';
@@ -36,14 +36,14 @@ if($path != '')
 	$mtime = OC_Filesystem::filemtime($path);
 	if($mtime)
 	{
-		OC_JSON::success(array('data' => array('path' => $path, 'mtime' => $mtime)));
+		OCP\JSON::success(array('data' => array('path' => $path, 'mtime' => $mtime)));
 	}
 	else
 	{
-		OC_JSON::error();
+		OCP\JSON::error();
 	}	
 }
 else
 {
-	OC_JSON::error();	
+	OCP\JSON::error();	
 }
\ No newline at end of file
diff --git a/apps/files_texteditor/ajax/savefile.php b/apps/files_texteditor/ajax/savefile.php
old mode 100644
new mode 100755
index 57a948478f52d6f4c8f8b1e38a6a82843c14761c..4c260e237c5b554c4e9f599c3d86ff2125b33ab3
--- a/apps/files_texteditor/ajax/savefile.php
+++ b/apps/files_texteditor/ajax/savefile.php
@@ -21,11 +21,11 @@
  */
 
 // Init owncloud
-require_once('../../../lib/base.php');
+ 
 
 
 // Check if we are a user
-OC_JSON::checkLoggedIn();
+OCP\JSON::checkLoggedIn();
 
 // Get paramteres
 $filecontents = $_POST['filecontents'];
@@ -39,8 +39,8 @@ if($path != '' && $mtime != '')
 	if($mtime != $filemtime)
 	{
 		// Then the file has changed since opening
-		OC_JSON::error();
-		OC_Log::write('files_texteditor',"File: ".$path." modified since opening.",OC_Log::ERROR);	
+		OCP\JSON::error();
+		OCP\Util::writeLog('files_texteditor',"File: ".$path." modified since opening.",OCP\Util::ERROR);	
 	}
 	else
 	{
@@ -53,16 +53,16 @@ if($path != '' && $mtime != '')
 			clearstatcache();
 			// Get new mtime
 			$newmtime = OC_Filesystem::filemtime($path);
-			OC_JSON::success(array('data' => array('mtime' => $newmtime)));
+			OCP\JSON::success(array('data' => array('mtime' => $newmtime)));
 		}
 		else
 		{
 			// Not writeable!
-			OC_JSON::error(array('data' => array( 'message' => 'Insufficient permissions')));	
-			OC_Log::write('files_texteditor',"User does not have permission to write to file: ".$path,OC_Log::ERROR);
+			OCP\JSON::error(array('data' => array( 'message' => 'Insufficient permissions')));	
+			OCP\Util::writeLog('files_texteditor',"User does not have permission to write to file: ".$path,OCP\Util::ERROR);
 		}
 	}
 } else {
-	OC_JSON::error(array('data' => array( 'message' => 'File path or mtime not supplied')));
-	OC_Log::write('files_texteditor',"Invalid path supplied:".$path,OC_Log::ERROR);	
+	OCP\JSON::error(array('data' => array( 'message' => 'File path or mtime not supplied')));
+	OCP\Util::writeLog('files_texteditor',"Invalid path supplied:".$path,OCP\Util::ERROR);	
 }
diff --git a/apps/files_texteditor/appinfo/app.php b/apps/files_texteditor/appinfo/app.php
old mode 100644
new mode 100755
index 1bf09b5da2a1c0c847a43745302fd2fb77ca842e..a08077ebb67e31b75afeb40e99a02c4ebe5cc9b6
--- a/apps/files_texteditor/appinfo/app.php
+++ b/apps/files_texteditor/appinfo/app.php
@@ -1,6 +1,6 @@
 <?php
 //load the required files
-OC_Util::addStyle( 'files_texteditor', 'style' );
-OC_Util::addScript( 'files_texteditor', 'editor');
-OC_Util::addScript( 'files_texteditor', 'aceeditor/ace');
-?>
\ No newline at end of file
+OCP\Util::addStyle( 'files_texteditor', 'style' );
+OCP\Util::addscript( 'files_texteditor', 'editor');
+OCP\Util::addscript( 'files_texteditor', 'aceeditor/ace');
+?>
diff --git a/apps/files_texteditor/appinfo/info.xml b/apps/files_texteditor/appinfo/info.xml
index da1cdba15dd8d0182859ad24d793599c76a220e8..83c057f38fdf3ce3fb01fd1ae10b5e1de81d423b 100644
--- a/apps/files_texteditor/appinfo/info.xml
+++ b/apps/files_texteditor/appinfo/info.xml
@@ -3,7 +3,6 @@
 	<id>files_texteditor</id>
 	<name>Text Editor</name>
 	<description>Simple plain text editor based on Ace editor.</description>
-	<version>0.3</version>
 	<licence>AGPL</licence>
 	<author>Tom Needham</author>
 	<require>2</require>
diff --git a/apps/files_texteditor/appinfo/version b/apps/files_texteditor/appinfo/version
new file mode 100644
index 0000000000000000000000000000000000000000..1d71ef97443918d538e8188167c94d7bbafaf753
--- /dev/null
+++ b/apps/files_texteditor/appinfo/version
@@ -0,0 +1 @@
+0.3
\ No newline at end of file
diff --git a/apps/files_texteditor/css/style.css b/apps/files_texteditor/css/style.css
index 6a4392a08e96854a551b977b1bec5212508ecb08..d91a91d18d0ac3f93c8008964961fdc27bc62ca7 100644
--- a/apps/files_texteditor/css/style.css
+++ b/apps/files_texteditor/css/style.css
@@ -14,12 +14,9 @@
 }
 #editor_save{
 	margin-left: 7px;
-	float: left;	
+	float: left;
 }
 #saving_icon{
 	margin-top: 3px;
-	float: left;	
-}
-#gotolineval{
-	width: 30px;
+	float: left;
 }
diff --git a/apps/files_texteditor/js/aceeditor/LICENSE b/apps/files_texteditor/js/aceeditor/LICENSE
old mode 100755
new mode 100644
diff --git a/apps/files_texteditor/js/aceeditor/ace-compat-uncompressed.js b/apps/files_texteditor/js/aceeditor/ace-compat-uncompressed.js
old mode 100755
new mode 100644
index 7fa232a335f4ff324222e9c469a9282ad3672c46..50efbe1443cacc3b1173e6c6bcce131a06ecc3c8
--- a/apps/files_texteditor/js/aceeditor/ace-compat-uncompressed.js
+++ b/apps/files_texteditor/js/aceeditor/ace-compat-uncompressed.js
@@ -478,13 +478,3 @@ define('pilot/canon', ['require', 'exports', 'module' ], function(require, expor
         console.trace();
     }
 });
-;
-            (function() {
-                window.require(["ace/ace"], function(a) {
-                    if (!window.ace)
-                        window.ace = {};
-                    for (var key in a) if (a.hasOwnProperty(key))
-                        ace[key] = a[key];
-                });
-            })();
-        
\ No newline at end of file
diff --git a/apps/files_texteditor/js/aceeditor/ace-compat.js b/apps/files_texteditor/js/aceeditor/ace-compat.js
old mode 100755
new mode 100644
index 5dcbb1cc38ae8e909bb70e217cec48bc1166b445..18d2ed78d0f71fb7db928b818b42f98cee11410b
--- a/apps/files_texteditor/js/aceeditor/ace-compat.js
+++ b/apps/files_texteditor/js/aceeditor/ace-compat.js
@@ -1 +1 @@
-define("pilot/index",["require","exports","module","pilot/browser_focus","pilot/dom","pilot/event","pilot/event_emitter","pilot/fixoldbrowsers","pilot/keys","pilot/lang","pilot/oop","pilot/useragent","pilot/canon"],function(a,b,c){a("pilot/browser_focus"),a("pilot/dom"),a("pilot/event"),a("pilot/event_emitter"),a("pilot/fixoldbrowsers"),a("pilot/keys"),a("pilot/lang"),a("pilot/oop"),a("pilot/useragent"),a("pilot/canon")}),define("pilot/browser_focus",["require","exports","module","ace/lib/browser_focus"],function(a,b,c){console.warn("DEPRECATED: 'pilot/browser_focus' is deprecated. Use 'ace/lib/browser_focus' instead"),c.exports=a("ace/lib/browser_focus")}),define("pilot/dom",["require","exports","module","ace/lib/dom"],function(a,b,c){console.warn("DEPRECATED: 'pilot/dom' is deprecated. Use 'ace/lib/dom' instead"),c.exports=a("ace/lib/dom")}),define("pilot/event",["require","exports","module","ace/lib/event"],function(a,b,c){console.warn("DEPRECATED: 'pilot/event' is deprecated. Use 'ace/lib/event' instead"),c.exports=a("ace/lib/event")}),define("pilot/event_emitter",["require","exports","module","ace/lib/event_emitter"],function(a,b,c){console.warn("DEPRECATED: 'pilot/event_emitter' is deprecated. Use 'ace/lib/event_emitter' instead"),c.exports=a("ace/lib/event_emitter")}),define("pilot/fixoldbrowsers",["require","exports","module","ace/lib/fixoldbrowsers"],function(a,b,c){console.warn("DEPRECATED: 'pilot/fixoldbrowsers' is deprecated. Use 'ace/lib/fixoldbrowsers' instead"),c.exports=a("ace/lib/fixoldbrowsers")}),define("pilot/keys",["require","exports","module","ace/lib/keys"],function(a,b,c){console.warn("DEPRECATED: 'pilot/keys' is deprecated. Use 'ace/lib/keys' instead"),c.exports=a("ace/lib/keys")}),define("pilot/lang",["require","exports","module","ace/lib/lang"],function(a,b,c){console.warn("DEPRECATED: 'pilot/lang' is deprecated. Use 'ace/lib/lang' instead"),c.exports=a("ace/lib/lang")}),define("pilot/oop",["require","exports","module","ace/lib/oop"],function(a,b,c){console.warn("DEPRECATED: 'pilot/oop' is deprecated. Use 'ace/lib/oop' instead"),c.exports=a("ace/lib/oop")}),define("pilot/useragent",["require","exports","module","ace/lib/useragent"],function(a,b,c){console.warn("DEPRECATED: 'pilot/useragent' is deprecated. Use 'ace/lib/useragent' instead"),c.exports=a("ace/lib/useragent")}),define("pilot/canon",["require","exports","module"],function(a,b,c){console.warn("DEPRECATED: 'pilot/canon' is deprecated."),b.addCommand=function(){console.warn("DEPRECATED: 'canon.addCommand()' is deprecated. Use 'editor.commands.addCommand(command)' instead."),console.trace()},b.removeCommand=function(){console.warn("DEPRECATED: 'canon.removeCommand()' is deprecated. Use 'editor.commands.removeCommand(command)' instead."),console.trace()}}),function(){window.require(["ace/ace"],function(a){window.ace||(window.ace={});for(var b in a)a.hasOwnProperty(b)&&(ace[b]=a[b])})}()
\ No newline at end of file
+define("pilot/index",["require","exports","module","pilot/browser_focus","pilot/dom","pilot/event","pilot/event_emitter","pilot/fixoldbrowsers","pilot/keys","pilot/lang","pilot/oop","pilot/useragent","pilot/canon"],function(a,b,c){a("pilot/browser_focus"),a("pilot/dom"),a("pilot/event"),a("pilot/event_emitter"),a("pilot/fixoldbrowsers"),a("pilot/keys"),a("pilot/lang"),a("pilot/oop"),a("pilot/useragent"),a("pilot/canon")}),define("pilot/browser_focus",["require","exports","module","ace/lib/browser_focus"],function(a,b,c){console.warn("DEPRECATED: 'pilot/browser_focus' is deprecated. Use 'ace/lib/browser_focus' instead"),c.exports=a("ace/lib/browser_focus")}),define("pilot/dom",["require","exports","module","ace/lib/dom"],function(a,b,c){console.warn("DEPRECATED: 'pilot/dom' is deprecated. Use 'ace/lib/dom' instead"),c.exports=a("ace/lib/dom")}),define("pilot/event",["require","exports","module","ace/lib/event"],function(a,b,c){console.warn("DEPRECATED: 'pilot/event' is deprecated. Use 'ace/lib/event' instead"),c.exports=a("ace/lib/event")}),define("pilot/event_emitter",["require","exports","module","ace/lib/event_emitter"],function(a,b,c){console.warn("DEPRECATED: 'pilot/event_emitter' is deprecated. Use 'ace/lib/event_emitter' instead"),c.exports=a("ace/lib/event_emitter")}),define("pilot/fixoldbrowsers",["require","exports","module","ace/lib/fixoldbrowsers"],function(a,b,c){console.warn("DEPRECATED: 'pilot/fixoldbrowsers' is deprecated. Use 'ace/lib/fixoldbrowsers' instead"),c.exports=a("ace/lib/fixoldbrowsers")}),define("pilot/keys",["require","exports","module","ace/lib/keys"],function(a,b,c){console.warn("DEPRECATED: 'pilot/keys' is deprecated. Use 'ace/lib/keys' instead"),c.exports=a("ace/lib/keys")}),define("pilot/lang",["require","exports","module","ace/lib/lang"],function(a,b,c){console.warn("DEPRECATED: 'pilot/lang' is deprecated. Use 'ace/lib/lang' instead"),c.exports=a("ace/lib/lang")}),define("pilot/oop",["require","exports","module","ace/lib/oop"],function(a,b,c){console.warn("DEPRECATED: 'pilot/oop' is deprecated. Use 'ace/lib/oop' instead"),c.exports=a("ace/lib/oop")}),define("pilot/useragent",["require","exports","module","ace/lib/useragent"],function(a,b,c){console.warn("DEPRECATED: 'pilot/useragent' is deprecated. Use 'ace/lib/useragent' instead"),c.exports=a("ace/lib/useragent")}),define("pilot/canon",["require","exports","module"],function(a,b,c){console.warn("DEPRECATED: 'pilot/canon' is deprecated."),b.addCommand=function(){console.warn("DEPRECATED: 'canon.addCommand()' is deprecated. Use 'editor.commands.addCommand(command)' instead."),console.trace()},b.removeCommand=function(){console.warn("DEPRECATED: 'canon.removeCommand()' is deprecated. Use 'editor.commands.removeCommand(command)' instead."),console.trace()}})
\ No newline at end of file
diff --git a/apps/files_texteditor/js/aceeditor/ace-uncompressed.js b/apps/files_texteditor/js/aceeditor/ace-uncompressed.js
old mode 100755
new mode 100644
index 619baf49016619220c81571953f1cd879f7e96a8..74bb44b16d83d627ad172e3411d1d87dd286d52e
--- a/apps/files_texteditor/js/aceeditor/ace-uncompressed.js
+++ b/apps/files_texteditor/js/aceeditor/ace-uncompressed.js
@@ -40,7 +40,7 @@
  * @param module a name for the payload
  * @param payload a function to call with (require, exports, module) params
  */
- 
+
 (function() {
 
 var ACE_NAMESPACE = "";
@@ -49,9 +49,6 @@ var global = (function() {
     return this;
 })();
 
-if (typeof requirejs !== "undefined")
-    return;
-
 var _define = function(module, deps, payload) {
     if (typeof module !== 'string') {
         if (_define.original)
@@ -68,7 +65,7 @@ var _define = function(module, deps, payload) {
 
     if (!_define.modules)
         _define.modules = {};
-        
+
     _define.modules[module] = payload;
 };
 
@@ -92,11 +89,11 @@ var _require = function(parentId, module, callback) {
         var payload = lookup(parentId, module);
         if (!payload && _require.original)
             return _require.original.apply(window, arguments);
-        
+
         if (callback) {
             callback();
         }
-    
+
         return payload;
     }
     else {
@@ -115,13 +112,13 @@ var normalizeModule = function(parentId, moduleName) {
     if (moduleName.charAt(0) == ".") {
         var base = parentId.split("/").slice(0, -1).join("/");
         moduleName = base + "/" + moduleName;
-        
+
         while(moduleName.indexOf(".") !== -1 && previous != moduleName) {
             var previous = moduleName;
             moduleName = moduleName.replace(/\/\.\//, "/").replace(/[^\/]+\/\.\.\//, "");
         }
     }
-    
+
     return moduleName;
 };
 
@@ -141,19 +138,19 @@ var lookup = function(parentId, moduleName) {
     if (typeof module === 'function') {
         var exports = {};
         var mod = {
-            id: moduleName, 
+            id: moduleName,
             uri: '',
             exports: exports,
             packaged: true
         };
-        
+
         var req = function(module, callback) {
             return _require(moduleName, module, callback);
         };
-        
+
         var returnValue = module(req, exports, mod);
         exports = returnValue || mod.exports;
-            
+
         // cache the resulting module object for next time
         _define.modules[moduleName] = exports;
         return exports;
@@ -163,26 +160,45 @@ var lookup = function(parentId, moduleName) {
 };
 
 function exportAce(ns) {
+
+    if (typeof requirejs !== "undefined") {
+
+        var define = global.define;
+        global.define = function(id, deps, callback) {
+            if (typeof callback !== "function")
+                return define.apply(this, arguments);
+
+            return define(id, deps, function(require, exports, module) {
+                if (deps[2] == "module")
+                    module.packaged = true;
+                return callback.apply(this, arguments);
+            });
+        };
+        global.define.packaged = true;
+
+        return;
+    }
+
     var require = function(module, callback) {
         return _require("", module, callback);
     };
     require.packaged = true;
-    
+
     var root = global;
     if (ns) {
         if (!global[ns])
             global[ns] = {};
         root = global[ns];
     }
-        
+
     if (root.define)
         _define.original = root.define;
-    
+
     root.define = _define;
 
     if (root.require)
         _require.original = root.require;
-    
+
     root.require = require;
 }
 
@@ -225,7 +241,7 @@ exportAce(ACE_NAMESPACE);
  *
  * ***** END LICENSE BLOCK ***** */
 
-define('ace/ace', ['require', 'exports', 'module' , 'ace/lib/fixoldbrowsers', 'ace/lib/dom', 'ace/lib/event', 'ace/editor', 'ace/edit_session', 'ace/undomanager', 'ace/virtual_renderer', 'ace/theme/textmate'], function(require, exports, module) {
+define('ace/ace', ['require', 'exports', 'module' , 'ace/lib/fixoldbrowsers', 'ace/lib/dom', 'ace/lib/event', 'ace/editor', 'ace/edit_session', 'ace/undomanager', 'ace/virtual_renderer', 'ace/multi_select', 'ace/worker/worker_client', 'ace/keyboard/hash_handler', 'ace/keyboard/state_handler', 'ace/placeholder', 'ace/config', 'ace/theme/textmate'], function(require, exports, module) {
 "use strict";
 
 require("./lib/fixoldbrowsers");
@@ -237,6 +253,14 @@ var Editor = require("./editor").Editor;
 var EditSession = require("./edit_session").EditSession;
 var UndoManager = require("./undomanager").UndoManager;
 var Renderer = require("./virtual_renderer").VirtualRenderer;
+var MultiSelect = require("./multi_select").MultiSelect;
+
+// The following require()s are for inclusion in the built ace file
+require("./worker/worker_client");
+require("./keyboard/hash_handler");
+require("./keyboard/state_handler");
+require("./placeholder");
+require("./config").init();
 
 exports.edit = function(el) {
     if (typeof(el) == "string") {
@@ -248,6 +272,7 @@ exports.edit = function(el) {
     el.innerHTML = '';
 
     var editor = new Editor(new Renderer(el, require("./theme/textmate")));
+    new MultiSelect(editor);
     editor.setSession(doc);
 
     var env = {};
@@ -326,7 +351,7 @@ define('ace/lib/regexp', ['require', 'exports', 'module' ], function(require, ex
     RegExp.prototype.exec = function (str) {
         var match = real.exec.apply(this, arguments),
             name, r2;
-        if (match) {
+        if ( typeof(str) == 'string' && match) {
             // Fix browsers whose `exec` methods don't consistently return `undefined` for
             // nonparticipating capturing groups
             if (!compliantExecNpcg && match.length > 1 && indexOf(match, "") > -1) {
@@ -391,7 +416,8 @@ define('ace/lib/regexp', ['require', 'exports', 'module' ], function(require, ex
         return -1;
     };
 
-});// vim: ts=4 sts=4 sw=4 expandtab
+});
+// vim: ts=4 sts=4 sw=4 expandtab
 // -- kriskowal Kris Kowal Copyright (C) 2009-2011 MIT License
 // -- tlrobinson Tom Robinson Copyright (C) 2009-2010 MIT License (Narwhal Project)
 // -- dantman Daniel Friesen Copyright (C) 2010 XXX TODO License or CLA
@@ -1573,7 +1599,7 @@ exports.hasCssString = function(id, doc) {
 
     if (doc.createStyleSheet && (sheets = doc.styleSheets)) {
         while (index < sheets.length)
-            if (sheets[index++].title === id) return true;
+            if (sheets[index++].owningElement.id === id) return true;
     } else if ((sheets = doc.getElementsByTagName("style"))) {
         while (index < sheets.length)
             if (sheets[index++].id === id) return true;
@@ -1594,7 +1620,7 @@ exports.importCssString = function importCssString(cssText, id, doc) {
         style = doc.createStyleSheet();
         style.cssText = cssText;
         if (id)
-            style.title = id;
+            style.owningElement.id = id;
     } else {
         style = doc.createElementNS
             ? doc.createElementNS(XHTML_NS, "style")
@@ -1740,8 +1766,7 @@ exports.getParentWindow = function(document) {
     return document.defaultView || document.parentWindow;
 };
 
-});
-/* ***** BEGIN LICENSE BLOCK *****
+});/* ***** BEGIN LICENSE BLOCK *****
  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  *
  * The contents of this file are subject to the Mozilla Public License Version
@@ -1917,20 +1942,9 @@ else {
 }
 
 exports.addMouseWheelListener = function(el, callback) {
-    var max = 0;
+    var factor = 8;
     var listener = function(e) {
         if (e.wheelDelta !== undefined) {
-
-            // some versions of Safari (e.g. 5.0.5) report insanely high
-            // scroll values. These browsers require a higher factor
-            if (Math.abs(e.wheelDeltaY) > max)
-                max = Math.abs(e.wheelDeltaY);
-
-            if (max > 5000)
-                var factor = 400;
-            else
-                var factor = 8;
-
             if (e.wheelDeltaX !== undefined) {
                 e.wheelX = -e.wheelDeltaX / factor;
                 e.wheelY = -e.wheelDeltaY / factor;
@@ -2029,7 +2043,7 @@ function normalizeCommandKeys(callback, e, keyCode) {
 
 exports.addCommandKeyListener = function(el, callback) {
     var addListener = exports.addListener;
-    if (useragent.isOldGecko) {
+    if (useragent.isOldGecko || useragent.isOpera) {
         // Old versions of Gecko aka. Firefox < 4.0 didn't repeat the keydown
         // event if the user pressed the key for a longer time. Instead, the
         // keydown event was fired once and later on only the keypress event.
@@ -2050,18 +2064,6 @@ exports.addCommandKeyListener = function(el, callback) {
             lastDown = e.keyIdentifier || e.keyCode;
             return normalizeCommandKeys(callback, e, e.keyCode);
         });
-
-        // repeated keys are fired as keypress and not keydown events
-        if (useragent.isMac && useragent.isOpera) {
-            addListener(el, "keypress", function(e) {
-                var keyId = e.keyIdentifier || e.keyCode;
-                if (lastDown !== keyId) {
-                    return normalizeCommandKeys(callback, e, lastDown);
-                } else {
-                    lastDown = null;
-                }
-            });
-        }
     }
 };
 
@@ -2446,7 +2448,7 @@ var Editor = function(renderer, session) {
     var container = renderer.getContainerElement();
     this.container = container;
     this.renderer = renderer;
-    
+
     this.textInput  = new TextInput(renderer.getTextAreaContainer(), this);
     this.keyBinding = new KeyBinding(this);
 
@@ -2558,7 +2560,10 @@ var Editor = function(renderer, session) {
 
         this.onChangeMode();
 
+        this.$blockScrolling += 1;
         this.onCursorChange();
+        this.$blockScrolling -= 1;
+
         this.onScrollTopChange();
         this.onScrollLeftChange();
         this.onSelectionChange();
@@ -2605,6 +2610,7 @@ var Editor = function(renderer, session) {
 
     this.setFontSize = function(size) {
         this.container.style.fontSize = size;
+        this.renderer.updateFontSize();
     };
 
     this.$highlightBrackets = function() {
@@ -2710,21 +2716,29 @@ var Editor = function(renderer, session) {
     this.$updateHighlightActiveLine = function() {
         var session = this.getSession();
 
-        if (session.$highlightLineMarker) {
+        if (session.$highlightLineMarker)
             session.removeMarker(session.$highlightLineMarker);
-        }
+        if (typeof this.$lastrow == "number")
+            this.renderer.removeGutterDecoration(this.$lastrow, "ace_gutter_active_line");
+
         session.$highlightLineMarker = null;
+        this.$lastrow = null;
 
-        if (this.getHighlightActiveLine() && (this.getSelectionStyle() != "line" || !this.selection.isMultiLine())) {
+        if (this.getHighlightActiveLine()) {
             var cursor = this.getCursorPosition(),
                 foldLine = this.session.getFoldLine(cursor.row);
-            var range;
-            if (foldLine) {
-                range = new Range(foldLine.start.row, 0, foldLine.end.row + 1, 0);
-            } else {
-                range = new Range(cursor.row, 0, cursor.row+1, 0);
+
+            if ((this.getSelectionStyle() != "line" || !this.selection.isMultiLine())) {
+                var range;
+                if (foldLine) {
+                    range = new Range(foldLine.start.row, 0, foldLine.end.row + 1, 0);
+                } else {
+                    range = new Range(cursor.row, 0, cursor.row+1, 0);
+                }
+                session.$highlightLineMarker = session.addMarker(range, "ace_active_line", "background");
             }
-            session.$highlightLineMarker = session.addMarker(range, "ace_active_line", "background");
+
+            this.renderer.addGutterDecoration(this.$lastrow = cursor.row, "ace_gutter_active_line");
         }
     };
 
@@ -2794,16 +2808,7 @@ var Editor = function(renderer, session) {
     };
 
     this.onCut = function() {
-        if (this.$readOnly)
-            return;
-
-        var range = this.getSelectionRange();
-        this._emit("cut", range);
-
-        if (!this.selection.isEmpty()) {
-            this.session.remove(range);
-            this.clearSelection();
-        }
+        this.commands.exec("cut", this);
     };
 
     this.insert = function(text) {
@@ -2978,6 +2983,14 @@ var Editor = function(renderer, session) {
         return this.$highlightSelectedWord;
     };
 
+    this.setAnimatedScroll = function(shouldAnimate){
+        this.renderer.setAnimatedScroll(shouldAnimate);
+    };
+
+    this.getAnimatedScroll = function(){
+        return this.renderer.getAnimatedScroll();
+    };
+
     this.setShowInvisibles = function(showInvisibles) {
         if (this.getShowInvisibles() == showInvisibles)
             return;
@@ -3032,7 +3045,7 @@ var Editor = function(renderer, session) {
         this.$showFoldWidgets = show;
         this.renderer.updateFull();
     };
-    
+
     this.getShowFoldWidgets = function() {
         return this.renderer.$gutterLayer.getShowFoldWidgets();
     };
@@ -3249,7 +3262,7 @@ var Editor = function(renderer, session) {
             range.start.row += linesMoved;
             range.end.row += linesMoved;
             selection.setSelectionRange(range, reverse);
-        } 
+        }
         else {
             selection.setSelectionAnchor(rows.last+linesMoved+1, 0);
             selection.$moveSelection(function() {
@@ -3413,13 +3426,13 @@ var Editor = function(renderer, session) {
             cursor.column -= 2;
             pos = this.session.findMatchingBracket(cursor);
         }
-        
+
         if (pos) {
             this.clearSelection();
             this.moveCursorTo(pos.row, pos.column);
         }
     };
-    
+
     this.gotoLine = function(lineNumber, column) {
         this.selection.clearSelection();
         this.session.unfold({row: lineNumber - 1, column: column || 0});
@@ -3511,12 +3524,19 @@ var Editor = function(renderer, session) {
             this.$search.set(options);
 
         var range = this.$search.find(this.session);
+        var replaced = 0;
         if (!range)
-            return;
+            return replaced;
 
-        this.$tryReplace(range, replacement);
-        if (range !== null)
+        if (this.$tryReplace(range, replacement)) {
+            replaced = 1;
+        }
+        if (range !== null) {
             this.selection.setSelectionRange(range);
+            this.renderer.scrollSelectionIntoView(range.start, range.end);
+        }
+
+        return replaced;
     };
 
     this.replaceAll = function(replacement, options) {
@@ -3525,19 +3545,25 @@ var Editor = function(renderer, session) {
         }
 
         var ranges = this.$search.findAll(this.session);
+        var replaced = 0;
         if (!ranges.length)
-            return;
+            return replaced;
 
         var selection = this.getSelectionRange();
         this.clearSelection();
         this.selection.moveCursorTo(0, 0);
 
         this.$blockScrolling += 1;
-        for (var i = ranges.length - 1; i >= 0; --i)
-            this.$tryReplace(ranges[i], replacement);
+        for (var i = ranges.length - 1; i >= 0; --i) {
+            if(this.$tryReplace(ranges[i], replacement)) {
+                replaced++;
+            }
+        }
 
         this.selection.setSelectionRange(selection);
         this.$blockScrolling -= 1;
+
+        return replaced;
     };
 
     this.$tryReplace = function(range, replacement) {
@@ -3589,8 +3615,23 @@ var Editor = function(renderer, session) {
         var range = this.$search.find(this.session);
         if (range) {
             this.session.unfold(range);
-            this.gotoLine(range.end.row+1, range.end.column);
+
+            this.$blockScrolling += 1;
             this.selection.setSelectionRange(range);
+            this.$blockScrolling -= 1;
+
+            if (this.getAnimatedScroll()) {
+                var cursor = this.getCursorPosition();
+                if (!this.isRowFullyVisible(cursor.row))
+                    this.scrollToLine(cursor.row, true);
+    
+                //@todo scroll X
+                //if (!this.isColumnFullyVisible(cursor.column))
+                    //this.scrollToRow(cursor.column);
+            }
+            else {
+                this.renderer.scrollSelectionIntoView(range.start, range.end);
+            }
         }
     };
 
@@ -4298,7 +4339,7 @@ function DefaultHandlers(editor) {
             if (!editor.$mouseHandler.$clickSelection) {
                 if (!dragCursor) {
                     editor.moveCursorToPosition(pos);
-                    editor.selection.clearSelection(pos.row, pos.column);
+                    editor.selection.clearSelection();
                 }
             }
 
@@ -4333,7 +4374,6 @@ function DefaultHandlers(editor) {
                 if (distance > DRAG_OFFSET) {
                     state = STATE_SELECT;
                     var cursor = editor.renderer.screenToTextCoordinates(mousePageX, mousePageY);
-                    cursor.row = Math.max(0, Math.min(cursor.row, editor.session.getLength()-1));
                     onStartSelect(cursor);
                 }
                 else if ((time - mousedownTime) > editor.getDragDelay()) {
@@ -4360,7 +4400,7 @@ function DefaultHandlers(editor) {
             else {
                 if (!_self.$clickSelection) {
                     editor.moveCursorToPosition(pos);
-                    editor.selection.clearSelection(pos.row, pos.column);
+                    editor.selection.clearSelection();
                 }
             }
             state = STATE_SELECT;
@@ -4369,7 +4409,6 @@ function DefaultHandlers(editor) {
         var onUpdateSelectionInterval = function() {
             var anchor;
             var cursor = editor.renderer.screenToTextCoordinates(mousePageX, mousePageY);
-            cursor.row = Math.max(0, Math.min(cursor.row, editor.session.getLength()-1));
 
             if (_self.$clickSelection) {
                 if (_self.$clickSelection.contains(cursor.row, cursor.column)) {
@@ -4395,8 +4434,6 @@ function DefaultHandlers(editor) {
 
         var onDragSelectionInterval = function() {
             dragCursor = editor.renderer.screenToTextCoordinates(mousePageX, mousePageY);
-            dragCursor.row = Math.max(0, Math.min(dragCursor.row, editor.session.getLength() - 1));
-
             editor.moveCursorToPosition(dragCursor);
         };
 
@@ -4818,7 +4855,6 @@ var MouseEvent = exports.MouseEvent = function(domEvent, editor) {
         var pageX = event.getDocumentX(this.domEvent);
         var pageY = event.getDocumentY(this.domEvent);
         this.$pos = this.editor.renderer.screenToTextCoordinates(pageX, pageY);
-        this.$pos.row = Math.max(0, Math.min(this.$pos.row, this.editor.session.getLength()-1));
         return this.$pos;
     };
     
@@ -4918,7 +4954,7 @@ function FoldHandler(editor) {
         var position = e.getDocumentPosition();
         var session = editor.session;
         
-        // If the user dclicked on a fold, then expand it.
+        // If the user clicked on a fold, then expand it.
         var fold = session.getFoldAt(position.row, position.column, 1);
         if (fold) {
             if (e.getAccelKey())
@@ -5198,91 +5234,109 @@ exports.commands = [{
     name: "selectup",
     bindKey: bindKey("Shift-Up", "Shift-Up"),
     exec: function(editor) { editor.getSelection().selectUp(); },
+    multiSelectAction: "forEach",
     readOnly: true
 }, {
     name: "golineup",
     bindKey: bindKey("Up", "Up|Ctrl-P"),
     exec: function(editor, args) { editor.navigateUp(args.times); },
+    multiSelectAction: "forEach",
     readOnly: true
 }, {
     name: "selecttoend",
     bindKey: bindKey("Ctrl-Shift-End|Alt-Shift-Down", "Command-Shift-Down"),
     exec: function(editor) { editor.getSelection().selectFileEnd(); },
+    multiSelectAction: "forEach",
     readOnly: true
 }, {
     name: "gotoend",
     bindKey: bindKey("Ctrl-End|Ctrl-Down", "Command-End|Command-Down"),
     exec: function(editor) { editor.navigateFileEnd(); },
+    multiSelectAction: "forEach",
     readOnly: true
 }, {
     name: "selectdown",
     bindKey: bindKey("Shift-Down", "Shift-Down"),
     exec: function(editor) { editor.getSelection().selectDown(); },
+    multiSelectAction: "forEach",
     readOnly: true
 }, {
     name: "golinedown",
     bindKey: bindKey("Down", "Down|Ctrl-N"),
     exec: function(editor, args) { editor.navigateDown(args.times); },
+    multiSelectAction: "forEach",
     readOnly: true
 }, {
     name: "selectwordleft",
     bindKey: bindKey("Ctrl-Shift-Left", "Option-Shift-Left"),
     exec: function(editor) { editor.getSelection().selectWordLeft(); },
+    multiSelectAction: "forEach",
     readOnly: true
 }, {
     name: "gotowordleft",
     bindKey: bindKey("Ctrl-Left", "Option-Left"),
     exec: function(editor) { editor.navigateWordLeft(); },
+    multiSelectAction: "forEach",
     readOnly: true
 }, {
     name: "selecttolinestart",
     bindKey: bindKey("Alt-Shift-Left", "Command-Shift-Left"),
     exec: function(editor) { editor.getSelection().selectLineStart(); },
+    multiSelectAction: "forEach",
     readOnly: true
 }, {
     name: "gotolinestart",
     bindKey: bindKey("Alt-Left|Home", "Command-Left|Home|Ctrl-A"),
     exec: function(editor) { editor.navigateLineStart(); },
+    multiSelectAction: "forEach",
     readOnly: true
 }, {
     name: "selectleft",
     bindKey: bindKey("Shift-Left", "Shift-Left"),
     exec: function(editor) { editor.getSelection().selectLeft(); },
+    multiSelectAction: "forEach",
     readOnly: true
 }, {
     name: "gotoleft",
     bindKey: bindKey("Left", "Left|Ctrl-B"),
     exec: function(editor, args) { editor.navigateLeft(args.times); },
+    multiSelectAction: "forEach",
     readOnly: true
 }, {
     name: "selectwordright",
     bindKey: bindKey("Ctrl-Shift-Right", "Option-Shift-Right"),
     exec: function(editor) { editor.getSelection().selectWordRight(); },
+    multiSelectAction: "forEach",
     readOnly: true
 }, {
     name: "gotowordright",
     bindKey: bindKey("Ctrl-Right", "Option-Right"),
     exec: function(editor) { editor.navigateWordRight(); },
+    multiSelectAction: "forEach",
     readOnly: true
 }, {
     name: "selecttolineend",
     bindKey: bindKey("Alt-Shift-Right", "Command-Shift-Right"),
     exec: function(editor) { editor.getSelection().selectLineEnd(); },
+    multiSelectAction: "forEach",
     readOnly: true
 }, {
     name: "gotolineend",
     bindKey: bindKey("Alt-Right|End", "Command-Right|End|Ctrl-E"),
     exec: function(editor) { editor.navigateLineEnd(); },
+    multiSelectAction: "forEach",
     readOnly: true
 }, {
     name: "selectright",
     bindKey: bindKey("Shift-Right", "Shift-Right"),
     exec: function(editor) { editor.getSelection().selectRight(); },
+    multiSelectAction: "forEach",
     readOnly: true
 }, {
     name: "gotoright",
     bindKey: bindKey("Right", "Right|Ctrl-F"),
     exec: function(editor, args) { editor.navigateRight(args.times); },
+    multiSelectAction: "forEach",
     readOnly: true
 }, {
     name: "selectpagedown",
@@ -5318,11 +5372,13 @@ exports.commands = [{
     name: "selectlinestart",
     bindKey: bindKey("Shift-Home", "Shift-Home"),
     exec: function(editor) { editor.getSelection().selectLineStart(); },
+    multiSelectAction: "forEach",
     readOnly: true
 }, {
     name: "selectlineend",
     bindKey: bindKey("Shift-End", "Shift-End"),
     exec: function(editor) { editor.getSelection().selectLineEnd(); },
+    multiSelectAction: "forEach",
     readOnly: true
 }, {
     name: "togglerecording",
@@ -5334,17 +5390,37 @@ exports.commands = [{
     bindKey: bindKey("Ctrl-Shift-E", "Command-Shift-E"),
     exec: function(editor) { editor.commands.replay(editor); },
     readOnly: true
+}, {
+    name: "jumptomatching",
+    bindKey: bindKey("Ctrl-Shift-P", "Ctrl-Shift-P"),
+    exec: function(editor) { editor.jumpToMatching(); },
+    multiSelectAction: "forEach",
+    readOnly: true
 }, 
 
 // commands disabled in readOnly mode
 {
+    name: "cut",
+    exec: function(editor) {
+        var range = editor.getSelectionRange();
+        editor._emit("cut", range);
+
+        if (!editor.selection.isEmpty()) {
+            editor.session.remove(range);
+            editor.clearSelection();
+        }
+    },
+    multiSelectAction: "forEach"
+}, {
     name: "removeline",
     bindKey: bindKey("Ctrl-D", "Command-D"),
-    exec: function(editor) { editor.removeLines(); }
+    exec: function(editor) { editor.removeLines(); },
+    multiSelectAction: "forEach"
 }, {
     name: "togglecomment",
     bindKey: bindKey("Ctrl-7", "Command-7"),
-    exec: function(editor) { editor.toggleCommentLines(); }
+    exec: function(editor) { editor.toggleCommentLines(); },
+    multiSelectAction: "forEach"
 }, {
     name: "replace",
     bindKey: bindKey("Ctrl-R", "Command-Option-F"),
@@ -5396,66 +5472,76 @@ exports.commands = [{
 }, {
     name: "del",
     bindKey: bindKey("Delete", "Delete|Ctrl-D"),
-    exec: function(editor) { editor.remove("right"); }
+    exec: function(editor) { editor.remove("right"); },
+    multiSelectAction: "forEach"
 }, {
     name: "backspace",
     bindKey: bindKey(
-        "Ctrl-Backspace|Command-Backspace|Option-Backspace|Shift-Backspace|Backspace",
+        "Command-Backspace|Option-Backspace|Shift-Backspace|Backspace",
         "Ctrl-Backspace|Command-Backspace|Shift-Backspace|Backspace|Ctrl-H"
     ),
-    exec: function(editor) { editor.remove("left"); }
+    exec: function(editor) { editor.remove("left"); },
+    multiSelectAction: "forEach"
 }, {
     name: "removetolinestart",
-    bindKey: bindKey("Alt-Backspace", "Option-Backspace"),
-    exec: function(editor) { editor.removeToLineStart(); }
+    bindKey: bindKey("Alt-Backspace", "Command-Backspace"),
+    exec: function(editor) { editor.removeToLineStart(); },
+    multiSelectAction: "forEach"
 }, {
     name: "removetolineend",
     bindKey: bindKey("Alt-Delete", "Ctrl-K"),
-    exec: function(editor) { editor.removeToLineEnd(); }
+    exec: function(editor) { editor.removeToLineEnd(); },
+    multiSelectAction: "forEach"
 }, {
     name: "removewordleft",
     bindKey: bindKey("Ctrl-Backspace", "Alt-Backspace|Ctrl-Alt-Backspace"),
-    exec: function(editor) { editor.removeWordLeft(); }
+    exec: function(editor) { editor.removeWordLeft(); },
+    multiSelectAction: "forEach"
 }, {
     name: "removewordright",
     bindKey: bindKey("Ctrl-Delete", "Alt-Delete"),
-    exec: function(editor) { editor.removeWordRight(); }
+    exec: function(editor) { editor.removeWordRight(); },
+    multiSelectAction: "forEach"
 }, {
     name: "outdent",
     bindKey: bindKey("Shift-Tab", "Shift-Tab"),
-    exec: function(editor) { editor.blockOutdent(); }
+    exec: function(editor) { editor.blockOutdent(); },
+    multiSelectAction: "forEach"
 }, {
     name: "indent",
     bindKey: bindKey("Tab", "Tab"),
-    exec: function(editor) { editor.indent(); }
+    exec: function(editor) { editor.indent(); },
+    multiSelectAction: "forEach"
 }, {
     name: "insertstring",
-    exec: function(editor, str) { editor.insert(str); }
+    exec: function(editor, str) { editor.insert(str); },
+    multiSelectAction: "forEach"
 }, {
     name: "inserttext",
     exec: function(editor, args) {
         editor.insert(lang.stringRepeat(args.text  || "", args.times || 1));
-    }
+    },
+    multiSelectAction: "forEach"
 }, {
     name: "splitline",
     bindKey: bindKey(null, "Ctrl-O"),
-    exec: function(editor) { editor.splitLine(); }
+    exec: function(editor) { editor.splitLine(); },
+    multiSelectAction: "forEach"
 }, {
     name: "transposeletters",
     bindKey: bindKey("Ctrl-T", "Ctrl-T"),
-    exec: function(editor) { editor.transposeLetters(); }
+    exec: function(editor) { editor.transposeLetters(); },
+    multiSelectAction: function(editor) {editor.transposeSelections(1); }
 }, {
     name: "touppercase",
     bindKey: bindKey("Ctrl-U", "Ctrl-U"),
-    exec: function(editor) { editor.toUpperCase(); }
+    exec: function(editor) { editor.toUpperCase(); },
+    multiSelectAction: "forEach"
 }, {
     name: "tolowercase",
     bindKey: bindKey("Ctrl-Shift-U", "Ctrl-Shift-U"),
-    exec: function(editor) { editor.toLowerCase(); }
-}, {
-    name: "jumptomatching",
-    bindKey: bindKey("Ctrl-Shift-P", "Ctrl-Shift-P"),
-    exec: function(editor) { editor.jumpToMatching(); }
+    exec: function(editor) { editor.toLowerCase(); },
+    multiSelectAction: "forEach"
 }];
 
 });
@@ -5499,11 +5585,13 @@ exports.commands = [{
  *
  * ***** END LICENSE BLOCK ***** */
 
-define('ace/edit_session', ['require', 'exports', 'module' , 'ace/lib/oop', 'ace/lib/lang', 'ace/lib/event_emitter', 'ace/selection', 'ace/mode/text', 'ace/range', 'ace/document', 'ace/background_tokenizer', 'ace/edit_session/folding', 'ace/edit_session/bracket_match'], function(require, exports, module) {
+define('ace/edit_session', ['require', 'exports', 'module' , 'ace/config', 'ace/lib/oop', 'ace/lib/lang', 'ace/lib/net', 'ace/lib/event_emitter', 'ace/selection', 'ace/mode/text', 'ace/range', 'ace/document', 'ace/background_tokenizer', 'ace/edit_session/folding', 'ace/edit_session/bracket_match'], function(require, exports, module) {
 "use strict";
 
+var config = require("./config");
 var oop = require("./lib/oop");
 var lang = require("./lib/lang");
+var net = require("./lib/net");
 var EventEmitter = require("./lib/event_emitter").EventEmitter;
 var Selection = require("./selection").Selection;
 var TextMode = require("./mode/text").Mode;
@@ -5945,10 +6033,65 @@ var EditSession = function(text, mode) {
         this._emit("tokenizerUpdate", e);
     };
 
+    this.$modes = {};
+    this._loadMode = function(mode, callback) {
+        if (this.$modes[mode])
+            return callback(this.$modes[mode]);
+        
+        var _self = this;
+        var module;
+        try {
+            module = require(mode);
+        } catch (e) {};
+        if (module)
+            return done(module);
+            
+        fetch(function() {
+            require([mode], done);
+        });
+        
+        function done(module) {
+            if (_self.$modes[mode])
+                return callback(_self.$modes[mode]);
+            
+            _self.$modes[mode] = new module.Mode();
+            _self._emit("loadmode", {
+                name: mode,
+                mode: _self.$modes[mode]
+            });
+            callback(_self.$modes[mode]);
+        }
+
+        function fetch(callback) {
+            if (!config.get("packaged"))
+                return callback();
+                
+            var base = mode.split("/").pop();
+            var filename = config.get("modePath") + "/mode-" + base + config.get("suffix");
+            net.loadScript(filename, callback);
+        }
+    };
+
     this.$mode = null;
+    this.$origMode = null;
     this.setMode = function(mode) {
+        this.$origMode = mode;
+        
+        // load on demand
+        if (typeof mode === "string") {
+            var _self = this;
+            this._loadMode(mode, function(module) {
+                if (_self.$origMode !== mode)
+                    return;
+            
+                _self.setMode(module);
+            });
+            return;
+        }
+        
         if (this.$mode === mode) return;
         this.$mode = mode;
+        
 
         this.$stopWorker();
 
@@ -6847,8 +6990,8 @@ var EditSession = function(text, mode) {
     }
 
     this.getScreenLastRowColumn = function(screenRow) {
-        //return this.screenToDocumentColumn(screenRow, Number.MAX_VALUE / 10)
-        return this.documentToScreenColumn(screenRow, this.doc.getLine(screenRow).length);
+        var pos = this.screenToDocumentPosition(screenRow, Number.MAX_VALUE)
+        return this.documentToScreenColumn(pos.row, pos.column);
     };
 
     this.getDocumentLastRowColumn = function(docRow, docColumn) {
@@ -6963,16 +7106,10 @@ var EditSession = function(text, mode) {
 
         docColumn += this.$getStringScreenWidth(line, screenColumn)[1];
 
-        // Need to do some clamping action here.
-        if (this.$useWrapMode) {
-            if (docColumn >= column) {
-                // We remove one character at the end such that the docColumn
-                // position returned is not associated to the next row on the
-                // screen.
-                docColumn = column - 1;
-            }
-        } else {
-            docColumn = Math.min(docColumn, line.length);
+        // We remove one character at the end so that the docColumn
+        // position returned is not associated to the next row on the screen.
+        if (this.$useWrapMode && docColumn >= column) {
+            docColumn = column - 1;
         }
 
         if (foldLine) {
@@ -7174,7 +7311,195 @@ require("./edit_session/bracket_match").BracketMatch.call(EditSession.prototype)
 
 exports.EditSession = EditSession;
 });
-/* ***** BEGIN LICENSE BLOCK *****
+/* vim:ts=4:sts=4:sw=4:
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Ajax.org Code Editor (ACE).
+ *
+ * The Initial Developer of the Original Code is
+ * Ajax.org B.V.
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *      Fabian Jakobs <fabian AT ajax DOT org>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+define('ace/config', ['require', 'exports', 'module' , 'ace/lib/lang'], function(require, exports, module) {
+"no use strict";
+
+var lang = require("./lib/lang");
+
+var global = (function() {
+    return this;
+})();
+
+var options = {
+    packaged: false,
+    workerPath: "",
+    modePath: "",
+    themePath: "",
+    suffix: ".js"
+};
+
+exports.get = function(key) {
+    if (!options.hasOwnProperty(key))
+        throw new Error("Unknown confik key: " + key);
+        
+    return options[key];
+};
+
+exports.set = function(key, value) {
+    if (!options.hasOwnProperty(key))
+        throw new Error("Unknown confik key: " + key);
+        
+    options[key] = value;
+};
+
+exports.all = function() {
+    return lang.copyObject(options);
+};
+
+exports.init = function() {
+    options.packaged = require.packaged || module.packaged || (global.define && define.packaged);
+
+    if (!global.document)
+        return "";
+
+    var scriptOptions = {};
+    var scriptUrl = "";
+    var suffix;
+    
+    var scripts = document.getElementsByTagName("script");
+    for (var i=0; i<scripts.length; i++) {
+        var script = scripts[i];
+
+        var src = script.src || script.getAttribute("src");
+        if (!src) {
+            continue;
+        }
+        
+        var attributes = script.attributes;
+        for (var j=0, l=attributes.length; j < l; j++) {
+            var attr = attributes[j];
+            if (attr.name.indexOf("data-ace-") === 0) {
+                scriptOptions[deHyphenate(attr.name.replace(/^data-ace-/, ""))] = attr.value;
+            }
+        }
+
+        var m = src.match(/^(?:(.*\/)ace\.js|(.*\/)ace((-uncompressed)?(-noconflict)?\.js))(?:\?|$)/);
+        if (m) {
+            scriptUrl = m[1] || m[2];
+            suffix = m[3];
+        }
+    }
+    
+    if (scriptUrl) {
+        scriptOptions.base = scriptOptions.base || scriptUrl;
+        scriptOptions.packaged = true;
+    }
+    
+    scriptOptions.suffix = scriptOptions.suffix || suffix;
+    scriptOptions.workerPath = scriptOptions.workerPath || scriptOptions.base;
+    scriptOptions.modePath = scriptOptions.modePath || scriptOptions.base;
+    scriptOptions.themePath = scriptOptions.themePath || scriptOptions.base;
+    delete scriptOptions.base;
+    
+    for (var key in scriptOptions)
+        if (typeof scriptOptions[key] !== "undefined")
+            exports.set(key, scriptOptions[key]);
+};
+
+function deHyphenate(str) {
+    return str.replace(/-(.)/g, function(m, m1) { return m1.toUpperCase(); });
+}
+
+});/**
+ * based on code from:
+ * 
+ * @license RequireJS text 0.25.0 Copyright (c) 2010-2011, The Dojo Foundation All Rights Reserved.
+ * Available via the MIT or new BSD license.
+ * see: http://github.com/jrburke/requirejs for details
+ */
+define('ace/lib/net', ['require', 'exports', 'module' ], function(require, exports, module) {
+"use strict";
+
+exports.get = function (url, callback) {
+    var xhr = exports.createXhr();
+    xhr.open('GET', url, true);
+    xhr.onreadystatechange = function (evt) {
+        //Do not explicitly handle errors, those should be
+        //visible via console output in the browser.
+        if (xhr.readyState === 4) {
+            callback(xhr.responseText);
+        }
+    };
+    xhr.send(null);
+};
+
+var progIds = ['Msxml2.XMLHTTP', 'Microsoft.XMLHTTP', 'Msxml2.XMLHTTP.4.0'];
+
+exports.createXhr = function() {
+    //Would love to dump the ActiveX crap in here. Need IE 6 to die first.
+    var xhr, i, progId;
+    if (typeof XMLHttpRequest !== "undefined") {
+        return new XMLHttpRequest();
+    } else {
+        for (i = 0; i < 3; i++) {
+            progId = progIds[i];
+            try {
+                xhr = new ActiveXObject(progId);
+            } catch (e) {}
+
+            if (xhr) {
+                progIds = [progId];  // so faster next time
+                break;
+            }
+        }
+    }
+
+    if (!xhr) {
+        throw new Error("createXhr(): XMLHttpRequest not available");
+    }
+
+    return xhr;
+};
+
+exports.loadScript = function(path, callback) {
+    var head = document.getElementsByTagName('head')[0];
+    var s = document.createElement('script');
+
+    s.src = path;
+    head.appendChild(s);
+    
+    s.onload = callback;
+};
+
+});/* ***** BEGIN LICENSE BLOCK *****
  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  *
  * The contents of this file are subject to the Mozilla Public License Version
@@ -7235,18 +7560,18 @@ var Selection = function(session) {
     this.selectionLead = this.doc.createAnchor(0, 0);
     this.selectionAnchor = this.doc.createAnchor(0, 0);
 
-    var _self = this;
+    var self = this;
     this.selectionLead.on("change", function(e) {
-        _self._emit("changeCursor");
-        if (!_self.$isEmpty)
-            _self._emit("changeSelection");
-        if (!_self.$preventUpdateDesiredColumnOnChange && e.old.column != e.value.column)
-            _self.$updateDesiredColumn();
+        self._emit("changeCursor");
+        if (!self.$isEmpty)
+            self._emit("changeSelection");
+        if (!self.$keepDesiredColumnOnChange && e.old.column != e.value.column)
+            self.$desiredColumn = null;
     });
 
     this.selectionAnchor.on("change", function() {
-        if (!_self.$isEmpty)
-            _self._emit("changeSelection");
+        if (!self.$isEmpty)
+            self._emit("changeSelection");
     });
 };
 
@@ -7356,12 +7681,7 @@ var Selection = function(session) {
             this.setSelectionAnchor(range.start.row, range.start.column);
             this.selectTo(range.end.row, range.end.column);
         }
-        this.$updateDesiredColumn();
-    };
-
-    this.$updateDesiredColumn = function() {
-        var cursor = this.getCursor();
-        this.$desiredColumn = this.session.documentToScreenColumn(cursor.row, cursor.column);
+        this.$desiredColumn = null;
     };
 
     this.$moveSelection = function(mover) {
@@ -7568,14 +7888,14 @@ var Selection = function(session) {
             this.moveCursorTo(fold.end.row, fold.end.column);
             return;
         }
-        
+
         // first skip space
         if (match = this.session.nonTokenRe.exec(rightOfCursor)) {
             column += this.session.nonTokenRe.lastIndex;
             this.session.nonTokenRe.lastIndex = 0;
             rightOfCursor = line.substring(column);
         }
-        
+
         // if at line end proceed with next line
         if (column >= line.length) {
             this.moveCursorTo(row, line.length);
@@ -7584,7 +7904,7 @@ var Selection = function(session) {
                 this.moveCursorWordRight();
             return;
         }
-        
+
         // advance to the end of the next token
         if (match = this.session.tokenRe.exec(rightOfCursor)) {
             column += this.session.tokenRe.lastIndex;
@@ -7609,19 +7929,19 @@ var Selection = function(session) {
         if (str == null) {
             str = this.doc.getLine(row).substring(0, column)
         }
-        
+
         var leftOfCursor = lang.stringReverse(str);
         var match;
         this.session.nonTokenRe.lastIndex = 0;
         this.session.tokenRe.lastIndex = 0;
-        
+
         // skip whitespace
         if (match = this.session.nonTokenRe.exec(leftOfCursor)) {
             column -= this.session.nonTokenRe.lastIndex;
             leftOfCursor = leftOfCursor.slice(this.session.nonTokenRe.lastIndex);
             this.session.nonTokenRe.lastIndex = 0;
         }
-        
+
         // if at begin of the line proceed in line above
         if (column <= 0) {
             this.moveCursorTo(row, 0);
@@ -7646,8 +7966,14 @@ var Selection = function(session) {
             this.selectionLead.column
         );
 
-        var screenCol = (chars === 0 && this.$desiredColumn) || screenPos.column;
-        var docPos = this.session.screenToDocumentPosition(screenPos.row + rows, screenCol);
+        if (chars === 0) {
+            if (this.$desiredColumn)
+                screenPos.column = this.$desiredColumn;
+            else
+                this.$desiredColumn = screenPos.column;
+        }
+
+        var docPos = this.session.screenToDocumentPosition(screenPos.row + rows, screenPos.column);
 
         // move the cursor and update the desired column
         this.moveCursorTo(docPos.row, docPos.column + chars, chars === 0);
@@ -7657,7 +7983,7 @@ var Selection = function(session) {
         this.moveCursorTo(position.row, position.column);
     };
 
-    this.moveCursorTo = function(row, column, preventUpdateDesiredColumn) {
+    this.moveCursorTo = function(row, column, keepDesiredColumn) {
         // Ensure the row/column is not inside of a fold.
         var fold = this.session.getFoldAt(row, column, 1);
         if (fold) {
@@ -7665,21 +7991,47 @@ var Selection = function(session) {
             column = fold.start.column;
         }
 
-        this.$preventUpdateDesiredColumnOnChange = true;
+        this.$keepDesiredColumnOnChange = true;
         this.selectionLead.setPosition(row, column);
-        this.$preventUpdateDesiredColumnOnChange = false;
+        this.$keepDesiredColumnOnChange = false;
 
-        if (!preventUpdateDesiredColumn)
-            this.$updateDesiredColumn(this.selectionLead.column);
+        if (!keepDesiredColumn)
+            this.$desiredColumn = null;
     };
 
-    this.moveCursorToScreen = function(row, column, preventUpdateDesiredColumn) {
+    this.moveCursorToScreen = function(row, column, keepDesiredColumn) {
         var pos = this.session.screenToDocumentPosition(row, column);
-        row = pos.row;
-        column = pos.column;
-        this.moveCursorTo(row, column, preventUpdateDesiredColumn);
+        this.moveCursorTo(pos.row, pos.column, keepDesiredColumn);
     };
 
+    // remove listeners from document
+    this.detach = function() {
+        this.selectionLead.detach();
+        this.selectionAnchor.detach();
+        this.session = this.doc = null;
+    }
+
+    this.fromOrientedRange = function(range) {
+        this.setSelectionRange(range, range.cursor == range.start);
+        this.$desiredColumn = range.desiredColumn || this.$desiredColumn;
+    }
+
+    this.toOrientedRange = function(range) {
+        var r = this.getRange();
+        if (range) {
+            range.start.column = r.start.column;
+            range.start.row = r.start.row;
+            range.end.column = r.end.column;
+            range.end.row = r.end.row;
+        } else {
+            range = r;
+        }
+
+        range.cursor = this.isBackwards() ? range.start : range.end;
+        range.desiredColumn = this.$desiredColumn;
+        return range;
+    }
+
 }).call(Selection.prototype);
 
 exports.Selection = Selection;
@@ -7737,7 +8089,7 @@ var Range = function(startRow, startColumn, endRow, endColumn) {
 };
 
 (function() {
-    this.isEequal = function(range) {
+    this.isEqual = function(range) {
         return this.start.row == range.start.row &&
             this.end.row == range.end.row &&
             this.start.column == range.start.column &&
@@ -7803,6 +8155,11 @@ var Range = function(startRow, startColumn, endRow, endColumn) {
         return this.comparePoint(range.start) == 0 && this.comparePoint(range.end) == 0;
     }
 
+    this.intersectsRange = function(range) {
+        var cmp = this.compareRange(range);
+        return (cmp == -1 || cmp == 0 || cmp == 1);
+    }
+
     this.isEnd = function(row, column) {
         return this.end.row == row && this.end.column == column;
     }
@@ -7962,6 +8319,21 @@ var Range = function(startRow, startColumn, endRow, endColumn) {
         return Range.fromPoints(start || this.start, end || this.end);
     };
 
+    this.fixOrientation = function() {
+        if (
+            this.start.row < this.end.row 
+            || (this.start.row == this.end.row && this.start.column < this.end.column)
+        ) {
+            return false;
+        }
+        
+        var temp = this.start;
+        this.end = this.start;
+        this.start = temp;
+        return true;
+    };
+
+
     this.isEmpty = function() {
         return (this.start.row == this.end.row && this.start.column == this.end.column);
     };
@@ -8275,23 +8647,30 @@ var Tokenizer = function(rules, flag) {
         var ruleRegExps = [];
         var matchTotal = 0;
         var mapping = this.matchMappings[key] = {};
-        
+
         for ( var i = 0; i < state.length; i++) {
+
+            if (state[i].regex instanceof RegExp)
+                state[i].regex = state[i].regex.toString().slice(1, -1);
+
             // Count number of matching groups. 2 extra groups from the full match
             // And the catch-all on the end (used to force a match);
             var matchcount = new RegExp("(?:(" + state[i].regex + ")|(.))").exec("a").length - 2;
-        
+
             // Replace any backreferences and offset appropriately.
             var adjustedregex = state[i].regex.replace(/\\([0-9]+)/g, function (match, digit) {
                 return "\\" + (parseInt(digit, 10) + matchTotal + 1);
             });
-            
+
+            if (matchcount > 1 && state[i].token.length !== matchcount-1)
+                throw new Error("Matching groups and length of the token array don't match in rule #" + i + " of state " + key);
+
             mapping[matchTotal] = {
                 rule: i,
                 len: matchcount
             };
             matchTotal += matchcount;
-            
+
             ruleRegExps.push(adjustedregex);
         }
 
@@ -8307,47 +8686,47 @@ var Tokenizer = function(rules, flag) {
         var mapping = this.matchMappings[currentState];
         var re = this.regExps[currentState];
         re.lastIndex = 0;
-        
+
         var match, tokens = [];
-        
+
         var lastIndex = 0;
-        
+
         var token = {
             type: null,
             value: ""
         };
-        
+
         while (match = re.exec(line)) {
             var type = "text";
             var rule = null;
             var value = [match[0]];
 
             for (var i = 0; i < match.length-2; i++) {
-                if (match[i + 1] !== undefined) {
-                    rule = state[mapping[i].rule];
-                    
-                    if (mapping[i].len > 1) {
-                        value = match.slice(i+2, i+1+mapping[i].len);
-                    }
-                    
-                    // compute token type
-                    if (typeof rule.token == "function")
-                        type = rule.token.apply(this, value);
-                    else
-                        type = rule.token;
+                if (match[i + 1] === undefined)
+                    continue;
 
-                    var next = rule.next;                    
-                    if (next && next !== currentState) {
-                        currentState = next;
-                        state = this.rules[currentState];
-                        mapping = this.matchMappings[currentState];
-                        lastIndex = re.lastIndex;
+                rule = state[mapping[i].rule];
 
-                        re = this.regExps[currentState];
-                        re.lastIndex = lastIndex;
-                    }
-                    break;
+                if (mapping[i].len > 1)
+                    value = match.slice(i+2, i+1+mapping[i].len);
+
+                // compute token type
+                if (typeof rule.token == "function")
+                    type = rule.token.apply(this, value);
+                else
+                    type = rule.token;
+
+                var next = rule.next;
+                if (next && next !== currentState) {
+                    currentState = next;
+                    state = this.rules[currentState];
+                    mapping = this.matchMappings[currentState];
+                    lastIndex = re.lastIndex;
+
+                    re = this.regExps[currentState];
+                    re.lastIndex = lastIndex;
                 }
+                break;
             }
 
             if (value[0]) {
@@ -8356,13 +8735,15 @@ var Tokenizer = function(rules, flag) {
                     type = [type];
                 }
                 for (var i = 0; i < value.length; i++) {
+                    if (!value[i])
+                        continue;
+
                     if ((!rule || rule.merge || type[i] === "text") && token.type === type[i]) {
                         token.value += value[i];
                     } else {
-                        if (token.type) {
+                        if (token.type)
                             tokens.push(token);
-                        }
-                    
+
                         token = {
                             type: type[i],
                             value: value[i]
@@ -8370,10 +8751,10 @@ var Tokenizer = function(rules, flag) {
                     }
                 }
             }
-            
+
             if (lastIndex == line.length)
                 break;
-            
+
             lastIndex = re.lastIndex;
         }
 
@@ -8879,11 +9260,12 @@ var Document = function(text) {
     };
 
     this.insert = function(position, text) {
-        if (text.length == 0)
+        if (!text || text.length === 0)
             return position;
 
         position = this.$clipPosition(position);
 
+        // only detect new lines if the document has no line break yet
         if (this.getLength() <= 1)
             this.$detectNewLine(text);
 
@@ -10106,7 +10488,7 @@ function Folding() {
 
     this.foldAll = function(startRow, endRow) {
         var foldWidgets = this.foldWidgets;
-        endRow = endRow || foldWidgets.length;
+        endRow = endRow || this.getLength();
         for (var row = startRow || 0; row < endRow; row++) {
             if (foldWidgets[row] == null)
                 foldWidgets[row] = this.getFoldWidget(row);
@@ -10195,7 +10577,7 @@ function Folding() {
             // sometimes singleline folds can be missed by the code above
             if (!range.isMultiLine()) {
                 fold = this.getFoldAt(range.start.row, range.start.column, 1);
-                if (fold && range.isEequal(fold.range)) {
+                if (fold && range.isEqual(fold.range)) {
                     this.removeFold(fold);
                     return;
                 }
@@ -10586,7 +10968,7 @@ var Fold = exports.Fold = function(range, placeholder) {
     };
 
     this.addSubFold = function(fold) {
-        if (this.range.isEequal(fold))
+        if (this.range.isEqual(fold))
             return this;
 
         if (!this.range.containsRange(fold))
@@ -11264,21 +11646,153 @@ Search.SELECTION = 2;
 
 exports.Search = Search;
 });
-define('ace/commands/command_manager', ['require', 'exports', 'module' , 'ace/lib/keys'], function(require, exports, module) {
+define('ace/commands/command_manager', ['require', 'exports', 'module' , 'ace/lib/oop', 'ace/keyboard/hash_handler', 'ace/lib/event_emitter'], function(require, exports, module) {
 "use strict";
 
-var keyUtil = require("../lib/keys");
+var oop = require("../lib/oop");
+var HashHandler = require("../keyboard/hash_handler").HashHandler;
+var EventEmitter = require("../lib/event_emitter").EventEmitter;
 
 var CommandManager = function(platform, commands) {
-    if (typeof platform !== "string")
-        throw new TypeError("'platform' argument must be either 'mac' or 'win'");
+    this.platform = platform;
+    this.commands = {};
+    this.commmandKeyBinding = {};
+
+    this.addCommands(commands);
+    
+    this.setDefaultHandler("exec", function(e) {
+        e.command.exec(e.editor, e.args || {});
+    });
+};
+
+oop.inherits(CommandManager, HashHandler);
+
+(function() {
+
+    oop.implement(this, EventEmitter);
+
+    this.exec = function(command, editor, args) {
+        if (typeof command === 'string')
+            command = this.commands[command];
+
+        if (!command)
+            return false;
+
+        if (editor && editor.$readOnly && !command.readOnly)
+            return false;
+
+        this._emit("exec", {editor: editor, command: command, args: args});
+        return true;
+    };
+
+    this.toggleRecording = function() {
+        if (this.$inReplay)
+            return;
+        if (this.recording) {
+            this.macro.pop();
+            this.removeEventListener("exec", this.$addCommandToMacro);
+
+            if (!this.macro.length)
+                this.macro = this.oldMacro;
+
+            return this.recording = false;
+        }
+        if (!this.$addCommandToMacro) {
+            this.$addCommandToMacro = function(e) {
+                    this.macro.push([e.command, e.args]);
+                }.bind(this);
+        }
+
+        this.oldMacro = this.macro;
+        this.macro = [];
+        this.on("exec", this.$addCommandToMacro);
+        return this.recording = true;
+    };
+
+    this.replay = function(editor) {
+        if (this.$inReplay || !this.macro)
+            return;
+
+        if (this.recording)
+            return this.toggleRecording();
+
+        try {
+            this.$inReplay = true;
+            this.macro.forEach(function(x) {
+                if (typeof x == "string")
+                    this.exec(x, editor);
+                else
+                    this.exec(x[0], editor, x[1]);
+            }, this);
+        } finally {
+            this.$inReplay = false;
+        }
+    };
+
+    this.trimMacro = function(m) {
+        return m.map(function(x){
+            if (typeof x[0] != "string")
+                x[0] = x[0].name;
+            if (!x[1])
+                x = x[0];
+            return x;
+        });
+    };
+
+}).call(CommandManager.prototype);
+
+exports.CommandManager = CommandManager;
+
+});
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Skywriter.
+ *
+ * The Initial Developer of the Original Code is
+ * Mozilla.
+ * Portions created by the Initial Developer are Copyright (C) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Fabian Jakobs <fabian AT ajax DOT org>
+ *   Julian Viereck (julian.viereck@gmail.com)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+define('ace/keyboard/hash_handler', ['require', 'exports', 'module' , 'ace/lib/keys'], function(require, exports, module) {
+"use strict";
+
+var keyUtil  = require("../lib/keys");
 
+function HashHandler(config, platform) {
     this.platform = platform;
     this.commands = {};
     this.commmandKeyBinding = {};
 
-    if (commands)
-        commands.forEach(this.addCommand, this);
+    this.addCommands(config);
 };
 
 (function() {
@@ -11299,7 +11813,7 @@ var CommandManager = function(platform, commands) {
         command = this.commands[name];
         delete this.commands[name];
 
-        // exaustive search is brute force but since removeCommand is
+        // exhaustive search is brute force but since removeCommand is
         // not a performance critical operation this should be OK
         var ckb = this.commmandKeyBinding;
         for (var hashId in ckb) {
@@ -11311,7 +11825,7 @@ var CommandManager = function(platform, commands) {
     };
 
     this.addCommands = function(commands) {
-        Object.keys(commands).forEach(function(name) {
+        commands && Object.keys(commands).forEach(function(name) {
             var command = commands[name];
             if (typeof command === "string")
                 return this.bindKey(command, name);
@@ -11357,14 +11871,14 @@ var CommandManager = function(platform, commands) {
 
         var key = typeof binding == "string" ? binding: binding[this.platform];
         this.bindKey(key, command);
-    }
+    };
 
     function parseKeys(keys, val, ret) {
         var key;
         var hashId = 0;
-        var parts = splitSafe(keys);
+        var parts = splitSafe(keys.toLowerCase());
 
-        for (var i=0, l = parts.length; i < l; i++) {
+        for (var i = 0, l = parts.length; i < l; i++) {
             if (keyUtil.KEY_MODS[parts[i]])
                 hashId = hashId | keyUtil.KEY_MODS[parts[i]];
             else
@@ -11374,95 +11888,28 @@ var CommandManager = function(platform, commands) {
         return {
             key: key,
             hashId: hashId
-        }
+        };
     }
 
-    function splitSafe(s, separator) {
-        return (s.toLowerCase()
-            .trim()
+    function splitSafe(s) {
+        return (s.trim()
             .split(new RegExp("[\\s ]*\\-[\\s ]*", "g"), 999));
     }
 
-    this.findKeyCommand = function findKeyCommand(hashId, textOrKey) {
-        // Convert keyCode to the string representation.
-        if (typeof textOrKey == "number") {
-            textOrKey = keyUtil.keyCodeToString(textOrKey);
-        }
-
+    this.findKeyCommand = function findKeyCommand(hashId, keyString) {
         var ckbr = this.commmandKeyBinding;
-        return ckbr[hashId] && ckbr[hashId][textOrKey.toLowerCase()];
+        return ckbr[hashId] && ckbr[hashId][keyString.toLowerCase()];
     }
 
-    this.exec = function(command, editor, args) {
-        if (typeof command === 'string')
-            command = this.commands[command];
-
-        if (!command)
-            return false;
-
-        if (editor && editor.$readOnly && !command.readOnly)
-            return false;
-
-        command.exec(editor, args || {});
-        return true;
-    };
-
-    this.toggleRecording = function() {
-        if (this.$inReplay)
-            return;
-        if (this.recording) {
-            this.macro.pop();
-            this.exec = this.normal_exec;
-
-            if (!this.macro.length)
-                this.macro = this.oldMacro;
-
-            return this.recording = false;
-        }
-        this.oldMacro = this.macro;
-        this.macro = [];
-        this.normal_exec = this.exec;
-        this.exec = function(command, editor, args) {
-            this.macro.push([command, args]);
-            return this.normal_exec(command, editor, args);
+    this.handleKeyboard = function(data, hashId, keyString, keyCode) {
+        return {
+            command: this.findKeyCommand(hashId, keyString)
         };
-        return this.recording = true;
     };
 
-    this.replay = function(editor) {
-        if (this.$inReplay || !this.macro)
-            return;
-
-        if (this.recording)
-            return this.toggleRecording();
-
-        try {
-            this.$inReplay = true;
-            this.macro.forEach(function(x) {
-                if (typeof x == "string")
-                    this.exec(x, editor);
-                else
-                    this.exec(x[0], editor, x[1]);
-            }, this)
-        } finally {
-            this.$inReplay = false;
-        }
-    };
-
-    this.trimMacro = function(m) {
-        return m.map(function(x){
-            if (typeof x[0] != "string")
-                x[0] = x[0].name;
-            if (!x[1])
-                x = x[0];
-            return x
-        })
-    }
-
-}).call(CommandManager.prototype);
-
-exports.CommandManager = CommandManager;
+}).call(HashHandler.prototype)
 
+exports.HashHandler = HashHandler;
 });
 /* vim:ts=4:sts=4:sw=4:
  * ***** BEGIN LICENSE BLOCK *****
@@ -11598,13 +12045,15 @@ exports.UndoManager = UndoManager;
  *
  * ***** END LICENSE BLOCK ***** */
 
-define('ace/virtual_renderer', ['require', 'exports', 'module' , 'ace/lib/oop', 'ace/lib/dom', 'ace/lib/event', 'ace/lib/useragent', 'ace/layer/gutter', 'ace/layer/marker', 'ace/layer/text', 'ace/layer/cursor', 'ace/scrollbar', 'ace/renderloop', 'ace/lib/event_emitter', 'text!ace/css/editor.css'], function(require, exports, module) {
+define('ace/virtual_renderer', ['require', 'exports', 'module' , 'ace/lib/oop', 'ace/lib/dom', 'ace/lib/event', 'ace/lib/useragent', 'ace/config', 'ace/lib/net', 'ace/layer/gutter', 'ace/layer/marker', 'ace/layer/text', 'ace/layer/cursor', 'ace/scrollbar', 'ace/renderloop', 'ace/lib/event_emitter', 'text!ace/css/editor.css'], function(require, exports, module) {
 "use strict";
 
 var oop = require("./lib/oop");
 var dom = require("./lib/dom");
 var event = require("./lib/event");
 var useragent = require("./lib/useragent");
+var config = require("./config");
+var net = require("./lib/net");
 var GutterLayer = require("./layer/gutter").Gutter;
 var MarkerLayer = require("./layer/marker").Marker;
 var TextLayer = require("./layer/text").Text;
@@ -11618,13 +12067,13 @@ dom.importCssString(editorCss, "ace_editor");
 
 var VirtualRenderer = function(container, theme) {
     var _self = this;
-    
+
     this.container = container;
 
     // TODO: this breaks rendering in Cloud9 with multiple ace instances
 //    // Imports CSS once per DOM document ('ace_editor' serves as an identifier).
 //    dom.importCssString(editorCss, "ace_editor", container.ownerDocument);
-    
+
     dom.addCssClass(container, "ace_editor");
 
     this.setTheme(theme);
@@ -11642,8 +12091,8 @@ var VirtualRenderer = function(container, theme) {
     this.scroller.appendChild(this.content);
 
     this.$gutterLayer = new GutterLayer(this.$gutter);
-    this.$gutterLayer.on("changeGutterWidth", this.onResize.bind(this, true));    
-    
+    this.$gutterLayer.on("changeGutterWidth", this.onResize.bind(this, true));
+
     this.$markerBack = new MarkerLayer(this.content);
 
     var textLayer = this.$textLayer = new TextLayer(this.content);
@@ -11661,6 +12110,8 @@ var VirtualRenderer = function(container, theme) {
     this.$horizScroll = true;
     this.$horizScrollAlwaysVisible = true;
 
+    this.$animatedScroll = false;
+
     this.scrollBar = new ScrollBar(container);
     this.scrollBar.addEventListener("scroll", function(e) {
         _self.session.setScrollTop(e.data);
@@ -11668,9 +12119,18 @@ var VirtualRenderer = function(container, theme) {
 
     this.scrollTop = 0;
     this.scrollLeft = 0;
-    
+
     event.addListener(this.scroller, "scroll", function() {
-        _self.session.setScrollLeft(_self.scroller.scrollLeft);
+        var scrollLeft = _self.scroller.scrollLeft;
+        _self.scrollLeft = scrollLeft;
+        _self.session.setScrollLeft(scrollLeft);
+
+        if (scrollLeft == 0) {
+            _self.$gutter.className = "ace_gutter";
+        }
+        else {
+            _self.$gutter.className = "ace_gutter horscroll";
+        }
     });
 
     this.cursorPos = {
@@ -11678,7 +12138,7 @@ var VirtualRenderer = function(container, theme) {
         column : 0
     };
 
-    this.$textLayer.addEventListener("changeCharaterSize", function() {
+    this.$textLayer.addEventListener("changeCharacterSize", function() {
         _self.characterWidth = textLayer.getCharacterWidth();
         _self.lineHeight = textLayer.getLineHeight();
         _self.$updatePrintMargin();
@@ -11731,6 +12191,7 @@ var VirtualRenderer = function(container, theme) {
     this.CHANGE_MARKER_BACK = 128;
     this.CHANGE_MARKER_FRONT = 256;
     this.CHANGE_FULL = 512;
+    this.CHANGE_H_SCROLL = 1024;
 
     oop.implement(this, EventEmitter);
 
@@ -11829,6 +12290,14 @@ var VirtualRenderer = function(container, theme) {
         return this.session.adjustWrapLimit(limit);
     };
 
+    this.setAnimatedScroll = function(shouldAnimate){
+        this.$animatedScroll = shouldAnimate;
+    };
+
+    this.getAnimatedScroll = function() {
+        return this.$animatedScroll;
+    };
+
     this.setShowInvisibles = function(showInvisibles) {
         if (this.$textLayer.setShowInvisibles(showInvisibles))
             this.$loop.schedule(this.CHANGE_TEXT);
@@ -11907,7 +12376,7 @@ var VirtualRenderer = function(container, theme) {
         // this persists in IE9
         if (useragent.isIE)
             return;
-        
+
         if (this.layerConfig.lastRow === 0)
             return;
 
@@ -11968,7 +12437,7 @@ var VirtualRenderer = function(container, theme) {
     };
 
     this.$renderChanges = function(changes) {
-        if (!changes || !this.session)
+        if (!changes || !this.session || !this.container.offsetWidth)
             return;
 
         // text, scrolling and resize changes can cause the view port size to change
@@ -11980,20 +12449,33 @@ var VirtualRenderer = function(container, theme) {
         )
             this.$computeLayerConfig();
 
+        // horizontal scrolling
+        if (changes & this.CHANGE_H_SCROLL) {
+            this.scroller.scrollLeft = this.scrollLeft;
+
+            // read the value after writing it since the value might get clipped
+            var scrollLeft = this.scroller.scrollLeft;
+            this.scrollLeft = scrollLeft;
+            this.session.setScrollLeft(scrollLeft);
+        }
+
         // full
         if (changes & this.CHANGE_FULL) {
+            this.$textLayer.checkForSizeChanges();
+            // update scrollbar first to not lose scroll position when gutter calls resize
+            this.$updateScrollBar();
             this.$textLayer.update(this.layerConfig);
             if (this.showGutter)
                 this.$gutterLayer.update(this.layerConfig);
             this.$markerBack.update(this.layerConfig);
             this.$markerFront.update(this.layerConfig);
             this.$cursorLayer.update(this.layerConfig);
-            this.$updateScrollBar();
             return;
         }
 
         // scrolling
         if (changes & this.CHANGE_SCROLL) {
+            this.$updateScrollBar();
             if (changes & this.CHANGE_TEXT || changes & this.CHANGE_LINES)
                 this.$textLayer.update(this.layerConfig);
             else
@@ -12004,7 +12486,6 @@ var VirtualRenderer = function(container, theme) {
             this.$markerBack.update(this.layerConfig);
             this.$markerFront.update(this.layerConfig);
             this.$cursorLayer.update(this.layerConfig);
-            this.$updateScrollBar();
             return;
         }
 
@@ -12014,10 +12495,11 @@ var VirtualRenderer = function(container, theme) {
                 this.$gutterLayer.update(this.layerConfig);
         }
         else if (changes & this.CHANGE_LINES) {
-            this.$updateLines();
-            this.$updateScrollBar();
-            if (this.showGutter)
-                this.$gutterLayer.update(this.layerConfig);
+            if (this.$updateLines()) {
+                this.$updateScrollBar();
+                if (this.showGutter)
+                    this.$gutterLayer.update(this.layerConfig);
+            }
         } else if (changes & this.CHANGE_GUTTER) {
             if (this.showGutter)
                 this.$gutterLayer.update(this.layerConfig);
@@ -12049,9 +12531,13 @@ var VirtualRenderer = function(container, theme) {
         var horizScroll = this.$horizScrollAlwaysVisible || this.$size.scrollerWidth - longestLine < 0;
         var horizScrollChanged = this.$horizScroll !== horizScroll;
         this.$horizScroll = horizScroll;
-        if (horizScrollChanged)
+        if (horizScrollChanged) {
             this.scroller.style.overflowX = horizScroll ? "scroll" : "hidden";
-
+            // when we hide scrollbar scroll event isn't emited
+            // leaving session with wrong scrollLeft value
+            if (!horizScroll)
+                this.session.setScrollLeft(0);
+        }
         var maxHeight = this.session.getScreenLength() * this.lineHeight;
         this.session.setScrollTop(Math.max(0, Math.min(this.scrollTop, maxHeight - this.$size.scrollerHeight)));
 
@@ -12102,12 +12588,6 @@ var VirtualRenderer = function(container, theme) {
         this.content.style.width = longestLine + 2 * this.$padding + "px";
         this.content.style.height = minHeight + "px";
 
-        // scroller.scrollWidth was smaller than scrollLeft we needed
-        if (this.$desiredScrollLeft) {
-            this.scrollToX(this.$desiredScrollLeft);
-            this.$desiredScrollLeft = 0;
-        }
-
         // Horizontal scrollbar visibility may have changed, which changes
         // the client height of the scroller
         if (horizScrollChanged)
@@ -12138,6 +12618,7 @@ var VirtualRenderer = function(container, theme) {
 
         // else update only the changed rows
         this.$textLayer.updateLines(layerConfig, firstRow, lastRow);
+        return true;
     };
 
     this.$getLongestLine = function() {
@@ -12190,12 +12671,18 @@ var VirtualRenderer = function(container, theme) {
         this.$cursorLayer.showCursor();
     };
 
-    this.scrollCursorIntoView = function() {
+    this.scrollSelectionIntoView = function(anchor, lead) {
+        // first scroll anchor into view then scroll lead into view
+        this.scrollCursorIntoView(anchor);
+        this.scrollCursorIntoView(lead);
+    };
+
+    this.scrollCursorIntoView = function(cursor) {
         // the editor is not visible
         if (this.$size.scrollerHeight === 0)
             return;
 
-        var pos = this.$cursorLayer.getPixelPosition();
+        var pos = this.$cursorLayer.getPixelPosition(cursor);
 
         var left = pos.left;
         var top = pos.top;
@@ -12213,14 +12700,11 @@ var VirtualRenderer = function(container, theme) {
         if (scrollLeft > left) {
             if (left < this.$padding + 2 * this.layerConfig.characterWidth)
                 left = 0;
-            this.scrollToX(left);
+            this.session.setScrollLeft(left);
         }
 
         if (scrollLeft + this.$size.scrollerWidth < left + this.characterWidth) {
-            if (left > this.layerConfig.width + 2 * this.$padding)
-                this.$desiredScrollLeft = left;
-            else
-                this.scrollToX(Math.round(left + this.characterWidth - this.$size.scrollerWidth));
+            this.session.setScrollLeft(Math.round(left + this.characterWidth - this.$size.scrollerWidth));
         }
     };
 
@@ -12229,7 +12713,7 @@ var VirtualRenderer = function(container, theme) {
     };
 
     this.getScrollLeft = function() {
-        return this.session.getScrollTop();
+        return this.session.getScrollLeft();
     };
 
     this.getScrollTopRow = function() {
@@ -12244,17 +12728,46 @@ var VirtualRenderer = function(container, theme) {
         this.session.setScrollTop(row * this.lineHeight);
     };
 
-    this.scrollToLine = function(line, center) {
-        var lineHeight = { lineHeight: this.lineHeight };
-        var offset = 0;
-        for (var l = 1; l < line; l++) {
-            offset += this.session.getRowHeight(lineHeight, l-1);
-        }
+    this.STEPS = 10;
+    this.$calcSteps = function(fromValue, toValue){
+        var i = 0;
+        var l = this.STEPS;
+        var steps = [];
+
+        var func  = function(t, x_min, dx) {
+            if ((t /= .5) < 1)
+                return dx / 2 * Math.pow(t, 3) + x_min;
+            return dx / 2 * (Math.pow(t - 2, 3) + 2) + x_min;
+        };
+
+        for (i = 0; i < l; ++i)
+            steps.push(func(i / this.STEPS, fromValue, toValue - fromValue));
+        steps.push(toValue);
+
+        return steps;
+    };
 
-        if (center) {
+    this.scrollToLine = function(line, center) {
+        var pos = this.$cursorLayer.getPixelPosition({row: line, column: 0});
+        var offset = pos.top;
+        if (center)
             offset -= this.$size.scrollerHeight / 2;
+
+        if (this.$animatedScroll && Math.abs(offset - this.scrollTop) < 10000) {
+            var _self = this;
+            var steps = _self.$calcSteps(this.scrollTop, offset);
+
+            clearInterval(this.$timer);
+            this.$timer = setInterval(function() {
+                _self.session.setScrollTop(steps.shift());
+                
+                if (!steps.length)
+                    clearInterval(_self.$timer);
+            }, 10);
+        }
+        else {
+            this.session.setScrollTop(offset);
         }
-        this.session.setScrollTop(offset);
     };
 
     this.scrollToY = function(scrollTop) {
@@ -12270,8 +12783,9 @@ var VirtualRenderer = function(container, theme) {
         if (scrollLeft <= this.$padding)
             scrollLeft = 0;
 
-        this.scroller.scrollLeft = scrollLeft;
-        scrollLeft = this.scroller.scrollLeft;
+        if (this.scrollLeft !== scrollLeft)
+            this.scrollLeft = scrollLeft;
+        this.$loop.schedule(this.CHANGE_H_SCROLL);
     };
 
     this.scrollBy = function(deltaX, deltaY) {
@@ -12287,16 +12801,27 @@ var VirtualRenderer = function(container, theme) {
         // todo: handle horizontal scrolling
     };
 
+    this.pixelToScreenCoordinates = function(pageX, pageY) {
+        var canvasPos = this.scroller.getBoundingClientRect();
+
+        var col = Math.round(
+            (pageX + this.scrollLeft - canvasPos.left - this.$padding - dom.getPageScrollLeft()) / this.characterWidth
+        );
+        var row = Math.floor(
+            (pageY + this.scrollTop - canvasPos.top - dom.getPageScrollTop()) / this.lineHeight
+        );
+
+        return {row: row, column: col};
+    };
+
     this.screenToTextCoordinates = function(pageX, pageY) {
         var canvasPos = this.scroller.getBoundingClientRect();
 
         var col = Math.round(
-            (pageX + this.scrollLeft - canvasPos.left - this.$padding - dom.getPageScrollLeft())
-            / this.characterWidth
+            (pageX + this.scrollLeft - canvasPos.left - this.$padding - dom.getPageScrollLeft()) / this.characterWidth
         );
         var row = Math.floor(
-            (pageY + this.scrollTop - canvasPos.top - dom.getPageScrollTop())
-            / this.lineHeight
+            (pageY + this.scrollTop - canvasPos.top - dom.getPageScrollTop()) / this.lineHeight
         );
 
         return this.session.screenToDocumentPosition(row, Math.max(col, 0));
@@ -12356,14 +12881,36 @@ var VirtualRenderer = function(container, theme) {
         style.left = "-10000px";
     };
 
+    this._loadTheme = function(name, callback) {
+        if (!config.get("packaged"))
+            return callback();
+
+        var base = name.split("/").pop();
+        var filename = config.get("themePath") + "/theme-" + base + config.get("suffix");
+        net.loadScript(filename, callback);
+    };
+
     this.setTheme = function(theme) {
         var _self = this;
 
         this.$themeValue = theme;
         if (!theme || typeof theme == "string") {
-            theme = theme || "ace/theme/textmate";
-            require([theme], function(theme) {
-                afterLoad(theme);
+            var moduleName = theme || "ace/theme/textmate";
+
+            var module;
+            try {
+                module = require(moduleName);
+            } catch (e) {};
+            if (module)
+                return afterLoad(module);
+
+            _self._loadTheme(moduleName, function() {
+                require([moduleName], function(module) {
+                    if (_self.$themeValue !== theme)
+                        return;
+
+                    afterLoad(module);
+                });
             });
         } else {
             afterLoad(theme);
@@ -12492,11 +13039,11 @@ var Gutter = function(parentEl) {
     this.addGutterDecoration = function(row, className){
         if (!this.$decorations[row])
             this.$decorations[row] = "";
-        this.$decorations[row] += " ace_" + className;
+        this.$decorations[row] += " " + className;
     };
 
     this.removeGutterDecoration = function(row, className){
-        this.$decorations[row] = this.$decorations[row].replace(" ace_" + className, "");
+        this.$decorations[row] = this.$decorations[row].replace(" " + className, "");
     };
 
     this.setBreakpoints = function(rows) {
@@ -12723,7 +13270,7 @@ var Marker = function(parentEl) {
     };
 
     /**
-     * Draws a marker, which spans a range of text in a single line
+     * Draws a marker, which spans a range of text on multiple lines
      */ 
     this.drawTextMarker = function(stringBuilder, range, clazz, layerConfig) {
         // selection start
@@ -12798,7 +13345,7 @@ var Marker = function(parentEl) {
     };
 
     /**
-     * Draws a marker which covers one single full line
+     * Draws a marker which covers part or whole width of a single screen line
      */
     this.drawSingleLineMarker = function(stringBuilder, range, clazz, layerConfig, extraLength, type) {
         var padding = type === "background" ? 0 : this.$padding;
@@ -12914,7 +13461,7 @@ var Text = function(parentEl) {
         var size = this.$measureSizes();
         if (size && (this.$characterSize.width !== size.width || this.$characterSize.height !== size.height)) {
             this.$characterSize = size;
-            this._emit("changeCharaterSize", {data: size});
+            this._emit("changeCharacterSize", {data: size});
         }
     };
 
@@ -12933,7 +13480,7 @@ var Text = function(parentEl) {
         lineHeight : 1
     };
 
-    this.$measureSizes = function() {
+    this.$measureSizes = useragent.isIE || useragent.isOldGecko ? function() {
         var n = 1000;
         if (!this.$measureNode) {
             var measureNode = this.$measureNode = dom.createElement("div");
@@ -12943,7 +13490,7 @@ var Text = function(parentEl) {
             style.left = style.top = (-n * 40)  + "px";
 
             style.visibility = "hidden";
-            style.position = "absolute";
+            style.position = "fixed";
             style.overflow = "visible";
             style.whiteSpace = "nowrap";
 
@@ -12960,8 +13507,12 @@ var Text = function(parentEl) {
                     container = container.parentNode;
                 container.appendChild(measureNode);
             }
-
         }
+        
+        // Size and width can be null if the editor is not visible or
+        // detached from the document
+        if (!this.element.offsetWidth)
+            return null;
 
         var style = this.$measureNode.style;
         var computedStyle = dom.computedStyle(this.element);
@@ -12975,7 +13526,46 @@ var Text = function(parentEl) {
 
         // Size and width can be null if the editor is not visible or
         // detached from the document
-        if (size.width == 0 && size.height == 0)
+        if (size.width == 0 || size.height == 0)
+            return null;
+
+        return size;
+    } 
+    : function() {
+        if (!this.$measureNode) {
+            var measureNode = this.$measureNode = dom.createElement("div");
+            var style = measureNode.style;
+
+            style.width = style.height = "auto";
+            style.left = style.top = -100 + "px";
+
+            style.visibility = "hidden";
+            style.position = "fixed";
+            style.overflow = "visible";
+            style.whiteSpace = "nowrap";
+
+            measureNode.innerHTML = "X";
+
+            var container = this.element.parentNode;
+            while (container && !dom.hasCssClass(container, "ace_editor"))
+                container = container.parentNode;
+
+            if (!container)
+                return this.$measureNode = null;
+
+            container.appendChild(measureNode);
+        }
+        
+        var rect = this.$measureNode.getBoundingClientRect();
+
+        var size = {
+            height: rect.height,
+            width: rect.width
+        };
+
+        // Size and width can be null if the editor is not visible or
+        // detached from the document
+        if (size.width == 0 || size.height == 0)
             return null;
 
         return size;
@@ -13089,16 +13679,16 @@ var Text = function(parentEl) {
     };
 
     this.$renderLinesFragment = function(config, firstRow, lastRow) {
-        var fragment = this.element.ownerDocument.createDocumentFragment(),
-            row = firstRow,
-            fold = this.session.getNextFoldLine(row),
-            foldStart = fold ?fold.start.row :Infinity;
+        var fragment = this.element.ownerDocument.createDocumentFragment();
+        var row = firstRow;
+        var foldLine = this.session.getNextFoldLine(row);
+        var foldStart = foldLine ? foldLine.start.row : Infinity;
 
         while (true) {
             if (row > foldStart) {
-                row = fold.end.row+1;
-                fold = this.session.getNextFoldLine(row, fold);
-                foldStart = fold ?fold.start.row :Infinity;
+                row = foldLine.end.row+1;
+                foldLine = this.session.getNextFoldLine(row, foldLine);
+                foldStart = foldLine ? foldLine.start.row : Infinity;
             }
             if (row > lastRow)
                 break;
@@ -13137,15 +13727,15 @@ var Text = function(parentEl) {
         var html = [];
         var firstRow = config.firstRow, lastRow = config.lastRow;
 
-        var row = firstRow,
-            fold = this.session.getNextFoldLine(row),
-            foldStart = fold ?fold.start.row :Infinity;
+        var row = firstRow;
+        var foldLine = this.session.getNextFoldLine(row);
+        var foldStart = foldLine ? foldLine.start.row : Infinity;
 
         while (true) {
             if (row > foldStart) {
-                row = fold.end.row+1;
-                fold = this.session.getNextFoldLine(row, fold);
-                foldStart = fold ?fold.start.row :Infinity;
+                row = foldLine.end.row+1;
+                foldLine = this.session.getNextFoldLine(row, foldLine);
+                foldStart = foldLine ? foldLine.start.row :Infinity;
             }
             if (row > lastRow)
                 break;
@@ -13446,11 +14036,10 @@ var Cursor = function(parentEl) {
     this.element.className = "ace_layer ace_cursor-layer";
     parentEl.appendChild(this.element);
 
-    this.cursor = dom.createElement("div");
-    this.cursor.className = "ace_cursor ace_hidden";
-    this.element.appendChild(this.cursor);
-
     this.isVisible = false;
+
+    this.cursors = [];
+    this.cursor = this.addCursor();
 };
 
 (function() {
@@ -13464,35 +14053,59 @@ var Cursor = function(parentEl) {
         this.session = session;
     };
 
+    this.addCursor = function() {
+        var el = dom.createElement("div");
+        var className = "ace_cursor";
+        if (!this.isVisible)
+            className += " ace_hidden";
+        if (this.overwrite)
+            className += " ace_overwrite";
+
+        el.className = className;
+        this.element.appendChild(el);
+        this.cursors.push(el);
+        return el;
+    };
+
+    this.removeCursor = function() {
+        if (this.cursors.length > 1) {
+            var el = this.cursors.pop();
+            el.parentNode.removeChild(el);
+            return el;
+        }
+    };
+
     this.hideCursor = function() {
         this.isVisible = false;
-        dom.addCssClass(this.cursor, "ace_hidden");
+        for (var i = this.cursors.length; i--; )
+            dom.addCssClass(this.cursors[i], "ace_hidden");
         clearInterval(this.blinkId);
     };
 
     this.showCursor = function() {
         this.isVisible = true;
-        dom.removeCssClass(this.cursor, "ace_hidden");
-        this.cursor.style.visibility = "visible";
+        for (var i = this.cursors.length; i--; )
+            dom.removeCssClass(this.cursors[i], "ace_hidden");
+
+        this.element.style.visibility = "";
         this.restartTimer();
     };
 
     this.restartTimer = function() {
         clearInterval(this.blinkId);
-        if (!this.isVisible) {
+        if (!this.isVisible)
             return;
-        }
 
-        var cursor = this.cursor;
+        var element = this.element;
         this.blinkId = setInterval(function() {
-            cursor.style.visibility = "hidden";
+            element.style.visibility = "hidden";
             setTimeout(function() {
-                cursor.style.visibility = "visible";
+                element.style.visibility = "visible";
             }, 400);
         }, 1000);
     };
 
-    this.getPixelPosition = function(onScreen) {
+    this.getPixelPosition = function(position, onScreen) {
         if (!this.config || !this.session) {
             return {
                 left : 0,
@@ -13500,7 +14113,8 @@ var Cursor = function(parentEl) {
             };
         }
 
-        var position = this.session.selection.getCursor();
+        if (!position)
+            position = this.session.selection.getCursor();
         var pos = this.session.documentToScreenPosition(position);
         var cursorLeft = Math.round(this.$padding +
                                     pos.column * this.config.characterWidth);
@@ -13516,25 +14130,53 @@ var Cursor = function(parentEl) {
     this.update = function(config) {
         this.config = config;
 
-        this.pixelPos = this.getPixelPosition(true);
+        if (this.session.selectionMarkerCount > 1) {
+            var selections = this.session.$selectionMarkers;
+            var i = 0, sel, cursorIndex = 0;
 
-        this.cursor.style.left = this.pixelPos.left + "px";
-        this.cursor.style.top =  this.pixelPos.top + "px";
-        this.cursor.style.width = config.characterWidth + "px";
-        this.cursor.style.height = config.lineHeight + "px";
+            for (var i = selections.length; i--; ) {
+                sel = selections[i];
+                var pixelPos = this.getPixelPosition(sel.cursor, true);
 
-        var overwrite = this.session.getOverwrite()
-        if (overwrite != this.overwrite) {
-            this.overwrite = overwrite;
-            if (overwrite)
-                dom.addCssClass(this.cursor, "ace_overwrite");
-            else
-                dom.removeCssClass(this.cursor, "ace_overwrite");
+                var style = (this.cursors[cursorIndex++] || this.addCursor()).style;
+
+                style.left = pixelPos.left + "px";
+                style.top = pixelPos.top + "px";
+                style.width = config.characterWidth + "px";
+                style.height = config.lineHeight + "px";
+            }
+            if (cursorIndex > 1)
+                while (this.cursors.length > cursorIndex)
+                    this.removeCursor();
+        } else {
+            var pixelPos = this.getPixelPosition(null, true);
+            var style = this.cursor.style;
+            style.left = pixelPos.left + "px";
+            style.top = pixelPos.top + "px";
+            style.width = config.characterWidth + "px";
+            style.height = config.lineHeight + "px";
+
+            while (this.cursors.length > 1)
+                this.removeCursor();
         }
 
+        var overwrite = this.session.getOverwrite();
+        if (overwrite != this.overwrite)
+            this.$setOverite(overwrite);
+
         this.restartTimer();
     };
 
+    this.$setOverite = function(overwrite) {
+        this.overwrite = overwrite;
+        for (var i = this.cursors.length; i--; ) {
+            if (overwrite)
+                dom.addCssClass(this.cursors[i], "ace_overwrite");
+            else
+                dom.removeCssClass(this.cursors[i], "ace_overwrite");
+        }
+    };
+
     this.destroy = function() {
         clearInterval(this.blinkId);
     }
@@ -13629,6 +14271,8 @@ var ScrollBar = function(parent) {
         this.inner.style.height = height + "px";
     };
 
+    // TODO: on chrome 17+ after for small zoom levels after this function
+    // this.element.scrollTop != scrollTop which makes page to scroll up.
     this.setScrollTop = function(scrollTop) {
         this.element.scrollTop = scrollTop;
     };
@@ -13712,12 +14356,11 @@ var RenderLoop = function(onRender, win) {
 exports.RenderLoop = RenderLoop;
 });
 define("text!ace/css/editor.css", [], "@import url(//fonts.googleapis.com/css?family=Droid+Sans+Mono);\n" +
-  "\n" +
   "\n" +
   ".ace_editor {\n" +
   "    position: absolute;\n" +
   "    overflow: hidden;\n" +
-  "    font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', 'Droid Sans Mono', 'Courier New', monospace;\n" +
+  "    font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', 'Droid Sans Mono', 'Consolas', monospace;\n" +
   "    font-size: 12px;\n" +
   "}\n" +
   "\n" +
@@ -13735,12 +14378,6 @@ define("text!ace/css/editor.css", [], "@import url(//fonts.googleapis.com/css?fa
   "    cursor: text;\n" +
   "}\n" +
   "\n" +
-  "/* setting pointer-events: auto; on node under the mouse, which changes during scroll,\n" +
-  "  will break mouse wheel scrolling in Safari */\n" +
-  ".ace_content * {\n" +
-  "     pointer-events: none;\n" +
-  "}\n" +
-  "\n" +
   ".ace_composition {\n" +
   "    position: absolute;\n" +
   "    background: #555;\n" +
@@ -13748,18 +14385,17 @@ define("text!ace/css/editor.css", [], "@import url(//fonts.googleapis.com/css?fa
   "    z-index: 4;\n" +
   "}\n" +
   "\n" +
-  ".ace_gutter .ace_layer {\n" +
-  "    position: relative;\n" +
-  "    min-width: 54px;\n" +
-  "    text-align: right;\n" +
-  "}\n" +
-  "\n" +
   ".ace_gutter {\n" +
   "    position: absolute;\n" +
   "    overflow : hidden;\n" +
   "    height: 100%;\n" +
   "    width: auto;\n" +
   "    cursor: default;\n" +
+  "    z-index: 1000;\n" +
+  "}\n" +
+  "\n" +
+  ".ace_gutter.horscroll {\n" +
+  "    box-shadow: 0px 0px 20px rgba(0,0,0,0.4);\n" +
   "}\n" +
   "\n" +
   ".ace_gutter-cell {\n" +
@@ -13838,6 +14474,16 @@ define("text!ace/css/editor.css", [], "@import url(//fonts.googleapis.com/css?fa
   "    box-sizing: border-box;\n" +
   "    -moz-box-sizing: border-box;\n" +
   "    -webkit-box-sizing: border-box;\n" +
+  "    /* setting pointer-events: auto; on node under the mouse, which changes\n" +
+  "        during scroll, will break mouse wheel scrolling in Safari */\n" +
+  "    pointer-events: none;\n" +
+  "}\n" +
+  "\n" +
+  ".ace_gutter .ace_layer {\n" +
+  "    position: relative;\n" +
+  "    min-width: 40px;\n" +
+  "    text-align: right;\n" +
+  "    pointer-events: auto;\n" +
   "}\n" +
   "\n" +
   ".ace_text-layer {\n" +
@@ -13873,12 +14519,12 @@ define("text!ace/css/editor.css", [], "@import url(//fonts.googleapis.com/css?fa
   "\n" +
   ".ace_marker-layer .ace_selection {\n" +
   "    position: absolute;\n" +
-  "    z-index: 4;\n" +
+  "    z-index: 5;\n" +
   "}\n" +
   "\n" +
   ".ace_marker-layer .ace_bracket {\n" +
   "    position: absolute;\n" +
-  "    z-index: 5;\n" +
+  "    z-index: 6;\n" +
   "}\n" +
   "\n" +
   ".ace_marker-layer .ace_active_line {\n" +
@@ -13886,9 +14532,13 @@ define("text!ace/css/editor.css", [], "@import url(//fonts.googleapis.com/css?fa
   "    z-index: 2;\n" +
   "}\n" +
   "\n" +
+  ".ace_gutter .ace_gutter_active_line{\n" +
+  "    background-color : #dcdcdc;\n" +
+  "}\n" +
+  "\n" +
   ".ace_marker-layer .ace_selected_word {\n" +
   "    position: absolute;\n" +
-  "    z-index: 6;\n" +
+  "    z-index: 4;\n" +
   "    box-sizing: border-box;\n" +
   "    -moz-box-sizing: border-box;\n" +
   "    -webkit-box-sizing: border-box;\n" +
@@ -13935,7 +14585,7 @@ define("text!ace/css/editor.css", [], "@import url(//fonts.googleapis.com/css?fa
   "    cursor: move;\n" +
   "}\n" +
   "\n" +
-  ".ace_folding-enabled .ace_gutter-cell {\n" +
+  ".ace_folding-enabled > .ace_gutter-cell {\n" +
   "    padding-right: 13px;\n" +
   "}\n" +
   "\n" +
@@ -13994,7 +14644,8 @@ define("text!ace/css/editor.css", [], "@import url(//fonts.googleapis.com/css?fa
   "}\n" +
   "");
 
-/* ***** BEGIN LICENSE BLOCK *****
+/* vim:ts=4:sts=4:sw=4:
+ * ***** BEGIN LICENSE BLOCK *****
  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  *
  * The contents of this file are subject to the Mozilla Public License Version
@@ -14015,7 +14666,7 @@ define("text!ace/css/editor.css", [], "@import url(//fonts.googleapis.com/css?fa
  * the Initial Developer. All Rights Reserved.
  *
  * Contributor(s):
- *      Fabian Jakobs <fabian AT ajax DOT org>
+ *      Harutyun Amirjanyan <amirjanyan AT gmail DOT com>
  *
  * Alternatively, the contents of this file may be used under the terms of
  * either the GNU General Public License Version 2 or later (the "GPL"), or
@@ -14031,52 +14682,1811 @@ define("text!ace/css/editor.css", [], "@import url(//fonts.googleapis.com/css?fa
  *
  * ***** END LICENSE BLOCK ***** */
 
-define('ace/theme/textmate', ['require', 'exports', 'module' , 'ace/lib/dom'], function(require, exports, module) {
-"use strict";
+define('ace/multi_select', ['require', 'exports', 'module' , 'ace/range_list', 'ace/range', 'ace/selection', 'ace/mouse/multi_select_handler', 'ace/commands/multi_select_commands', 'ace/search', 'ace/edit_session', 'ace/editor'], function(require, exports, module) {
 
-exports.isDark = false;
-exports.cssClass = "ace-tm";
-exports.cssText = ".ace-tm .ace_editor {\
-  border: 2px solid rgb(159, 159, 159);\
-}\
-\
-.ace-tm .ace_editor.ace_focus {\
-  border: 2px solid #327fbd;\
-}\
-\
-.ace-tm .ace_gutter {\
-  background: #e8e8e8;\
-  color: #333;\
-}\
-\
-.ace-tm .ace_print_margin {\
-  width: 1px;\
-  background: #e8e8e8;\
-}\
-\
-.ace-tm .ace_fold {\
-    background-color: #0000A2;\
-}\
-\
-.ace-tm .ace_text-layer {\
-  cursor: text;\
-}\
-\
-.ace-tm .ace_cursor {\
-  border-left: 2px solid black;\
-}\
-\
-.ace-tm .ace_cursor.ace_overwrite {\
-  border-left: 0px;\
-  border-bottom: 1px solid black;\
-}\
-        \
-.ace-tm .ace_line .ace_invisible {\
-  color: rgb(191, 191, 191);\
-}\
-\
-.ace-tm .ace_line .ace_keyword {\
-  color: blue;\
+var RangeList = require("./range_list").RangeList;
+var Range = require("./range").Range;
+var Selection = require("./selection").Selection;
+var onMouseDown = require("./mouse/multi_select_handler").onMouseDown;
+exports.commands = require("./commands/multi_select_commands");
+
+// Todo: session.find or editor.findVolatile that returns range
+var Search = require("./search").Search;
+var search = new Search();
+
+function find(session, needle, dir) {
+    search.$options.wrap = true;
+    search.$options.needle = needle;
+    search.$options.backwards = dir == -1;
+    return search.find(session);
+}
+
+// extend EditSession
+var EditSession = require("./edit_session").EditSession;
+(function() {
+    this.getSelectionMarkers = function() {
+        return this.$selectionMarkers;
+    };
+}).call(EditSession.prototype);
+
+// extend Selection
+(function() {
+    // list of ranges in reverse addition order
+    this.ranges = null;
+
+    // automatically sorted list of ranges
+    this.rangeList = null;
+
+    /**
+     * Selection.addRange(Range) -> Void
+     *
+     * adds a range to selection entering multiselect mode if necessary
+     **/
+    this.addRange = function(range) {
+        if (!this.inMultiSelectMode && this.rangeCount == 0) {
+            var oldRange = this.toOrientedRange();
+            if (!range || !range.isEqual(oldRange)) {
+                this.rangeList.add(oldRange);
+                this.$onAddRange(oldRange);
+            }
+        }
+
+        if (!range)
+            return;
+
+        if (!range.cursor)
+            range.cursor = range.end;
+
+        var removed = this.rangeList.add(range);
+
+        this.$onAddRange(range);
+
+        if (removed.length)
+            this.$onRemoveRange(removed);
+
+        if (this.rangeCount > 0 && !this.inMultiSelectMode) {
+            this._emit("multiSelect");
+            this.inMultiSelectMode = true;
+            this.session.$undoSelect = false;
+            this.rangeList.attach(this.session);
+        }
+    };
+
+    this.toSingleRange = function(range) {
+        range = range || this.ranges[0];
+        var removed = this.rangeList.removeAll();
+        if (removed.length)
+            this.$onRemoveRange(removed);
+
+        range && this.fromOrientedRange(range);
+    };
+    
+    /**
+     * Selection.addRange(pos) -> Range
+     * pos: {row, column}
+     *
+     * removes range containing pos (if exists)
+     **/
+    this.substractPoint = function(pos) {
+        var removed = this.rangeList.substractPoint(pos);
+        if (removed) {
+            this.$onRemoveRange(removed);
+            return removed[0];
+        }
+    };
+
+    /**
+     * Selection.mergeOverlappingRanges() -> Void
+     *
+     * merges overlapping ranges ensuring consistency after changes
+     **/
+    this.mergeOverlappingRanges = function() {
+        var removed = this.rangeList.merge();
+        if (removed.length)
+            this.$onRemoveRange(removed);
+        else if(this.ranges[0])
+            this.fromOrientedRange(this.ranges[0]);
+    };
+
+    this.$onAddRange = function(range) {
+        this.rangeCount = this.rangeList.ranges.length;
+        this.ranges.unshift(range);
+        this.fromOrientedRange(range);
+        this._emit("addRange", {range: range});
+    };
+
+    this.$onRemoveRange = function(removed) {
+        this.rangeCount = this.rangeList.ranges.length;
+        if (this.rangeCount == 1 && this.inMultiSelectMode) {
+            var lastRange = this.rangeList.ranges.pop();
+            removed.push(lastRange);
+            this.rangeCount = 0;
+        }
+
+        for (var i = removed.length; i--; ) {
+            var index = this.ranges.indexOf(removed[i]);
+            this.ranges.splice(index, 1);
+        }
+
+        this._emit("removeRange", {ranges: removed});
+
+        if (this.rangeCount == 0 && this.inMultiSelectMode) {
+            this.inMultiSelectMode = false;
+            this._emit("singleSelect");
+            this.session.$undoSelect = true;
+            this.rangeList.detach(this.session);
+        }
+
+        lastRange = lastRange || this.ranges[0];
+        if (lastRange && !lastRange.isEqual(this.getRange()))
+            this.fromOrientedRange(lastRange);
+    };
+
+    // adds multicursor support to selection
+    this.$initRangeList = function() {
+        if (this.rangeList)
+            return;
+
+        this.rangeList = new RangeList();
+        this.ranges = [];
+        this.rangeCount = 0;
+    };
+
+    this.getAllRanges = function() {
+        return this.rangeList.ranges.concat();
+    };
+
+    this.splitIntoLines = function () {
+        if (this.rangeCount > 1) {
+            var ranges = this.rangeList.ranges;
+            var lastRange = ranges[ranges.length - 1];
+            var range = Range.fromPoints(ranges[0].start, lastRange.end);
+
+            this.toSingleRange();
+            this.setSelectionRange(range, lastRange.cursor == lastRange.start);
+        } else {
+            var cursor = this.session.documentToScreenPosition(this.selectionLead);
+            var anchor = this.session.documentToScreenPosition(this.selectionAnchor);
+
+            var rectSel = this.rectangularRangeBlock(cursor, anchor);
+            rectSel.forEach(this.addRange, this);
+        }
+    };
+
+    /**
+     *   Selection.rectangularRangeBlock(screenCursor, screenAnchor, includeEmptyLines) -> [Range]
+     *   gets list of ranges composing rectangular block on the screen
+     *   @includeEmptyLines if true includes ranges inside the block which
+     *         are empty becuase of the clipping
+     */
+    this.rectangularRangeBlock = function(screenCursor, screenAnchor, includeEmptyLines) {
+        var rectSel = [];
+
+        var xBackwards = screenCursor.column < screenAnchor.column;
+        if (xBackwards) {
+            var startColumn = screenCursor.column;
+            var endColumn = screenAnchor.column;
+        } else {
+            var startColumn = screenAnchor.column;
+            var endColumn = screenCursor.column;
+        }
+
+        var yBackwards = screenCursor.row < screenAnchor.row;
+        if (yBackwards) {
+            var startRow = screenCursor.row;
+            var endRow = screenAnchor.row;
+        } else {
+            var startRow = screenAnchor.row;
+            var endRow = screenCursor.row;
+        }
+
+        if (startColumn < 0)
+            startColumn = 0;
+        if (startRow < 0)
+            startRow = 0;
+
+        if (startRow == endRow)
+            includeEmptyLines = true;
+
+        for (var row = startRow; row <= endRow; row++) {
+            var range = Range.fromPoints(
+                this.session.screenToDocumentPosition(row, startColumn),
+                this.session.screenToDocumentPosition(row, endColumn)
+            );
+            if (range.isEmpty()) {
+                if (docEnd && isSamePoint(range.end, docEnd))
+                    break;
+                var docEnd = range.end;
+            }
+            range.cursor = xBackwards ? range.start : range.end;
+            rectSel.push(range);
+        }
+
+        if (yBackwards)
+            rectSel.reverse();
+
+        if (!includeEmptyLines) {
+            var end = rectSel.length - 1;
+            while (rectSel[end].isEmpty() && end > 0)
+                end--;
+            if (end > 0) {
+                var start = 0;
+                while (rectSel[start].isEmpty())
+                    start++;
+            }
+            for (var i = end; i >= start; i--) {
+                if (rectSel[i].isEmpty())
+                    rectSel.splice(i, 1);
+            }
+        }
+
+        return rectSel;
+    };
+}).call(Selection.prototype);
+
+// extend Editor
+var Editor = require("./editor").Editor;
+(function() {
+    /**
+     * Editor.updateSelectionMarkers() -> Void
+     *
+     * updates cursor and marker layers
+     **/
+    this.updateSelectionMarkers = function() {
+        this.renderer.updateCursor();
+        this.renderer.updateBackMarkers();
+    };
+
+    /**
+     * Editor.addSelectionMarker(orientedRange) -> Range
+     * - orientedRange: range with cursor
+     *
+     * adds selection and cursor
+     **/
+    this.addSelectionMarker = function(orientedRange) {
+        if (!orientedRange.cursor)
+            orientedRange.cursor = orientedRange.end;
+
+        var style = this.getSelectionStyle();
+        orientedRange.marker = this.session.addMarker(orientedRange, "ace_selection", style);
+
+        this.session.$selectionMarkers.push(orientedRange);
+        this.session.selectionMarkerCount = this.session.$selectionMarkers.length;
+        return orientedRange;
+    };
+
+    this.removeSelectionMarkers = function(ranges) {
+        for (var i = ranges.length; i--; ) {
+            var range = ranges[i];
+            if (!range.marker)
+                continue;
+            this.session.removeMarker(range.marker);
+            var index = this.session.$selectionMarkers.indexOf(range);
+            if (index != -1)
+                this.session.$selectionMarkers.splice(index, 1);
+        }
+        this.session.selectionMarkerCount = this.session.$selectionMarkers.length;
+    };
+
+    this.$onAddRange = function(e) {
+        this.addSelectionMarker(e.range);
+        this.renderer.updateCursor();
+        this.renderer.updateBackMarkers();
+    };
+    
+    this.$onRemoveRange = function(e) {
+        this.removeSelectionMarkers(e.ranges);
+        this.renderer.updateCursor();
+        this.renderer.updateBackMarkers();
+    };
+    
+    this.$onMultiSelect = function(e) {
+        if (this.inMultiSelectMode)
+            return;
+        this.inMultiSelectMode = true;
+
+        this.setStyle("multiselect");
+        this.keyBinding.addKeyboardHandler(exports.commands.keyboardHandler);
+        this.commands.on("exec", this.$onMultiSelectExec);
+
+        this.renderer.updateCursor();
+        this.renderer.updateBackMarkers();
+    };
+    
+    this.$onSingleSelect = function(e) {
+        if (this.session.multiSelect.inVirtualMode)
+            return;
+        this.inMultiSelectMode = false;
+
+        this.unsetStyle("multiselect");
+        this.keyBinding.removeKeyboardHandler(exports.commands.keyboardHandler);
+
+        this.commands.removeEventListener("exec", this.$onMultiSelectExec);
+        this.renderer.updateCursor();
+        this.renderer.updateBackMarkers();
+    };
+
+    this.$onMultiSelectExec = function(e) {
+        var command = e.command;
+        var editor = e.editor;
+        if (!command.multiSelectAction) {
+            command.exec(editor, e.args || {});
+            editor.multiSelect.addRange(editor.multiSelect.toOrientedRange());
+            editor.multiSelect.mergeOverlappingRanges();
+        } else if (command.multiSelectAction == "forEach") {
+            editor.forEachSelection(command, e.args);
+        } else if (command.multiSelectAction == "single") {
+            editor.exitMultiSelectMode();
+            command.exec(editor, e.args || {});
+        } else {
+            command.multiSelectAction(editor, e.args || {});
+        }
+        e.preventDefault();
+    };
+
+    /**
+     * Editor.forEachSelection(cmd, args) -> Void
+     * - cmd: command to execute
+     * - args: arguments to the command
+     *
+     * executes command for each selection range
+     **/
+    this.forEachSelection = function(cmd, args) {
+        if (this.inVirtualSelectionMode)
+            return;
+
+        var session = this.session;
+        var selection = this.selection;
+        var rangeList = selection.rangeList;
+
+        var reg = selection._eventRegistry;
+        selection._eventRegistry = {};
+
+        var tmpSel = new Selection(session);
+        this.inVirtualSelectionMode = true;
+        for (var i = rangeList.ranges.length; i--;) {
+            tmpSel.fromOrientedRange(rangeList.ranges[i]);
+            this.selection = session.selection = tmpSel;
+            cmd.exec(this, args || {});
+            tmpSel.toOrientedRange(rangeList.ranges[i]);
+        }
+        tmpSel.detach();
+
+        this.selection = session.selection = selection;
+        this.inVirtualSelectionMode = false;
+        selection._eventRegistry = reg;
+        selection.mergeOverlappingRanges();
+
+        this.onCursorChange();
+        this.onSelectionChange();
+    };
+    
+    /**
+    * Editor.exitMultiSelectMode() -> Void
+    *
+    * removes all selections except the last added one.
+    **/
+    this.exitMultiSelectMode = function() {
+        if (this.inVirtualSelectionMode)
+            return;
+        this.multiSelect.toSingleRange();
+    };
+
+    this.getCopyText = function() {
+        var text = "";
+        if (this.inMultiSelectMode) {
+            var ranges = this.multiSelect.rangeList.ranges;
+            text = [];
+            for (var i = 0; i < ranges.length; i++) {
+                text.push(this.session.getTextRange(ranges[i]));
+            }
+            text = text.join(this.session.getDocument().getNewLineCharacter());
+        } else if (!this.selection.isEmpty()) {
+            text = this.session.getTextRange(this.getSelectionRange());
+        }
+
+        return text;
+    };
+
+
+    // commands
+    /**
+     * Editor.selectMoreLines(dir, skip) -> Void
+     * - dir: -1 up, 1 down
+     * - skip: remove active selection range if true
+     *
+     * adds cursor above or bellow active cursor
+     **/
+    this.selectMoreLines = function(dir, skip) {
+        var range = this.selection.toOrientedRange();
+        var isBackwards = range.cursor == range.end;
+
+        var screenLead = this.session.documentToScreenPosition(range.cursor);
+        if (this.selection.$desiredColumn)
+            screenLead.column = this.selection.$desiredColumn;
+
+        var lead = this.session.screenToDocumentPosition(screenLead.row + dir, screenLead.column);
+
+        if (!range.isEmpty()) {
+            var screenAnchor = this.session.documentToScreenPosition(isBackwards ? range.end : range.start);
+            var anchor = this.session.screenToDocumentPosition(screenAnchor.row + dir, screenAnchor.column);
+        } else {
+            var anchor = lead;
+        }
+
+        if (isBackwards) {
+            var newRange = Range.fromPoints(lead, anchor);
+            newRange.cursor = newRange.start;
+        } else {
+            var newRange = Range.fromPoints(anchor, lead);
+            newRange.cursor = newRange.end;
+        }
+
+        newRange.desiredColumn = screenLead.column;
+        if (!this.selection.inMultiSelectMode) {
+            this.selection.addRange(range);
+        } else {
+            if (skip)
+                var toRemove = range.cursor;
+        }
+
+        this.selection.addRange(newRange);
+        if (toRemove)
+            this.selection.substractPoint(toRemove);
+    };
+
+    /**
+     * Editor.transposeSelections(dir) -> Void
+     * - dir: direction to rotate selections
+     *
+     * contents 
+     * empty ranges are expanded to word
+     **/
+    this.transposeSelections = function(dir) {
+        var session = this.session;
+        var sel = session.multiSelect;
+        var all = sel.ranges;
+
+        for (var i = all.length; i--; ) {
+            var range = all[i];
+            if (range.isEmpty()) {
+                var tmp = session.getWordRange(range.start.row, range.start.column);
+                range.start.row = tmp.start.row;
+                range.start.column = tmp.start.column;
+                range.end.row = tmp.end.row;
+                range.end.column = tmp.end.column;
+            }
+        }
+        sel.mergeOverlappingRanges();
+        
+        var words = [];
+        for (var i = all.length; i--; ) {
+            var range = all[i];
+            words.unshift(session.getTextRange(range));
+        }
+
+        if (dir < 0)
+            words.unshift(words.pop());
+        else
+            words.push(words.shift());
+
+        for (var i = all.length; i--; ) {
+            var range = all[i];
+            var tmp = range.clone();
+            session.replace(range, words[i]);
+            range.start.row = tmp.start.row;
+            range.start.column = tmp.start.column;
+        }
+    }
+
+    /**
+     * Editor.selectMore(dir, skip) -> Void
+     * - dir: 1 next, -1 previous
+     * - skip: remove active selection range if true
+     *
+     * finds next occurence of text in active selection
+     * and adds it to the selections
+     **/
+    this.selectMore = function (dir, skip) {
+        var session = this.session;
+        var sel = session.multiSelect;
+
+        var range = sel.toOrientedRange();
+        if (range.isEmpty()) {
+            var range = session.getWordRange(range.start.row, range.start.column);
+            range.cursor = range.end;
+            this.multiSelect.addRange(range);
+        }
+        var needle = session.getTextRange(range);
+
+        var newRange = find(session, needle, dir);
+        if (newRange) {
+            newRange.cursor = dir == -1 ? newRange.start : newRange.end;
+            this.multiSelect.addRange(newRange);
+        }
+        if (skip)
+            this.multiSelect.substractPoint(range.cursor);
+    };
+}).call(Editor.prototype);
+
+
+function isSamePoint(p1, p2) {
+    return p1.row == p2.row && p1.column == p2.column;
+}
+
+// patch
+// adds multicursor support to a session
+exports.onSessionChange = function(e) {
+    var session = e.session;
+    if (!session.multiSelect) {
+        session.$selectionMarkers = [];
+        session.selection.$initRangeList();
+        session.multiSelect = session.selection;
+    }
+    this.multiSelect = session.multiSelect;
+
+    var oldSession = e.oldSession;
+    if (oldSession) {
+        // todo use events
+        if (oldSession.multiSelect && oldSession.multiSelect.editor == this)
+            oldSession.multiSelect.editor = null;
+
+        session.multiSelect.removeEventListener("addRange", this.$onAddRange);
+        session.multiSelect.removeEventListener("removeRange", this.$onRemoveRange);
+        session.multiSelect.removeEventListener("multiSelect", this.$onMultiSelect);
+        session.multiSelect.removeEventListener("singleSelect", this.$onSingleSelect);
+    }
+
+    session.multiSelect.on("addRange", this.$onAddRange);
+    session.multiSelect.on("removeRange", this.$onRemoveRange);
+    session.multiSelect.on("multiSelect", this.$onMultiSelect);
+    session.multiSelect.on("singleSelect", this.$onSingleSelect);
+
+    // this.$onSelectionChange = this.onSelectionChange.bind(this);
+
+    if (this.inMultiSelectMode != session.selection.inMultiSelectMode) {
+        if (session.selection.inMultiSelectMode)
+            this.$onMultiSelect();
+        else
+            this.$onSingleSelect();
+    }
+};
+
+/**
+ * MultiSelect(editor) -> Void
+ *
+ * adds multiple selection support to the editor
+ * (note: should be called only once for each editor instance)
+ **/
+function MultiSelect(editor) {
+    editor.$onAddRange = editor.$onAddRange.bind(editor);
+    editor.$onRemoveRange = editor.$onRemoveRange.bind(editor);
+    editor.$onMultiSelect = editor.$onMultiSelect.bind(editor);
+    editor.$onSingleSelect = editor.$onSingleSelect.bind(editor);
+
+    exports.onSessionChange.call(editor, editor);
+    editor.on("changeSession", exports.onSessionChange.bind(editor));
+
+    editor.on("mousedown", onMouseDown);
+    editor.commands.addCommands(exports.commands.defaultCommands);
+}
+
+exports.MultiSelect = MultiSelect;
+
+});/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Ajax.org Code Editor (ACE).
+ *
+ * The Initial Developer of the Original Code is
+ * Ajax.org B.V.
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *      Harutyun Amirjanyan <amirjanyan AT gmail DOT com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+define('ace/range_list', ['require', 'exports', 'module' ], function(require, exports, module) {
+"use strict";
+
+
+var RangeList = function() {
+    this.ranges = [];
+};
+
+(function() {
+    this.comparePoints = function(p1, p2) {
+        return p1.row - p2.row || p1.column - p2.column;
+    };
+
+    this.pointIndex = function(pos, startIndex) {
+        var list = this.ranges;
+
+        for (var i = startIndex || 0; i < list.length; i++) {
+            var range = list[i];
+            var cmp = this.comparePoints(pos, range.end);
+
+            if (cmp > 0)
+                continue;
+            if (cmp == 0)
+                return i;
+            cmp = this.comparePoints(pos, range.start);
+            if (cmp >= 0)
+                return i;
+
+            return -i-1;
+        }
+        return -i - 1;
+    };
+
+    this.add = function(range) {
+        var startIndex = this.pointIndex(range.start);
+        if (startIndex < 0)
+            startIndex = -startIndex - 1;
+
+        var endIndex = this.pointIndex(range.end, startIndex);
+
+        if (endIndex < 0)
+            endIndex = -endIndex - 1;
+        else
+            endIndex++;
+
+        return this.ranges.splice(startIndex, endIndex - startIndex, range);
+    };
+
+    this.addList = function(list) {
+        var removed = [];
+        for (var i = list.length; i--; ) {
+            removed.push.call(removed, this.add(list[i]));
+        }
+        return removed;
+    };
+
+    this.substractPoint = function(pos) {
+        var i = this.pointIndex(pos);
+
+        if (i >= 0)
+            return this.ranges.splice(i, 1);
+    };
+
+    // merge overlapping ranges
+    this.merge = function() {
+        var removed = [];
+        var list = this.ranges;
+        var next = list[0], range;
+        for (var i = 1; i < list.length; i++) {
+            range = next;
+            next = list[i];
+            var cmp = this.comparePoints(range.end, next.start);
+            if (cmp < 0)
+                continue;
+
+            if (cmp == 0 && !(range.isEmpty() || next.isEmpty()))
+                continue;
+
+            if (this.comparePoints(range.end, next.end) < 0) {
+                range.end.row = next.end.row;
+                range.end.column = next.end.column;
+            }
+
+            list.splice(i, 1);
+            removed.push(next);
+            next = range;
+            i--;
+        }
+
+        return removed;
+    };
+
+    this.contains = function(row, column) {
+        return this.pointIndex({row: row, column: column}) >= 0;
+    };
+
+    this.containsPoint = function(pos) {
+        return this.pointIndex(pos) >= 0;
+    };
+
+    this.rangeAtPoint = function(pos) {
+        var i = this.pointIndex(pos);
+        if (i >= 0)
+            return this.ranges[i];
+    };
+
+
+    this.clipRows = function(startRow, endRow) {
+        var list = this.ranges;
+        if (list[0].start.row > endRow || list[list.length - 1].start.row < startRow)
+            return [];
+
+        var startIndex = this.pointIndex({row: startRow, column: 0});
+        if (startIndex < 0)
+            startIndex = -startIndex - 1;
+        var endIndex = this.pointIndex({row: endRow, column: 0}, startIndex);
+        if (endIndex < 0)
+            endIndex = -endIndex - 1;
+
+        var clipped = [];
+        for (var i = startIndex; i < endIndex; i++) {
+            clipped.push(list[i]);
+        }
+        return clipped;
+    };
+
+    this.removeAll = function() {
+        return this.ranges.splice(0, this.ranges.length);
+    };
+
+    this.attach = function(session) {
+        if (this.session)
+            this.detach();
+
+        this.session = session;
+        this.onChange = this.$onChange.bind(this);
+
+        this.session.on('change', this.onChange);
+    };
+
+    this.detach = function() {
+        if (!this.session)
+            return;
+        this.session.removeListener('change', this.onChange);
+        this.session = null;
+    };
+
+    this.$onChange = function(e) {
+        var changeRange = e.data.range;
+        if (e.data.action[0] == "i"){
+            var start = changeRange.start;
+            var end = changeRange.end;
+        } else {
+            var end = changeRange.start;
+            var start = changeRange.end;
+        }
+        var startRow = start.row;
+        var endRow = end.row;
+        var lineDif = endRow - startRow;
+
+        var colDiff = -start.column + end.column;
+
+        var ranges = this.ranges;
+
+        for (var i=0, n = ranges.length; i < n; i++) {
+            var r = ranges[i];
+            if (r.end.row < startRow)
+                continue;
+            if (r.start.row > startRow)
+                break;
+
+            if (r.start.row == startRow && r.start.column >= start.column ) {
+                r.start.column += colDiff;
+                r.start.row += lineDif;
+            }
+            if (r.end.row == startRow && r.end.column >=  start.column) {
+                r.end.column += colDiff;
+                r.end.row += lineDif;
+            }
+        }
+
+        if (lineDif != 0 && i < n) {
+            for (; i < n; i++) {
+                var r = ranges[i];
+                r.start.row += lineDif;
+                r.end.row += lineDif;
+            }
+        }
+    };
+
+}).call(RangeList.prototype);
+
+exports.RangeList = RangeList;
+});
+/* vim:ts=4:sts=4:sw=4:
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Ajax.org Code Editor (ACE).
+ *
+ * The Initial Developer of the Original Code is
+ * Ajax.org B.V.
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *      Harutyun Amirjanyan <amirjanyan AT gmail DOT com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+define('ace/mouse/multi_select_handler', ['require', 'exports', 'module' , 'ace/lib/event'], function(require, exports, module) {
+
+var event = require("../lib/event");
+
+
+// mouse
+function isSamePoint(p1, p2) {
+    return p1.row == p2.row && p1.column == p2.column;
+}
+
+function onMouseDown(e) {
+    var ev = e.domEvent;
+    var alt = ev.altKey;
+    var shift = ev.shiftKey;
+    var ctrl = e.getAccelKey();
+    var button = e.getButton();
+
+    if (!ctrl && !alt) {
+        if (e.editor.inMultiSelectMode) {
+            if (button == 0) {
+                e.editor.exitMultiSelectMode();
+            } else if (button == 2) {
+                var editor = e.editor;
+                var selectionEmpty = editor.selection.isEmpty();
+                editor.textInput.onContextMenu({x: e.clientX, y: e.clientY}, selectionEmpty);
+                event.capture(editor.container, function(){}, editor.textInput.onContextMenuClose);
+                e.stop();
+            }
+        }
+        return;
+    }
+
+    var editor = e.editor;
+    var selection = editor.selection;
+    var isMultiSelect = editor.inMultiSelectMode;
+    var pos = e.getDocumentPosition();
+    var cursor = selection.getCursor();
+    var inSelection = e.inSelection() || (selection.isEmpty() && isSamePoint(pos, cursor));
+
+
+    var mouseX = e.pageX, mouseY = e.pageY;
+    var onMouseSelection = function(e) {
+        mouseX = event.getDocumentX(e);
+        mouseY = event.getDocumentY(e);
+    };
+
+    var blockSelect = function() {
+        var newCursor = editor.renderer.pixelToScreenCoordinates(mouseX, mouseY);
+        var cursor = session.screenToDocumentPosition(newCursor.row, newCursor.column);
+
+        if (isSamePoint(screenCursor, newCursor)
+            && isSamePoint(cursor, selection.selectionLead))
+            return;
+        screenCursor = newCursor;
+
+        editor.selection.moveCursorToPosition(cursor);
+        editor.selection.clearSelection();
+        editor.renderer.scrollCursorIntoView();
+
+        editor.removeSelectionMarkers(rectSel);
+        rectSel = selection.rectangularRangeBlock(screenCursor, screenAnchor);
+        rectSel.forEach(editor.addSelectionMarker, editor);
+        editor.updateSelectionMarkers();
+    };
+    
+    var session = editor.session;
+    var screenAnchor = editor.renderer.pixelToScreenCoordinates(mouseX, mouseY);
+    var screenCursor = screenAnchor;
+
+    
+
+    if (ctrl && !shift && !alt && button == 0) {
+        if (!isMultiSelect && inSelection)
+            return; // dragging
+
+        if (!isMultiSelect)
+            selection.addRange(selection.toOrientedRange());
+
+
+        var oldRange = selection.rangeList.rangeAtPoint(pos);
+
+        event.capture(editor.container, function(){}, function() {
+            var tmpSel = selection.toOrientedRange();
+
+            if (oldRange && tmpSel.isEmpty() && isSamePoint(oldRange.cursor, tmpSel.cursor))
+                selection.substractPoint(tmpSel.cursor);
+            else
+                selection.addRange(tmpSel);
+        });
+
+    } else if (!shift && alt && button == 0) {
+        e.stop();
+
+        if (isMultiSelect && !ctrl)
+            selection.toSingleRange();
+        else if (!isMultiSelect && ctrl)
+            selection.addRange();
+
+        selection.moveCursorToPosition(pos);
+        selection.clearSelection();
+
+        var rectSel = [];
+
+        var onMouseSelectionEnd = function(e) {
+            clearInterval(timerId);
+            editor.removeSelectionMarkers(rectSel);
+            for (var i = 0; i < rectSel.length; i++)
+                selection.addRange(rectSel[i]);
+        };
+
+        var onSelectionInterval = blockSelect;
+
+        event.capture(editor.container, onMouseSelection, onMouseSelectionEnd);
+        var timerId = setInterval(function() {onSelectionInterval();}, 20);
+
+        return e.preventDefault();
+    }
+}
+
+
+exports.onMouseDown = onMouseDown;
+
+});/* vim:ts=4:sts=4:sw=4:
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Ajax.org Code Editor (ACE).
+ *
+ * The Initial Developer of the Original Code is
+ * Ajax.org B.V.
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *      Harutyun Amirjanyan <amirjanyan AT gmail DOT com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+define('ace/commands/multi_select_commands', ['require', 'exports', 'module' , 'ace/keyboard/hash_handler'], function(require, exports, module) {
+
+// commands to enter multiselect mode
+exports.defaultCommands = [{
+    name: "addCursorAbove",
+    exec: function(editor) { editor.selectMoreLines(-1); },
+    bindKey: {win: "Ctrl-Alt-Up", mac: "Ctrl-Alt-Up"},
+    readonly: true
+}, {
+    name: "addCursorBelow",
+    exec: function(editor) { editor.selectMoreLines(1); },
+    bindKey: {win: "Ctrl-Alt-Down", mac: "Ctrl-Alt-Down"},
+    readonly: true
+}, {
+    name: "addCursorAboveSkipCurrent",
+    exec: function(editor) { editor.selectMoreLines(-1, true); },
+    bindKey: {win: "Ctrl-Alt-Shift-Up", mac: "Ctrl-Alt-Shift-Up"},
+    readonly: true
+}, {
+    name: "addCursorBelowSkipCurrent",
+    exec: function(editor) { editor.selectMoreLines(1, true); },
+    bindKey: {win: "Ctrl-Alt-Shift-Down", mac: "Ctrl-Alt-Shift-Down"},
+    readonly: true
+}, {
+    name: "selectMoreBefore",
+    exec: function(editor) { editor.selectMore(-1); },
+    bindKey: {win: "Ctrl-Alt-Left", mac: "Ctrl-Alt-Left"},
+    readonly: true
+}, {
+    name: "selectMoreAfter",
+    exec: function(editor) { editor.selectMore(1); },
+    bindKey: {win: "Ctrl-Alt-Right", mac: "Ctrl-Alt-Right"},
+    readonly: true
+}, {
+    name: "selectNextBefore",
+    exec: function(editor) { editor.selectMore(-1, true); },
+    bindKey: {win: "Ctrl-Alt-Shift-Left", mac: "Ctrl-Alt-Shift-Left"},
+    readonly: true
+}, {
+    name: "selectNextAfter",
+    exec: function(editor) { editor.selectMore(1, true); },
+    bindKey: {win: "Ctrl-Alt-Shift-Right", mac: "Ctrl-Alt-Shift-Right"},
+    readonly: true
+},  {
+    name: "splitIntoLines",
+    exec: function(editor) { editor.multiSelect.splitIntoLines(); },
+    bindKey: {win: "Ctrl-Shift-L", mac: "Ctrl-Shift-L"},
+    readonly: true
+}];
+
+// commands active in multiselect mode
+exports.multiEditCommands = [{
+    name: "singleSelection",
+    bindKey: "esc",
+    exec: function(editor) { editor.exitMultiSelectMode(); },
+    readonly: true
+}];
+
+var HashHandler = require("../keyboard/hash_handler").HashHandler;
+exports.keyboardHandler = new HashHandler(exports.multiEditCommands);
+
+});/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Ajax.org Code Editor (ACE).
+ *
+ * The Initial Developer of the Original Code is
+ * Ajax.org B.V.
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *      Fabian Jakobs <fabian AT ajax DOT org>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+define('ace/worker/worker_client', ['require', 'exports', 'module' , 'ace/lib/oop', 'ace/lib/event_emitter', 'ace/config'], function(require, exports, module) {
+"use strict";
+
+var oop = require("../lib/oop");
+var EventEmitter = require("../lib/event_emitter").EventEmitter;
+var config = require("../config");
+
+var WorkerClient = function(topLevelNamespaces, packagedJs, mod, classname) {
+
+    this.changeListener = this.changeListener.bind(this);
+
+    if (config.get("packaged")) {
+        this.$worker = new Worker(config.get("workerPath") + "/" + packagedJs);
+    }
+    else {
+        var workerUrl = this.$normalizePath(require.nameToUrl("ace/worker/worker", null, "_"));
+        this.$worker = new Worker(workerUrl);
+
+        var tlns = {};
+        for (var i=0; i<topLevelNamespaces.length; i++) {
+            var ns = topLevelNamespaces[i];
+            var path = this.$normalizePath(require.nameToUrl(ns, null, "_").replace(/.js$/, ""));
+
+            tlns[ns] = path;
+        }
+    }
+
+    this.$worker.postMessage({
+        init : true,
+        tlns: tlns,
+        module: mod,
+        classname: classname
+    });
+
+    this.callbackId = 1;
+    this.callbacks = {};
+
+    var _self = this;
+    this.$worker.onerror = function(e) {
+        window.console && console.log && console.log(e);
+        throw e;
+    };
+    this.$worker.onmessage = function(e) {
+        var msg = e.data;
+        switch(msg.type) {
+            case "log":
+                window.console && console.log && console.log(msg.data);
+                break;
+
+            case "event":
+                _self._emit(msg.name, {data: msg.data});
+                break;
+
+            case "call":
+                var callback = _self.callbacks[msg.id];
+                if (callback) {
+                    callback(msg.data);
+                    delete _self.callbacks[msg.id];
+                }
+                break;
+        }
+    };
+};
+
+(function(){
+
+    oop.implement(this, EventEmitter);
+
+    this.$normalizePath = function(path) {
+        path = path.replace(/^[a-z]+:\/\/[^\/]+/, ""); // Remove domain name and rebuild it
+        path = location.protocol + "//" + location.host
+            // paths starting with a slash are relative to the root (host)
+            + (path.charAt(0) == "/" ? "" : location.pathname.replace(/\/[^\/]*$/, ""))
+            + "/" + path.replace(/^[\/]+/, "");
+        return path;
+    };
+
+    this.terminate = function() {
+        this._emit("terminate", {});
+        this.$worker.terminate();
+        this.$worker = null;
+        this.$doc.removeEventListener("change", this.changeListener);
+        this.$doc = null;
+    };
+
+    this.send = function(cmd, args) {
+        this.$worker.postMessage({command: cmd, args: args});
+    };
+
+    this.call = function(cmd, args, callback) {
+        if (callback) {
+            var id = this.callbackId++;
+            this.callbacks[id] = callback;
+            args.push(id);
+        }
+        this.send(cmd, args);
+    };
+
+    this.emit = function(event, data) {
+        try {
+            // firefox refuses to clone objects which have function properties
+            // TODO: cleanup event
+            this.$worker.postMessage({event: event, data: {data: data.data}});
+        }
+        catch(ex) {}
+    };
+
+    this.attachToDocument = function(doc) {
+        if(this.$doc)
+            this.terminate();
+
+        this.$doc = doc;
+        this.call("setValue", [doc.getValue()]);
+        doc.on("change", this.changeListener);
+    };
+
+    this.changeListener = function(e) {
+        e.range = {
+            start: e.data.range.start,
+            end: e.data.range.end
+        };
+        this.emit("change", e);
+    };
+
+}).call(WorkerClient.prototype);
+
+exports.WorkerClient = WorkerClient;
+
+});
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Skywriter.
+ *
+ * The Initial Developer of the Original Code is
+ * Mozilla.
+ * Portions created by the Initial Developer are Copyright (C) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Julian Viereck (julian.viereck@gmail.com)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+define('ace/keyboard/state_handler', ['require', 'exports', 'module' ], function(require, exports, module) {
+"use strict";
+
+// If you're developing a new keymapping and want to get an idea what's going
+// on, then enable debugging.
+var DEBUG = false;
+
+function StateHandler(keymapping) {
+    this.keymapping = this.$buildKeymappingRegex(keymapping);
+}
+
+StateHandler.prototype = {
+    /**
+     * Build the RegExp from the keymapping as RegExp can't stored directly
+     * in the metadata JSON and as the RegExp used to match the keys/buffer
+     * need to be adapted.
+     */
+    $buildKeymappingRegex: function(keymapping) {
+        for (var state in keymapping) {
+            this.$buildBindingsRegex(keymapping[state]);
+        }
+        return keymapping;
+    },
+
+    $buildBindingsRegex: function(bindings) {
+        // Escape a given Regex string.
+        bindings.forEach(function(binding) {
+            if (binding.key) {
+                binding.key = new RegExp('^' + binding.key + '$');
+            } else if (Array.isArray(binding.regex)) {
+                if (!('key' in binding))
+                  binding.key = new RegExp('^' + binding.regex[1] + '$');
+                binding.regex = new RegExp(binding.regex.join('') + '$');
+            } else if (binding.regex) {
+                binding.regex = new RegExp(binding.regex + '$');
+            }
+        });
+    },
+
+    $composeBuffer: function(data, hashId, key, e) {
+        // Initialize the data object.
+        if (data.state == null || data.buffer == null) {
+            data.state = "start";
+            data.buffer = "";
+        }
+
+        var keyArray = [];
+        if (hashId & 1) keyArray.push("ctrl");
+        if (hashId & 8) keyArray.push("command");
+        if (hashId & 2) keyArray.push("option");
+        if (hashId & 4) keyArray.push("shift");
+        if (key)        keyArray.push(key);
+
+        var symbolicName = keyArray.join("-");
+        var bufferToUse = data.buffer + symbolicName;
+
+        // Don't add the symbolic name to the key buffer if the alt_ key is
+        // part of the symbolic name. If it starts with alt_, this means
+        // that the user hit an alt keycombo and there will be a single,
+        // new character detected after this event, which then will be
+        // added to the buffer (e.g. alt_j will result in ∆).
+        //
+        // We test for 2 and not for & 2 as we only want to exclude the case where
+        // the option key is pressed alone.
+        if (hashId != 2) {
+            data.buffer = bufferToUse;
+        }
+
+        var bufferObj = {
+            bufferToUse: bufferToUse,
+            symbolicName: symbolicName,
+        };
+
+        if (e) {
+            bufferObj.keyIdentifier = e.keyIdentifier
+        }
+
+        return bufferObj;
+    },
+
+    $find: function(data, buffer, symbolicName, hashId, key, keyIdentifier) {
+        // Holds the command to execute and the args if a command matched.
+        var result = {};
+
+        // Loop over all the bindings of the keymap until a match is found.
+        this.keymapping[data.state].some(function(binding) {
+            var match;
+
+            // Check if the key matches.
+            if (binding.key && !binding.key.test(symbolicName)) {
+                return false;
+            }
+
+            // Check if the regex matches.
+            if (binding.regex && !(match = binding.regex.exec(buffer))) {
+                return false;
+            }
+
+            // Check if the match function matches.
+            if (binding.match && !binding.match(buffer, hashId, key, symbolicName, keyIdentifier)) {
+                return false;
+            }
+
+            // Check for disallowed matches.
+            if (binding.disallowMatches) {
+                for (var i = 0; i < binding.disallowMatches.length; i++) {
+                    if (!!match[binding.disallowMatches[i]]) {
+                        return false;
+                    }
+                }
+            }
+
+            // If there is a command to execute, then figure out the
+            // command and the arguments.
+            if (binding.exec) {
+                result.command = binding.exec;
+
+                // Build the arguments.
+                if (binding.params) {
+                    var value;
+                    result.args = {};
+                    binding.params.forEach(function(param) {
+                        if (param.match != null && match != null) {
+                            value = match[param.match] || param.defaultValue;
+                        } else {
+                            value = param.defaultValue;
+                        }
+
+                        if (param.type === 'number') {
+                            value = parseInt(value);
+                        }
+
+                        result.args[param.name] = value;
+                    });
+                }
+                data.buffer = "";
+            }
+
+            // Handle the 'then' property.
+            if (binding.then) {
+                data.state = binding.then;
+                data.buffer = "";
+            }
+
+            // If no command is set, then execute the "null" fake command.
+            if (result.command == null) {
+                result.command = "null";
+            }
+
+            if (DEBUG) {
+                console.log("KeyboardStateMapper#find", binding);
+            }
+            return true;
+        });
+
+        if (result.command) {
+            return result;
+        } else {
+            data.buffer = "";
+            return false;
+        }
+    },
+
+    /**
+     * This function is called by keyBinding.
+     */
+    handleKeyboard: function(data, hashId, key, keyCode, e) {
+        // If we pressed any command key but no other key, then ignore the input.
+        // Otherwise "shift-" is added to the buffer, and later on "shift-g"
+        // which results in "shift-shift-g" which doesn't make sense.
+        if (hashId != 0 && (key == "" || key == String.fromCharCode(0))) {
+            return null;
+        }
+
+        // Compute the current value of the keyboard input buffer.
+        var r = this.$composeBuffer(data, hashId, key, e);
+        var buffer = r.bufferToUse;
+        var symbolicName = r.symbolicName;
+        var keyId = r.keyIdentifier;
+
+        r = this.$find(data, buffer, symbolicName, hashId, key, keyId);
+        if (DEBUG) {
+            console.log("KeyboardStateMapper#match", buffer, symbolicName, r);
+        }
+
+        return r;
+    }
+}
+
+/**
+ * This is a useful matching function and therefore is defined here so that
+ * users of KeyboardStateMapper can use it.
+ *
+ * @return boolean
+ *          If no command key (Command|Option|Shift|Ctrl) is pressed, it
+ *          returns true. If the only the Shift key is pressed + a character
+ *          true is returned as well. Otherwise, false is returned.
+ *          Summing up, the function returns true whenever the user typed
+ *          a normal character on the keyboard and no shortcut.
+ */
+exports.matchCharacterOnly = function(buffer, hashId, key, symbolicName) {
+    // If no command keys are pressed, then catch the input.
+    if (hashId == 0) {
+        return true;
+    }
+    // If only the shift key is pressed and a character key, then
+    // catch that input as well.
+    else if ((hashId == 4) && key.length == 1) {
+        return true;
+    }
+    // Otherwise, we let the input got through.
+    else {
+        return false;
+    }
+};
+
+exports.StateHandler = StateHandler;
+});
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Ajax.org Code Editor (ACE).
+ *
+ * The Initial Developer of the Original Code is
+ * Ajax.org B.V.
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *      Zef Hemel <zef@c9.io>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+define('ace/placeholder', ['require', 'exports', 'module' , 'ace/range', 'ace/lib/event_emitter', 'ace/lib/oop'], function(require, exports, module) {
+"use strict";
+
+var Range = require('./range').Range;
+var EventEmitter = require("./lib/event_emitter").EventEmitter;
+var oop = require("./lib/oop");
+
+var PlaceHolder = function(session, length, pos, others, mainClass, othersClass) {
+    var _self = this;
+    this.length = length;
+    this.session = session;
+    this.doc = session.getDocument();
+    this.mainClass = mainClass;
+    this.othersClass = othersClass;
+    this.$onUpdate = this.onUpdate.bind(this);
+    this.doc.on("change", this.$onUpdate);
+    this.$others = others;
+    
+    this.$onCursorChange = function() {
+        setTimeout(function() {
+            _self.onCursorChange();
+        });
+    };
+    
+    this.$pos = pos;
+    // Used for reset
+    var undoStack = session.getUndoManager().$undoStack || session.getUndoManager().$undostack || {length: -1};
+    this.$undoStackDepth =  undoStack.length;
+    this.setup();
+
+    session.selection.on("changeCursor", this.$onCursorChange);
+};
+
+(function() {
+
+    oop.implement(this, EventEmitter);
+
+    this.setup = function() {
+        var _self = this;
+        var doc = this.doc;
+        var session = this.session;
+        var pos = this.$pos;
+
+        this.pos = doc.createAnchor(pos.row, pos.column);
+        this.markerId = session.addMarker(new Range(pos.row, pos.column, pos.row, pos.column + this.length), this.mainClass, null, false);
+        this.pos.on("change", function(event) {
+            session.removeMarker(_self.markerId);
+            _self.markerId = session.addMarker(new Range(event.value.row, event.value.column, event.value.row, event.value.column+_self.length), _self.mainClass, null, false);
+        });
+        this.others = [];
+        this.$others.forEach(function(other) {
+            var anchor = doc.createAnchor(other.row, other.column);
+            _self.others.push(anchor);
+        });
+        session.setUndoSelect(false);
+    };
+    
+    this.showOtherMarkers = function() {
+        if(this.othersActive) return;
+        var session = this.session;
+        var _self = this;
+        this.othersActive = true;
+        this.others.forEach(function(anchor) {
+            anchor.markerId = session.addMarker(new Range(anchor.row, anchor.column, anchor.row, anchor.column+_self.length), _self.othersClass, null, false);
+            anchor.on("change", function(event) {
+                session.removeMarker(anchor.markerId);
+                anchor.markerId = session.addMarker(new Range(event.value.row, event.value.column, event.value.row, event.value.column+_self.length), _self.othersClass, null, false);
+            });
+        });
+    };
+    
+    this.hideOtherMarkers = function() {
+        if(!this.othersActive) return;
+        this.othersActive = false;
+        for (var i = 0; i < this.others.length; i++) {
+            this.session.removeMarker(this.others[i].markerId);
+        }
+    };
+
+    this.onUpdate = function(event) {
+        var delta = event.data;
+        var range = delta.range;
+        if(range.start.row !== range.end.row) return;
+        if(range.start.row !== this.pos.row) return;
+        if (this.$updating) return;
+        this.$updating = true;
+        var lengthDiff = delta.action === "insertText" ? range.end.column - range.start.column : range.start.column - range.end.column;
+        
+        if(range.start.column >= this.pos.column && range.start.column <= this.pos.column + this.length + 1) {
+            var distanceFromStart = range.start.column - this.pos.column;
+            this.length += lengthDiff;
+            if(!this.session.$fromUndo) {
+                if(delta.action === "insertText") {
+                    for (var i = this.others.length - 1; i >= 0; i--) {
+                        var otherPos = this.others[i];
+                        var newPos = {row: otherPos.row, column: otherPos.column + distanceFromStart};
+                        if(otherPos.row === range.start.row && range.start.column < otherPos.column)
+                            newPos.column += lengthDiff;
+                        this.doc.insert(newPos, delta.text);
+                    }
+                } else if(delta.action === "removeText") {
+                    for (var i = this.others.length - 1; i >= 0; i--) {
+                        var otherPos = this.others[i];
+                        var newPos = {row: otherPos.row, column: otherPos.column + distanceFromStart};
+                        if(otherPos.row === range.start.row && range.start.column < otherPos.column)
+                            newPos.column += lengthDiff;
+                        this.doc.remove(new Range(newPos.row, newPos.column, newPos.row, newPos.column - lengthDiff));
+                    }
+                }
+                // Special case: insert in beginning
+                if(range.start.column === this.pos.column && delta.action === "insertText") {
+                    setTimeout(function() {
+                        this.pos.setPosition(this.pos.row, this.pos.column - lengthDiff);
+                        for (var i = 0; i < this.others.length; i++) {
+                            var other = this.others[i];
+                            var newPos = {row: other.row, column: other.column - lengthDiff};
+                            if(other.row === range.start.row && range.start.column < other.column)
+                                newPos.column += lengthDiff;
+                            other.setPosition(newPos.row, newPos.column);
+                        }
+                    }.bind(this), 0);
+                }
+                else if(range.start.column === this.pos.column && delta.action === "removeText") {
+                    setTimeout(function() {
+                        for (var i = 0; i < this.others.length; i++) {
+                            var other = this.others[i];
+                            if(other.row === range.start.row && range.start.column < other.column) {
+                                other.setPosition(other.row, other.column - lengthDiff);
+                            }
+                        }
+                    }.bind(this), 0);
+                }
+            }
+            this.pos._emit("change", {value: this.pos});
+            for (var i = 0; i < this.others.length; i++) {
+                this.others[i]._emit("change", {value: this.others[i]});
+            }
+        }
+        this.$updating = false;
+    };
+    
+    this.onCursorChange = function(event) {
+        if (this.$updating) return;
+        var pos = this.session.selection.getCursor();
+        if(pos.row === this.pos.row && pos.column >= this.pos.column && pos.column <= this.pos.column + this.length) {
+            this.showOtherMarkers();
+            this._emit("cursorEnter", event);
+        } else {
+            this.hideOtherMarkers();
+            this._emit("cursorLeave", event);
+        }
+    };
+    
+    this.detach = function() {
+        this.session.removeMarker(this.markerId);
+        this.hideOtherMarkers();
+        this.doc.removeEventListener("change", this.$onUpdate);
+        this.session.selection.removeEventListener("changeCursor", this.$onCursorChange);
+        this.pos.detach();
+        for (var i = 0; i < this.others.length; i++) {
+            this.others[i].detach();
+        }
+        this.session.setUndoSelect(true);
+    };
+    
+    this.cancel = function() {
+        if(this.$undoStackDepth === -1)
+            throw Error("Canceling placeholders only supported with undo manager attached to session.");
+        var undoManager = this.session.getUndoManager();
+        var undosRequired = (undoManager.$undoStack || undoManager.$undostack).length - this.$undoStackDepth;
+        for (var i = 0; i < undosRequired; i++) {
+            undoManager.undo(true);
+        }
+    };
+}).call(PlaceHolder.prototype);
+
+
+exports.PlaceHolder = PlaceHolder;
+});
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Ajax.org Code Editor (ACE).
+ *
+ * The Initial Developer of the Original Code is
+ * Ajax.org B.V.
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *      Fabian Jakobs <fabian AT ajax DOT org>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+define('ace/theme/textmate', ['require', 'exports', 'module' , 'ace/lib/dom'], function(require, exports, module) {
+"use strict";
+
+exports.isDark = false;
+exports.cssClass = "ace-tm";
+exports.cssText = ".ace-tm .ace_editor {\
+  border: 2px solid rgb(159, 159, 159);\
+}\
+\
+.ace-tm .ace_editor.ace_focus {\
+  border: 2px solid #327fbd;\
+}\
+\
+.ace-tm .ace_gutter {\
+  background: #e8e8e8;\
+  color: #333;\
+}\
+\
+.ace-tm .ace_print_margin {\
+  width: 1px;\
+  background: #e8e8e8;\
+}\
+\
+.ace-tm .ace_fold {\
+    background-color: #6B72E6;\
+}\
+\
+.ace-tm .ace_text-layer {\
+  cursor: text;\
+}\
+\
+.ace-tm .ace_cursor {\
+  border-left: 1px solid black;\
+}\
+\
+.ace-tm .ace_cursor.ace_overwrite {\
+  border-left: 0px;\
+  border-bottom: 1px solid black;\
+}\
+        \
+.ace-tm .ace_line .ace_invisible {\
+  color: rgb(191, 191, 191);\
+}\
+\
+.ace-tm .ace_line .ace_storage,\
+.ace-tm .ace_line .ace_keyword {\
+  color: blue;\
+}\
+\
+.ace-tm .ace_line .ace_constant {\
+  color: rgb(197, 6, 11);\
 }\
 \
 .ace-tm .ace_line .ace_constant.ace_buildin {\
diff --git a/apps/files_texteditor/js/aceeditor/ace.js b/apps/files_texteditor/js/aceeditor/ace.js
index d8f08d58878cd20f9c9e41affc199de07f82c928..6043589ac1f2fa1a68df3383b708c38357ea6cfb 100644
--- a/apps/files_texteditor/js/aceeditor/ace.js
+++ b/apps/files_texteditor/js/aceeditor/ace.js
@@ -1 +1,10 @@
-(function(){function g(a){var e=function(a,b){return d("",a,b)};e.packaged=!0;var f=b;a&&(b[a]||(b[a]={}),f=b[a]),f.define&&(c.original=f.define),f.define=c,f.require&&(d.original=f.require),f.require=e}var a="",b=function(){return this}();if(typeof requirejs!="undefined")return;var c=function(a,b,d){if(typeof a!="string"){c.original?c.original.apply(window,arguments):(console.error("dropping module because define wasn't a string."),console.trace());return}arguments.length==2&&(d=b),c.modules||(c.modules={}),c.modules[a]=d},d=function(a,b,c){if(Object.prototype.toString.call(b)==="[object Array]"){var e=[];for(var g=0,h=b.length;g<h;++g){var i=f(a,b[g]);if(!i&&d.original)return d.original.apply(window,arguments);e.push(i)}c&&c.apply(null,e)}else{if(typeof b=="string"){var j=f(a,b);return!j&&d.original?d.original.apply(window,arguments):(c&&c(),j)}if(d.original)return d.original.apply(window,arguments)}},e=function(a,b){if(b.indexOf("!")!==-1){var c=b.split("!");return e(a,c[0])+"!"+e(a,c[1])}if(b.charAt(0)=="."){var d=a.split("/").slice(0,-1).join("/");b=d+"/"+b;while(b.indexOf(".")!==-1&&f!=b){var f=b;b=b.replace(/\/\.\//,"/").replace(/[^\/]+\/\.\.\//,"")}}return b},f=function(a,b){b=e(a,b);var f=c.modules[b];if(!f)return null;if(typeof f=="function"){var g={},h={id:b,uri:"",exports:g,packaged:!0},i=function(a,c){return d(b,a,c)},j=f(i,g,h);return g=j||h.exports,c.modules[b]=g,g}return f};g(a)})(),define("ace/ace",["require","exports","module","ace/lib/fixoldbrowsers","ace/lib/dom","ace/lib/event","ace/editor","ace/edit_session","ace/undomanager","ace/virtual_renderer","ace/theme/textmate"],function(a,b,c){"use strict",a("./lib/fixoldbrowsers");var d=a("./lib/dom"),e=a("./lib/event"),f=a("./editor").Editor,g=a("./edit_session").EditSession,h=a("./undomanager").UndoManager,i=a("./virtual_renderer").VirtualRenderer;b.edit=function(b){typeof b=="string"&&(b=document.getElementById(b));var c=new g(d.getInnerText(b));c.setUndoManager(new h),b.innerHTML="";var j=new f(new i(b,a("./theme/textmate")));j.setSession(c);var k={};return k.document=c,k.editor=j,j.resize(),e.addListener(window,"resize",function(){j.resize()}),b.env=k,j.env=k,j}}),define("ace/lib/fixoldbrowsers",["require","exports","module","ace/lib/regexp","ace/lib/es5-shim"],function(a,b,c){"use strict",a("./regexp"),a("./es5-shim")}),define("ace/lib/regexp",["require","exports","module"],function(a,b,c){function g(a){return(a.global?"g":"")+(a.ignoreCase?"i":"")+(a.multiline?"m":"")+(a.extended?"x":"")+(a.sticky?"y":"")}function h(a,b,c){if(Array.prototype.indexOf)return a.indexOf(b,c);for(var d=c||0;d<a.length;d++)if(a[d]===b)return d;return-1}"use strict";var d={exec:RegExp.prototype.exec,test:RegExp.prototype.test,match:String.prototype.match,replace:String.prototype.replace,split:String.prototype.split},e=d.exec.call(/()??/,"")[1]===undefined,f=function(){var a=/^/g;return d.test.call(a,""),!a.lastIndex}();RegExp.prototype.exec=function(a){var b=d.exec.apply(this,arguments),c,i;if(b){!e&&b.length>1&&h(b,"")>-1&&(i=RegExp(this.source,d.replace.call(g(this),"g","")),d.replace.call(a.slice(b.index),i,function(){for(var a=1;a<arguments.length-2;a++)arguments[a]===undefined&&(b[a]=undefined)}));if(this._xregexp&&this._xregexp.captureNames)for(var j=1;j<b.length;j++)c=this._xregexp.captureNames[j-1],c&&(b[c]=b[j]);!f&&this.global&&!b[0].length&&this.lastIndex>b.index&&this.lastIndex--}return b},f||(RegExp.prototype.test=function(a){var b=d.exec.call(this,a);return b&&this.global&&!b[0].length&&this.lastIndex>b.index&&this.lastIndex--,!!b})}),define("ace/lib/es5-shim",["require","exports","module"],function(a,b,c){function p(a){try{return Object.defineProperty(a,"sentinel",{}),"sentinel"in a}catch(b){}}Function.prototype.bind||(Function.prototype.bind=function(a){var b=this;if(typeof b!="function")throw new TypeError;var c=g.call(arguments,1),d=function(){if(this instanceof d){var e=function(){};e.prototype=b.prototype;var f=new e,h=b.apply(f,c.concat(g.call(arguments)));return h!==null&&Object(h)===h?h:f}return b.apply(a,c.concat(g.call(arguments)))};return d});var d=Function.prototype.call,e=Array.prototype,f=Object.prototype,g=e.slice,h=d.bind(f.toString),i=d.bind(f.hasOwnProperty),j,k,l,m,n;if(n=i(f,"__defineGetter__"))j=d.bind(f.__defineGetter__),k=d.bind(f.__defineSetter__),l=d.bind(f.__lookupGetter__),m=d.bind(f.__lookupSetter__);Array.isArray||(Array.isArray=function(a){return h(a)=="[object Array]"}),Array.prototype.forEach||(Array.prototype.forEach=function(a){var b=G(this),c=arguments[1],d=0,e=b.length>>>0;if(h(a)!="[object Function]")throw new TypeError;while(d<e)d in b&&a.call(c,b[d],d,b),d++}),Array.prototype.map||(Array.prototype.map=function(a){var b=G(this),c=b.length>>>0,d=Array(c),e=arguments[1];if(h(a)!="[object Function]")throw new TypeError;for(var f=0;f<c;f++)f in b&&(d[f]=a.call(e,b[f],f,b));return d}),Array.prototype.filter||(Array.prototype.filter=function(a){var b=G(this),c=b.length>>>0,d=[],e=arguments[1];if(h(a)!="[object Function]")throw new TypeError;for(var f=0;f<c;f++)f in b&&a.call(e,b[f],f,b)&&d.push(b[f]);return d}),Array.prototype.every||(Array.prototype.every=function(a){var b=G(this),c=b.length>>>0,d=arguments[1];if(h(a)!="[object Function]")throw new TypeError;for(var e=0;e<c;e++)if(e in b&&!a.call(d,b[e],e,b))return!1;return!0}),Array.prototype.some||(Array.prototype.some=function(a){var b=G(this),c=b.length>>>0,d=arguments[1];if(h(a)!="[object Function]")throw new TypeError;for(var e=0;e<c;e++)if(e in b&&a.call(d,b[e],e,b))return!0;return!1}),Array.prototype.reduce||(Array.prototype.reduce=function(a){var b=G(this),c=b.length>>>0;if(h(a)!="[object Function]")throw new TypeError;if(!c&&arguments.length==1)throw new TypeError;var d=0,e;if(arguments.length>=2)e=arguments[1];else do{if(d in b){e=b[d++];break}if(++d>=c)throw new TypeError}while(!0);for(;d<c;d++)d in b&&(e=a.call(void 0,e,b[d],d,b));return e}),Array.prototype.reduceRight||(Array.prototype.reduceRight=function(a){var b=G(this),c=b.length>>>0;if(h(a)!="[object Function]")throw new TypeError;if(!c&&arguments.length==1)throw new TypeError;var d,e=c-1;if(arguments.length>=2)d=arguments[1];else do{if(e in b){d=b[e--];break}if(--e<0)throw new TypeError}while(!0);do e in this&&(d=a.call(void 0,d,b[e],e,b));while(e--);return d}),Array.prototype.indexOf||(Array.prototype.indexOf=function(a){var b=G(this),c=b.length>>>0;if(!c)return-1;var d=0;arguments.length>1&&(d=E(arguments[1])),d=d>=0?d:Math.max(0,c+d);for(;d<c;d++)if(d in b&&b[d]===a)return d;return-1}),Array.prototype.lastIndexOf||(Array.prototype.lastIndexOf=function(a){var b=G(this),c=b.length>>>0;if(!c)return-1;var d=c-1;arguments.length>1&&(d=Math.min(d,E(arguments[1]))),d=d>=0?d:c-Math.abs(d);for(;d>=0;d--)if(d in b&&a===b[d])return d;return-1}),Object.getPrototypeOf||(Object.getPrototypeOf=function(a){return a.__proto__||(a.constructor?a.constructor.prototype:f)});if(!Object.getOwnPropertyDescriptor){var o="Object.getOwnPropertyDescriptor called on a non-object: ";Object.getOwnPropertyDescriptor=function(a,b){if(typeof a!="object"&&typeof a!="function"||a===null)throw new TypeError(o+a);if(!i(a,b))return;var c,d,e;c={enumerable:!0,configurable:!0};if(n){var g=a.__proto__;a.__proto__=f;var d=l(a,b),e=m(a,b);a.__proto__=g;if(d||e)return d&&(c.get=d),e&&(c.set=e),c}return c.value=a[b],c}}Object.getOwnPropertyNames||(Object.getOwnPropertyNames=function(a){return Object.keys(a)}),Object.create||(Object.create=function(a,b){var c;if(a===null)c={"__proto__":null};else{if(typeof a!="object")throw new TypeError("typeof prototype["+typeof a+"] != 'object'");var d=function(){};d.prototype=a,c=new d,c.__proto__=a}return b!==void 0&&Object.defineProperties(c,b),c});if(Object.defineProperty){var q=p({}),r=typeof document=="undefined"||p(document.createElement("div"));if(!q||!r)var s=Object.defineProperty}if(!Object.defineProperty||s){var t="Property description must be an object: ",u="Object.defineProperty called on non-object: ",v="getters & setters can not be defined on this javascript engine";Object.defineProperty=function(a,b,c){if(typeof a!="object"&&typeof a!="function"||a===null)throw new TypeError(u+a);if(typeof c!="object"&&typeof c!="function"||c===null)throw new TypeError(t+c);if(s)try{return s.call(Object,a,b,c)}catch(d){}if(i(c,"value"))if(n&&(l(a,b)||m(a,b))){var e=a.__proto__;a.__proto__=f,delete a[b],a[b]=c.value,a.__proto__=e}else a[b]=c.value;else{if(!n)throw new TypeError(v);i(c,"get")&&j(a,b,c.get),i(c,"set")&&k(a,b,c.set)}return a}}Object.defineProperties||(Object.defineProperties=function(a,b){for(var c in b)i(b,c)&&Object.defineProperty(a,c,b[c]);return a}),Object.seal||(Object.seal=function(a){return a}),Object.freeze||(Object.freeze=function(a){return a});try{Object.freeze(function(){})}catch(w){Object.freeze=function(a){return function b(b){return typeof b=="function"?b:a(b)}}(Object.freeze)}Object.preventExtensions||(Object.preventExtensions=function(a){return a}),Object.isSealed||(Object.isSealed=function(a){return!1}),Object.isFrozen||(Object.isFrozen=function(a){return!1}),Object.isExtensible||(Object.isExtensible=function(a){if(Object(a)===a)throw new TypeError;var b="";while(i(a,b))b+="?";a[b]=!0;var c=i(a,b);return delete a[b],c});if(!Object.keys){var x=!0,y=["toString","toLocaleString","valueOf","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","constructor"],z=y.length;for(var A in{toString:null})x=!1;Object.keys=function bd(a){if(typeof a!="object"&&typeof a!="function"||a===null)throw new TypeError("Object.keys called on a non-object");var bd=[];for(var b in a)i(a,b)&&bd.push(b);if(x)for(var c=0,d=z;c<d;c++){var e=y[c];i(a,e)&&bd.push(e)}return bd}}if(!Date.prototype.toISOString||(new Date(-621987552e5)).toISOString().indexOf("-000001")===-1)Date.prototype.toISOString=function(){var a,b,c,d;if(!isFinite(this))throw new RangeError;a=[this.getUTCMonth()+1,this.getUTCDate(),this.getUTCHours(),this.getUTCMinutes(),this.getUTCSeconds()],d=this.getUTCFullYear(),d=(d<0?"-":d>9999?"+":"")+("00000"+Math.abs(d)).slice(0<=d&&d<=9999?-4:-6),b=a.length;while(b--)c=a[b],c<10&&(a[b]="0"+c);return d+"-"+a.slice(0,2).join("-")+"T"+a.slice(2).join(":")+"."+("000"+this.getUTCMilliseconds()).slice(-3)+"Z"};Date.now||(Date.now=function(){return(new Date).getTime()}),Date.prototype.toJSON||(Date.prototype.toJSON=function(a){if(typeof this.toISOString!="function")throw new TypeError;return this.toISOString()}),Date.parse("+275760-09-13T00:00:00.000Z")!==864e13&&(Date=function(a){var b=function e(b,c,d,f,g,h,i){var j=arguments.length;if(this instanceof a){var k=j==1&&String(b)===b?new a(e.parse(b)):j>=7?new a(b,c,d,f,g,h,i):j>=6?new a(b,c,d,f,g,h):j>=5?new a(b,c,d,f,g):j>=4?new a(b,c,d,f):j>=3?new a(b,c,d):j>=2?new a(b,c):j>=1?new a(b):new a;return k.constructor=e,k}return a.apply(this,arguments)},c=new RegExp("^(\\d{4}|[+-]\\d{6})(?:-(\\d{2})(?:-(\\d{2})(?:T(\\d{2}):(\\d{2})(?::(\\d{2})(?:\\.(\\d{3}))?)?(?:Z|(?:([-+])(\\d{2}):(\\d{2})))?)?)?)?$");for(var d in a)b[d]=a[d];return b.now=a.now,b.UTC=a.UTC,b.prototype=a.prototype,b.prototype.constructor=b,b.parse=function f(b){var d=c.exec(b);if(d){d.shift();for(var e=1;e<7;e++)d[e]=+(d[e]||(e<3?1:0)),e==1&&d[e]--;var f=+d.pop(),g=+d.pop(),h=d.pop(),i=0;if(h){if(g>23||f>59)return NaN;i=(g*60+f)*6e4*(h=="+"?-1:1)}var j=+d[0];return 0<=j&&j<=99?(d[0]=j+400,a.UTC.apply(this,d)+i-126227808e5):a.UTC.apply(this,d)+i}return a.parse.apply(this,arguments)},b}(Date));var B="\t\n\f\r   ᠎              \u2028\u2029";if(!String.prototype.trim||B.trim()){B="["+B+"]";var C=new RegExp("^"+B+B+"*"),D=new RegExp(B+B+"*$");String.prototype.trim=function(){return String(this).replace(C,"").replace(D,"")}}var E=function(a){return a=+a,a!==a?a=0:a!==0&&a!==1/0&&a!==-Infinity&&(a=(a>0||-1)*Math.floor(Math.abs(a))),a},F="a"[0]!="a",G=function(a){if(a==null)throw new TypeError;return F&&typeof a=="string"&&a?a.split(""):Object(a)}}),define("ace/lib/dom",["require","exports","module"],function(a,b,c){"use strict";var d="http://www.w3.org/1999/xhtml";b.createElement=function(a,b){return document.createElementNS?document.createElementNS(b||d,a):document.createElement(a)},b.setText=function(a,b){a.innerText!==undefined&&(a.innerText=b),a.textContent!==undefined&&(a.textContent=b)},b.hasCssClass=function(a,b){var c=a.className.split(/\s+/g);return c.indexOf(b)!==-1},b.addCssClass=function(a,c){b.hasCssClass(a,c)||(a.className+=" "+c)},b.removeCssClass=function(a,b){var c=a.className.split(/\s+/g);for(;;){var d=c.indexOf(b);if(d==-1)break;c.splice(d,1)}a.className=c.join(" ")},b.toggleCssClass=function(a,b){var c=a.className.split(/\s+/g),d=!0;for(;;){var e=c.indexOf(b);if(e==-1)break;d=!1,c.splice(e,1)}return d&&c.push(b),a.className=c.join(" "),d},b.setCssClass=function(a,c,d){d?b.addCssClass(a,c):b.removeCssClass(a,c)},b.hasCssString=function(a,b){var c=0,d;b=b||document;if(b.createStyleSheet&&(d=b.styleSheets)){while(c<d.length)if(d[c++].title===a)return!0}else if(d=b.getElementsByTagName("style"))while(c<d.length)if(d[c++].id===a)return!0;return!1},b.importCssString=function e(a,c,e){e=e||document;if(c&&b.hasCssString(c,e))return null;var f;if(e.createStyleSheet)f=e.createStyleSheet(),f.cssText=a,c&&(f.title=c);else{f=e.createElementNS?e.createElementNS(d,"style"):e.createElement("style"),f.appendChild(e.createTextNode(a)),c&&(f.id=c);var g=e.getElementsByTagName("head")[0]||e.documentElement;g.appendChild(f)}},b.importCssStylsheet=function(a,c){if(c.createStyleSheet)c.createStyleSheet(a);else{var d=b.createElement("link");d.rel="stylesheet",d.href=a;var e=c.getElementsByTagName("head")[0]||c.documentElement;e.appendChild(d)}},b.getInnerWidth=function(a){return parseInt(b.computedStyle(a,"paddingLeft"),10)+parseInt(b.computedStyle(a,"paddingRight"),10)+a.clientWidth},b.getInnerHeight=function(a){return parseInt(b.computedStyle(a,"paddingTop"),10)+parseInt(b.computedStyle(a,"paddingBottom"),10)+a.clientHeight},window.pageYOffset!==undefined?(b.getPageScrollTop=function(){return window.pageYOffset},b.getPageScrollLeft=function(){return window.pageXOffset}):(b.getPageScrollTop=function(){return document.body.scrollTop},b.getPageScrollLeft=function(){return document.body.scrollLeft}),window.getComputedStyle?b.computedStyle=function(a,b){return b?(window.getComputedStyle(a,"")||{})[b]||"":window.getComputedStyle(a,"")||{}}:b.computedStyle=function(a,b){return b?a.currentStyle[b]:a.currentStyle},b.scrollbarWidth=function(a){var c=b.createElement("p");c.style.width="100%",c.style.minWidth="0px",c.style.height="200px";var d=b.createElement("div"),e=d.style;e.position="absolute",e.left="-10000px",e.overflow="hidden",e.width="200px",e.minWidth="0px",e.height="150px",d.appendChild(c);var f=a.body||a.documentElement;f.appendChild(d);var g=c.offsetWidth;e.overflow="scroll";var h=c.offsetWidth;return g==h&&(h=d.clientWidth),f.removeChild(d),g-h},b.setInnerHtml=function(a,b){var c=a.cloneNode(!1);return c.innerHTML=b,a.parentNode.replaceChild(c,a),c},b.setInnerText=function(a,b){var c=a.ownerDocument;c.body&&"textContent"in c.body?a.textContent=b:a.innerText=b},b.getInnerText=function(a){var b=a.ownerDocument;return b.body&&"textContent"in b.body?a.textContent:a.innerText||a.textContent||""},b.getParentWindow=function(a){return a.defaultView||a.parentWindow}}),define("ace/lib/event",["require","exports","module","ace/lib/keys","ace/lib/useragent","ace/lib/dom"],function(a,b,c){function g(a,b,c){var f=0;e.isOpera&&e.isMac?f=0|(b.metaKey?1:0)|(b.altKey?2:0)|(b.shiftKey?4:0)|(b.ctrlKey?8:0):f=0|(b.ctrlKey?1:0)|(b.altKey?2:0)|(b.shiftKey?4:0)|(b.metaKey?8:0);if(c in d.MODIFIER_KEYS){switch(d.MODIFIER_KEYS[c]){case"Alt":f=2;break;case"Shift":f=4;break;case"Ctrl":f=1;break;default:f=8}c=0}return f&8&&(c==91||c==93)&&(c=0),!!f||c in d.FUNCTION_KEYS||c in d.PRINTABLE_KEYS?a(b,f,c):!1}"use strict";var d=a("./keys"),e=a("./useragent"),f=a("./dom");b.addListener=function(a,b,c){if(a.addEventListener)return a.addEventListener(b,c,!1);if(a.attachEvent){var d=function(){c(window.event)};c._wrapper=d,a.attachEvent("on"+b,d)}},b.removeListener=function(a,b,c){if(a.removeEventListener)return a.removeEventListener(b,c,!1);a.detachEvent&&a.detachEvent("on"+b,c._wrapper||c)},b.stopEvent=function(a){return b.stopPropagation(a),b.preventDefault(a),!1},b.stopPropagation=function(a){a.stopPropagation?a.stopPropagation():a.cancelBubble=!0},b.preventDefault=function(a){a.preventDefault?a.preventDefault():a.returnValue=!1},b.getDocumentX=function(a){return a.clientX?a.clientX+f.getPageScrollLeft():a.pageX},b.getDocumentY=function(a){return a.clientY?a.clientY+f.getPageScrollTop():a.pageY},b.getButton=function(a){return a.type=="dblclick"?0:a.type=="contextmenu"?2:a.preventDefault?a.button:{1:0,2:2,4:1}[a.button]},document.documentElement.setCapture?b.capture=function(a,c,d){function e(a){return c(a),b.stopPropagation(a)}function g(e){c(e),f||(f=!0,d(e)),b.removeListener(a,"mousemove",c),b.removeListener(a,"mouseup",g),b.removeListener(a,"losecapture",g),a.releaseCapture()}var f=!1;b.addListener(a,"mousemove",c),b.addListener(a,"mouseup",g),b.addListener(a,"losecapture",g),a.setCapture()}:b.capture=function(a,b,c){function d(a){b(a),a.stopPropagation()}function e(a){b&&b(a),c&&c(a),document.removeEventListener("mousemove",d,!0),document.removeEventListener("mouseup",e,!0),a.stopPropagation()}document.addEventListener("mousemove",d,!0),document.addEventListener("mouseup",e,!0)},b.addMouseWheelListener=function(a,c){var d=0,e=function(a){if(a.wheelDelta!==undefined){Math.abs(a.wheelDeltaY)>d&&(d=Math.abs(a.wheelDeltaY));if(d>5e3)var b=400;else var b=8;a.wheelDeltaX!==undefined?(a.wheelX=-a.wheelDeltaX/b,a.wheelY=-a.wheelDeltaY/b):(a.wheelX=0,a.wheelY=-a.wheelDelta/b)}else a.axis&&a.axis==a.HORIZONTAL_AXIS?(a.wheelX=(a.detail||0)*5,a.wheelY=0):(a.wheelX=0,a.wheelY=(a.detail||0)*5);c(a)};b.addListener(a,"DOMMouseScroll",e),b.addListener(a,"mousewheel",e)},b.addMultiMouseDownListener=function(a,c,d,f,g){var h=0,i,j,k=function(a){h+=1,h==1&&(i=a.clientX,j=a.clientY,setTimeout(function(){h=0},f||600));var e=b.getButton(a)==c;if(!e||Math.abs(a.clientX-i)>5||Math.abs(a.clientY-j)>5)h=0;h==d&&(h=0,g(a));if(e)return b.preventDefault(a)};b.addListener(a,"mousedown",k),e.isOldIE&&b.addListener(a,"dblclick",k)},b.addCommandKeyListener=function(a,c){var d=b.addListener;if(e.isOldGecko){var f=null;d(a,"keydown",function(a){f=a.keyCode}),d(a,"keypress",function(a){return g(c,a,f)})}else{var h=null;d(a,"keydown",function(a){return h=a.keyIdentifier||a.keyCode,g(c,a,a.keyCode)}),e.isMac&&e.isOpera&&d(a,"keypress",function(a){var b=a.keyIdentifier||a.keyCode;if(h!==b)return g(c,a,h);h=null})}};if(window.postMessage){var h=1;b.nextTick=function(a,c){c=c||window;var d="zero-timeout-message-"+h;b.addListener(c,"message",function e(f){f.data==d&&(b.stopPropagation(f),b.removeListener(c,"message",e),a())}),c.postMessage(d,"*")}}else b.nextTick=function(a,b){b=b||window,window.setTimeout(a,0)}}),define("ace/lib/keys",["require","exports","module","ace/lib/oop"],function(a,b,c){"use strict";var d=a("./oop"),e=function(){var a={MODIFIER_KEYS:{16:"Shift",17:"Ctrl",18:"Alt",224:"Meta"},KEY_MODS:{ctrl:1,alt:2,option:2,shift:4,meta:8,command:8},FUNCTION_KEYS:{8:"Backspace",9:"Tab",13:"Return",19:"Pause",27:"Esc",32:"Space",33:"PageUp",34:"PageDown",35:"End",36:"Home",37:"Left",38:"Up",39:"Right",40:"Down",44:"Print",45:"Insert",46:"Delete",96:"Numpad0",97:"Numpad1",98:"Numpad2",99:"Numpad3",100:"Numpad4",101:"Numpad5",102:"Numpad6",103:"Numpad7",104:"Numpad8",105:"Numpad9",112:"F1",113:"F2",114:"F3",115:"F4",116:"F5",117:"F6",118:"F7",119:"F8",120:"F9",121:"F10",122:"F11",123:"F12",144:"Numlock",145:"Scrolllock"},PRINTABLE_KEYS:{32:" ",48:"0",49:"1",50:"2",51:"3",52:"4",53:"5",54:"6",55:"7",56:"8",57:"9",59:";",61:"=",65:"a",66:"b",67:"c",68:"d",69:"e",70:"f",71:"g",72:"h",73:"i",74:"j",75:"k",76:"l",77:"m",78:"n",79:"o",80:"p",81:"q",82:"r",83:"s",84:"t",85:"u",86:"v",87:"w",88:"x",89:"y",90:"z",107:"+",109:"-",110:".",188:",",190:".",191:"/",192:"`",219:"[",220:"\\",221:"]",222:'"'}};for(var b in a.FUNCTION_KEYS){var c=a.FUNCTION_KEYS[b].toUpperCase();a[c]=parseInt(b,10)}return d.mixin(a,a.MODIFIER_KEYS),d.mixin(a,a.PRINTABLE_KEYS),d.mixin(a,a.FUNCTION_KEYS),a}();d.mixin(b,e),b.keyCodeToString=function(a){return(e[a]||String.fromCharCode(a)).toLowerCase()}}),define("ace/lib/oop",["require","exports","module"],function(a,b,c){"use strict",b.inherits=function(){var a=function(){};return function(b,c){a.prototype=c.prototype,b.super_=c.prototype,b.prototype=new a,b.prototype.constructor=b}}(),b.mixin=function(a,b){for(var c in b)a[c]=b[c]},b.implement=function(a,c){b.mixin(a,c)}}),define("ace/lib/useragent",["require","exports","module"],function(a,b,c){"use strict";var d=(navigator.platform.match(/mac|win|linux/i)||["other"])[0].toLowerCase(),e=navigator.userAgent;b.isWin=d=="win",b.isMac=d=="mac",b.isLinux=d=="linux",b.isIE=navigator.appName=="Microsoft Internet Explorer"&&parseFloat(navigator.userAgent.match(/MSIE ([0-9]+[\.0-9]+)/)[1]),b.isOldIE=b.isIE&&b.isIE<9,b.isGecko=b.isMozilla=window.controllers&&window.navigator.product==="Gecko",b.isOldGecko=b.isGecko&&parseInt((navigator.userAgent.match(/rv\:(\d+)/)||[])[1],10)<4,b.isOpera=window.opera&&Object.prototype.toString.call(window.opera)=="[object Opera]",b.isWebKit=parseFloat(e.split("WebKit/")[1])||undefined,b.isChrome=parseFloat(e.split(" Chrome/")[1])||undefined,b.isAIR=e.indexOf("AdobeAIR")>=0,b.isIPad=e.indexOf("iPad")>=0,b.isTouchPad=e.indexOf("TouchPad")>=0,b.OS={LINUX:"LINUX",MAC:"MAC",WINDOWS:"WINDOWS"},b.getOS=function(){return b.isMac?b.OS.MAC:b.isLinux?b.OS.LINUX:b.OS.WINDOWS}}),define("ace/editor",["require","exports","module","ace/lib/fixoldbrowsers","ace/lib/oop","ace/lib/lang","ace/lib/useragent","ace/keyboard/textinput","ace/mouse/mouse_handler","ace/mouse/fold_handler","ace/keyboard/keybinding","ace/edit_session","ace/search","ace/range","ace/lib/event_emitter","ace/commands/command_manager","ace/commands/default_commands"],function(a,b,c){"use strict",a("./lib/fixoldbrowsers");var d=a("./lib/oop"),e=a("./lib/lang"),f=a("./lib/useragent"),g=a("./keyboard/textinput").TextInput,h=a("./mouse/mouse_handler").MouseHandler,i=a("./mouse/fold_handler").FoldHandler,j=a("./keyboard/keybinding").KeyBinding,k=a("./edit_session").EditSession,l=a("./search").Search,m=a("./range").Range,n=a("./lib/event_emitter").EventEmitter,o=a("./commands/command_manager").CommandManager,p=a("./commands/default_commands").commands,q=function(a,b){var c=a.getContainerElement();this.container=c,this.renderer=a,this.textInput=new g(a.getTextAreaContainer(),this),this.keyBinding=new j(this),f.isIPad||(this.$mouseHandler=new h(this),new i(this)),this.$blockScrolling=0,this.$search=(new l).set({wrap:!0}),this.commands=new o(f.isMac?"mac":"win",p),this.setSession(b||new k(""))};((function(){d.implement(this,n),this.setKeyboardHandler=function(a){this.keyBinding.setKeyboardHandler(a)},this.getKeyboardHandler=function(){return this.keyBinding.getKeyboardHandler()},this.setSession=function(a){if(this.session==a)return;if(this.session){var b=this.session;this.session.removeEventListener("change",this.$onDocumentChange),this.session.removeEventListener("changeMode",this.$onChangeMode),this.session.removeEventListener("tokenizerUpdate",this.$onTokenizerUpdate),this.session.removeEventListener("changeTabSize",this.$onChangeTabSize),this.session.removeEventListener("changeWrapLimit",this.$onChangeWrapLimit),this.session.removeEventListener("changeWrapMode",this.$onChangeWrapMode),this.session.removeEventListener("onChangeFold",this.$onChangeFold),this.session.removeEventListener("changeFrontMarker",this.$onChangeFrontMarker),this.session.removeEventListener("changeBackMarker",this.$onChangeBackMarker),this.session.removeEventListener("changeBreakpoint",this.$onChangeBreakpoint),this.session.removeEventListener("changeAnnotation",this.$onChangeAnnotation),this.session.removeEventListener("changeOverwrite",this.$onCursorChange),this.session.removeEventListener("changeScrollTop",this.$onScrollTopChange),this.session.removeEventListener("changeLeftTop",this.$onScrollLeftChange);var c=this.session.getSelection();c.removeEventListener("changeCursor",this.$onCursorChange),c.removeEventListener("changeSelection",this.$onSelectionChange)}this.session=a,this.$onDocumentChange=this.onDocumentChange.bind(this),a.addEventListener("change",this.$onDocumentChange),this.renderer.setSession(a),this.$onChangeMode=this.onChangeMode.bind(this),a.addEventListener("changeMode",this.$onChangeMode),this.$onTokenizerUpdate=this.onTokenizerUpdate.bind(this),a.addEventListener("tokenizerUpdate",this.$onTokenizerUpdate),this.$onChangeTabSize=this.renderer.updateText.bind(this.renderer),a.addEventListener("changeTabSize",this.$onChangeTabSize),this.$onChangeWrapLimit=this.onChangeWrapLimit.bind(this),a.addEventListener("changeWrapLimit",this.$onChangeWrapLimit),this.$onChangeWrapMode=this.onChangeWrapMode.bind(this),a.addEventListener("changeWrapMode",this.$onChangeWrapMode),this.$onChangeFold=this.onChangeFold.bind(this),a.addEventListener("changeFold",this.$onChangeFold),this.$onChangeFrontMarker=this.onChangeFrontMarker.bind(this),this.session.addEventListener("changeFrontMarker",this.$onChangeFrontMarker),this.$onChangeBackMarker=this.onChangeBackMarker.bind(this),this.session.addEventListener("changeBackMarker",this.$onChangeBackMarker),this.$onChangeBreakpoint=this.onChangeBreakpoint.bind(this),this.session.addEventListener("changeBreakpoint",this.$onChangeBreakpoint),this.$onChangeAnnotation=this.onChangeAnnotation.bind(this),this.session.addEventListener("changeAnnotation",this.$onChangeAnnotation),this.$onCursorChange=this.onCursorChange.bind(this),this.session.addEventListener("changeOverwrite",this.$onCursorChange),this.$onScrollTopChange=this.onScrollTopChange.bind(this),this.session.addEventListener("changeScrollTop",this.$onScrollTopChange),this.$onScrollLeftChange=this.onScrollLeftChange.bind(this),this.session.addEventListener("changeScrollLeft",this.$onScrollLeftChange),this.selection=a.getSelection(),this.selection.addEventListener("changeCursor",this.$onCursorChange),this.$onSelectionChange=this.onSelectionChange.bind(this),this.selection.addEventListener("changeSelection",this.$onSelectionChange),this.onChangeMode(),this.onCursorChange(),this.onScrollTopChange(),this.onScrollLeftChange(),this.onSelectionChange(),this.onChangeFrontMarker(),this.onChangeBackMarker(),this.onChangeBreakpoint(),this.onChangeAnnotation(),this.session.getUseWrapMode()&&this.renderer.adjustWrapLimit(),this.renderer.updateFull(),this._emit("changeSession",{session:a,oldSession:b})},this.getSession=function(){return this.session},this.getSelection=function(){return this.selection},this.resize=function(){this.renderer.onResize()},this.setTheme=function(a){this.renderer.setTheme(a)},this.getTheme=function(){return this.renderer.getTheme()},this.setStyle=function(a){this.renderer.setStyle(a)},this.unsetStyle=function(a){this.renderer.unsetStyle(a)},this.setFontSize=function(a){this.container.style.fontSize=a},this.$highlightBrackets=function(){this.session.$bracketHighlight&&(this.session.removeMarker(this.session.$bracketHighlight),this.session.$bracketHighlight=null);if(this.$highlightPending)return;var a=this;this.$highlightPending=!0,setTimeout(function(){a.$highlightPending=!1;var b=a.session.findMatchingBracket(a.getCursorPosition());if(b){var c=new m(b.row,b.column,b.row,b.column+1);a.session.$bracketHighlight=a.session.addMarker(c,"ace_bracket","text")}},10)},this.focus=function(){var a=this;setTimeout(function(){a.textInput.focus()}),this.textInput.focus()},this.isFocused=function(){return this.textInput.isFocused()},this.blur=function(){this.textInput.blur()},this.onFocus=function(){this.renderer.showCursor(),this.renderer.visualizeFocus(),this._emit("focus")},this.onBlur=function(){this.renderer.hideCursor(),this.renderer.visualizeBlur(),this._emit("blur")},this.onDocumentChange=function(a){var b=a.data,c=b.range,d;c.start.row==c.end.row&&b.action!="insertLines"&&b.action!="removeLines"?d=c.end.row:d=Infinity,this.renderer.updateLines(c.start.row,d),this._emit("change",a),this.onCursorChange()},this.onTokenizerUpdate=function(a){var b=a.data;this.renderer.updateLines(b.first,b.last)},this.onScrollTopChange=function(){this.renderer.scrollToY(this.session.getScrollTop())},this.onScrollLeftChange=function(){this.renderer.scrollToX(this.session.getScrollLeft())},this.onCursorChange=function(){this.renderer.updateCursor(),this.$blockScrolling||this.renderer.scrollCursorIntoView(),this.renderer.moveTextAreaToCursor(this.textInput.getElement()),this.$highlightBrackets(),this.$updateHighlightActiveLine()},this.$updateHighlightActiveLine=function(){var a=this.getSession();a.$highlightLineMarker&&a.removeMarker(a.$highlightLineMarker),a.$highlightLineMarker=null;if(this.getHighlightActiveLine()&&(this.getSelectionStyle()!="line"||!this.selection.isMultiLine())){var b=this.getCursorPosition(),c=this.session.getFoldLine(b.row),d;c?d=new m(c.start.row,0,c.end.row+1,0):d=new m(b.row,0,b.row+1,0),a.$highlightLineMarker=a.addMarker(d,"ace_active_line","background")}},this.onSelectionChange=function(a){var b=this.getSession();b.$selectionMarker&&b.removeMarker(b.$selectionMarker),b.$selectionMarker=null;if(!this.selection.isEmpty()){var c=this.selection.getRange(),d=this.getSelectionStyle();b.$selectionMarker=b.addMarker(c,"ace_selection",d)}else this.$updateHighlightActiveLine();this.$highlightSelectedWord&&this.session.getMode().highlightSelection(this)},this.onChangeFrontMarker=function(){this.renderer.updateFrontMarkers()},this.onChangeBackMarker=function(){this.renderer.updateBackMarkers()},this.onChangeBreakpoint=function(){this.renderer.setBreakpoints(this.session.getBreakpoints())},this.onChangeAnnotation=function(){this.renderer.setAnnotations(this.session.getAnnotations())},this.onChangeMode=function(){this.renderer.updateText()},this.onChangeWrapLimit=function(){this.renderer.updateFull()},this.onChangeWrapMode=function(){this.renderer.onResize(!0)},this.onChangeFold=function(){this.$updateHighlightActiveLine(),this.renderer.updateFull()},this.getCopyText=function(){var a="";return this.selection.isEmpty()||(a=this.session.getTextRange(this.getSelectionRange())),this._emit("copy",a),a},this.onCut=function(){if(this.$readOnly)return;var a=this.getSelectionRange();this._emit("cut",a),this.selection.isEmpty()||(this.session.remove(a),this.clearSelection())},this.insert=function(a){var b=this.session,c=b.getMode(),d=this.getCursorPosition();if(this.getBehavioursEnabled()){var e=c.transformAction(b.getState(d.row),"insertion",this,b,a);e&&(a=e.text)}a=a.replace("\t",this.session.getTabString());if(!this.selection.isEmpty())d=this.session.remove(this.getSelectionRange()),this.clearSelection();else if(this.session.getOverwrite()){var f=new m.fromPoints(d,d);f.end.column+=a.length,this.session.remove(f)}this.clearSelection();var g=d.column,h=b.getState(d.row),i=c.checkOutdent(h,b.getLine(d.row),a),j=b.getLine(d.row),k=c.getNextLineIndent(h,j.slice(0,d.column),b.getTabString()),l=b.insert(d,a);e&&e.selection&&(e.selection.length==2?this.selection.setSelectionRange(new m(d.row,g+e.selection[0],d.row,g+e.selection[1])):this.selection.setSelectionRange(new m(d.row+e.selection[0],e.selection[1],d.row+e.selection[2],e.selection[3])));var h=b.getState(d.row);if(b.getDocument().isNewLine(a)){this.moveCursorTo(d.row+1,0);var n=b.getTabSize(),o=Number.MAX_VALUE;for(var p=d.row+1;p<=l.row;++p){var q=0;j=b.getLine(p);for(var r=0;r<j.length;++r)if(j.charAt(r)=="\t")q+=n;else if(j.charAt(r)==" ")q+=1;else break;/[^\s]/.test(j)&&(o=Math.min(q,o))}for(var p=d.row+1;p<=l.row;++p){var s=o;j=b.getLine(p);for(var r=0;r<j.length&&s>0;++r)j.charAt(r)=="\t"?s-=n:j.charAt(r)==" "&&(s-=1);b.remove(new m(p,0,p,r))}b.indentRows(d.row+1,l.row,k)}i&&c.autoOutdent(h,b,d.row)},this.onTextInput=function(a,b){b&&this._emit("paste",a),this.keyBinding.onTextInput(a,b)},this.onCommandKey=function(a,b,c){this.keyBinding.onCommandKey(a,b,c)},this.setOverwrite=function(a){this.session.setOverwrite(a)},this.getOverwrite=function(){return this.session.getOverwrite()},this.toggleOverwrite=function(){this.session.toggleOverwrite()},this.setScrollSpeed=function(a){this.$mouseHandler.setScrollSpeed(a)},this.getScrollSpeed=function(){return this.$mouseHandler.getScrollSpeed()},this.setDragDelay=function(a){this.$mouseHandler.setDragDelay(a)},this.getDragDelay=function(){return this.$mouseHandler.getDragDelay()},this.$selectionStyle="line",this.setSelectionStyle=function(a){if(this.$selectionStyle==a)return;this.$selectionStyle=a,this.onSelectionChange(),this._emit("changeSelectionStyle",{data:a})},this.getSelectionStyle=function(){return this.$selectionStyle},this.$highlightActiveLine=!0,this.setHighlightActiveLine=function(a){if(this.$highlightActiveLine==a)return;this.$highlightActiveLine=a,this.$updateHighlightActiveLine()},this.getHighlightActiveLine=function(){return this.$highlightActiveLine},this.$highlightSelectedWord=!0,this.setHighlightSelectedWord=function(a){if(this.$highlightSelectedWord==a)return;this.$highlightSelectedWord=a,a?this.session.getMode().highlightSelection(this):this.session.getMode().clearSelectionHighlight(this)},this.getHighlightSelectedWord=function(){return this.$highlightSelectedWord},this.setShowInvisibles=function(a){if(this.getShowInvisibles()==a)return;this.renderer.setShowInvisibles(a)},this.getShowInvisibles=function(){return this.renderer.getShowInvisibles()},this.setShowPrintMargin=function(a){this.renderer.setShowPrintMargin(a)},this.getShowPrintMargin=function(){return this.renderer.getShowPrintMargin()},this.setPrintMarginColumn=function(a){this.renderer.setPrintMarginColumn(a)},this.getPrintMarginColumn=function(){return this.renderer.getPrintMarginColumn()},this.$readOnly=!1,this.setReadOnly=function(a){this.$readOnly=a},this.getReadOnly=function(){return this.$readOnly},this.$modeBehaviours=!0,this.setBehavioursEnabled=function(a){this.$modeBehaviours=a},this.getBehavioursEnabled=function(){return this.$modeBehaviours},this.setShowFoldWidgets=function(a){var b=this.renderer.$gutterLayer;if(b.getShowFoldWidgets()==a)return;this.renderer.$gutterLayer.setShowFoldWidgets(a),this.$showFoldWidgets=a,this.renderer.updateFull()},this.getShowFoldWidgets=function(){return this.renderer.$gutterLayer.getShowFoldWidgets()},this.remove=function(a){this.selection.isEmpty()&&(a=="left"?this.selection.selectLeft():this.selection.selectRight());var b=this.getSelectionRange();if(this.getBehavioursEnabled()){var c=this.session,d=c.getState(b.start.row),e=c.getMode().transformAction(d,"deletion",this,c,b);e&&(b=e)}this.session.remove(b),this.clearSelection()},this.removeWordRight=function(){this.selection.isEmpty()&&this.selection.selectWordRight(),this.session.remove(this.getSelectionRange()),this.clearSelection()},this.removeWordLeft=function(){this.selection.isEmpty()&&this.selection.selectWordLeft(),this.session.remove(this.getSelectionRange()),this.clearSelection()},this.removeToLineStart=function(){this.selection.isEmpty()&&this.selection.selectLineStart(),this.session.remove(this.getSelectionRange()),this.clearSelection()},this.removeToLineEnd=function(){this.selection.isEmpty()&&this.selection.selectLineEnd();var a=this.getSelectionRange();a.start.column==a.end.column&&a.start.row==a.end.row&&(a.end.column=0,a.end.row++),this.session.remove(a),this.clearSelection()},this.splitLine=function(){this.selection.isEmpty()||(this.session.remove(this.getSelectionRange()),this.clearSelection());var a=this.getCursorPosition();this.insert("\n"),this.moveCursorToPosition(a)},this.transposeLetters=function(){if(!this.selection.isEmpty())return;var a=this.getCursorPosition(),b=a.column;if(b===0)return;var c=this.session.getLine(a.row),d,e;b<c.length?(d=c.charAt(b)+c.charAt(b-1),e=new m(a.row,b-1,a.row,b+1)):(d=c.charAt(b-1)+c.charAt(b-2),e=new m(a.row,b-2,a.row,b)),this.session.replace(e,d)},this.toLowerCase=function(){var a=this.getSelectionRange();this.selection.isEmpty()&&this.selection.selectWord();var b=this.getSelectionRange(),c=this.session.getTextRange(b);this.session.replace(b,c.toLowerCase()),this.selection.setSelectionRange(a)},this.toUpperCase=function(){var a=this.getSelectionRange();this.selection.isEmpty()&&this.selection.selectWord();var b=this.getSelectionRange(),c=this.session.getTextRange(b);this.session.replace(b,c.toUpperCase()),this.selection.setSelectionRange(a)},this.indent=function(){var a=this.session,b=this.getSelectionRange();if(!(b.start.row<b.end.row||b.start.column<b.end.column)){var d;if(this.session.getUseSoftTabs()){var f=a.getTabSize(),g=this.getCursorPosition(),h=a.documentToScreenColumn(g.row,g.column),i=f-h%f;d=e.stringRepeat(" ",i)}else d="\t";return this.insert(d)}var c=this.$getSelectedRows();a.indentRows(c.first,c.last,"\t")},this.blockOutdent=function(){var a=this.session.getSelection();this.session.outdentRows(a.getRange())},this.toggleCommentLines=function(){var a=this.session.getState(this.getCursorPosition().row),b=this.$getSelectedRows();this.session.getMode().toggleCommentLines(a,this.session,b.first,b.last)},this.removeLines=function(){var a=this.$getSelectedRows(),b;a.first===0||a.last+1<this.session.getLength()?b=new m(a.first,0,a.last+1,0):b=new m(a.first-1,this.session.getLine(a.first-1).length,a.last,this.session.getLine(a.last).length),this.session.remove(b),this.clearSelection()},this.moveLinesDown=function(){this.$moveLines(function(a,b){return this.session.moveLinesDown(a,b)})},this.moveLinesUp=function(){this.$moveLines(function(a,b){return this.session.moveLinesUp(a,b)})},this.moveText=function(a,b){return this.$readOnly?null:this.session.moveText(a,b)},this.copyLinesUp=function(){this.$moveLines(function(a,b){return this.session.duplicateLines(a,b),0})},this.copyLinesDown=function(){this.$moveLines(function(a,b){return this.session.duplicateLines(a,b)})},this.$moveLines=function(a){var b=this.$getSelectedRows(),c=this.selection;if(!c.isMultiLine())var d=c.getRange(),e=c.isBackwards();var f=a.call(this,b.first,b.last);d?(d.start.row+=f,d.end.row+=f,c.setSelectionRange(d,e)):(c.setSelectionAnchor(b.last+f+1,0),c.$moveSelection(function(){c.moveCursorTo(b.first+f,0)}))},this.$getSelectedRows=function(){var a=this.getSelectionRange().collapseRows();return{first:a.start.row,last:a.end.row}},this.onCompositionStart=function(a){this.renderer.showComposition(this.getCursorPosition())},this.onCompositionUpdate=function(a){this.renderer.setCompositionText(a)},this.onCompositionEnd=function(){this.renderer.hideComposition()},this.getFirstVisibleRow=function(){return this.renderer.getFirstVisibleRow()},this.getLastVisibleRow=function(){return this.renderer.getLastVisibleRow()},this.isRowVisible=function(a){return a>=this.getFirstVisibleRow()&&a<=this.getLastVisibleRow()},this.isRowFullyVisible=function(a){return a>=this.renderer.getFirstFullyVisibleRow()&&a<=this.renderer.getLastFullyVisibleRow()},this.$getVisibleRowCount=function(){return this.renderer.getScrollBottomRow()-this.renderer.getScrollTopRow()+1},this.$getPageDownRow=function(){return this.renderer.getScrollBottomRow()},this.$getPageUpRow=function(){var a=this.renderer.getScrollTopRow(),b=this.renderer.getScrollBottomRow();return a-(b-a)},this.selectPageDown=function(){var a=this.$getPageDownRow()+Math.floor(this.$getVisibleRowCount()/2);this.scrollPageDown();var b=this.getSelection(),c=this.session.documentToScreenPosition(b.getSelectionLead()),d=this.session.screenToDocumentPosition(a,c.column);b.selectTo(d.row,d.column)},this.selectPageUp=function(){var a=this.renderer.getScrollTopRow()-this.renderer.getScrollBottomRow(),b=this.$getPageUpRow()+Math.round(a/2);this.scrollPageUp();var c=this.getSelection(),d=this.session.documentToScreenPosition(c.getSelectionLead()),e=this.session.screenToDocumentPosition(b,d.column);c.selectTo(e.row,e.column)},this.gotoPageDown=function(){var a=this.$getPageDownRow(),b=this.getCursorPositionScreen().column;this.scrollToRow(a),this.getSelection().moveCursorToScreen(a,b)},this.gotoPageUp=function(){var a=this.$getPageUpRow(),b=this.getCursorPositionScreen().column;this.scrollToRow(a),this.getSelection().moveCursorToScreen(a,b)},this.scrollPageDown=function(){this.scrollToRow(this.$getPageDownRow())},this.scrollPageUp=function(){this.renderer.scrollToRow(this.$getPageUpRow())},this.scrollToRow=function(a){this.renderer.scrollToRow(a)},this.scrollToLine=function(a,b){this.renderer.scrollToLine(a,b)},this.centerSelection=function(){var a=this.getSelectionRange(),b=Math.floor(a.start.row+(a.end.row-a.start.row)/2);this.renderer.scrollToLine(b,!0)},this.getCursorPosition=function(){return this.selection.getCursor()},this.getCursorPositionScreen=function(){return this.session.documentToScreenPosition(this.getCursorPosition())},this.getSelectionRange=function(){return this.selection.getRange()},this.selectAll=function(){this.$blockScrolling+=1,this.selection.selectAll(),this.$blockScrolling-=1},this.clearSelection=function(){this.selection.clearSelection()},this.moveCursorTo=function(a,b){this.selection.moveCursorTo(a,b)},this.moveCursorToPosition=function(a){this.selection.moveCursorToPosition(a)},this.jumpToMatching=function(){var a=this.getCursorPosition(),b=this.session.findMatchingBracket(a);b||(a.column+=1,b=this.session.findMatchingBracket(a)),b||(a.column-=2,b=this.session.findMatchingBracket(a)),b&&(this.clearSelection(),this.moveCursorTo(b.row,b.column))},this.gotoLine=function(a,b){this.selection.clearSelection(),this.session.unfold({row:a-1,column:b||0}),this.$blockScrolling+=1,this.moveCursorTo(a-1,b||0),this.$blockScrolling-=1,this.isRowFullyVisible(this.getCursorPosition().row)||this.scrollToLine(a,!0)},this.navigateTo=function(a,b){this.clearSelection(),this.moveCursorTo(a,b)},this.navigateUp=function(a){this.selection.clearSelection(),a=a||1,this.selection.moveCursorBy(-a,0)},this.navigateDown=function(a){this.selection.clearSelection(),a=a||1,this.selection.moveCursorBy(a,0)},this.navigateLeft=function(a){if(!this.selection.isEmpty()){var b=this.getSelectionRange().start;this.moveCursorToPosition(b)}else{a=a||1;while(a--)this.selection.moveCursorLeft()}this.clearSelection()},this.navigateRight=function(a){if(!this.selection.isEmpty()){var b=this.getSelectionRange().end;this.moveCursorToPosition(b)}else{a=a||1;while(a--)this.selection.moveCursorRight()}this.clearSelection()},this.navigateLineStart=function(){this.selection.moveCursorLineStart(),this.clearSelection()},this.navigateLineEnd=function(){this.selection.moveCursorLineEnd(),this.clearSelection()},this.navigateFileEnd=function(){this.selection.moveCursorFileEnd(),this.clearSelection()},this.navigateFileStart=function(){this.selection.moveCursorFileStart(),this.clearSelection()},this.navigateWordRight=function(){this.selection.moveCursorWordRight(),this.clearSelection()},this.navigateWordLeft=function(){this.selection.moveCursorWordLeft(),this.clearSelection()},this.replace=function(a,b){b&&this.$search.set(b);var c=this.$search.find(this.session);if(!c)return;this.$tryReplace(c,a),c!==null&&this.selection.setSelectionRange(c)},this.replaceAll=function(a,b){b&&this.$search.set(b);var c=this.$search.findAll(this.session);if(!c.length)return;var d=this.getSelectionRange();this.clearSelection(),this.selection.moveCursorTo(0,0),this.$blockScrolling+=1;for(var e=c.length-1;e>=0;--e)this.$tryReplace(c[e],a);this.selection.setSelectionRange(d),this.$blockScrolling-=1},this.$tryReplace=function(a,b){var c=this.session.getTextRange(a);return b=this.$search.replace(c,b),b!==null?(a.end=this.session.replace(a,b),a):null},this.getLastSearchOptions=function(){return this.$search.getOptions()},this.find=function(a,b){this.clearSelection(),b=b||{},b.needle=a,this.$search.set(b),this.$find()},this.findNext=function(a){a=a||{},typeof a.backwards=="undefined"&&(a.backwards=!1),this.$search.set(a),this.$find()},this.findPrevious=function(a){a=a||{},typeof a.backwards=="undefined"&&(a.backwards=!0),this.$search.set(a),this.$find()},this.$find=function(a){this.selection.isEmpty()||this.$search.set({needle:this.session.getTextRange(this.getSelectionRange())}),typeof a!="undefined"&&this.$search.set({backwards:a});var b=this.$search.find(this.session);b&&(this.session.unfold(b),this.gotoLine(b.end.row+1,b.end.column),this.selection.setSelectionRange(b))},this.undo=function(){this.session.getUndoManager().undo()},this.redo=function(){this.session.getUndoManager().redo()},this.destroy=function(){this.renderer.destroy()}})).call(q.prototype),b.Editor=q}),define("ace/lib/lang",["require","exports","module"],function(a,b,c){"use strict",b.stringReverse=function(a){return a.split("").reverse().join("")},b.stringRepeat=function(a,b){return(new Array(b+1)).join(a)};var d=/^\s\s*/,e=/\s\s*$/;b.stringTrimLeft=function(a){return a.replace(d,"")},b.stringTrimRight=function(a){return a.replace(e,"")},b.copyObject=function(a){var b={};for(var c in a)b[c]=a[c];return b},b.copyArray=function(a){var b=[];for(var c=0,d=a.length;c<d;c++)a[c]&&typeof a[c]=="object"?b[c]=this.copyObject(a[c]):b[c]=a[c];return b},b.deepCopy=function(a){if(typeof a!="object")return a;var b=a.constructor();for(var c in a)typeof a[c]=="object"?b[c]=this.deepCopy(a[c]):b[c]=a[c];return b},b.arrayToMap=function(a){var b={};for(var c=0;c<a.length;c++)b[a[c]]=1;return b},b.arrayRemove=function(a,b){for(var c=0;c<=a.length;c++)b===a[c]&&a.splice(c,1)},b.escapeRegExp=function(a){return a.replace(/([.*+?^${}()|[\]\/\\])/g,"\\$1")},b.deferredCall=function(a){var b=null,c=function(){b=null,a()},d=function(a){return d.cancel(),b=setTimeout(c,a||0),d};return d.schedule=d,d.call=function(){return this.cancel(),a(),d},d.cancel=function(){return clearTimeout(b),b=null,d},d}}),define("ace/keyboard/textinput",["require","exports","module","ace/lib/event","ace/lib/useragent","ace/lib/dom"],function(a,b,c){"use strict";var d=a("../lib/event"),e=a("../lib/useragent"),f=a("../lib/dom"),g=function(a,b){function l(){try{c.select()}catch(a){}}function m(a){if(!i){var d=a||c.value;if(d){d.charCodeAt(d.length-1)==g.charCodeAt(0)?(d=d.slice(0,-1),d&&b.onTextInput(d,j)):b.onTextInput(d,j);if(!v())return!1}}i=!1,j=!1,c.value=g,l()}function v(){return document.activeElement===c}var c=f.createElement("textarea");e.isTouchPad&&c.setAttribute("x-palm-disable-auto-cap",!0),c.style.left="-10000px",c.style.position="fixed",a.insertBefore(c,a.firstChild);var g=String.fromCharCode(0);m();var h=!1,i=!1,j=!1,k="",n=function(a){setTimeout(function(){h||m(a.data)},0)},o=function(a){if(e.isOldIE&&c.value.charCodeAt(0)>128)return;setTimeout(function(){h||m()},0)},p=function(a){h=!0,b.onCompositionStart(),e.isGecko||setTimeout(q,0)},q=function(){if(!h)return;b.onCompositionUpdate(c.value)},r=function(a){h=!1,b.onCompositionEnd()},s=function(a){i=!0;var d=b.getCopyText();d?c.value=d:a.preventDefault(),l(),setTimeout(function(){m()},0)},t=function(a){i=!0;var d=b.getCopyText();d?(c.value=d,b.onCut()):a.preventDefault(),l(),setTimeout(function(){m()},0)};d.addCommandKeyListener(c,b.onCommandKey.bind(b));if(e.isOldIE){var u={13:1,27:1};d.addListener(c,"keyup",function(a){h&&(!c.value||u[a.keyCode])&&setTimeout(r,0);if((c.value.charCodeAt(0)|0)<129)return;h?q():p()})}"onpropertychange"in c&&!("oninput"in c)?d.addListener(c,"propertychange",o):d.addListener(c,"input",n),d.addListener(c,"paste",function(a){j=!0,a.clipboardData&&a.clipboardData.getData?(m(a.clipboardData.getData("text/plain")),a.preventDefault()):o()}),"onbeforecopy"in c&&typeof clipboardData!="undefined"?(d.addListener(c,"beforecopy",function(a){var c=b.getCopyText();c?clipboardData.setData("Text",c):a.preventDefault()}),d.addListener(a,"keydown",function(a){if(a.ctrlKey&&a.keyCode==88){var c=b.getCopyText();c&&(clipboardData.setData("Text",c),b.onCut()),d.preventDefault(a)}})):(d.addListener(c,"copy",s),d.addListener(c,"cut",t)),d.addListener(c,"compositionstart",p),e.isGecko&&d.addListener(c,"text",q),e.isWebKit&&d.addListener(c,"keyup",q),d.addListener(c,"compositionend",r),d.addListener(c,"blur",function(){b.onBlur()}),d.addListener(c,"focus",function(){b.onFocus(),l()}),this.focus=function(){b.onFocus(),l(),c.focus()},this.blur=function(){c.blur()},this.isFocused=v,this.getElement=function(){return c},this.onContextMenu=function(a,b){a&&(k||(k=c.style.cssText),c.style.cssText="position:fixed; z-index:1000;left:"+(a.x-2)+"px; top:"+(a.y-2)+"px;"),b&&(c.value="")},this.onContextMenuClose=function(){setTimeout(function(){k&&(c.style.cssText=k,k=""),m()},0)}};b.TextInput=g}),define("ace/mouse/mouse_handler",["require","exports","module","ace/lib/event","ace/mouse/default_handlers","ace/mouse/default_gutter_handler","ace/mouse/mouse_event"],function(a,b,c){"use strict";var d=a("../lib/event"),e=a("./default_handlers").DefaultHandlers,f=a("./default_gutter_handler").GutterHandler,g=a("./mouse_event").MouseEvent,h=function(a){this.editor=a,new e(a),new f(a),d.addListener(a.container,"mousedown",function(b){return a.focus(),d.preventDefault(b)}),d.addListener(a.container,"selectstart",function(a){return d.preventDefault(a)});var b=a.renderer.getMouseEventTarget();d.addListener(b,"mousedown",this.onMouseEvent.bind(this,"mousedown")),d.addListener(b,"click",this.onMouseEvent.bind(this,"click")),d.addListener(b,"mousemove",this.onMouseMove.bind(this,"mousemove")),d.addMultiMouseDownListener(b,0,2,500,this.onMouseEvent.bind(this,"dblclick")),d.addMultiMouseDownListener(b,0,3,600,this.onMouseEvent.bind(this,"tripleclick")),d.addMultiMouseDownListener(b,0,4,600,this.onMouseEvent.bind(this,"quadclick")),d.addMouseWheelListener(a.container,this.onMouseWheel.bind(this,"mousewheel"));var c=a.renderer.$gutter;d.addListener(c,"mousedown",this.onMouseEvent.bind(this,"guttermousedown")),d.addListener(c,"click",this.onMouseEvent.bind(this,"gutterclick")),d.addListener(c,"dblclick",this.onMouseEvent.bind(this,"gutterdblclick")),d.addListener(c,"mousemove",this.onMouseMove.bind(this,"gutter"))};((function(){this.$scrollSpeed=1,this.setScrollSpeed=function(a){this.$scrollSpeed=a},this.getScrollSpeed=function(){return this.$scrollSpeed},this.onMouseEvent=function(a,b){this.editor._emit(a,new g(b,this.editor))},this.$dragDelay=250,this.setDragDelay=function(a){this.$dragDelay=a},this.getDragDelay=function(){return this.$dragDelay},this.onMouseMove=function(a,b){var c=this.editor._eventRegistry&&this.editor._eventRegistry.mousemove;if(!c||!c.length)return;this.editor._emit(a,new g(b,this.editor))},this.onMouseWheel=function(a,b){var c=new g(b,this.editor);c.speed=this.$scrollSpeed*2,c.wheelX=b.wheelX,c.wheelY=b.wheelY,this.editor._emit(a,c)}})).call(h.prototype),b.MouseHandler=h}),define("ace/mouse/default_handlers",["require","exports","module","ace/lib/event","ace/lib/dom","ace/lib/browser_focus"],function(a,b,c){function k(a){this.editor=a,this.$clickSelection=null,this.browserFocus=new f,a.setDefaultHandler("mousedown",this.onMouseDown.bind(this)),a.setDefaultHandler("dblclick",this.onDoubleClick.bind(this)),a.setDefaultHandler("tripleclick",this.onTripleClick.bind(this)),a.setDefaultHandler("quadclick",this.onQuadClick.bind(this)),a.setDefaultHandler("mousewheel",this.onScroll.bind(this))}function l(a,b,c,d){return Math.sqrt(Math.pow(c-a,2)+Math.pow(d-b,2))}"use strict";var d=a("../lib/event"),e=a("../lib/dom"),f=a("../lib/browser_focus").BrowserFocus,g=0,h=1,i=2,j=5;((function(){this.onMouseDown=function(a){function C(b){a.getShiftKey()?m.selection.selectToPosition(b):n.$clickSelection||(m.moveCursorToPosition(b),m.selection.clearSelection(b.row,b.column)),q=h}var b=a.inSelection(),c=a.pageX,f=a.pageY,k=a.getDocumentPosition(),m=this.editor,n=this,o=m.getSelectionRange(),p=o.isEmpty(),q=g;if(b&&(!this.browserFocus.isFocused()||(new Date).getTime()-this.browserFocus.lastFocus<20||!m.isFocused())){m.focus();return}var r=a.getButton();if(r!==0){p&&m.moveCursorToPosition(k),r==2&&(m.textInput.onContextMenu({x:a.clientX,y:a.clientY},p),d.capture(m.container,function(){},m.textInput.onContextMenuClose));return}b||C(k);var s=c,t=f,u=(new Date).getTime(),v,w,x,y=function(a){s=d.getDocumentX(a),t=d.getDocumentY(a)},z=function(a){clearInterval(F),q==g?C(k):q==i&&A(a),n.$clickSelection=null,q=g},A=function(a){e.removeCssClass(m.container,"ace_dragging"),m.session.removeMarker(x),m.$mouseHandler.$clickSelection||v||(m.moveCursorToPosition(k),m.selection.clearSelection(k.row,k.column));if(!v)return;if(w.contains(v.row,v.column)){v=null;return}m.clearSelection();if(a&&(a.ctrlKey||a.altKey))var b=m.session,c=b.insert(v,b.getTextRange(w));else var c=m.moveText(w,v);if(!c){v=null;return}m.selection.setSelectionRange(c)},B=function(){if(q==g){var a=l(c,f,s,t),b=(new Date).getTime();if(a>j){q=h;var d=m.renderer.screenToTextCoordinates(s,t);d.row=Math.max(0,Math.min(d.row,m.session.getLength()-1)),C(d)}else if(b-u>m.getDragDelay()){q=i,w=m.getSelectionRange();var k=m.getSelectionStyle();x=m.session.addMarker(w,"ace_selection",k),m.clearSelection(),e.addCssClass(m.container,"ace_dragging")}}q==i?E():q==h&&D()},D=function(){var a,b=m.renderer.screenToTextCoordinates(s,t);b.row=Math.max(0,Math.min(b.row,m.session.getLength()-1)),n.$clickSelection?n.$clickSelection.contains(b.row,b.column)?m.selection.setSelectionRange(n.$clickSelection):(n.$clickSelection.compare(b.row,b.column)==-1?a=n.$clickSelection.end:a=n.$clickSelection.start,m.selection.setSelectionAnchor(a.row,a.column),m.selection.selectToPosition(b)):m.selection.selectToPosition(b),m.renderer.scrollCursorIntoView()},E=function(){v=m.renderer.screenToTextCoordinates(s,t),v.row=Math.max(0,Math.min(v.row,m.session.getLength()-1)),m.moveCursorToPosition(v)};d.capture(m.container,y,z);var F=setInterval(B,20);return a.preventDefault()},this.onDoubleClick=function(a){var b=a.getDocumentPosition(),c=this.editor;c.moveCursorToPosition(b),c.selection.selectWord(),this.$clickSelection=c.getSelectionRange()},this.onTripleClick=function(a){var b=a.getDocumentPosition(),c=this.editor;c.moveCursorToPosition(b),c.selection.selectLine(),this.$clickSelection=c.getSelectionRange()},this.onQuadClick=function(a){var b=this.editor;b.selectAll(),this.$clickSelection=b.getSelectionRange()},this.onScroll=function(a){var b=this.editor;b.renderer.scrollBy(a.wheelX*a.speed,a.wheelY*a.speed);if(b.renderer.isScrollableBy(a.wheelX*a.speed,a.wheelY*a.speed))return a.preventDefault()}})).call(k.prototype),b.DefaultHandlers=k}),define("ace/lib/browser_focus",["require","exports","module","ace/lib/oop","ace/lib/event","ace/lib/event_emitter"],function(a,b,c){"use strict";var d=a("./oop"),e=a("./event"),f=a("./event_emitter").EventEmitter,g=function(a){a=a||window,this.lastFocus=(new Date).getTime(),this._isFocused=!0;var b=this;"onfocusin"in a.document?(e.addListener(a.document,"focusin",function(a){b._setFocused(!0)}),e.addListener(a.document,"focusout",function(a){b._setFocused(!!a.toElement)})):(e.addListener(a,"blur",function(a){b._setFocused(!1)}),e.addListener(a,"focus",function(a){b._setFocused(!0)}))};((function(){d.implement(this,f),this.isFocused=function(){return this._isFocused},this._setFocused=function(a){if(this._isFocused==a)return;a&&(this.lastFocus=(new Date).getTime()),this._isFocused=a,this._emit("changeFocus")}})).call(g.prototype),b.BrowserFocus=g}),define("ace/lib/event_emitter",["require","exports","module"],function(a,b,c){"use strict";var d={};d._emit=d._dispatchEvent=function(a,b){this._eventRegistry=this._eventRegistry||{},this._defaultHandlers=this._defaultHandlers||{};var c=this._eventRegistry[a]||[],d=this._defaultHandlers[a];if(!c.length&&!d)return;b=b||{},b.type=a,b.stopPropagation||(b.stopPropagation=function(){this.propagationStopped=!0}),b.preventDefault||(b.preventDefault=function(){this.defaultPrevented=!0});for(var e=0;e<c.length;e++){c[e](b);if(b.propagationStopped)break}d&&!b.defaultPrevented&&d(b)},d.setDefaultHandler=function(a,b){this._defaultHandlers=this._defaultHandlers||{};if(this._defaultHandlers[a])throw new Error("The default handler for '"+a+"' is already set");this._defaultHandlers[a]=b},d.on=d.addEventListener=function(a,b){this._eventRegistry=this._eventRegistry||{};var c=this._eventRegistry[a];if(!c)var c=this._eventRegistry[a]=[];c.indexOf(b)==-1&&c.push(b)},d.removeListener=d.removeEventListener=function(a,b){this._eventRegistry=this._eventRegistry||{};var c=this._eventRegistry[a];if(!c)return;var d=c.indexOf(b);d!==-1&&c.splice(d,1)},d.removeAllListeners=function(a){this._eventRegistry&&(this._eventRegistry[a]=[])},b.EventEmitter=d}),define("ace/mouse/default_gutter_handler",["require","exports","module"],function(a,b,c){function d(a){a.setDefaultHandler("gutterclick",function(b){var c=b.getDocumentPosition().row,d=a.session.selection;d.moveCursorTo(c,0),d.selectLine()})}"use strict",b.GutterHandler=d}),define("ace/mouse/mouse_event",["require","exports","module","ace/lib/event"],function(a,b,c){"use strict";var d=a("../lib/event"),e=b.MouseEvent=function(a,b){this.domEvent=a,this.editor=b,this.pageX=d.getDocumentX(a),this.pageY=d.getDocumentY(a),this.clientX=a.clientX,this.clientY=a.clientY,this.$pos=null,this.$inSelection=null,this.propagationStopped=!1,this.defaultPrevented=!1};((function(){this.stopPropagation=function(){d.stopPropagation(this.domEvent),this.propagationStopped=!0},this.preventDefault=function(){d.preventDefault(this.domEvent),this.defaultPrevented=!0},this.stop=function(){this.stopPropagation(),this.preventDefault()},this.getDocumentPosition=function(){if(this.$pos)return this.$pos;var a=d.getDocumentX(this.domEvent),b=d.getDocumentY(this.domEvent);return this.$pos=this.editor.renderer.screenToTextCoordinates(a,b),this.$pos.row=Math.max(0,Math.min(this.$pos.row,this.editor.session.getLength()-1)),this.$pos},this.inSelection=function(){if(this.$inSelection!==null)return this.$inSelection;var a=this.editor;if(a.getReadOnly())this.$inSelection=!1;else{var b=a.getSelectionRange();if(b.isEmpty())this.$inSelection=!1;else{var c=this.getDocumentPosition();this.$inSelection=b.contains(c.row,c.column)}}return this.$inSelection},this.getButton=function(){return d.getButton(this.domEvent)},this.getShiftKey=function(){return this.domEvent.shiftKey},this.getAccelKey=function(){return this.domEvent.ctrlKey||this.domEvent.metaKey}})).call(e.prototype)}),define("ace/mouse/fold_handler",["require","exports","module"],function(a,b,c){function d(a){a.on("click",function(b){var c=b.getDocumentPosition(),d=a.session,e=d.getFoldAt(c.row,c.column,1);e&&(b.getAccelKey()?d.removeFold(e):d.expandFold(e),b.stop())}),a.on("gutterclick",function(b){if(b.domEvent.target.className.indexOf("ace_fold-widget")!=-1){var c=b.getDocumentPosition().row;a.session.onFoldWidgetClick(c,b.domEvent),b.stop()}})}"use strict",b.FoldHandler=d}),define("ace/keyboard/keybinding",["require","exports","module","ace/lib/keys","ace/lib/event","ace/commands/default_commands"],function(a,b,c){"use strict";var d=a("../lib/keys"),e=a("../lib/event");a("../commands/default_commands");var f=function(a){this.$editor=a,this.$data={},this.$handlers=[this]};((function(){this.setKeyboardHandler=function(a){if(this.$handlers[this.$handlers.length-1]==a)return;this.$data={},this.$handlers=a?[this,a]:[this]},this.addKeyboardHandler=function(a){this.removeKeyboardHandler(a),this.$handlers.push(a)},this.removeKeyboardHandler=function(a){var b=this.$handlers.indexOf(a);return b==-1?!1:(this.$handlers.splice(b,1),!0)},this.getKeyboardHandler=function(){return this.$handlers[this.$handlers.length-1]},this.$callKeyboardHandlers=function(a,b,c,d){var f;for(var g=this.$handlers.length;g--;){f=this.$handlers[g].handleKeyboard(this.$data,a,b,c,d);if(f&&f.command)break}if(!f||!f.command)return!1;var h=!1,i=this.$editor.commands;return f.command!="null"?h=i.exec(f.command,this.$editor,f.args):h=!0,h&&d&&e.stopEvent(d),h},this.handleKeyboard=function(a,b,c){return{command:this.$editor.commands.findKeyCommand(b,c)}},this.onCommandKey=function(a,b,c){var e=d.keyCodeToString(c);this.$callKeyboardHandlers(b,e,c,a)},this.onTextInput=function(a,b){var c=!1;!b&&a.length==1&&(c=this.$callKeyboardHandlers(0,a)),c||this.$editor.commands.exec("insertstring",this.$editor,a)}})).call(f.prototype),b.KeyBinding=f}),define("ace/commands/default_commands",["require","exports","module","ace/lib/lang"],function(a,b,c){function e(a,b){return{win:a,mac:b}}"use strict";var d=a("../lib/lang");b.commands=[{name:"selectall",bindKey:e("Ctrl-A","Command-A"),exec:function(a){a.selectAll()},readOnly:!0},{name:"centerselection",bindKey:e(null,"Ctrl-L"),exec:function(a){a.centerSelection()},readOnly:!0},{name:"gotoline",bindKey:e("Ctrl-L","Command-L"),exec:function(a){var b=parseInt(prompt("Enter line number:"),10);isNaN(b)||a.gotoLine(b)},readOnly:!0},{name:"fold",bindKey:e("Alt-L","Alt-L"),exec:function(a){a.session.toggleFold(!1)},readOnly:!0},{name:"unfold",bindKey:e("Alt-Shift-L","Alt-Shift-L"),exec:function(a){a.session.toggleFold(!0)},readOnly:!0},{name:"foldall",bindKey:e("Alt-0","Alt-0"),exec:function(a){a.session.foldAll()},readOnly:!0},{name:"unfoldall",bindKey:e("Alt-Shift-0","Alt-Shift-0"),exec:function(a){a.session.unfold()},readOnly:!0},{name:"findnext",bindKey:e("Ctrl-K","Command-G"),exec:function(a){a.findNext()},readOnly:!0},{name:"findprevious",bindKey:e("Ctrl-Shift-K","Command-Shift-G"),exec:function(a){a.findPrevious()},readOnly:!0},{name:"find",bindKey:e("Ctrl-F","Command-F"),exec:function(a){var b=prompt("Find:",a.getCopyText());a.find(b)},readOnly:!0},{name:"overwrite",bindKey:e("Insert","Insert"),exec:function(a){a.toggleOverwrite()},readOnly:!0},{name:"selecttostart",bindKey:e("Ctrl-Shift-Home|Alt-Shift-Up","Command-Shift-Up"),exec:function(a){a.getSelection().selectFileStart()},readOnly:!0},{name:"gotostart",bindKey:e("Ctrl-Home|Ctrl-Up","Command-Home|Command-Up"),exec:function(a){a.navigateFileStart()},readOnly:!0},{name:"selectup",bindKey:e("Shift-Up","Shift-Up"),exec:function(a){a.getSelection().selectUp()},readOnly:!0},{name:"golineup",bindKey:e("Up","Up|Ctrl-P"),exec:function(a,b){a.navigateUp(b.times)},readOnly:!0},{name:"selecttoend",bindKey:e("Ctrl-Shift-End|Alt-Shift-Down","Command-Shift-Down"),exec:function(a){a.getSelection().selectFileEnd()},readOnly:!0},{name:"gotoend",bindKey:e("Ctrl-End|Ctrl-Down","Command-End|Command-Down"),exec:function(a){a.navigateFileEnd()},readOnly:!0},{name:"selectdown",bindKey:e("Shift-Down","Shift-Down"),exec:function(a){a.getSelection().selectDown()},readOnly:!0},{name:"golinedown",bindKey:e("Down","Down|Ctrl-N"),exec:function(a,b){a.navigateDown(b.times)},readOnly:!0},{name:"selectwordleft",bindKey:e("Ctrl-Shift-Left","Option-Shift-Left"),exec:function(a){a.getSelection().selectWordLeft()},readOnly:!0},{name:"gotowordleft",bindKey:e("Ctrl-Left","Option-Left"),exec:function(a){a.navigateWordLeft()},readOnly:!0},{name:"selecttolinestart",bindKey:e("Alt-Shift-Left","Command-Shift-Left"),exec:function(a){a.getSelection().selectLineStart()},readOnly:!0},{name:"gotolinestart",bindKey:e("Alt-Left|Home","Command-Left|Home|Ctrl-A"),exec:function(a){a.navigateLineStart()},readOnly:!0},{name:"selectleft",bindKey:e("Shift-Left","Shift-Left"),exec:function(a){a.getSelection().selectLeft()},readOnly:!0},{name:"gotoleft",bindKey:e("Left","Left|Ctrl-B"),exec:function(a,b){a.navigateLeft(b.times)},readOnly:!0},{name:"selectwordright",bindKey:e("Ctrl-Shift-Right","Option-Shift-Right"),exec:function(a){a.getSelection().selectWordRight()},readOnly:!0},{name:"gotowordright",bindKey:e("Ctrl-Right","Option-Right"),exec:function(a){a.navigateWordRight()},readOnly:!0},{name:"selecttolineend",bindKey:e("Alt-Shift-Right","Command-Shift-Right"),exec:function(a){a.getSelection().selectLineEnd()},readOnly:!0},{name:"gotolineend",bindKey:e("Alt-Right|End","Command-Right|End|Ctrl-E"),exec:function(a){a.navigateLineEnd()},readOnly:!0},{name:"selectright",bindKey:e("Shift-Right","Shift-Right"),exec:function(a){a.getSelection().selectRight()},readOnly:!0},{name:"gotoright",bindKey:e("Right","Right|Ctrl-F"),exec:function(a,b){a.navigateRight(b.times)},readOnly:!0},{name:"selectpagedown",bindKey:e("Shift-PageDown","Shift-PageDown"),exec:function(a){a.selectPageDown()},readOnly:!0},{name:"pagedown",bindKey:e(null,"PageDown"),exec:function(a){a.scrollPageDown()},readOnly:!0},{name:"gotopagedown",bindKey:e("PageDown","Option-PageDown|Ctrl-V"),exec:function(a){a.gotoPageDown()},readOnly:!0},{name:"selectpageup",bindKey:e("Shift-PageUp","Shift-PageUp"),exec:function(a){a.selectPageUp()},readOnly:!0},{name:"pageup",bindKey:e(null,"PageUp"),exec:function(a){a.scrollPageUp()},readOnly:!0},{name:"gotopageup",bindKey:e("PageUp","Option-PageUp"),exec:function(a){a.gotoPageUp()},readOnly:!0},{name:"selectlinestart",bindKey:e("Shift-Home","Shift-Home"),exec:function(a){a.getSelection().selectLineStart()},readOnly:!0},{name:"selectlineend",bindKey:e("Shift-End","Shift-End"),exec:function(a){a.getSelection().selectLineEnd()},readOnly:!0},{name:"togglerecording",bindKey:e("Ctrl-Alt-E","Command-Option-E"),exec:function(a){a.commands.toggleRecording()},readOnly:!0},{name:"replaymacro",bindKey:e("Ctrl-Shift-E","Command-Shift-E"),exec:function(a){a.commands.replay(a)},readOnly:!0},{name:"removeline",bindKey:e("Ctrl-D","Command-D"),exec:function(a){a.removeLines()}},{name:"togglecomment",bindKey:e("Ctrl-7","Command-7"),exec:function(a){a.toggleCommentLines()}},{name:"replace",bindKey:e("Ctrl-R","Command-Option-F"),exec:function(a){var b=prompt("Find:",a.getCopyText());if(!b)return;var c=prompt("Replacement:");if(!c)return;a.replace(c,{needle:b})}},{name:"replaceall",bindKey:e("Ctrl-Shift-R","Command-Shift-Option-F"),exec:function(a){var b=prompt("Find:");if(!b)return;var c=prompt("Replacement:");if(!c)return;a.replaceAll(c,{needle:b})}},{name:"undo",bindKey:e("Ctrl-Z","Command-Z"),exec:function(a){a.undo()}},{name:"redo",bindKey:e("Ctrl-Shift-Z|Ctrl-Y","Command-Shift-Z|Command-Y"),exec:function(a){a.redo()}},{name:"copylinesup",bindKey:e("Ctrl-Alt-Up","Command-Option-Up"),exec:function(a){a.copyLinesUp()}},{name:"movelinesup",bindKey:e("Alt-Up","Option-Up"),exec:function(a){a.moveLinesUp()}},{name:"copylinesdown",bindKey:e("Ctrl-Alt-Down","Command-Option-Down"),exec:function(a){a.copyLinesDown()}},{name:"movelinesdown",bindKey:e("Alt-Down","Option-Down"),exec:function(a){a.moveLinesDown()}},{name:"del",bindKey:e("Delete","Delete|Ctrl-D"),exec:function(a){a.remove("right")}},{name:"backspace",bindKey:e("Ctrl-Backspace|Command-Backspace|Option-Backspace|Shift-Backspace|Backspace","Ctrl-Backspace|Command-Backspace|Shift-Backspace|Backspace|Ctrl-H"),exec:function(a){a.remove("left")}},{name:"removetolinestart",bindKey:e("Alt-Backspace","Option-Backspace"),exec:function(a){a.removeToLineStart()}},{name:"removetolineend",bindKey:e("Alt-Delete","Ctrl-K"),exec:function(a){a.removeToLineEnd()}},{name:"removewordleft",bindKey:e("Ctrl-Backspace","Alt-Backspace|Ctrl-Alt-Backspace"),exec:function(a){a.removeWordLeft()}},{name:"removewordright",bindKey:e("Ctrl-Delete","Alt-Delete"),exec:function(a){a.removeWordRight()}},{name:"outdent",bindKey:e("Shift-Tab","Shift-Tab"),exec:function(a){a.blockOutdent()}},{name:"indent",bindKey:e("Tab","Tab"),exec:function(a){a.indent()}},{name:"insertstring",exec:function(a,b){a.insert(b)}},{name:"inserttext",exec:function(a,b){a.insert(d.stringRepeat(b.text||"",b.times||1))}},{name:"splitline",bindKey:e(null,"Ctrl-O"),exec:function(a){a.splitLine()}},{name:"transposeletters",bindKey:e("Ctrl-T","Ctrl-T"),exec:function(a){a.transposeLetters()}},{name:"touppercase",bindKey:e("Ctrl-U","Ctrl-U"),exec:function(a){a.toUpperCase()}},{name:"tolowercase",bindKey:e("Ctrl-Shift-U","Ctrl-Shift-U"),exec:function(a){a.toLowerCase()}},{name:"jumptomatching",bindKey:e("Ctrl-Shift-P","Ctrl-Shift-P"),exec:function(a){a.jumpToMatching()}}]}),define("ace/edit_session",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/lib/event_emitter","ace/selection","ace/mode/text","ace/range","ace/document","ace/background_tokenizer","ace/edit_session/folding","ace/edit_session/bracket_match"],function(a,b,c){"use strict";var d=a("./lib/oop"),e=a("./lib/lang"),f=a("./lib/event_emitter").EventEmitter,g=a("./selection").Selection,h=a("./mode/text").Mode,i=a("./range").Range,j=a("./document").Document,k=a("./background_tokenizer").BackgroundTokenizer,l=function(a,b){this.$modified=!0,this.$breakpoints=[],this.$frontMarkers={},this.$backMarkers={},this.$markerId=1,this.$rowCache=[],this.$wrapData=[],this.$foldData=[],this.$undoSelect=!0,this.$foldData.toString=function(){var a="";return this.forEach(function(b){a+="\n"+b.toString()}),a},a instanceof j?this.setDocument(a):this.setDocument(new j(a)),this.selection=new g(this),b?this.setMode(b):this.setMode(new h)};((function(){function o(a){return a<4352?!1:a>=4352&&a<=4447||a>=4515&&a<=4519||a>=4602&&a<=4607||a>=9001&&a<=9002||a>=11904&&a<=11929||a>=11931&&a<=12019||a>=12032&&a<=12245||a>=12272&&a<=12283||a>=12288&&a<=12350||a>=12353&&a<=12438||a>=12441&&a<=12543||a>=12549&&a<=12589||a>=12593&&a<=12686||a>=12688&&a<=12730||a>=12736&&a<=12771||a>=12784&&a<=12830||a>=12832&&a<=12871||a>=12880&&a<=13054||a>=13056&&a<=19903||a>=19968&&a<=42124||a>=42128&&a<=42182||a>=43360&&a<=43388||a>=44032&&a<=55203||a>=55216&&a<=55238||a>=55243&&a<=55291||a>=63744&&a<=64255||a>=65040&&a<=65049||a>=65072&&a<=65106||a>=65108&&a<=65126||a>=65128&&a<=65131||a>=65281&&a<=65376||a>=65504&&a<=65510}d.implement(this,f),this.setDocument=function(a){if(this.doc)throw new Error("Document is already set");this.doc=a,a.on("change",this.onChange.bind(this)),this.on("changeFold",this.onChangeFold.bind(this)),this.bgTokenizer&&(this.bgTokenizer.setDocument(this.getDocument()),this.bgTokenizer.start(0))},this.getDocument=function(){return this.doc},this.$resetRowCache=function(a){if(a==0){this.$rowCache=[];return}var b=this.$rowCache;for(var c=0;c<b.length;c++)if(b[c].docRow>=a){b.splice(c,b.length);return}},this.onChangeFold=function(a){var b=a.data;this.$resetRowCache(b.start.row)},this.onChange=function(a){var b=a.data;this.$modified=!0,this.$resetRowCache(b.range.start.row);var c=this.$updateInternalDataOnChange(a);!this.$fromUndo&&this.$undoManager&&!b.ignore&&(this.$deltasDoc.push(b),c&&c.length!=0&&this.$deltasFold.push({action:"removeFolds",folds:c}),this.$informUndoManager.schedule()),this.bgTokenizer.start(b.range.start.row),this._emit("change",a)},this.setValue=function(a){this.doc.setValue(a),this.selection.moveCursorTo(0,0),this.selection.clearSelection(),this.$resetRowCache(0),this.$deltas=[],this.$deltasDoc=[],this.$deltasFold=[],this.getUndoManager().reset()},this.getValue=this.toString=function(){return this.doc.getValue()},this.getSelection=function(){return this.selection},this.getState=function(a){return this.bgTokenizer.getState(a)},this.getTokens=function(a,b){return this.bgTokenizer.getTokens(a,b)},this.getTokenAt=function(a,b){var c=this.bgTokenizer.getTokens(a,a)[0].tokens,d,e=0;if(b==null)f=c.length-1,e=this.getLine(a).length;else for(var f=0;f<c.length;f++){e+=c[f].value.length;if(e>=b)break}return d=c[f],d?(d.index=f,d.start=e-d.value.length,d):null},this.setUndoManager=function(a){this.$undoManager=a,this.$resetRowCache(0),this.$deltas=[],this.$deltasDoc=[],this.$deltasFold=[],this.$informUndoManager&&this.$informUndoManager.cancel();if(a){var b=this;this.$syncInformUndoManager=function(){b.$informUndoManager.cancel(),b.$deltasFold.length&&(b.$deltas.push({group:"fold",deltas:b.$deltasFold}),b.$deltasFold=[]),b.$deltasDoc.length&&(b.$deltas.push({group:"doc",deltas:b.$deltasDoc}),b.$deltasDoc=[]),b.$deltas.length>0&&a.execute({action:"aceupdate",args:[b.$deltas,b]}),b.$deltas=[]},this.$informUndoManager=e.deferredCall(this.$syncInformUndoManager)}},this.$defaultUndoManager={undo:function(){},redo:function(){},reset:function(){}},this.getUndoManager=function(){return this.$undoManager||this.$defaultUndoManager},this.getTabString=function(){return this.getUseSoftTabs()?e.stringRepeat(" ",this.getTabSize()):"\t"},this.$useSoftTabs=!0,this.setUseSoftTabs=function(a){if(this.$useSoftTabs===a)return;this.$useSoftTabs=a},this.getUseSoftTabs=function(){return this.$useSoftTabs},this.$tabSize=4,this.setTabSize=function(a){if(isNaN(a)||this.$tabSize===a)return;this.$modified=!0,this.$tabSize=a,this._emit("changeTabSize")},this.getTabSize=function(){return this.$tabSize},this.isTabStop=function(a){return this.$useSoftTabs&&a.column%this.$tabSize==0},this.$overwrite=!1,this.setOverwrite=function(a){if(this.$overwrite==a)return;this.$overwrite=a,this._emit("changeOverwrite")},this.getOverwrite=function(){return this.$overwrite},this.toggleOverwrite=function(){this.setOverwrite(!this.$overwrite)},this.getBreakpoints=function(){return this.$breakpoints},this.setBreakpoints=function(a){this.$breakpoints=[];for(var b=0;b<a.length;b++)this.$breakpoints[a[b]]=!0;this._emit("changeBreakpoint",{})},this.clearBreakpoints=function(){this.$breakpoints=[],this._emit("changeBreakpoint",{})},this.setBreakpoint=function(a){this.$breakpoints[a]=!0,this._emit("changeBreakpoint",{})},this.clearBreakpoint=function(a){delete this.$breakpoints[a],this._emit("changeBreakpoint",{})},this.getBreakpoints=function(){return this.$breakpoints},this.addMarker=function(a,b,c,d){var e=this.$markerId++,f={range:a,type:c||"line",renderer:typeof c=="function"?c:null,clazz:b,inFront:!!d};return d?(this.$frontMarkers[e]=f,this._emit("changeFrontMarker")):(this.$backMarkers[e]=f,this._emit("changeBackMarker")),e},this.removeMarker=function(a){var b=this.$frontMarkers[a]||this.$backMarkers[a];if(!b)return;var c=b.inFront?this.$frontMarkers:this.$backMarkers;b&&(delete c[a],this._emit(b.inFront?"changeFrontMarker":"changeBackMarker"))},this.getMarkers=function(a){return a?this.$frontMarkers:this.$backMarkers},this.setAnnotations=function(a){this.$annotations={};for(var b=0;b<a.length;b++){var c=a[b],d=c.row;this.$annotations[d]?this.$annotations[d].push(c):this.$annotations[d]=[c]}this._emit("changeAnnotation",{})},this.getAnnotations=function(){return this.$annotations||{}},this.clearAnnotations=function(){this.$annotations={},this._emit("changeAnnotation",{})},this.$detectNewLine=function(a){var b=a.match(/^.*?(\r?\n)/m);b?this.$autoNewLine=b[1]:this.$autoNewLine="\n"},this.getWordRange=function(a,b){var c=this.getLine(a),d=!1;b>0&&(d=!!c.charAt(b-1).match(this.tokenRe)),d||(d=!!c.charAt(b).match(this.tokenRe));var e=d?this.tokenRe:this.nonTokenRe,f=b;if(f>0){do f--;while(f>=0&&c.charAt(f).match(e));f++}var g=b;while(g<c.length&&c.charAt(g).match(e))g++;return new i(a,f,a,g)},this.getAWordRange=function(a,b){var c=this.getWordRange(a,b),d=this.getLine(c.end.row);while(d.charAt(c.end.column).match(/[ \t]/))c.end.column+=1;return c},this.setNewLineMode=function(a){this.doc.setNewLineMode(a)},this.getNewLineMode=function(){return this.doc.getNewLineMode()},this.$useWorker=!0,this.setUseWorker=function(a){if(this.$useWorker==a)return;this.$useWorker=a,this.$stopWorker(),a&&this.$startWorker()},this.getUseWorker=function(){return this.$useWorker},this.onReloadTokenizer=function(a){var b=a.data;this.bgTokenizer.start(b.first),this._emit("tokenizerUpdate",a)},this.$mode=null,this.setMode=function(a){if(this.$mode===a)return;this.$mode=a,this.$stopWorker(),this.$useWorker&&this.$startWorker();var b=a.getTokenizer();if(b.addEventListener!==undefined){var c=this.onReloadTokenizer.bind(this);b.addEventListener("update",c)}if(!this.bgTokenizer){this.bgTokenizer=new k(b);var d=this;this.bgTokenizer.addEventListener("update",function(a){d._emit("tokenizerUpdate",a)})}else this.bgTokenizer.setTokenizer(b);this.bgTokenizer.setDocument(this.getDocument()),this.bgTokenizer.start(0),this.tokenRe=a.tokenRe,this.nonTokenRe=a.nonTokenRe,this.$setFolding(a.foldingRules),this._emit("changeMode")},this.$stopWorker=function(){this.$worker&&this.$worker.terminate(),this.$worker=null},this.$startWorker=function(){if(typeof Worker!="undefined"&&!a.noWorker)try{this.$worker=this.$mode.createWorker(this)}catch(b){console.log("Could not load worker"),console.log(b),this.$worker=null}else this.$worker=null},this.getMode=function(){return this.$mode},this.$scrollTop=0,this.setScrollTop=function(a){a=Math.round(Math.max(0,a));if(this.$scrollTop===a)return;this.$scrollTop=a,this._emit("changeScrollTop",a)},this.getScrollTop=function(){return this.$scrollTop},this.$scrollLeft=0,this.setScrollLeft=function(a){a=Math.round(Math.max(0,a));if(this.$scrollLeft===a)return;this.$scrollLeft=a,this._emit("changeScrollLeft",a)},this.getScrollLeft=function(){return this.$scrollLeft},this.getWidth=function(){return this.$computeWidth(),this.width},this.getScreenWidth=function(){return this.$computeWidth(),this.screenWidth},this.$computeWidth=function(a){if(this.$modified||a){this.$modified=!1;var b=this.doc.getAllLines(),c=0,d=0;for(var e=0;e<b.length;e++){var f=this.getFoldLine(e),g,h;g=b[e];if(f){var i=f.range.end;g=this.getFoldDisplayLine(f),e=i.row}h=g.length,c=Math.max(c,h),this.$useWrapMode||(d=Math.max(d,this.$getStringScreenWidth(g)[0]))}this.width=c,this.$useWrapMode?this.screenWidth=this.$wrapLimit:this.screenWidth=d}},this.getLine=function(a){return this.doc.getLine(a)},this.getLines=function(a,b){return this.doc.getLines(a,b)},this.getLength=function(){return this.doc.getLength()},this.getTextRange=function(a){return this.doc.getTextRange(a)},this.insert=function(a,b){return this.doc.insert(a,b)},this.remove=function(a){return this.doc.remove(a)},this.undoChanges=function(a,b){if(!a.length)return;this.$fromUndo=!0;var c=null;for(var d=a.length-1;d!=-1;d--){var e=a[d];e.group=="doc"?(this.doc.revertDeltas(e.deltas),c=this.$getUndoSelection(e.deltas,!0,c)):e.deltas.forEach(function(a){this.addFolds(a.folds)},this)}return this.$fromUndo=!1,c&&this.$undoSelect&&!b&&this.selection.setSelectionRange(c),c},this.redoChanges=function(a,b){if(!a.length)return;this.$fromUndo=!0;var c=null;for(var d=0;d<a.length;d++){var e=a[d];e.group=="doc"&&(this.doc.applyDeltas(e.deltas),c=this.$getUndoSelection(e.deltas,!1,c))}return this.$fromUndo=!1,c&&this.$undoSelect&&!b&&this.selection.setSelectionRange(c),c},this.setUndoSelect=function(a){this.$undoSelect=a},this.$getUndoSelection=function(a,b,c){function d(a){var c=a.action=="insertText"||a.action=="insertLines";return b?!c:c}var e=a[0],f,g,h=!1;d(e)?(f=e.range.clone(),h=!0):(f=i.fromPoints(e.range.start,e.range.start),h=!1);for(var j=1;j<a.length;j++)e=a[j],d(e)?(g=e.range.start,f.compare(g.row,g.column)==-1&&f.setStart(e.range.start),g=e.range.end,f.compare(g.row,g.column)==1&&f.setEnd(e.range.end),h=!0):(g=e.range.start,f.compare(g.row,g.column)==-1&&(f=i.fromPoints(e.range.start,e.range.start)),h=!1);if(c!=null){var k=c.compareRange(f);k==1?f.setStart(c.start):k==-1&&f.setEnd(c.end)}return f},this.replace=function(a,b){return this.doc.replace(a,b)},this.moveText=function(a,b){var c=this.getTextRange(a);this.remove(a);var d=b.row,e=b.column;!a.isMultiLine()&&a.start.row==d&&a.end.column<e&&(e-=c.length);if(a.isMultiLine()&&a.end.row<d){var f=this.doc.$split(c);d-=f.length-1}var g=d+a.end.row-a.start.row,h=a.isMultiLine()?a.end.column:e+a.end.column-a.start.column,j=new i(d,e,g,h);return this.insert(j.start,c),j},this.indentRows=function(a,b,c){c=c.replace(/\t/g,this.getTabString());for(var d=a;d<=b;d++)this.insert({row:d,column:0},c)},this.outdentRows=function(a){var b=a.collapseRows(),c=new i(0,0,0,0),d=this.getTabSize();for(var e=b.start.row;e<=b.end.row;++e){var f=this.getLine(e);c.start.row=e,c.end.row=e;for(var g=0;g<d;++g)if(f.charAt(g)!=" ")break;g<d&&f.charAt(g)=="\t"?(c.start.column=g,c.end.column=g+1):(c.start.column=0,c.end.column=g),this.remove(c)}},this.moveLinesUp=function(a,b){if(a<=0)return 0;var c=this.doc.removeLines(a,b);return this.doc.insertLines(a-1,c),-1},this.moveLinesDown=function(a,b){if(b>=this.doc.getLength()-1)return 0;var c=this.doc.removeLines(a,b);return this.doc.insertLines(a+1,c),1},this.duplicateLines=function(a,b){var a=this.$clipRowToDocument(a),b=this.$clipRowToDocument(b),c=this.getLines(a,b);this.doc.insertLines(a,c);var d=b-a+1;return d},this.$clipRowToDocument=function(a){return Math.max(0,Math.min(a,this.doc.getLength()-1))},this.$clipColumnToRow=function(a,b){return b<0?0:Math.min(this.doc.getLine(a).length,b)},this.$clipPositionToDocument=function(a,b){b=Math.max(0,b);if(a<0)a=0,b=0;else{var c=this.doc.getLength();a>=c?(a=c-1,b=this.doc.getLine(c-1).length):b=Math.min(this.doc.getLine(a).length,b)}return{row:a,column:b}},this.$clipRangeToDocument=function(a){a.start.row<0?(a.start.row=0,a.start.column=0):a.start.column=this.$clipColumnToRow(a.start.row,a.start.column);var b=this.doc.getLength()-1;return a.end.row>b?(a.end.row=b,a.end.column=this.doc.getLine(b).length):a.end.column=this.$clipColumnToRow(a.end.row,a.end.column),a},this.$wrapLimit=80,this.$useWrapMode=!1,this.$wrapLimitRange={min:null,max:null},this.setUseWrapMode=function(a){if(a!=this.$useWrapMode){this.$useWrapMode=a,this.$modified=!0,this.$resetRowCache(0);if(a){var b=this.getLength();this.$wrapData=[];for(var c=0;c<b;c++)this.$wrapData.push([]);this.$updateWrapData(0,b-1)}this._emit("changeWrapMode")}},this.getUseWrapMode=function(){return this.$useWrapMode},this.setWrapLimitRange=function(a,b){if(this.$wrapLimitRange.min!==a||this.$wrapLimitRange.max!==b)this.$wrapLimitRange.min=a,this.$wrapLimitRange.max=b,this.$modified=!0,this._emit("changeWrapMode")},this.adjustWrapLimit=function(a){var b=this.$constrainWrapLimit(a);return b!=this.$wrapLimit&&b>0?(this.$wrapLimit=b,this.$modified=!0,this.$useWrapMode&&(this.$updateWrapData(0,this.getLength()-1),this.$resetRowCache(0),this._emit("changeWrapLimit")),!0):!1},this.$constrainWrapLimit=function(a){var b=this.$wrapLimitRange.min;b&&(a=Math.max(b,a));var c=this.$wrapLimitRange.max;return c&&(a=Math.min(c,a)),Math.max(1,a)},this.getWrapLimit=function(){return this.$wrapLimit},this.getWrapLimitRange=function(){return{min:this.$wrapLimitRange.min,max:this.$wrapLimitRange.max}},this.$updateInternalDataOnChange=function(a){var b=this.$useWrapMode,c,d=a.data.action,e=a.data.range.start.row,f=a.data.range.end.row,g=a.data.range.start,h=a.data.range.end,i=null;d.indexOf("Lines")!=-1?(d=="insertLines"?f=e+a.data.lines.length:f=e,c=a.data.lines?a.data.lines.length:f-e):c=f-e;if(c!=0)if(d.indexOf("remove")!=-1){b&&this.$wrapData.splice(e,c);var j=this.$foldData;i=this.getFoldsInRange(a.data.range),this.removeFolds(i);var k=this.getFoldLine(h.row),l=0;if(k){k.addRemoveChars(h.row,h.column,g.column-h.column),k.shiftRow(-c);var m=this.getFoldLine(e);m&&m!==k&&(m.merge(k),k=m),l=j.indexOf(k)+1}for(l;l<j.length;l++){var k=j[l];k.start.row>=h.row&&k.shiftRow(-c)}f=e}else{var n;if(b){n=[e,0];for(var o=0;o<c;o++)n.push([]);this.$wrapData.splice.apply(this.$wrapData,n)}var j=this.$foldData,k=this.getFoldLine(e),l=0;if(k){var p=k.range.compareInside(g.row,g.column);p==0?(k=k.split(g.row,g.column),k.shiftRow(c),k.addRemoveChars(f,0,h.column-g.column)):p==-1&&(k.addRemoveChars(e,0,h.column-g.column),k.shiftRow(c)),l=j.indexOf(k)+1}for(l;l<j.length;l++){var k=j[l];k.start.row>=e&&k.shiftRow(c)}}else{c=Math.abs(a.data.range.start.column-a.data.range.end.column),d.indexOf("remove")!=-1&&(i=this.getFoldsInRange(a.data.range),this.removeFolds(i),c=-c);var k=this.getFoldLine(e);k&&k.addRemoveChars(e,g.column,c)}return b&&this.$wrapData.length!=this.doc.getLength()&&console.error("doc.getLength() and $wrapData.length have to be the same!"),b&&this.$updateWrapData(e,f),i},this.$updateWrapData=function(a,b){var c=this.doc.getAllLines(),d=this.getTabSize(),f=this.$wrapData,i=this.$wrapLimit,j,k,m=a;b=Math.min(b,c.length-1);while(m<=b){k=this.getFoldLine(m,k);if(!k)j=this.$getDisplayTokens(e.stringTrimRight(c[m])),f[m]=this.$computeWrapSplits(j,i,d),m++;else{j=[],k.walk(function(a,b,d,e){var f;if(a){f=this.$getDisplayTokens(a,j.length),f[0]=g;for(var i=1;i<f.length;i++)f[i]=h}else f=this.$getDisplayTokens(c[b].substring(e,d),j.length);j=j.concat(f)}.bind(this),k.end.row,c[k.end.row].length+1);while(j.length!=0&&j[j.length-1]>=l)j.pop();f[k.start.row]=this.$computeWrapSplits(j,i,d),m=k.end.row+1}}};var b=1,c=2,g=3,h=4,j=9,l=10,m=11,n=12;this.$computeWrapSplits=function(a,b){function i(b){var d=a.slice(e,b),g=d.length;d.join("").replace(/12/g,function(){g-=1}).replace(/2/g,function(){g-=1}),f+=g,c.push(f),e=b}if(a.length==0)return[];var c=[],d=a.length,e=0,f=0;while(d-e>b){var k=e+b;if(a[k]>=l){while(a[k]>=l)k++;i(k);continue}if(a[k]==g||a[k]==h){for(k;k!=e-1;k--)if(a[k]==g)break;if(k>e){i(k);continue}k=e+b;for(k;k<a.length;k++)if(a[k]!=h)break;if(k==a.length)break;i(k);continue}var m=Math.max(k-10,e-1);while(k>m&&a[k]<g)k--;while(k>m&&a[k]==j)k--;if(k>m){i(++k);continue}k=e+b,i(k)}return c},this.$getDisplayTokens=function(a,d){var e=[],f;d=d||0;for(var g=0;g<a.length;g++){var h=a.charCodeAt(g);if(h==9){f=this.getScreenTabSize(e.length+d),e.push(m);for(var i=1;i<f;i++)e.push(n)}else h==32?e.push(l):h>39&&h<48||h>57&&h<64?e.push(j):h>=4352&&o(h)?e.push(b,c):e.push(b)}return e},this.$getStringScreenWidth=function(a,b,c){if(b==0)return[0,0];b==null&&(b=c+a.length*Math.max(this.getTabSize(),2)),c=c||0;var d,e;for(e=0;e<a.length;e++){d=a.charCodeAt(e),d==9?c+=this.getScreenTabSize(c):d>=4352&&o(d)?c+=2:c+=1;if(c>b)break}return[c,e]},this.getRowLength=function(a){return!this.$useWrapMode||!this.$wrapData[a]?1:this.$wrapData[a].length+1},this.getRowHeight=function(a,b){return this.getRowLength(b)*a.lineHeight},this.getScreenLastRowColumn=function(a){return this.documentToScreenColumn(a,this.doc.getLine(a).length)},this.getDocumentLastRowColumn=function(a,b){var c=this.documentToScreenRow(a,b);return this.getScreenLastRowColumn(c)},this.getDocumentLastRowColumnPosition=function(a,b){var c=this.documentToScreenRow(a,b);return this.screenToDocumentPosition(c,Number.MAX_VALUE/10)},this.getRowSplitData=function(a){return this.$useWrapMode?this.$wrapData[a]:undefined},this.getScreenTabSize=function(a){return this.$tabSize-a%this.$tabSize},this.screenToDocumentRow=function(a,b){return this.screenToDocumentPosition(a,b).row},this.screenToDocumentColumn=function(a,b){return this.screenToDocumentPosition(a,b).column},this.screenToDocumentPosition=function(a,b){if(a<0)return{row:0,column:0};var c,d=0,e=0,f,g=0,h=0,i=this.$rowCache;for(var j=0;j<i.length;j++)if(i[j].screenRow<a)g=i[j].screenRow,d=i[j].docRow;else break;var k=!i.length||j==i.length,l=this.getLength()-1,m=this.getNextFoldLine(d),n=m?m.start.row:Infinity;while(g<=a){h=this.getRowLength(d);if(g+h-1>=a||d>=l)break;g+=h,d++,d>n&&(d=m.end.row+1,m=this.getNextFoldLine(d,m),n=m?m.start.row:Infinity),k&&i.push({docRow:d,screenRow:g})}if(m&&m.start.row<=d)c=this.getFoldDisplayLine(m),d=m.start.row;else{if(g+h<=a||d>l)return{row:l,column:this.getLine(l).length};c=this.getLine(d),m=null}if(this.$useWrapMode){var o=this.$wrapData[d];o&&(f=o[a-g],a>g&&o.length&&(e=o[a-g-1]||o[o.length-1],c=c.substring(e)))}return e+=this.$getStringScreenWidth(c,b)[1],this.$useWrapMode?e>=f&&(e=f-1):e=Math.min(e,c.length),m?m.idxToPosition(e):{row:d,column:e}},this.documentToScreenPosition=function(a,b){if(typeof b=="undefined")var c=this.$clipPositionToDocument(a.row,a.column);else c=this.$clipPositionToDocument(a,b);a=c.row,b=c.column;var d;if(this.$useWrapMode){d=this.$wrapData;if(a>d.length-1)return{row:this.getScreenLength(),column:d.length==0?0:d[d.length-1].length-1}}var e=0,f=null,g=null;g=this.getFoldAt(a,b,1),g&&(a=g.start.row,b=g.start.column);var h,i=0,j=this.$rowCache;for(var k=0;k<j.length;k++)if(j[k].docRow<a)e=j[k].screenRow,i=j[k].docRow;else break;var l=!j.length||k==j.length,m=this.getNextFoldLine(i),n=m?m.start.row:Infinity;while(i<a){if(i>=n){h=m.end.row+1;if(h>a)break;m=this.getNextFoldLine(h,m),n=m?m.start.row:Infinity}else h=i+1;e+=this.getRowLength(i),i=h,l&&j.push({docRow:i,screenRow:e})}var o="";m&&i>=n?(o=this.getFoldDisplayLine(m,a,b),f=m.start.row):(o=this.getLine(a).substring(0,b),f=a);if(this.$useWrapMode){var p=d[f],q=0;while(o.length>=p[q])e++,q++;o=o.substring(p[q-1]||0,o.length)}return{row:e,column:this.$getStringScreenWidth(o)[0]}},this.documentToScreenColumn=function(a,b){return this.documentToScreenPosition(a,b).column},this.documentToScreenRow=function(a,b){return this.documentToScreenPosition(a,b).row},this.getScreenLength=function(){var a=0,b=null;if(!this.$useWrapMode){a=this.getLength();var c=this.$foldData;for(var d=0;d<c.length;d++)b=c[d],a-=b.end.row-b.start.row}else{var e=this.$wrapData.length,f=0,d=0,b=this.$foldData[d++],g=b?b.start.row:Infinity;while(f<e)a+=this.$wrapData[f].length+1,f++,f>g&&(f=b.end.row+1,b=this.$foldData[d++],g=b?b.start.row:Infinity)}return a}})).call(l.prototype),a("./edit_session/folding").Folding.call(l.prototype),a("./edit_session/bracket_match").BracketMatch.call(l.prototype),b.EditSession=l}),define("ace/selection",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/lib/event_emitter","ace/range"],function(a,b,c){"use strict";var d=a("./lib/oop"),e=a("./lib/lang"),f=a("./lib/event_emitter").EventEmitter,g=a("./range").Range,h=function(a){this.session=a,this.doc=a.getDocument(),this.clearSelection(),this.selectionLead=this.doc.createAnchor(0,0),this.selectionAnchor=this.doc.createAnchor(0,0);var b=this;this.selectionLead.on("change",function(a){b._emit("changeCursor"),b.$isEmpty||b._emit("changeSelection"),!b.$preventUpdateDesiredColumnOnChange&&a.old.column!=a.value.column&&b.$updateDesiredColumn()}),this.selectionAnchor.on("change",function(){b.$isEmpty||b._emit("changeSelection")})};((function(){d.implement(this,f),this.isEmpty=function(){return this.$isEmpty||this.selectionAnchor.row==this.selectionLead.row&&this.selectionAnchor.column==this.selectionLead.column},this.isMultiLine=function(){return this.isEmpty()?!1:this.getRange().isMultiLine()},this.getCursor=function(){return this.selectionLead.getPosition()},this.setSelectionAnchor=function(a,b){this.selectionAnchor.setPosition(a,b),this.$isEmpty&&(this.$isEmpty=!1,this._emit("changeSelection"))},this.getSelectionAnchor=function(){return this.$isEmpty?this.getSelectionLead():this.selectionAnchor.getPosition()},this.getSelectionLead=function(){return this.selectionLead.getPosition()},this.shiftSelection=function(a){if(this.$isEmpty){this.moveCursorTo(this.selectionLead.row,this.selectionLead.column+a);return}var b=this.getSelectionAnchor(),c=this.getSelectionLead(),d=this.isBackwards();(!d||b.column!==0)&&this.setSelectionAnchor(b.row,b.column+a),(d||c.column!==0)&&this.$moveSelection(function(){this.moveCursorTo(c.row,c.column+a)})},this.isBackwards=function(){var a=this.selectionAnchor,b=this.selectionLead;return a.row>b.row||a.row==b.row&&a.column>b.column},this.getRange=function(){var a=this.selectionAnchor,b=this.selectionLead;return this.isEmpty()?g.fromPoints(b,b):this.isBackwards()?g.fromPoints(b,a):g.fromPoints(a,b)},this.clearSelection=function(){this.$isEmpty||(this.$isEmpty=!0,this._emit("changeSelection"))},this.selectAll=function(){var a=this.doc.getLength()-1;this.setSelectionAnchor(a,this.doc.getLine(a).length),this.moveCursorTo(0,0)},this.setSelectionRange=function(a,b){b?(this.setSelectionAnchor(a.end.row,a.end.column),this.selectTo(a.start.row,a.start.column)):(this.setSelectionAnchor(a.start.row,a.start.column),this.selectTo(a.end.row,a.end.column)),this.$updateDesiredColumn()},this.$updateDesiredColumn=function(){var a=this.getCursor();this.$desiredColumn=this.session.documentToScreenColumn(a.row,a.column)},this.$moveSelection=function(a){var b=this.selectionLead;this.$isEmpty&&this.setSelectionAnchor(b.row,b.column),a.call(this)},this.selectTo=function(a,b){this.$moveSelection(function(){this.moveCursorTo(a,b)})},this.selectToPosition=function(a){this.$moveSelection(function(){this.moveCursorToPosition(a)})},this.selectUp=function(){this.$moveSelection(this.moveCursorUp)},this.selectDown=function(){this.$moveSelection(this.moveCursorDown)},this.selectRight=function(){this.$moveSelection(this.moveCursorRight)},this.selectLeft=function(){this.$moveSelection(this.moveCursorLeft)},this.selectLineStart=function(){this.$moveSelection(this.moveCursorLineStart)},this.selectLineEnd=function(){this.$moveSelection(this.moveCursorLineEnd)},this.selectFileEnd=function(){this.$moveSelection(this.moveCursorFileEnd)},this.selectFileStart=function(){this.$moveSelection(this.moveCursorFileStart)},this.selectWordRight=function(){this.$moveSelection(this.moveCursorWordRight)},this.selectWordLeft=function(){this.$moveSelection(this.moveCursorWordLeft)},this.selectWord=function(){var a=this.getCursor(),b=this.session.getWordRange(a.row,a.column);this.setSelectionRange(b)},this.selectAWord=function(){var a=this.getCursor(),b=this.session.getAWordRange(a.row,a.column);this.setSelectionRange(b)},this.selectLine=function(){var a=this.selectionLead.row,b,c=this.session.getFoldLine(a);c?(a=c.start.row,b=c.end.row):b=a,this.setSelectionAnchor(a,0),this.$moveSelection(function(){this.moveCursorTo(b+1,0)})},this.moveCursorUp=function(){this.moveCursorBy(-1,0)},this.moveCursorDown=function(){this.moveCursorBy(1,0)},this.moveCursorLeft=function(){var a=this.selectionLead.getPosition(),b;if(b=this.session.getFoldAt(a.row,a.column,-1))this.moveCursorTo(b.start.row,b.start.column);else if(a.column==0)a.row>0&&this.moveCursorTo(a.row-1,this.doc.getLine(a.row-1).length);else{var c=this.session.getTabSize();this.session.isTabStop(a)&&this.doc.getLine(a.row).slice(a.column-c,a.column).split(" ").length-1==c?this.moveCursorBy(0,-c):this.moveCursorBy(0,-1)}},this.moveCursorRight=function(){var a=this.selectionLead.getPosition(),b;if(b=this.session.getFoldAt(a.row,a.column,1))this.moveCursorTo(b.end.row,b.end.column);else if(this.selectionLead.column==this.doc.getLine(this.selectionLead.row).length)this.selectionLead.row<this.doc.getLength()-1&&this.moveCursorTo(this.selectionLead.row+1,0);else{var c=this.session.getTabSize(),a=this.selectionLead;this.session.isTabStop(a)&&this.doc.getLine(a.row).slice(a.column,a.column+c).split(" ").length-1==c?this.moveCursorBy(0,c):this.moveCursorBy(0,1)}},this.moveCursorLineStart=function(){var a=this.selectionLead.row,b=this.selectionLead.column,c=this.session.documentToScreenRow(a,b),d=this.session.screenToDocumentPosition(c,0),e=this.session.getDisplayLine(a,null,d.row,d.column),f=e.match(/^\s*/);f[0].length==b?this.moveCursorTo(d.row,d.column):this.moveCursorTo(d.row,d.column+f[0].length)},this.moveCursorLineEnd=function(){var a=this.selectionLead,b=this.session.getDocumentLastRowColumnPosition(a.row,a.column);this.moveCursorTo(b.row,b.column)},this.moveCursorFileEnd=function(){var a=this.doc.getLength()-1,b=this.doc.getLine(a).length;this.moveCursorTo(a,b)},this.moveCursorFileStart=function(){this.moveCursorTo(0,0)},this.moveCursorWordRight=function(){var a=this.selectionLead.row,b=this.selectionLead.column,c=this.doc.getLine(a),d=c.substring(b),e;this.session.nonTokenRe.lastIndex=0,this.session.tokenRe.lastIndex=0;var f=this.session.getFoldAt(a,b,1);if(f){this.moveCursorTo(f.end.row,f.end.column);return}if(e=this.session.nonTokenRe.exec(d))b+=this.session.nonTokenRe.lastIndex,this.session.nonTokenRe.lastIndex=0,d=c.substring(b);if(b>=c.length){this.moveCursorTo(a,c.length),this.moveCursorRight(),a<this.doc.getLength()-1&&this.moveCursorWordRight();return}if(e=this.session.tokenRe.exec(d))b+=this.session.tokenRe.lastIndex,this.session.tokenRe.lastIndex=0;this.moveCursorTo(a,b)},this.moveCursorWordLeft=function(){var a=this.selectionLead.row,b=this.selectionLead.column,c;if(c=this.session.getFoldAt(a,b,-1)){this.moveCursorTo(c.start.row,c.start.column);return}var d=this.session.getFoldStringAt(a,b,-1);d==null&&(d=this.doc.getLine(a).substring(0,b));var f=e.stringReverse(d),g;this.session.nonTokenRe.lastIndex=0,this.session.tokenRe.lastIndex=0;if(g=this.session.nonTokenRe.exec(f))b-=this.session.nonTokenRe.lastIndex,f=f.slice(this.session.nonTokenRe.lastIndex),this.session.nonTokenRe.lastIndex=0;if(b<=0){this.moveCursorTo(a,0),this.moveCursorLeft(),a>0&&this.moveCursorWordLeft();return}if(g=this.session.tokenRe.exec(f))b-=this.session.tokenRe.lastIndex,this.session.tokenRe.lastIndex=0;this.moveCursorTo(a,b)},this.moveCursorBy=function(a,b){var c=this.session.documentToScreenPosition(this.selectionLead.row,this.selectionLead.column),d=b===0&&this.$desiredColumn||c.column,e=this.session.screenToDocumentPosition(c.row+a,d);this.moveCursorTo(e.row,e.column+b,b===0)},this.moveCursorToPosition=function(a){this.moveCursorTo(a.row,a.column)},this.moveCursorTo=function(a,b,c){var d=this.session.getFoldAt(a,b,1);d&&(a=d.start.row,b=d.start.column),this.$preventUpdateDesiredColumnOnChange=!0,this.selectionLead.setPosition(a,b),this.$preventUpdateDesiredColumnOnChange=!1,c||this.$updateDesiredColumn(this.selectionLead.column)},this.moveCursorToScreen=function(a,b,c){var d=this.session.screenToDocumentPosition(a,b);a=d.row,b=d.column,this.moveCursorTo(a,b,c)}})).call(h.prototype),b.Selection=h}),define("ace/range",["require","exports","module"],function(a,b,c){"use strict";var d=function(a,b,c,d){this.start={row:a,column:b},this.end={row:c,column:d}};((function(){this.isEequal=function(a){return this.start.row==a.start.row&&this.end.row==a.end.row&&this.start.column==a.start.column&&this.end.column==a.end.column},this.toString=function(){return"Range: ["+this.start.row+"/"+this.start.column+"] -> ["+this.end.row+"/"+this.end.column+"]"},this.contains=function(a,b){return this.compare(a,b)==0},this.compareRange=function(a){var b,c=a.end,d=a.start;return b=this.compare(c.row,c.column),b==1?(b=this.compare(d.row,d.column),b==1?2:b==0?1:0):b==-1?-2:(b=this.compare(d.row,d.column),b==-1?-1:b==1?42:0)},this.comparePoint=function(a){return this.compare(a.row,a.column)},this.containsRange=function(a){return this.comparePoint(a.start)==0&&this.comparePoint(a.end)==0},this.isEnd=function(a,b){return this.end.row==a&&this.end.column==b},this.isStart=function(a,b){return this.start.row==a&&this.start.column==b},this.setStart=function(a,b){typeof a=="object"?(this.start.column=a.column,this.start.row=a.row):(this.start.row=a,this.start.column=b)},this.setEnd=function(a,b){typeof a=="object"?(this.end.column=a.column,this.end.row=a.row):(this.end.row=a,this.end.column=b)},this.inside=function(a,b){return this.compare(a,b)==0?this.isEnd(a,b)||this.isStart(a,b)?!1:!0:!1},this.insideStart=function(a,b){return this.compare(a,b)==0?this.isEnd(a,b)?!1:!0:!1},this.insideEnd=function(a,b){return this.compare(a,b)==0?this.isStart(a,b)?!1:!0:!1},this.compare=function(a,b){return!this.isMultiLine()&&a===this.start.row?b<this.start.column?-1:b>this.end.column?1:0:a<this.start.row?-1:a>this.end.row?1:this.start.row===a?b>=this.start.column?0:-1:this.end.row===a?b<=this.end.column?0:1:0},this.compareStart=function(a,b){return this.start.row==a&&this.start.column==b?-1:this.compare(a,b)},this.compareEnd=function(a,b){return this.end.row==a&&this.end.column==b?1:this.compare(a,b)},this.compareInside=function(a,b){return this.end.row==a&&this.end.column==b?1:this.start.row==a&&this.start.column==b?-1:this.compare(a,b)},this.clipRows=function(a,b){if(this.end.row>b)var c={row:b+1,column:0};if(this.start.row>b)var e={row:b+1,column:0};if(this.start.row<a)var e={row:a,column:0};if(this.end.row<a)var c={row:a,column:0};return d.fromPoints(e||this.start,c||this.end)},this.extend=function(a,b){var c=this.compare(a,b);if(c==0)return this;if(c==-1)var e={row:a,column:b};else var f={row:a,column:b};return d.fromPoints(e||this.start,f||this.end)},this.isEmpty=function(){return this.start.row==this.end.row&&this.start.column==this.end.column},this.isMultiLine=function(){return this.start.row!==this.end.row},this.clone=function(){return d.fromPoints(this.start,this.end)},this.collapseRows=function(){return this.end.column==0?new d(this.start.row,0,Math.max(this.start.row,this.end.row-1),0):new d(this.start.row,0,this.end.row,0)},this.toScreenRange=function(a){var b=a.documentToScreenPosition(this.start),c=a.documentToScreenPosition(this.end);return new d(b.row,b.column,c.row,c.column)}})).call(d.prototype),d.fromPoints=function(a,b){return new d(a.row,a.column,b.row,b.column)},b.Range=d}),define("ace/mode/text",["require","exports","module","ace/tokenizer","ace/mode/text_highlight_rules","ace/mode/behaviour","ace/unicode"],function(a,b,c){"use strict";var d=a("../tokenizer").Tokenizer,e=a("./text_highlight_rules").TextHighlightRules,f=a("./behaviour").Behaviour,g=a("../unicode"),h=function(){this.$tokenizer=new d((new e).getRules()),this.$behaviour=new f};((function(){this.tokenRe=new RegExp("^["+g.packages.L+g.packages.Mn+g.packages.Mc+g.packages.Nd+g.packages.Pc+"\\$_]+","g"),this.nonTokenRe=new RegExp("^(?:[^"+g.packages.L+g.packages.Mn+g.packages.Mc+g.packages.Nd+g.packages.Pc+"\\$_]|s])+","g"),this.getTokenizer=function(){return this.$tokenizer},this.toggleCommentLines=function(a,b,c,d){},this.getNextLineIndent=function(a,b,c){return""},this.checkOutdent=function(a,b,c){return!1},this.autoOutdent=function(a,b,c){},this.$getIndent=function(a){var b=a.match(/^(\s+)/);return b?b[1]:""},this.createWorker=function(a){return null},this.highlightSelection=function(a){var b=a.session;b.$selectionOccurrences||(b.$selectionOccurrences=[]),b.$selectionOccurrences.length&&this.clearSelectionHighlight(a);var c=a.getSelectionRange();if(c.isEmpty()||c.isMultiLine())return;var d=c.start.column-1,e=c.end.column+1,f=b.getLine(c.start.row),g=f.length,h=f.substring(Math.max(d,0),Math.min(e,g));if(d>=0&&/^[\w\d]/.test(h)||e<=g&&/[\w\d]$/.test(h))return;h=f.substring(c.start.column,c.end.column);if(!/^[\w\d]+$/.test(h))return;var i=a.getCursorPosition(),j={wrap:!0,wholeWord:!0,caseSensitive:!0,needle:h},k=a.$search.getOptions();a.$search.set(j);var l=a.$search.findAll(b);l.forEach(function(a){if(!a.contains(i.row,i.column)){var c=b.addMarker(a,"ace_selected_word","text");b.$selectionOccurrences.push(c)}}),a.$search.set(k)},this.clearSelectionHighlight=function(a){if(!a.session.$selectionOccurrences)return;a.session.$selectionOccurrences.forEach(function(b){a.session.removeMarker(b)}),a.session.$selectionOccurrences=[]},this.createModeDelegates=function(a){if(!this.$embeds)return;this.$modes={};for(var b=0;b<this.$embeds.length;b++)a[this.$embeds[b]]&&(this.$modes[this.$embeds[b]]=new a[this.$embeds[b]]);var c=["toggleCommentLines","getNextLineIndent","checkOutdent","autoOutdent","transformAction"];for(var b=0;b<c.length;b++)(function(a){var d=c[b],e=a[d];a[c[b]]=function(){return this.$delegator(d,arguments,e)}})(this)},this.$delegator=function(a,b,c){var d=b[0];for(var e=0;e<this.$embeds.length;e++){if(!this.$modes[this.$embeds[e]])continue;var f=d.split(this.$embeds[e]);if(!f[0]&&f[1]){b[0]=f[1];var g=this.$modes[this.$embeds[e]];return g[a].apply(g,b)}}var h=c.apply(this,b);return c?h:undefined},this.transformAction=function(a,b,c,d,e){if(this.$behaviour){var f=this.$behaviour.getBehaviours();for(var g in f)if(f[g][b]){var h=f[g][b].apply(this,arguments);if(h)return h}}}})).call(h.prototype),b.Mode=h}),define("ace/tokenizer",["require","exports","module"],function(a,b,c){"use strict";var d=function(a,b){b=b?"g"+b:"g",this.rules=a,this.regExps={},this.matchMappings={};for(var c in this.rules){var d=this.rules[c],e=d,f=[],g=0,h=this.matchMappings[c]={};for(var i=0;i<e.length;i++){var j=(new RegExp("(?:("+e[i].regex+")|(.))")).exec("a").length-2,k=e[i].regex.replace(/\\([0-9]+)/g,function(a,b){return"\\"+(parseInt(b,10)+g+1)});h[g]={rule:i,len:j},g+=j,f.push(k)}this.regExps[c]=new RegExp("(?:("+f.join(")|(")+")|(.))",b)}};((function(){this.getLineTokens=function(a,b){var c=b,d=this.rules[c],e=this.matchMappings[c],f=this.regExps[c];f.lastIndex=0;var g,h=[],i=0,j={type:null,value:""};while(g=f.exec(a)){var k="text",l=null,m=[g[0]];for(var n=0;n<g.length-2;n++)if(g[n+1]!==undefined){l=d[e[n].rule],e[n].len>1&&(m=g.slice(n+2,n+1+e[n].len)),typeof l.token=="function"?k=l.token.apply(this,m):k=l.token;var o=l.next;o&&o!==c&&(c=o,d=this.rules[c],e=this.matchMappings[c],i=f.lastIndex,f=this.regExps[c],f.lastIndex=i);break}if(m[0]){typeof k=="string"&&(m=[m.join("")],k=[k]);for(var n=0;n<m.length;n++)(!l||l.merge||k[n]==="text")&&j.type===k[n]?j.value+=m[n]:(j.type&&h.push(j),j={type:k[n],value:m[n]})}if(i==a.length)break;i=f.lastIndex}return j.type&&h.push(j),{tokens:h,state:c}}})).call(d.prototype),b.Tokenizer=d}),define("ace/mode/text_highlight_rules",["require","exports","module","ace/lib/lang"],function(a,b,c){"use strict";var d=a("../lib/lang"),e=function(){this.$rules={start:[{token:"empty_line",regex:"^$"},{token:"text",regex:".+"}]}};((function(){this.addRules=function(a,b){for(var c in a){var d=a[c];for(var e=0;e<d.length;e++){var f=d[e];f.next?f.next=b+f.next:f.next=b+c}this.$rules[b+c]=d}},this.getRules=function(){return this.$rules},this.embedRules=function(a,b,c,e){var f=(new a).getRules();if(e)for(var g=0;g<e.length;g++)e[g]=b+e[g];else{e=[];for(var h in f)e.push(b+h)}this.addRules(f,b);for(var g=0;g<e.length;g++)Array.prototype.unshift.apply(this.$rules[e[g]],d.deepCopy(c));this.$embeds||(this.$embeds=[]),this.$embeds.push(b)},this.getEmbeds=function(){return this.$embeds}})).call(e.prototype),b.TextHighlightRules=e}),define("ace/mode/behaviour",["require","exports","module"],function(a,b,c){"use strict";var d=function(){this.$behaviours={}};((function(){this.add=function(a,b,c){switch(undefined){case this.$behaviours:this.$behaviours={};case this.$behaviours[a]:this.$behaviours[a]={}}this.$behaviours[a][b]=c},this.addBehaviours=function(a){for(var b in a)for(var c in a[b])this.add(b,c,a[b][c])},this.remove=function(a){this.$behaviours&&this.$behaviours[a]&&delete this.$behaviours[a]},this.inherit=function(a,b){if(typeof a=="function")var c=(new a).getBehaviours(b);else var c=a.getBehaviours(b);this.addBehaviours(c)},this.getBehaviours=function(a){if(!a)return this.$behaviours;var b={};for(var c=0;c<a.length;c++)this.$behaviours[a[c]]&&(b[a[c]]=this.$behaviours[a[c]]);return b}})).call(d.prototype),b.Behaviour=d}),define("ace/unicode",["require","exports","module"],function(a,b,c){function d(a){var c=/\w{4}/g;for(var d in a)b.packages[d]=a[d].replace(c,"\\u$&")}"use strict",b.packages={},d({L:"0041-005A0061-007A00AA00B500BA00C0-00D600D8-00F600F8-02C102C6-02D102E0-02E402EC02EE0370-037403760377037A-037D03860388-038A038C038E-03A103A3-03F503F7-0481048A-05250531-055605590561-058705D0-05EA05F0-05F20621-064A066E066F0671-06D306D506E506E606EE06EF06FA-06FC06FF07100712-072F074D-07A507B107CA-07EA07F407F507FA0800-0815081A082408280904-0939093D09500958-0961097109720979-097F0985-098C098F09900993-09A809AA-09B009B209B6-09B909BD09CE09DC09DD09DF-09E109F009F10A05-0A0A0A0F0A100A13-0A280A2A-0A300A320A330A350A360A380A390A59-0A5C0A5E0A72-0A740A85-0A8D0A8F-0A910A93-0AA80AAA-0AB00AB20AB30AB5-0AB90ABD0AD00AE00AE10B05-0B0C0B0F0B100B13-0B280B2A-0B300B320B330B35-0B390B3D0B5C0B5D0B5F-0B610B710B830B85-0B8A0B8E-0B900B92-0B950B990B9A0B9C0B9E0B9F0BA30BA40BA8-0BAA0BAE-0BB90BD00C05-0C0C0C0E-0C100C12-0C280C2A-0C330C35-0C390C3D0C580C590C600C610C85-0C8C0C8E-0C900C92-0CA80CAA-0CB30CB5-0CB90CBD0CDE0CE00CE10D05-0D0C0D0E-0D100D12-0D280D2A-0D390D3D0D600D610D7A-0D7F0D85-0D960D9A-0DB10DB3-0DBB0DBD0DC0-0DC60E01-0E300E320E330E40-0E460E810E820E840E870E880E8A0E8D0E94-0E970E99-0E9F0EA1-0EA30EA50EA70EAA0EAB0EAD-0EB00EB20EB30EBD0EC0-0EC40EC60EDC0EDD0F000F40-0F470F49-0F6C0F88-0F8B1000-102A103F1050-1055105A-105D106110651066106E-10701075-1081108E10A0-10C510D0-10FA10FC1100-1248124A-124D1250-12561258125A-125D1260-1288128A-128D1290-12B012B2-12B512B8-12BE12C012C2-12C512C8-12D612D8-13101312-13151318-135A1380-138F13A0-13F41401-166C166F-167F1681-169A16A0-16EA1700-170C170E-17111720-17311740-17511760-176C176E-17701780-17B317D717DC1820-18771880-18A818AA18B0-18F51900-191C1950-196D1970-19741980-19AB19C1-19C71A00-1A161A20-1A541AA71B05-1B331B45-1B4B1B83-1BA01BAE1BAF1C00-1C231C4D-1C4F1C5A-1C7D1CE9-1CEC1CEE-1CF11D00-1DBF1E00-1F151F18-1F1D1F20-1F451F48-1F4D1F50-1F571F591F5B1F5D1F5F-1F7D1F80-1FB41FB6-1FBC1FBE1FC2-1FC41FC6-1FCC1FD0-1FD31FD6-1FDB1FE0-1FEC1FF2-1FF41FF6-1FFC2071207F2090-209421022107210A-211321152119-211D212421262128212A-212D212F-2139213C-213F2145-2149214E218321842C00-2C2E2C30-2C5E2C60-2CE42CEB-2CEE2D00-2D252D30-2D652D6F2D80-2D962DA0-2DA62DA8-2DAE2DB0-2DB62DB8-2DBE2DC0-2DC62DC8-2DCE2DD0-2DD62DD8-2DDE2E2F300530063031-3035303B303C3041-3096309D-309F30A1-30FA30FC-30FF3105-312D3131-318E31A0-31B731F0-31FF3400-4DB54E00-9FCBA000-A48CA4D0-A4FDA500-A60CA610-A61FA62AA62BA640-A65FA662-A66EA67F-A697A6A0-A6E5A717-A71FA722-A788A78BA78CA7FB-A801A803-A805A807-A80AA80C-A822A840-A873A882-A8B3A8F2-A8F7A8FBA90A-A925A930-A946A960-A97CA984-A9B2A9CFAA00-AA28AA40-AA42AA44-AA4BAA60-AA76AA7AAA80-AAAFAAB1AAB5AAB6AAB9-AABDAAC0AAC2AADB-AADDABC0-ABE2AC00-D7A3D7B0-D7C6D7CB-D7FBF900-FA2DFA30-FA6DFA70-FAD9FB00-FB06FB13-FB17FB1DFB1F-FB28FB2A-FB36FB38-FB3CFB3EFB40FB41FB43FB44FB46-FBB1FBD3-FD3DFD50-FD8FFD92-FDC7FDF0-FDFBFE70-FE74FE76-FEFCFF21-FF3AFF41-FF5AFF66-FFBEFFC2-FFC7FFCA-FFCFFFD2-FFD7FFDA-FFDC",Ll:"0061-007A00AA00B500BA00DF-00F600F8-00FF01010103010501070109010B010D010F01110113011501170119011B011D011F01210123012501270129012B012D012F01310133013501370138013A013C013E014001420144014601480149014B014D014F01510153015501570159015B015D015F01610163016501670169016B016D016F0171017301750177017A017C017E-0180018301850188018C018D019201950199-019B019E01A101A301A501A801AA01AB01AD01B001B401B601B901BA01BD-01BF01C601C901CC01CE01D001D201D401D601D801DA01DC01DD01DF01E101E301E501E701E901EB01ED01EF01F001F301F501F901FB01FD01FF02010203020502070209020B020D020F02110213021502170219021B021D021F02210223022502270229022B022D022F02310233-0239023C023F0240024202470249024B024D024F-02930295-02AF037103730377037B-037D039003AC-03CE03D003D103D5-03D703D903DB03DD03DF03E103E303E503E703E903EB03ED03EF-03F303F503F803FB03FC0430-045F04610463046504670469046B046D046F04710473047504770479047B047D047F0481048B048D048F04910493049504970499049B049D049F04A104A304A504A704A904AB04AD04AF04B104B304B504B704B904BB04BD04BF04C204C404C604C804CA04CC04CE04CF04D104D304D504D704D904DB04DD04DF04E104E304E504E704E904EB04ED04EF04F104F304F504F704F904FB04FD04FF05010503050505070509050B050D050F05110513051505170519051B051D051F0521052305250561-05871D00-1D2B1D62-1D771D79-1D9A1E011E031E051E071E091E0B1E0D1E0F1E111E131E151E171E191E1B1E1D1E1F1E211E231E251E271E291E2B1E2D1E2F1E311E331E351E371E391E3B1E3D1E3F1E411E431E451E471E491E4B1E4D1E4F1E511E531E551E571E591E5B1E5D1E5F1E611E631E651E671E691E6B1E6D1E6F1E711E731E751E771E791E7B1E7D1E7F1E811E831E851E871E891E8B1E8D1E8F1E911E931E95-1E9D1E9F1EA11EA31EA51EA71EA91EAB1EAD1EAF1EB11EB31EB51EB71EB91EBB1EBD1EBF1EC11EC31EC51EC71EC91ECB1ECD1ECF1ED11ED31ED51ED71ED91EDB1EDD1EDF1EE11EE31EE51EE71EE91EEB1EED1EEF1EF11EF31EF51EF71EF91EFB1EFD1EFF-1F071F10-1F151F20-1F271F30-1F371F40-1F451F50-1F571F60-1F671F70-1F7D1F80-1F871F90-1F971FA0-1FA71FB0-1FB41FB61FB71FBE1FC2-1FC41FC61FC71FD0-1FD31FD61FD71FE0-1FE71FF2-1FF41FF61FF7210A210E210F2113212F21342139213C213D2146-2149214E21842C30-2C5E2C612C652C662C682C6A2C6C2C712C732C742C76-2C7C2C812C832C852C872C892C8B2C8D2C8F2C912C932C952C972C992C9B2C9D2C9F2CA12CA32CA52CA72CA92CAB2CAD2CAF2CB12CB32CB52CB72CB92CBB2CBD2CBF2CC12CC32CC52CC72CC92CCB2CCD2CCF2CD12CD32CD52CD72CD92CDB2CDD2CDF2CE12CE32CE42CEC2CEE2D00-2D25A641A643A645A647A649A64BA64DA64FA651A653A655A657A659A65BA65DA65FA663A665A667A669A66BA66DA681A683A685A687A689A68BA68DA68FA691A693A695A697A723A725A727A729A72BA72DA72F-A731A733A735A737A739A73BA73DA73FA741A743A745A747A749A74BA74DA74FA751A753A755A757A759A75BA75DA75FA761A763A765A767A769A76BA76DA76FA771-A778A77AA77CA77FA781A783A785A787A78CFB00-FB06FB13-FB17FF41-FF5A",Lu:"0041-005A00C0-00D600D8-00DE01000102010401060108010A010C010E01100112011401160118011A011C011E01200122012401260128012A012C012E01300132013401360139013B013D013F0141014301450147014A014C014E01500152015401560158015A015C015E01600162016401660168016A016C016E017001720174017601780179017B017D018101820184018601870189-018B018E-0191019301940196-0198019C019D019F01A001A201A401A601A701A901AC01AE01AF01B1-01B301B501B701B801BC01C401C701CA01CD01CF01D101D301D501D701D901DB01DE01E001E201E401E601E801EA01EC01EE01F101F401F6-01F801FA01FC01FE02000202020402060208020A020C020E02100212021402160218021A021C021E02200222022402260228022A022C022E02300232023A023B023D023E02410243-02460248024A024C024E03700372037603860388-038A038C038E038F0391-03A103A3-03AB03CF03D2-03D403D803DA03DC03DE03E003E203E403E603E803EA03EC03EE03F403F703F903FA03FD-042F04600462046404660468046A046C046E04700472047404760478047A047C047E0480048A048C048E04900492049404960498049A049C049E04A004A204A404A604A804AA04AC04AE04B004B204B404B604B804BA04BC04BE04C004C104C304C504C704C904CB04CD04D004D204D404D604D804DA04DC04DE04E004E204E404E604E804EA04EC04EE04F004F204F404F604F804FA04FC04FE05000502050405060508050A050C050E05100512051405160518051A051C051E0520052205240531-055610A0-10C51E001E021E041E061E081E0A1E0C1E0E1E101E121E141E161E181E1A1E1C1E1E1E201E221E241E261E281E2A1E2C1E2E1E301E321E341E361E381E3A1E3C1E3E1E401E421E441E461E481E4A1E4C1E4E1E501E521E541E561E581E5A1E5C1E5E1E601E621E641E661E681E6A1E6C1E6E1E701E721E741E761E781E7A1E7C1E7E1E801E821E841E861E881E8A1E8C1E8E1E901E921E941E9E1EA01EA21EA41EA61EA81EAA1EAC1EAE1EB01EB21EB41EB61EB81EBA1EBC1EBE1EC01EC21EC41EC61EC81ECA1ECC1ECE1ED01ED21ED41ED61ED81EDA1EDC1EDE1EE01EE21EE41EE61EE81EEA1EEC1EEE1EF01EF21EF41EF61EF81EFA1EFC1EFE1F08-1F0F1F18-1F1D1F28-1F2F1F38-1F3F1F48-1F4D1F591F5B1F5D1F5F1F68-1F6F1FB8-1FBB1FC8-1FCB1FD8-1FDB1FE8-1FEC1FF8-1FFB21022107210B-210D2110-211221152119-211D212421262128212A-212D2130-2133213E213F214521832C00-2C2E2C602C62-2C642C672C692C6B2C6D-2C702C722C752C7E-2C802C822C842C862C882C8A2C8C2C8E2C902C922C942C962C982C9A2C9C2C9E2CA02CA22CA42CA62CA82CAA2CAC2CAE2CB02CB22CB42CB62CB82CBA2CBC2CBE2CC02CC22CC42CC62CC82CCA2CCC2CCE2CD02CD22CD42CD62CD82CDA2CDC2CDE2CE02CE22CEB2CEDA640A642A644A646A648A64AA64CA64EA650A652A654A656A658A65AA65CA65EA662A664A666A668A66AA66CA680A682A684A686A688A68AA68CA68EA690A692A694A696A722A724A726A728A72AA72CA72EA732A734A736A738A73AA73CA73EA740A742A744A746A748A74AA74CA74EA750A752A754A756A758A75AA75CA75EA760A762A764A766A768A76AA76CA76EA779A77BA77DA77EA780A782A784A786A78BFF21-FF3A",Lt:"01C501C801CB01F21F88-1F8F1F98-1F9F1FA8-1FAF1FBC1FCC1FFC",Lm:"02B0-02C102C6-02D102E0-02E402EC02EE0374037A0559064006E506E607F407F507FA081A0824082809710E460EC610FC17D718431AA71C78-1C7D1D2C-1D611D781D9B-1DBF2071207F2090-20942C7D2D6F2E2F30053031-3035303B309D309E30FC-30FEA015A4F8-A4FDA60CA67FA717-A71FA770A788A9CFAA70AADDFF70FF9EFF9F",Lo:"01BB01C0-01C3029405D0-05EA05F0-05F20621-063F0641-064A066E066F0671-06D306D506EE06EF06FA-06FC06FF07100712-072F074D-07A507B107CA-07EA0800-08150904-0939093D09500958-096109720979-097F0985-098C098F09900993-09A809AA-09B009B209B6-09B909BD09CE09DC09DD09DF-09E109F009F10A05-0A0A0A0F0A100A13-0A280A2A-0A300A320A330A350A360A380A390A59-0A5C0A5E0A72-0A740A85-0A8D0A8F-0A910A93-0AA80AAA-0AB00AB20AB30AB5-0AB90ABD0AD00AE00AE10B05-0B0C0B0F0B100B13-0B280B2A-0B300B320B330B35-0B390B3D0B5C0B5D0B5F-0B610B710B830B85-0B8A0B8E-0B900B92-0B950B990B9A0B9C0B9E0B9F0BA30BA40BA8-0BAA0BAE-0BB90BD00C05-0C0C0C0E-0C100C12-0C280C2A-0C330C35-0C390C3D0C580C590C600C610C85-0C8C0C8E-0C900C92-0CA80CAA-0CB30CB5-0CB90CBD0CDE0CE00CE10D05-0D0C0D0E-0D100D12-0D280D2A-0D390D3D0D600D610D7A-0D7F0D85-0D960D9A-0DB10DB3-0DBB0DBD0DC0-0DC60E01-0E300E320E330E40-0E450E810E820E840E870E880E8A0E8D0E94-0E970E99-0E9F0EA1-0EA30EA50EA70EAA0EAB0EAD-0EB00EB20EB30EBD0EC0-0EC40EDC0EDD0F000F40-0F470F49-0F6C0F88-0F8B1000-102A103F1050-1055105A-105D106110651066106E-10701075-1081108E10D0-10FA1100-1248124A-124D1250-12561258125A-125D1260-1288128A-128D1290-12B012B2-12B512B8-12BE12C012C2-12C512C8-12D612D8-13101312-13151318-135A1380-138F13A0-13F41401-166C166F-167F1681-169A16A0-16EA1700-170C170E-17111720-17311740-17511760-176C176E-17701780-17B317DC1820-18421844-18771880-18A818AA18B0-18F51900-191C1950-196D1970-19741980-19AB19C1-19C71A00-1A161A20-1A541B05-1B331B45-1B4B1B83-1BA01BAE1BAF1C00-1C231C4D-1C4F1C5A-1C771CE9-1CEC1CEE-1CF12135-21382D30-2D652D80-2D962DA0-2DA62DA8-2DAE2DB0-2DB62DB8-2DBE2DC0-2DC62DC8-2DCE2DD0-2DD62DD8-2DDE3006303C3041-3096309F30A1-30FA30FF3105-312D3131-318E31A0-31B731F0-31FF3400-4DB54E00-9FCBA000-A014A016-A48CA4D0-A4F7A500-A60BA610-A61FA62AA62BA66EA6A0-A6E5A7FB-A801A803-A805A807-A80AA80C-A822A840-A873A882-A8B3A8F2-A8F7A8FBA90A-A925A930-A946A960-A97CA984-A9B2AA00-AA28AA40-AA42AA44-AA4BAA60-AA6FAA71-AA76AA7AAA80-AAAFAAB1AAB5AAB6AAB9-AABDAAC0AAC2AADBAADCABC0-ABE2AC00-D7A3D7B0-D7C6D7CB-D7FBF900-FA2DFA30-FA6DFA70-FAD9FB1DFB1F-FB28FB2A-FB36FB38-FB3CFB3EFB40FB41FB43FB44FB46-FBB1FBD3-FD3DFD50-FD8FFD92-FDC7FDF0-FDFBFE70-FE74FE76-FEFCFF66-FF6FFF71-FF9DFFA0-FFBEFFC2-FFC7FFCA-FFCFFFD2-FFD7FFDA-FFDC",M:"0300-036F0483-04890591-05BD05BF05C105C205C405C505C70610-061A064B-065E067006D6-06DC06DE-06E406E706E806EA-06ED07110730-074A07A6-07B007EB-07F30816-0819081B-08230825-08270829-082D0900-0903093C093E-094E0951-0955096209630981-098309BC09BE-09C409C709C809CB-09CD09D709E209E30A01-0A030A3C0A3E-0A420A470A480A4B-0A4D0A510A700A710A750A81-0A830ABC0ABE-0AC50AC7-0AC90ACB-0ACD0AE20AE30B01-0B030B3C0B3E-0B440B470B480B4B-0B4D0B560B570B620B630B820BBE-0BC20BC6-0BC80BCA-0BCD0BD70C01-0C030C3E-0C440C46-0C480C4A-0C4D0C550C560C620C630C820C830CBC0CBE-0CC40CC6-0CC80CCA-0CCD0CD50CD60CE20CE30D020D030D3E-0D440D46-0D480D4A-0D4D0D570D620D630D820D830DCA0DCF-0DD40DD60DD8-0DDF0DF20DF30E310E34-0E3A0E47-0E4E0EB10EB4-0EB90EBB0EBC0EC8-0ECD0F180F190F350F370F390F3E0F3F0F71-0F840F860F870F90-0F970F99-0FBC0FC6102B-103E1056-1059105E-10601062-10641067-106D1071-10741082-108D108F109A-109D135F1712-17141732-1734175217531772177317B6-17D317DD180B-180D18A91920-192B1930-193B19B0-19C019C819C91A17-1A1B1A55-1A5E1A60-1A7C1A7F1B00-1B041B34-1B441B6B-1B731B80-1B821BA1-1BAA1C24-1C371CD0-1CD21CD4-1CE81CED1CF21DC0-1DE61DFD-1DFF20D0-20F02CEF-2CF12DE0-2DFF302A-302F3099309AA66F-A672A67CA67DA6F0A6F1A802A806A80BA823-A827A880A881A8B4-A8C4A8E0-A8F1A926-A92DA947-A953A980-A983A9B3-A9C0AA29-AA36AA43AA4CAA4DAA7BAAB0AAB2-AAB4AAB7AAB8AABEAABFAAC1ABE3-ABEAABECABEDFB1EFE00-FE0FFE20-FE26",Mn:"0300-036F0483-04870591-05BD05BF05C105C205C405C505C70610-061A064B-065E067006D6-06DC06DF-06E406E706E806EA-06ED07110730-074A07A6-07B007EB-07F30816-0819081B-08230825-08270829-082D0900-0902093C0941-0948094D0951-095509620963098109BC09C1-09C409CD09E209E30A010A020A3C0A410A420A470A480A4B-0A4D0A510A700A710A750A810A820ABC0AC1-0AC50AC70AC80ACD0AE20AE30B010B3C0B3F0B41-0B440B4D0B560B620B630B820BC00BCD0C3E-0C400C46-0C480C4A-0C4D0C550C560C620C630CBC0CBF0CC60CCC0CCD0CE20CE30D41-0D440D4D0D620D630DCA0DD2-0DD40DD60E310E34-0E3A0E47-0E4E0EB10EB4-0EB90EBB0EBC0EC8-0ECD0F180F190F350F370F390F71-0F7E0F80-0F840F860F870F90-0F970F99-0FBC0FC6102D-10301032-10371039103A103D103E10581059105E-10601071-1074108210851086108D109D135F1712-17141732-1734175217531772177317B7-17BD17C617C9-17D317DD180B-180D18A91920-19221927192819321939-193B1A171A181A561A58-1A5E1A601A621A65-1A6C1A73-1A7C1A7F1B00-1B031B341B36-1B3A1B3C1B421B6B-1B731B801B811BA2-1BA51BA81BA91C2C-1C331C361C371CD0-1CD21CD4-1CE01CE2-1CE81CED1DC0-1DE61DFD-1DFF20D0-20DC20E120E5-20F02CEF-2CF12DE0-2DFF302A-302F3099309AA66FA67CA67DA6F0A6F1A802A806A80BA825A826A8C4A8E0-A8F1A926-A92DA947-A951A980-A982A9B3A9B6-A9B9A9BCAA29-AA2EAA31AA32AA35AA36AA43AA4CAAB0AAB2-AAB4AAB7AAB8AABEAABFAAC1ABE5ABE8ABEDFB1EFE00-FE0FFE20-FE26",Mc:"0903093E-09400949-094C094E0982098309BE-09C009C709C809CB09CC09D70A030A3E-0A400A830ABE-0AC00AC90ACB0ACC0B020B030B3E0B400B470B480B4B0B4C0B570BBE0BBF0BC10BC20BC6-0BC80BCA-0BCC0BD70C01-0C030C41-0C440C820C830CBE0CC0-0CC40CC70CC80CCA0CCB0CD50CD60D020D030D3E-0D400D46-0D480D4A-0D4C0D570D820D830DCF-0DD10DD8-0DDF0DF20DF30F3E0F3F0F7F102B102C10311038103B103C105610571062-10641067-106D108310841087-108C108F109A-109C17B617BE-17C517C717C81923-19261929-192B193019311933-193819B0-19C019C819C91A19-1A1B1A551A571A611A631A641A6D-1A721B041B351B3B1B3D-1B411B431B441B821BA11BA61BA71BAA1C24-1C2B1C341C351CE11CF2A823A824A827A880A881A8B4-A8C3A952A953A983A9B4A9B5A9BAA9BBA9BD-A9C0AA2FAA30AA33AA34AA4DAA7BABE3ABE4ABE6ABE7ABE9ABEAABEC",Me:"0488048906DE20DD-20E020E2-20E4A670-A672",N:"0030-003900B200B300B900BC-00BE0660-066906F0-06F907C0-07C90966-096F09E6-09EF09F4-09F90A66-0A6F0AE6-0AEF0B66-0B6F0BE6-0BF20C66-0C6F0C78-0C7E0CE6-0CEF0D66-0D750E50-0E590ED0-0ED90F20-0F331040-10491090-10991369-137C16EE-16F017E0-17E917F0-17F91810-18191946-194F19D0-19DA1A80-1A891A90-1A991B50-1B591BB0-1BB91C40-1C491C50-1C5920702074-20792080-20892150-21822185-21892460-249B24EA-24FF2776-27932CFD30073021-30293038-303A3192-31953220-32293251-325F3280-328932B1-32BFA620-A629A6E6-A6EFA830-A835A8D0-A8D9A900-A909A9D0-A9D9AA50-AA59ABF0-ABF9FF10-FF19",Nd:"0030-00390660-066906F0-06F907C0-07C90966-096F09E6-09EF0A66-0A6F0AE6-0AEF0B66-0B6F0BE6-0BEF0C66-0C6F0CE6-0CEF0D66-0D6F0E50-0E590ED0-0ED90F20-0F291040-10491090-109917E0-17E91810-18191946-194F19D0-19DA1A80-1A891A90-1A991B50-1B591BB0-1BB91C40-1C491C50-1C59A620-A629A8D0-A8D9A900-A909A9D0-A9D9AA50-AA59ABF0-ABF9FF10-FF19",Nl:"16EE-16F02160-21822185-218830073021-30293038-303AA6E6-A6EF",No:"00B200B300B900BC-00BE09F4-09F90BF0-0BF20C78-0C7E0D70-0D750F2A-0F331369-137C17F0-17F920702074-20792080-20892150-215F21892460-249B24EA-24FF2776-27932CFD3192-31953220-32293251-325F3280-328932B1-32BFA830-A835",P:"0021-00230025-002A002C-002F003A003B003F0040005B-005D005F007B007D00A100AB00B700BB00BF037E0387055A-055F0589058A05BE05C005C305C605F305F40609060A060C060D061B061E061F066A-066D06D40700-070D07F7-07F90830-083E0964096509700DF40E4F0E5A0E5B0F04-0F120F3A-0F3D0F850FD0-0FD4104A-104F10FB1361-13681400166D166E169B169C16EB-16ED1735173617D4-17D617D8-17DA1800-180A1944194519DE19DF1A1E1A1F1AA0-1AA61AA8-1AAD1B5A-1B601C3B-1C3F1C7E1C7F1CD32010-20272030-20432045-20512053-205E207D207E208D208E2329232A2768-277527C527C627E6-27EF2983-299829D8-29DB29FC29FD2CF9-2CFC2CFE2CFF2E00-2E2E2E302E313001-30033008-30113014-301F3030303D30A030FBA4FEA4FFA60D-A60FA673A67EA6F2-A6F7A874-A877A8CEA8CFA8F8-A8FAA92EA92FA95FA9C1-A9CDA9DEA9DFAA5C-AA5FAADEAADFABEBFD3EFD3FFE10-FE19FE30-FE52FE54-FE61FE63FE68FE6AFE6BFF01-FF03FF05-FF0AFF0C-FF0FFF1AFF1BFF1FFF20FF3B-FF3DFF3FFF5BFF5DFF5F-FF65",Pd:"002D058A05BE140018062010-20152E172E1A301C303030A0FE31FE32FE58FE63FF0D",Ps:"0028005B007B0F3A0F3C169B201A201E2045207D208D23292768276A276C276E27702772277427C527E627E827EA27EC27EE2983298529872989298B298D298F299129932995299729D829DA29FC2E222E242E262E283008300A300C300E3010301430163018301A301DFD3EFE17FE35FE37FE39FE3BFE3DFE3FFE41FE43FE47FE59FE5BFE5DFF08FF3BFF5BFF5FFF62",Pe:"0029005D007D0F3B0F3D169C2046207E208E232A2769276B276D276F27712773277527C627E727E927EB27ED27EF298429862988298A298C298E2990299229942996299829D929DB29FD2E232E252E272E293009300B300D300F3011301530173019301B301E301FFD3FFE18FE36FE38FE3AFE3CFE3EFE40FE42FE44FE48FE5AFE5CFE5EFF09FF3DFF5DFF60FF63",Pi:"00AB2018201B201C201F20392E022E042E092E0C2E1C2E20",Pf:"00BB2019201D203A2E032E052E0A2E0D2E1D2E21",Pc:"005F203F20402054FE33FE34FE4D-FE4FFF3F",Po:"0021-00230025-0027002A002C002E002F003A003B003F0040005C00A100B700BF037E0387055A-055F058905C005C305C605F305F40609060A060C060D061B061E061F066A-066D06D40700-070D07F7-07F90830-083E0964096509700DF40E4F0E5A0E5B0F04-0F120F850FD0-0FD4104A-104F10FB1361-1368166D166E16EB-16ED1735173617D4-17D617D8-17DA1800-18051807-180A1944194519DE19DF1A1E1A1F1AA0-1AA61AA8-1AAD1B5A-1B601C3B-1C3F1C7E1C7F1CD3201620172020-20272030-2038203B-203E2041-20432047-205120532055-205E2CF9-2CFC2CFE2CFF2E002E012E06-2E082E0B2E0E-2E162E182E192E1B2E1E2E1F2E2A-2E2E2E302E313001-3003303D30FBA4FEA4FFA60D-A60FA673A67EA6F2-A6F7A874-A877A8CEA8CFA8F8-A8FAA92EA92FA95FA9C1-A9CDA9DEA9DFAA5C-AA5FAADEAADFABEBFE10-FE16FE19FE30FE45FE46FE49-FE4CFE50-FE52FE54-FE57FE5F-FE61FE68FE6AFE6BFF01-FF03FF05-FF07FF0AFF0CFF0EFF0FFF1AFF1BFF1FFF20FF3CFF61FF64FF65",S:"0024002B003C-003E005E0060007C007E00A2-00A900AC00AE-00B100B400B600B800D700F702C2-02C502D2-02DF02E5-02EB02ED02EF-02FF03750384038503F604820606-0608060B060E060F06E906FD06FE07F609F209F309FA09FB0AF10B700BF3-0BFA0C7F0CF10CF20D790E3F0F01-0F030F13-0F170F1A-0F1F0F340F360F380FBE-0FC50FC7-0FCC0FCE0FCF0FD5-0FD8109E109F13601390-139917DB194019E0-19FF1B61-1B6A1B74-1B7C1FBD1FBF-1FC11FCD-1FCF1FDD-1FDF1FED-1FEF1FFD1FFE20442052207A-207C208A-208C20A0-20B8210021012103-21062108210921142116-2118211E-2123212521272129212E213A213B2140-2144214A-214D214F2190-2328232B-23E82400-24262440-244A249C-24E92500-26CD26CF-26E126E326E8-26FF2701-27042706-2709270C-27272729-274B274D274F-27522756-275E2761-276727942798-27AF27B1-27BE27C0-27C427C7-27CA27CC27D0-27E527F0-29822999-29D729DC-29FB29FE-2B4C2B50-2B592CE5-2CEA2E80-2E992E9B-2EF32F00-2FD52FF0-2FFB300430123013302030363037303E303F309B309C319031913196-319F31C0-31E33200-321E322A-32503260-327F328A-32B032C0-32FE3300-33FF4DC0-4DFFA490-A4C6A700-A716A720A721A789A78AA828-A82BA836-A839AA77-AA79FB29FDFCFDFDFE62FE64-FE66FE69FF04FF0BFF1C-FF1EFF3EFF40FF5CFF5EFFE0-FFE6FFE8-FFEEFFFCFFFD",Sm:"002B003C-003E007C007E00AC00B100D700F703F60606-060820442052207A-207C208A-208C2140-2144214B2190-2194219A219B21A021A321A621AE21CE21CF21D221D421F4-22FF2308-230B23202321237C239B-23B323DC-23E125B725C125F8-25FF266F27C0-27C427C7-27CA27CC27D0-27E527F0-27FF2900-29822999-29D729DC-29FB29FE-2AFF2B30-2B442B47-2B4CFB29FE62FE64-FE66FF0BFF1C-FF1EFF5CFF5EFFE2FFE9-FFEC",Sc:"002400A2-00A5060B09F209F309FB0AF10BF90E3F17DB20A0-20B8A838FDFCFE69FF04FFE0FFE1FFE5FFE6",Sk:"005E006000A800AF00B400B802C2-02C502D2-02DF02E5-02EB02ED02EF-02FF0375038403851FBD1FBF-1FC11FCD-1FCF1FDD-1FDF1FED-1FEF1FFD1FFE309B309CA700-A716A720A721A789A78AFF3EFF40FFE3",So:"00A600A700A900AE00B000B60482060E060F06E906FD06FE07F609FA0B700BF3-0BF80BFA0C7F0CF10CF20D790F01-0F030F13-0F170F1A-0F1F0F340F360F380FBE-0FC50FC7-0FCC0FCE0FCF0FD5-0FD8109E109F13601390-1399194019E0-19FF1B61-1B6A1B74-1B7C210021012103-21062108210921142116-2118211E-2123212521272129212E213A213B214A214C214D214F2195-2199219C-219F21A121A221A421A521A7-21AD21AF-21CD21D021D121D321D5-21F32300-2307230C-231F2322-2328232B-237B237D-239A23B4-23DB23E2-23E82400-24262440-244A249C-24E92500-25B625B8-25C025C2-25F72600-266E2670-26CD26CF-26E126E326E8-26FF2701-27042706-2709270C-27272729-274B274D274F-27522756-275E2761-276727942798-27AF27B1-27BE2800-28FF2B00-2B2F2B452B462B50-2B592CE5-2CEA2E80-2E992E9B-2EF32F00-2FD52FF0-2FFB300430123013302030363037303E303F319031913196-319F31C0-31E33200-321E322A-32503260-327F328A-32B032C0-32FE3300-33FF4DC0-4DFFA490-A4C6A828-A82BA836A837A839AA77-AA79FDFDFFE4FFE8FFEDFFEEFFFCFFFD",Z:"002000A01680180E2000-200A20282029202F205F3000",Zs:"002000A01680180E2000-200A202F205F3000",Zl:"2028",Zp:"2029",C:"0000-001F007F-009F00AD03780379037F-0383038B038D03A20526-05300557055805600588058B-059005C8-05CF05EB-05EF05F5-0605061C061D0620065F06DD070E070F074B074C07B2-07BF07FB-07FF082E082F083F-08FF093A093B094F095609570973-097809800984098D098E0991099209A909B109B3-09B509BA09BB09C509C609C909CA09CF-09D609D8-09DB09DE09E409E509FC-0A000A040A0B-0A0E0A110A120A290A310A340A370A3A0A3B0A3D0A43-0A460A490A4A0A4E-0A500A52-0A580A5D0A5F-0A650A76-0A800A840A8E0A920AA90AB10AB40ABA0ABB0AC60ACA0ACE0ACF0AD1-0ADF0AE40AE50AF00AF2-0B000B040B0D0B0E0B110B120B290B310B340B3A0B3B0B450B460B490B4A0B4E-0B550B58-0B5B0B5E0B640B650B72-0B810B840B8B-0B8D0B910B96-0B980B9B0B9D0BA0-0BA20BA5-0BA70BAB-0BAD0BBA-0BBD0BC3-0BC50BC90BCE0BCF0BD1-0BD60BD8-0BE50BFB-0C000C040C0D0C110C290C340C3A-0C3C0C450C490C4E-0C540C570C5A-0C5F0C640C650C70-0C770C800C810C840C8D0C910CA90CB40CBA0CBB0CC50CC90CCE-0CD40CD7-0CDD0CDF0CE40CE50CF00CF3-0D010D040D0D0D110D290D3A-0D3C0D450D490D4E-0D560D58-0D5F0D640D650D76-0D780D800D810D840D97-0D990DB20DBC0DBE0DBF0DC7-0DC90DCB-0DCE0DD50DD70DE0-0DF10DF5-0E000E3B-0E3E0E5C-0E800E830E850E860E890E8B0E8C0E8E-0E930E980EA00EA40EA60EA80EA90EAC0EBA0EBE0EBF0EC50EC70ECE0ECF0EDA0EDB0EDE-0EFF0F480F6D-0F700F8C-0F8F0F980FBD0FCD0FD9-0FFF10C6-10CF10FD-10FF1249124E124F12571259125E125F1289128E128F12B112B612B712BF12C112C612C712D7131113161317135B-135E137D-137F139A-139F13F5-13FF169D-169F16F1-16FF170D1715-171F1737-173F1754-175F176D17711774-177F17B417B517DE17DF17EA-17EF17FA-17FF180F181A-181F1878-187F18AB-18AF18F6-18FF191D-191F192C-192F193C-193F1941-1943196E196F1975-197F19AC-19AF19CA-19CF19DB-19DD1A1C1A1D1A5F1A7D1A7E1A8A-1A8F1A9A-1A9F1AAE-1AFF1B4C-1B4F1B7D-1B7F1BAB-1BAD1BBA-1BFF1C38-1C3A1C4A-1C4C1C80-1CCF1CF3-1CFF1DE7-1DFC1F161F171F1E1F1F1F461F471F4E1F4F1F581F5A1F5C1F5E1F7E1F7F1FB51FC51FD41FD51FDC1FF01FF11FF51FFF200B-200F202A-202E2060-206F20722073208F2095-209F20B9-20CF20F1-20FF218A-218F23E9-23FF2427-243F244B-245F26CE26E226E4-26E727002705270A270B2728274C274E2753-2755275F27602795-279727B027BF27CB27CD-27CF2B4D-2B4F2B5A-2BFF2C2F2C5F2CF2-2CF82D26-2D2F2D66-2D6E2D70-2D7F2D97-2D9F2DA72DAF2DB72DBF2DC72DCF2DD72DDF2E32-2E7F2E9A2EF4-2EFF2FD6-2FEF2FFC-2FFF3040309730983100-3104312E-3130318F31B8-31BF31E4-31EF321F32FF4DB6-4DBF9FCC-9FFFA48D-A48FA4C7-A4CFA62C-A63FA660A661A674-A67BA698-A69FA6F8-A6FFA78D-A7FAA82C-A82FA83A-A83FA878-A87FA8C5-A8CDA8DA-A8DFA8FC-A8FFA954-A95EA97D-A97FA9CEA9DA-A9DDA9E0-A9FFAA37-AA3FAA4EAA4FAA5AAA5BAA7C-AA7FAAC3-AADAAAE0-ABBFABEEABEFABFA-ABFFD7A4-D7AFD7C7-D7CAD7FC-F8FFFA2EFA2FFA6EFA6FFADA-FAFFFB07-FB12FB18-FB1CFB37FB3DFB3FFB42FB45FBB2-FBD2FD40-FD4FFD90FD91FDC8-FDEFFDFEFDFFFE1A-FE1FFE27-FE2FFE53FE67FE6C-FE6FFE75FEFD-FF00FFBF-FFC1FFC8FFC9FFD0FFD1FFD8FFD9FFDD-FFDFFFE7FFEF-FFFBFFFEFFFF",Cc:"0000-001F007F-009F",Cf:"00AD0600-060306DD070F17B417B5200B-200F202A-202E2060-2064206A-206FFEFFFFF9-FFFB",Co:"E000-F8FF",Cs:"D800-DFFF",Cn:"03780379037F-0383038B038D03A20526-05300557055805600588058B-059005C8-05CF05EB-05EF05F5-05FF06040605061C061D0620065F070E074B074C07B2-07BF07FB-07FF082E082F083F-08FF093A093B094F095609570973-097809800984098D098E0991099209A909B109B3-09B509BA09BB09C509C609C909CA09CF-09D609D8-09DB09DE09E409E509FC-0A000A040A0B-0A0E0A110A120A290A310A340A370A3A0A3B0A3D0A43-0A460A490A4A0A4E-0A500A52-0A580A5D0A5F-0A650A76-0A800A840A8E0A920AA90AB10AB40ABA0ABB0AC60ACA0ACE0ACF0AD1-0ADF0AE40AE50AF00AF2-0B000B040B0D0B0E0B110B120B290B310B340B3A0B3B0B450B460B490B4A0B4E-0B550B58-0B5B0B5E0B640B650B72-0B810B840B8B-0B8D0B910B96-0B980B9B0B9D0BA0-0BA20BA5-0BA70BAB-0BAD0BBA-0BBD0BC3-0BC50BC90BCE0BCF0BD1-0BD60BD8-0BE50BFB-0C000C040C0D0C110C290C340C3A-0C3C0C450C490C4E-0C540C570C5A-0C5F0C640C650C70-0C770C800C810C840C8D0C910CA90CB40CBA0CBB0CC50CC90CCE-0CD40CD7-0CDD0CDF0CE40CE50CF00CF3-0D010D040D0D0D110D290D3A-0D3C0D450D490D4E-0D560D58-0D5F0D640D650D76-0D780D800D810D840D97-0D990DB20DBC0DBE0DBF0DC7-0DC90DCB-0DCE0DD50DD70DE0-0DF10DF5-0E000E3B-0E3E0E5C-0E800E830E850E860E890E8B0E8C0E8E-0E930E980EA00EA40EA60EA80EA90EAC0EBA0EBE0EBF0EC50EC70ECE0ECF0EDA0EDB0EDE-0EFF0F480F6D-0F700F8C-0F8F0F980FBD0FCD0FD9-0FFF10C6-10CF10FD-10FF1249124E124F12571259125E125F1289128E128F12B112B612B712BF12C112C612C712D7131113161317135B-135E137D-137F139A-139F13F5-13FF169D-169F16F1-16FF170D1715-171F1737-173F1754-175F176D17711774-177F17DE17DF17EA-17EF17FA-17FF180F181A-181F1878-187F18AB-18AF18F6-18FF191D-191F192C-192F193C-193F1941-1943196E196F1975-197F19AC-19AF19CA-19CF19DB-19DD1A1C1A1D1A5F1A7D1A7E1A8A-1A8F1A9A-1A9F1AAE-1AFF1B4C-1B4F1B7D-1B7F1BAB-1BAD1BBA-1BFF1C38-1C3A1C4A-1C4C1C80-1CCF1CF3-1CFF1DE7-1DFC1F161F171F1E1F1F1F461F471F4E1F4F1F581F5A1F5C1F5E1F7E1F7F1FB51FC51FD41FD51FDC1FF01FF11FF51FFF2065-206920722073208F2095-209F20B9-20CF20F1-20FF218A-218F23E9-23FF2427-243F244B-245F26CE26E226E4-26E727002705270A270B2728274C274E2753-2755275F27602795-279727B027BF27CB27CD-27CF2B4D-2B4F2B5A-2BFF2C2F2C5F2CF2-2CF82D26-2D2F2D66-2D6E2D70-2D7F2D97-2D9F2DA72DAF2DB72DBF2DC72DCF2DD72DDF2E32-2E7F2E9A2EF4-2EFF2FD6-2FEF2FFC-2FFF3040309730983100-3104312E-3130318F31B8-31BF31E4-31EF321F32FF4DB6-4DBF9FCC-9FFFA48D-A48FA4C7-A4CFA62C-A63FA660A661A674-A67BA698-A69FA6F8-A6FFA78D-A7FAA82C-A82FA83A-A83FA878-A87FA8C5-A8CDA8DA-A8DFA8FC-A8FFA954-A95EA97D-A97FA9CEA9DA-A9DDA9E0-A9FFAA37-AA3FAA4EAA4FAA5AAA5BAA7C-AA7FAAC3-AADAAAE0-ABBFABEEABEFABFA-ABFFD7A4-D7AFD7C7-D7CAD7FC-D7FFFA2EFA2FFA6EFA6FFADA-FAFFFB07-FB12FB18-FB1CFB37FB3DFB3FFB42FB45FBB2-FBD2FD40-FD4FFD90FD91FDC8-FDEFFDFEFDFFFE1A-FE1FFE27-FE2FFE53FE67FE6C-FE6FFE75FEFDFEFEFF00FFBF-FFC1FFC8FFC9FFD0FFD1FFD8FFD9FFDD-FFDFFFE7FFEF-FFF8FFFEFFFF"})}),define("ace/document",["require","exports","module","ace/lib/oop","ace/lib/event_emitter","ace/range","ace/anchor"],function(a,b,c){"use strict";var d=a("./lib/oop"),e=a("./lib/event_emitter").EventEmitter,f=a("./range").Range,g=a("./anchor").Anchor,h=function(a){this.$lines=[],Array.isArray(a)?this.insertLines(0,a):a.length==0?this.$lines=[""]:this.insert({row:0,column:0},a)};((function(){d.implement(this,e),this.setValue=function(a){var b=this.getLength();this.remove(new f(0,0,b,this.getLine(b-1).length)),this.insert({row:0,column:0},a)},this.getValue=function(){return this.getAllLines().join(this.getNewLineCharacter())},this.createAnchor=function(a,b){return new g(this,a,b)},"aaa".split(/a/).length==0?this.$split=function(a){return a.replace(/\r\n|\r/g,"\n").split("\n")}:this.$split=function(a){return a.split(/\r\n|\r|\n/)},this.$detectNewLine=function(a){var b=a.match(/^.*?(\r\n|\r|\n)/m);b?this.$autoNewLine=b[1]:this.$autoNewLine="\n"},this.getNewLineCharacter=function(){switch(this.$newLineMode){case"windows":return"\r\n";case"unix":return"\n";case"auto":return this.$autoNewLine}},this.$autoNewLine="\n",this.$newLineMode="auto",this.setNewLineMode=function(a){if(this.$newLineMode===a)return;this.$newLineMode=a},this.getNewLineMode=function(){return this.$newLineMode},this.isNewLine=function(a){return a=="\r\n"||a=="\r"||a=="\n"},this.getLine=function(a){return this.$lines[a]||""},this.getLines=function(a,b){return this.$lines.slice(a,b+1)},this.getAllLines=function(){return this.getLines(0,this.getLength())},this.getLength=function(){return this.$lines.length},this.getTextRange=function(a){if(a.start.row==a.end.row)return this.$lines[a.start.row].substring(a.start.column,a.end.column);var b=[];return b.push(this.$lines[a.start.row].substring(a.start.column)),b.push.apply(b,this.getLines(a.start.row+1,a.end.row-1)),b.push(this.$lines[a.end.row].substring(0,a.end.column)),b.join(this.getNewLineCharacter())},this.$clipPosition=function(a){var b=this.getLength();return a.row>=b&&(a.row=Math.max(0,b-1),a.column=this.getLine(b-1).length),a},this.insert=function(a,b){if(b.length==0)return a;a=this.$clipPosition(a),this.getLength()<=1&&this.$detectNewLine(b);var c=this.$split(b),d=c.splice(0,1)[0],e=c.length==0?null:c.splice(c.length-1,1)[0];return a=this.insertInLine(a,d),e!==null&&(a=this.insertNewLine(a),a=this.insertLines(a.row,c),a=this.insertInLine(a,e||"")),a},this.insertLines=function(a,b){if(b.length==0)return{row:a,column:0};var c=[a,0];c.push.apply(c,b),this.$lines.splice.apply(this.$lines,c);var d=new f(a,0,a+b.length,0),e={action:"insertLines",range:d,lines:b};return this._emit("change",{data:e}),d.end},this.insertNewLine=function(a){a=this.$clipPosition(a);var b=this.$lines[a.row]||"";this.$lines[a.row]=b.substring(0,a.column),this.$lines.splice(a.row+1,0,b.substring(a.column,b.length));var c={row:a.row+1,column:0},d={action:"insertText",range:f.fromPoints(a,c),text:this.getNewLineCharacter()};return this._emit("change",{data:d}),c},this.insertInLine=function(a,b){if(b.length==0)return a;var c=this.$lines[a.row]||"";this.$lines[a.row]=c.substring(0,a.column)+b+c.substring(a.column);var d={row:a.row,column:a.column+b.length},e={action:"insertText",range:f.fromPoints(a,d),text:b};return this._emit("change",{data:e}),d},this.remove=function(a){a.start=this.$clipPosition(a.start),a.end=this.$clipPosition(a.end);if(a.isEmpty())return a.start;var b=a.start.row,c=a.end.row;if(a.isMultiLine()){var d=a.start.column==0?b:b+1,e=c-1;a.end.column>0&&this.removeInLine(c,0,a.end.column),e>=d&&this.removeLines(d,e),d!=b&&(this.removeInLine(b,a.start.column,this.getLine(b).length),this.removeNewLine(a.start.row))}else this.removeInLine(b,a.start.column,a.end.column);return a.start},this.removeInLine=function(a,b,c){if(b==c)return;var d=new f(a,b,a,c),e=this.getLine(a),g=e.substring(b,c),h=e.substring(0,b)+e.substring(c,e.length);this.$lines.splice(a,1,h);var i={action:"removeText",range:d,text:g};return this._emit("change",{data:i}),d.start},this.removeLines=function(a,b){var c=new f(a,0,b+1,0),d=this.$lines.splice(a,b-a+1),e={action:"removeLines",range:c,nl:this.getNewLineCharacter(),lines:d};return this._emit("change",{data:e}),d},this.removeNewLine=function(a){var b=this.getLine(a),c=this.getLine(a+1),d=new f(a,b.length,a+1,0),e=b+c;this.$lines.splice(a,2,e);var g={action:"removeText",range:d,text:this.getNewLineCharacter()};this._emit("change",{data:g})},this.replace=function(a,b){if(b.length==0&&a.isEmpty())return a.start;if(b==this.getTextRange(a))return a.end;this.remove(a);if(b)var c=this.insert(a.start,b);else c=a.start;return c},this.applyDeltas=function(a){for(var b=0;b<a.length;b++){var c=a[b],d=f.fromPoints(c.range.start,c.range.end);c.action=="insertLines"?this.insertLines(d.start.row,c.lines):c.action=="insertText"?this.insert(d.start,c.text):c.action=="removeLines"?this.removeLines(d.start.row,d.end.row-1):c.action=="removeText"&&this.remove(d)}},this.revertDeltas=function(a){for(var b=a.length-1;b>=0;b--){var c=a[b],d=f.fromPoints(c.range.start,c.range.end);c.action=="insertLines"?this.removeLines(d.start.row,d.end.row-1):c.action=="insertText"?this.remove(d):c.action=="removeLines"?this.insertLines(d.start.row,c.lines):c.action=="removeText"&&this.insert(d.start,c.text)}}})).call(h.prototype),b.Document=h}),define("ace/anchor",["require","exports","module","ace/lib/oop","ace/lib/event_emitter"],function(a,b,c){"use strict";var d=a("./lib/oop"),e=a("./lib/event_emitter").EventEmitter,f=b.Anchor=function(a,b,c){this.document=a,typeof c=="undefined"?this.setPosition(b.row,b.column):this.setPosition(b,c),this.$onChange=this.onChange.bind(this),a.on("change",this.$onChange)};((function(){d.implement(this,e),this.getPosition=function(){return this.$clipPositionToDocument(this.row,this.column)},this.getDocument=function(){return this.document},this.onChange=function(a){var b=a.data,c=b.range;if(c.start.row==c.end.row&&c.start.row!=this.row)return;if(c.start.row>this.row)return;if(c.start.row==this.row&&c.start.column>this.column)return;var d=this.row,e=this.column;b.action==="insertText"?c.start.row===d&&c.start.column<=e?c.start.row===c.end.row?e+=c.end.column-c.start.column:(e-=c.start.column,d+=c.end.row-c.start.row):c.start.row!==c.end.row&&c.start.row<d&&(d+=c.end.row-c.start.row):b.action==="insertLines"?c.start.row<=d&&(d+=c.end.row-c.start.row):b.action=="removeText"?c.start.row==d&&c.start.column<e?c.end.column>=e?e=c.start.column:e=Math.max(0,e-(c.end.column-c.start.column)):c.start.row!==c.end.row&&c.start.row<d?(c.end.row==d&&(e=Math.max(0,e-c.end.column)+c.start.column),d-=c.end.row-c.start.row):c.end.row==d&&(d-=c.end.row-c.start.row,e=Math.max(0,e-c.end.column)+c.start.column):b.action=="removeLines"&&c.start.row<=d&&(c.end.row<=d?d-=c.end.row-c.start.row:(d=c.start.row,e=0)),this.setPosition(d,e,!0)},this.setPosition=function(a,b,c){var d;c?d={row:a,column:b}:d=this.$clipPositionToDocument(a,b);if(this.row==d.row&&this.column==d.column)return;var e={row:this.row,column:this.column};this.row=d.row,this.column=d.column,this._emit("change",{old:e,value:d})},this.detach=function(){this.document.removeEventListener("change",this.$onChange)},this.$clipPositionToDocument=function(a,b){var c={};return a>=this.document.getLength()?(c.row=Math.max(0,this.document.getLength()-1),c.column=this.document.getLine(c.row).length):a<0?(c.row=0,c.column=0):(c.row=a,c.column=Math.min(this.document.getLine(c.row).length,Math.max(0,b))),b<0&&(c.column=0),c}})).call(f.prototype)}),define("ace/background_tokenizer",["require","exports","module","ace/lib/oop","ace/lib/event_emitter"],function(a,b,c){"use strict";var d=a("./lib/oop"),e=a("./lib/event_emitter").EventEmitter,f=function(a,b){this.running=!1,this.lines=[],this.currentLine=0,this.tokenizer=a;var c=this;this.$worker=function(){if(!c.running)return;var a=new Date,b=c.currentLine,d=c.doc,e=0,f=d.getLength();while(c.currentLine<f){c.lines[c.currentLine]=c.$tokenizeRows(c.currentLine,c.currentLine)[0],c.currentLine++,e+=1;if(e%5==0&&new Date-a>20){c.fireUpdateEvent(b,c.currentLine-1),c.running=setTimeout(c.$worker,20);return}}c.running=!1,c.fireUpdateEvent(b,f-1)}};((function(){d.implement(this,e),this.setTokenizer=function(a){this.tokenizer=a,this.lines=[],this.start(0)},this.setDocument=function(a){this.doc=a,this.lines=[],this.stop()},this.fireUpdateEvent=function(a,b){var c={first:a,last:b};this._emit("update",{data:c})},this.start=function(a){this.currentLine=Math.min(a||0,this.currentLine,this.doc.getLength()),this.lines.splice(this.currentLine,this.lines.length),this.stop(),this.running=setTimeout(this.$worker,700)},this.stop=function(){this.running&&clearTimeout(this.running),this.running=!1},this.getTokens=function(a,b){return this.$tokenizeRows(a,b)},this.getState=function(a){return this.$tokenizeRows(a,a)[0].state},this.$tokenizeRows=function(a,b){if(!this.doc||isNaN(a)||isNaN(b))return[{state:"start",tokens:[]}];var c=[],d="start",e=!1;a>0&&this.lines[a-1]?(d=this.lines[a-1].state,e=!0):a==0?(d="start",e=!0):this.lines.length>0&&(d=this.lines[this.lines.length-1].state);var f=this.doc.getLines(a,b);for(var g=a;g<=b;g++)if(!this.lines[g]){var h=this.tokenizer.getLineTokens(f[g-a]||"",d),d=h.state;c.push(h),e&&(this.lines[g]=h)}else{var h=this.lines[g];d=h.state,c.push(h)}return c}})).call(f.prototype),b.BackgroundTokenizer=f}),define("ace/edit_session/folding",["require","exports","module","ace/range","ace/edit_session/fold_line","ace/edit_session/fold","ace/token_iterator"],function(a,b,c){function h(){this.getFoldAt=function(a,b,c){var d=this.getFoldLine(a);if(!d)return null;var e=d.folds;for(var f=0;f<e.length;f++){var g=e[f];if(g.range.contains(a,b)){if(c==1&&g.range.isEnd(a,b))continue;if(c==-1&&g.range.isStart(a,b))continue;return g}}},this.getFoldsInRange=function(a){a=a.clone();var b=a.start,c=a.end,d=this.$foldData,e=[];b.column+=1,c.column-=1;for(var f=0;f<d.length;f++){var g=d[f].range.compareRange(a);if(g==2)continue;if(g==-2)break;var h=d[f].folds;for(var i=0;i<h.length;i++){var j=h[i];g=j.range.compareRange(a);if(g==-2)break;if(g==2)continue;if(g==42)break;e.push(j)}}return e},this.getAllFolds=function(){function c(b){a.push(b);if(!b.subFolds)return;for(var d=0;d<b.subFolds.length;d++)c(b.subFolds[d])}var a=[],b=this.$foldData;for(var d=0;d<b.length;d++)for(var e=0;e<b[d].folds.length;e++)c(b[d].folds[e]);return a},this.getFoldStringAt=function(a,b,c,d){d=d||this.getFoldLine(a);if(!d)return null;var e={end:{column:0}},f,g;for(var h=0;h<d.folds.length;h++){g=d.folds[h];var i=g.range.compareEnd(a,b);if(i==-1){f=this.getLine(g.start.row).substring(e.end.column,g.start.column);break}if(i===0)return null;e=g}return f||(f=this.getLine(g.start.row).substring(e.end.column)),c==-1?f.substring(0,b-e.end.column):c==1?f.substring(b-e.end.column):f},this.getFoldLine=function(a,b){var c=this.$foldData,d=0;b&&(d=c.indexOf(b)),d==-1&&(d=0);for(d;d<c.length;d++){var e=c[d];if(e.start.row<=a&&e.end.row>=a)return e;if(e.end.row>a)return null}return null},this.getNextFoldLine=function(a,b){var c=this.$foldData,d=0;b&&(d=c.indexOf(b)),d==-1&&(d=0);for(d;d<c.length;d++){var e=c[d];if(e.end.row>=a)return e}return null},this.getFoldedRowCount=function(a,b){var c=this.$foldData,d=b-a+1;for(var e=0;e<c.length;e++){var f=c[e],g=f.end.row,h=f.start.row;if(g>=b){h<b&&(h>=a?d-=b-h:d=0);break}g>=a&&(h>=a?d-=g-h:d-=g-a+1)}return d},this.$addFoldLine=function(a){return this.$foldData.push(a),this.$foldData.sort(function(a,b){return a.start.row-b.start.row}),a},this.addFold=function(a,b){var c=this.$foldData,d=!1,g;a instanceof f?g=a:g=new f(b,a),this.$clipRangeToDocument(g.range);var h=g.start.row,i=g.start.column,j=g.end.row,k=g.end.column;if(g.placeholder.length<2)throw"Placeholder has to be at least 2 characters";if(h==j&&k-i<2)throw"The range has to be at least 2 characters width";var l=this.getFoldAt(h,i,1),m=this.getFoldAt(j,k,-1);if(l&&m==l)return l.addSubFold(g);if(l&&!l.range.isStart(h,i)||m&&!m.range.isEnd(j,k))throw"A fold can't intersect already existing fold"+g.range+l.range;var n=this.getFoldsInRange(g.range);n.length>0&&(this.removeFolds(n),g.subFolds=n);for(var o=0;o<c.length;o++){var p=c[o];if(j==p.start.row){p.addFold(g),d=!0;break}if(h==p.end.row){p.addFold(g),d=!0;if(!g.sameRow){var q=c[o+1];if(q&&q.start.row==j){p.merge(q);break}}break}if(j<=p.start.row)break}return d||(p=this.$addFoldLine(new e(this.$foldData,g))),this.$useWrapMode&&this.$updateWrapData(p.start.row,p.start.row),this.$modified=!0,this._emit("changeFold",{data:g}),g},this.addFolds=function(a){a.forEach(function(a){this.addFold(a)},this)},this.removeFold=function(a){var b=a.foldLine,c=b.start.row,d=b.end.row,e=this.$foldData,f=b.folds;if(f.length==1)e.splice(e.indexOf(b),1);else if(b.range.isEnd(a.end.row,a.end.column))f.pop(),b.end.row=f[f.length-1].end.row,b.end.column=f[f.length-1].end.column;else if(b.range.isStart(a.start.row,a.start.column))f.shift(),b.start.row=f[0].start.row,b.start.column=f[0].start.column;else if(a.sameRow)f.splice(f.indexOf(a),1);else{var g=b.split(a.start.row,a.start.column);f=g.folds,f.shift(),g.start.row=f[0].start.row,g.start.column=f[0].start.column}this.$useWrapMode&&this.$updateWrapData(c,d),this.$modified=!0,this._emit("changeFold",{data:a})},this.removeFolds=function(a){var b=[];for(var c=0;c<a.length;c++)b.push(a[c]);b.forEach(function(a){this.removeFold(a)},this),this.$modified=!0},this.expandFold=function(a){this.removeFold(a),a.subFolds.forEach(function(a){this.addFold(a)},this),a.subFolds=[]},this.expandFolds=function(a){a.forEach(function(a){this.expandFold(a)},this)},this.unfold=function(a,b){var c,e;a==null?c=new d(0,0,this.getLength(),0):typeof a=="number"?c=new d(a,0,a,this.getLine(a).length):"row"in a?c=d.fromPoints(a,a):c=a,e=this.getFoldsInRange(c);if(b)this.removeFolds(e);else while(e.length)this.expandFolds(e),e=this.getFoldsInRange(c)},this.isRowFolded=function(a,b){return!!this.getFoldLine(a,b)},this.getRowFoldEnd=function(a,b){var c=this.getFoldLine(a,b);return c?c.end.row:a},this.getFoldDisplayLine=function(a,b,c,d,e){d==null&&(d=a.start.row,e=0),b==null&&(b=a.end.row,c=this.getLine(b).length);var f=this.doc,g="";return a.walk(function(a,b,c,h){if(b<d)return;if(b==d){if(c<e)return;h=Math.max(e,h)}a?g+=a:g+=f.getLine(b).substring(h,c)}.bind(this),b,c),g},this.getDisplayLine=function(a,b,c,d){var e=this.getFoldLine(a);if(!e){var f;return f=this.doc.getLine(a),f.substring(d||0,b||f.length)}return this.getFoldDisplayLine(e,a,b,c,d)},this.$cloneFoldData=function(){var a=[];return a=this.$foldData.map(function(b){var c=b.folds.map(function(a){return a.clone()});return new e(a,c)}),a},this.toggleFold=function(a){var b=this.selection,c=b.getRange(),d,e;if(c.isEmpty()){var f=c.start;d=this.getFoldAt(f.row,f.column);if(d){this.expandFold(d);return}(e=this.findMatchingBracket(f))?c.comparePoint(e)==1?c.end=e:(c.start=e,c.start.column++,c.end.column--):(e=this.findMatchingBracket({row:f.row,column:f.column+1}))?(c.comparePoint(e)==1?c.end=e:c.start=e,c.start.column++):c=this.getCommentFoldRange(f.row,f.column)||c}else{var g=this.getFoldsInRange(c);if(a&&g.length){this.expandFolds(g);return}g.length==1&&(d=g[0])}d||(d=this.getFoldAt(c.start.row,c.start.column));if(d&&d.range.toString()==c.toString()){this.expandFold(d);return}var h="...";if(!c.isMultiLine()){h=this.getTextRange(c);if(h.length<4)return;h=h.trim().substring(0,2)+".."}this.addFold(h,c)},this.getCommentFoldRange=function(a,b){var c=new g(this,a,b),e=c.getCurrentToken();if(e&&/^comment|string/.test(e.type)){var f=new d,h=new RegExp(e.type.replace(/\..*/,"\\."));do e=c.stepBackward();while(e&&h.test(e.type));c.stepForward(),f.start.row=c.getCurrentTokenRow(),f.start.column=c.getCurrentTokenColumn()+2,c=new g(this,a,b);do e=c.stepForward();while(e&&h.test(e.type));return e=c.stepBackward(),f.end.row=c.getCurrentTokenRow(),f.end.column=c.getCurrentTokenColumn()+e.value.length,f}},this.foldAll=function(a,b){var c=this.foldWidgets;b=b||c.length;for(var d=a||0;d<b;d++){c[d]==null&&(c[d]=this.getFoldWidget(d));if(c[d]!="start")continue;var e=this.getFoldWidgetRange(d);if(e&&e.end.row<b)try{this.addFold("...",e)}catch(f){}}},this.$foldStyles={manual:1,markbegin:1,markbeginend:1},this.$foldStyle="markbegin",this.setFoldStyle=function(a){if(!this.$foldStyles[a])throw new Error("invalid fold style: "+a+"["+Object.keys(this.$foldStyles).join(", ")+"]");if(this.$foldStyle==a)return;this.$foldStyle=a,a=="manual"&&this.unfold();var b=this.$foldMode;this.$setFolding(null),this.$setFolding(b)},this.$setFolding=function(a){if(this.$foldMode==a)return;this.$foldMode=a,this.removeListener("change",this.$updateFoldWidgets),this._emit("changeAnnotation");if(!a||this.$foldStyle=="manual"){this.foldWidgets=null;return}this.foldWidgets=[],this.getFoldWidget=a.getFoldWidget.bind(a,this,this.$foldStyle),this.getFoldWidgetRange=a.getFoldWidgetRange.bind(a,this,this.$foldStyle),this.$updateFoldWidgets=this.updateFoldWidgets.bind(this),this.on("change",this.$updateFoldWidgets)},this.onFoldWidgetClick=function(a,b){var c=this.getFoldWidget(a),d=this.getLine(a),e=b.shiftKey,f=e||b.ctrlKey||b.altKey||b.metaKey,g;c=="end"?g=this.getFoldAt(a,0,-1):g=this.getFoldAt(a,d.length,1);if(g){f?this.removeFold(g):this.expandFold(g);return}var h=this.getFoldWidgetRange(a);if(h){if(!h.isMultiLine()){g=this.getFoldAt(h.start.row,h.start.column,1);if(g&&h.isEequal(g.range)){this.removeFold(g);return}}e||this.addFold("...",h),f&&this.foldAll(h.start.row+1,h.end.row)}else f&&this.foldAll(a+1,this.getLength()),b.target.className+=" invalid"},this.updateFoldWidgets=function(a){var b=a.data,c=b.range,d=c.start.row,e=c.end.row-d;if(e===0)this.foldWidgets[d]=null;else if(b.action=="removeText"||b.action=="removeLines")this.foldWidgets.splice(d,e+1,null);else{var f=Array(e+1);f.unshift(d,1),this.foldWidgets.splice.apply(this.foldWidgets,f)}}}"use strict";var d=a("../range").Range,e=a("./fold_line").FoldLine,f=a("./fold").Fold,g=a("../token_iterator").TokenIterator;b.Folding=h}),define("ace/edit_session/fold_line",["require","exports","module","ace/range"],function(a,b,c){function e(a,b){this.foldData=a,Array.isArray(b)?this.folds=b:b=this.folds=[b];var c=b[b.length-1];this.range=new d(b[0].start.row,b[0].start.column,c.end.row,c.end.column),this.start=this.range.start,this.end=this.range.end,this.folds.forEach(function(a){a.setFoldLine(this)},this)}"use strict";var d=a("../range").Range;((function(){this.shiftRow=function(a){this.start.row+=a,this.end.row+=a,this.folds.forEach(function(b){b.start.row+=a,b.end.row+=a})},this.addFold=function(a){if(a.sameRow){if(a.start.row<this.startRow||a.endRow>this.endRow)throw"Can't add a fold to this FoldLine as it has no connection";this.folds.push(a),this.folds.sort(function(a,b){return-a.range.compareEnd(b.start.row,b.start.column)}),this.range.compareEnd(a.start.row,a.start.column)>0?(this.end.row=a.end.row,this.end.column=a.end.column):this.range.compareStart(a.end.row,a.end.column)<0&&(this.start.row=a.start.row,this.start.column=a.start.column)}else if(a.start.row==this.end.row)this.folds.push(a),this.end.row=a.end.row,this.end.column=a.end.column;else if(a.end.row==this.start.row)this.folds.unshift(a),this.start.row=a.start.row,this.start.column=a.start.column;else throw"Trying to add fold to FoldRow that doesn't have a matching row";a.foldLine=this},this.containsRow=function(a){return a>=this.start.row&&a<=this.end.row},this.walk=function(a,b,c){var d=0,e=this.folds,f,g,h,i=!0;b==null&&(b=this.end.row,c=this.end.column);for(var j=0;j<e.length;j++){f=e[j],g=f.range.compareStart(b,c);if(g==-1){a(null,b,c,d,i);return}h=a(null,f.start.row,f.start.column,d,i),h=!h&&a(f.placeholder,f.start.row,f.start.column,d);if(h||g==0)return;i=!f.sameRow,d=f.end.column}a(null,b,c,d,i)},this.getNextFoldTo=function(a,b){var c,d;for(var e=0;e<this.folds.length;e++){c=this.folds[e],d=c.range.compareEnd(a,b);if(d==-1)return{fold:c,kind:"after"};if(d==0)return{fold:c,kind:"inside"}}return null},this.addRemoveChars=function(a,b,c){var d=this.getNextFoldTo(a,b),e,f;if(d){e=d.fold;if(d.kind=="inside"&&e.start.column!=b&&e.start.row!=a)throw"Moving characters inside of a fold should never be reached";if(e.start.row==a){f=this.folds;var g=f.indexOf(e);g==0&&(this.start.column+=c);for(g;g<f.length;g++){e=f[g],e.start.column+=c;if(!e.sameRow)return;e.end.column+=c}this.end.column+=c}}},this.split=function(a,b){var c=this.getNextFoldTo(a,b).fold,d=this.folds,f=this.foldData;if(!c)return null;var g=d.indexOf(c),h=d[g-1];this.end.row=h.end.row,this.end.column=h.end.column,d=d.splice(g,d.length-g);var i=new e(f,d);return f.splice(f.indexOf(this)+1,0,i),i},this.merge=function(a){var b=a.folds;for(var c=0;c<b.length;c++)this.addFold(b[c]);var d=this.foldData;d.splice(d.indexOf(a),1)},this.toString=function(){var a=[this.range.toString()+": ["];return this.folds.forEach(function(b){a.push("  "+b.toString())}),a.push("]"),a.join("\n")},this.idxToPosition=function(a){var b=0,c;for(var d=0;d<this.folds.length;d++){var c=this.folds[d];a-=c.start.column-b;if(a<0)return{row:c.start.row,column:c.start.column+a};a-=c.placeholder.length;if(a<0)return c.start;b=c.end.column}return{row:this.end.row,column:this.end.column+a}}})).call(e.prototype),b.FoldLine=e}),define("ace/edit_session/fold",["require","exports","module"],function(a,b,c){"use strict";var d=b.Fold=function(a,b){this.foldLine=null,this.placeholder=b,this.range=a,this.start=a.start,this.end=a.end,this.sameRow=a.start.row==a.end.row,this.subFolds=[]};((function(){this.toString=function(){return'"'+this.placeholder+'" '+this.range.toString()},this.setFoldLine=function(a){this.foldLine=a,this.subFolds.forEach(function(b){b.setFoldLine(a)})},this.clone=function(){var a=this.range.clone(),b=new d(a,this.placeholder);return this.subFolds.forEach(function(a){b.subFolds.push(a.clone())}),b},this.addSubFold=function(a){if(this.range.isEequal(a))return this;if(!this.range.containsRange(a))throw"A fold can't intersect already existing fold"+a.range+this.range;var b=a.range.start.row,c=a.range.start.column;for(var d=0,e=-1;d<this.subFolds.length;d++){e=this.subFolds[d].range.compare(b,c);if(e!=1)break}var f=this.subFolds[d];if(e==0)return f.addSubFold(a);var b=a.range.end.row,c=a.range.end.column;for(var g=d,e=-1;g<this.subFolds.length;g++){e=this.subFolds[g].range.compare(b,c);if(e!=1)break}var h=this.subFolds[g];if(e==0)throw"A fold can't intersect already existing fold"+a.range+this.range;var i=this.subFolds.splice(d,g-d,a);return a.setFoldLine(this.foldLine),a}})).call(d.prototype)}),define("ace/token_iterator",["require","exports","module"],function(a,b,c){"use strict";var d=function(a,b,c){this.$session=a,this.$row=b,this.$rowTokens=a.getTokens(b,b)[0].tokens;var d=a.getTokenAt(b,c);this.$tokenIndex=d?d.index:-1};((function(){this.stepBackward=function(){this.$tokenIndex-=1;while(this.$tokenIndex<0){this.$row-=1;if(this.$row<0)return this.$row=0,null;this.$rowTokens=this.$session.getTokens(this.$row,this.$row)[0].tokens,this.$tokenIndex=this.$rowTokens.length-1}return this.$rowTokens[this.$tokenIndex]},this.stepForward=function(){var a=this.$session.getLength();this.$tokenIndex+=1;while(this.$tokenIndex>=this.$rowTokens.length){this.$row+=1;if(this.$row>=a)return this.$row=a-1,null;this.$rowTokens=this.$session.getTokens(this.$row,this.$row)[0].tokens,this.$tokenIndex=0}return this.$rowTokens[this.$tokenIndex]},this.getCurrentToken=function(){return this.$rowTokens[this.$tokenIndex]},this.getCurrentTokenRow=function(){return this.$row},this.getCurrentTokenColumn=function(){var a=this.$rowTokens,b=this.$tokenIndex,c=a[b].start;if(c!==undefined)return c;c=0;while(b>0)b-=1,c+=a[b].value.length;return c}})).call(d.prototype),b.TokenIterator=d}),define("ace/edit_session/bracket_match",["require","exports","module","ace/token_iterator"],function(a,b,c){function e(){this.findMatchingBracket=function(a){if(a.column==0)return null;var b=this.getLine(a.row).charAt(a.column-1);if(b=="")return null;var c=b.match(/([\(\[\{])|([\)\]\}])/);return c?c[1]?this.$findClosingBracket(c[1],a):this.$findOpeningBracket(c[2],a):null},this.$brackets={")":"(","(":")","]":"[","[":"]","{":"}","}":"{"},this.$findOpeningBracket=function(a,b){var c=this.$brackets[a],e=1,f=new d(this,b.row,b.column),g=f.getCurrentToken();if(!g)return null;var h=new RegExp("(\\.?"+g.type.replace(".","|").replace("rparen","lparen|rparen")+")+"),i=b.column-f.getCurrentTokenColumn()-2,j=g.value;for(;;){while(i>=0){var k=j.charAt(i);if(k==c){e-=1;if(e==0)return{row:f.getCurrentTokenRow(),column:i+f.getCurrentTokenColumn()}}else k==a&&(e+=1);i-=1}do g=f.stepBackward();while(g&&!h.test(g.type));if(g==null)break;j=g.value,i=j.length-1}return null},this.$findClosingBracket=function(a,b){var c=this.$brackets[a],e=1,f=new d(this,b.row,b.column),g=f.getCurrentToken();if(!g)return null;var h=new RegExp("(\\.?"+g.type.replace(".","|").replace("lparen","lparen|rparen")+")+"),i=b.column-f.getCurrentTokenColumn();for(;;){var j=g.value,k=j.length;while(i<k){var l=j.charAt(i);if(l==c){e-=1;if(e==0)return{row:f.getCurrentTokenRow(),column:i+f.getCurrentTokenColumn()}}else l==a&&(e+=1);i+=1}do g=f.stepForward();while(g&&!h.test(g.type));if(g==null)break;i=0}return null}}"use strict";var d=a("../token_iterator").TokenIterator;b.BracketMatch=e}),define("ace/search",["require","exports","module","ace/lib/lang","ace/lib/oop","ace/range"],function(a,b,c){"use strict";var d=a("./lib/lang"),e=a("./lib/oop"),f=a("./range").Range,g=function(){this.$options={needle:"",backwards:!1,wrap:!1,caseSensitive:!1,wholeWord:!1,scope:g.ALL,regExp:!1}};g.ALL=1,g.SELECTION=2,function(){this.set=function(a){return e.mixin(this.$options,a),this},this.getOptions=function(){return d.copyObject(this.$options)},this.find=function(a){if(!this.$options.needle)return null;if(this.$options.backwards)var b=this.$backwardMatchIterator(a);else b=this.$forwardMatchIterator(a);var c=null;return b.forEach(function(a){return c=a,!0}),c},this.findAll=function(a){var b=this.$options;if(!b.needle)return[];if(b.backwards)var c=this.$backwardMatchIterator(a);else c=this.$forwardMatchIterator(a);var d=!b.start&&b.wrap&&b.scope==g.ALL;d&&(b.start={row:0,column:0});var e=[];return c.forEach(function(a){e.push(a)}),d&&(b.start=null),e},this.replace=function(a,b){var c=this.$assembleRegExp(),d=c.exec(a);return d&&d[0].length==a.length?this.$options.regExp?a.replace(c,b):b:null},this.$forwardMatchIterator=function(a){var b=this.$assembleRegExp(),c=this;return{forEach:function(d){c.$forwardLineIterator(a).forEach(function(a,e,f){e&&(a=a.substring(e));var g=[];a.replace(b,function(a){var b=arguments[arguments.length-2];return g.push({str:a,offset:e+b}),a});for(var h=0;h<g.length;h++){var i=g[h],j=c.$rangeFromMatch(f,i.offset,i.str.length);if(d(j))return!0}})}}},this.$backwardMatchIterator=function(a){var b=this.$assembleRegExp(),c=this;return{forEach:function(d){c.$backwardLineIterator(a).forEach(function(a,e,f){e&&(a=a.substring(e));var g=[];a.replace(b,function(a,b){return g.push({str:a,offset:e+b}),a});for(var h=g.length-1;h>=0;h--){var i=g[h],j=c.$rangeFromMatch(f,i.offset,i.str.length);if(d(j))return!0}})}}},this.$rangeFromMatch=function(a,b,c){return new f(a,b,a,b+c)},this.$assembleRegExp=function(){if(this.$options.regExp)var a=this.$options.needle;else a=d.escapeRegExp(this.$options.needle);this.$options.wholeWord&&(a="\\b"+a+"\\b");var b="g";this.$options.caseSensitive||(b+="i");var c=new RegExp(a,b);return c},this.$forwardLineIterator=function(a){function k(e){var f=a.getLine(e);return b&&e==c.end.row&&(f=f.substring(0,c.end.column)),j&&e==d.row&&(f=f.substring(0,d.column)),f}var b=this.$options.scope==g.SELECTION,c=this.$options.range||a.getSelection().getRange(),d=this.$options.start||c[b?"start":"end"],e=b?c.start.row:0,f=b?c.start.column:0,h=b?c.end.row:a.getLength()-1,i=this.$options.wrap,j=!1;return{forEach:function(a){var b=d.row,c=k(b),g=d.column,l=!1;j=!1;while(!a(c,g,b)){if(l)return;b++,g=0;if(b>h)if(i)b=e,g=f,j=!0;else return;b==d.row&&(l=!0),c=k(b)}}}},this.$backwardLineIterator=function(a){var b=this.$options.scope==g.SELECTION,c=this.$options.range||a.getSelection().getRange(),d=this.$options.start||c[b?"end":"start"],e=b?c.start.row:0,f=b?c.start.column:0,h=b?c.end.row:a.getLength()-1,i=this.$options.wrap;return{forEach:function(g){var j=d.row,k=a.getLine(j).substring(0,d.column),l=0,m=!1,n=!1;while(!g(k,l,j)){if(m)return;j--,l=0;if(j<e)if(i)j=h,n=!0;else return;j==d.row&&(m=!0),k=a.getLine(j),b&&(j==e?l=f:j==h&&(k=k.substring(0,c.end.column))),n&&j==d.row&&(l=d.column)}}}}}.call(g.prototype),b.Search=g}),define("ace/commands/command_manager",["require","exports","module","ace/lib/keys"],function(a,b,c){"use strict";var d=a("../lib/keys"),e=function(a,b){if(typeof a!="string")throw new TypeError("'platform' argument must be either 'mac' or 'win'");this.platform=a,this.commands={},this.commmandKeyBinding={},b&&b.forEach(this.addCommand,this)};((function(){function a(a,c,e){var f,g=0,h=b(a);for(var i=0,j=h.length;i<j;i++)d.KEY_MODS[h[i]]?g|=d.KEY_MODS[h[i]]:f=h[i]||"-";return{key:f,hashId:g}}function b(a,b){return a.toLowerCase().trim().split(new RegExp("[\\s ]*\\-[\\s ]*","g"),999)}this.addCommand=function(a){this.commands[a.name]&&this.removeCommand(a),this.commands[a.name]=a,a.bindKey&&this._buildKeyHash(a)},this.removeCommand=function(a){var b=typeof a=="string"?a:a.name;a=this.commands[b],delete this.commands[b];var c=this.commmandKeyBinding;for(var d in c)for(var e in c[d])c[d][e]==a&&delete c[d][e]},this.addCommands=function(a){Object.keys(a).forEach(function(b){var c=a[b];if(typeof c=="string")return this.bindKey(c,b);typeof c=="function"&&(c={exec:c}),c.name||(c.name=b),this.addCommand(c)},this)},this.removeCommands=function(a){Object.keys(a).forEach(function(b){this.removeCommand(a[b])},this)},this.bindKey=function(b,c){if(!b)return;var d=this.commmandKeyBinding;b.split("|").forEach(function(b){var e=a(b,c),f=e.hashId;(d[f]||(d[f]={}))[e.key]=c})},this.bindKeys=function(a){Object.keys(a).forEach(function(b){this.bindKey(b,a[b])},this)},this._buildKeyHash=function(a){var b=a.bindKey;if(!b)return;var c=typeof b=="string"?b:b[this.platform];this.bindKey(c,a)},this.findKeyCommand=function c(a,b){typeof b=="number"&&(b=d.keyCodeToString(b));var c=this.commmandKeyBinding;return c[a]&&c[a][b.toLowerCase()]},this.exec=function(a,b,c){return typeof a=="string"&&(a=this.commands[a]),a?b&&b.$readOnly&&!a.readOnly?!1:(a.exec(b,c||{}),!0):!1},this.toggleRecording=function(){if(this.$inReplay)return;return this.recording?(this.macro.pop(),this.exec=this.normal_exec,this.macro.length||(this.macro=this.oldMacro),this.recording=!1):(this.oldMacro=this.macro,this.macro=[],this.normal_exec=this.exec,this.exec=function(a,b,c){return this.macro.push([a,c]),this.normal_exec(a,b,c)},this.recording=!0)},this.replay=function(a){if(this.$inReplay||!this.macro)return;if(this.recording)return this.toggleRecording();try{this.$inReplay=!0,this.macro.forEach(function(b){typeof b=="string"?this.exec(b,a):this.exec(b[0],a,b[1])},this)}finally{this.$inReplay=!1}},this.trimMacro=function(a){return a.map(function(a){return typeof a[0]!="string"&&(a[0]=a[0].name),a[1]||(a=a[0]),a})}})).call(e.prototype),b.CommandManager=e}),define("ace/undomanager",["require","exports","module"],function(a,b,c){"use strict";var d=function(){this.reset()};((function(){this.execute=function(a){var b=a.args[0];this.$doc=a.args[1],this.$undoStack.push(b),this.$redoStack=[]},this.undo=function(a){var b=this.$undoStack.pop(),c=null;return b&&(c=this.$doc.undoChanges(b,a),this.$redoStack.push(b)),c},this.redo=function(a){var b=this.$redoStack.pop(),c=null;return b&&(c=this.$doc.redoChanges(b,a),this.$undoStack.push(b)),c},this.reset=function(){this.$undoStack=[],this.$redoStack=[]},this.hasUndo=function(){return this.$undoStack.length>0},this.hasRedo=function(){return this.$redoStack.length>0}})).call(d.prototype),b.UndoManager=d}),define("ace/virtual_renderer",["require","exports","module","ace/lib/oop","ace/lib/dom","ace/lib/event","ace/lib/useragent","ace/layer/gutter","ace/layer/marker","ace/layer/text","ace/layer/cursor","ace/scrollbar","ace/renderloop","ace/lib/event_emitter","text!ace/css/editor.css"],function(a,b,c){"use strict";var d=a("./lib/oop"),e=a("./lib/dom"),f=a("./lib/event"),g=a("./lib/useragent"),h=a("./layer/gutter").Gutter,i=a("./layer/marker").Marker,j=a("./layer/text").Text,k=a("./layer/cursor").Cursor,l=a("./scrollbar").ScrollBar,m=a("./renderloop").RenderLoop,n=a("./lib/event_emitter").EventEmitter,o=a("text!./css/editor.css");e.importCssString(o,"ace_editor");var p=function(a,b){var c=this;this.container=a,e.addCssClass(a,"ace_editor"),this.setTheme(b),this.$gutter=e.createElement("div"),this.$gutter.className="ace_gutter",this.container.appendChild(this.$gutter),this.scroller=e.createElement("div"),this.scroller.className="ace_scroller",this.container.appendChild(this.scroller),this.content=e.createElement("div"),this.content.className="ace_content",this.scroller.appendChild(this.content),this.$gutterLayer=new h(this.$gutter),this.$gutterLayer.on("changeGutterWidth",this.onResize.bind(this,!0)),this.$markerBack=new i(this.content);var d=this.$textLayer=new j(this.content);this.canvas=d.element,this.$markerFront=new i(this.content),this.characterWidth=d.getCharacterWidth(),this.lineHeight=d.getLineHeight(),this.$cursorLayer=new k(this.content),this.$cursorPadding=8,this.$horizScroll=!0,this.$horizScrollAlwaysVisible=!0,this.scrollBar=new l(a),this.scrollBar.addEventListener("scroll",function(a){c.session.setScrollTop(a.data)}),this.scrollTop=0,this.scrollLeft=0,f.addListener(this.scroller,"scroll",function(){c.session.setScrollLeft(c.scroller.scrollLeft)}),this.cursorPos={row:0,column:0},this.$textLayer.addEventListener("changeCharaterSize",function(){c.characterWidth=d.getCharacterWidth(),c.lineHeight=d.getLineHeight(),c.$updatePrintMargin(),c.onResize(!0),c.$loop.schedule(c.CHANGE_FULL)}),this.$size={width:0,height:0,scrollerHeight:0,scrollerWidth:0},this.layerConfig={width:1,padding:0,firstRow:0,firstRowScreen:0,lastRow:0,lineHeight:1,characterWidth:1,minHeight:1,maxHeight:1,offset:0,height:1},this.$loop=new m(this.$renderChanges.bind(this),this.container.ownerDocument.defaultView),this.$loop.schedule(this.CHANGE_FULL),this.setPadding(4),this.$updatePrintMargin()};((function(){this.showGutter=!0,this.CHANGE_CURSOR=1,this.CHANGE_MARKER=2,this.CHANGE_GUTTER=4,this.CHANGE_SCROLL=8,this.CHANGE_LINES=16,this.CHANGE_TEXT=32,this.CHANGE_SIZE=64,this.CHANGE_MARKER_BACK=128,this.CHANGE_MARKER_FRONT=256,this.CHANGE_FULL=512,d.implement(this,n),this.setSession=function(a){this.session=a,this.$cursorLayer.setSession(a),this.$markerBack.setSession(a),this.$markerFront.setSession(a),this.$gutterLayer.setSession(a),this.$textLayer.setSession(a),this.$loop.schedule(this.CHANGE_FULL)},this.updateLines=function(a,b){b===undefined&&(b=Infinity),this.$changedLines?(this.$changedLines.firstRow>a&&(this.$changedLines.firstRow=a),this.$changedLines.lastRow<b&&(this.$changedLines.lastRow=b)):this.$changedLines={firstRow:a,lastRow:b},this.$loop.schedule(this.CHANGE_LINES)},this.updateText=function(){this.$loop.schedule(this.CHANGE_TEXT)},this.updateFull=function(){this.$loop.schedule(this.CHANGE_FULL)},this.updateFontSize=function(){this.$textLayer.checkForSizeChanges()},this.onResize=function(a){var b=this.CHANGE_SIZE,c=this.$size,d=e.getInnerHeight(this.container);if(a||c.height!=d)c.height=d,this.scroller.style.height=d+"px",c.scrollerHeight=this.scroller.clientHeight,this.scrollBar.setHeight(c.scrollerHeight),this.session&&(this.session.setScrollTop(this.getScrollTop()),b|=this.CHANGE_FULL);var f=e.getInnerWidth(this.container);if(a||c.width!=f){c.width=f;var g=this.showGutter?this.$gutter.offsetWidth:0;this.scroller.style.left=g+"px",c.scrollerWidth=Math.max(0,f-g-this.scrollBar.getWidth()),this.scroller.style.width=c.scrollerWidth+"px";if(this.session.getUseWrapMode()&&this.adjustWrapLimit()||a)b|=this.CHANGE_FULL}this.$loop.schedule(b)},this.adjustWrapLimit=function(){var a=this.$size.scrollerWidth-this.$padding*2,b=Math.floor(a/this.characterWidth);return this.session.adjustWrapLimit(b)},this.setShowInvisibles=function(a){this.$textLayer.setShowInvisibles(a)&&this.$loop.schedule(this.CHANGE_TEXT)},this.getShowInvisibles=function(){return this.$textLayer.showInvisibles},this.$showPrintMargin=!0,this.setShowPrintMargin=function(a){this.$showPrintMargin=a,this.$updatePrintMargin()},this.getShowPrintMargin=function(){return this.$showPrintMargin},this.$printMarginColumn=80,this.setPrintMarginColumn=function(a){this.$printMarginColumn=a,this.$updatePrintMargin()},this.getPrintMarginColumn=function(){return this.$printMarginColumn},this.getShowGutter=function(){return this.showGutter},this.setShowGutter=function(a){if(this.showGutter===a)return;this.$gutter.style.display=a?"block":"none",this.showGutter=a,this.onResize(!0)},this.$updatePrintMargin=function(){var a;if(!this.$showPrintMargin&&!this.$printMarginEl)return;this.$printMarginEl||(a=e.createElement("div"),a.className="ace_print_margin_layer",this.$printMarginEl=e.createElement("div"),this.$printMarginEl.className="ace_print_margin",a.appendChild(this.$printMarginEl),this.content.insertBefore(a,this.$textLayer.element));var b=this.$printMarginEl.style;b.left=this.characterWidth*this.$printMarginColumn+this.$padding+"px",b.visibility=this.$showPrintMargin?"visible":"hidden"},this.getContainerElement=function(){return this.container},this.getMouseEventTarget=function(){return this.content},this.getTextAreaContainer=function(){return this.container},this.moveTextAreaToCursor=function(a){if(g.isIE)return;if(this.layerConfig.lastRow===0)return;var b=this.$cursorLayer.getPixelPosition();if(!b)return;var c=this.content.getBoundingClientRect(),d=this.layerConfig.offset;a.style.left=c.left+b.left+"px",a.style.top=c.top+b.top-this.scrollTop+d+"px"},this.getFirstVisibleRow=function(){return this.layerConfig.firstRow},this.getFirstFullyVisibleRow=function(){return this.layerConfig.firstRow+(this.layerConfig.offset===0?0:1)},this.getLastFullyVisibleRow=function(){var a=Math.floor((this.layerConfig.height+this.layerConfig.offset)/this.layerConfig.lineHeight);return this.layerConfig.firstRow-1+a},this.getLastVisibleRow=function(){return this.layerConfig.lastRow},this.$padding=null,this.setPadding=function(a){this.$padding=a,this.$textLayer.setPadding(a),this.$cursorLayer.setPadding(a),this.$markerFront.setPadding(a),this.$markerBack.setPadding(a),this.$loop.schedule(this.CHANGE_FULL),this.$updatePrintMargin()},this.getHScrollBarAlwaysVisible=function(){return this.$horizScrollAlwaysVisible},this.setHScrollBarAlwaysVisible=function(a){this.$horizScrollAlwaysVisible!=a&&(this.$horizScrollAlwaysVisible=a,(!this.$horizScrollAlwaysVisible||!this.$horizScroll)&&this.$loop.schedule(this.CHANGE_SCROLL))},this.$updateScrollBar=function(){this.scrollBar.setInnerHeight(this.layerConfig.maxHeight),this.scrollBar.setScrollTop(this.scrollTop)},this.$renderChanges=function(a){if(!a||!this.session)return;(a&this.CHANGE_FULL||a&this.CHANGE_SIZE||a&this.CHANGE_TEXT||a&this.CHANGE_LINES||a&this.CHANGE_SCROLL)&&this.$computeLayerConfig();if(a&this.CHANGE_FULL){this.$textLayer.update(this.layerConfig),this.showGutter&&this.$gutterLayer.update(this.layerConfig),this.$markerBack.update(this.layerConfig),this.$markerFront.update(this.layerConfig),this.$cursorLayer.update(this.layerConfig),this.$updateScrollBar();return}if(a&this.CHANGE_SCROLL){a&this.CHANGE_TEXT||a&this.CHANGE_LINES?this.$textLayer.update(this.layerConfig):this.$textLayer.scrollLines(this.layerConfig),this.showGutter&&this.$gutterLayer.update(this.layerConfig),this.$markerBack.update(this.layerConfig),this.$markerFront.update(this.layerConfig),this.$cursorLayer.update(this.layerConfig),this.$updateScrollBar();return}a&this.CHANGE_TEXT?(this.$textLayer.update(this.layerConfig),this.showGutter&&this.$gutterLayer.update(this.layerConfig)):a&this.CHANGE_LINES?(this.$updateLines(),this.$updateScrollBar(),this.showGutter&&this.$gutterLayer.update(this.layerConfig)):a&this.CHANGE_GUTTER&&this.showGutter&&this.$gutterLayer.update(this.layerConfig),a&this.CHANGE_CURSOR&&this.$cursorLayer.update(this.layerConfig),a&(this.CHANGE_MARKER|this.CHANGE_MARKER_FRONT)&&this.$markerFront.update(this.layerConfig),a&(this.CHANGE_MARKER|this.CHANGE_MARKER_BACK)&&this.$markerBack.update(this.layerConfig),a&this.CHANGE_SIZE&&this.$updateScrollBar()},this.$computeLayerConfig=function(){var a=this.session,b=this.scrollTop%this.lineHeight,c=this.$size.scrollerHeight+this.lineHeight,d=this.$getLongestLine(),e=this.$horizScrollAlwaysVisible||this.$size.scrollerWidth-d<0,f=this.$horizScroll!==e;this.$horizScroll=e,f&&(this.scroller.style.overflowX=e?"scroll":"hidden");var g=this.session.getScreenLength()*this.lineHeight;this.session.setScrollTop(Math.max(0,Math.min(this.scrollTop,g-this.$size.scrollerHeight)));var h=Math.ceil(c/this.lineHeight)-1,i=Math.max(0,Math.round((this.scrollTop-b)/this.lineHeight)),j=i+h,k,l,m={lineHeight:this.lineHeight};i=a.screenToDocumentRow(i,0);var n=a.getFoldLine(i);n&&(i=n.start.row),k=a.documentToScreenRow(i,0),l=a.getRowHeight(m,i),j=Math.min(a.screenToDocumentRow(j,0),a.getLength()-1),c=this.$size.scrollerHeight+a.getRowHeight(m,j)+l,b=this.scrollTop-k*this.lineHeight,this.layerConfig={width:d,padding:this.$padding,firstRow:i,firstRowScreen:k,lastRow:j,lineHeight:this.lineHeight,characterWidth:this.characterWidth,minHeight:c,maxHeight:g,offset:b,height:this.$size.scrollerHeight},this.$gutterLayer.element.style.marginTop=-b+"px",this.content.style.marginTop=-b+"px",this.content.style.width=d+2*this.$padding+"px",this.content.style.height=c+"px",this.$desiredScrollLeft&&(this.scrollToX(this.$desiredScrollLeft),this.$desiredScrollLeft=0),f&&this.onResize(!0)},this.$updateLines=function(){var a=this.$changedLines.firstRow,b=this.$changedLines.lastRow;this.$changedLines=null;var c=this.layerConfig;if(c.width!=this.$getLongestLine())return this.$textLayer.update(c);if(a>c.lastRow+1)return;if(b<c.firstRow)return;if(b===Infinity){this.showGutter&&this.$gutterLayer.update(c),this.$textLayer.update(c);return}this.$textLayer.updateLines(c,a,b)},this.$getLongestLine=function(){var a=this.session.getScreenWidth();return this.$textLayer.showInvisibles&&(a+=1),Math.max(this.$size.scrollerWidth-2*this.$padding,Math.round(a*this.characterWidth))},this.updateFrontMarkers=function(){this.$markerFront.setMarkers(this.session.getMarkers(!0)),this.$loop.schedule(this.CHANGE_MARKER_FRONT)},this.updateBackMarkers=function(){this.$markerBack.setMarkers(this.session.getMarkers()),this.$loop.schedule(this.CHANGE_MARKER_BACK)},this.addGutterDecoration=function(a,b){this.$gutterLayer.addGutterDecoration(a,b),this.$loop.schedule(this.CHANGE_GUTTER)},this.removeGutterDecoration=function(a,b){this.$gutterLayer.removeGutterDecoration(a,b),this.$loop.schedule(this.CHANGE_GUTTER)},this.setBreakpoints=function(a){this.$gutterLayer.setBreakpoints(a),this.$loop.schedule(this.CHANGE_GUTTER)},this.setAnnotations=function(a){this.$gutterLayer.setAnnotations(a),this.$loop.schedule(this.CHANGE_GUTTER)},this.updateCursor=function(){this.$loop.schedule(this.CHANGE_CURSOR)},this.hideCursor=function(){this.$cursorLayer.hideCursor()},this.showCursor=function(){this.$cursorLayer.showCursor()},this.scrollCursorIntoView=function(){if(this.$size.scrollerHeight===0)return;var a=this.$cursorLayer.getPixelPosition(),b=a.left,c=a.top;this.scrollTop>c&&this.session.setScrollTop(c),this.scrollTop+this.$size.scrollerHeight<c+this.lineHeight&&this.session.setScrollTop(c+this.lineHeight-this.$size.scrollerHeight);var d=this.scrollLeft;d>b&&(b<this.$padding+2*this.layerConfig.characterWidth&&(b=0),this.scrollToX(b)),d+this.$size.scrollerWidth<b+this.characterWidth&&(b>this.layerConfig.width+2*this.$padding?this.$desiredScrollLeft=b:this.scrollToX(Math.round(b+this.characterWidth-this.$size.scrollerWidth)))},this.getScrollTop=function(){return this.session.getScrollTop()},this.getScrollLeft=function(){return this.session.getScrollTop()},this.getScrollTopRow=function(){return this.scrollTop/this.lineHeight},this.getScrollBottomRow=function(){return Math.max(0,Math.floor((this.scrollTop+this.$size.scrollerHeight)/this.lineHeight)-1)},this.scrollToRow=function(a){this.session.setScrollTop(a*this.lineHeight)},this.scrollToLine=function(a,b){var c={lineHeight:this.lineHeight},d=0;for(var e=1;e<a;e++)d+=this.session.getRowHeight(c,e-1);b&&(d-=this.$size.scrollerHeight/2),this.session.setScrollTop(d)},this.scrollToY=function(a){this.scrollTop!==a&&(this.$loop.schedule(this.CHANGE_SCROLL),this.scrollTop=a)},this.scrollToX=function(a){a<=this.$padding&&(a=0),this.scroller.scrollLeft=a,a=this.scroller.scrollLeft},this.scrollBy=function(a,b){b&&this.session.setScrollTop(this.session.getScrollTop()+b),a&&this.session.setScrollLeft(this.session.getScrollLeft()+a)},this.isScrollableBy=function(a,b){if(b<0&&this.session.getScrollTop()>0)return!0;if(b>0&&this.session.getScrollTop()+this.$size.scrollerHeight<this.layerConfig.maxHeight)return!0},this.screenToTextCoordinates=function(a,b){var c=this.scroller.getBoundingClientRect(),d=Math.round((a+this.scrollLeft-c.left-this.$padding-e.getPageScrollLeft())/this.characterWidth),f=Math.floor((b+this.scrollTop-c.top-e.getPageScrollTop())/this.lineHeight);return this.session.screenToDocumentPosition(f,Math.max(d,0))},this.textToScreenCoordinates=function(a,b){var c=this.scroller.getBoundingClientRect(),d=this.session.documentToScreenPosition(a,b),e=this.$padding+Math.round(d.column*this.characterWidth),f=d.row*this.lineHeight;return{pageX:c.left+e-this.scrollLeft,pageY:c.top+f-this.scrollTop}},this.visualizeFocus=function(){e.addCssClass(this.container,"ace_focus")},this.visualizeBlur=function(){e.removeCssClass(this.container,"ace_focus")},this.showComposition=function(a){this.$composition||(this.$composition=e.createElement("div"),this.$composition.className="ace_composition",this.content.appendChild(this.$composition)),this.$composition.innerHTML="&#160;";var b=this.$cursorLayer.getPixelPosition(),c=this.$composition.style;c.top=b.top+"px",c.left=b.left+this.$padding+"px",c.height=this.lineHeight+"px",this.hideCursor()},this.setCompositionText=function(a){e.setInnerText(this.$composition,a)},this.hideComposition=function(){this.showCursor();if(!this.$composition)return;var a=this.$composition.style;a.top="-10000px",a.left="-10000px"},this.setTheme=function(b){function d(a){e.importCssString(a.cssText,a.cssClass,c.container.ownerDocument),c.$theme&&e.removeCssClass(c.container,c.$theme),c.$theme=a?a.cssClass:null,c.$theme&&e.addCssClass(c.container,c.$theme),a&&a.isDark?e.addCssClass(c.container,"ace_dark"):e.removeCssClass(c.container,"ace_dark"),c.$size&&(c.$size.width=0,c.onResize())}var c=this;this.$themeValue=b,!b||typeof b=="string"?(b=b||"ace/theme/textmate",a([b],function(a){d(a)})):d(b)},this.getTheme=function(){return this.$themeValue},this.setStyle=function(a){e.addCssClass(this.container,a)},this.unsetStyle=function(a){e.removeCssClass(this.container,a)},this.destroy=function(){this.$textLayer.destroy(),this.$cursorLayer.destroy()}})).call(p.prototype),b.VirtualRenderer=p}),define("ace/layer/gutter",["require","exports","module","ace/lib/dom","ace/lib/oop","ace/lib/event_emitter"],function(a,b,c){"use strict";var d=a("../lib/dom"),e=a("../lib/oop"),f=a("../lib/event_emitter").EventEmitter,g=function(a){this.element=d.createElement("div"),this.element.className="ace_layer ace_gutter-layer",a.appendChild(this.element),this.setShowFoldWidgets(this.$showFoldWidgets),this.gutterWidth=0,this.$breakpoints=[],this.$annotations=[],this.$decorations=[]};((function(){e.implement(this,f),this.setSession=function(a){this.session=a},this.addGutterDecoration=function(a,b){this.$decorations[a]||(this.$decorations[a]=""),this.$decorations[a]+=" ace_"+b},this.removeGutterDecoration=function(a,b){this.$decorations[a]=this.$decorations[a].replace(" ace_"+b,"")},this.setBreakpoints=function(a){this.$breakpoints=a.concat()},this.setAnnotations=function(a){this.$annotations=[];for(var b in a)if(a.hasOwnProperty(b)){var c=a[b];if(!c)continue;var d=this.$annotations[b]={text:[]};for(var e=0;e<c.length;e++){var f=c[e],g=f.text.replace(/"/g,"&quot;").replace(/'/g,"&#8217;").replace(/</,"&lt;");d.text.indexOf(g)===-1&&d.text.push(g);var h=f.type;h=="error"?d.className="ace_error":h=="warning"&&d.className!="ace_error"?d.className="ace_warning":h=="info"&&!d.className&&(d.className="ace_info")}}},this.update=function(a){this.$config=a;var b={className:"",text:[]},c=[],e=a.firstRow,f=a.lastRow,g=this.session.getNextFoldLine(e),h=g?g.start.row:Infinity,i=this.$showFoldWidgets&&this.session.foldWidgets;for(;;){e>h&&(e=g.end.row+1,g=this.session.getNextFoldLine(e,g),h=g?g.start.row:Infinity);if(e>f)break;var j=this.$annotations[e]||b;c.push("<div class='ace_gutter-cell",this.$decorations[e]||"",this.$breakpoints[e]?" ace_breakpoint ":" ",j.className,"' title='",j.text.join("\n"),"' style='height:",a.lineHeight,"px;'>",e+1);if(i){var k=i[e];k==null&&(k=i[e]=this.session.getFoldWidget(e)),k&&c.push("<span class='ace_fold-widget ",k,k=="start"&&e==h&&e<g.end.row?" closed":" open","'></span>")}var l=this.session.getRowLength(e)-1;while(l--)c.push("</div><div class='ace_gutter-cell' style='height:",a.lineHeight,"px'>¦");c.push("</div>"),e++}this.element=d.setInnerHtml(this.element,c.join("")),this.element.style.height=a.minHeight+"px";var m=this.element.offsetWidth;m!==this.gutterWidth&&(this.gutterWidth=m,this._emit("changeGutterWidth",m))},this.$showFoldWidgets=!0,this.setShowFoldWidgets=function(a){a?d.addCssClass(this.element,"ace_folding-enabled"):d.removeCssClass(this.element,"ace_folding-enabled"),this.$showFoldWidgets=a},this.getShowFoldWidgets=function(){return this.$showFoldWidgets}})).call(g.prototype),b.Gutter=g}),define("ace/layer/marker",["require","exports","module","ace/range","ace/lib/dom"],function(a,b,c){"use strict";var d=a("../range").Range,e=a("../lib/dom"),f=function(a){this.element=e.createElement("div"),this.element.className="ace_layer ace_marker-layer",a.appendChild(this.element)};((function(){this.$padding=0,this.setPadding=function(a){this.$padding=a},this.setSession=function(a){this.session=a},this.setMarkers=function(a){this.markers=a},this.update=function(a){var a=a||this.config;if(!a)return;this.config=a;var b=[];for(var c in this.markers){var d=this.markers[c],f=d.range.clipRows(a.firstRow,a.lastRow);if(f.isEmpty())continue;f=f.toScreenRange(this.session);if(d.renderer){var g=this.$getTop(f.start.row,a),h=Math.round(this.$padding+f.start.column*a.characterWidth);d.renderer(b,f,h,g,a)}else f.isMultiLine()?d.type=="text"?this.drawTextMarker(b,f,d.clazz,a):this.drawMultiLineMarker(b,f,d.clazz,a,d.type):this.drawSingleLineMarker(b,f,d.clazz,a,null,d.type)}this.element=e.setInnerHtml(this.element,b.join(""))},this.$getTop=function(a,b){return(a-b.firstRowScreen)*b.lineHeight},this.drawTextMarker=function(a,b,c,e){var f=b.start.row,g=new d(f,b.start.column,f,this.session.getScreenLastRowColumn(f));this.drawSingleLineMarker(a,g,c,e,1,"text"),f=b.end.row,g=new d(f,0,f,b.end.column),this.drawSingleLineMarker(a,g,c,e,0,"text");for(f=b.start.row+1;f<b.end.row;f++)g.start.row=f,g.end.row=f,g.end.column=this.session.getScreenLastRowColumn(f),this.drawSingleLineMarker(a,g,c,e,1,"text")},this.drawMultiLineMarker=function(a,b,c,d,e){var f=e==="background"?0:this.$padding,g=d.width+2*this.$padding-f,h=d.lineHeight,i=Math.round(g-b.start.column*d.characterWidth),j=this.$getTop(b.start.row,d),k=Math.round(f+b.start.column*d.characterWidth);a.push("<div class='",c,"' style='","height:",h,"px;","width:",i,"px;","top:",j,"px;","left:",k,"px;'></div>"),j=this.$getTop(b.end.row,d),i=Math.round(b.end.column*d.characterWidth),a.push("<div class='",c,"' style='","height:",h,"px;","width:",i,"px;","top:",j,"px;","left:",f,"px;'></div>"),h=(b.end.row-b.start.row-1)*d.lineHeight;if(h<0)return;j=this.$getTop(b.start.row+1,d),a.push("<div class='",c,"' style='","height:",h,"px;","width:",g,"px;","top:",j,"px;","left:",f,"px;'></div>")},this.drawSingleLineMarker=function(a,b,c,d,e,f){var g=f==="background"?0:this.$padding,h=d.lineHeight;if(f==="background")var i=d.width;else i=Math.round((b.end.column+(e||0)-b.start.column)*d.characterWidth);var j=this.$getTop(b.start.row,d),k=Math.round(g+b.start.column*d.characterWidth);a.push("<div class='",c,"' style='","height:",h,"px;","width:",i,"px;","top:",j,"px;","left:",k,"px;'></div>")}})).call(f.prototype),b.Marker=f}),define("ace/layer/text",["require","exports","module","ace/lib/oop","ace/lib/dom","ace/lib/lang","ace/lib/useragent","ace/lib/event_emitter"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("../lib/dom"),f=a("../lib/lang"),g=a("../lib/useragent"),h=a("../lib/event_emitter").EventEmitter,i=function(a){this.element=e.createElement("div"),this.element.className="ace_layer ace_text-layer",a.appendChild(this.element),this.$characterSize=this.$measureSizes()||{width:0,height:0},this.$pollSizeChanges()};((function(){d.implement(this,h),this.EOF_CHAR="¶",this.EOL_CHAR="¬",this.TAB_CHAR="→",this.SPACE_CHAR="·",this.$padding=0,this.setPadding=function(a){this.$padding=a,this.element.style.padding="0 "+a+"px"},this.getLineHeight=function(){return this.$characterSize.height||1},this.getCharacterWidth=function(){return this.$characterSize.width||1},this.checkForSizeChanges=function(){var a=this.$measureSizes();a&&(this.$characterSize.width!==a.width||this.$characterSize.height!==a.height)&&(this.$characterSize=a,this._emit("changeCharaterSize",{data:a}))},this.$pollSizeChanges=function(){var a=this;this.$pollSizeChangesTimer=setInterval(function(){a.checkForSizeChanges()},500)},this.$fontStyles={fontFamily:1,fontSize:1,fontWeight:1,fontStyle:1,lineHeight:1},this.$measureSizes=function(){var a=1e3;if(!this.$measureNode){var b=this.$measureNode=e.createElement("div"),c=b.style;c.width=c.height="auto",c.left=c.top=-a*40+"px",c.visibility="hidden",c.position="absolute",c.overflow="visible",c.whiteSpace="nowrap",b.innerHTML=f.stringRepeat("Xy",a);if(this.element.ownerDocument.body)this.element.ownerDocument.body.appendChild(b);else{var d=this.element.parentNode;while(!e.hasCssClass(d,"ace_editor"))d=d.parentNode;d.appendChild(b)}}var c=this.$measureNode.style,g=e.computedStyle(this.element);for(var h in this.$fontStyles)c[h]=g[h];var i={height:this.$measureNode.offsetHeight,width:this.$measureNode.offsetWidth/(a*2)};return i.width==0&&i.height==0?null:i},this.setSession=function(a){this.session=a},this.showInvisibles=!1,this.setShowInvisibles=function(a){return this.showInvisibles==a?!1:(this.showInvisibles=a,!0)},this.$tabStrings=[],this.$computeTabString=function(){var a=this.session.getTabSize(),b=this.$tabStrings=[0];for(var c=1;c<a+1;c++)this.showInvisibles?b.push("<span class='ace_invisible'>"+this.TAB_CHAR+(new Array(c)).join("&#160;")+"</span>"):b.push((new Array(c+1)).join("&#160;"))},this.updateLines=function(a,b,c){this.$computeTabString(),(this.config.lastRow!=a.lastRow||this.config.firstRow!=a.firstRow)&&this.scrollLines(a),this.config=a;var d=Math.max(b,a.firstRow),f=Math.min(c,a.lastRow),g=this.element.childNodes,h=0;for(var i=a.firstRow;i<d;i++){var j=this.session.getFoldLine(i);if(j){if(j.containsRow(d)){d=j.start.row;break}i=j.end.row}h++}for(var k=d;k<=f;k++){var l=g[h++];if(!l)continue;var m=[],n=this.session.getTokens(k,k);this.$renderLine(m,k,n[0].tokens,!this.$useLineGroups()),l=e.setInnerHtml(l,m.join("")),k=this.session.getRowFoldEnd(k)}},this.scrollLines=function(a){this.$computeTabString();var b=this.config;this.config=a;if(!b||b.lastRow<a.firstRow)return this.update(a);if(a.lastRow<b.firstRow)return this.update(a);var c=this.element;if(b.firstRow<a.firstRow)for(var d=this.session.getFoldedRowCount(b.firstRow,a.firstRow-1);d>0;d--)c.removeChild(c.firstChild);if(b.lastRow>a.lastRow)for(var d=this.session.getFoldedRowCount(a.lastRow+1,b.lastRow);d>0;d--)c.removeChild(c.lastChild);if(a.firstRow<b.firstRow){var e=this.$renderLinesFragment(a,a.firstRow,b.firstRow-1);c.firstChild?c.insertBefore(e,c.firstChild):c.appendChild(e)}if(a.lastRow>b.lastRow){var e=this.$renderLinesFragment(a,b.lastRow+1,a.lastRow);c.appendChild(e)}},this.$renderLinesFragment=function(a,b,c){var d=this.element.ownerDocument.createDocumentFragment(),f=b,g=this.session.getNextFoldLine(f),h=g?g.start.row:Infinity;for(;;){f>h&&(f=g.end.row+1,g=this.session.getNextFoldLine(f,g),h=g?g.start.row:Infinity);if(f>c)break;var i=e.createElement("div"),j=[],k=this.session.getTokens(f,f);k.length==1&&this.$renderLine(j,f,k[0].tokens,!1),i.innerHTML=j.join("");if(this.$useLineGroups())i.className="ace_line_group",d.appendChild(i);else{var l=i.childNodes;while(l.length)d.appendChild(l[0])}f++}return d},this.update=function(a){this.$computeTabString(),this.config=a;var b=[],c=a.firstRow,d=a.lastRow,f=c,g=this.session.getNextFoldLine(f),h=g?g.start.row:Infinity;for(;;){f>h&&(f=g.end.row+1,g=this.session.getNextFoldLine(f,g),h=g?g.start.row:Infinity);if(f>d)break;this.$useLineGroups()&&b.push("<div class='ace_line_group'>");var i=this.session.getTokens(f,f);i.length==1&&this.$renderLine(b,f,i[0].tokens,!1),this.$useLineGroups()&&b.push("</div>"),f++}this.element=e.setInnerHtml(this.element,b.join(""))},this.$textToken={text:!0,rparen:!0,lparen:!0},this.$renderToken=function(a,b,c,d){var e=this,f=/\t|&|<|( +)|([\v\f \u00a0\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u200b\u2028\u2029\u3000])|[\u1100-\u115F]|[\u11A3-\u11A7]|[\u11FA-\u11FF]|[\u2329-\u232A]|[\u2E80-\u2E99]|[\u2E9B-\u2EF3]|[\u2F00-\u2FD5]|[\u2FF0-\u2FFB]|[\u3000-\u303E]|[\u3041-\u3096]|[\u3099-\u30FF]|[\u3105-\u312D]|[\u3131-\u318E]|[\u3190-\u31BA]|[\u31C0-\u31E3]|[\u31F0-\u321E]|[\u3220-\u3247]|[\u3250-\u32FE]|[\u3300-\u4DBF]|[\u4E00-\uA48C]|[\uA490-\uA4C6]|[\uA960-\uA97C]|[\uAC00-\uD7A3]|[\uD7B0-\uD7C6]|[\uD7CB-\uD7FB]|[\uF900-\uFAFF]|[\uFE10-\uFE19]|[\uFE30-\uFE52]|[\uFE54-\uFE66]|[\uFE68-\uFE6B]|[\uFF01-\uFF60]|[\uFFE0-\uFFE6]/g,h=function(a,c,d,f,h){if(a.charCodeAt(0)==32)return(new Array(a.length+1)).join("&#160;");if(a=="\t"){var i=e.session.getScreenTabSize(b+f);return b+=i-1,e.$tabStrings[i]}if(a=="&")return g.isOldGecko?"&":"&amp;";if(a=="<")return"&lt;";if(a==" "){var j=e.showInvisibles?"ace_cjk ace_invisible":"ace_cjk",k=e.showInvisibles?e.SPACE_CHAR:"";return b+=1,"<span class='"+j+"' style='width:"+e.config.characterWidth*2+"px'>"+k+"</span>"}if(a.match(/[\v\f \u00a0\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u200b\u2028\u2029\u3000]/)){if(e.showInvisibles){var k=(new Array(a.length+1)).join(e.SPACE_CHAR);return"<span class='ace_invisible'>"+k+"</span>"}return"&#160;"}return b+=1,"<span class='ace_cjk' style='width:"+e.config.characterWidth*2+"px'>"+a+"</span>"},i=d.replace(f,h);if(!this.$textToken[c.type]){var j="ace_"+c.type.replace(/\./g," ace_"),k="";c.type=="fold"&&(k=" style='width:"+c.value.length*this.config.characterWidth+"px;' "),a.push("<span class='",j,"'",k,">",i,"</span>")}else a.push(i);return b+d.length},this.$renderLineCore=function(a,b,c,d,e){var f=0,g=0,h,i=0,j=this;!d||d.length==0?h=Number.MAX_VALUE:h=d[0],e||a.push("<div class='ace_line' style='height:",this.config.lineHeight,"px","'>");for(var k=0;k<c.length;k++){var l=c[k],m=l.value;if(f+m.length<h)i=j.$renderToken(a,i,l,m),f+=m.length;else{while(f+m.length>=h)i=j.$renderToken(a,i,l,m.substring(0,h-f)),m=m.substring(h-f),f=h,e||a.push("</div>","<div class='ace_line' style='height:",this.config.lineHeight,"px","'>"),g++,i=0,h=d[g]||Number.MAX_VALUE;m.length!=0&&(f+=m.length,i=j.$renderToken(a,i,l,m))}}this.showInvisibles&&(b!==this.session.getLength()-1?a.push("<span class='ace_invisible'>"+this.EOL_CHAR+"</span>"):a.push("<span class='ace_invisible'>"+this.EOF_CHAR+"</span>")),e||a.push("</div>")},this.$renderLine=function(a,b,c,d){if(!this.session.isRowFolded(b)){var e=this.session.getRowSplitData(b);this.$renderLineCore(a,b,c,e,d)}else this.$renderFoldLine(a,b,c,d)},this.$renderFoldLine=function(a,b,c,d){function h(a,b,c){var d=0,e=0;while(e+a[d].value.length<b){e+=a[d].value.length,d++;if(d==a.length)return}if(e!=b){var f=a[d].value.substring(b-e);f.length>c-b&&(f=f.substring(0,c-b)),g.push({type:a[d].type,value:f}),e=b+f.length,d+=1}while(e<c){var f=a[d].value;f.length+e>c&&(f=f.substring(0,c-e)),g.push({type:a[d].type,value:f}),e+=f.length,d+=1}}var e=this.session,f=e.getFoldLine(b),g=[];f.walk(function(a,b,d,e,f){a?g.push({type:"fold",value:a}):(f&&(c=this.session.getTokens(b,b)[0].tokens),c.length!=0&&h(c,e,d))}.bind(this),f.end.row,this.session.getLine(f.end.row).length);var i=this.session.$useWrapMode?this.session.$wrapData[b]:null;this.$renderLineCore(a,b,g,i,d)},this.$useLineGroups=function(){return this.session.getUseWrapMode()},this.destroy=function(){clearInterval(this.$pollSizeChangesTimer),this.$measureNode&&this.$measureNode.parentNode.removeChild(this.$measureNode),delete this.$measureNode}})).call(i.prototype),b.Text=i}),define("ace/layer/cursor",["require","exports","module","ace/lib/dom"],function(a,b,c){"use strict";var d=a("../lib/dom"),e=function(a){this.element=d.createElement("div"),this.element.className="ace_layer ace_cursor-layer",a.appendChild(this.element),this.cursor=d.createElement("div"),this.cursor.className="ace_cursor ace_hidden",this.element.appendChild(this.cursor),this.isVisible=!1};((function(){this.$padding=0,this.setPadding=function(a){this.$padding=a},this.setSession=function(a){this.session=a},this.hideCursor=function(){this.isVisible=!1,d.addCssClass(this.cursor,"ace_hidden"),clearInterval(this.blinkId)},this.showCursor=function(){this.isVisible=!0,d.removeCssClass(this.cursor,"ace_hidden"),this.cursor.style.visibility="visible",this.restartTimer()},this.restartTimer=function(){clearInterval(this.blinkId);if(!this.isVisible)return;var a=this.cursor;this.blinkId=setInterval(function(){a.style.visibility="hidden",setTimeout(function(){a.style.visibility="visible"},400)},1e3)},this.getPixelPosition=function(a){if(!this.config||!this.session)return{left:0,top:0};var b=this.session.selection.getCursor(),c=this.session.documentToScreenPosition(b),d=Math.round(this.$padding+c.column*this.config.characterWidth),e=(c.row-(a?this.config.firstRowScreen:0))*this.config.lineHeight;return{left:d,top:e}},this.update=function(a){this.config=a,this.pixelPos=this.getPixelPosition(!0),this.cursor.style.left=this.pixelPos.left+"px",this.cursor.style.top=this.pixelPos.top+"px",this.cursor.style.width=a.characterWidth+"px",this.cursor.style.height=a.lineHeight+"px";var b=this.session.getOverwrite();b!=this.overwrite&&(this.overwrite=b,b?d.addCssClass(this.cursor,"ace_overwrite"):d.removeCssClass(this.cursor,"ace_overwrite")),this.restartTimer()},this.destroy=function(){clearInterval(this.blinkId)}})).call(e.prototype),b.Cursor=e}),define("ace/scrollbar",["require","exports","module","ace/lib/oop","ace/lib/dom","ace/lib/event","ace/lib/event_emitter"],function(a,b,c){"use strict";var d=a("./lib/oop"),e=a("./lib/dom"),f=a("./lib/event"),g=a("./lib/event_emitter").EventEmitter,h=function(a){this.element=e.createElement("div"),this.element.className="ace_sb",this.inner=e.createElement("div"),this.element.appendChild(this.inner),a.appendChild(this.element),this.width=e.scrollbarWidth(a.ownerDocument),this.element.style.width=(this.width||15)+5+"px",f.addListener(this.element,"scroll",this.onScroll.bind(this))};((function(){d.implement(this,g),this.onScroll=function(){this._emit("scroll",{data:this.element.scrollTop})},this.getWidth=function(){return this.width},this.setHeight=function(a){this.element.style.height=a+"px"},this.setInnerHeight=function(a){this.inner.style.height=a+"px"},this.setScrollTop=function(a){this.element.scrollTop=a}})).call(h.prototype),b.ScrollBar=h}),define("ace/renderloop",["require","exports","module","ace/lib/event"],function(a,b,c){"use strict";var d=a("./lib/event"),e=function(a,b){this.onRender=a,this.pending=!1,this.changes=0,this.window=b||window};((function(){this.schedule=function(a){this.changes=this.changes|a;if(!this.pending){this.pending=!0;var b=this;d.nextTick(function(){b.pending=!1;var a;while(a=b.changes)b.changes=0,b.onRender(a)},this.window)}}})).call(e.prototype),b.RenderLoop=e}),define("text!ace/css/editor.css",[],"@import url(//fonts.googleapis.com/css?family=Droid+Sans+Mono);\n\n\n.ace_editor {\n    position: absolute;\n    overflow: hidden;\n    font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', 'Droid Sans Mono', 'Courier New', monospace;\n    font-size: 12px;\n}\n\n.ace_scroller {\n    position: absolute;\n    overflow-x: scroll;\n    overflow-y: hidden;\n}\n\n.ace_content {\n    position: absolute;\n    box-sizing: border-box;\n    -moz-box-sizing: border-box;\n    -webkit-box-sizing: border-box;\n    cursor: text;\n}\n\n/* setting pointer-events: auto; on node under the mouse, which changes during scroll,\n  will break mouse wheel scrolling in Safari */\n.ace_content * {\n     pointer-events: none;\n}\n\n.ace_composition {\n    position: absolute;\n    background: #555;\n    color: #DDD;\n    z-index: 4;\n}\n\n.ace_gutter .ace_layer {\n    position: relative;\n    min-width: 54px;\n    text-align: right;\n}\n\n.ace_gutter {\n    position: absolute;\n    overflow : hidden;\n    height: 100%;\n    width: auto;\n    cursor: default;\n}\n\n.ace_gutter-cell {\n    padding-left: 19px;\n    padding-right: 6px;\n}\n\n.ace_gutter-cell.ace_error {\n    background-image: url(\"data:image/gif,GIF89a%10%00%10%00%D5%00%00%F5or%F5%87%88%F5nr%F4ns%EBmq%F5z%7F%DDJT%DEKS%DFOW%F1Yc%F2ah%CE(7%CE)8%D18E%DD%40M%F2KZ%EBU%60%F4%60m%DCir%C8%16(%C8%19*%CE%255%F1%3FR%F1%3FS%E6%AB%B5%CA%5DI%CEn%5E%F7%A2%9A%C9G%3E%E0a%5B%F7%89%85%F5yy%F6%82%80%ED%82%80%FF%BF%BF%E3%C4%C4%FF%FF%FF%FF%FF%FF%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00!%F9%04%01%00%00%25%00%2C%00%00%00%00%10%00%10%00%00%06p%C0%92pH%2C%1A%8F%C8%D2H%93%E1d4%23%E4%88%D3%09mB%1DN%B48%F5%90%40%60%92G%5B%94%20%3E%22%D2%87%24%FA%20%24%C5%06A%00%20%B1%07%02B%A38%89X.v%17%82%11%13q%10%0Fi%24%0F%8B%10%7BD%12%0Ei%09%92%09%0EpD%18%15%24%0A%9Ci%05%0C%18F%18%0B%07%04%01%04%06%A0H%18%12%0D%14%0D%12%A1I%B3%B4%B5IA%00%3B\");\n    background-repeat: no-repeat;\n    background-position: 2px center;\n}\n\n.ace_gutter-cell.ace_warning {\n    background-image: url(\"data:image/gif,GIF89a%10%00%10%00%D5%00%00%FF%DBr%FF%DE%81%FF%E2%8D%FF%E2%8F%FF%E4%96%FF%E3%97%FF%E5%9D%FF%E6%9E%FF%EE%C1%FF%C8Z%FF%CDk%FF%D0s%FF%D4%81%FF%D5%82%FF%D5%83%FF%DC%97%FF%DE%9D%FF%E7%B8%FF%CCl%7BQ%13%80U%15%82W%16%81U%16%89%5B%18%87%5B%18%8C%5E%1A%94d%1D%C5%83-%C9%87%2F%C6%84.%C6%85.%CD%8B2%C9%871%CB%8A3%CD%8B5%DC%98%3F%DF%9BB%E0%9CC%E1%A5U%CB%871%CF%8B5%D1%8D6%DB%97%40%DF%9AB%DD%99B%E3%B0p%E7%CC%AE%FF%FF%FF%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00!%F9%04%01%00%00%2F%00%2C%00%00%00%00%10%00%10%00%00%06a%C0%97pH%2C%1A%8FH%A1%ABTr%25%87%2B%04%82%F4%7C%B9X%91%08%CB%99%1C!%26%13%84*iJ9(%15G%CA%84%14%01%1A%97%0C%03%80%3A%9A%3E%81%84%3E%11%08%B1%8B%20%02%12%0F%18%1A%0F%0A%03'F%1C%04%0B%10%16%18%10%0B%05%1CF%1D-%06%07%9A%9A-%1EG%1B%A0%A1%A0U%A4%A5%A6BA%00%3B\");\n    background-repeat: no-repeat;\n    background-position: 2px center;\n}\n\n.ace_gutter-cell.ace_info {\n    background-image: url(\"data:image/gif;base64,R0lGODlhEAAQAMQAAAAAAEFBQVJSUl5eXmRkZGtra39/f4WFhYmJiZGRkaampry8vMPDw8zMzNXV1dzc3OTk5Orq6vDw8P///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAkAABQALAAAAAAQABAAAAUuICWOZGmeaBml5XGwFCQSBGyXRSAwtqQIiRuiwIM5BoYVbEFIyGCQoeJGrVptIQA7\");\n    background-repeat: no-repeat;\n    background-position: 2px center;\n}\n\n.ace_editor .ace_sb {\n    position: absolute;\n    overflow-x: hidden;\n    overflow-y: scroll;\n    right: 0;\n}\n\n.ace_editor .ace_sb div {\n    position: absolute;\n    width: 1px;\n    left: 0;\n}\n\n.ace_editor .ace_print_margin_layer {\n    z-index: 0;\n    position: absolute;\n    overflow: hidden;\n    margin: 0;\n    left: 0;\n    height: 100%;\n    width: 100%;\n}\n\n.ace_editor .ace_print_margin {\n    position: absolute;\n    height: 100%;\n}\n\n.ace_editor textarea {\n    position: fixed;\n    z-index: 0;\n    width: 10px;\n    height: 30px;\n    opacity: 0;\n    background: transparent;\n    appearance: none;\n    -moz-appearance: none;\n    border: none;\n    resize: none;\n    outline: none;\n    overflow: hidden;\n}\n\n.ace_layer {\n    z-index: 1;\n    position: absolute;\n    overflow: hidden;\n    white-space: nowrap;\n    height: 100%;\n    width: 100%;\n    box-sizing: border-box;\n    -moz-box-sizing: border-box;\n    -webkit-box-sizing: border-box;\n}\n\n.ace_text-layer {\n    color: black;\n}\n\n.ace_cjk {\n    display: inline-block;\n    text-align: center;\n}\n\n.ace_cursor-layer {\n    z-index: 4;\n}\n\n.ace_cursor {\n    z-index: 4;\n    position: absolute;\n}\n\n.ace_cursor.ace_hidden {\n    opacity: 0.2;\n}\n\n.ace_line {\n    white-space: nowrap;\n}\n\n.ace_marker-layer .ace_step {\n    position: absolute;\n    z-index: 3;\n}\n\n.ace_marker-layer .ace_selection {\n    position: absolute;\n    z-index: 4;\n}\n\n.ace_marker-layer .ace_bracket {\n    position: absolute;\n    z-index: 5;\n}\n\n.ace_marker-layer .ace_active_line {\n    position: absolute;\n    z-index: 2;\n}\n\n.ace_marker-layer .ace_selected_word {\n    position: absolute;\n    z-index: 6;\n    box-sizing: border-box;\n    -moz-box-sizing: border-box;\n    -webkit-box-sizing: border-box;\n}\n\n.ace_line .ace_fold {\n    box-sizing: border-box;\n    -moz-box-sizing: border-box;\n    -webkit-box-sizing: border-box;\n    \n    display: inline-block;\n    height: 11px;\n    margin-top: -2px;\n    vertical-align: middle;\n\n    background-image: \n        url(\"data:image/png,%89PNG%0D%0A%1A%0A%00%00%00%0DIHDR%00%00%00%11%00%00%00%09%08%06%00%00%00%D4%E8%C7%0C%00%00%03%1EiCCPICC%20Profile%00%00x%01%85T%DFk%D3P%14%FE%DAe%9D%B0%E1%8B%3Ag%11%09%3Eh%91ndStC%9C%B6kW%BA%CDZ%EA6%B7!H%9B%A6m%5C%9A%C6%24%ED~%B0%07%D9%8Bo%3A%C5w%F1%07%3E%F9%07%0C%D9%83o%7B%92%0D%C6%14a%F8%AC%88%22L%F6%22%B3%9E%9B4M'S%03%B9%F7%BB%DF%F9%EE9'%E7%E4%5E%A0%F9qZ%D3%14%2F%0F%14USO%C5%C2%FC%C4%E4%14%DF%F2%01%5E%1CC%2B%FChM%8B%86%16J%26G%40%0F%D3%B2y%EF%B3%F3%0E%1E%C6lt%EEo%DF%AB%FEc%D5%9A%95%0C%11%F0%1C%20%BE%945%C4%22%E1Y%A0i%5C%D4t%13%E0%D6%89%EF%9D15%C2%CDLsX%A7%04%09%1Fg8oc%81%E1%8C%8D%23%96f45%40%9A%09%C2%07%C5B%3AK%B8%408%98i%E0%F3%0D%D8%CE%81%14%E4'%26%A9%92.%8B%3C%ABER%2F%E5dE%B2%0C%F6%F0%1Fs%83%F2_%B0%A8%94%E9%9B%AD%E7%10%8Dm%9A%19N%D1%7C%8A%DE%1F9%7Dp%8C%E6%00%D5%C1%3F_%18%BDA%B8%9DpX6%E3%A35~B%CD%24%AE%11%26%BD%E7%EEti%98%EDe%9A%97Y)%12%25%1C%24%BCbT%AE3li%E6%0B%03%89%9A%E6%D3%ED%F4P%92%B0%9F4%BF43Y%F3%E3%EDP%95%04%EB1%C5%F5%F6KF%F4%BA%BD%D7%DB%91%93%07%E35%3E%A7)%D6%7F%40%FE%BD%F7%F5r%8A%E5y%92%F0%EB%B4%1E%8D%D5%F4%5B%92%3AV%DB%DB%E4%CD%A6%23%C3%C4wQ%3F%03HB%82%8E%1Cd(%E0%91B%0Ca%9Ac%C4%AA%F8L%16%19%22J%A4%D2itTy%B28%D6%3B(%93%96%ED%1CGx%C9_%0E%B8%5E%16%F5%5B%B2%B8%F6%E0%FB%9E%DD%25%D7%8E%BC%15%85%C5%B7%A3%D8Q%ED%B5%81%E9%BA%B2%13%9A%1B%7Fua%A5%A3n%E17%B9%E5%9B%1Bm%AB%0B%08Q%FE%8A%E5%B1H%5Ee%CAO%82Q%D7u6%E6%90S%97%FCu%0B%CF2%94%EE%25v%12X%0C%BA%AC%F0%5E%F8*l%0AO%85%17%C2%97%BF%D4%C8%CE%DE%AD%11%CB%80q%2C%3E%AB%9ES%CD%C6%EC%25%D2L%D2%EBd%B8%BF%8A%F5B%C6%18%F9%901CZ%9D%BE%24M%9C%8A9%F2%DAP%0B'%06w%82%EB%E6%E2%5C%2F%D7%07%9E%BB%CC%5D%E1%FA%B9%08%AD.r%23%8E%C2%17%F5E%7C!%F0%BE3%BE%3E_%B7o%88a%A7%DB%BE%D3d%EB%A31Z%EB%BB%D3%91%BA%A2%B1z%94%8F%DB'%F6%3D%8E%AA%13%19%B2%B1%BE%B1~V%08%2B%B4%A2cjJ%B3tO%00%03%25mN%97%F3%05%93%EF%11%84%0B%7C%88%AE-%89%8F%ABbW%90O%2B%0Ao%99%0C%5E%97%0CI%AFH%D9.%B0%3B%8F%ED%03%B6S%D6%5D%E6i_s9%F3*p%E9%1B%FD%C3%EB.7U%06%5E%19%C0%D1s.%17%A03u%E4%09%B0%7C%5E%2C%EB%15%DB%1F%3C%9E%B7%80%91%3B%DBc%AD%3Dma%BA%8B%3EV%AB%DBt.%5B%1E%01%BB%0F%AB%D5%9F%CF%AA%D5%DD%E7%E4%7F%0Bx%A3%FC%06%A9%23%0A%D6%C2%A1_2%00%00%00%09pHYs%00%00%0B%13%00%00%0B%13%01%00%9A%9C%18%00%00%00%B5IDAT(%15%A5%91%3D%0E%02!%10%85ac%E1%05%D6%CE%D6%C6%CE%D2%E8%ED%CD%DE%C0%C6%D6N.%E0V%F8%3D%9Ca%891XH%C2%BE%D9y%3F%90!%E6%9C%C3%BFk%E5%011%C6-%F5%C8N%04%DF%BD%FF%89%DFt%83DN%60%3E%F3%AB%A0%DE%1A%5Dg%BE%10Q%97%1B%40%9C%A8o%10%8F%5E%828%B4%1B%60%87%F6%02%26%85%1Ch%1E%C1%2B%5Bk%FF%86%EE%B7j%09%9A%DA%9B%ACe%A3%F9%EC%DA!9%B4%D5%A6%81%86%86%98%CC%3C%5B%40%FA%81%B3%E9%CB%23%94%C16Azo%05%D4%E1%C1%95a%3B%8A'%A0%E8%CC%17%22%85%1D%BA%00%A2%FA%DC%0A%94%D1%D1%8D%8B%3A%84%17B%C7%60%1A%25Z%FC%8D%00%00%00%00IEND%AEB%60%82\"),\n        url(\"data:image/png,%89PNG%0D%0A%1A%0A%00%00%00%0DIHDR%00%00%00%05%00%00%007%08%06%00%00%00%C4%DD%80C%00%00%03%1EiCCPICC%20Profile%00%00x%01%85T%DFk%D3P%14%FE%DAe%9D%B0%E1%8B%3Ag%11%09%3Eh%91ndStC%9C%B6kW%BA%CDZ%EA6%B7!H%9B%A6m%5C%9A%C6%24%ED~%B0%07%D9%8Bo%3A%C5w%F1%07%3E%F9%07%0C%D9%83o%7B%92%0D%C6%14a%F8%AC%88%22L%F6%22%B3%9E%9B4M'S%03%B9%F7%BB%DF%F9%EE9'%E7%E4%5E%A0%F9qZ%D3%14%2F%0F%14USO%C5%C2%FC%C4%E4%14%DF%F2%01%5E%1CC%2B%FChM%8B%86%16J%26G%40%0F%D3%B2y%EF%B3%F3%0E%1E%C6lt%EEo%DF%AB%FEc%D5%9A%95%0C%11%F0%1C%20%BE%945%C4%22%E1Y%A0i%5C%D4t%13%E0%D6%89%EF%9D15%C2%CDLsX%A7%04%09%1Fg8oc%81%E1%8C%8D%23%96f45%40%9A%09%C2%07%C5B%3AK%B8%408%98i%E0%F3%0D%D8%CE%81%14%E4'%26%A9%92.%8B%3C%ABER%2F%E5dE%B2%0C%F6%F0%1Fs%83%F2_%B0%A8%94%E9%9B%AD%E7%10%8Dm%9A%19N%D1%7C%8A%DE%1F9%7Dp%8C%E6%00%D5%C1%3F_%18%BDA%B8%9DpX6%E3%A35~B%CD%24%AE%11%26%BD%E7%EEti%98%EDe%9A%97Y)%12%25%1C%24%BCbT%AE3li%E6%0B%03%89%9A%E6%D3%ED%F4P%92%B0%9F4%BF43Y%F3%E3%EDP%95%04%EB1%C5%F5%F6KF%F4%BA%BD%D7%DB%91%93%07%E35%3E%A7)%D6%7F%40%FE%BD%F7%F5r%8A%E5y%92%F0%EB%B4%1E%8D%D5%F4%5B%92%3AV%DB%DB%E4%CD%A6%23%C3%C4wQ%3F%03HB%82%8E%1Cd(%E0%91B%0Ca%9Ac%C4%AA%F8L%16%19%22J%A4%D2itTy%B28%D6%3B(%93%96%ED%1CGx%C9_%0E%B8%5E%16%F5%5B%B2%B8%F6%E0%FB%9E%DD%25%D7%8E%BC%15%85%C5%B7%A3%D8Q%ED%B5%81%E9%BA%B2%13%9A%1B%7Fua%A5%A3n%E17%B9%E5%9B%1Bm%AB%0B%08Q%FE%8A%E5%B1H%5Ee%CAO%82Q%D7u6%E6%90S%97%FCu%0B%CF2%94%EE%25v%12X%0C%BA%AC%F0%5E%F8*l%0AO%85%17%C2%97%BF%D4%C8%CE%DE%AD%11%CB%80q%2C%3E%AB%9ES%CD%C6%EC%25%D2L%D2%EBd%B8%BF%8A%F5B%C6%18%F9%901CZ%9D%BE%24M%9C%8A9%F2%DAP%0B'%06w%82%EB%E6%E2%5C%2F%D7%07%9E%BB%CC%5D%E1%FA%B9%08%AD.r%23%8E%C2%17%F5E%7C!%F0%BE3%BE%3E_%B7o%88a%A7%DB%BE%D3d%EB%A31Z%EB%BB%D3%91%BA%A2%B1z%94%8F%DB'%F6%3D%8E%AA%13%19%B2%B1%BE%B1~V%08%2B%B4%A2cjJ%B3tO%00%03%25mN%97%F3%05%93%EF%11%84%0B%7C%88%AE-%89%8F%ABbW%90O%2B%0Ao%99%0C%5E%97%0CI%AFH%D9.%B0%3B%8F%ED%03%B6S%D6%5D%E6i_s9%F3*p%E9%1B%FD%C3%EB.7U%06%5E%19%C0%D1s.%17%A03u%E4%09%B0%7C%5E%2C%EB%15%DB%1F%3C%9E%B7%80%91%3B%DBc%AD%3Dma%BA%8B%3EV%AB%DBt.%5B%1E%01%BB%0F%AB%D5%9F%CF%AA%D5%DD%E7%E4%7F%0Bx%A3%FC%06%A9%23%0A%D6%C2%A1_2%00%00%00%09pHYs%00%00%0B%13%00%00%0B%13%01%00%9A%9C%18%00%00%00%3AIDAT8%11c%FC%FF%FF%7F%18%03%1A%60%01%F2%3F%A0%891%80%04%FF%11-%F8%17%9BJ%E2%05%B1ZD%81v%26t%E7%80%F8%A3%82h%A12%1A%20%A3%01%02%0F%01%BA%25%06%00%19%C0%0D%AEF%D5%3ES%00%00%00%00IEND%AEB%60%82\");\n    background-repeat: no-repeat, repeat-x;\n    background-position: center center, top left;\n    color: transparent;\n\n    border: 1px solid black;\n    -moz-border-radius: 2px;\n    -webkit-border-radius: 2px;\n    border-radius: 2px;\n    \n    cursor: pointer;\n    pointer-events: auto;\n}\n\n.ace_dark .ace_fold {\n}\n\n.ace_fold:hover{\n    background-image: \n        url(\"data:image/png,%89PNG%0D%0A%1A%0A%00%00%00%0DIHDR%00%00%00%11%00%00%00%09%08%06%00%00%00%D4%E8%C7%0C%00%00%03%1EiCCPICC%20Profile%00%00x%01%85T%DFk%D3P%14%FE%DAe%9D%B0%E1%8B%3Ag%11%09%3Eh%91ndStC%9C%B6kW%BA%CDZ%EA6%B7!H%9B%A6m%5C%9A%C6%24%ED~%B0%07%D9%8Bo%3A%C5w%F1%07%3E%F9%07%0C%D9%83o%7B%92%0D%C6%14a%F8%AC%88%22L%F6%22%B3%9E%9B4M'S%03%B9%F7%BB%DF%F9%EE9'%E7%E4%5E%A0%F9qZ%D3%14%2F%0F%14USO%C5%C2%FC%C4%E4%14%DF%F2%01%5E%1CC%2B%FChM%8B%86%16J%26G%40%0F%D3%B2y%EF%B3%F3%0E%1E%C6lt%EEo%DF%AB%FEc%D5%9A%95%0C%11%F0%1C%20%BE%945%C4%22%E1Y%A0i%5C%D4t%13%E0%D6%89%EF%9D15%C2%CDLsX%A7%04%09%1Fg8oc%81%E1%8C%8D%23%96f45%40%9A%09%C2%07%C5B%3AK%B8%408%98i%E0%F3%0D%D8%CE%81%14%E4'%26%A9%92.%8B%3C%ABER%2F%E5dE%B2%0C%F6%F0%1Fs%83%F2_%B0%A8%94%E9%9B%AD%E7%10%8Dm%9A%19N%D1%7C%8A%DE%1F9%7Dp%8C%E6%00%D5%C1%3F_%18%BDA%B8%9DpX6%E3%A35~B%CD%24%AE%11%26%BD%E7%EEti%98%EDe%9A%97Y)%12%25%1C%24%BCbT%AE3li%E6%0B%03%89%9A%E6%D3%ED%F4P%92%B0%9F4%BF43Y%F3%E3%EDP%95%04%EB1%C5%F5%F6KF%F4%BA%BD%D7%DB%91%93%07%E35%3E%A7)%D6%7F%40%FE%BD%F7%F5r%8A%E5y%92%F0%EB%B4%1E%8D%D5%F4%5B%92%3AV%DB%DB%E4%CD%A6%23%C3%C4wQ%3F%03HB%82%8E%1Cd(%E0%91B%0Ca%9Ac%C4%AA%F8L%16%19%22J%A4%D2itTy%B28%D6%3B(%93%96%ED%1CGx%C9_%0E%B8%5E%16%F5%5B%B2%B8%F6%E0%FB%9E%DD%25%D7%8E%BC%15%85%C5%B7%A3%D8Q%ED%B5%81%E9%BA%B2%13%9A%1B%7Fua%A5%A3n%E17%B9%E5%9B%1Bm%AB%0B%08Q%FE%8A%E5%B1H%5Ee%CAO%82Q%D7u6%E6%90S%97%FCu%0B%CF2%94%EE%25v%12X%0C%BA%AC%F0%5E%F8*l%0AO%85%17%C2%97%BF%D4%C8%CE%DE%AD%11%CB%80q%2C%3E%AB%9ES%CD%C6%EC%25%D2L%D2%EBd%B8%BF%8A%F5B%C6%18%F9%901CZ%9D%BE%24M%9C%8A9%F2%DAP%0B'%06w%82%EB%E6%E2%5C%2F%D7%07%9E%BB%CC%5D%E1%FA%B9%08%AD.r%23%8E%C2%17%F5E%7C!%F0%BE3%BE%3E_%B7o%88a%A7%DB%BE%D3d%EB%A31Z%EB%BB%D3%91%BA%A2%B1z%94%8F%DB'%F6%3D%8E%AA%13%19%B2%B1%BE%B1~V%08%2B%B4%A2cjJ%B3tO%00%03%25mN%97%F3%05%93%EF%11%84%0B%7C%88%AE-%89%8F%ABbW%90O%2B%0Ao%99%0C%5E%97%0CI%AFH%D9.%B0%3B%8F%ED%03%B6S%D6%5D%E6i_s9%F3*p%E9%1B%FD%C3%EB.7U%06%5E%19%C0%D1s.%17%A03u%E4%09%B0%7C%5E%2C%EB%15%DB%1F%3C%9E%B7%80%91%3B%DBc%AD%3Dma%BA%8B%3EV%AB%DBt.%5B%1E%01%BB%0F%AB%D5%9F%CF%AA%D5%DD%E7%E4%7F%0Bx%A3%FC%06%A9%23%0A%D6%C2%A1_2%00%00%00%09pHYs%00%00%0B%13%00%00%0B%13%01%00%9A%9C%18%00%00%00%B5IDAT(%15%A5%91%3D%0E%02!%10%85ac%E1%05%D6%CE%D6%C6%CE%D2%E8%ED%CD%DE%C0%C6%D6N.%E0V%F8%3D%9Ca%891XH%C2%BE%D9y%3F%90!%E6%9C%C3%BFk%E5%011%C6-%F5%C8N%04%DF%BD%FF%89%DFt%83DN%60%3E%F3%AB%A0%DE%1A%5Dg%BE%10Q%97%1B%40%9C%A8o%10%8F%5E%828%B4%1B%60%87%F6%02%26%85%1Ch%1E%C1%2B%5Bk%FF%86%EE%B7j%09%9A%DA%9B%ACe%A3%F9%EC%DA!9%B4%D5%A6%81%86%86%98%CC%3C%5B%40%FA%81%B3%E9%CB%23%94%C16Azo%05%D4%E1%C1%95a%3B%8A'%A0%E8%CC%17%22%85%1D%BA%00%A2%FA%DC%0A%94%D1%D1%8D%8B%3A%84%17B%C7%60%1A%25Z%FC%8D%00%00%00%00IEND%AEB%60%82\"),\n        url(\"data:image/png,%89PNG%0D%0A%1A%0A%00%00%00%0DIHDR%00%00%00%05%00%00%007%08%06%00%00%00%C4%DD%80C%00%00%03%1EiCCPICC%20Profile%00%00x%01%85T%DFk%D3P%14%FE%DAe%9D%B0%E1%8B%3Ag%11%09%3Eh%91ndStC%9C%B6kW%BA%CDZ%EA6%B7!H%9B%A6m%5C%9A%C6%24%ED~%B0%07%D9%8Bo%3A%C5w%F1%07%3E%F9%07%0C%D9%83o%7B%92%0D%C6%14a%F8%AC%88%22L%F6%22%B3%9E%9B4M'S%03%B9%F7%BB%DF%F9%EE9'%E7%E4%5E%A0%F9qZ%D3%14%2F%0F%14USO%C5%C2%FC%C4%E4%14%DF%F2%01%5E%1CC%2B%FChM%8B%86%16J%26G%40%0F%D3%B2y%EF%B3%F3%0E%1E%C6lt%EEo%DF%AB%FEc%D5%9A%95%0C%11%F0%1C%20%BE%945%C4%22%E1Y%A0i%5C%D4t%13%E0%D6%89%EF%9D15%C2%CDLsX%A7%04%09%1Fg8oc%81%E1%8C%8D%23%96f45%40%9A%09%C2%07%C5B%3AK%B8%408%98i%E0%F3%0D%D8%CE%81%14%E4'%26%A9%92.%8B%3C%ABER%2F%E5dE%B2%0C%F6%F0%1Fs%83%F2_%B0%A8%94%E9%9B%AD%E7%10%8Dm%9A%19N%D1%7C%8A%DE%1F9%7Dp%8C%E6%00%D5%C1%3F_%18%BDA%B8%9DpX6%E3%A35~B%CD%24%AE%11%26%BD%E7%EEti%98%EDe%9A%97Y)%12%25%1C%24%BCbT%AE3li%E6%0B%03%89%9A%E6%D3%ED%F4P%92%B0%9F4%BF43Y%F3%E3%EDP%95%04%EB1%C5%F5%F6KF%F4%BA%BD%D7%DB%91%93%07%E35%3E%A7)%D6%7F%40%FE%BD%F7%F5r%8A%E5y%92%F0%EB%B4%1E%8D%D5%F4%5B%92%3AV%DB%DB%E4%CD%A6%23%C3%C4wQ%3F%03HB%82%8E%1Cd(%E0%91B%0Ca%9Ac%C4%AA%F8L%16%19%22J%A4%D2itTy%B28%D6%3B(%93%96%ED%1CGx%C9_%0E%B8%5E%16%F5%5B%B2%B8%F6%E0%FB%9E%DD%25%D7%8E%BC%15%85%C5%B7%A3%D8Q%ED%B5%81%E9%BA%B2%13%9A%1B%7Fua%A5%A3n%E17%B9%E5%9B%1Bm%AB%0B%08Q%FE%8A%E5%B1H%5Ee%CAO%82Q%D7u6%E6%90S%97%FCu%0B%CF2%94%EE%25v%12X%0C%BA%AC%F0%5E%F8*l%0AO%85%17%C2%97%BF%D4%C8%CE%DE%AD%11%CB%80q%2C%3E%AB%9ES%CD%C6%EC%25%D2L%D2%EBd%B8%BF%8A%F5B%C6%18%F9%901CZ%9D%BE%24M%9C%8A9%F2%DAP%0B'%06w%82%EB%E6%E2%5C%2F%D7%07%9E%BB%CC%5D%E1%FA%B9%08%AD.r%23%8E%C2%17%F5E%7C!%F0%BE3%BE%3E_%B7o%88a%A7%DB%BE%D3d%EB%A31Z%EB%BB%D3%91%BA%A2%B1z%94%8F%DB'%F6%3D%8E%AA%13%19%B2%B1%BE%B1~V%08%2B%B4%A2cjJ%B3tO%00%03%25mN%97%F3%05%93%EF%11%84%0B%7C%88%AE-%89%8F%ABbW%90O%2B%0Ao%99%0C%5E%97%0CI%AFH%D9.%B0%3B%8F%ED%03%B6S%D6%5D%E6i_s9%F3*p%E9%1B%FD%C3%EB.7U%06%5E%19%C0%D1s.%17%A03u%E4%09%B0%7C%5E%2C%EB%15%DB%1F%3C%9E%B7%80%91%3B%DBc%AD%3Dma%BA%8B%3EV%AB%DBt.%5B%1E%01%BB%0F%AB%D5%9F%CF%AA%D5%DD%E7%E4%7F%0Bx%A3%FC%06%A9%23%0A%D6%C2%A1_2%00%00%00%09pHYs%00%00%0B%13%00%00%0B%13%01%00%9A%9C%18%00%00%003IDAT8%11c%FC%FF%FF%7F%3E%03%1A%60%01%F2%3F%A3%891%80%04%FFQ%26%F8w%C0%B43%A1%DB%0C%E2%8F%0A%A2%85%CAh%80%8C%06%08%3C%04%E8%96%18%00%A3S%0D%CD%CF%D8%C1%9D%00%00%00%00IEND%AEB%60%82\");\n    background-repeat: no-repeat, repeat-x;\n    background-position: center center, top left;\n}\n\n.ace_dragging .ace_content {\n    cursor: move;\n}\n\n.ace_folding-enabled .ace_gutter-cell {\n    padding-right: 13px;\n}\n\n.ace_fold-widget {\n    box-sizing: border-box;\n    -moz-box-sizing: border-box;\n    -webkit-box-sizing: border-box;\n\n    margin: 0 -12px 1px 1px;\n    display: inline-block;\n    height: 14px;\n    width: 11px;\n    vertical-align: text-bottom;\n    \n    background-image: url(\"data:image/png,%89PNG%0D%0A%1A%0A%00%00%00%0DIHDR%00%00%00%05%00%00%00%05%08%06%00%00%00%8Do%26%E5%00%00%004IDATx%DAe%8A%B1%0D%000%0C%C2%F2%2CK%96%BC%D0%8F9%81%88H%E9%D0%0E%96%C0%10%92%3E%02%80%5E%82%E4%A9*-%EEsw%C8%CC%11%EE%96w%D8%DC%E9*Eh%0C%151(%00%00%00%00IEND%AEB%60%82\");\n    background-repeat: no-repeat;\n    background-position: center 5px;\n\n    border-radius: 3px;\n}\n\n.ace_fold-widget.end {\n    background-image: url(\"data:image/png,%89PNG%0D%0A%1A%0A%00%00%00%0DIHDR%00%00%00%05%00%00%00%05%08%06%00%00%00%8Do%26%E5%00%00%004IDATx%DAm%C7%C1%09%000%08C%D1%8C%ECE%C8E(%8E%EC%02)%1EZJ%F1%C1'%04%07I%E1%E5%EE%CAL%F5%A2%99%99%22%E2%D6%1FU%B5%FE0%D9x%A7%26Wz5%0E%D5%00%00%00%00IEND%AEB%60%82\");\n}\n\n.ace_fold-widget.closed {\n    background-image: url(\"data:image/png,%89PNG%0D%0A%1A%0A%00%00%00%0DIHDR%00%00%00%03%00%00%00%06%08%06%00%00%00%06%E5%24%0C%00%00%009IDATx%DA5%CA%C1%09%000%08%03%C0%AC*(%3E%04%C1%0D%BA%B1%23%A4Uh%E0%20%81%C0%CC%F8%82%81%AA%A2%AArGfr%88%08%11%11%1C%DD%7D%E0%EE%5B%F6%F6%CB%B8%05Q%2F%E9tai%D9%00%00%00%00IEND%AEB%60%82\");\n}\n\n.ace_fold-widget:hover {\n    border: 1px solid rgba(0, 0, 0, 0.3);\n    background-color: rgba(255, 255, 255, 0.2);\n    -moz-box-shadow:inset 0 1px 1px rgba(255, 255, 255, 0.7);\n    -moz-box-shadow: 0 1px 1px rgba(255, 255, 255, 0.7);\n    -webkit-box-shadow:inset 0 1px 1px rgba(255, 255, 255, 0.7);\n    -webkit-box-shadow: 0 1px 1px rgba(255, 255, 255, 0.7);\n    box-shadow:inset 0 1px 1px rgba(255, 255, 255, 0.7);\n    box-shadow: 0 1px 1px rgba(255, 255, 255, 0.7);\n    background-position: center 4px;\n}\n\n.ace_fold-widget:active {\n    border: 1px solid rgba(0, 0, 0, 0.4);\n    background-color: rgba(0, 0, 0, 0.05);\n    -moz-box-shadow:inset 0 1px 1px rgba(255, 255, 255);\n    -moz-box-shadow: 0 1px 1px rgba(255, 255, 255, 0.8);\n    -webkit-box-shadow:inset 0 1px 1px rgba(255, 255, 255);\n    -webkit-box-shadow: 0 1px 1px rgba(255, 255, 255, 0.8);\n    box-shadow:inset 0 1px 1px rgba(255, 255, 255);\n    box-shadow: 0 1px 1px rgba(255, 255, 255, 0.8);\n}\n\n.ace_fold-widget.invalid {\n    background-color: #FFB4B4;\n    border-color: #DE5555;\n}\n"),define("ace/theme/textmate",["require","exports","module","ace/lib/dom"],function(a,b,c){"use strict",b.isDark=!1,b.cssClass="ace-tm",b.cssText=".ace-tm .ace_editor {  border: 2px solid rgb(159, 159, 159);}.ace-tm .ace_editor.ace_focus {  border: 2px solid #327fbd;}.ace-tm .ace_gutter {  background: #e8e8e8;  color: #333;}.ace-tm .ace_print_margin {  width: 1px;  background: #e8e8e8;}.ace-tm .ace_fold {    background-color: #0000A2;}.ace-tm .ace_text-layer {  cursor: text;}.ace-tm .ace_cursor {  border-left: 2px solid black;}.ace-tm .ace_cursor.ace_overwrite {  border-left: 0px;  border-bottom: 1px solid black;}        .ace-tm .ace_line .ace_invisible {  color: rgb(191, 191, 191);}.ace-tm .ace_line .ace_keyword {  color: blue;}.ace-tm .ace_line .ace_constant.ace_buildin {  color: rgb(88, 72, 246);}.ace-tm .ace_line .ace_constant.ace_language {  color: rgb(88, 92, 246);}.ace-tm .ace_line .ace_constant.ace_library {  color: rgb(6, 150, 14);}.ace-tm .ace_line .ace_invalid {  background-color: rgb(153, 0, 0);  color: white;}.ace-tm .ace_line .ace_support.ace_function {  color: rgb(60, 76, 114);}.ace-tm .ace_line .ace_support.ace_constant {  color: rgb(6, 150, 14);}.ace-tm .ace_line .ace_support.ace_type,.ace-tm .ace_line .ace_support.ace_class {  color: rgb(109, 121, 222);}.ace-tm .ace_line .ace_keyword.ace_operator {  color: rgb(104, 118, 135);}.ace-tm .ace_line .ace_string {  color: rgb(3, 106, 7);}.ace-tm .ace_line .ace_comment {  color: rgb(76, 136, 107);}.ace-tm .ace_line .ace_comment.ace_doc {  color: rgb(0, 102, 255);}.ace-tm .ace_line .ace_comment.ace_doc.ace_tag {  color: rgb(128, 159, 191);}.ace-tm .ace_line .ace_constant.ace_numeric {  color: rgb(0, 0, 205);}.ace-tm .ace_line .ace_variable {  color: rgb(49, 132, 149);}.ace-tm .ace_line .ace_xml_pe {  color: rgb(104, 104, 91);}.ace-tm .ace_entity.ace_name.ace_function {  color: #0000A2;}.ace-tm .ace_markup.ace_markupine {    text-decoration:underline;}.ace-tm .ace_markup.ace_heading {  color: rgb(12, 7, 255);}.ace-tm .ace_markup.ace_list {  color:rgb(185, 6, 144);}.ace-tm .ace_marker-layer .ace_selection {  background: rgb(181, 213, 255);}.ace-tm .ace_marker-layer .ace_step {  background: rgb(252, 255, 0);}.ace-tm .ace_marker-layer .ace_stack {  background: rgb(164, 229, 101);}.ace-tm .ace_marker-layer .ace_bracket {  margin: -1px 0 0 -1px;  border: 1px solid rgb(192, 192, 192);}.ace-tm .ace_marker-layer .ace_active_line {  background: rgba(0, 0, 0, 0.07);}.ace-tm .ace_marker-layer .ace_selected_word {  background: rgb(250, 250, 255);  border: 1px solid rgb(200, 200, 250);}.ace-tm .ace_meta.ace_tag {  color:rgb(28, 2, 255);}.ace-tm .ace_string.ace_regex {  color: rgb(255, 0, 0)}";var d=a("../lib/dom");d.importCssString(b.cssText,b.cssClass)}),function(){window.require(["ace/ace"],function(a){window.ace||(window.ace={});for(var b in a)a.hasOwnProperty(b)&&(ace[b]=a[b])})}()
\ No newline at end of file
+(function(){function g(a){if(typeof requirejs!="undefined"){var e=b.define;b.define=function(a,b,c){return typeof c!="function"?e.apply(this,arguments):e(a,b,function(a,d,e){return b[2]=="module"&&(e.packaged=!0),c.apply(this,arguments)})},b.define.packaged=!0;return}var f=function(a,b){return d("",a,b)};f.packaged=!0;var g=b;a&&(b[a]||(b[a]={}),g=b[a]),g.define&&(c.original=g.define),g.define=c,g.require&&(d.original=g.require),g.require=f}var a="",b=function(){return this}(),c=function(a,b,d){if(typeof a!="string"){c.original?c.original.apply(window,arguments):(console.error("dropping module because define wasn't a string."),console.trace());return}arguments.length==2&&(d=b),c.modules||(c.modules={}),c.modules[a]=d},d=function(a,b,c){if(Object.prototype.toString.call(b)==="[object Array]"){var e=[];for(var g=0,h=b.length;g<h;++g){var i=f(a,b[g]);if(!i&&d.original)return d.original.apply(window,arguments);e.push(i)}c&&c.apply(null,e)}else{if(typeof b=="string"){var j=f(a,b);return!j&&d.original?d.original.apply(window,arguments):(c&&c(),j)}if(d.original)return d.original.apply(window,arguments)}},e=function(a,b){if(b.indexOf("!")!==-1){var c=b.split("!");return e(a,c[0])+"!"+e(a,c[1])}if(b.charAt(0)=="."){var d=a.split("/").slice(0,-1).join("/");b=d+"/"+b;while(b.indexOf(".")!==-1&&f!=b){var f=b;b=b.replace(/\/\.\//,"/").replace(/[^\/]+\/\.\.\//,"")}}return b},f=function(a,b){b=e(a,b);var f=c.modules[b];if(!f)return null;if(typeof f=="function"){var g={},h={id:b,uri:"",exports:g,packaged:!0},i=function(a,c){return d(b,a,c)},j=f(i,g,h);return g=j||h.exports,c.modules[b]=g,g}return f};g(a)})(),define("ace/ace",["require","exports","module","ace/lib/fixoldbrowsers","ace/lib/dom","ace/lib/event","ace/editor","ace/edit_session","ace/undomanager","ace/virtual_renderer","ace/multi_select","ace/worker/worker_client","ace/keyboard/hash_handler","ace/keyboard/state_handler","ace/placeholder","ace/config","ace/theme/textmate"],function(a,b,c){"use strict",a("./lib/fixoldbrowsers");var d=a("./lib/dom"),e=a("./lib/event"),f=a("./editor").Editor,g=a("./edit_session").EditSession,h=a("./undomanager").UndoManager,i=a("./virtual_renderer").VirtualRenderer,j=a("./multi_select").MultiSelect;a("./worker/worker_client"),a("./keyboard/hash_handler"),a("./keyboard/state_handler"),a("./placeholder"),a("./config").init(),b.edit=function(b){typeof b=="string"&&(b=document.getElementById(b));var c=new g(d.getInnerText(b));c.setUndoManager(new h),b.innerHTML="";var k=new f(new i(b,a("./theme/textmate")));new j(k),k.setSession(c);var l={};return l.document=c,l.editor=k,k.resize(),e.addListener(window,"resize",function(){k.resize()}),b.env=l,k.env=l,k}}),define("ace/lib/fixoldbrowsers",["require","exports","module","ace/lib/regexp","ace/lib/es5-shim"],function(a,b,c){"use strict",a("./regexp"),a("./es5-shim")}),define("ace/lib/regexp",["require","exports","module"],function(a,b,c){function g(a){return(a.global?"g":"")+(a.ignoreCase?"i":"")+(a.multiline?"m":"")+(a.extended?"x":"")+(a.sticky?"y":"")}function h(a,b,c){if(Array.prototype.indexOf)return a.indexOf(b,c);for(var d=c||0;d<a.length;d++)if(a[d]===b)return d;return-1}"use strict";var d={exec:RegExp.prototype.exec,test:RegExp.prototype.test,match:String.prototype.match,replace:String.prototype.replace,split:String.prototype.split},e=d.exec.call(/()??/,"")[1]===undefined,f=function(){var a=/^/g;return d.test.call(a,""),!a.lastIndex}();RegExp.prototype.exec=function(a){var b=d.exec.apply(this,arguments),c,i;if(typeof a=="string"&&b){!e&&b.length>1&&h(b,"")>-1&&(i=RegExp(this.source,d.replace.call(g(this),"g","")),d.replace.call(a.slice(b.index),i,function(){for(var a=1;a<arguments.length-2;a++)arguments[a]===undefined&&(b[a]=undefined)}));if(this._xregexp&&this._xregexp.captureNames)for(var j=1;j<b.length;j++)c=this._xregexp.captureNames[j-1],c&&(b[c]=b[j]);!f&&this.global&&!b[0].length&&this.lastIndex>b.index&&this.lastIndex--}return b},f||(RegExp.prototype.test=function(a){var b=d.exec.call(this,a);return b&&this.global&&!b[0].length&&this.lastIndex>b.index&&this.lastIndex--,!!b})}),define("ace/lib/es5-shim",["require","exports","module"],function(a,b,c){function p(a){try{return Object.defineProperty(a,"sentinel",{}),"sentinel"in a}catch(b){}}Function.prototype.bind||(Function.prototype.bind=function(b){var c=this;if(typeof c!="function")throw new TypeError;var d=g.call(arguments,1),e=function(){if(this instanceof e){var a=function(){};a.prototype=c.prototype;var f=new a,h=c.apply(f,d.concat(g.call(arguments)));return h!==null&&Object(h)===h?h:f}return c.apply(b,d.concat(g.call(arguments)))};return e});var d=Function.prototype.call,e=Array.prototype,f=Object.prototype,g=e.slice,h=d.bind(f.toString),i=d.bind(f.hasOwnProperty),j,k,l,m,n;if(n=i(f,"__defineGetter__"))j=d.bind(f.__defineGetter__),k=d.bind(f.__defineSetter__),l=d.bind(f.__lookupGetter__),m=d.bind(f.__lookupSetter__);Array.isArray||(Array.isArray=function(b){return h(b)=="[object Array]"}),Array.prototype.forEach||(Array.prototype.forEach=function(b){var c=G(this),d=arguments[1],e=0,f=c.length>>>0;if(h(b)!="[object Function]")throw new TypeError;while(e<f)e in c&&b.call(d,c[e],e,c),e++}),Array.prototype.map||(Array.prototype.map=function(b){var c=G(this),d=c.length>>>0,e=Array(d),f=arguments[1];if(h(b)!="[object Function]")throw new TypeError;for(var g=0;g<d;g++)g in c&&(e[g]=b.call(f,c[g],g,c));return e}),Array.prototype.filter||(Array.prototype.filter=function(b){var c=G(this),d=c.length>>>0,e=[],f=arguments[1];if(h(b)!="[object Function]")throw new TypeError;for(var g=0;g<d;g++)g in c&&b.call(f,c[g],g,c)&&e.push(c[g]);return e}),Array.prototype.every||(Array.prototype.every=function(b){var c=G(this),d=c.length>>>0,e=arguments[1];if(h(b)!="[object Function]")throw new TypeError;for(var f=0;f<d;f++)if(f in c&&!b.call(e,c[f],f,c))return!1;return!0}),Array.prototype.some||(Array.prototype.some=function(b){var c=G(this),d=c.length>>>0,e=arguments[1];if(h(b)!="[object Function]")throw new TypeError;for(var f=0;f<d;f++)if(f in c&&b.call(e,c[f],f,c))return!0;return!1}),Array.prototype.reduce||(Array.prototype.reduce=function(b){var c=G(this),d=c.length>>>0;if(h(b)!="[object Function]")throw new TypeError;if(!d&&arguments.length==1)throw new TypeError;var e=0,f;if(arguments.length>=2)f=arguments[1];else do{if(e in c){f=c[e++];break}if(++e>=d)throw new TypeError}while(!0);for(;e<d;e++)e in c&&(f=b.call(void 0,f,c[e],e,c));return f}),Array.prototype.reduceRight||(Array.prototype.reduceRight=function(b){var c=G(this),d=c.length>>>0;if(h(b)!="[object Function]")throw new TypeError;if(!d&&arguments.length==1)throw new TypeError;var e,f=d-1;if(arguments.length>=2)e=arguments[1];else do{if(f in c){e=c[f--];break}if(--f<0)throw new TypeError}while(!0);do f in this&&(e=b.call(void 0,e,c[f],f,c));while(f--);return e}),Array.prototype.indexOf||(Array.prototype.indexOf=function(b){var c=G(this),d=c.length>>>0;if(!d)return-1;var e=0;arguments.length>1&&(e=E(arguments[1])),e=e>=0?e:Math.max(0,d+e);for(;e<d;e++)if(e in c&&c[e]===b)return e;return-1}),Array.prototype.lastIndexOf||(Array.prototype.lastIndexOf=function(b){var c=G(this),d=c.length>>>0;if(!d)return-1;var e=d-1;arguments.length>1&&(e=Math.min(e,E(arguments[1]))),e=e>=0?e:d-Math.abs(e);for(;e>=0;e--)if(e in c&&b===c[e])return e;return-1}),Object.getPrototypeOf||(Object.getPrototypeOf=function(b){return b.__proto__||(b.constructor?b.constructor.prototype:f)});if(!Object.getOwnPropertyDescriptor){var o="Object.getOwnPropertyDescriptor called on a non-object: ";Object.getOwnPropertyDescriptor=function(b,c){if(typeof b!="object"&&typeof b!="function"||b===null)throw new TypeError(o+b);if(!i(b,c))return;var d,e,g;d={enumerable:!0,configurable:!0};if(n){var h=b.__proto__;b.__proto__=f;var e=l(b,c),g=m(b,c);b.__proto__=h;if(e||g)return e&&(d.get=e),g&&(d.set=g),d}return d.value=b[c],d}}Object.getOwnPropertyNames||(Object.getOwnPropertyNames=function(b){return Object.keys(b)}),Object.create||(Object.create=function(b,c){var d;if(b===null)d={__proto__:null};else{if(typeof b!="object")throw new TypeError("typeof prototype["+typeof b+"] != 'object'");var e=function(){};e.prototype=b,d=new e,d.__proto__=b}return c!==void 0&&Object.defineProperties(d,c),d});if(Object.defineProperty){var q=p({}),r=typeof document=="undefined"||p(document.createElement("div"));if(!q||!r)var s=Object.defineProperty}if(!Object.defineProperty||s){var t="Property description must be an object: ",u="Object.defineProperty called on non-object: ",v="getters & setters can not be defined on this javascript engine";Object.defineProperty=function(b,c,d){if(typeof b!="object"&&typeof b!="function"||b===null)throw new TypeError(u+b);if(typeof d!="object"&&typeof d!="function"||d===null)throw new TypeError(t+d);if(s)try{return s.call(Object,b,c,d)}catch(e){}if(i(d,"value"))if(n&&(l(b,c)||m(b,c))){var g=b.__proto__;b.__proto__=f,delete b[c],b[c]=d.value,b.__proto__=g}else b[c]=d.value;else{if(!n)throw new TypeError(v);i(d,"get")&&j(b,c,d.get),i(d,"set")&&k(b,c,d.set)}return b}}Object.defineProperties||(Object.defineProperties=function(b,c){for(var d in c)i(c,d)&&Object.defineProperty(b,d,c[d]);return b}),Object.seal||(Object.seal=function(b){return b}),Object.freeze||(Object.freeze=function(b){return b});try{Object.freeze(function(){})}catch(w){Object.freeze=function(b){return function(c){return typeof c=="function"?c:b(c)}}(Object.freeze)}Object.preventExtensions||(Object.preventExtensions=function(b){return b}),Object.isSealed||(Object.isSealed=function(b){return!1}),Object.isFrozen||(Object.isFrozen=function(b){return!1}),Object.isExtensible||(Object.isExtensible=function(b){if(Object(b)===b)throw new TypeError;var c="";while(i(b,c))c+="?";b[c]=!0;var d=i(b,c);return delete b[c],d});if(!Object.keys){var x=!0,y=["toString","toLocaleString","valueOf","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","constructor"],z=y.length;for(var A in{toString:null})x=!1;Object.keys=function H(a){if(typeof a!="object"&&typeof a!="function"||a===null)throw new TypeError("Object.keys called on a non-object");var H=[];for(var b in a)i(a,b)&&H.push(b);if(x)for(var c=0,d=z;c<d;c++){var e=y[c];i(a,e)&&H.push(e)}return H}}if(!Date.prototype.toISOString||(new Date(-621987552e5)).toISOString().indexOf("-000001")===-1)Date.prototype.toISOString=function(){var b,c,d,e;if(!isFinite(this))throw new RangeError;b=[this.getUTCMonth()+1,this.getUTCDate(),this.getUTCHours(),this.getUTCMinutes(),this.getUTCSeconds()],e=this.getUTCFullYear(),e=(e<0?"-":e>9999?"+":"")+("00000"+Math.abs(e)).slice(0<=e&&e<=9999?-4:-6),c=b.length;while(c--)d=b[c],d<10&&(b[c]="0"+d);return e+"-"+b.slice(0,2).join("-")+"T"+b.slice(2).join(":")+"."+("000"+this.getUTCMilliseconds()).slice(-3)+"Z"};Date.now||(Date.now=function(){return(new Date).getTime()}),Date.prototype.toJSON||(Date.prototype.toJSON=function(b){if(typeof this.toISOString!="function")throw new TypeError;return this.toISOString()}),Date.parse("+275760-09-13T00:00:00.000Z")!==864e13&&(Date=function(a){var b=function e(b,c,d,f,g,h,i){var j=arguments.length;if(this instanceof a){var k=j==1&&String(b)===b?new a(e.parse(b)):j>=7?new a(b,c,d,f,g,h,i):j>=6?new a(b,c,d,f,g,h):j>=5?new a(b,c,d,f,g):j>=4?new a(b,c,d,f):j>=3?new a(b,c,d):j>=2?new a(b,c):j>=1?new a(b):new a;return k.constructor=e,k}return a.apply(this,arguments)},c=new RegExp("^(\\d{4}|[+-]\\d{6})(?:-(\\d{2})(?:-(\\d{2})(?:T(\\d{2}):(\\d{2})(?::(\\d{2})(?:\\.(\\d{3}))?)?(?:Z|(?:([-+])(\\d{2}):(\\d{2})))?)?)?)?$");for(var d in a)b[d]=a[d];return b.now=a.now,b.UTC=a.UTC,b.prototype=a.prototype,b.prototype.constructor=b,b.parse=function(d){var e=c.exec(d);if(e){e.shift();for(var f=1;f<7;f++)e[f]=+(e[f]||(f<3?1:0)),f==1&&e[f]--;var g=+e.pop(),h=+e.pop(),i=e.pop(),j=0;if(i){if(h>23||g>59)return NaN;j=(h*60+g)*6e4*(i=="+"?-1:1)}var k=+e[0];return 0<=k&&k<=99?(e[0]=k+400,a.UTC.apply(this,e)+j-126227808e5):a.UTC.apply(this,e)+j}return a.parse.apply(this,arguments)},b}(Date));var B="	\n\f\r   ᠎              \u2028\u2029";if(!String.prototype.trim||B.trim()){B="["+B+"]";var C=new RegExp("^"+B+B+"*"),D=new RegExp(B+B+"*$");String.prototype.trim=function(){return String(this).replace(C,"").replace(D,"")}}var E=function(a){return a=+a,a!==a?a=0:a!==0&&a!==1/0&&a!==-Infinity&&(a=(a>0||-1)*Math.floor(Math.abs(a))),a},F="a"[0]!="a",G=function(a){if(a==null)throw new TypeError;return F&&typeof a=="string"&&a?a.split(""):Object(a)}}),define("ace/lib/dom",["require","exports","module"],function(a,b,c){"use strict";var d="http://www.w3.org/1999/xhtml";b.createElement=function(a,b){return document.createElementNS?document.createElementNS(b||d,a):document.createElement(a)},b.setText=function(a,b){a.innerText!==undefined&&(a.innerText=b),a.textContent!==undefined&&(a.textContent=b)},b.hasCssClass=function(a,b){var c=a.className.split(/\s+/g);return c.indexOf(b)!==-1},b.addCssClass=function(a,c){b.hasCssClass(a,c)||(a.className+=" "+c)},b.removeCssClass=function(a,b){var c=a.className.split(/\s+/g);for(;;){var d=c.indexOf(b);if(d==-1)break;c.splice(d,1)}a.className=c.join(" ")},b.toggleCssClass=function(a,b){var c=a.className.split(/\s+/g),d=!0;for(;;){var e=c.indexOf(b);if(e==-1)break;d=!1,c.splice(e,1)}return d&&c.push(b),a.className=c.join(" "),d},b.setCssClass=function(a,c,d){d?b.addCssClass(a,c):b.removeCssClass(a,c)},b.hasCssString=function(a,b){var c=0,d;b=b||document;if(b.createStyleSheet&&(d=b.styleSheets)){while(c<d.length)if(d[c++].owningElement.id===a)return!0}else if(d=b.getElementsByTagName("style"))while(c<d.length)if(d[c++].id===a)return!0;return!1},b.importCssString=function(c,e,f){f=f||document;if(e&&b.hasCssString(e,f))return null;var g;if(f.createStyleSheet)g=f.createStyleSheet(),g.cssText=c,e&&(g.owningElement.id=e);else{g=f.createElementNS?f.createElementNS(d,"style"):f.createElement("style"),g.appendChild(f.createTextNode(c)),e&&(g.id=e);var h=f.getElementsByTagName("head")[0]||f.documentElement;h.appendChild(g)}},b.importCssStylsheet=function(a,c){if(c.createStyleSheet)c.createStyleSheet(a);else{var d=b.createElement("link");d.rel="stylesheet",d.href=a;var e=c.getElementsByTagName("head")[0]||c.documentElement;e.appendChild(d)}},b.getInnerWidth=function(a){return parseInt(b.computedStyle(a,"paddingLeft"),10)+parseInt(b.computedStyle(a,"paddingRight"),10)+a.clientWidth},b.getInnerHeight=function(a){return parseInt(b.computedStyle(a,"paddingTop"),10)+parseInt(b.computedStyle(a,"paddingBottom"),10)+a.clientHeight},window.pageYOffset!==undefined?(b.getPageScrollTop=function(){return window.pageYOffset},b.getPageScrollLeft=function(){return window.pageXOffset}):(b.getPageScrollTop=function(){return document.body.scrollTop},b.getPageScrollLeft=function(){return document.body.scrollLeft}),window.getComputedStyle?b.computedStyle=function(a,b){return b?(window.getComputedStyle(a,"")||{})[b]||"":window.getComputedStyle(a,"")||{}}:b.computedStyle=function(a,b){return b?a.currentStyle[b]:a.currentStyle},b.scrollbarWidth=function(a){var c=b.createElement("p");c.style.width="100%",c.style.minWidth="0px",c.style.height="200px";var d=b.createElement("div"),e=d.style;e.position="absolute",e.left="-10000px",e.overflow="hidden",e.width="200px",e.minWidth="0px",e.height="150px",d.appendChild(c);var f=a.body||a.documentElement;f.appendChild(d);var g=c.offsetWidth;e.overflow="scroll";var h=c.offsetWidth;return g==h&&(h=d.clientWidth),f.removeChild(d),g-h},b.setInnerHtml=function(a,b){var c=a.cloneNode(!1);return c.innerHTML=b,a.parentNode.replaceChild(c,a),c},b.setInnerText=function(a,b){var c=a.ownerDocument;c.body&&"textContent"in c.body?a.textContent=b:a.innerText=b},b.getInnerText=function(a){var b=a.ownerDocument;return b.body&&"textContent"in b.body?a.textContent:a.innerText||a.textContent||""},b.getParentWindow=function(a){return a.defaultView||a.parentWindow}}),define("ace/lib/event",["require","exports","module","ace/lib/keys","ace/lib/useragent","ace/lib/dom"],function(a,b,c){function g(a,b,c){var f=0;e.isOpera&&e.isMac?f=0|(b.metaKey?1:0)|(b.altKey?2:0)|(b.shiftKey?4:0)|(b.ctrlKey?8:0):f=0|(b.ctrlKey?1:0)|(b.altKey?2:0)|(b.shiftKey?4:0)|(b.metaKey?8:0);if(c in d.MODIFIER_KEYS){switch(d.MODIFIER_KEYS[c]){case"Alt":f=2;break;case"Shift":f=4;break;case"Ctrl":f=1;break;default:f=8}c=0}return f&8&&(c==91||c==93)&&(c=0),!!f||c in d.FUNCTION_KEYS||c in d.PRINTABLE_KEYS?a(b,f,c):!1}"use strict";var d=a("./keys"),e=a("./useragent"),f=a("./dom");b.addListener=function(a,b,c){if(a.addEventListener)return a.addEventListener(b,c,!1);if(a.attachEvent){var d=function(){c(window.event)};c._wrapper=d,a.attachEvent("on"+b,d)}},b.removeListener=function(a,b,c){if(a.removeEventListener)return a.removeEventListener(b,c,!1);a.detachEvent&&a.detachEvent("on"+b,c._wrapper||c)},b.stopEvent=function(a){return b.stopPropagation(a),b.preventDefault(a),!1},b.stopPropagation=function(a){a.stopPropagation?a.stopPropagation():a.cancelBubble=!0},b.preventDefault=function(a){a.preventDefault?a.preventDefault():a.returnValue=!1},b.getDocumentX=function(a){return a.clientX?a.clientX+f.getPageScrollLeft():a.pageX},b.getDocumentY=function(a){return a.clientY?a.clientY+f.getPageScrollTop():a.pageY},b.getButton=function(a){return a.type=="dblclick"?0:a.type=="contextmenu"?2:a.preventDefault?a.button:{1:0,2:2,4:1}[a.button]},document.documentElement.setCapture?b.capture=function(a,c,d){function e(a){return c(a),b.stopPropagation(a)}function g(e){c(e),f||(f=!0,d(e)),b.removeListener(a,"mousemove",c),b.removeListener(a,"mouseup",g),b.removeListener(a,"losecapture",g),a.releaseCapture()}var f=!1;b.addListener(a,"mousemove",c),b.addListener(a,"mouseup",g),b.addListener(a,"losecapture",g),a.setCapture()}:b.capture=function(a,b,c){function d(a){b(a),a.stopPropagation()}function e(a){b&&b(a),c&&c(a),document.removeEventListener("mousemove",d,!0),document.removeEventListener("mouseup",e,!0),a.stopPropagation()}document.addEventListener("mousemove",d,!0),document.addEventListener("mouseup",e,!0)},b.addMouseWheelListener=function(a,c){var d=8,e=function(a){a.wheelDelta!==undefined?a.wheelDeltaX!==undefined?(a.wheelX=-a.wheelDeltaX/d,a.wheelY=-a.wheelDeltaY/d):(a.wheelX=0,a.wheelY=-a.wheelDelta/d):a.axis&&a.axis==a.HORIZONTAL_AXIS?(a.wheelX=(a.detail||0)*5,a.wheelY=0):(a.wheelX=0,a.wheelY=(a.detail||0)*5),c(a)};b.addListener(a,"DOMMouseScroll",e),b.addListener(a,"mousewheel",e)},b.addMultiMouseDownListener=function(a,c,d,f,g){var h=0,i,j,k=function(a){h+=1,h==1&&(i=a.clientX,j=a.clientY,setTimeout(function(){h=0},f||600));var e=b.getButton(a)==c;if(!e||Math.abs(a.clientX-i)>5||Math.abs(a.clientY-j)>5)h=0;h==d&&(h=0,g(a));if(e)return b.preventDefault(a)};b.addListener(a,"mousedown",k),e.isOldIE&&b.addListener(a,"dblclick",k)},b.addCommandKeyListener=function(a,c){var d=b.addListener;if(e.isOldGecko||e.isOpera){var f=null;d(a,"keydown",function(a){f=a.keyCode}),d(a,"keypress",function(a){return g(c,a,f)})}else{var h=null;d(a,"keydown",function(a){return h=a.keyIdentifier||a.keyCode,g(c,a,a.keyCode)})}};if(window.postMessage){var h=1;b.nextTick=function(a,c){c=c||window;var d="zero-timeout-message-"+h;b.addListener(c,"message",function e(f){f.data==d&&(b.stopPropagation(f),b.removeListener(c,"message",e),a())}),c.postMessage(d,"*")}}else b.nextTick=function(a,b){b=b||window,window.setTimeout(a,0)}}),define("ace/lib/keys",["require","exports","module","ace/lib/oop"],function(a,b,c){"use strict";var d=a("./oop"),e=function(){var a={MODIFIER_KEYS:{16:"Shift",17:"Ctrl",18:"Alt",224:"Meta"},KEY_MODS:{ctrl:1,alt:2,option:2,shift:4,meta:8,command:8},FUNCTION_KEYS:{8:"Backspace",9:"Tab",13:"Return",19:"Pause",27:"Esc",32:"Space",33:"PageUp",34:"PageDown",35:"End",36:"Home",37:"Left",38:"Up",39:"Right",40:"Down",44:"Print",45:"Insert",46:"Delete",96:"Numpad0",97:"Numpad1",98:"Numpad2",99:"Numpad3",100:"Numpad4",101:"Numpad5",102:"Numpad6",103:"Numpad7",104:"Numpad8",105:"Numpad9",112:"F1",113:"F2",114:"F3",115:"F4",116:"F5",117:"F6",118:"F7",119:"F8",120:"F9",121:"F10",122:"F11",123:"F12",144:"Numlock",145:"Scrolllock"},PRINTABLE_KEYS:{32:" ",48:"0",49:"1",50:"2",51:"3",52:"4",53:"5",54:"6",55:"7",56:"8",57:"9",59:";",61:"=",65:"a",66:"b",67:"c",68:"d",69:"e",70:"f",71:"g",72:"h",73:"i",74:"j",75:"k",76:"l",77:"m",78:"n",79:"o",80:"p",81:"q",82:"r",83:"s",84:"t",85:"u",86:"v",87:"w",88:"x",89:"y",90:"z",107:"+",109:"-",110:".",188:",",190:".",191:"/",192:"`",219:"[",220:"\\",221:"]",222:'"'}};for(var b in a.FUNCTION_KEYS){var c=a.FUNCTION_KEYS[b].toUpperCase();a[c]=parseInt(b,10)}return d.mixin(a,a.MODIFIER_KEYS),d.mixin(a,a.PRINTABLE_KEYS),d.mixin(a,a.FUNCTION_KEYS),a}();d.mixin(b,e),b.keyCodeToString=function(a){return(e[a]||String.fromCharCode(a)).toLowerCase()}}),define("ace/lib/oop",["require","exports","module"],function(a,b,c){"use strict",b.inherits=function(){var a=function(){};return function(b,c){a.prototype=c.prototype,b.super_=c.prototype,b.prototype=new a,b.prototype.constructor=b}}(),b.mixin=function(a,b){for(var c in b)a[c]=b[c]},b.implement=function(a,c){b.mixin(a,c)}}),define("ace/lib/useragent",["require","exports","module"],function(a,b,c){"use strict";var d=(navigator.platform.match(/mac|win|linux/i)||["other"])[0].toLowerCase(),e=navigator.userAgent;b.isWin=d=="win",b.isMac=d=="mac",b.isLinux=d=="linux",b.isIE=navigator.appName=="Microsoft Internet Explorer"&&parseFloat(navigator.userAgent.match(/MSIE ([0-9]+[\.0-9]+)/)[1]),b.isOldIE=b.isIE&&b.isIE<9,b.isGecko=b.isMozilla=window.controllers&&window.navigator.product==="Gecko",b.isOldGecko=b.isGecko&&parseInt((navigator.userAgent.match(/rv\:(\d+)/)||[])[1],10)<4,b.isOpera=window.opera&&Object.prototype.toString.call(window.opera)=="[object Opera]",b.isWebKit=parseFloat(e.split("WebKit/")[1])||undefined,b.isChrome=parseFloat(e.split(" Chrome/")[1])||undefined,b.isAIR=e.indexOf("AdobeAIR")>=0,b.isIPad=e.indexOf("iPad")>=0,b.isTouchPad=e.indexOf("TouchPad")>=0,b.OS={LINUX:"LINUX",MAC:"MAC",WINDOWS:"WINDOWS"},b.getOS=function(){return b.isMac?b.OS.MAC:b.isLinux?b.OS.LINUX:b.OS.WINDOWS}}),define("ace/editor",["require","exports","module","ace/lib/fixoldbrowsers","ace/lib/oop","ace/lib/lang","ace/lib/useragent","ace/keyboard/textinput","ace/mouse/mouse_handler","ace/mouse/fold_handler","ace/keyboard/keybinding","ace/edit_session","ace/search","ace/range","ace/lib/event_emitter","ace/commands/command_manager","ace/commands/default_commands"],function(a,b,c){"use strict",a("./lib/fixoldbrowsers");var d=a("./lib/oop"),e=a("./lib/lang"),f=a("./lib/useragent"),g=a("./keyboard/textinput").TextInput,h=a("./mouse/mouse_handler").MouseHandler,i=a("./mouse/fold_handler").FoldHandler,j=a("./keyboard/keybinding").KeyBinding,k=a("./edit_session").EditSession,l=a("./search").Search,m=a("./range").Range,n=a("./lib/event_emitter").EventEmitter,o=a("./commands/command_manager").CommandManager,p=a("./commands/default_commands").commands,q=function(a,b){var c=a.getContainerElement();this.container=c,this.renderer=a,this.textInput=new g(a.getTextAreaContainer(),this),this.keyBinding=new j(this),f.isIPad||(this.$mouseHandler=new h(this),new i(this)),this.$blockScrolling=0,this.$search=(new l).set({wrap:!0}),this.commands=new o(f.isMac?"mac":"win",p),this.setSession(b||new k(""))};(function(){d.implement(this,n),this.setKeyboardHandler=function(a){this.keyBinding.setKeyboardHandler(a)},this.getKeyboardHandler=function(){return this.keyBinding.getKeyboardHandler()},this.setSession=function(a){if(this.session==a)return;if(this.session){var b=this.session;this.session.removeEventListener("change",this.$onDocumentChange),this.session.removeEventListener("changeMode",this.$onChangeMode),this.session.removeEventListener("tokenizerUpdate",this.$onTokenizerUpdate),this.session.removeEventListener("changeTabSize",this.$onChangeTabSize),this.session.removeEventListener("changeWrapLimit",this.$onChangeWrapLimit),this.session.removeEventListener("changeWrapMode",this.$onChangeWrapMode),this.session.removeEventListener("onChangeFold",this.$onChangeFold),this.session.removeEventListener("changeFrontMarker",this.$onChangeFrontMarker),this.session.removeEventListener("changeBackMarker",this.$onChangeBackMarker),this.session.removeEventListener("changeBreakpoint",this.$onChangeBreakpoint),this.session.removeEventListener("changeAnnotation",this.$onChangeAnnotation),this.session.removeEventListener("changeOverwrite",this.$onCursorChange),this.session.removeEventListener("changeScrollTop",this.$onScrollTopChange),this.session.removeEventListener("changeLeftTop",this.$onScrollLeftChange);var c=this.session.getSelection();c.removeEventListener("changeCursor",this.$onCursorChange),c.removeEventListener("changeSelection",this.$onSelectionChange)}this.session=a,this.$onDocumentChange=this.onDocumentChange.bind(this),a.addEventListener("change",this.$onDocumentChange),this.renderer.setSession(a),this.$onChangeMode=this.onChangeMode.bind(this),a.addEventListener("changeMode",this.$onChangeMode),this.$onTokenizerUpdate=this.onTokenizerUpdate.bind(this),a.addEventListener("tokenizerUpdate",this.$onTokenizerUpdate),this.$onChangeTabSize=this.renderer.updateText.bind(this.renderer),a.addEventListener("changeTabSize",this.$onChangeTabSize),this.$onChangeWrapLimit=this.onChangeWrapLimit.bind(this),a.addEventListener("changeWrapLimit",this.$onChangeWrapLimit),this.$onChangeWrapMode=this.onChangeWrapMode.bind(this),a.addEventListener("changeWrapMode",this.$onChangeWrapMode),this.$onChangeFold=this.onChangeFold.bind(this),a.addEventListener("changeFold",this.$onChangeFold),this.$onChangeFrontMarker=this.onChangeFrontMarker.bind(this),this.session.addEventListener("changeFrontMarker",this.$onChangeFrontMarker),this.$onChangeBackMarker=this.onChangeBackMarker.bind(this),this.session.addEventListener("changeBackMarker",this.$onChangeBackMarker),this.$onChangeBreakpoint=this.onChangeBreakpoint.bind(this),this.session.addEventListener("changeBreakpoint",this.$onChangeBreakpoint),this.$onChangeAnnotation=this.onChangeAnnotation.bind(this),this.session.addEventListener("changeAnnotation",this.$onChangeAnnotation),this.$onCursorChange=this.onCursorChange.bind(this),this.session.addEventListener("changeOverwrite",this.$onCursorChange),this.$onScrollTopChange=this.onScrollTopChange.bind(this),this.session.addEventListener("changeScrollTop",this.$onScrollTopChange),this.$onScrollLeftChange=this.onScrollLeftChange.bind(this),this.session.addEventListener("changeScrollLeft",this.$onScrollLeftChange),this.selection=a.getSelection(),this.selection.addEventListener("changeCursor",this.$onCursorChange),this.$onSelectionChange=this.onSelectionChange.bind(this),this.selection.addEventListener("changeSelection",this.$onSelectionChange),this.onChangeMode(),this.$blockScrolling+=1,this.onCursorChange(),this.$blockScrolling-=1,this.onScrollTopChange(),this.onScrollLeftChange(),this.onSelectionChange(),this.onChangeFrontMarker(),this.onChangeBackMarker(),this.onChangeBreakpoint(),this.onChangeAnnotation(),this.session.getUseWrapMode()&&this.renderer.adjustWrapLimit(),this.renderer.updateFull(),this._emit("changeSession",{session:a,oldSession:b})},this.getSession=function(){return this.session},this.getSelection=function(){return this.selection},this.resize=function(){this.renderer.onResize()},this.setTheme=function(a){this.renderer.setTheme(a)},this.getTheme=function(){return this.renderer.getTheme()},this.setStyle=function(a){this.renderer.setStyle(a)},this.unsetStyle=function(a){this.renderer.unsetStyle(a)},this.setFontSize=function(a){this.container.style.fontSize=a,this.renderer.updateFontSize()},this.$highlightBrackets=function(){this.session.$bracketHighlight&&(this.session.removeMarker(this.session.$bracketHighlight),this.session.$bracketHighlight=null);if(this.$highlightPending)return;var a=this;this.$highlightPending=!0,setTimeout(function(){a.$highlightPending=!1;var b=a.session.findMatchingBracket(a.getCursorPosition());if(b){var c=new m(b.row,b.column,b.row,b.column+1);a.session.$bracketHighlight=a.session.addMarker(c,"ace_bracket","text")}},10)},this.focus=function(){var a=this;setTimeout(function(){a.textInput.focus()}),this.textInput.focus()},this.isFocused=function(){return this.textInput.isFocused()},this.blur=function(){this.textInput.blur()},this.onFocus=function(){this.renderer.showCursor(),this.renderer.visualizeFocus(),this._emit("focus")},this.onBlur=function(){this.renderer.hideCursor(),this.renderer.visualizeBlur(),this._emit("blur")},this.onDocumentChange=function(a){var b=a.data,c=b.range,d;c.start.row==c.end.row&&b.action!="insertLines"&&b.action!="removeLines"?d=c.end.row:d=Infinity,this.renderer.updateLines(c.start.row,d),this._emit("change",a),this.onCursorChange()},this.onTokenizerUpdate=function(a){var b=a.data;this.renderer.updateLines(b.first,b.last)},this.onScrollTopChange=function(){this.renderer.scrollToY(this.session.getScrollTop())},this.onScrollLeftChange=function(){this.renderer.scrollToX(this.session.getScrollLeft())},this.onCursorChange=function(){this.renderer.updateCursor(),this.$blockScrolling||this.renderer.scrollCursorIntoView(),this.renderer.moveTextAreaToCursor(this.textInput.getElement()),this.$highlightBrackets(),this.$updateHighlightActiveLine()},this.$updateHighlightActiveLine=function(){var a=this.getSession();a.$highlightLineMarker&&a.removeMarker(a.$highlightLineMarker),typeof this.$lastrow=="number"&&this.renderer.removeGutterDecoration(this.$lastrow,"ace_gutter_active_line"),a.$highlightLineMarker=null,this.$lastrow=null;if(this.getHighlightActiveLine()){var b=this.getCursorPosition(),c=this.session.getFoldLine(b.row);if(this.getSelectionStyle()!="line"||!this.selection.isMultiLine()){var d;c?d=new m(c.start.row,0,c.end.row+1,0):d=new m(b.row,0,b.row+1,0),a.$highlightLineMarker=a.addMarker(d,"ace_active_line","background")}this.renderer.addGutterDecoration(this.$lastrow=b.row,"ace_gutter_active_line")}},this.onSelectionChange=function(a){var b=this.getSession();b.$selectionMarker&&b.removeMarker(b.$selectionMarker),b.$selectionMarker=null;if(!this.selection.isEmpty()){var c=this.selection.getRange(),d=this.getSelectionStyle();b.$selectionMarker=b.addMarker(c,"ace_selection",d)}else this.$updateHighlightActiveLine();this.$highlightSelectedWord&&this.session.getMode().highlightSelection(this)},this.onChangeFrontMarker=function(){this.renderer.updateFrontMarkers()},this.onChangeBackMarker=function(){this.renderer.updateBackMarkers()},this.onChangeBreakpoint=function(){this.renderer.setBreakpoints(this.session.getBreakpoints())},this.onChangeAnnotation=function(){this.renderer.setAnnotations(this.session.getAnnotations())},this.onChangeMode=function(){this.renderer.updateText()},this.onChangeWrapLimit=function(){this.renderer.updateFull()},this.onChangeWrapMode=function(){this.renderer.onResize(!0)},this.onChangeFold=function(){this.$updateHighlightActiveLine(),this.renderer.updateFull()},this.getCopyText=function(){var a="";return this.selection.isEmpty()||(a=this.session.getTextRange(this.getSelectionRange())),this._emit("copy",a),a},this.onCut=function(){this.commands.exec("cut",this)},this.insert=function(a){var b=this.session,c=b.getMode(),d=this.getCursorPosition();if(this.getBehavioursEnabled()){var e=c.transformAction(b.getState(d.row),"insertion",this,b,a);e&&(a=e.text)}a=a.replace("	",this.session.getTabString());if(!this.selection.isEmpty())d=this.session.remove(this.getSelectionRange()),this.clearSelection();else if(this.session.getOverwrite()){var f=new m.fromPoints(d,d);f.end.column+=a.length,this.session.remove(f)}this.clearSelection();var g=d.column,h=b.getState(d.row),i=c.checkOutdent(h,b.getLine(d.row),a),j=b.getLine(d.row),k=c.getNextLineIndent(h,j.slice(0,d.column),b.getTabString()),l=b.insert(d,a);e&&e.selection&&(e.selection.length==2?this.selection.setSelectionRange(new m(d.row,g+e.selection[0],d.row,g+e.selection[1])):this.selection.setSelectionRange(new m(d.row+e.selection[0],e.selection[1],d.row+e.selection[2],e.selection[3])));var h=b.getState(d.row);if(b.getDocument().isNewLine(a)){this.moveCursorTo(d.row+1,0);var n=b.getTabSize(),o=Number.MAX_VALUE;for(var p=d.row+1;p<=l.row;++p){var q=0;j=b.getLine(p);for(var r=0;r<j.length;++r)if(j.charAt(r)=="	")q+=n;else{if(j.charAt(r)!=" ")break;q+=1}/[^\s]/.test(j)&&(o=Math.min(q,o))}for(var p=d.row+1;p<=l.row;++p){var s=o;j=b.getLine(p);for(var r=0;r<j.length&&s>0;++r)j.charAt(r)=="	"?s-=n:j.charAt(r)==" "&&(s-=1);b.remove(new m(p,0,p,r))}b.indentRows(d.row+1,l.row,k)}i&&c.autoOutdent(h,b,d.row)},this.onTextInput=function(a,b){b&&this._emit("paste",a),this.keyBinding.onTextInput(a,b)},this.onCommandKey=function(a,b,c){this.keyBinding.onCommandKey(a,b,c)},this.setOverwrite=function(a){this.session.setOverwrite(a)},this.getOverwrite=function(){return this.session.getOverwrite()},this.toggleOverwrite=function(){this.session.toggleOverwrite()},this.setScrollSpeed=function(a){this.$mouseHandler.setScrollSpeed(a)},this.getScrollSpeed=function(){return this.$mouseHandler.getScrollSpeed()},this.setDragDelay=function(a){this.$mouseHandler.setDragDelay(a)},this.getDragDelay=function(){return this.$mouseHandler.getDragDelay()},this.$selectionStyle="line",this.setSelectionStyle=function(a){if(this.$selectionStyle==a)return;this.$selectionStyle=a,this.onSelectionChange(),this._emit("changeSelectionStyle",{data:a})},this.getSelectionStyle=function(){return this.$selectionStyle},this.$highlightActiveLine=!0,this.setHighlightActiveLine=function(a){if(this.$highlightActiveLine==a)return;this.$highlightActiveLine=a,this.$updateHighlightActiveLine()},this.getHighlightActiveLine=function(){return this.$highlightActiveLine},this.$highlightSelectedWord=!0,this.setHighlightSelectedWord=function(a){if(this.$highlightSelectedWord==a)return;this.$highlightSelectedWord=a,a?this.session.getMode().highlightSelection(this):this.session.getMode().clearSelectionHighlight(this)},this.getHighlightSelectedWord=function(){return this.$highlightSelectedWord},this.setAnimatedScroll=function(a){this.renderer.setAnimatedScroll(a)},this.getAnimatedScroll=function(){return this.renderer.getAnimatedScroll()},this.setShowInvisibles=function(a){if(this.getShowInvisibles()==a)return;this.renderer.setShowInvisibles(a)},this.getShowInvisibles=function(){return this.renderer.getShowInvisibles()},this.setShowPrintMargin=function(a){this.renderer.setShowPrintMargin(a)},this.getShowPrintMargin=function(){return this.renderer.getShowPrintMargin()},this.setPrintMarginColumn=function(a){this.renderer.setPrintMarginColumn(a)},this.getPrintMarginColumn=function(){return this.renderer.getPrintMarginColumn()},this.$readOnly=!1,this.setReadOnly=function(a){this.$readOnly=a},this.getReadOnly=function(){return this.$readOnly},this.$modeBehaviours=!0,this.setBehavioursEnabled=function(a){this.$modeBehaviours=a},this.getBehavioursEnabled=function(){return this.$modeBehaviours},this.setShowFoldWidgets=function(a){var b=this.renderer.$gutterLayer;if(b.getShowFoldWidgets()==a)return;this.renderer.$gutterLayer.setShowFoldWidgets(a),this.$showFoldWidgets=a,this.renderer.updateFull()},this.getShowFoldWidgets=function(){return this.renderer.$gutterLayer.getShowFoldWidgets()},this.remove=function(a){this.selection.isEmpty()&&(a=="left"?this.selection.selectLeft():this.selection.selectRight());var b=this.getSelectionRange();if(this.getBehavioursEnabled()){var c=this.session,d=c.getState(b.start.row),e=c.getMode().transformAction(d,"deletion",this,c,b);e&&(b=e)}this.session.remove(b),this.clearSelection()},this.removeWordRight=function(){this.selection.isEmpty()&&this.selection.selectWordRight(),this.session.remove(this.getSelectionRange()),this.clearSelection()},this.removeWordLeft=function(){this.selection.isEmpty()&&this.selection.selectWordLeft(),this.session.remove(this.getSelectionRange()),this.clearSelection()},this.removeToLineStart=function(){this.selection.isEmpty()&&this.selection.selectLineStart(),this.session.remove(this.getSelectionRange()),this.clearSelection()},this.removeToLineEnd=function(){this.selection.isEmpty()&&this.selection.selectLineEnd();var a=this.getSelectionRange();a.start.column==a.end.column&&a.start.row==a.end.row&&(a.end.column=0,a.end.row++),this.session.remove(a),this.clearSelection()},this.splitLine=function(){this.selection.isEmpty()||(this.session.remove(this.getSelectionRange()),this.clearSelection());var a=this.getCursorPosition();this.insert("\n"),this.moveCursorToPosition(a)},this.transposeLetters=function(){if(!this.selection.isEmpty())return;var a=this.getCursorPosition(),b=a.column;if(b===0)return;var c=this.session.getLine(a.row),d,e;b<c.length?(d=c.charAt(b)+c.charAt(b-1),e=new m(a.row,b-1,a.row,b+1)):(d=c.charAt(b-1)+c.charAt(b-2),e=new m(a.row,b-2,a.row,b)),this.session.replace(e,d)},this.toLowerCase=function(){var a=this.getSelectionRange();this.selection.isEmpty()&&this.selection.selectWord();var b=this.getSelectionRange(),c=this.session.getTextRange(b);this.session.replace(b,c.toLowerCase()),this.selection.setSelectionRange(a)},this.toUpperCase=function(){var a=this.getSelectionRange();this.selection.isEmpty()&&this.selection.selectWord();var b=this.getSelectionRange(),c=this.session.getTextRange(b);this.session.replace(b,c.toUpperCase()),this.selection.setSelectionRange(a)},this.indent=function(){var a=this.session,b=this.getSelectionRange();if(!(b.start.row<b.end.row||b.start.column<b.end.column)){var d;if(this.session.getUseSoftTabs()){var f=a.getTabSize(),g=this.getCursorPosition(),h=a.documentToScreenColumn(g.row,g.column),i=f-h%f;d=e.stringRepeat(" ",i)}else d="	";return this.insert(d)}var c=this.$getSelectedRows();a.indentRows(c.first,c.last,"	")},this.blockOutdent=function(){var a=this.session.getSelection();this.session.outdentRows(a.getRange())},this.toggleCommentLines=function(){var a=this.session.getState(this.getCursorPosition().row),b=this.$getSelectedRows();this.session.getMode().toggleCommentLines(a,this.session,b.first,b.last)},this.removeLines=function(){var a=this.$getSelectedRows(),b;a.first===0||a.last+1<this.session.getLength()?b=new m(a.first,0,a.last+1,0):b=new m(a.first-1,this.session.getLine(a.first-1).length,a.last,this.session.getLine(a.last).length),this.session.remove(b),this.clearSelection()},this.moveLinesDown=function(){this.$moveLines(function(a,b){return this.session.moveLinesDown(a,b)})},this.moveLinesUp=function(){this.$moveLines(function(a,b){return this.session.moveLinesUp(a,b)})},this.moveText=function(a,b){return this.$readOnly?null:this.session.moveText(a,b)},this.copyLinesUp=function(){this.$moveLines(function(a,b){return this.session.duplicateLines(a,b),0})},this.copyLinesDown=function(){this.$moveLines(function(a,b){return this.session.duplicateLines(a,b)})},this.$moveLines=function(a){var b=this.$getSelectedRows(),c=this.selection;if(!c.isMultiLine())var d=c.getRange(),e=c.isBackwards();var f=a.call(this,b.first,b.last);d?(d.start.row+=f,d.end.row+=f,c.setSelectionRange(d,e)):(c.setSelectionAnchor(b.last+f+1,0),c.$moveSelection(function(){c.moveCursorTo(b.first+f,0)}))},this.$getSelectedRows=function(){var a=this.getSelectionRange().collapseRows();return{first:a.start.row,last:a.end.row}},this.onCompositionStart=function(a){this.renderer.showComposition(this.getCursorPosition())},this.onCompositionUpdate=function(a){this.renderer.setCompositionText(a)},this.onCompositionEnd=function(){this.renderer.hideComposition()},this.getFirstVisibleRow=function(){return this.renderer.getFirstVisibleRow()},this.getLastVisibleRow=function(){return this.renderer.getLastVisibleRow()},this.isRowVisible=function(a){return a>=this.getFirstVisibleRow()&&a<=this.getLastVisibleRow()},this.isRowFullyVisible=function(a){return a>=this.renderer.getFirstFullyVisibleRow()&&a<=this.renderer.getLastFullyVisibleRow()},this.$getVisibleRowCount=function(){return this.renderer.getScrollBottomRow()-this.renderer.getScrollTopRow()+1},this.$getPageDownRow=function(){return this.renderer.getScrollBottomRow()},this.$getPageUpRow=function(){var a=this.renderer.getScrollTopRow(),b=this.renderer.getScrollBottomRow();return a-(b-a)},this.selectPageDown=function(){var a=this.$getPageDownRow()+Math.floor(this.$getVisibleRowCount()/2);this.scrollPageDown();var b=this.getSelection(),c=this.session.documentToScreenPosition(b.getSelectionLead()),d=this.session.screenToDocumentPosition(a,c.column);b.selectTo(d.row,d.column)},this.selectPageUp=function(){var a=this.renderer.getScrollTopRow()-this.renderer.getScrollBottomRow(),b=this.$getPageUpRow()+Math.round(a/2);this.scrollPageUp();var c=this.getSelection(),d=this.session.documentToScreenPosition(c.getSelectionLead()),e=this.session.screenToDocumentPosition(b,d.column);c.selectTo(e.row,e.column)},this.gotoPageDown=function(){var a=this.$getPageDownRow(),b=this.getCursorPositionScreen().column;this.scrollToRow(a),this.getSelection().moveCursorToScreen(a,b)},this.gotoPageUp=function(){var a=this.$getPageUpRow(),b=this.getCursorPositionScreen().column;this.scrollToRow(a),this.getSelection().moveCursorToScreen(a,b)},this.scrollPageDown=function(){this.scrollToRow(this.$getPageDownRow())},this.scrollPageUp=function(){this.renderer.scrollToRow(this.$getPageUpRow())},this.scrollToRow=function(a){this.renderer.scrollToRow(a)},this.scrollToLine=function(a,b){this.renderer.scrollToLine(a,b)},this.centerSelection=function(){var a=this.getSelectionRange(),b=Math.floor(a.start.row+(a.end.row-a.start.row)/2);this.renderer.scrollToLine(b,!0)},this.getCursorPosition=function(){return this.selection.getCursor()},this.getCursorPositionScreen=function(){return this.session.documentToScreenPosition(this.getCursorPosition())},this.getSelectionRange=function(){return this.selection.getRange()},this.selectAll=function(){this.$blockScrolling+=1,this.selection.selectAll(),this.$blockScrolling-=1},this.clearSelection=function(){this.selection.clearSelection()},this.moveCursorTo=function(a,b){this.selection.moveCursorTo(a,b)},this.moveCursorToPosition=function(a){this.selection.moveCursorToPosition(a)},this.jumpToMatching=function(){var a=this.getCursorPosition(),b=this.session.findMatchingBracket(a);b||(a.column+=1,b=this.session.findMatchingBracket(a)),b||(a.column-=2,b=this.session.findMatchingBracket(a)),b&&(this.clearSelection(),this.moveCursorTo(b.row,b.column))},this.gotoLine=function(a,b){this.selection.clearSelection(),this.session.unfold({row:a-1,column:b||0}),this.$blockScrolling+=1,this.moveCursorTo(a-1,b||0),this.$blockScrolling-=1,this.isRowFullyVisible(this.getCursorPosition().row)||this.scrollToLine(a,!0)},this.navigateTo=function(a,b){this.clearSelection(),this.moveCursorTo(a,b)},this.navigateUp=function(a){this.selection.clearSelection(),a=a||1,this.selection.moveCursorBy(-a,0)},this.navigateDown=function(a){this.selection.clearSelection(),a=a||1,this.selection.moveCursorBy(a,0)},this.navigateLeft=function(a){if(!this.selection.isEmpty()){var b=this.getSelectionRange().start;this.moveCursorToPosition(b)}else{a=a||1;while(a--)this.selection.moveCursorLeft()}this.clearSelection()},this.navigateRight=function(a){if(!this.selection.isEmpty()){var b=this.getSelectionRange().end;this.moveCursorToPosition(b)}else{a=a||1;while(a--)this.selection.moveCursorRight()}this.clearSelection()},this.navigateLineStart=function(){this.selection.moveCursorLineStart(),this.clearSelection()},this.navigateLineEnd=function(){this.selection.moveCursorLineEnd(),this.clearSelection()},this.navigateFileEnd=function(){this.selection.moveCursorFileEnd(),this.clearSelection()},this.navigateFileStart=function(){this.selection.moveCursorFileStart(),this.clearSelection()},this.navigateWordRight=function(){this.selection.moveCursorWordRight(),this.clearSelection()},this.navigateWordLeft=function(){this.selection.moveCursorWordLeft(),this.clearSelection()},this.replace=function(a,b){b&&this.$search.set(b);var c=this.$search.find(this.session),d=0;return c?(this.$tryReplace(c,a)&&(d=1),c!==null&&(this.selection.setSelectionRange(c),this.renderer.scrollSelectionIntoView(c.start,c.end)),d):d},this.replaceAll=function(a,b){b&&this.$search.set(b);var c=this.$search.findAll(this.session),d=0;if(!c.length)return d;var e=this.getSelectionRange();this.clearSelection(),this.selection.moveCursorTo(0,0),this.$blockScrolling+=1;for(var f=c.length-1;f>=0;--f)this.$tryReplace(c[f],a)&&d++;return this.selection.setSelectionRange(e),this.$blockScrolling-=1,d},this.$tryReplace=function(a,b){var c=this.session.getTextRange(a);return b=this.$search.replace(c,b),b!==null?(a.end=this.session.replace(a,b),a):null},this.getLastSearchOptions=function(){return this.$search.getOptions()},this.find=function(a,b){this.clearSelection(),b=b||{},b.needle=a,this.$search.set(b),this.$find()},this.findNext=function(a){a=a||{},typeof a.backwards=="undefined"&&(a.backwards=!1),this.$search.set(a),this.$find()},this.findPrevious=function(a){a=a||{},typeof a.backwards=="undefined"&&(a.backwards=!0),this.$search.set(a),this.$find()},this.$find=function(a){this.selection.isEmpty()||this.$search.set({needle:this.session.getTextRange(this.getSelectionRange())}),typeof a!="undefined"&&this.$search.set({backwards:a});var b=this.$search.find(this.session);if(b){this.session.unfold(b),this.$blockScrolling+=1,this.selection.setSelectionRange(b),this.$blockScrolling-=1;if(this.getAnimatedScroll()){var c=this.getCursorPosition();this.isRowFullyVisible(c.row)||this.scrollToLine(c.row,!0)}else this.renderer.scrollSelectionIntoView(b.start,b.end)}},this.undo=function(){this.session.getUndoManager().undo()},this.redo=function(){this.session.getUndoManager().redo()},this.destroy=function(){this.renderer.destroy()}}).call(q.prototype),b.Editor=q}),define("ace/lib/lang",["require","exports","module"],function(a,b,c){"use strict",b.stringReverse=function(a){return a.split("").reverse().join("")},b.stringRepeat=function(a,b){return(new Array(b+1)).join(a)};var d=/^\s\s*/,e=/\s\s*$/;b.stringTrimLeft=function(a){return a.replace(d,"")},b.stringTrimRight=function(a){return a.replace(e,"")},b.copyObject=function(a){var b={};for(var c in a)b[c]=a[c];return b},b.copyArray=function(a){var b=[];for(var c=0,d=a.length;c<d;c++)a[c]&&typeof a[c]=="object"?b[c]=this.copyObject(a[c]):b[c]=a[c];return b},b.deepCopy=function(a){if(typeof a!="object")return a;var b=a.constructor();for(var c in a)typeof a[c]=="object"?b[c]=this.deepCopy(a[c]):b[c]=a[c];return b},b.arrayToMap=function(a){var b={};for(var c=0;c<a.length;c++)b[a[c]]=1;return b},b.arrayRemove=function(a,b){for(var c=0;c<=a.length;c++)b===a[c]&&a.splice(c,1)},b.escapeRegExp=function(a){return a.replace(/([.*+?^${}()|[\]\/\\])/g,"\\$1")},b.deferredCall=function(a){var b=null,c=function(){b=null,a()},d=function(a){return d.cancel(),b=setTimeout(c,a||0),d};return d.schedule=d,d.call=function(){return this.cancel(),a(),d},d.cancel=function(){return clearTimeout(b),b=null,d},d}}),define("ace/keyboard/textinput",["require","exports","module","ace/lib/event","ace/lib/useragent","ace/lib/dom"],function(a,b,c){"use strict";var d=a("../lib/event"),e=a("../lib/useragent"),f=a("../lib/dom"),g=function(a,b){function l(){try{c.select()}catch(a){}}function m(a){if(!i){var d=a||c.value;if(d){d.charCodeAt(d.length-1)==g.charCodeAt(0)?(d=d.slice(0,-1),d&&b.onTextInput(d,j)):b.onTextInput(d,j);if(!v())return!1}}i=!1,j=!1,c.value=g,l()}function v(){return document.activeElement===c}var c=f.createElement("textarea");e.isTouchPad&&c.setAttribute("x-palm-disable-auto-cap",!0),c.style.left="-10000px",c.style.position="fixed",a.insertBefore(c,a.firstChild);var g=String.fromCharCode(0);m();var h=!1,i=!1,j=!1,k="",n=function(a){setTimeout(function(){h||m(a.data)},0)},o=function(a){if(e.isOldIE&&c.value.charCodeAt(0)>128)return;setTimeout(function(){h||m()},0)},p=function(a){h=!0,b.onCompositionStart(),e.isGecko||setTimeout(q,0)},q=function(){if(!h)return;b.onCompositionUpdate(c.value)},r=function(a){h=!1,b.onCompositionEnd()},s=function(a){i=!0;var d=b.getCopyText();d?c.value=d:a.preventDefault(),l(),setTimeout(function(){m()},0)},t=function(a){i=!0;var d=b.getCopyText();d?(c.value=d,b.onCut()):a.preventDefault(),l(),setTimeout(function(){m()},0)};d.addCommandKeyListener(c,b.onCommandKey.bind(b));if(e.isOldIE){var u={13:1,27:1};d.addListener(c,"keyup",function(a){h&&(!c.value||u[a.keyCode])&&setTimeout(r,0);if((c.value.charCodeAt(0)|0)<129)return;h?q():p()})}"onpropertychange"in c&&!("oninput"in c)?d.addListener(c,"propertychange",o):d.addListener(c,"input",n),d.addListener(c,"paste",function(a){j=!0,a.clipboardData&&a.clipboardData.getData?(m(a.clipboardData.getData("text/plain")),a.preventDefault()):o()}),"onbeforecopy"in c&&typeof clipboardData!="undefined"?(d.addListener(c,"beforecopy",function(a){var c=b.getCopyText();c?clipboardData.setData("Text",c):a.preventDefault()}),d.addListener(a,"keydown",function(a){if(a.ctrlKey&&a.keyCode==88){var c=b.getCopyText();c&&(clipboardData.setData("Text",c),b.onCut()),d.preventDefault(a)}})):(d.addListener(c,"copy",s),d.addListener(c,"cut",t)),d.addListener(c,"compositionstart",p),e.isGecko&&d.addListener(c,"text",q),e.isWebKit&&d.addListener(c,"keyup",q),d.addListener(c,"compositionend",r),d.addListener(c,"blur",function(){b.onBlur()}),d.addListener(c,"focus",function(){b.onFocus(),l()}),this.focus=function(){b.onFocus(),l(),c.focus()},this.blur=function(){c.blur()},this.isFocused=v,this.getElement=function(){return c},this.onContextMenu=function(a,b){a&&(k||(k=c.style.cssText),c.style.cssText="position:fixed; z-index:1000;left:"+(a.x-2)+"px; top:"+(a.y-2)+"px;"),b&&(c.value="")},this.onContextMenuClose=function(){setTimeout(function(){k&&(c.style.cssText=k,k=""),m()},0)}};b.TextInput=g}),define("ace/mouse/mouse_handler",["require","exports","module","ace/lib/event","ace/mouse/default_handlers","ace/mouse/default_gutter_handler","ace/mouse/mouse_event"],function(a,b,c){"use strict";var d=a("../lib/event"),e=a("./default_handlers").DefaultHandlers,f=a("./default_gutter_handler").GutterHandler,g=a("./mouse_event").MouseEvent,h=function(a){this.editor=a,new e(a),new f(a),d.addListener(a.container,"mousedown",function(b){return a.focus(),d.preventDefault(b)}),d.addListener(a.container,"selectstart",function(a){return d.preventDefault(a)});var b=a.renderer.getMouseEventTarget();d.addListener(b,"mousedown",this.onMouseEvent.bind(this,"mousedown")),d.addListener(b,"click",this.onMouseEvent.bind(this,"click")),d.addListener(b,"mousemove",this.onMouseMove.bind(this,"mousemove")),d.addMultiMouseDownListener(b,0,2,500,this.onMouseEvent.bind(this,"dblclick")),d.addMultiMouseDownListener(b,0,3,600,this.onMouseEvent.bind(this,"tripleclick")),d.addMultiMouseDownListener(b,0,4,600,this.onMouseEvent.bind(this,"quadclick")),d.addMouseWheelListener(a.container,this.onMouseWheel.bind(this,"mousewheel"));var c=a.renderer.$gutter;d.addListener(c,"mousedown",this.onMouseEvent.bind(this,"guttermousedown")),d.addListener(c,"click",this.onMouseEvent.bind(this,"gutterclick")),d.addListener(c,"dblclick",this.onMouseEvent.bind(this,"gutterdblclick")),d.addListener(c,"mousemove",this.onMouseMove.bind(this,"gutter"))};(function(){this.$scrollSpeed=1,this.setScrollSpeed=function(a){this.$scrollSpeed=a},this.getScrollSpeed=function(){return this.$scrollSpeed},this.onMouseEvent=function(a,b){this.editor._emit(a,new g(b,this.editor))},this.$dragDelay=250,this.setDragDelay=function(a){this.$dragDelay=a},this.getDragDelay=function(){return this.$dragDelay},this.onMouseMove=function(a,b){var c=this.editor._eventRegistry&&this.editor._eventRegistry.mousemove;if(!c||!c.length)return;this.editor._emit(a,new g(b,this.editor))},this.onMouseWheel=function(a,b){var c=new g(b,this.editor);c.speed=this.$scrollSpeed*2,c.wheelX=b.wheelX,c.wheelY=b.wheelY,this.editor._emit(a,c)}}).call(h.prototype),b.MouseHandler=h}),define("ace/mouse/default_handlers",["require","exports","module","ace/lib/event","ace/lib/dom","ace/lib/browser_focus"],function(a,b,c){function k(a){this.editor=a,this.$clickSelection=null,this.browserFocus=new f,a.setDefaultHandler("mousedown",this.onMouseDown.bind(this)),a.setDefaultHandler("dblclick",this.onDoubleClick.bind(this)),a.setDefaultHandler("tripleclick",this.onTripleClick.bind(this)),a.setDefaultHandler("quadclick",this.onQuadClick.bind(this)),a.setDefaultHandler("mousewheel",this.onScroll.bind(this))}function l(a,b,c,d){return Math.sqrt(Math.pow(c-a,2)+Math.pow(d-b,2))}"use strict";var d=a("../lib/event"),e=a("../lib/dom"),f=a("../lib/browser_focus").BrowserFocus,g=0,h=1,i=2,j=5;(function(){this.onMouseDown=function(a){function C(b){a.getShiftKey()?m.selection.selectToPosition(b):n.$clickSelection||(m.moveCursorToPosition(b),m.selection.clearSelection()),q=h}var b=a.inSelection(),c=a.pageX,f=a.pageY,k=a.getDocumentPosition(),m=this.editor,n=this,o=m.getSelectionRange(),p=o.isEmpty(),q=g;if(b&&(!this.browserFocus.isFocused()||(new Date).getTime()-this.browserFocus.lastFocus<20||!m.isFocused())){m.focus();return}var r=a.getButton();if(r!==0){p&&m.moveCursorToPosition(k),r==2&&(m.textInput.onContextMenu({x:a.clientX,y:a.clientY},p),d.capture(m.container,function(){},m.textInput.onContextMenuClose));return}b||C(k);var s=c,t=f,u=(new Date).getTime(),v,w,x,y=function(a){s=d.getDocumentX(a),t=d.getDocumentY(a)},z=function(a){clearInterval(F),q==g?C(k):q==i&&A(a),n.$clickSelection=null,q=g},A=function(a){e.removeCssClass(m.container,"ace_dragging"),m.session.removeMarker(x),m.$mouseHandler.$clickSelection||v||(m.moveCursorToPosition(k),m.selection.clearSelection());if(!v)return;if(w.contains(v.row,v.column)){v=null;return}m.clearSelection();if(a&&(a.ctrlKey||a.altKey))var b=m.session,c=b.insert(v,b.getTextRange(w));else var c=m.moveText(w,v);if(!c){v=null;return}m.selection.setSelectionRange(c)},B=function(){if(q==g){var a=l(c,f,s,t),b=(new Date).getTime();if(a>j){q=h;var d=m.renderer.screenToTextCoordinates(s,t);C(d)}else if(b-u>m.getDragDelay()){q=i,w=m.getSelectionRange();var k=m.getSelectionStyle();x=m.session.addMarker(w,"ace_selection",k),m.clearSelection(),e.addCssClass(m.container,"ace_dragging")}}q==i?E():q==h&&D()},D=function(){var a,b=m.renderer.screenToTextCoordinates(s,t);n.$clickSelection?n.$clickSelection.contains(b.row,b.column)?m.selection.setSelectionRange(n.$clickSelection):(n.$clickSelection.compare(b.row,b.column)==-1?a=n.$clickSelection.end:a=n.$clickSelection.start,m.selection.setSelectionAnchor(a.row,a.column),m.selection.selectToPosition(b)):m.selection.selectToPosition(b),m.renderer.scrollCursorIntoView()},E=function(){v=m.renderer.screenToTextCoordinates(s,t),m.moveCursorToPosition(v)};d.capture(m.container,y,z);var F=setInterval(B,20);return a.preventDefault()},this.onDoubleClick=function(a){var b=a.getDocumentPosition(),c=this.editor;c.moveCursorToPosition(b),c.selection.selectWord(),this.$clickSelection=c.getSelectionRange()},this.onTripleClick=function(a){var b=a.getDocumentPosition(),c=this.editor;c.moveCursorToPosition(b),c.selection.selectLine(),this.$clickSelection=c.getSelectionRange()},this.onQuadClick=function(a){var b=this.editor;b.selectAll(),this.$clickSelection=b.getSelectionRange()},this.onScroll=function(a){var b=this.editor;b.renderer.scrollBy(a.wheelX*a.speed,a.wheelY*a.speed);if(b.renderer.isScrollableBy(a.wheelX*a.speed,a.wheelY*a.speed))return a.preventDefault()}}).call(k.prototype),b.DefaultHandlers=k}),define("ace/lib/browser_focus",["require","exports","module","ace/lib/oop","ace/lib/event","ace/lib/event_emitter"],function(a,b,c){"use strict";var d=a("./oop"),e=a("./event"),f=a("./event_emitter").EventEmitter,g=function(a){a=a||window,this.lastFocus=(new Date).getTime(),this._isFocused=!0;var b=this;"onfocusin"in a.document?(e.addListener(a.document,"focusin",function(a){b._setFocused(!0)}),e.addListener(a.document,"focusout",function(a){b._setFocused(!!a.toElement)})):(e.addListener(a,"blur",function(a){b._setFocused(!1)}),e.addListener(a,"focus",function(a){b._setFocused(!0)}))};(function(){d.implement(this,f),this.isFocused=function(){return this._isFocused},this._setFocused=function(a){if(this._isFocused==a)return;a&&(this.lastFocus=(new Date).getTime()),this._isFocused=a,this._emit("changeFocus")}}).call(g.prototype),b.BrowserFocus=g}),define("ace/lib/event_emitter",["require","exports","module"],function(a,b,c){"use strict";var d={};d._emit=d._dispatchEvent=function(a,b){this._eventRegistry=this._eventRegistry||{},this._defaultHandlers=this._defaultHandlers||{};var c=this._eventRegistry[a]||[],d=this._defaultHandlers[a];if(!c.length&&!d)return;b=b||{},b.type=a,b.stopPropagation||(b.stopPropagation=function(){this.propagationStopped=!0}),b.preventDefault||(b.preventDefault=function(){this.defaultPrevented=!0});for(var e=0;e<c.length;e++){c[e](b);if(b.propagationStopped)break}d&&!b.defaultPrevented&&d(b)},d.setDefaultHandler=function(a,b){this._defaultHandlers=this._defaultHandlers||{};if(this._defaultHandlers[a])throw new Error("The default handler for '"+a+"' is already set");this._defaultHandlers[a]=b},d.on=d.addEventListener=function(a,b){this._eventRegistry=this._eventRegistry||{};var c=this._eventRegistry[a];if(!c)var c=this._eventRegistry[a]=[];c.indexOf(b)==-1&&c.push(b)},d.removeListener=d.removeEventListener=function(a,b){this._eventRegistry=this._eventRegistry||{};var c=this._eventRegistry[a];if(!c)return;var d=c.indexOf(b);d!==-1&&c.splice(d,1)},d.removeAllListeners=function(a){this._eventRegistry&&(this._eventRegistry[a]=[])},b.EventEmitter=d}),define("ace/mouse/default_gutter_handler",["require","exports","module"],function(a,b,c){function d(a){a.setDefaultHandler("gutterclick",function(b){var c=b.getDocumentPosition().row,d=a.session.selection;d.moveCursorTo(c,0),d.selectLine()})}"use strict",b.GutterHandler=d}),define("ace/mouse/mouse_event",["require","exports","module","ace/lib/event"],function(a,b,c){"use strict";var d=a("../lib/event"),e=b.MouseEvent=function(a,b){this.domEvent=a,this.editor=b,this.pageX=d.getDocumentX(a),this.pageY=d.getDocumentY(a),this.clientX=a.clientX,this.clientY=a.clientY,this.$pos=null,this.$inSelection=null,this.propagationStopped=!1,this.defaultPrevented=!1};(function(){this.stopPropagation=function(){d.stopPropagation(this.domEvent),this.propagationStopped=!0},this.preventDefault=function(){d.preventDefault(this.domEvent),this.defaultPrevented=!0},this.stop=function(){this.stopPropagation(),this.preventDefault()},this.getDocumentPosition=function(){if(this.$pos)return this.$pos;var a=d.getDocumentX(this.domEvent),b=d.getDocumentY(this.domEvent);return this.$pos=this.editor.renderer.screenToTextCoordinates(a,b),this.$pos},this.inSelection=function(){if(this.$inSelection!==null)return this.$inSelection;var a=this.editor;if(a.getReadOnly())this.$inSelection=!1;else{var b=a.getSelectionRange();if(b.isEmpty())this.$inSelection=!1;else{var c=this.getDocumentPosition();this.$inSelection=b.contains(c.row,c.column)}}return this.$inSelection},this.getButton=function(){return d.getButton(this.domEvent)},this.getShiftKey=function(){return this.domEvent.shiftKey},this.getAccelKey=function(){return this.domEvent.ctrlKey||this.domEvent.metaKey}}).call(e.prototype)}),define("ace/mouse/fold_handler",["require","exports","module"],function(a,b,c){function d(a){a.on("click",function(b){var c=b.getDocumentPosition(),d=a.session,e=d.getFoldAt(c.row,c.column,1);e&&(b.getAccelKey()?d.removeFold(e):d.expandFold(e),b.stop())}),a.on("gutterclick",function(b){if(b.domEvent.target.className.indexOf("ace_fold-widget")!=-1){var c=b.getDocumentPosition().row;a.session.onFoldWidgetClick(c,b.domEvent),b.stop()}})}"use strict",b.FoldHandler=d}),define("ace/keyboard/keybinding",["require","exports","module","ace/lib/keys","ace/lib/event","ace/commands/default_commands"],function(a,b,c){"use strict";var d=a("../lib/keys"),e=a("../lib/event");a("../commands/default_commands");var f=function(a){this.$editor=a,this.$data={},this.$handlers=[this]};(function(){this.setKeyboardHandler=function(a){if(this.$handlers[this.$handlers.length-1]==a)return;this.$data={},this.$handlers=a?[this,a]:[this]},this.addKeyboardHandler=function(a){this.removeKeyboardHandler(a),this.$handlers.push(a)},this.removeKeyboardHandler=function(a){var b=this.$handlers.indexOf(a);return b==-1?!1:(this.$handlers.splice(b,1),!0)},this.getKeyboardHandler=function(){return this.$handlers[this.$handlers.length-1]},this.$callKeyboardHandlers=function(a,b,c,d){var f;for(var g=this.$handlers.length;g--;){f=this.$handlers[g].handleKeyboard(this.$data,a,b,c,d);if(f&&f.command)break}if(!f||!f.command)return!1;var h=!1,i=this.$editor.commands;return f.command!="null"?h=i.exec(f.command,this.$editor,f.args):h=!0,h&&d&&e.stopEvent(d),h},this.handleKeyboard=function(a,b,c){return{command:this.$editor.commands.findKeyCommand(b,c)}},this.onCommandKey=function(a,b,c){var e=d.keyCodeToString(c);this.$callKeyboardHandlers(b,e,c,a)},this.onTextInput=function(a,b){var c=!1;!b&&a.length==1&&(c=this.$callKeyboardHandlers(0,a)),c||this.$editor.commands.exec("insertstring",this.$editor,a)}}).call(f.prototype),b.KeyBinding=f}),define("ace/commands/default_commands",["require","exports","module","ace/lib/lang"],function(a,b,c){function e(a,b){return{win:a,mac:b}}"use strict";var d=a("../lib/lang");b.commands=[{name:"selectall",bindKey:e("Ctrl-A","Command-A"),exec:function(a){a.selectAll()},readOnly:!0},{name:"centerselection",bindKey:e(null,"Ctrl-L"),exec:function(a){a.centerSelection()},readOnly:!0},{name:"gotoline",bindKey:e("Ctrl-L","Command-L"),exec:function(a){var b=parseInt(prompt("Enter line number:"),10);isNaN(b)||a.gotoLine(b)},readOnly:!0},{name:"fold",bindKey:e("Alt-L","Alt-L"),exec:function(a){a.session.toggleFold(!1)},readOnly:!0},{name:"unfold",bindKey:e("Alt-Shift-L","Alt-Shift-L"),exec:function(a){a.session.toggleFold(!0)},readOnly:!0},{name:"foldall",bindKey:e("Alt-0","Alt-0"),exec:function(a){a.session.foldAll()},readOnly:!0},{name:"unfoldall",bindKey:e("Alt-Shift-0","Alt-Shift-0"),exec:function(a){a.session.unfold()},readOnly:!0},{name:"findnext",bindKey:e("Ctrl-K","Command-G"),exec:function(a){a.findNext()},readOnly:!0},{name:"findprevious",bindKey:e("Ctrl-Shift-K","Command-Shift-G"),exec:function(a){a.findPrevious()},readOnly:!0},{name:"find",bindKey:e("Ctrl-F","Command-F"),exec:function(a){var b=prompt("Find:",a.getCopyText());a.find(b)},readOnly:!0},{name:"overwrite",bindKey:e("Insert","Insert"),exec:function(a){a.toggleOverwrite()},readOnly:!0},{name:"selecttostart",bindKey:e("Ctrl-Shift-Home|Alt-Shift-Up","Command-Shift-Up"),exec:function(a){a.getSelection().selectFileStart()},readOnly:!0},{name:"gotostart",bindKey:e("Ctrl-Home|Ctrl-Up","Command-Home|Command-Up"),exec:function(a){a.navigateFileStart()},readOnly:!0},{name:"selectup",bindKey:e("Shift-Up","Shift-Up"),exec:function(a){a.getSelection().selectUp()},multiSelectAction:"forEach",readOnly:!0},{name:"golineup",bindKey:e("Up","Up|Ctrl-P"),exec:function(a,b){a.navigateUp(b.times)},multiSelectAction:"forEach",readOnly:!0},{name:"selecttoend",bindKey:e("Ctrl-Shift-End|Alt-Shift-Down","Command-Shift-Down"),exec:function(a){a.getSelection().selectFileEnd()},multiSelectAction:"forEach",readOnly:!0},{name:"gotoend",bindKey:e("Ctrl-End|Ctrl-Down","Command-End|Command-Down"),exec:function(a){a.navigateFileEnd()},multiSelectAction:"forEach",readOnly:!0},{name:"selectdown",bindKey:e("Shift-Down","Shift-Down"),exec:function(a){a.getSelection().selectDown()},multiSelectAction:"forEach",readOnly:!0},{name:"golinedown",bindKey:e("Down","Down|Ctrl-N"),exec:function(a,b){a.navigateDown(b.times)},multiSelectAction:"forEach",readOnly:!0},{name:"selectwordleft",bindKey:e("Ctrl-Shift-Left","Option-Shift-Left"),exec:function(a){a.getSelection().selectWordLeft()},multiSelectAction:"forEach",readOnly:!0},{name:"gotowordleft",bindKey:e("Ctrl-Left","Option-Left"),exec:function(a){a.navigateWordLeft()},multiSelectAction:"forEach",readOnly:!0},{name:"selecttolinestart",bindKey:e("Alt-Shift-Left","Command-Shift-Left"),exec:function(a){a.getSelection().selectLineStart()},multiSelectAction:"forEach",readOnly:!0},{name:"gotolinestart",bindKey:e("Alt-Left|Home","Command-Left|Home|Ctrl-A"),exec:function(a){a.navigateLineStart()},multiSelectAction:"forEach",readOnly:!0},{name:"selectleft",bindKey:e("Shift-Left","Shift-Left"),exec:function(a){a.getSelection().selectLeft()},multiSelectAction:"forEach",readOnly:!0},{name:"gotoleft",bindKey:e("Left","Left|Ctrl-B"),exec:function(a,b){a.navigateLeft(b.times)},multiSelectAction:"forEach",readOnly:!0},{name:"selectwordright",bindKey:e("Ctrl-Shift-Right","Option-Shift-Right"),exec:function(a){a.getSelection().selectWordRight()},multiSelectAction:"forEach",readOnly:!0},{name:"gotowordright",bindKey:e("Ctrl-Right","Option-Right"),exec:function(a){a.navigateWordRight()},multiSelectAction:"forEach",readOnly:!0},{name:"selecttolineend",bindKey:e("Alt-Shift-Right","Command-Shift-Right"),exec:function(a){a.getSelection().selectLineEnd()},multiSelectAction:"forEach",readOnly:!0},{name:"gotolineend",bindKey:e("Alt-Right|End","Command-Right|End|Ctrl-E"),exec:function(a){a.navigateLineEnd()},multiSelectAction:"forEach",readOnly:!0},{name:"selectright",bindKey:e("Shift-Right","Shift-Right"),exec:function(a){a.getSelection().selectRight()},multiSelectAction:"forEach",readOnly:!0},{name:"gotoright",bindKey:e("Right","Right|Ctrl-F"),exec:function(a,b){a.navigateRight(b.times)},multiSelectAction:"forEach",readOnly:!0},{name:"selectpagedown",bindKey:e("Shift-PageDown","Shift-PageDown"),exec:function(a){a.selectPageDown()},readOnly:!0},{name:"pagedown",bindKey:e(null,"PageDown"),exec:function(a){a.scrollPageDown()},readOnly:!0},{name:"gotopagedown",bindKey:e("PageDown","Option-PageDown|Ctrl-V"),exec:function(a){a.gotoPageDown()},readOnly:!0},{name:"selectpageup",bindKey:e("Shift-PageUp","Shift-PageUp"),exec:function(a){a.selectPageUp()},readOnly:!0},{name:"pageup",bindKey:e(null,"PageUp"),exec:function(a){a.scrollPageUp()},readOnly:!0},{name:"gotopageup",bindKey:e("PageUp","Option-PageUp"),exec:function(a){a.gotoPageUp()},readOnly:!0},{name:"selectlinestart",bindKey:e("Shift-Home","Shift-Home"),exec:function(a){a.getSelection().selectLineStart()},multiSelectAction:"forEach",readOnly:!0},{name:"selectlineend",bindKey:e("Shift-End","Shift-End"),exec:function(a){a.getSelection().selectLineEnd()},multiSelectAction:"forEach",readOnly:!0},{name:"togglerecording",bindKey:e("Ctrl-Alt-E","Command-Option-E"),exec:function(a){a.commands.toggleRecording()},readOnly:!0},{name:"replaymacro",bindKey:e("Ctrl-Shift-E","Command-Shift-E"),exec:function(a){a.commands.replay(a)},readOnly:!0},{name:"jumptomatching",bindKey:e("Ctrl-Shift-P","Ctrl-Shift-P"),exec:function(a){a.jumpToMatching()},multiSelectAction:"forEach",readOnly:!0},{name:"cut",exec:function(a){var b=a.getSelectionRange();a._emit("cut",b),a.selection.isEmpty()||(a.session.remove(b),a.clearSelection())},multiSelectAction:"forEach"},{name:"removeline",bindKey:e("Ctrl-D","Command-D"),exec:function(a){a.removeLines()},multiSelectAction:"forEach"},{name:"togglecomment",bindKey:e("Ctrl-7","Command-7"),exec:function(a){a.toggleCommentLines()},multiSelectAction:"forEach"},{name:"replace",bindKey:e("Ctrl-R","Command-Option-F"),exec:function(a){var b=prompt("Find:",a.getCopyText());if(!b)return;var c=prompt("Replacement:");if(!c)return;a.replace(c,{needle:b})}},{name:"replaceall",bindKey:e("Ctrl-Shift-R","Command-Shift-Option-F"),exec:function(a){var b=prompt("Find:");if(!b)return;var c=prompt("Replacement:");if(!c)return;a.replaceAll(c,{needle:b})}},{name:"undo",bindKey:e("Ctrl-Z","Command-Z"),exec:function(a){a.undo()}},{name:"redo",bindKey:e("Ctrl-Shift-Z|Ctrl-Y","Command-Shift-Z|Command-Y"),exec:function(a){a.redo()}},{name:"copylinesup",bindKey:e("Ctrl-Alt-Up","Command-Option-Up"),exec:function(a){a.copyLinesUp()}},{name:"movelinesup",bindKey:e("Alt-Up","Option-Up"),exec:function(a){a.moveLinesUp()}},{name:"copylinesdown",bindKey:e("Ctrl-Alt-Down","Command-Option-Down"),exec:function(a){a.copyLinesDown()}},{name:"movelinesdown",bindKey:e("Alt-Down","Option-Down"),exec:function(a){a.moveLinesDown()}},{name:"del",bindKey:e("Delete","Delete|Ctrl-D"),exec:function(a){a.remove("right")},multiSelectAction:"forEach"},{name:"backspace",bindKey:e("Command-Backspace|Option-Backspace|Shift-Backspace|Backspace","Ctrl-Backspace|Command-Backspace|Shift-Backspace|Backspace|Ctrl-H"),exec:function(a){a.remove("left")},multiSelectAction:"forEach"},{name:"removetolinestart",bindKey:e("Alt-Backspace","Command-Backspace"),exec:function(a){a.removeToLineStart()},multiSelectAction:"forEach"},{name:"removetolineend",bindKey:e("Alt-Delete","Ctrl-K"),exec:function(a){a.removeToLineEnd()},multiSelectAction:"forEach"},{name:"removewordleft",bindKey:e("Ctrl-Backspace","Alt-Backspace|Ctrl-Alt-Backspace"),exec:function(a){a.removeWordLeft()},multiSelectAction:"forEach"},{name:"removewordright",bindKey:e("Ctrl-Delete","Alt-Delete"),exec:function(a){a.removeWordRight()},multiSelectAction:"forEach"},{name:"outdent",bindKey:e("Shift-Tab","Shift-Tab"),exec:function(a){a.blockOutdent()},multiSelectAction:"forEach"},{name:"indent",bindKey:e("Tab","Tab"),exec:function(a){a.indent()},multiSelectAction:"forEach"},{name:"insertstring",exec:function(a,b){a.insert(b)},multiSelectAction:"forEach"},{name:"inserttext",exec:function(a,b){a.insert(d.stringRepeat(b.text||"",b.times||1))},multiSelectAction:"forEach"},{name:"splitline",bindKey:e(null,"Ctrl-O"),exec:function(a){a.splitLine()},multiSelectAction:"forEach"},{name:"transposeletters",bindKey:e("Ctrl-T","Ctrl-T"),exec:function(a){a.transposeLetters()},multiSelectAction:function(a){a.transposeSelections(1)}},{name:"touppercase",bindKey:e("Ctrl-U","Ctrl-U"),exec:function(a){a.toUpperCase()},multiSelectAction:"forEach"},{name:"tolowercase",bindKey:e("Ctrl-Shift-U","Ctrl-Shift-U"),exec:function(a){a.toLowerCase()},multiSelectAction:"forEach"}]}),define("ace/edit_session",["require","exports","module","ace/config","ace/lib/oop","ace/lib/lang","ace/lib/net","ace/lib/event_emitter","ace/selection","ace/mode/text","ace/range","ace/document","ace/background_tokenizer","ace/edit_session/folding","ace/edit_session/bracket_match"],function(a,b,c){"use strict";var d=a("./config"),e=a("./lib/oop"),f=a("./lib/lang"),g=a("./lib/net"),h=a("./lib/event_emitter").EventEmitter,i=a("./selection").Selection,j=a("./mode/text").Mode,k=a("./range").Range,l=a("./document").Document,m=a("./background_tokenizer").BackgroundTokenizer,n=function(a,b){this.$modified=!0,this.$breakpoints=[],this.$frontMarkers={},this.$backMarkers={},this.$markerId=1,this.$rowCache=[],this.$wrapData=[],this.$foldData=[],this.$undoSelect=!0,this.$foldData.toString=function(){var a="";return this.forEach(function(b){a+="\n"+b.toString()}),a},a instanceof l?this.setDocument(a):this.setDocument(new l(a)),this.selection=new i(this),b?this.setMode(b):this.setMode(new j)};(function(){function q(a){return a<4352?!1:a>=4352&&a<=4447||a>=4515&&a<=4519||a>=4602&&a<=4607||a>=9001&&a<=9002||a>=11904&&a<=11929||a>=11931&&a<=12019||a>=12032&&a<=12245||a>=12272&&a<=12283||a>=12288&&a<=12350||a>=12353&&a<=12438||a>=12441&&a<=12543||a>=12549&&a<=12589||a>=12593&&a<=12686||a>=12688&&a<=12730||a>=12736&&a<=12771||a>=12784&&a<=12830||a>=12832&&a<=12871||a>=12880&&a<=13054||a>=13056&&a<=19903||a>=19968&&a<=42124||a>=42128&&a<=42182||a>=43360&&a<=43388||a>=44032&&a<=55203||a>=55216&&a<=55238||a>=55243&&a<=55291||a>=63744&&a<=64255||a>=65040&&a<=65049||a>=65072&&a<=65106||a>=65108&&a<=65126||a>=65128&&a<=65131||a>=65281&&a<=65376||a>=65504&&a<=65510}e.implement(this,h),this.setDocument=function(a){if(this.doc)throw new Error("Document is already set");this.doc=a,a.on("change",this.onChange.bind(this)),this.on("changeFold",this.onChangeFold.bind(this)),this.bgTokenizer&&(this.bgTokenizer.setDocument(this.getDocument()),this.bgTokenizer.start(0))},this.getDocument=function(){return this.doc},this.$resetRowCache=function(a){if(a==0){this.$rowCache=[];return}var b=this.$rowCache;for(var c=0;c<b.length;c++)if(b[c].docRow>=a){b.splice(c,b.length);return}},this.onChangeFold=function(a){var b=a.data;this.$resetRowCache(b.start.row)},this.onChange=function(a){var b=a.data;this.$modified=!0,this.$resetRowCache(b.range.start.row);var c=this.$updateInternalDataOnChange(a);!this.$fromUndo&&this.$undoManager&&!b.ignore&&(this.$deltasDoc.push(b),c&&c.length!=0&&this.$deltasFold.push({action:"removeFolds",folds:c}),this.$informUndoManager.schedule()),this.bgTokenizer.start(b.range.start.row),this._emit("change",a)},this.setValue=function(a){this.doc.setValue(a),this.selection.moveCursorTo(0,0),this.selection.clearSelection(),this.$resetRowCache(0),this.$deltas=[],this.$deltasDoc=[],this.$deltasFold=[],this.getUndoManager().reset()},this.getValue=this.toString=function(){return this.doc.getValue()},this.getSelection=function(){return this.selection},this.getState=function(a){return this.bgTokenizer.getState(a)},this.getTokens=function(a,b){return this.bgTokenizer.getTokens(a,b)},this.getTokenAt=function(a,b){var c=this.bgTokenizer.getTokens(a,a)[0].tokens,d,e=0;if(b==null)f=c.length-1,e=this.getLine(a).length;else for(var f=0;f<c.length;f++){e+=c[f].value.length;if(e>=b)break}return d=c[f],d?(d.index=f,d.start=e-d.value.length,d):null},this.setUndoManager=function(a){this.$undoManager=a,this.$resetRowCache(0),this.$deltas=[],this.$deltasDoc=[],this.$deltasFold=[],this.$informUndoManager&&this.$informUndoManager.cancel();if(a){var b=this;this.$syncInformUndoManager=function(){b.$informUndoManager.cancel(),b.$deltasFold.length&&(b.$deltas.push({group:"fold",deltas:b.$deltasFold}),b.$deltasFold=[]),b.$deltasDoc.length&&(b.$deltas.push({group:"doc",deltas:b.$deltasDoc}),b.$deltasDoc=[]),b.$deltas.length>0&&a.execute({action:"aceupdate",args:[b.$deltas,b]}),b.$deltas=[]},this.$informUndoManager=f.deferredCall(this.$syncInformUndoManager)}},this.$defaultUndoManager={undo:function(){},redo:function(){},reset:function(){}},this.getUndoManager=function(){return this.$undoManager||this.$defaultUndoManager},this.getTabString=function(){return this.getUseSoftTabs()?f.stringRepeat(" ",this.getTabSize()):"	"},this.$useSoftTabs=!0,this.setUseSoftTabs=function(a){if(this.$useSoftTabs===a)return;this.$useSoftTabs=a},this.getUseSoftTabs=function(){return this.$useSoftTabs},this.$tabSize=4,this.setTabSize=function(a){if(isNaN(a)||this.$tabSize===a)return;this.$modified=!0,this.$tabSize=a,this._emit("changeTabSize")},this.getTabSize=function(){return this.$tabSize},this.isTabStop=function(a){return this.$useSoftTabs&&a.column%this.$tabSize==0},this.$overwrite=!1,this.setOverwrite=function(a){if(this.$overwrite==a)return;this.$overwrite=a,this._emit("changeOverwrite")},this.getOverwrite=function(){return this.$overwrite},this.toggleOverwrite=function(){this.setOverwrite(!this.$overwrite)},this.getBreakpoints=function(){return this.$breakpoints},this.setBreakpoints=function(a){this.$breakpoints=[];for(var b=0;b<a.length;b++)this.$breakpoints[a[b]]=!0;this._emit("changeBreakpoint",{})},this.clearBreakpoints=function(){this.$breakpoints=[],this._emit("changeBreakpoint",{})},this.setBreakpoint=function(a){this.$breakpoints[a]=!0,this._emit("changeBreakpoint",{})},this.clearBreakpoint=function(a){delete this.$breakpoints[a],this._emit("changeBreakpoint",{})},this.getBreakpoints=function(){return this.$breakpoints},this.addMarker=function(a,b,c,d){var e=this.$markerId++,f={range:a,type:c||"line",renderer:typeof c=="function"?c:null,clazz:b,inFront:!!d};return d?(this.$frontMarkers[e]=f,this._emit("changeFrontMarker")):(this.$backMarkers[e]=f,this._emit("changeBackMarker")),e},this.removeMarker=function(a){var b=this.$frontMarkers[a]||this.$backMarkers[a];if(!b)return;var c=b.inFront?this.$frontMarkers:this.$backMarkers;b&&(delete c[a],this._emit(b.inFront?"changeFrontMarker":"changeBackMarker"))},this.getMarkers=function(a){return a?this.$frontMarkers:this.$backMarkers},this.setAnnotations=function(a){this.$annotations={};for(var b=0;b<a.length;b++){var c=a[b],d=c.row;this.$annotations[d]?this.$annotations[d].push(c):this.$annotations[d]=[c]}this._emit("changeAnnotation",{})},this.getAnnotations=function(){return this.$annotations||{}},this.clearAnnotations=function(){this.$annotations={},this._emit("changeAnnotation",{})},this.$detectNewLine=function(a){var b=a.match(/^.*?(\r?\n)/m);b?this.$autoNewLine=b[1]:this.$autoNewLine="\n"},this.getWordRange=function(a,b){var c=this.getLine(a),d=!1;b>0&&(d=!!c.charAt(b-1).match(this.tokenRe)),d||(d=!!c.charAt(b).match(this.tokenRe));var e=d?this.tokenRe:this.nonTokenRe,f=b;if(f>0){do f--;while(f>=0&&c.charAt(f).match(e));f++}var g=b;while(g<c.length&&c.charAt(g).match(e))g++;return new k(a,f,a,g)},this.getAWordRange=function(a,b){var c=this.getWordRange(a,b),d=this.getLine(c.end.row);while(d.charAt(c.end.column).match(/[ \t]/))c.end.column+=1;return c},this.setNewLineMode=function(a){this.doc.setNewLineMode(a)},this.getNewLineMode=function(){return this.doc.getNewLineMode()},this.$useWorker=!0,this.setUseWorker=function(a){if(this.$useWorker==a)return;this.$useWorker=a,this.$stopWorker(),a&&this.$startWorker()},this.getUseWorker=function(){return this.$useWorker},this.onReloadTokenizer=function(a){var b=a.data;this.bgTokenizer.start(b.first),this._emit("tokenizerUpdate",a)},this.$modes={},this._loadMode=function(b,c){function i(a){if(e.$modes[b])return c(e.$modes[b]);e.$modes[b]=new a.Mode,e._emit("loadmode",{name:b,mode:e.$modes[b]}),c(e.$modes[b])}function j(a){if(!d.get("packaged"))return a();var c=b.split("/").pop(),e=d.get("modePath")+"/mode-"+c+d.get("suffix");g.loadScript(e,a)}if(this.$modes[b])return c(this.$modes[b]);var e=this,f;try{f=a(b)}catch(h){}if(f)return i(f);j(function(){a([b],i)})},this.$mode=null,this.$origMode=null,this.setMode=function(a){this.$origMode=a;if(typeof a=="string"){var b=this;this._loadMode(a,function(c){if(b.$origMode!==a)return;b.setMode(c)});return}if(this.$mode===a)return;this.$mode=a,this.$stopWorker(),this.$useWorker&&this.$startWorker();var c=a.getTokenizer();if(c.addEventListener!==undefined){var d=this.onReloadTokenizer.bind(this);c.addEventListener("update",d)}if(!this.bgTokenizer){this.bgTokenizer=new m(c);var b=this;this.bgTokenizer.addEventListener("update",function(a){b._emit("tokenizerUpdate",a)})}else this.bgTokenizer.setTokenizer(c);this.bgTokenizer.setDocument(this.getDocument()),this.bgTokenizer.start(0),this.tokenRe=a.tokenRe,this.nonTokenRe=a.nonTokenRe,this.$setFolding(a.foldingRules),this._emit("changeMode")},this.$stopWorker=function(){this.$worker&&this.$worker.terminate(),this.$worker=null},this.$startWorker=function(){if(typeof Worker!="undefined"&&!a.noWorker)try{this.$worker=this.$mode.createWorker(this)}catch(b){console.log("Could not load worker"),console.log(b),this.$worker=null}else this.$worker=null},this.getMode=function(){return this.$mode},this.$scrollTop=0,this.setScrollTop=function(a){a=Math.round(Math.max(0,a));if(this.$scrollTop===a)return;this.$scrollTop=a,this._emit("changeScrollTop",a)},this.getScrollTop=function(){return this.$scrollTop},this.$scrollLeft=0,this.setScrollLeft=function(a){a=Math.round(Math.max(0,a));if(this.$scrollLeft===a)return;this.$scrollLeft=a,this._emit("changeScrollLeft",a)},this.getScrollLeft=function(){return this.$scrollLeft},this.getWidth=function(){return this.$computeWidth(),this.width},this.getScreenWidth=function(){return this.$computeWidth(),this.screenWidth},this.$computeWidth=function(a){if(this.$modified||a){this.$modified=!1;var b=this.doc.getAllLines(),c=0,d=0;for(var e=0;e<b.length;e++){var f=this.getFoldLine(e),g,h;g=b[e];if(f){var i=f.range.end;g=this.getFoldDisplayLine(f),e=i.row}h=g.length,c=Math.max(c,h),this.$useWrapMode||(d=Math.max(d,this.$getStringScreenWidth(g)[0]))}this.width=c,this.$useWrapMode?this.screenWidth=this.$wrapLimit:this.screenWidth=d}},this.getLine=function(a){return this.doc.getLine(a)},this.getLines=function(a,b){return this.doc.getLines(a,b)},this.getLength=function(){return this.doc.getLength()},this.getTextRange=function(a){return this.doc.getTextRange(a)},this.insert=function(a,b){return this.doc.insert(a,b)},this.remove=function(a){return this.doc.remove(a)},this.undoChanges=function(a,b){if(!a.length)return;this.$fromUndo=!0;var c=null;for(var d=a.length-1;d!=-1;d--){var e=a[d];e.group=="doc"?(this.doc.revertDeltas(e.deltas),c=this.$getUndoSelection(e.deltas,!0,c)):e.deltas.forEach(function(a){this.addFolds(a.folds)},this)}return this.$fromUndo=!1,c&&this.$undoSelect&&!b&&this.selection.setSelectionRange(c),c},this.redoChanges=function(a,b){if(!a.length)return;this.$fromUndo=!0;var c=null;for(var d=0;d<a.length;d++){var e=a[d];e.group=="doc"&&(this.doc.applyDeltas(e.deltas),c=this.$getUndoSelection(e.deltas,!1,c))}return this.$fromUndo=!1,c&&this.$undoSelect&&!b&&this.selection.setSelectionRange(c),c},this.setUndoSelect=function(a){this.$undoSelect=a},this.$getUndoSelection=function(a,b,c){function d(a){var c=a.action=="insertText"||a.action=="insertLines";return b?!c:c}var e=a[0],f,g,h=!1;d(e)?(f=e.range.clone(),h=!0):(f=k.fromPoints(e.range.start,e.range.start),h=!1);for(var i=1;i<a.length;i++)e=a[i],d(e)?(g=e.range.start,f.compare(g.row,g.column)==-1&&f.setStart(e.range.start),g=e.range.end,f.compare(g.row,g.column)==1&&f.setEnd(e.range.end),h=!0):(g=e.range.start,f.compare(g.row,g.column)==-1&&(f=k.fromPoints(e.range.start,e.range.start)),h=!1);if(c!=null){var j=c.compareRange(f);j==1?f.setStart(c.start):j==-1&&f.setEnd(c.end)}return f},this.replace=function(a,b){return this.doc.replace(a,b)},this.moveText=function(a,b){var c=this.getTextRange(a);this.remove(a);var d=b.row,e=b.column;!a.isMultiLine()&&a.start.row==d&&a.end.column<e&&(e-=c.length);if(a.isMultiLine()&&a.end.row<d){var f=this.doc.$split(c);d-=f.length-1}var g=d+a.end.row-a.start.row,h=a.isMultiLine()?a.end.column:e+a.end.column-a.start.column,i=new k(d,e,g,h);return this.insert(i.start,c),i},this.indentRows=function(a,b,c){c=c.replace(/\t/g,this.getTabString());for(var d=a;d<=b;d++)this.insert({row:d,column:0},c)},this.outdentRows=function(a){var b=a.collapseRows(),c=new k(0,0,0,0),d=this.getTabSize();for(var e=b.start.row;e<=b.end.row;++e){var f=this.getLine(e);c.start.row=e,c.end.row=e;for(var g=0;g<d;++g)if(f.charAt(g)!=" ")break;g<d&&f.charAt(g)=="	"?(c.start.column=g,c.end.column=g+1):(c.start.column=0,c.end.column=g),this.remove(c)}},this.moveLinesUp=function(a,b){if(a<=0)return 0;var c=this.doc.removeLines(a,b);return this.doc.insertLines(a-1,c),-1},this.moveLinesDown=function(a,b){if(b>=this.doc.getLength()-1)return 0;var c=this.doc.removeLines(a,b);return this.doc.insertLines(a+1,c),1},this.duplicateLines=function(a,b){var a=this.$clipRowToDocument(a),b=this.$clipRowToDocument(b),c=this.getLines(a,b);this.doc.insertLines(a,c);var d=b-a+1;return d},this.$clipRowToDocument=function(a){return Math.max(0,Math.min(a,this.doc.getLength()-1))},this.$clipColumnToRow=function(a,b){return b<0?0:Math.min(this.doc.getLine(a).length,b)},this.$clipPositionToDocument=function(a,b){b=Math.max(0,b);if(a<0)a=0,b=0;else{var c=this.doc.getLength();a>=c?(a=c-1,b=this.doc.getLine(c-1).length):b=Math.min(this.doc.getLine(a).length,b)}return{row:a,column:b}},this.$clipRangeToDocument=function(a){a.start.row<0?(a.start.row=0,a.start.column=0):a.start.column=this.$clipColumnToRow(a.start.row,a.start.column);var b=this.doc.getLength()-1;return a.end.row>b?(a.end.row=b,a.end.column=this.doc.getLine(b).length):a.end.column=this.$clipColumnToRow(a.end.row,a.end.column),a},this.$wrapLimit=80,this.$useWrapMode=!1,this.$wrapLimitRange={min:null,max:null},this.setUseWrapMode=function(a){if(a!=this.$useWrapMode){this.$useWrapMode=a,this.$modified=!0,this.$resetRowCache(0);if(a){var b=this.getLength();this.$wrapData=[];for(var c=0;c<b;c++)this.$wrapData.push([]);this.$updateWrapData(0,b-1)}this._emit("changeWrapMode")}},this.getUseWrapMode=function(){return this.$useWrapMode},this.setWrapLimitRange=function(a,b){if(this.$wrapLimitRange.min!==a||this.$wrapLimitRange.max!==b)this.$wrapLimitRange.min=a,this.$wrapLimitRange.max=b,this.$modified=!0,this._emit("changeWrapMode")},this.adjustWrapLimit=function(a){var b=this.$constrainWrapLimit(a);return b!=this.$wrapLimit&&b>0?(this.$wrapLimit=b,this.$modified=!0,this.$useWrapMode&&(this.$updateWrapData(0,this.getLength()-1),this.$resetRowCache(0),this._emit("changeWrapLimit")),!0):!1},this.$constrainWrapLimit=function(a){var b=this.$wrapLimitRange.min;b&&(a=Math.max(b,a));var c=this.$wrapLimitRange.max;return c&&(a=Math.min(c,a)),Math.max(1,a)},this.getWrapLimit=function(){return this.$wrapLimit},this.getWrapLimitRange=function(){return{min:this.$wrapLimitRange.min,max:this.$wrapLimitRange.max}},this.$updateInternalDataOnChange=function(a){var b=this.$useWrapMode,c,d=a.data.action,e=a.data.range.start.row,f=a.data.range.end.row,g=a.data.range.start,h=a.data.range.end,i=null;d.indexOf("Lines")!=-1?(d=="insertLines"?f=e+a.data.lines.length:f=e,c=a.data.lines?a.data.lines.length:f-e):c=f-e;if(c!=0)if(d.indexOf("remove")!=-1){b&&this.$wrapData.splice(e,c);var j=this.$foldData;i=this.getFoldsInRange(a.data.range),this.removeFolds(i);var k=this.getFoldLine(h.row),l=0;if(k){k.addRemoveChars(h.row,h.column,g.column-h.column),k.shiftRow(-c);var m=this.getFoldLine(e);m&&m!==k&&(m.merge(k),k=m),l=j.indexOf(k)+1}for(l;l<j.length;l++){var k=j[l];k.start.row>=h.row&&k.shiftRow(-c)}f=e}else{var n;if(b){n=[e,0];for(var o=0;o<c;o++)n.push([]);this.$wrapData.splice.apply(this.$wrapData,n)}var j=this.$foldData,k=this.getFoldLine(e),l=0;if(k){var p=k.range.compareInside(g.row,g.column);p==0?(k=k.split(g.row,g.column),k.shiftRow(c),k.addRemoveChars(f,0,h.column-g.column)):p==-1&&(k.addRemoveChars(e,0,h.column-g.column),k.shiftRow(c)),l=j.indexOf(k)+1}for(l;l<j.length;l++){var k=j[l];k.start.row>=e&&k.shiftRow(c)}}else{c=Math.abs(a.data.range.start.column-a.data.range.end.column),d.indexOf("remove")!=-1&&(i=this.getFoldsInRange(a.data.range),this.removeFolds(i),c=-c);var k=this.getFoldLine(e);k&&k.addRemoveChars(e,g.column,c)}return b&&this.$wrapData.length!=this.doc.getLength()&&console.error("doc.getLength() and $wrapData.length have to be the same!"),b&&this.$updateWrapData(e,f),i},this.$updateWrapData=function(a,b){var c=this.doc.getAllLines(),d=this.getTabSize(),e=this.$wrapData,g=this.$wrapLimit,h,k,l=a;b=Math.min(b,c.length-1);while(l<=b){k=this.getFoldLine(l,k);if(!k)h=this.$getDisplayTokens(f.stringTrimRight(c[l])),e[l]=this.$computeWrapSplits(h,g,d),l++;else{h=[],k.walk(function(a,b,d,e){var f;if(a){f=this.$getDisplayTokens(a,h.length),f[0]=i;for(var g=1;g<f.length;g++)f[g]=j}else f=this.$getDisplayTokens(c[b].substring(e,d),h.length);h=h.concat(f)}.bind(this),k.end.row,c[k.end.row].length+1);while(h.length!=0&&h[h.length-1]>=n)h.pop();e[k.start.row]=this.$computeWrapSplits(h,g,d),l=k.end.row+1}}};var b=1,c=2,i=3,j=4,l=9,n=10,o=11,p=12;this.$computeWrapSplits=function(a,b){function g(b){var d=a.slice(e,b),g=d.length;d.join("").replace(/12/g,function(){g-=1}).replace(/2/g,function(){g-=1}),f+=g,c.push(f),e=b}if(a.length==0)return[];var c=[],d=a.length,e=0,f=0;while(d-e>b){var h=e+b;if(a[h]>=n){while(a[h]>=n)h++;g(h);continue}if(a[h]==i||a[h]==j){for(h;h!=e-1;h--)if(a[h]==i)break;if(h>e){g(h);continue}h=e+b;for(h;h<a.length;h++)if(a[h]!=j)break;if(h==a.length)break;g(h);continue}var k=Math.max(h-10,e-1);while(h>k&&a[h]<i)h--;while(h>k&&a[h]==l)h--;if(h>k){g(++h);continue}h=e+b,g(h)}return c},this.$getDisplayTokens=function(a,d){var e=[],f;d=d||0;for(var g=0;g<a.length;g++){var h=a.charCodeAt(g);if(h==9){f=this.getScreenTabSize(e.length+d),e.push(o);for(var i=1;i<f;i++)e.push(p)}else h==32?e.push(n):h>39&&h<48||h>57&&h<64?e.push(l):h>=4352&&q(h)?e.push(b,c):e.push(b)}return e},this.$getStringScreenWidth=function(a,b,c){if(b==0)return[0,0];b==null&&(b=c+a.length*Math.max(this.getTabSize(),2)),c=c||0;var d,e;for(e=0;e<a.length;e++){d=a.charCodeAt(e),d==9?c+=this.getScreenTabSize(c):d>=4352&&q(d)?c+=2:c+=1;if(c>b)break}return[c,e]},this.getRowLength=function(a){return!this.$useWrapMode||!this.$wrapData[a]?1:this.$wrapData[a].length+1},this.getRowHeight=function(a,b){return this.getRowLength(b)*a.lineHeight},this.getScreenLastRowColumn=function(a){var b=this.screenToDocumentPosition(a,Number.MAX_VALUE);return this.documentToScreenColumn(b.row,b.column)},this.getDocumentLastRowColumn=function(a,b){var c=this.documentToScreenRow(a,b);return this.getScreenLastRowColumn(c)},this.getDocumentLastRowColumnPosition=function(a,b){var c=this.documentToScreenRow(a,b);return this.screenToDocumentPosition(c,Number.MAX_VALUE/10)},this.getRowSplitData=function(a){return this.$useWrapMode?this.$wrapData[a]:undefined},this.getScreenTabSize=function(a){return this.$tabSize-a%this.$tabSize},this.screenToDocumentRow=function(a,b){return this.screenToDocumentPosition(a,b).row},this.screenToDocumentColumn=function(a,b){return this.screenToDocumentPosition(a,b).column},this.screenToDocumentPosition=function(a,b){if(a<0)return{row:0,column:0};var c,d=0,e=0,f,g=0,h=0,i=this.$rowCache;for(var j=0;j<i.length;j++){if(!(i[j].screenRow<a))break;g=i[j].screenRow,d=i[j].docRow}var k=!i.length||j==i.length,l=this.getLength()-1,m=this.getNextFoldLine(d),n=m?m.start.row:Infinity;while(g<=a){h=this.getRowLength(d);if(g+h-1>=a||d>=l)break;g+=h,d++,d>n&&(d=m.end.row+1,m=this.getNextFoldLine(d,m),n=m?m.start.row:Infinity),k&&i.push({docRow:d,screenRow:g})}if(m&&m.start.row<=d)c=this.getFoldDisplayLine(m),d=m.start.row;else{if(g+h<=a||d>l)return{row:l,column:this.getLine(l).length};c=this.getLine(d),m=null}if(this.$useWrapMode){var o=this.$wrapData[d];o&&(f=o[a-g],a>g&&o.length&&(e=o[a-g-1]||o[o.length-1],c=c.substring(e)))}return e+=this.$getStringScreenWidth(c,b)[1],this.$useWrapMode&&e>=f&&(e=f-1),m?m.idxToPosition(e):{row:d,column:e}},this.documentToScreenPosition=function(a,b){if(typeof b=="undefined")var c=this.$clipPositionToDocument(a.row,a.column);else c=this.$clipPositionToDocument(a,b);a=c.row,b=c.column;var d;if(this.$useWrapMode){d=this.$wrapData;if(a>d.length-1)return{row:this.getScreenLength(),column:d.length==0?0:d[d.length-1].length-1}}var e=0,f=null,g=null;g=this.getFoldAt(a,b,1),g&&(a=g.start.row,b=g.start.column);var h,i=0,j=this.$rowCache;for(var k=0;k<j.length;k++){if(!(j[k].docRow<a))break;e=j[k].screenRow,i=j[k].docRow}var l=!j.length||k==j.length,m=this.getNextFoldLine(i),n=m?m.start.row:Infinity;while(i<a){if(i>=n){h=m.end.row+1;if(h>a)break;m=this.getNextFoldLine(h,m),n=m?m.start.row:Infinity}else h=i+1;e+=this.getRowLength(i),i=h,l&&j.push({docRow:i,screenRow:e})}var o="";m&&i>=n?(o=this.getFoldDisplayLine(m,a,b),f=m.start.row):(o=this.getLine(a).substring(0,b),f=a);if(this.$useWrapMode){var p=d[f],q=0;while(o.length>=p[q])e++,q++;o=o.substring(p[q-1]||0,o.length)}return{row:e,column:this.$getStringScreenWidth(o)[0]}},this.documentToScreenColumn=function(a,b){return this.documentToScreenPosition(a,b).column},this.documentToScreenRow=function(a,b){return this.documentToScreenPosition(a,b).row},this.getScreenLength=function(){var a=0,b=null;if(!this.$useWrapMode){a=this.getLength();var c=this.$foldData;for(var d=0;d<c.length;d++)b=c[d],a-=b.end.row-b.start.row}else{var e=this.$wrapData.length,f=0,d=0,b=this.$foldData[d++],g=b?b.start.row:Infinity;while(f<e)a+=this.$wrapData[f].length+1,f++,f>g&&(f=b.end.row+1,b=this.$foldData[d++],g=b?b.start.row:Infinity)}return a}}).call(n.prototype),a("./edit_session/folding").Folding.call(n.prototype),a("./edit_session/bracket_match").BracketMatch.call(n.prototype),b.EditSession=n}),define("ace/config",["require","exports","module","ace/lib/lang"],function(a,b,c){function g(a){return a.replace(/-(.)/g,function(a,b){return b.toUpperCase()})}"no use strict";var d=a("./lib/lang"),e=function(){return this}(),f={packaged:!1,workerPath:"",modePath:"",themePath:"",suffix:".js"};b.get=function(a){if(!f.hasOwnProperty(a))throw new Error("Unknown confik key: "+a);return f[a]},b.set=function(a,b){if(!f.hasOwnProperty(a))throw new Error("Unknown confik key: "+a);f[a]=b},b.all=function(){return d.copyObject(f)},b.init=function(){f.packaged=a.packaged||c.packaged||e.define&&define.packaged;if(!e.document)return"";var d={},h="",i,j=document.getElementsByTagName("script");for(var k=0;k<j.length;k++){var l=j[k],m=l.src||l.getAttribute("src");if(!m)continue;var n=l.attributes;for(var o=0,p=n.length;o<p;o++){var q=n[o];q.name.indexOf("data-ace-")===0&&(d[g(q.name.replace(/^data-ace-/,""))]=q.value)}var r=m.match(/^(?:(.*\/)ace\.js|(.*\/)ace((-uncompressed)?(-noconflict)?\.js))(?:\?|$)/);r&&(h=r[1]||r[2],i=r[3])}h&&(d.base=d.base||h,d.packaged=!0),d.suffix=d.suffix||i,d.workerPath=d.workerPath||d.base,d.modePath=d.modePath||d.base,d.themePath=d.themePath||d.base,delete d.base;for(var s in d)typeof d[s]!="undefined"&&b.set(s,d[s])}}),define("ace/lib/net",["require","exports","module"],function(a,b,c){"use strict",b.get=function(a,c){var d=b.createXhr();d.open("GET",a,!0),d.onreadystatechange=function(a){d.readyState===4&&c(d.responseText)},d.send(null)};var d=["Msxml2.XMLHTTP","Microsoft.XMLHTTP","Msxml2.XMLHTTP.4.0"];b.createXhr=function(){var a,b,c;if(typeof XMLHttpRequest!="undefined")return new XMLHttpRequest;for(b=0;b<3;b++){c=d[b];try{a=new ActiveXObject(c)}catch(e){}if(a){d=[c];break}}if(!a)throw new Error("createXhr(): XMLHttpRequest not available");return a},b.loadScript=function(a,b){var c=document.getElementsByTagName("head")[0],d=document.createElement("script");d.src=a,c.appendChild(d),d.onload=b}}),define("ace/selection",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/lib/event_emitter","ace/range"],function(a,b,c){"use strict";var d=a("./lib/oop"),e=a("./lib/lang"),f=a("./lib/event_emitter").EventEmitter,g=a("./range").Range,h=function(a){this.session=a,this.doc=a.getDocument(),this.clearSelection(),this.selectionLead=this.doc.createAnchor(0,0),this.selectionAnchor=this.doc.createAnchor(0,0);var b=this;this.selectionLead.on("change",function(a){b._emit("changeCursor"),b.$isEmpty||b._emit("changeSelection"),!b.$keepDesiredColumnOnChange&&a.old.column!=a.value.column&&(b.$desiredColumn=null)}),this.selectionAnchor.on("change",function(){b.$isEmpty||b._emit("changeSelection")})};(function(){d.implement(this,f),this.isEmpty=function(){return this.$isEmpty||this.selectionAnchor.row==this.selectionLead.row&&this.selectionAnchor.column==this.selectionLead.column},this.isMultiLine=function(){return this.isEmpty()?!1:this.getRange().isMultiLine()},this.getCursor=function(){return this.selectionLead.getPosition()},this.setSelectionAnchor=function(a,b){this.selectionAnchor.setPosition(a,b),this.$isEmpty&&(this.$isEmpty=!1,this._emit("changeSelection"))},this.getSelectionAnchor=function(){return this.$isEmpty?this.getSelectionLead():this.selectionAnchor.getPosition()},this.getSelectionLead=function(){return this.selectionLead.getPosition()},this.shiftSelection=function(a){if(this.$isEmpty){this.moveCursorTo(this.selectionLead.row,this.selectionLead.column+a);return}var b=this.getSelectionAnchor(),c=this.getSelectionLead(),d=this.isBackwards();(!d||b.column!==0)&&this.setSelectionAnchor(b.row,b.column+a),(d||c.column!==0)&&this.$moveSelection(function(){this.moveCursorTo(c.row,c.column+a)})},this.isBackwards=function(){var a=this.selectionAnchor,b=this.selectionLead;return a.row>b.row||a.row==b.row&&a.column>b.column},this.getRange=function(){var a=this.selectionAnchor,b=this.selectionLead;return this.isEmpty()?g.fromPoints(b,b):this.isBackwards()?g.fromPoints(b,a):g.fromPoints(a,b)},this.clearSelection=function(){this.$isEmpty||(this.$isEmpty=!0,this._emit("changeSelection"))},this.selectAll=function(){var a=this.doc.getLength()-1;this.setSelectionAnchor(a,this.doc.getLine(a).length),this.moveCursorTo(0,0)},this.setSelectionRange=function(a,b){b?(this.setSelectionAnchor(a.end.row,a.end.column),this.selectTo(a.start.row,a.start.column)):(this.setSelectionAnchor(a.start.row,a.start.column),this.selectTo(a.end.row,a.end.column)),this.$desiredColumn=null},this.$moveSelection=function(a){var b=this.selectionLead;this.$isEmpty&&this.setSelectionAnchor(b.row,b.column),a.call(this)},this.selectTo=function(a,b){this.$moveSelection(function(){this.moveCursorTo(a,b)})},this.selectToPosition=function(a){this.$moveSelection(function(){this.moveCursorToPosition(a)})},this.selectUp=function(){this.$moveSelection(this.moveCursorUp)},this.selectDown=function(){this.$moveSelection(this.moveCursorDown)},this.selectRight=function(){this.$moveSelection(this.moveCursorRight)},this.selectLeft=function(){this.$moveSelection(this.moveCursorLeft)},this.selectLineStart=function(){this.$moveSelection(this.moveCursorLineStart)},this.selectLineEnd=function(){this.$moveSelection(this.moveCursorLineEnd)},this.selectFileEnd=function(){this.$moveSelection(this.moveCursorFileEnd)},this.selectFileStart=function(){this.$moveSelection(this.moveCursorFileStart)},this.selectWordRight=function(){this.$moveSelection(this.moveCursorWordRight)},this.selectWordLeft=function(){this.$moveSelection(this.moveCursorWordLeft)},this.selectWord=function(){var a=this.getCursor(),b=this.session.getWordRange(a.row,a.column);this.setSelectionRange(b)},this.selectAWord=function(){var a=this.getCursor(),b=this.session.getAWordRange(a.row,a.column);this.setSelectionRange(b)},this.selectLine=function(){var a=this.selectionLead.row,b,c=this.session.getFoldLine(a);c?(a=c.start.row,b=c.end.row):b=a,this.setSelectionAnchor(a,0),this.$moveSelection(function(){this.moveCursorTo(b+1,0)})},this.moveCursorUp=function(){this.moveCursorBy(-1,0)},this.moveCursorDown=function(){this.moveCursorBy(1,0)},this.moveCursorLeft=function(){var a=this.selectionLead.getPosition(),b;if(b=this.session.getFoldAt(a.row,a.column,-1))this.moveCursorTo(b.start.row,b.start.column);else if(a.column==0)a.row>0&&this.moveCursorTo(a.row-1,this.doc.getLine(a.row-1).length);else{var c=this.session.getTabSize();this.session.isTabStop(a)&&this.doc.getLine(a.row).slice(a.column-c,a.column).split(" ").length-1==c?this.moveCursorBy(0,-c):this.moveCursorBy(0,-1)}},this.moveCursorRight=function(){var a=this.selectionLead.getPosition(),b;if(b=this.session.getFoldAt(a.row,a.column,1))this.moveCursorTo(b.end.row,b.end.column);else if(this.selectionLead.column==this.doc.getLine(this.selectionLead.row).length)this.selectionLead.row<this.doc.getLength()-1&&this.moveCursorTo(this.selectionLead.row+1,0);else{var c=this.session.getTabSize(),a=this.selectionLead;this.session.isTabStop(a)&&this.doc.getLine(a.row).slice(a.column,a.column+c).split(" ").length-1==c?this.moveCursorBy(0,c):this.moveCursorBy(0,1)}},this.moveCursorLineStart=function(){var a=this.selectionLead.row,b=this.selectionLead.column,c=this.session.documentToScreenRow(a,b),d=this.session.screenToDocumentPosition(c,0),e=this.session.getDisplayLine(a,null,d.row,d.column),f=e.match(/^\s*/);f[0].length==b?this.moveCursorTo(d.row,d.column):this.moveCursorTo(d.row,d.column+f[0].length)},this.moveCursorLineEnd=function(){var a=this.selectionLead,b=this.session.getDocumentLastRowColumnPosition(a.row,a.column);this.moveCursorTo(b.row,b.column)},this.moveCursorFileEnd=function(){var a=this.doc.getLength()-1,b=this.doc.getLine(a).length;this.moveCursorTo(a,b)},this.moveCursorFileStart=function(){this.moveCursorTo(0,0)},this.moveCursorWordRight=function(){var a=this.selectionLead.row,b=this.selectionLead.column,c=this.doc.getLine(a),d=c.substring(b),e;this.session.nonTokenRe.lastIndex=0,this.session.tokenRe.lastIndex=0;var f=this.session.getFoldAt(a,b,1);if(f){this.moveCursorTo(f.end.row,f.end.column);return}if(e=this.session.nonTokenRe.exec(d))b+=this.session.nonTokenRe.lastIndex,this.session.nonTokenRe.lastIndex=0,d=c.substring(b);if(b>=c.length){this.moveCursorTo(a,c.length),this.moveCursorRight(),a<this.doc.getLength()-1&&this.moveCursorWordRight();return}if(e=this.session.tokenRe.exec(d))b+=this.session.tokenRe.lastIndex,this.session.tokenRe.lastIndex=0;this.moveCursorTo(a,b)},this.moveCursorWordLeft=function(){var a=this.selectionLead.row,b=this.selectionLead.column,c;if(c=this.session.getFoldAt(a,b,-1)){this.moveCursorTo(c.start.row,c.start.column);return}var d=this.session.getFoldStringAt(a,b,-1);d==null&&(d=this.doc.getLine(a).substring(0,b));var f=e.stringReverse(d),g;this.session.nonTokenRe.lastIndex=0,this.session.tokenRe.lastIndex=0;if(g=this.session.nonTokenRe.exec(f))b-=this.session.nonTokenRe.lastIndex,f=f.slice(this.session.nonTokenRe.lastIndex),this.session.nonTokenRe.lastIndex=0;if(b<=0){this.moveCursorTo(a,0),this.moveCursorLeft(),a>0&&this.moveCursorWordLeft();return}if(g=this.session.tokenRe.exec(f))b-=this.session.tokenRe.lastIndex,this.session.tokenRe.lastIndex=0;this.moveCursorTo(a,b)},this.moveCursorBy=function(a,b){var c=this.session.documentToScreenPosition(this.selectionLead.row,this.selectionLead.column);b===0&&(this.$desiredColumn?c.column=this.$desiredColumn:this.$desiredColumn=c.column);var d=this.session.screenToDocumentPosition(c.row+a,c.column);this.moveCursorTo(d.row,d.column+b,b===0)},this.moveCursorToPosition=function(a){this.moveCursorTo(a.row,a.column)},this.moveCursorTo=function(a,b,c){var d=this.session.getFoldAt(a,b,1);d&&(a=d.start.row,b=d.start.column),this.$keepDesiredColumnOnChange=!0,this.selectionLead.setPosition(a,b),this.$keepDesiredColumnOnChange=!1,c||(this.$desiredColumn=null)},this.moveCursorToScreen=function(a,b,c){var d=this.session.screenToDocumentPosition(a,b);this.moveCursorTo(d.row,d.column,c)},this.detach=function(){this.selectionLead.detach(),this.selectionAnchor.detach(),this.session=this.doc=null},this.fromOrientedRange=function(a){this.setSelectionRange(a,a.cursor==a.start),this.$desiredColumn=a.desiredColumn||this.$desiredColumn},this.toOrientedRange=function(a){var b=this.getRange();return a?(a.start.column=b.start.column,a.start.row=b.start.row,a.end.column=b.end.column,a.end.row=b.end.row):a=b,a.cursor=this.isBackwards()?a.start:a.end,a.desiredColumn=this.$desiredColumn,a}}).call(h.prototype),b.Selection=h}),define("ace/range",["require","exports","module"],function(a,b,c){"use strict";var d=function(a,b,c,d){this.start={row:a,column:b},this.end={row:c,column:d}};(function(){this.isEqual=function(a){return this.start.row==a.start.row&&this.end.row==a.end.row&&this.start.column==a.start.column&&this.end.column==a.end.column},this.toString=function(){return"Range: ["+this.start.row+"/"+this.start.column+"] -> ["+this.end.row+"/"+this.end.column+"]"},this.contains=function(a,b){return this.compare(a,b)==0},this.compareRange=function(a){var b,c=a.end,d=a.start;return b=this.compare(c.row,c.column),b==1?(b=this.compare(d.row,d.column),b==1?2:b==0?1:0):b==-1?-2:(b=this.compare(d.row,d.column),b==-1?-1:b==1?42:0)},this.comparePoint=function(a){return this.compare(a.row,a.column)},this.containsRange=function(a){return this.comparePoint(a.start)==0&&this.comparePoint(a.end)==0},this.intersectsRange=function(a){var b=this.compareRange(a);return b==-1||b==0||b==1},this.isEnd=function(a,b){return this.end.row==a&&this.end.column==b},this.isStart=function(a,b){return this.start.row==a&&this.start.column==b},this.setStart=function(a,b){typeof a=="object"?(this.start.column=a.column,this.start.row=a.row):(this.start.row=a,this.start.column=b)},this.setEnd=function(a,b){typeof a=="object"?(this.end.column=a.column,this.end.row=a.row):(this.end.row=a,this.end.column=b)},this.inside=function(a,b){return this.compare(a,b)==0?this.isEnd(a,b)||this.isStart(a,b)?!1:!0:!1},this.insideStart=function(a,b){return this.compare(a,b)==0?this.isEnd(a,b)?!1:!0:!1},this.insideEnd=function(a,b){return this.compare(a,b)==0?this.isStart(a,b)?!1:!0:!1},this.compare=function(a,b){return!this.isMultiLine()&&a===this.start.row?b<this.start.column?-1:b>this.end.column?1:0:a<this.start.row?-1:a>this.end.row?1:this.start.row===a?b>=this.start.column?0:-1:this.end.row===a?b<=this.end.column?0:1:0},this.compareStart=function(a,b){return this.start.row==a&&this.start.column==b?-1:this.compare(a,b)},this.compareEnd=function(a,b){return this.end.row==a&&this.end.column==b?1:this.compare(a,b)},this.compareInside=function(a,b){return this.end.row==a&&this.end.column==b?1:this.start.row==a&&this.start.column==b?-1:this.compare(a,b)},this.clipRows=function(a,b){if(this.end.row>b)var c={row:b+1,column:0};if(this.start.row>b)var e={row:b+1,column:0};if(this.start.row<a)var e={row:a,column:0};if(this.end.row<a)var c={row:a,column:0};return d.fromPoints(e||this.start,c||this.end)},this.extend=function(a,b){var c=this.compare(a,b);if(c==0)return this;if(c==-1)var e={row:a,column:b};else var f={row:a,column:b};return d.fromPoints(e||this.start,f||this.end)},this.fixOrientation=function(){if(this.start.row<this.end.row||this.start.row==this.end.row&&this.start.column<this.end.column)return!1;var a=this.start;return this.end=this.start,this.start=a,!0},this.isEmpty=function(){return this.start.row==this.end.row&&this.start.column==this.end.column},this.isMultiLine=function(){return this.start.row!==this.end.row},this.clone=function(){return d.fromPoints(this.start,this.end)},this.collapseRows=function(){return this.end.column==0?new d(this.start.row,0,Math.max(this.start.row,this.end.row-1),0):new d(this.start.row,0,this.end.row,0)},this.toScreenRange=function(a){var b=a.documentToScreenPosition(this.start),c=a.documentToScreenPosition(this.end);return new d(b.row,b.column,c.row,c.column)}}).call(d.prototype),d.fromPoints=function(a,b){return new d(a.row,a.column,b.row,b.column)},b.Range=d}),define("ace/mode/text",["require","exports","module","ace/tokenizer","ace/mode/text_highlight_rules","ace/mode/behaviour","ace/unicode"],function(a,b,c){"use strict";var d=a("../tokenizer").Tokenizer,e=a("./text_highlight_rules").TextHighlightRules,f=a("./behaviour").Behaviour,g=a("../unicode"),h=function(){this.$tokenizer=new d((new e).getRules()),this.$behaviour=new f};(function(){this.tokenRe=new RegExp("^["+g.packages.L+g.packages.Mn+g.packages.Mc+g.packages.Nd+g.packages.Pc+"\\$_]+","g"),this.nonTokenRe=new RegExp("^(?:[^"+g.packages.L+g.packages.Mn+g.packages.Mc+g.packages.Nd+g.packages.Pc+"\\$_]|s])+","g"),this.getTokenizer=function(){return this.$tokenizer},this.toggleCommentLines=function(a,b,c,d){},this.getNextLineIndent=function(a,b,c){return""},this.checkOutdent=function(a,b,c){return!1},this.autoOutdent=function(a,b,c){},this.$getIndent=function(a){var b=a.match(/^(\s+)/);return b?b[1]:""},this.createWorker=function(a){return null},this.highlightSelection=function(a){var b=a.session;b.$selectionOccurrences||(b.$selectionOccurrences=[]),b.$selectionOccurrences.length&&this.clearSelectionHighlight(a);var c=a.getSelectionRange();if(c.isEmpty()||c.isMultiLine())return;var d=c.start.column-1,e=c.end.column+1,f=b.getLine(c.start.row),g=f.length,h=f.substring(Math.max(d,0),Math.min(e,g));if(d>=0&&/^[\w\d]/.test(h)||e<=g&&/[\w\d]$/.test(h))return;h=f.substring(c.start.column,c.end.column);if(!/^[\w\d]+$/.test(h))return;var i=a.getCursorPosition(),j={wrap:!0,wholeWord:!0,caseSensitive:!0,needle:h},k=a.$search.getOptions();a.$search.set(j);var l=a.$search.findAll(b);l.forEach(function(a){if(!a.contains(i.row,i.column)){var c=b.addMarker(a,"ace_selected_word","text");b.$selectionOccurrences.push(c)}}),a.$search.set(k)},this.clearSelectionHighlight=function(a){if(!a.session.$selectionOccurrences)return;a.session.$selectionOccurrences.forEach(function(b){a.session.removeMarker(b)}),a.session.$selectionOccurrences=[]},this.createModeDelegates=function(a){if(!this.$embeds)return;this.$modes={};for(var b=0;b<this.$embeds.length;b++)a[this.$embeds[b]]&&(this.$modes[this.$embeds[b]]=new a[this.$embeds[b]]);var c=["toggleCommentLines","getNextLineIndent","checkOutdent","autoOutdent","transformAction"];for(var b=0;b<c.length;b++)(function(a){var d=c[b],e=a[d];a[c[b]]=function(){return this.$delegator(d,arguments,e)}})(this)},this.$delegator=function(a,b,c){var d=b[0];for(var e=0;e<this.$embeds.length;e++){if(!this.$modes[this.$embeds[e]])continue;var f=d.split(this.$embeds[e]);if(!f[0]&&f[1]){b[0]=f[1];var g=this.$modes[this.$embeds[e]];return g[a].apply(g,b)}}var h=c.apply(this,b);return c?h:undefined},this.transformAction=function(a,b,c,d,e){if(this.$behaviour){var f=this.$behaviour.getBehaviours();for(var g in f)if(f[g][b]){var h=f[g][b].apply(this,arguments);if(h)return h}}}}).call(h.prototype),b.Mode=h}),define("ace/tokenizer",["require","exports","module"],function(a,b,c){"use strict";var d=function(a,b){b=b?"g"+b:"g",this.rules=a,this.regExps={},this.matchMappings={};for(var c in this.rules){var d=this.rules[c],e=d,f=[],g=0,h=this.matchMappings[c]={};for(var i=0;i<e.length;i++){e[i].regex instanceof RegExp&&(e[i].regex=e[i].regex.toString().slice(1,-1));var j=(new RegExp("(?:("+e[i].regex+")|(.))")).exec("a").length-2,k=e[i].regex.replace(/\\([0-9]+)/g,function(a,b){return"\\"+(parseInt(b,10)+g+1)});if(j>1&&e[i].token.length!==j-1)throw new Error("Matching groups and length of the token array don't match in rule #"+i+" of state "+c);h[g]={rule:i,len:j},g+=j,f.push(k)}this.regExps[c]=new RegExp("(?:("+f.join(")|(")+")|(.))",b)}};(function(){this.getLineTokens=function(a,b){var c=b,d=this.rules[c],e=this.matchMappings[c],f=this.regExps[c];f.lastIndex=0;var g,h=[],i=0,j={type:null,value:""};while(g=f.exec(a)){var k="text",l=null,m=[g[0]];for(var n=0;n<g.length-2;n++){if(g[n+1]===undefined)continue;l=d[e[n].rule],e[n].len>1&&(m=g.slice(n+2,n+1+e[n].len)),typeof l.token=="function"?k=l.token.apply(this,m):k=l.token;var o=l.next;o&&o!==c&&(c=o,d=this.rules[c],e=this.matchMappings[c],i=f.lastIndex,f=this.regExps[c],f.lastIndex=i);break}if(m[0]){typeof k=="string"&&(m=[m.join("")],k=[k]);for(var n=0;n<m.length;n++){if(!m[n])continue;(!l||l.merge||k[n]==="text")&&j.type===k[n]?j.value+=m[n]:(j.type&&h.push(j),j={type:k[n],value:m[n]})}}if(i==a.length)break;i=f.lastIndex}return j.type&&h.push(j),{tokens:h,state:c}}}).call(d.prototype),b.Tokenizer=d}),define("ace/mode/text_highlight_rules",["require","exports","module","ace/lib/lang"],function(a,b,c){"use strict";var d=a("../lib/lang"),e=function(){this.$rules={start:[{token:"empty_line",regex:"^$"},{token:"text",regex:".+"}]}};(function(){this.addRules=function(a,b){for(var c in a){var d=a[c];for(var e=0;e<d.length;e++){var f=d[e];f.next?f.next=b+f.next:f.next=b+c}this.$rules[b+c]=d}},this.getRules=function(){return this.$rules},this.embedRules=function(a,b,c,e){var f=(new a).getRules();if(e)for(var g=0;g<e.length;g++)e[g]=b+e[g];else{e=[];for(var h in f)e.push(b+h)}this.addRules(f,b);for(var g=0;g<e.length;g++)Array.prototype.unshift.apply(this.$rules[e[g]],d.deepCopy(c));this.$embeds||(this.$embeds=[]),this.$embeds.push(b)},this.getEmbeds=function(){return this.$embeds}}).call(e.prototype),b.TextHighlightRules=e}),define("ace/mode/behaviour",["require","exports","module"],function(a,b,c){"use strict";var d=function(){this.$behaviours={}};(function(){this.add=function(a,b,c){switch(undefined){case this.$behaviours:this.$behaviours={};case this.$behaviours[a]:this.$behaviours[a]={}}this.$behaviours[a][b]=c},this.addBehaviours=function(a){for(var b in a)for(var c in a[b])this.add(b,c,a[b][c])},this.remove=function(a){this.$behaviours&&this.$behaviours[a]&&delete this.$behaviours[a]},this.inherit=function(a,b){if(typeof a=="function")var c=(new a).getBehaviours(b);else var c=a.getBehaviours(b);this.addBehaviours(c)},this.getBehaviours=function(a){if(!a)return this.$behaviours;var b={};for(var c=0;c<a.length;c++)this.$behaviours[a[c]]&&(b[a[c]]=this.$behaviours[a[c]]);return b}}).call(d.prototype),b.Behaviour=d}),define("ace/unicode",["require","exports","module"],function(a,b,c){function d(a){var c=/\w{4}/g;for(var d in a)b.packages[d]=a[d].replace(c,"\\u$&")}"use strict",b.packages={},d({L:"0041-005A0061-007A00AA00B500BA00C0-00D600D8-00F600F8-02C102C6-02D102E0-02E402EC02EE0370-037403760377037A-037D03860388-038A038C038E-03A103A3-03F503F7-0481048A-05250531-055605590561-058705D0-05EA05F0-05F20621-064A066E066F0671-06D306D506E506E606EE06EF06FA-06FC06FF07100712-072F074D-07A507B107CA-07EA07F407F507FA0800-0815081A082408280904-0939093D09500958-0961097109720979-097F0985-098C098F09900993-09A809AA-09B009B209B6-09B909BD09CE09DC09DD09DF-09E109F009F10A05-0A0A0A0F0A100A13-0A280A2A-0A300A320A330A350A360A380A390A59-0A5C0A5E0A72-0A740A85-0A8D0A8F-0A910A93-0AA80AAA-0AB00AB20AB30AB5-0AB90ABD0AD00AE00AE10B05-0B0C0B0F0B100B13-0B280B2A-0B300B320B330B35-0B390B3D0B5C0B5D0B5F-0B610B710B830B85-0B8A0B8E-0B900B92-0B950B990B9A0B9C0B9E0B9F0BA30BA40BA8-0BAA0BAE-0BB90BD00C05-0C0C0C0E-0C100C12-0C280C2A-0C330C35-0C390C3D0C580C590C600C610C85-0C8C0C8E-0C900C92-0CA80CAA-0CB30CB5-0CB90CBD0CDE0CE00CE10D05-0D0C0D0E-0D100D12-0D280D2A-0D390D3D0D600D610D7A-0D7F0D85-0D960D9A-0DB10DB3-0DBB0DBD0DC0-0DC60E01-0E300E320E330E40-0E460E810E820E840E870E880E8A0E8D0E94-0E970E99-0E9F0EA1-0EA30EA50EA70EAA0EAB0EAD-0EB00EB20EB30EBD0EC0-0EC40EC60EDC0EDD0F000F40-0F470F49-0F6C0F88-0F8B1000-102A103F1050-1055105A-105D106110651066106E-10701075-1081108E10A0-10C510D0-10FA10FC1100-1248124A-124D1250-12561258125A-125D1260-1288128A-128D1290-12B012B2-12B512B8-12BE12C012C2-12C512C8-12D612D8-13101312-13151318-135A1380-138F13A0-13F41401-166C166F-167F1681-169A16A0-16EA1700-170C170E-17111720-17311740-17511760-176C176E-17701780-17B317D717DC1820-18771880-18A818AA18B0-18F51900-191C1950-196D1970-19741980-19AB19C1-19C71A00-1A161A20-1A541AA71B05-1B331B45-1B4B1B83-1BA01BAE1BAF1C00-1C231C4D-1C4F1C5A-1C7D1CE9-1CEC1CEE-1CF11D00-1DBF1E00-1F151F18-1F1D1F20-1F451F48-1F4D1F50-1F571F591F5B1F5D1F5F-1F7D1F80-1FB41FB6-1FBC1FBE1FC2-1FC41FC6-1FCC1FD0-1FD31FD6-1FDB1FE0-1FEC1FF2-1FF41FF6-1FFC2071207F2090-209421022107210A-211321152119-211D212421262128212A-212D212F-2139213C-213F2145-2149214E218321842C00-2C2E2C30-2C5E2C60-2CE42CEB-2CEE2D00-2D252D30-2D652D6F2D80-2D962DA0-2DA62DA8-2DAE2DB0-2DB62DB8-2DBE2DC0-2DC62DC8-2DCE2DD0-2DD62DD8-2DDE2E2F300530063031-3035303B303C3041-3096309D-309F30A1-30FA30FC-30FF3105-312D3131-318E31A0-31B731F0-31FF3400-4DB54E00-9FCBA000-A48CA4D0-A4FDA500-A60CA610-A61FA62AA62BA640-A65FA662-A66EA67F-A697A6A0-A6E5A717-A71FA722-A788A78BA78CA7FB-A801A803-A805A807-A80AA80C-A822A840-A873A882-A8B3A8F2-A8F7A8FBA90A-A925A930-A946A960-A97CA984-A9B2A9CFAA00-AA28AA40-AA42AA44-AA4BAA60-AA76AA7AAA80-AAAFAAB1AAB5AAB6AAB9-AABDAAC0AAC2AADB-AADDABC0-ABE2AC00-D7A3D7B0-D7C6D7CB-D7FBF900-FA2DFA30-FA6DFA70-FAD9FB00-FB06FB13-FB17FB1DFB1F-FB28FB2A-FB36FB38-FB3CFB3EFB40FB41FB43FB44FB46-FBB1FBD3-FD3DFD50-FD8FFD92-FDC7FDF0-FDFBFE70-FE74FE76-FEFCFF21-FF3AFF41-FF5AFF66-FFBEFFC2-FFC7FFCA-FFCFFFD2-FFD7FFDA-FFDC",Ll:"0061-007A00AA00B500BA00DF-00F600F8-00FF01010103010501070109010B010D010F01110113011501170119011B011D011F01210123012501270129012B012D012F01310133013501370138013A013C013E014001420144014601480149014B014D014F01510153015501570159015B015D015F01610163016501670169016B016D016F0171017301750177017A017C017E-0180018301850188018C018D019201950199-019B019E01A101A301A501A801AA01AB01AD01B001B401B601B901BA01BD-01BF01C601C901CC01CE01D001D201D401D601D801DA01DC01DD01DF01E101E301E501E701E901EB01ED01EF01F001F301F501F901FB01FD01FF02010203020502070209020B020D020F02110213021502170219021B021D021F02210223022502270229022B022D022F02310233-0239023C023F0240024202470249024B024D024F-02930295-02AF037103730377037B-037D039003AC-03CE03D003D103D5-03D703D903DB03DD03DF03E103E303E503E703E903EB03ED03EF-03F303F503F803FB03FC0430-045F04610463046504670469046B046D046F04710473047504770479047B047D047F0481048B048D048F04910493049504970499049B049D049F04A104A304A504A704A904AB04AD04AF04B104B304B504B704B904BB04BD04BF04C204C404C604C804CA04CC04CE04CF04D104D304D504D704D904DB04DD04DF04E104E304E504E704E904EB04ED04EF04F104F304F504F704F904FB04FD04FF05010503050505070509050B050D050F05110513051505170519051B051D051F0521052305250561-05871D00-1D2B1D62-1D771D79-1D9A1E011E031E051E071E091E0B1E0D1E0F1E111E131E151E171E191E1B1E1D1E1F1E211E231E251E271E291E2B1E2D1E2F1E311E331E351E371E391E3B1E3D1E3F1E411E431E451E471E491E4B1E4D1E4F1E511E531E551E571E591E5B1E5D1E5F1E611E631E651E671E691E6B1E6D1E6F1E711E731E751E771E791E7B1E7D1E7F1E811E831E851E871E891E8B1E8D1E8F1E911E931E95-1E9D1E9F1EA11EA31EA51EA71EA91EAB1EAD1EAF1EB11EB31EB51EB71EB91EBB1EBD1EBF1EC11EC31EC51EC71EC91ECB1ECD1ECF1ED11ED31ED51ED71ED91EDB1EDD1EDF1EE11EE31EE51EE71EE91EEB1EED1EEF1EF11EF31EF51EF71EF91EFB1EFD1EFF-1F071F10-1F151F20-1F271F30-1F371F40-1F451F50-1F571F60-1F671F70-1F7D1F80-1F871F90-1F971FA0-1FA71FB0-1FB41FB61FB71FBE1FC2-1FC41FC61FC71FD0-1FD31FD61FD71FE0-1FE71FF2-1FF41FF61FF7210A210E210F2113212F21342139213C213D2146-2149214E21842C30-2C5E2C612C652C662C682C6A2C6C2C712C732C742C76-2C7C2C812C832C852C872C892C8B2C8D2C8F2C912C932C952C972C992C9B2C9D2C9F2CA12CA32CA52CA72CA92CAB2CAD2CAF2CB12CB32CB52CB72CB92CBB2CBD2CBF2CC12CC32CC52CC72CC92CCB2CCD2CCF2CD12CD32CD52CD72CD92CDB2CDD2CDF2CE12CE32CE42CEC2CEE2D00-2D25A641A643A645A647A649A64BA64DA64FA651A653A655A657A659A65BA65DA65FA663A665A667A669A66BA66DA681A683A685A687A689A68BA68DA68FA691A693A695A697A723A725A727A729A72BA72DA72F-A731A733A735A737A739A73BA73DA73FA741A743A745A747A749A74BA74DA74FA751A753A755A757A759A75BA75DA75FA761A763A765A767A769A76BA76DA76FA771-A778A77AA77CA77FA781A783A785A787A78CFB00-FB06FB13-FB17FF41-FF5A",Lu:"0041-005A00C0-00D600D8-00DE01000102010401060108010A010C010E01100112011401160118011A011C011E01200122012401260128012A012C012E01300132013401360139013B013D013F0141014301450147014A014C014E01500152015401560158015A015C015E01600162016401660168016A016C016E017001720174017601780179017B017D018101820184018601870189-018B018E-0191019301940196-0198019C019D019F01A001A201A401A601A701A901AC01AE01AF01B1-01B301B501B701B801BC01C401C701CA01CD01CF01D101D301D501D701D901DB01DE01E001E201E401E601E801EA01EC01EE01F101F401F6-01F801FA01FC01FE02000202020402060208020A020C020E02100212021402160218021A021C021E02200222022402260228022A022C022E02300232023A023B023D023E02410243-02460248024A024C024E03700372037603860388-038A038C038E038F0391-03A103A3-03AB03CF03D2-03D403D803DA03DC03DE03E003E203E403E603E803EA03EC03EE03F403F703F903FA03FD-042F04600462046404660468046A046C046E04700472047404760478047A047C047E0480048A048C048E04900492049404960498049A049C049E04A004A204A404A604A804AA04AC04AE04B004B204B404B604B804BA04BC04BE04C004C104C304C504C704C904CB04CD04D004D204D404D604D804DA04DC04DE04E004E204E404E604E804EA04EC04EE04F004F204F404F604F804FA04FC04FE05000502050405060508050A050C050E05100512051405160518051A051C051E0520052205240531-055610A0-10C51E001E021E041E061E081E0A1E0C1E0E1E101E121E141E161E181E1A1E1C1E1E1E201E221E241E261E281E2A1E2C1E2E1E301E321E341E361E381E3A1E3C1E3E1E401E421E441E461E481E4A1E4C1E4E1E501E521E541E561E581E5A1E5C1E5E1E601E621E641E661E681E6A1E6C1E6E1E701E721E741E761E781E7A1E7C1E7E1E801E821E841E861E881E8A1E8C1E8E1E901E921E941E9E1EA01EA21EA41EA61EA81EAA1EAC1EAE1EB01EB21EB41EB61EB81EBA1EBC1EBE1EC01EC21EC41EC61EC81ECA1ECC1ECE1ED01ED21ED41ED61ED81EDA1EDC1EDE1EE01EE21EE41EE61EE81EEA1EEC1EEE1EF01EF21EF41EF61EF81EFA1EFC1EFE1F08-1F0F1F18-1F1D1F28-1F2F1F38-1F3F1F48-1F4D1F591F5B1F5D1F5F1F68-1F6F1FB8-1FBB1FC8-1FCB1FD8-1FDB1FE8-1FEC1FF8-1FFB21022107210B-210D2110-211221152119-211D212421262128212A-212D2130-2133213E213F214521832C00-2C2E2C602C62-2C642C672C692C6B2C6D-2C702C722C752C7E-2C802C822C842C862C882C8A2C8C2C8E2C902C922C942C962C982C9A2C9C2C9E2CA02CA22CA42CA62CA82CAA2CAC2CAE2CB02CB22CB42CB62CB82CBA2CBC2CBE2CC02CC22CC42CC62CC82CCA2CCC2CCE2CD02CD22CD42CD62CD82CDA2CDC2CDE2CE02CE22CEB2CEDA640A642A644A646A648A64AA64CA64EA650A652A654A656A658A65AA65CA65EA662A664A666A668A66AA66CA680A682A684A686A688A68AA68CA68EA690A692A694A696A722A724A726A728A72AA72CA72EA732A734A736A738A73AA73CA73EA740A742A744A746A748A74AA74CA74EA750A752A754A756A758A75AA75CA75EA760A762A764A766A768A76AA76CA76EA779A77BA77DA77EA780A782A784A786A78BFF21-FF3A",Lt:"01C501C801CB01F21F88-1F8F1F98-1F9F1FA8-1FAF1FBC1FCC1FFC",Lm:"02B0-02C102C6-02D102E0-02E402EC02EE0374037A0559064006E506E607F407F507FA081A0824082809710E460EC610FC17D718431AA71C78-1C7D1D2C-1D611D781D9B-1DBF2071207F2090-20942C7D2D6F2E2F30053031-3035303B309D309E30FC-30FEA015A4F8-A4FDA60CA67FA717-A71FA770A788A9CFAA70AADDFF70FF9EFF9F",Lo:"01BB01C0-01C3029405D0-05EA05F0-05F20621-063F0641-064A066E066F0671-06D306D506EE06EF06FA-06FC06FF07100712-072F074D-07A507B107CA-07EA0800-08150904-0939093D09500958-096109720979-097F0985-098C098F09900993-09A809AA-09B009B209B6-09B909BD09CE09DC09DD09DF-09E109F009F10A05-0A0A0A0F0A100A13-0A280A2A-0A300A320A330A350A360A380A390A59-0A5C0A5E0A72-0A740A85-0A8D0A8F-0A910A93-0AA80AAA-0AB00AB20AB30AB5-0AB90ABD0AD00AE00AE10B05-0B0C0B0F0B100B13-0B280B2A-0B300B320B330B35-0B390B3D0B5C0B5D0B5F-0B610B710B830B85-0B8A0B8E-0B900B92-0B950B990B9A0B9C0B9E0B9F0BA30BA40BA8-0BAA0BAE-0BB90BD00C05-0C0C0C0E-0C100C12-0C280C2A-0C330C35-0C390C3D0C580C590C600C610C85-0C8C0C8E-0C900C92-0CA80CAA-0CB30CB5-0CB90CBD0CDE0CE00CE10D05-0D0C0D0E-0D100D12-0D280D2A-0D390D3D0D600D610D7A-0D7F0D85-0D960D9A-0DB10DB3-0DBB0DBD0DC0-0DC60E01-0E300E320E330E40-0E450E810E820E840E870E880E8A0E8D0E94-0E970E99-0E9F0EA1-0EA30EA50EA70EAA0EAB0EAD-0EB00EB20EB30EBD0EC0-0EC40EDC0EDD0F000F40-0F470F49-0F6C0F88-0F8B1000-102A103F1050-1055105A-105D106110651066106E-10701075-1081108E10D0-10FA1100-1248124A-124D1250-12561258125A-125D1260-1288128A-128D1290-12B012B2-12B512B8-12BE12C012C2-12C512C8-12D612D8-13101312-13151318-135A1380-138F13A0-13F41401-166C166F-167F1681-169A16A0-16EA1700-170C170E-17111720-17311740-17511760-176C176E-17701780-17B317DC1820-18421844-18771880-18A818AA18B0-18F51900-191C1950-196D1970-19741980-19AB19C1-19C71A00-1A161A20-1A541B05-1B331B45-1B4B1B83-1BA01BAE1BAF1C00-1C231C4D-1C4F1C5A-1C771CE9-1CEC1CEE-1CF12135-21382D30-2D652D80-2D962DA0-2DA62DA8-2DAE2DB0-2DB62DB8-2DBE2DC0-2DC62DC8-2DCE2DD0-2DD62DD8-2DDE3006303C3041-3096309F30A1-30FA30FF3105-312D3131-318E31A0-31B731F0-31FF3400-4DB54E00-9FCBA000-A014A016-A48CA4D0-A4F7A500-A60BA610-A61FA62AA62BA66EA6A0-A6E5A7FB-A801A803-A805A807-A80AA80C-A822A840-A873A882-A8B3A8F2-A8F7A8FBA90A-A925A930-A946A960-A97CA984-A9B2AA00-AA28AA40-AA42AA44-AA4BAA60-AA6FAA71-AA76AA7AAA80-AAAFAAB1AAB5AAB6AAB9-AABDAAC0AAC2AADBAADCABC0-ABE2AC00-D7A3D7B0-D7C6D7CB-D7FBF900-FA2DFA30-FA6DFA70-FAD9FB1DFB1F-FB28FB2A-FB36FB38-FB3CFB3EFB40FB41FB43FB44FB46-FBB1FBD3-FD3DFD50-FD8FFD92-FDC7FDF0-FDFBFE70-FE74FE76-FEFCFF66-FF6FFF71-FF9DFFA0-FFBEFFC2-FFC7FFCA-FFCFFFD2-FFD7FFDA-FFDC",M:"0300-036F0483-04890591-05BD05BF05C105C205C405C505C70610-061A064B-065E067006D6-06DC06DE-06E406E706E806EA-06ED07110730-074A07A6-07B007EB-07F30816-0819081B-08230825-08270829-082D0900-0903093C093E-094E0951-0955096209630981-098309BC09BE-09C409C709C809CB-09CD09D709E209E30A01-0A030A3C0A3E-0A420A470A480A4B-0A4D0A510A700A710A750A81-0A830ABC0ABE-0AC50AC7-0AC90ACB-0ACD0AE20AE30B01-0B030B3C0B3E-0B440B470B480B4B-0B4D0B560B570B620B630B820BBE-0BC20BC6-0BC80BCA-0BCD0BD70C01-0C030C3E-0C440C46-0C480C4A-0C4D0C550C560C620C630C820C830CBC0CBE-0CC40CC6-0CC80CCA-0CCD0CD50CD60CE20CE30D020D030D3E-0D440D46-0D480D4A-0D4D0D570D620D630D820D830DCA0DCF-0DD40DD60DD8-0DDF0DF20DF30E310E34-0E3A0E47-0E4E0EB10EB4-0EB90EBB0EBC0EC8-0ECD0F180F190F350F370F390F3E0F3F0F71-0F840F860F870F90-0F970F99-0FBC0FC6102B-103E1056-1059105E-10601062-10641067-106D1071-10741082-108D108F109A-109D135F1712-17141732-1734175217531772177317B6-17D317DD180B-180D18A91920-192B1930-193B19B0-19C019C819C91A17-1A1B1A55-1A5E1A60-1A7C1A7F1B00-1B041B34-1B441B6B-1B731B80-1B821BA1-1BAA1C24-1C371CD0-1CD21CD4-1CE81CED1CF21DC0-1DE61DFD-1DFF20D0-20F02CEF-2CF12DE0-2DFF302A-302F3099309AA66F-A672A67CA67DA6F0A6F1A802A806A80BA823-A827A880A881A8B4-A8C4A8E0-A8F1A926-A92DA947-A953A980-A983A9B3-A9C0AA29-AA36AA43AA4CAA4DAA7BAAB0AAB2-AAB4AAB7AAB8AABEAABFAAC1ABE3-ABEAABECABEDFB1EFE00-FE0FFE20-FE26",Mn:"0300-036F0483-04870591-05BD05BF05C105C205C405C505C70610-061A064B-065E067006D6-06DC06DF-06E406E706E806EA-06ED07110730-074A07A6-07B007EB-07F30816-0819081B-08230825-08270829-082D0900-0902093C0941-0948094D0951-095509620963098109BC09C1-09C409CD09E209E30A010A020A3C0A410A420A470A480A4B-0A4D0A510A700A710A750A810A820ABC0AC1-0AC50AC70AC80ACD0AE20AE30B010B3C0B3F0B41-0B440B4D0B560B620B630B820BC00BCD0C3E-0C400C46-0C480C4A-0C4D0C550C560C620C630CBC0CBF0CC60CCC0CCD0CE20CE30D41-0D440D4D0D620D630DCA0DD2-0DD40DD60E310E34-0E3A0E47-0E4E0EB10EB4-0EB90EBB0EBC0EC8-0ECD0F180F190F350F370F390F71-0F7E0F80-0F840F860F870F90-0F970F99-0FBC0FC6102D-10301032-10371039103A103D103E10581059105E-10601071-1074108210851086108D109D135F1712-17141732-1734175217531772177317B7-17BD17C617C9-17D317DD180B-180D18A91920-19221927192819321939-193B1A171A181A561A58-1A5E1A601A621A65-1A6C1A73-1A7C1A7F1B00-1B031B341B36-1B3A1B3C1B421B6B-1B731B801B811BA2-1BA51BA81BA91C2C-1C331C361C371CD0-1CD21CD4-1CE01CE2-1CE81CED1DC0-1DE61DFD-1DFF20D0-20DC20E120E5-20F02CEF-2CF12DE0-2DFF302A-302F3099309AA66FA67CA67DA6F0A6F1A802A806A80BA825A826A8C4A8E0-A8F1A926-A92DA947-A951A980-A982A9B3A9B6-A9B9A9BCAA29-AA2EAA31AA32AA35AA36AA43AA4CAAB0AAB2-AAB4AAB7AAB8AABEAABFAAC1ABE5ABE8ABEDFB1EFE00-FE0FFE20-FE26",Mc:"0903093E-09400949-094C094E0982098309BE-09C009C709C809CB09CC09D70A030A3E-0A400A830ABE-0AC00AC90ACB0ACC0B020B030B3E0B400B470B480B4B0B4C0B570BBE0BBF0BC10BC20BC6-0BC80BCA-0BCC0BD70C01-0C030C41-0C440C820C830CBE0CC0-0CC40CC70CC80CCA0CCB0CD50CD60D020D030D3E-0D400D46-0D480D4A-0D4C0D570D820D830DCF-0DD10DD8-0DDF0DF20DF30F3E0F3F0F7F102B102C10311038103B103C105610571062-10641067-106D108310841087-108C108F109A-109C17B617BE-17C517C717C81923-19261929-192B193019311933-193819B0-19C019C819C91A19-1A1B1A551A571A611A631A641A6D-1A721B041B351B3B1B3D-1B411B431B441B821BA11BA61BA71BAA1C24-1C2B1C341C351CE11CF2A823A824A827A880A881A8B4-A8C3A952A953A983A9B4A9B5A9BAA9BBA9BD-A9C0AA2FAA30AA33AA34AA4DAA7BABE3ABE4ABE6ABE7ABE9ABEAABEC",Me:"0488048906DE20DD-20E020E2-20E4A670-A672",N:"0030-003900B200B300B900BC-00BE0660-066906F0-06F907C0-07C90966-096F09E6-09EF09F4-09F90A66-0A6F0AE6-0AEF0B66-0B6F0BE6-0BF20C66-0C6F0C78-0C7E0CE6-0CEF0D66-0D750E50-0E590ED0-0ED90F20-0F331040-10491090-10991369-137C16EE-16F017E0-17E917F0-17F91810-18191946-194F19D0-19DA1A80-1A891A90-1A991B50-1B591BB0-1BB91C40-1C491C50-1C5920702074-20792080-20892150-21822185-21892460-249B24EA-24FF2776-27932CFD30073021-30293038-303A3192-31953220-32293251-325F3280-328932B1-32BFA620-A629A6E6-A6EFA830-A835A8D0-A8D9A900-A909A9D0-A9D9AA50-AA59ABF0-ABF9FF10-FF19",Nd:"0030-00390660-066906F0-06F907C0-07C90966-096F09E6-09EF0A66-0A6F0AE6-0AEF0B66-0B6F0BE6-0BEF0C66-0C6F0CE6-0CEF0D66-0D6F0E50-0E590ED0-0ED90F20-0F291040-10491090-109917E0-17E91810-18191946-194F19D0-19DA1A80-1A891A90-1A991B50-1B591BB0-1BB91C40-1C491C50-1C59A620-A629A8D0-A8D9A900-A909A9D0-A9D9AA50-AA59ABF0-ABF9FF10-FF19",Nl:"16EE-16F02160-21822185-218830073021-30293038-303AA6E6-A6EF",No:"00B200B300B900BC-00BE09F4-09F90BF0-0BF20C78-0C7E0D70-0D750F2A-0F331369-137C17F0-17F920702074-20792080-20892150-215F21892460-249B24EA-24FF2776-27932CFD3192-31953220-32293251-325F3280-328932B1-32BFA830-A835",P:"0021-00230025-002A002C-002F003A003B003F0040005B-005D005F007B007D00A100AB00B700BB00BF037E0387055A-055F0589058A05BE05C005C305C605F305F40609060A060C060D061B061E061F066A-066D06D40700-070D07F7-07F90830-083E0964096509700DF40E4F0E5A0E5B0F04-0F120F3A-0F3D0F850FD0-0FD4104A-104F10FB1361-13681400166D166E169B169C16EB-16ED1735173617D4-17D617D8-17DA1800-180A1944194519DE19DF1A1E1A1F1AA0-1AA61AA8-1AAD1B5A-1B601C3B-1C3F1C7E1C7F1CD32010-20272030-20432045-20512053-205E207D207E208D208E2329232A2768-277527C527C627E6-27EF2983-299829D8-29DB29FC29FD2CF9-2CFC2CFE2CFF2E00-2E2E2E302E313001-30033008-30113014-301F3030303D30A030FBA4FEA4FFA60D-A60FA673A67EA6F2-A6F7A874-A877A8CEA8CFA8F8-A8FAA92EA92FA95FA9C1-A9CDA9DEA9DFAA5C-AA5FAADEAADFABEBFD3EFD3FFE10-FE19FE30-FE52FE54-FE61FE63FE68FE6AFE6BFF01-FF03FF05-FF0AFF0C-FF0FFF1AFF1BFF1FFF20FF3B-FF3DFF3FFF5BFF5DFF5F-FF65",Pd:"002D058A05BE140018062010-20152E172E1A301C303030A0FE31FE32FE58FE63FF0D",Ps:"0028005B007B0F3A0F3C169B201A201E2045207D208D23292768276A276C276E27702772277427C527E627E827EA27EC27EE2983298529872989298B298D298F299129932995299729D829DA29FC2E222E242E262E283008300A300C300E3010301430163018301A301DFD3EFE17FE35FE37FE39FE3BFE3DFE3FFE41FE43FE47FE59FE5BFE5DFF08FF3BFF5BFF5FFF62",Pe:"0029005D007D0F3B0F3D169C2046207E208E232A2769276B276D276F27712773277527C627E727E927EB27ED27EF298429862988298A298C298E2990299229942996299829D929DB29FD2E232E252E272E293009300B300D300F3011301530173019301B301E301FFD3FFE18FE36FE38FE3AFE3CFE3EFE40FE42FE44FE48FE5AFE5CFE5EFF09FF3DFF5DFF60FF63",Pi:"00AB2018201B201C201F20392E022E042E092E0C2E1C2E20",Pf:"00BB2019201D203A2E032E052E0A2E0D2E1D2E21",Pc:"005F203F20402054FE33FE34FE4D-FE4FFF3F",Po:"0021-00230025-0027002A002C002E002F003A003B003F0040005C00A100B700BF037E0387055A-055F058905C005C305C605F305F40609060A060C060D061B061E061F066A-066D06D40700-070D07F7-07F90830-083E0964096509700DF40E4F0E5A0E5B0F04-0F120F850FD0-0FD4104A-104F10FB1361-1368166D166E16EB-16ED1735173617D4-17D617D8-17DA1800-18051807-180A1944194519DE19DF1A1E1A1F1AA0-1AA61AA8-1AAD1B5A-1B601C3B-1C3F1C7E1C7F1CD3201620172020-20272030-2038203B-203E2041-20432047-205120532055-205E2CF9-2CFC2CFE2CFF2E002E012E06-2E082E0B2E0E-2E162E182E192E1B2E1E2E1F2E2A-2E2E2E302E313001-3003303D30FBA4FEA4FFA60D-A60FA673A67EA6F2-A6F7A874-A877A8CEA8CFA8F8-A8FAA92EA92FA95FA9C1-A9CDA9DEA9DFAA5C-AA5FAADEAADFABEBFE10-FE16FE19FE30FE45FE46FE49-FE4CFE50-FE52FE54-FE57FE5F-FE61FE68FE6AFE6BFF01-FF03FF05-FF07FF0AFF0CFF0EFF0FFF1AFF1BFF1FFF20FF3CFF61FF64FF65",S:"0024002B003C-003E005E0060007C007E00A2-00A900AC00AE-00B100B400B600B800D700F702C2-02C502D2-02DF02E5-02EB02ED02EF-02FF03750384038503F604820606-0608060B060E060F06E906FD06FE07F609F209F309FA09FB0AF10B700BF3-0BFA0C7F0CF10CF20D790E3F0F01-0F030F13-0F170F1A-0F1F0F340F360F380FBE-0FC50FC7-0FCC0FCE0FCF0FD5-0FD8109E109F13601390-139917DB194019E0-19FF1B61-1B6A1B74-1B7C1FBD1FBF-1FC11FCD-1FCF1FDD-1FDF1FED-1FEF1FFD1FFE20442052207A-207C208A-208C20A0-20B8210021012103-21062108210921142116-2118211E-2123212521272129212E213A213B2140-2144214A-214D214F2190-2328232B-23E82400-24262440-244A249C-24E92500-26CD26CF-26E126E326E8-26FF2701-27042706-2709270C-27272729-274B274D274F-27522756-275E2761-276727942798-27AF27B1-27BE27C0-27C427C7-27CA27CC27D0-27E527F0-29822999-29D729DC-29FB29FE-2B4C2B50-2B592CE5-2CEA2E80-2E992E9B-2EF32F00-2FD52FF0-2FFB300430123013302030363037303E303F309B309C319031913196-319F31C0-31E33200-321E322A-32503260-327F328A-32B032C0-32FE3300-33FF4DC0-4DFFA490-A4C6A700-A716A720A721A789A78AA828-A82BA836-A839AA77-AA79FB29FDFCFDFDFE62FE64-FE66FE69FF04FF0BFF1C-FF1EFF3EFF40FF5CFF5EFFE0-FFE6FFE8-FFEEFFFCFFFD",Sm:"002B003C-003E007C007E00AC00B100D700F703F60606-060820442052207A-207C208A-208C2140-2144214B2190-2194219A219B21A021A321A621AE21CE21CF21D221D421F4-22FF2308-230B23202321237C239B-23B323DC-23E125B725C125F8-25FF266F27C0-27C427C7-27CA27CC27D0-27E527F0-27FF2900-29822999-29D729DC-29FB29FE-2AFF2B30-2B442B47-2B4CFB29FE62FE64-FE66FF0BFF1C-FF1EFF5CFF5EFFE2FFE9-FFEC",Sc:"002400A2-00A5060B09F209F309FB0AF10BF90E3F17DB20A0-20B8A838FDFCFE69FF04FFE0FFE1FFE5FFE6",Sk:"005E006000A800AF00B400B802C2-02C502D2-02DF02E5-02EB02ED02EF-02FF0375038403851FBD1FBF-1FC11FCD-1FCF1FDD-1FDF1FED-1FEF1FFD1FFE309B309CA700-A716A720A721A789A78AFF3EFF40FFE3",So:"00A600A700A900AE00B000B60482060E060F06E906FD06FE07F609FA0B700BF3-0BF80BFA0C7F0CF10CF20D790F01-0F030F13-0F170F1A-0F1F0F340F360F380FBE-0FC50FC7-0FCC0FCE0FCF0FD5-0FD8109E109F13601390-1399194019E0-19FF1B61-1B6A1B74-1B7C210021012103-21062108210921142116-2118211E-2123212521272129212E213A213B214A214C214D214F2195-2199219C-219F21A121A221A421A521A7-21AD21AF-21CD21D021D121D321D5-21F32300-2307230C-231F2322-2328232B-237B237D-239A23B4-23DB23E2-23E82400-24262440-244A249C-24E92500-25B625B8-25C025C2-25F72600-266E2670-26CD26CF-26E126E326E8-26FF2701-27042706-2709270C-27272729-274B274D274F-27522756-275E2761-276727942798-27AF27B1-27BE2800-28FF2B00-2B2F2B452B462B50-2B592CE5-2CEA2E80-2E992E9B-2EF32F00-2FD52FF0-2FFB300430123013302030363037303E303F319031913196-319F31C0-31E33200-321E322A-32503260-327F328A-32B032C0-32FE3300-33FF4DC0-4DFFA490-A4C6A828-A82BA836A837A839AA77-AA79FDFDFFE4FFE8FFEDFFEEFFFCFFFD",Z:"002000A01680180E2000-200A20282029202F205F3000",Zs:"002000A01680180E2000-200A202F205F3000",Zl:"2028",Zp:"2029",C:"0000-001F007F-009F00AD03780379037F-0383038B038D03A20526-05300557055805600588058B-059005C8-05CF05EB-05EF05F5-0605061C061D0620065F06DD070E070F074B074C07B2-07BF07FB-07FF082E082F083F-08FF093A093B094F095609570973-097809800984098D098E0991099209A909B109B3-09B509BA09BB09C509C609C909CA09CF-09D609D8-09DB09DE09E409E509FC-0A000A040A0B-0A0E0A110A120A290A310A340A370A3A0A3B0A3D0A43-0A460A490A4A0A4E-0A500A52-0A580A5D0A5F-0A650A76-0A800A840A8E0A920AA90AB10AB40ABA0ABB0AC60ACA0ACE0ACF0AD1-0ADF0AE40AE50AF00AF2-0B000B040B0D0B0E0B110B120B290B310B340B3A0B3B0B450B460B490B4A0B4E-0B550B58-0B5B0B5E0B640B650B72-0B810B840B8B-0B8D0B910B96-0B980B9B0B9D0BA0-0BA20BA5-0BA70BAB-0BAD0BBA-0BBD0BC3-0BC50BC90BCE0BCF0BD1-0BD60BD8-0BE50BFB-0C000C040C0D0C110C290C340C3A-0C3C0C450C490C4E-0C540C570C5A-0C5F0C640C650C70-0C770C800C810C840C8D0C910CA90CB40CBA0CBB0CC50CC90CCE-0CD40CD7-0CDD0CDF0CE40CE50CF00CF3-0D010D040D0D0D110D290D3A-0D3C0D450D490D4E-0D560D58-0D5F0D640D650D76-0D780D800D810D840D97-0D990DB20DBC0DBE0DBF0DC7-0DC90DCB-0DCE0DD50DD70DE0-0DF10DF5-0E000E3B-0E3E0E5C-0E800E830E850E860E890E8B0E8C0E8E-0E930E980EA00EA40EA60EA80EA90EAC0EBA0EBE0EBF0EC50EC70ECE0ECF0EDA0EDB0EDE-0EFF0F480F6D-0F700F8C-0F8F0F980FBD0FCD0FD9-0FFF10C6-10CF10FD-10FF1249124E124F12571259125E125F1289128E128F12B112B612B712BF12C112C612C712D7131113161317135B-135E137D-137F139A-139F13F5-13FF169D-169F16F1-16FF170D1715-171F1737-173F1754-175F176D17711774-177F17B417B517DE17DF17EA-17EF17FA-17FF180F181A-181F1878-187F18AB-18AF18F6-18FF191D-191F192C-192F193C-193F1941-1943196E196F1975-197F19AC-19AF19CA-19CF19DB-19DD1A1C1A1D1A5F1A7D1A7E1A8A-1A8F1A9A-1A9F1AAE-1AFF1B4C-1B4F1B7D-1B7F1BAB-1BAD1BBA-1BFF1C38-1C3A1C4A-1C4C1C80-1CCF1CF3-1CFF1DE7-1DFC1F161F171F1E1F1F1F461F471F4E1F4F1F581F5A1F5C1F5E1F7E1F7F1FB51FC51FD41FD51FDC1FF01FF11FF51FFF200B-200F202A-202E2060-206F20722073208F2095-209F20B9-20CF20F1-20FF218A-218F23E9-23FF2427-243F244B-245F26CE26E226E4-26E727002705270A270B2728274C274E2753-2755275F27602795-279727B027BF27CB27CD-27CF2B4D-2B4F2B5A-2BFF2C2F2C5F2CF2-2CF82D26-2D2F2D66-2D6E2D70-2D7F2D97-2D9F2DA72DAF2DB72DBF2DC72DCF2DD72DDF2E32-2E7F2E9A2EF4-2EFF2FD6-2FEF2FFC-2FFF3040309730983100-3104312E-3130318F31B8-31BF31E4-31EF321F32FF4DB6-4DBF9FCC-9FFFA48D-A48FA4C7-A4CFA62C-A63FA660A661A674-A67BA698-A69FA6F8-A6FFA78D-A7FAA82C-A82FA83A-A83FA878-A87FA8C5-A8CDA8DA-A8DFA8FC-A8FFA954-A95EA97D-A97FA9CEA9DA-A9DDA9E0-A9FFAA37-AA3FAA4EAA4FAA5AAA5BAA7C-AA7FAAC3-AADAAAE0-ABBFABEEABEFABFA-ABFFD7A4-D7AFD7C7-D7CAD7FC-F8FFFA2EFA2FFA6EFA6FFADA-FAFFFB07-FB12FB18-FB1CFB37FB3DFB3FFB42FB45FBB2-FBD2FD40-FD4FFD90FD91FDC8-FDEFFDFEFDFFFE1A-FE1FFE27-FE2FFE53FE67FE6C-FE6FFE75FEFD-FF00FFBF-FFC1FFC8FFC9FFD0FFD1FFD8FFD9FFDD-FFDFFFE7FFEF-FFFBFFFEFFFF",Cc:"0000-001F007F-009F",Cf:"00AD0600-060306DD070F17B417B5200B-200F202A-202E2060-2064206A-206FFEFFFFF9-FFFB",Co:"E000-F8FF",Cs:"D800-DFFF",Cn:"03780379037F-0383038B038D03A20526-05300557055805600588058B-059005C8-05CF05EB-05EF05F5-05FF06040605061C061D0620065F070E074B074C07B2-07BF07FB-07FF082E082F083F-08FF093A093B094F095609570973-097809800984098D098E0991099209A909B109B3-09B509BA09BB09C509C609C909CA09CF-09D609D8-09DB09DE09E409E509FC-0A000A040A0B-0A0E0A110A120A290A310A340A370A3A0A3B0A3D0A43-0A460A490A4A0A4E-0A500A52-0A580A5D0A5F-0A650A76-0A800A840A8E0A920AA90AB10AB40ABA0ABB0AC60ACA0ACE0ACF0AD1-0ADF0AE40AE50AF00AF2-0B000B040B0D0B0E0B110B120B290B310B340B3A0B3B0B450B460B490B4A0B4E-0B550B58-0B5B0B5E0B640B650B72-0B810B840B8B-0B8D0B910B96-0B980B9B0B9D0BA0-0BA20BA5-0BA70BAB-0BAD0BBA-0BBD0BC3-0BC50BC90BCE0BCF0BD1-0BD60BD8-0BE50BFB-0C000C040C0D0C110C290C340C3A-0C3C0C450C490C4E-0C540C570C5A-0C5F0C640C650C70-0C770C800C810C840C8D0C910CA90CB40CBA0CBB0CC50CC90CCE-0CD40CD7-0CDD0CDF0CE40CE50CF00CF3-0D010D040D0D0D110D290D3A-0D3C0D450D490D4E-0D560D58-0D5F0D640D650D76-0D780D800D810D840D97-0D990DB20DBC0DBE0DBF0DC7-0DC90DCB-0DCE0DD50DD70DE0-0DF10DF5-0E000E3B-0E3E0E5C-0E800E830E850E860E890E8B0E8C0E8E-0E930E980EA00EA40EA60EA80EA90EAC0EBA0EBE0EBF0EC50EC70ECE0ECF0EDA0EDB0EDE-0EFF0F480F6D-0F700F8C-0F8F0F980FBD0FCD0FD9-0FFF10C6-10CF10FD-10FF1249124E124F12571259125E125F1289128E128F12B112B612B712BF12C112C612C712D7131113161317135B-135E137D-137F139A-139F13F5-13FF169D-169F16F1-16FF170D1715-171F1737-173F1754-175F176D17711774-177F17DE17DF17EA-17EF17FA-17FF180F181A-181F1878-187F18AB-18AF18F6-18FF191D-191F192C-192F193C-193F1941-1943196E196F1975-197F19AC-19AF19CA-19CF19DB-19DD1A1C1A1D1A5F1A7D1A7E1A8A-1A8F1A9A-1A9F1AAE-1AFF1B4C-1B4F1B7D-1B7F1BAB-1BAD1BBA-1BFF1C38-1C3A1C4A-1C4C1C80-1CCF1CF3-1CFF1DE7-1DFC1F161F171F1E1F1F1F461F471F4E1F4F1F581F5A1F5C1F5E1F7E1F7F1FB51FC51FD41FD51FDC1FF01FF11FF51FFF2065-206920722073208F2095-209F20B9-20CF20F1-20FF218A-218F23E9-23FF2427-243F244B-245F26CE26E226E4-26E727002705270A270B2728274C274E2753-2755275F27602795-279727B027BF27CB27CD-27CF2B4D-2B4F2B5A-2BFF2C2F2C5F2CF2-2CF82D26-2D2F2D66-2D6E2D70-2D7F2D97-2D9F2DA72DAF2DB72DBF2DC72DCF2DD72DDF2E32-2E7F2E9A2EF4-2EFF2FD6-2FEF2FFC-2FFF3040309730983100-3104312E-3130318F31B8-31BF31E4-31EF321F32FF4DB6-4DBF9FCC-9FFFA48D-A48FA4C7-A4CFA62C-A63FA660A661A674-A67BA698-A69FA6F8-A6FFA78D-A7FAA82C-A82FA83A-A83FA878-A87FA8C5-A8CDA8DA-A8DFA8FC-A8FFA954-A95EA97D-A97FA9CEA9DA-A9DDA9E0-A9FFAA37-AA3FAA4EAA4FAA5AAA5BAA7C-AA7FAAC3-AADAAAE0-ABBFABEEABEFABFA-ABFFD7A4-D7AFD7C7-D7CAD7FC-D7FFFA2EFA2FFA6EFA6FFADA-FAFFFB07-FB12FB18-FB1CFB37FB3DFB3FFB42FB45FBB2-FBD2FD40-FD4FFD90FD91FDC8-FDEFFDFEFDFFFE1A-FE1FFE27-FE2FFE53FE67FE6C-FE6FFE75FEFDFEFEFF00FFBF-FFC1FFC8FFC9FFD0FFD1FFD8FFD9FFDD-FFDFFFE7FFEF-FFF8FFFEFFFF"})}),define("ace/document",["require","exports","module","ace/lib/oop","ace/lib/event_emitter","ace/range","ace/anchor"],function(a,b,c){"use strict";var d=a("./lib/oop"),e=a("./lib/event_emitter").EventEmitter,f=a("./range").Range,g=a("./anchor").Anchor,h=function(a){this.$lines=[],Array.isArray(a)?this.insertLines(0,a):a.length==0?this.$lines=[""]:this.insert({row:0,column:0},a)};(function(){d.implement(this,e),this.setValue=function(a){var b=this.getLength();this.remove(new f(0,0,b,this.getLine(b-1).length)),this.insert({row:0,column:0},a)},this.getValue=function(){return this.getAllLines().join(this.getNewLineCharacter())},this.createAnchor=function(a,b){return new g(this,a,b)},"aaa".split(/a/).length==0?this.$split=function(a){return a.replace(/\r\n|\r/g,"\n").split("\n")}:this.$split=function(a){return a.split(/\r\n|\r|\n/)},this.$detectNewLine=function(a){var b=a.match(/^.*?(\r\n|\r|\n)/m);b?this.$autoNewLine=b[1]:this.$autoNewLine="\n"},this.getNewLineCharacter=function(){switch(this.$newLineMode){case"windows":return"\r\n";case"unix":return"\n";case"auto":return this.$autoNewLine}},this.$autoNewLine="\n",this.$newLineMode="auto",this.setNewLineMode=function(a){if(this.$newLineMode===a)return;this.$newLineMode=a},this.getNewLineMode=function(){return this.$newLineMode},this.isNewLine=function(a){return a=="\r\n"||a=="\r"||a=="\n"},this.getLine=function(a){return this.$lines[a]||""},this.getLines=function(a,b){return this.$lines.slice(a,b+1)},this.getAllLines=function(){return this.getLines(0,this.getLength())},this.getLength=function(){return this.$lines.length},this.getTextRange=function(a){if(a.start.row==a.end.row)return this.$lines[a.start.row].substring(a.start.column,a.end.column);var b=[];return b.push(this.$lines[a.start.row].substring(a.start.column)),b.push.apply(b,this.getLines(a.start.row+1,a.end.row-1)),b.push(this.$lines[a.end.row].substring(0,a.end.column)),b.join(this.getNewLineCharacter())},this.$clipPosition=function(a){var b=this.getLength();return a.row>=b&&(a.row=Math.max(0,b-1),a.column=this.getLine(b-1).length),a},this.insert=function(a,b){if(!b||b.length===0)return a;a=this.$clipPosition(a),this.getLength()<=1&&this.$detectNewLine(b);var c=this.$split(b),d=c.splice(0,1)[0],e=c.length==0?null:c.splice(c.length-1,1)[0];return a=this.insertInLine(a,d),e!==null&&(a=this.insertNewLine(a),a=this.insertLines(a.row,c),a=this.insertInLine(a,e||"")),a},this.insertLines=function(a,b){if(b.length==0)return{row:a,column:0};var c=[a,0];c.push.apply(c,b),this.$lines.splice.apply(this.$lines,c);var d=new f(a,0,a+b.length,0),e={action:"insertLines",range:d,lines:b};return this._emit("change",{data:e}),d.end},this.insertNewLine=function(a){a=this.$clipPosition(a);var b=this.$lines[a.row]||"";this.$lines[a.row]=b.substring(0,a.column),this.$lines.splice(a.row+1,0,b.substring(a.column,b.length));var c={row:a.row+1,column:0},d={action:"insertText",range:f.fromPoints(a,c),text:this.getNewLineCharacter()};return this._emit("change",{data:d}),c},this.insertInLine=function(a,b){if(b.length==0)return a;var c=this.$lines[a.row]||"";this.$lines[a.row]=c.substring(0,a.column)+b+c.substring(a.column);var d={row:a.row,column:a.column+b.length},e={action:"insertText",range:f.fromPoints(a,d),text:b};return this._emit("change",{data:e}),d},this.remove=function(a){a.start=this.$clipPosition(a.start),a.end=this.$clipPosition(a.end);if(a.isEmpty())return a.start;var b=a.start.row,c=a.end.row;if(a.isMultiLine()){var d=a.start.column==0?b:b+1,e=c-1;a.end.column>0&&this.removeInLine(c,0,a.end.column),e>=d&&this.removeLines(d,e),d!=b&&(this.removeInLine(b,a.start.column,this.getLine(b).length),this.removeNewLine(a.start.row))}else this.removeInLine(b,a.start.column,a.end.column);return a.start},this.removeInLine=function(a,b,c){if(b==c)return;var d=new f(a,b,a,c),e=this.getLine(a),g=e.substring(b,c),h=e.substring(0,b)+e.substring(c,e.length);this.$lines.splice(a,1,h);var i={action:"removeText",range:d,text:g};return this._emit("change",{data:i}),d.start},this.removeLines=function(a,b){var c=new f(a,0,b+1,0),d=this.$lines.splice(a,b-a+1),e={action:"removeLines",range:c,nl:this.getNewLineCharacter(),lines:d};return this._emit("change",{data:e}),d},this.removeNewLine=function(a){var b=this.getLine(a),c=this.getLine(a+1),d=new f(a,b.length,a+1,0),e=b+c;this.$lines.splice(a,2,e);var g={action:"removeText",range:d,text:this.getNewLineCharacter()};this._emit("change",{data:g})},this.replace=function(a,b){if(b.length==0&&a.isEmpty())return a.start;if(b==this.getTextRange(a))return a.end;this.remove(a);if(b)var c=this.insert(a.start,b);else c=a.start;return c},this.applyDeltas=function(a){for(var b=0;b<a.length;b++){var c=a[b],d=f.fromPoints(c.range.start,c.range.end);c.action=="insertLines"?this.insertLines(d.start.row,c.lines):c.action=="insertText"?this.insert(d.start,c.text):c.action=="removeLines"?this.removeLines(d.start.row,d.end.row-1):c.action=="removeText"&&this.remove(d)}},this.revertDeltas=function(a){for(var b=a.length-1;b>=0;b--){var c=a[b],d=f.fromPoints(c.range.start,c.range.end);c.action=="insertLines"?this.removeLines(d.start.row,d.end.row-1):c.action=="insertText"?this.remove(d):c.action=="removeLines"?this.insertLines(d.start.row,c.lines):c.action=="removeText"&&this.insert(d.start,c.text)}}}).call(h.prototype),b.Document=h}),define("ace/anchor",["require","exports","module","ace/lib/oop","ace/lib/event_emitter"],function(a,b,c){"use strict";var d=a("./lib/oop"),e=a("./lib/event_emitter").EventEmitter,f=b.Anchor=function(a,b,c){this.document=a,typeof c=="undefined"?this.setPosition(b.row,b.column):this.setPosition(b,c),this.$onChange=this.onChange.bind(this),a.on("change",this.$onChange)};(function(){d.implement(this,e),this.getPosition=function(){return this.$clipPositionToDocument(this.row,this.column)},this.getDocument=function(){return this.document},this.onChange=function(a){var b=a.data,c=b.range;if(c.start.row==c.end.row&&c.start.row!=this.row)return;if(c.start.row>this.row)return;if(c.start.row==this.row&&c.start.column>this.column)return;var d=this.row,e=this.column;b.action==="insertText"?c.start.row===d&&c.start.column<=e?c.start.row===c.end.row?e+=c.end.column-c.start.column:(e-=c.start.column,d+=c.end.row-c.start.row):c.start.row!==c.end.row&&c.start.row<d&&(d+=c.end.row-c.start.row):b.action==="insertLines"?c.start.row<=d&&(d+=c.end.row-c.start.row):b.action=="removeText"?c.start.row==d&&c.start.column<e?c.end.column>=e?e=c.start.column:e=Math.max(0,e-(c.end.column-c.start.column)):c.start.row!==c.end.row&&c.start.row<d?(c.end.row==d&&(e=Math.max(0,e-c.end.column)+c.start.column),d-=c.end.row-c.start.row):c.end.row==d&&(d-=c.end.row-c.start.row,e=Math.max(0,e-c.end.column)+c.start.column):b.action=="removeLines"&&c.start.row<=d&&(c.end.row<=d?d-=c.end.row-c.start.row:(d=c.start.row,e=0)),this.setPosition(d,e,!0)},this.setPosition=function(a,b,c){var d;c?d={row:a,column:b}:d=this.$clipPositionToDocument(a,b);if(this.row==d.row&&this.column==d.column)return;var e={row:this.row,column:this.column};this.row=d.row,this.column=d.column,this._emit("change",{old:e,value:d})},this.detach=function(){this.document.removeEventListener("change",this.$onChange)},this.$clipPositionToDocument=function(a,b){var c={};return a>=this.document.getLength()?(c.row=Math.max(0,this.document.getLength()-1),c.column=this.document.getLine(c.row).length):a<0?(c.row=0,c.column=0):(c.row=a,c.column=Math.min(this.document.getLine(c.row).length,Math.max(0,b))),b<0&&(c.column=0),c}}).call(f.prototype)}),define("ace/background_tokenizer",["require","exports","module","ace/lib/oop","ace/lib/event_emitter"],function(a,b,c){"use strict";var d=a("./lib/oop"),e=a("./lib/event_emitter").EventEmitter,f=function(a,b){this.running=!1,this.lines=[],this.currentLine=0,this.tokenizer=a;var c=this;this.$worker=function(){if(!c.running)return;var a=new Date,b=c.currentLine,d=c.doc,e=0,f=d.getLength();while(c.currentLine<f){c.lines[c.currentLine]=c.$tokenizeRows(c.currentLine,c.currentLine)[0],c.currentLine++,e+=1;if(e%5==0&&new Date-a>20){c.fireUpdateEvent(b,c.currentLine-1),c.running=setTimeout(c.$worker,20);return}}c.running=!1,c.fireUpdateEvent(b,f-1)}};(function(){d.implement(this,e),this.setTokenizer=function(a){this.tokenizer=a,this.lines=[],this.start(0)},this.setDocument=function(a){this.doc=a,this.lines=[],this.stop()},this.fireUpdateEvent=function(a,b){var c={first:a,last:b};this._emit("update",{data:c})},this.start=function(a){this.currentLine=Math.min(a||0,this.currentLine,this.doc.getLength()),this.lines.splice(this.currentLine,this.lines.length),this.stop(),this.running=setTimeout(this.$worker,700)},this.stop=function(){this.running&&clearTimeout(this.running),this.running=!1},this.getTokens=function(a,b){return this.$tokenizeRows(a,b)},this.getState=function(a){return this.$tokenizeRows(a,a)[0].state},this.$tokenizeRows=function(a,b){if(!this.doc||isNaN(a)||isNaN(b))return[{state:"start",tokens:[]}];var c=[],d="start",e=!1;a>0&&this.lines[a-1]?(d=this.lines[a-1].state,e=!0):a==0?(d="start",e=!0):this.lines.length>0&&(d=this.lines[this.lines.length-1].state);var f=this.doc.getLines(a,b);for(var g=a;g<=b;g++)if(!this.lines[g]){var h=this.tokenizer.getLineTokens(f[g-a]||"",d),d=h.state;c.push(h),e&&(this.lines[g]=h)}else{var h=this.lines[g];d=h.state,c.push(h)}return c}}).call(f.prototype),b.BackgroundTokenizer=f}),define("ace/edit_session/folding",["require","exports","module","ace/range","ace/edit_session/fold_line","ace/edit_session/fold","ace/token_iterator"],function(a,b,c){function h(){this.getFoldAt=function(a,b,c){var d=this.getFoldLine(a);if(!d)return null;var e=d.folds;for(var f=0;f<e.length;f++){var g=e[f];if(g.range.contains(a,b)){if(c==1&&g.range.isEnd(a,b))continue;if(c==-1&&g.range.isStart(a,b))continue;return g}}},this.getFoldsInRange=function(a){a=a.clone();var b=a.start,c=a.end,d=this.$foldData,e=[];b.column+=1,c.column-=1;for(var f=0;f<d.length;f++){var g=d[f].range.compareRange(a);if(g==2)continue;if(g==-2)break;var h=d[f].folds;for(var i=0;i<h.length;i++){var j=h[i];g=j.range.compareRange(a);if(g==-2)break;if(g==2)continue;if(g==42)break;e.push(j)}}return e},this.getAllFolds=function(){function c(b){a.push(b);if(!b.subFolds)return;for(var d=0;d<b.subFolds.length;d++)c(b.subFolds[d])}var a=[],b=this.$foldData;for(var d=0;d<b.length;d++)for(var e=0;e<b[d].folds.length;e++)c(b[d].folds[e]);return a},this.getFoldStringAt=function(a,b,c,d){d=d||this.getFoldLine(a);if(!d)return null;var e={end:{column:0}},f,g;for(var h=0;h<d.folds.length;h++){g=d.folds[h];var i=g.range.compareEnd(a,b);if(i==-1){f=this.getLine(g.start.row).substring(e.end.column,g.start.column);break}if(i===0)return null;e=g}return f||(f=this.getLine(g.start.row).substring(e.end.column)),c==-1?f.substring(0,b-e.end.column):c==1?f.substring(b-e.end.column):f},this.getFoldLine=function(a,b){var c=this.$foldData,d=0;b&&(d=c.indexOf(b)),d==-1&&(d=0);for(d;d<c.length;d++){var e=c[d];if(e.start.row<=a&&e.end.row>=a)return e;if(e.end.row>a)return null}return null},this.getNextFoldLine=function(a,b){var c=this.$foldData,d=0;b&&(d=c.indexOf(b)),d==-1&&(d=0);for(d;d<c.length;d++){var e=c[d];if(e.end.row>=a)return e}return null},this.getFoldedRowCount=function(a,b){var c=this.$foldData,d=b-a+1;for(var e=0;e<c.length;e++){var f=c[e],g=f.end.row,h=f.start.row;if(g>=b){h<b&&(h>=a?d-=b-h:d=0);break}g>=a&&(h>=a?d-=g-h:d-=g-a+1)}return d},this.$addFoldLine=function(a){return this.$foldData.push(a),this.$foldData.sort(function(a,b){return a.start.row-b.start.row}),a},this.addFold=function(a,b){var c=this.$foldData,d=!1,g;a instanceof f?g=a:g=new f(b,a),this.$clipRangeToDocument(g.range);var h=g.start.row,i=g.start.column,j=g.end.row,k=g.end.column;if(g.placeholder.length<2)throw"Placeholder has to be at least 2 characters";if(h==j&&k-i<2)throw"The range has to be at least 2 characters width";var l=this.getFoldAt(h,i,1),m=this.getFoldAt(j,k,-1);if(l&&m==l)return l.addSubFold(g);if(l&&!l.range.isStart(h,i)||m&&!m.range.isEnd(j,k))throw"A fold can't intersect already existing fold"+g.range+l.range;var n=this.getFoldsInRange(g.range);n.length>0&&(this.removeFolds(n),g.subFolds=n);for(var o=0;o<c.length;o++){var p=c[o];if(j==p.start.row){p.addFold(g),d=!0;break}if(h==p.end.row){p.addFold(g),d=!0;if(!g.sameRow){var q=c[o+1];if(q&&q.start.row==j){p.merge(q);break}}break}if(j<=p.start.row)break}return d||(p=this.$addFoldLine(new e(this.$foldData,g))),this.$useWrapMode&&this.$updateWrapData(p.start.row,p.start.row),this.$modified=!0,this._emit("changeFold",{data:g}),g},this.addFolds=function(a){a.forEach(function(a){this.addFold(a)},this)},this.removeFold=function(a){var b=a.foldLine,c=b.start.row,d=b.end.row,e=this.$foldData,f=b.folds;if(f.length==1)e.splice(e.indexOf(b),1);else if(b.range.isEnd(a.end.row,a.end.column))f.pop(),b.end.row=f[f.length-1].end.row,b.end.column=f[f.length-1].end.column;else if(b.range.isStart(a.start.row,a.start.column))f.shift(),b.start.row=f[0].start.row,b.start.column=f[0].start.column;else if(a.sameRow)f.splice(f.indexOf(a),1);else{var g=b.split(a.start.row,a.start.column);f=g.folds,f.shift(),g.start.row=f[0].start.row,g.start.column=f[0].start.column}this.$useWrapMode&&this.$updateWrapData(c,d),this.$modified=!0,this._emit("changeFold",{data:a})},this.removeFolds=function(a){var b=[];for(var c=0;c<a.length;c++)b.push(a[c]);b.forEach(function(a){this.removeFold(a)},this),this.$modified=!0},this.expandFold=function(a){this.removeFold(a),a.subFolds.forEach(function(a){this.addFold(a)},this),a.subFolds=[]},this.expandFolds=function(a){a.forEach(function(a){this.expandFold(a)},this)},this.unfold=function(a,b){var c,e;a==null?c=new d(0,0,this.getLength(),0):typeof a=="number"?c=new d(a,0,a,this.getLine(a).length):"row"in a?c=d.fromPoints(a,a):c=a,e=this.getFoldsInRange(c);if(b)this.removeFolds(e);else while(e.length)this.expandFolds(e),e=this.getFoldsInRange(c)},this.isRowFolded=function(a,b){return!!this.getFoldLine(a,b)},this.getRowFoldEnd=function(a,b){var c=this.getFoldLine(a,b);return c?c.end.row:a},this.getFoldDisplayLine=function(a,b,c,d,e){d==null&&(d=a.start.row,e=0),b==null&&(b=a.end.row,c=this.getLine(b).length);var f=this.doc,g="";return a.walk(function(a,b,c,h){if(b<d)return;if(b==d){if(c<e)return;h=Math.max(e,h)}a?g+=a:g+=f.getLine(b).substring(h,c)}.bind(this),b,c),g},this.getDisplayLine=function(a,b,c,d){var e=this.getFoldLine(a);if(!e){var f;return f=this.doc.getLine(a),f.substring(d||0,b||f.length)}return this.getFoldDisplayLine(e,a,b,c,d)},this.$cloneFoldData=function(){var a=[];return a=this.$foldData.map(function(b){var c=b.folds.map(function(a){return a.clone()});return new e(a,c)}),a},this.toggleFold=function(a){var b=this.selection,c=b.getRange(),d,e;if(c.isEmpty()){var f=c.start;d=this.getFoldAt(f.row,f.column);if(d){this.expandFold(d);return}(e=this.findMatchingBracket(f))?c.comparePoint(e)==1?c.end=e:(c.start=e,c.start.column++,c.end.column--):(e=this.findMatchingBracket({row:f.row,column:f.column+1}))?(c.comparePoint(e)==1?c.end=e:c.start=e,c.start.column++):c=this.getCommentFoldRange(f.row,f.column)||c}else{var g=this.getFoldsInRange(c);if(a&&g.length){this.expandFolds(g);return}g.length==1&&(d=g[0])}d||(d=this.getFoldAt(c.start.row,c.start.column));if(d&&d.range.toString()==c.toString()){this.expandFold(d);return}var h="...";if(!c.isMultiLine()){h=this.getTextRange(c);if(h.length<4)return;h=h.trim().substring(0,2)+".."}this.addFold(h,c)},this.getCommentFoldRange=function(a,b){var c=new g(this,a,b),e=c.getCurrentToken();if(e&&/^comment|string/.test(e.type)){var f=new d,h=new RegExp(e.type.replace(/\..*/,"\\."));do e=c.stepBackward();while(e&&h.test(e.type));c.stepForward(),f.start.row=c.getCurrentTokenRow(),f.start.column=c.getCurrentTokenColumn()+2,c=new g(this,a,b);do e=c.stepForward();while(e&&h.test(e.type));return e=c.stepBackward(),f.end.row=c.getCurrentTokenRow(),f.end.column=c.getCurrentTokenColumn()+e.value.length,f}},this.foldAll=function(a,b){var c=this.foldWidgets;b=b||this.getLength();for(var d=a||0;d<b;d++){c[d]==null&&(c[d]=this.getFoldWidget(d));if(c[d]!="start")continue;var e=this.getFoldWidgetRange(d);if(e&&e.end.row<b)try{this.addFold("...",e)}catch(f){}}},this.$foldStyles={manual:1,markbegin:1,markbeginend:1},this.$foldStyle="markbegin",this.setFoldStyle=function(a){if(!this.$foldStyles[a])throw new Error("invalid fold style: "+a+"["+Object.keys(this.$foldStyles).join(", ")+"]");if(this.$foldStyle==a)return;this.$foldStyle=a,a=="manual"&&this.unfold();var b=this.$foldMode;this.$setFolding(null),this.$setFolding(b)},this.$setFolding=function(a){if(this.$foldMode==a)return;this.$foldMode=a,this.removeListener("change",this.$updateFoldWidgets),this._emit("changeAnnotation");if(!a||this.$foldStyle=="manual"){this.foldWidgets=null;return}this.foldWidgets=[],this.getFoldWidget=a.getFoldWidget.bind(a,this,this.$foldStyle),this.getFoldWidgetRange=a.getFoldWidgetRange.bind(a,this,this.$foldStyle),this.$updateFoldWidgets=this.updateFoldWidgets.bind(this),this.on("change",this.$updateFoldWidgets)},this.onFoldWidgetClick=function(a,b){var c=this.getFoldWidget(a),d=this.getLine(a),e=b.shiftKey,f=e||b.ctrlKey||b.altKey||b.metaKey,g;c=="end"?g=this.getFoldAt(a,0,-1):g=this.getFoldAt(a,d.length,1);if(g){f?this.removeFold(g):this.expandFold(g);return}var h=this.getFoldWidgetRange(a);if(h){if(!h.isMultiLine()){g=this.getFoldAt(h.start.row,h.start.column,1);if(g&&h.isEqual(g.range)){this.removeFold(g);return}}e||this.addFold("...",h),f&&this.foldAll(h.start.row+1,h.end.row)}else f&&this.foldAll(a+1,this.getLength()),b.target.className+=" invalid"},this.updateFoldWidgets=function(a){var b=a.data,c=b.range,d=c.start.row,e=c.end.row-d;if(e===0)this.foldWidgets[d]=null;else if(b.action=="removeText"||b.action=="removeLines")this.foldWidgets.splice(d,e+1,null);else{var f=Array(e+1);f.unshift(d,1),this.foldWidgets.splice.apply(this.foldWidgets,f)}}}"use strict";var d=a("../range").Range,e=a("./fold_line").FoldLine,f=a("./fold").Fold,g=a("../token_iterator").TokenIterator;b.Folding=h}),define("ace/edit_session/fold_line",["require","exports","module","ace/range"],function(a,b,c){function e(a,b){this.foldData=a,Array.isArray(b)?this.folds=b:b=this.folds=[b];var c=b[b.length-1];this.range=new d(b[0].start.row,b[0].start.column,c.end.row,c.end.column),this.start=this.range.start,this.end=this.range.end,this.folds.forEach(function(a){a.setFoldLine(this)},this)}"use strict";var d=a("../range").Range;(function(){this.shiftRow=function(a){this.start.row+=a,this.end.row+=a,this.folds.forEach(function(b){b.start.row+=a,b.end.row+=a})},this.addFold=function(a){if(a.sameRow){if(a.start.row<this.startRow||a.endRow>this.endRow)throw"Can't add a fold to this FoldLine as it has no connection";this.folds.push(a),this.folds.sort(function(a,b){return-a.range.compareEnd(b.start.row,b.start.column)}),this.range.compareEnd(a.start.row,a.start.column)>0?(this.end.row=a.end.row,this.end.column=a.end.column):this.range.compareStart(a.end.row,a.end.column)<0&&(this.start.row=a.start.row,this.start.column=a.start.column)}else if(a.start.row==this.end.row)this.folds.push(a),this.end.row=a.end.row,this.end.column=a.end.column;else{if(a.end.row!=this.start.row)throw"Trying to add fold to FoldRow that doesn't have a matching row";this.folds.unshift(a),this.start.row=a.start.row,this.start.column=a.start.column}a.foldLine=this},this.containsRow=function(a){return a>=this.start.row&&a<=this.end.row},this.walk=function(a,b,c){var d=0,e=this.folds,f,g,h,i=!0;b==null&&(b=this.end.row,c=this.end.column);for(var j=0;j<e.length;j++){f=e[j],g=f.range.compareStart(b,c);if(g==-1){a(null,b,c,d,i);return}h=a(null,f.start.row,f.start.column,d,i),h=!h&&a(f.placeholder,f.start.row,f.start.column,d);if(h||g==0)return;i=!f.sameRow,d=f.end.column}a(null,b,c,d,i)},this.getNextFoldTo=function(a,b){var c,d;for(var e=0;e<this.folds.length;e++){c=this.folds[e],d=c.range.compareEnd(a,b);if(d==-1)return{fold:c,kind:"after"};if(d==0)return{fold:c,kind:"inside"}}return null},this.addRemoveChars=function(a,b,c){var d=this.getNextFoldTo(a,b),e,f;if(d){e=d.fold;if(d.kind=="inside"&&e.start.column!=b&&e.start.row!=a)throw"Moving characters inside of a fold should never be reached";if(e.start.row==a){f=this.folds;var g=f.indexOf(e);g==0&&(this.start.column+=c);for(g;g<f.length;g++){e=f[g],e.start.column+=c;if(!e.sameRow)return;e.end.column+=c}this.end.column+=c}}},this.split=function(a,b){var c=this.getNextFoldTo(a,b).fold,d=this.folds,f=this.foldData;if(!c)return null;var g=d.indexOf(c),h=d[g-1];this.end.row=h.end.row,this.end.column=h.end.column,d=d.splice(g,d.length-g);var i=new e(f,d);return f.splice(f.indexOf(this)+1,0,i),i},this.merge=function(a){var b=a.folds;for(var c=0;c<b.length;c++)this.addFold(b[c]);var d=this.foldData;d.splice(d.indexOf(a),1)},this.toString=function(){var a=[this.range.toString()+": ["];return this.folds.forEach(function(b){a.push("  "+b.toString())}),a.push("]"),a.join("\n")},this.idxToPosition=function(a){var b=0,c;for(var d=0;d<this.folds.length;d++){var c=this.folds[d];a-=c.start.column-b;if(a<0)return{row:c.start.row,column:c.start.column+a};a-=c.placeholder.length;if(a<0)return c.start;b=c.end.column}return{row:this.end.row,column:this.end.column+a}}}).call(e.prototype),b.FoldLine=e}),define("ace/edit_session/fold",["require","exports","module"],function(a,b,c){"use strict";var d=b.Fold=function(a,b){this.foldLine=null,this.placeholder=b,this.range=a,this.start=a.start,this.end=a.end,this.sameRow=a.start.row==a.end.row,this.subFolds=[]};(function(){this.toString=function(){return'"'+this.placeholder+'" '+this.range.toString()},this.setFoldLine=function(a){this.foldLine=a,this.subFolds.forEach(function(b){b.setFoldLine(a)})},this.clone=function(){var a=this.range.clone(),b=new d(a,this.placeholder);return this.subFolds.forEach(function(a){b.subFolds.push(a.clone())}),b},this.addSubFold=function(a){if(this.range.isEqual(a))return this;if(!this.range.containsRange(a))throw"A fold can't intersect already existing fold"+a.range+this.range;var b=a.range.start.row,c=a.range.start.column;for(var d=0,e=-1;d<this.subFolds.length;d++){e=this.subFolds[d].range.compare(b,c);if(e!=1)break}var f=this.subFolds[d];if(e==0)return f.addSubFold(a);var b=a.range.end.row,c=a.range.end.column;for(var g=d,e=-1;g<this.subFolds.length;g++){e=this.subFolds[g].range.compare(b,c);if(e!=1)break}var h=this.subFolds[g];if(e==0)throw"A fold can't intersect already existing fold"+a.range+this.range;var i=this.subFolds.splice(d,g-d,a);return a.setFoldLine(this.foldLine),a}}).call(d.prototype)}),define("ace/token_iterator",["require","exports","module"],function(a,b,c){"use strict";var d=function(a,b,c){this.$session=a,this.$row=b,this.$rowTokens=a.getTokens(b,b)[0].tokens;var d=a.getTokenAt(b,c);this.$tokenIndex=d?d.index:-1};(function(){this.stepBackward=function(){this.$tokenIndex-=1;while(this.$tokenIndex<0){this.$row-=1;if(this.$row<0)return this.$row=0,null;this.$rowTokens=this.$session.getTokens(this.$row,this.$row)[0].tokens,this.$tokenIndex=this.$rowTokens.length-1}return this.$rowTokens[this.$tokenIndex]},this.stepForward=function(){var a=this.$session.getLength();this.$tokenIndex+=1;while(this.$tokenIndex>=this.$rowTokens.length){this.$row+=1;if(this.$row>=a)return this.$row=a-1,null;this.$rowTokens=this.$session.getTokens(this.$row,this.$row)[0].tokens,this.$tokenIndex=0}return this.$rowTokens[this.$tokenIndex]},this.getCurrentToken=function(){return this.$rowTokens[this.$tokenIndex]},this.getCurrentTokenRow=function(){return this.$row},this.getCurrentTokenColumn=function(){var a=this.$rowTokens,b=this.$tokenIndex,c=a[b].start;if(c!==undefined)return c;c=0;while(b>0)b-=1,c+=a[b].value.length;return c}}).call(d.prototype),b.TokenIterator=d}),define("ace/edit_session/bracket_match",["require","exports","module","ace/token_iterator"],function(a,b,c){function e(){this.findMatchingBracket=function(a){if(a.column==0)return null;var b=this.getLine(a.row).charAt(a.column-1);if(b=="")return null;var c=b.match(/([\(\[\{])|([\)\]\}])/);return c?c[1]?this.$findClosingBracket(c[1],a):this.$findOpeningBracket(c[2],a):null},this.$brackets={")":"(","(":")","]":"[","[":"]","{":"}","}":"{"},this.$findOpeningBracket=function(a,b){var c=this.$brackets[a],e=1,f=new d(this,b.row,b.column),g=f.getCurrentToken();if(!g)return null;var h=new RegExp("(\\.?"+g.type.replace(".","|").replace("rparen","lparen|rparen")+")+"),i=b.column-f.getCurrentTokenColumn()-2,j=g.value;for(;;){while(i>=0){var k=j.charAt(i);if(k==c){e-=1;if(e==0)return{row:f.getCurrentTokenRow(),column:i+f.getCurrentTokenColumn()}}else k==a&&(e+=1);i-=1}do g=f.stepBackward();while(g&&!h.test(g.type));if(g==null)break;j=g.value,i=j.length-1}return null},this.$findClosingBracket=function(a,b){var c=this.$brackets[a],e=1,f=new d(this,b.row,b.column),g=f.getCurrentToken();if(!g)return null;var h=new RegExp("(\\.?"+g.type.replace(".","|").replace("lparen","lparen|rparen")+")+"),i=b.column-f.getCurrentTokenColumn();for(;;){var j=g.value,k=j.length;while(i<k){var l=j.charAt(i);if(l==c){e-=1;if(e==0)return{row:f.getCurrentTokenRow(),column:i+f.getCurrentTokenColumn()}}else l==a&&(e+=1);i+=1}do g=f.stepForward();while(g&&!h.test(g.type));if(g==null)break;i=0}return null}}"use strict";var d=a("../token_iterator").TokenIterator;b.BracketMatch=e}),define("ace/search",["require","exports","module","ace/lib/lang","ace/lib/oop","ace/range"],function(a,b,c){"use strict";var d=a("./lib/lang"),e=a("./lib/oop"),f=a("./range").Range,g=function(){this.$options={needle:"",backwards:!1,wrap:!1,caseSensitive:!1,wholeWord:!1,scope:g.ALL,regExp:!1}};g.ALL=1,g.SELECTION=2,function(){this.set=function(a){return e.mixin(this.$options,a),this},this.getOptions=function(){return d.copyObject(this.$options)},this.find=function(a){if(!this.$options.needle)return null;if(this.$options.backwards)var b=this.$backwardMatchIterator(a);else b=this.$forwardMatchIterator(a);var c=null;return b.forEach(function(a){return c=a,!0}),c},this.findAll=function(a){var b=this.$options;if(!b.needle)return[];if(b.backwards)var c=this.$backwardMatchIterator(a);else c=this.$forwardMatchIterator(a);var d=!b.start&&b.wrap&&b.scope==g.ALL;d&&(b.start={row:0,column:0});var e=[];return c.forEach(function(a){e.push(a)}),d&&(b.start=null),e},this.replace=function(a,b){var c=this.$assembleRegExp(),d=c.exec(a);return d&&d[0].length==a.length?this.$options.regExp?a.replace(c,b):b:null},this.$forwardMatchIterator=function(a){var b=this.$assembleRegExp(),c=this;return{forEach:function(d){c.$forwardLineIterator(a).forEach(function(a,e,f){e&&(a=a.substring(e));var g=[];a.replace(b,function(a){var b=arguments[arguments.length-2];return g.push({str:a,offset:e+b}),a});for(var h=0;h<g.length;h++){var i=g[h],j=c.$rangeFromMatch(f,i.offset,i.str.length);if(d(j))return!0}})}}},this.$backwardMatchIterator=function(a){var b=this.$assembleRegExp(),c=this;return{forEach:function(d){c.$backwardLineIterator(a).forEach(function(a,e,f){e&&(a=a.substring(e));var g=[];a.replace(b,function(a,b){return g.push({str:a,offset:e+b}),a});for(var h=g.length-1;h>=0;h--){var i=g[h],j=c.$rangeFromMatch(f,i.offset,i.str.length);if(d(j))return!0}})}}},this.$rangeFromMatch=function(a,b,c){return new f(a,b,a,b+c)},this.$assembleRegExp=function(){if(this.$options.regExp)var a=this.$options.needle;else a=d.escapeRegExp(this.$options.needle);this.$options.wholeWord&&(a="\\b"+a+"\\b");var b="g";this.$options.caseSensitive||(b+="i");var c=new RegExp(a,b);return c},this.$forwardLineIterator=function(a){function k(e){var f=a.getLine(e);return b&&e==c.end.row&&(f=f.substring(0,c.end.column)),j&&e==d.row&&(f=f.substring(0,d.column)),f}var b=this.$options.scope==g.SELECTION,c=this.$options.range||a.getSelection().getRange(),d=this.$options.start||c[b?"start":"end"],e=b?c.start.row:0,f=b?c.start.column:0,h=b?c.end.row:a.getLength()-1,i=this.$options.wrap,j=!1;return{forEach:function(a){var b=d.row,c=k(b),g=d.column,l=!1;j=!1;while(!a(c,g,b)){if(l)return;b++,g=0;if(b>h){if(!i)return;b=e,g=f,j=!0}b==d.row&&(l=!0),c=k(b)}}}},this.$backwardLineIterator=function(a){var b=this.$options.scope==g.SELECTION,c=this.$options.range||a.getSelection().getRange(),d=this.$options.start||c[b?"end":"start"],e=b?c.start.row:0,f=b?c.start.column:0,h=b?c.end.row:a.getLength()-1,i=this.$options.wrap;return{forEach:function(g){var j=d.row,k=a.getLine(j).substring(0,d.column),l=0,m=!1,n=!1;while(!g(k,l,j)){if(m)return;j--,l=0;if(j<e){if(!i)return;j=h,n=!0}j==d.row&&(m=!0),k=a.getLine(j),b&&(j==e?l=f:j==h&&(k=k.substring(0,c.end.column))),n&&j==d.row&&(l=d.column)}}}}}.call(g.prototype),b.Search=g}),define("ace/commands/command_manager",["require","exports","module","ace/lib/oop","ace/keyboard/hash_handler","ace/lib/event_emitter"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("../keyboard/hash_handler").HashHandler,f=a("../lib/event_emitter").EventEmitter,g=function(a,b){this.platform=a,this.commands={},this.commmandKeyBinding={},this.addCommands(b),this.setDefaultHandler("exec",function(a){a.command.exec(a.editor,a.args||{})})};d.inherits(g,e),function(){d.implement(this,f),this.exec=function(a,b,c){return typeof a=="string"&&(a=this.commands[a]),a?b&&b.$readOnly&&!a.readOnly?!1:(this._emit("exec",{editor:b,command:a,args:c}),!0):!1},this.toggleRecording=function(){if(this.$inReplay)return;return this.recording?(this.macro.pop(),this.removeEventListener("exec",this.$addCommandToMacro),this.macro.length||(this.macro=this.oldMacro),this.recording=!1):(this.$addCommandToMacro||(this.$addCommandToMacro=function(a){this.macro.push([a.command,a.args])}.bind(this)),this.oldMacro=this.macro,this.macro=[],this.on("exec",this.$addCommandToMacro),this.recording=!0)},this.replay=function(a){if(this.$inReplay||!this.macro)return;if(this.recording)return this.toggleRecording();try{this.$inReplay=!0,this.macro.forEach(function(b){typeof b=="string"?this.exec(b,a):this.exec(b[0],a,b[1])},this)}finally{this.$inReplay=!1}},this.trimMacro=function(a){return a.map(function(a){return typeof a[0]!="string"&&(a[0]=a[0].name),a[1]||(a=a[0]),a})}}.call(g.prototype),b.CommandManager=g}),define("ace/keyboard/hash_handler",["require","exports","module","ace/lib/keys"],function(a,b,c){function e(a,b){this.platform=b,this.commands={},this.commmandKeyBinding={},this.addCommands(a)}"use strict";var d=a("../lib/keys");(function(){function a(a,c,e){var f,g=0,h=b(a.toLowerCase());for(var i=0,j=h.length;i<j;i++)d.KEY_MODS[h[i]]?g|=d.KEY_MODS[h[i]]:f=h[i]||"-";return{key:f,hashId:g}}function b(a){return a.trim().split(new RegExp("[\\s ]*\\-[\\s ]*","g"),999)}this.addCommand=function(a){this.commands[a.name]&&this.removeCommand(a),this.commands[a.name]=a,a.bindKey&&this._buildKeyHash(a)},this.removeCommand=function(a){var b=typeof a=="string"?a:a.name;a=this.commands[b],delete this.commands[b];var c=this.commmandKeyBinding;for(var d in c)for(var e in c[d])c[d][e]==a&&delete c[d][e]},this.addCommands=function(a){a&&Object.keys(a).forEach(function(b){var c=a[b];if(typeof c=="string")return this.bindKey(c,b);typeof c=="function"&&(c={exec:c}),c.name||(c.name=b),this.addCommand(c)},this)},this.removeCommands=function(a){Object.keys(a).forEach(function(b){this.removeCommand(a[b])},this)},this.bindKey=function(b,c){if(!b)return;var d=this.commmandKeyBinding;b.split("|").forEach(function(b){var e=a(b,c),f=e.hashId;(d[f]||(d[f]={}))[e.key]=c})},this.bindKeys=function(a){Object.keys(a).forEach(function(b){this.bindKey(b,a[b])},this)},this._buildKeyHash=function(a){var b=a.bindKey;if(!b)return;var c=typeof b=="string"?b:b[this.platform];this.bindKey(c,a)},this.findKeyCommand=function(b,c){var d=this.commmandKeyBinding;return d[b]&&d[b][c.toLowerCase()]},this.handleKeyboard=function(a,b,c,d){return{command:this.findKeyCommand(b,c)}}}).call(e.prototype),b.HashHandler=e}),define("ace/undomanager",["require","exports","module"],function(a,b,c){"use strict";var d=function(){this.reset()};(function(){this.execute=function(a){var b=a.args[0];this.$doc=a.args[1],this.$undoStack.push(b),this.$redoStack=[]},this.undo=function(a){var b=this.$undoStack.pop(),c=null;return b&&(c=this.$doc.undoChanges(b,a),this.$redoStack.push(b)),c},this.redo=function(a){var b=this.$redoStack.pop(),c=null;return b&&(c=this.$doc.redoChanges(b,a),this.$undoStack.push(b)),c},this.reset=function(){this.$undoStack=[],this.$redoStack=[]},this.hasUndo=function(){return this.$undoStack.length>0},this.hasRedo=function(){return this.$redoStack.length>0}}).call(d.prototype),b.UndoManager=d}),define("ace/virtual_renderer",["require","exports","module","ace/lib/oop","ace/lib/dom","ace/lib/event","ace/lib/useragent","ace/config","ace/lib/net","ace/layer/gutter","ace/layer/marker","ace/layer/text","ace/layer/cursor","ace/scrollbar","ace/renderloop","ace/lib/event_emitter","text!ace/css/editor.css"],function(a,b,c){"use strict";var d=a("./lib/oop"),e=a("./lib/dom"),f=a("./lib/event"),g=a("./lib/useragent"),h=a("./config"),i=a("./lib/net"),j=a("./layer/gutter").Gutter,k=a("./layer/marker").Marker,l=a("./layer/text").Text,m=a("./layer/cursor").Cursor,n=a("./scrollbar").ScrollBar,o=a("./renderloop").RenderLoop,p=a("./lib/event_emitter").EventEmitter,q=a("text!./css/editor.css");e.importCssString(q,"ace_editor");var r=function(a,b){var c=this;this.container=a,e.addCssClass(a,"ace_editor"),this.setTheme(b),this.$gutter=e.createElement("div"),this.$gutter.className="ace_gutter",this.container.appendChild(this.$gutter),this.scroller=e.createElement("div"),this.scroller.className="ace_scroller",this.container.appendChild(this.scroller),this.content=e.createElement("div"),this.content.className="ace_content",this.scroller.appendChild(this.content),this.$gutterLayer=new j(this.$gutter),this.$gutterLayer.on("changeGutterWidth",this.onResize.bind(this,!0)),this.$markerBack=new k(this.content);var d=this.$textLayer=new l(this.content);this.canvas=d.element,this.$markerFront=new k(this.content),this.characterWidth=d.getCharacterWidth(),this.lineHeight=d.getLineHeight(),this.$cursorLayer=new m(this.content),this.$cursorPadding=8,this.$horizScroll=!0,this.$horizScrollAlwaysVisible=!0,this.$animatedScroll=!1,this.scrollBar=new n(a),this.scrollBar.addEventListener("scroll",function(a){c.session.setScrollTop(a.data)}),this.scrollTop=0,this.scrollLeft=0,f.addListener(this.scroller,"scroll",function(){var a=c.scroller.scrollLeft;c.scrollLeft=a,c.session.setScrollLeft(a),a==0?c.$gutter.className="ace_gutter":c.$gutter.className="ace_gutter horscroll"}),this.cursorPos={row:0,column:0},this.$textLayer.addEventListener("changeCharacterSize",function(){c.characterWidth=d.getCharacterWidth(),c.lineHeight=d.getLineHeight(),c.$updatePrintMargin(),c.onResize(!0),c.$loop.schedule(c.CHANGE_FULL)}),this.$size={width:0,height:0,scrollerHeight:0,scrollerWidth:0},this.layerConfig={width:1,padding:0,firstRow:0,firstRowScreen:0,lastRow:0,lineHeight:1,characterWidth:1,minHeight:1,maxHeight:1,offset:0,height:1},this.$loop=new o(this.$renderChanges.bind(this),this.container.ownerDocument.defaultView),this.$loop.schedule(this.CHANGE_FULL),this.setPadding(4),this.$updatePrintMargin()};(function(){this.showGutter=!0,this.CHANGE_CURSOR=1,this.CHANGE_MARKER=2,this.CHANGE_GUTTER=4,this.CHANGE_SCROLL=8,this.CHANGE_LINES=16,this.CHANGE_TEXT=32,this.CHANGE_SIZE=64,this.CHANGE_MARKER_BACK=128,this.CHANGE_MARKER_FRONT=256,this.CHANGE_FULL=512,this.CHANGE_H_SCROLL=1024,d.implement(this,p),this.setSession=function(a){this.session=a,this.$cursorLayer.setSession(a),this.$markerBack.setSession(a),this.$markerFront.setSession(a),this.$gutterLayer.setSession(a),this.$textLayer.setSession(a),this.$loop.schedule(this.CHANGE_FULL)},this.updateLines=function(a,b){b===undefined&&(b=Infinity),this.$changedLines?(this.$changedLines.firstRow>a&&(this.$changedLines.firstRow=a),this.$changedLines.lastRow<b&&(this.$changedLines.lastRow=b)):this.$changedLines={firstRow:a,lastRow:b},this.$loop.schedule(this.CHANGE_LINES)},this.updateText=function(){this.$loop.schedule(this.CHANGE_TEXT)},this.updateFull=function(){this.$loop.schedule(this.CHANGE_FULL)},this.updateFontSize=function(){this.$textLayer.checkForSizeChanges()},this.onResize=function(a){var b=this.CHANGE_SIZE,c=this.$size,d=e.getInnerHeight(this.container);if(a||c.height!=d)c.height=d,this.scroller.style.height=d+"px",c.scrollerHeight=this.scroller.clientHeight,this.scrollBar.setHeight(c.scrollerHeight),this.session&&(this.session.setScrollTop(this.getScrollTop()),b|=this.CHANGE_FULL);var f=e.getInnerWidth(this.container);if(a||c.width!=f){c.width=f;var g=this.showGutter?this.$gutter.offsetWidth:0;this.scroller.style.left=g+"px",c.scrollerWidth=Math.max(0,f-g-this.scrollBar.getWidth()),this.scroller.style.width=c.scrollerWidth+"px";if(this.session.getUseWrapMode()&&this.adjustWrapLimit()||a)b|=this.CHANGE_FULL}this.$loop.schedule(b)},this.adjustWrapLimit=function(){var a=this.$size.scrollerWidth-this.$padding*2,b=Math.floor(a/this.characterWidth);return this.session.adjustWrapLimit(b)},this.setAnimatedScroll=function(a){this.$animatedScroll=a},this.getAnimatedScroll=function(){return this.$animatedScroll},this.setShowInvisibles=function(a){this.$textLayer.setShowInvisibles(a)&&this.$loop.schedule(this.CHANGE_TEXT)},this.getShowInvisibles=function(){return this.$textLayer.showInvisibles},this.$showPrintMargin=!0,this.setShowPrintMargin=function(a){this.$showPrintMargin=a,this.$updatePrintMargin()},this.getShowPrintMargin=function(){return this.$showPrintMargin},this.$printMarginColumn=80,this.setPrintMarginColumn=function(a){this.$printMarginColumn=a,this.$updatePrintMargin()},this.getPrintMarginColumn=function(){return this.$printMarginColumn},this.getShowGutter=function(){return this.showGutter},this.setShowGutter=function(a){if(this.showGutter===a)return;this.$gutter.style.display=a?"block":"none",this.showGutter=a,this.onResize(!0)},this.$updatePrintMargin=function(){var a;if(!this.$showPrintMargin&&!this.$printMarginEl)return;this.$printMarginEl||(a=e.createElement("div"),a.className="ace_print_margin_layer",this.$printMarginEl=e.createElement("div"),this.$printMarginEl.className="ace_print_margin",a.appendChild(this.$printMarginEl),this.content.insertBefore(a,this.$textLayer.element));var b=this.$printMarginEl.style;b.left=this.characterWidth*this.$printMarginColumn+this.$padding+"px",b.visibility=this.$showPrintMargin?"visible":"hidden"},this.getContainerElement=function(){return this.container},this.getMouseEventTarget=function(){return this.content},this.getTextAreaContainer=function(){return this.container},this.moveTextAreaToCursor=function(a){if(g.isIE)return;if(this.layerConfig.lastRow===0)return;var b=this.$cursorLayer.getPixelPosition();if(!b)return;var c=this.content.getBoundingClientRect(),d=this.layerConfig.offset;a.style.left=c.left+b.left+"px",a.style.top=c.top+b.top-this.scrollTop+d+"px"},this.getFirstVisibleRow=function(){return this.layerConfig.firstRow},this.getFirstFullyVisibleRow=function(){return this.layerConfig.firstRow+(this.layerConfig.offset===0?0:1)},this.getLastFullyVisibleRow=function(){var a=Math.floor((this.layerConfig.height+this.layerConfig.offset)/this.layerConfig.lineHeight);return this.layerConfig.firstRow-1+a},this.getLastVisibleRow=function(){return this.layerConfig.lastRow},this.$padding=null,this.setPadding=function(a){this.$padding=a,this.$textLayer.setPadding(a),this.$cursorLayer.setPadding(a),this.$markerFront.setPadding(a),this.$markerBack.setPadding(a),this.$loop.schedule(this.CHANGE_FULL),this.$updatePrintMargin()},this.getHScrollBarAlwaysVisible=function(){return this.$horizScrollAlwaysVisible},this.setHScrollBarAlwaysVisible=function(a){this.$horizScrollAlwaysVisible!=a&&(this.$horizScrollAlwaysVisible=a,(!this.$horizScrollAlwaysVisible||!this.$horizScroll)&&this.$loop.schedule(this.CHANGE_SCROLL))},this.$updateScrollBar=function(){this.scrollBar.setInnerHeight(this.layerConfig.maxHeight),this.scrollBar.setScrollTop(this.scrollTop)},this.$renderChanges=function(a){if(!a||!this.session||!this.container.offsetWidth)return;(a&this.CHANGE_FULL||a&this.CHANGE_SIZE||a&this.CHANGE_TEXT||a&this.CHANGE_LINES||a&this.CHANGE_SCROLL)&&this.$computeLayerConfig();if(a&this.CHANGE_H_SCROLL){this.scroller.scrollLeft=this.scrollLeft;var b=this.scroller.scrollLeft;this.scrollLeft=b,this.session.setScrollLeft(b)}if(a&this.CHANGE_FULL){this.$textLayer.checkForSizeChanges(),this.$updateScrollBar(),this.$textLayer.update(this.layerConfig),this.showGutter&&this.$gutterLayer.update(this.layerConfig),this.$markerBack.update(this.layerConfig),this.$markerFront.update(this.layerConfig),this.$cursorLayer.update(this.layerConfig);return}if(a&this.CHANGE_SCROLL){this.$updateScrollBar(),a&this.CHANGE_TEXT||a&this.CHANGE_LINES?this.$textLayer.update(this.layerConfig):this.$textLayer.scrollLines(this.layerConfig),this.showGutter&&this.$gutterLayer.update(this.layerConfig),this.$markerBack.update(this.layerConfig),this.$markerFront.update(this.layerConfig),this.$cursorLayer.update(this.layerConfig);return}a&this.CHANGE_TEXT?(this.$textLayer.update(this.layerConfig),this.showGutter&&this.$gutterLayer.update(this.layerConfig)):a&this.CHANGE_LINES?this.$updateLines()&&(this.$updateScrollBar(),this.showGutter&&this.$gutterLayer.update(this.layerConfig)):a&this.CHANGE_GUTTER&&this.showGutter&&this.$gutterLayer.update(this.layerConfig),a&this.CHANGE_CURSOR&&this.$cursorLayer.update(this.layerConfig),a&(this.CHANGE_MARKER|this.CHANGE_MARKER_FRONT)&&this.$markerFront.update(this.layerConfig),a&(this.CHANGE_MARKER|this.CHANGE_MARKER_BACK)&&this.$markerBack.update(this.layerConfig),a&this.CHANGE_SIZE&&this.$updateScrollBar()},this.$computeLayerConfig=function(){var a=this.session,b=this.scrollTop%this.lineHeight,c=this.$size.scrollerHeight+this.lineHeight,d=this.$getLongestLine(),e=this.$horizScrollAlwaysVisible||this.$size.scrollerWidth-d<0,f=this.$horizScroll!==e;this.$horizScroll=e,f&&(this.scroller.style.overflowX=e?"scroll":"hidden",e||this.session.setScrollLeft(0));var g=this.session.getScreenLength()*this.lineHeight;this.session.setScrollTop(Math.max(0,Math.min(this.scrollTop,g-this.$size.scrollerHeight)));var h=Math.ceil(c/this.lineHeight)-1,i=Math.max(0,Math.round((this.scrollTop-b)/this.lineHeight)),j=i+h,k,l,m={lineHeight:this.lineHeight};i=a.screenToDocumentRow(i,0);var n=a.getFoldLine(i);n&&(i=n.start.row),k=a.documentToScreenRow(i,0),l=a.getRowHeight(m,i),j=Math.min(a.screenToDocumentRow(j,0),a.getLength()-1),c=this.$size.scrollerHeight+a.getRowHeight(m,j)+l,b=this.scrollTop-k*this.lineHeight,this.layerConfig={width:d,padding:this.$padding,firstRow:i,firstRowScreen:k,lastRow:j,lineHeight:this.lineHeight,characterWidth:this.characterWidth,minHeight:c,maxHeight:g,offset:b,height:this.$size.scrollerHeight},this.$gutterLayer.element.style.marginTop=-b+"px",this.content.style.marginTop=-b+"px",this.content.style.width=d+2*this.$padding+"px",this.content.style.height=c+"px",f&&this.onResize(!0)},this.$updateLines=function(){var a=this.$changedLines.firstRow,b=this.$changedLines.lastRow;this.$changedLines=null;var c=this.layerConfig;if(c.width!=this.$getLongestLine())return this.$textLayer.update(c);if(a>c.lastRow+1)return;if(b<c.firstRow)return;if(b===Infinity){this.showGutter&&this.$gutterLayer.update(c),this.$textLayer.update(c);return}return this.$textLayer.updateLines(c,a,b),!0},this.$getLongestLine=function(){var a=this.session.getScreenWidth();return this.$textLayer.showInvisibles&&(a+=1),Math.max(this.$size.scrollerWidth-2*this.$padding,Math.round(a*this.characterWidth))},this.updateFrontMarkers=function(){this.$markerFront.setMarkers(this.session.getMarkers(!0)),this.$loop.schedule(this.CHANGE_MARKER_FRONT)},this.updateBackMarkers=function(){this.$markerBack.setMarkers(this.session.getMarkers()),this.$loop.schedule(this.CHANGE_MARKER_BACK)},this.addGutterDecoration=function(a,b){this.$gutterLayer.addGutterDecoration(a,b),this.$loop.schedule(this.CHANGE_GUTTER)},this.removeGutterDecoration=function(a,b){this.$gutterLayer.removeGutterDecoration(a,b),this.$loop.schedule(this.CHANGE_GUTTER)},this.setBreakpoints=function(a){this.$gutterLayer.setBreakpoints(a),this.$loop.schedule(this.CHANGE_GUTTER)},this.setAnnotations=function(a){this.$gutterLayer.setAnnotations(a),this.$loop.schedule(this.CHANGE_GUTTER)},this.updateCursor=function(){this.$loop.schedule(this.CHANGE_CURSOR)},this.hideCursor=function(){this.$cursorLayer.hideCursor()},this.showCursor=function(){this.$cursorLayer.showCursor()},this.scrollSelectionIntoView=function(a,b){this.scrollCursorIntoView(a),this.scrollCursorIntoView(b)},this.scrollCursorIntoView=function(a){if(this.$size.scrollerHeight===0)return;var b=this.$cursorLayer.getPixelPosition(a),c=b.left,d=b.top;this.scrollTop>d&&this.session.setScrollTop(d),this.scrollTop+this.$size.scrollerHeight<d+this.lineHeight&&this.session.setScrollTop(d+this.lineHeight-this.$size.scrollerHeight);var e=this.scrollLeft;e>c&&(c<this.$padding+2*this.layerConfig.characterWidth&&(c=0),this.session.setScrollLeft(c)),e+this.$size.scrollerWidth<c+this.characterWidth&&this.session.setScrollLeft(Math.round(c+this.characterWidth-this.$size.scrollerWidth))},this.getScrollTop=function(){return this.session.getScrollTop()},this.getScrollLeft=function(){return this.session.getScrollLeft()},this.getScrollTopRow=function(){return this.scrollTop/this.lineHeight},this.getScrollBottomRow=function(){return Math.max(0,Math.floor((this.scrollTop+this.$size.scrollerHeight)/this.lineHeight)-1)},this.scrollToRow=function(a){this.session.setScrollTop(a*this.lineHeight)},this.STEPS=10,this.$calcSteps=function(a,b){var c=0,d=this.STEPS,e=[],f=function(a,b,c){return(a/=.5)<1?c/2*Math.pow(a,3)+b:c/2*(Math.pow(a-2,3)+2)+b};for(c=0;c<d;++c)e.push(f(c/this.STEPS,a,b-a));return e.push(b),e},this.scrollToLine=function(a,b){var c=this.$cursorLayer.getPixelPosition({row:a,column:0}),d=c.top;b&&(d-=this.$size.scrollerHeight/2);if(this.$animatedScroll&&Math.abs(d-this.scrollTop)<1e4){var e=this,f=e.$calcSteps(this.scrollTop,d);clearInterval(this.$timer),this.$timer=setInterval(function(){e.session.setScrollTop(f.shift()),f.length||clearInterval(e.$timer)},10)}else this.session.setScrollTop(d)},this.scrollToY=function(a){this.scrollTop!==a&&(this.$loop.schedule(this.CHANGE_SCROLL),this.scrollTop=a)},this.scrollToX=function(a){a<=this.$padding&&(a=0),this.scrollLeft!==a&&(this.scrollLeft=a),this.$loop.schedule(this.CHANGE_H_SCROLL)},this.scrollBy=function(a,b){b&&this.session.setScrollTop(this.session.getScrollTop()+b),a&&this.session.setScrollLeft(this.session.getScrollLeft()+a)},this.isScrollableBy=function(a,b){if(b<0&&this.session.getScrollTop()>0)return!0;if(b>0&&this.session.getScrollTop()+this.$size.scrollerHeight<this.layerConfig.maxHeight)return!0},this.pixelToScreenCoordinates=function(a,b){var c=this.scroller.getBoundingClientRect(),d=Math.round((a+this.scrollLeft-c.left-this.$padding-e.getPageScrollLeft())/this.characterWidth),f=Math.floor((b+this.scrollTop-c.top-e.getPageScrollTop())/this.lineHeight);return{row:f,column:d}},this.screenToTextCoordinates=function(a,b){var c=this.scroller.getBoundingClientRect(),d=Math.round((a+this.scrollLeft-c.left-this.$padding-e.getPageScrollLeft())/this.characterWidth),f=Math.floor((b+this.scrollTop-c.top-e.getPageScrollTop())/this.lineHeight);return this.session.screenToDocumentPosition(f,Math.max(d,0))},this.textToScreenCoordinates=function(a,b){var c=this.scroller.getBoundingClientRect(),d=this.session.documentToScreenPosition(a,b),e=this.$padding+Math.round(d.column*this.characterWidth),f=d.row*this.lineHeight;return{pageX:c.left+e-this.scrollLeft,pageY:c.top+f-this.scrollTop}},this.visualizeFocus=function(){e.addCssClass(this.container,"ace_focus")},this.visualizeBlur=function(){e.removeCssClass(this.container,"ace_focus")},this.showComposition=function(a){this.$composition||(this.$composition=e.createElement("div"),this.$composition.className="ace_composition",this.content.appendChild(this.$composition)),this.$composition.innerHTML="&#160;";var b=this.$cursorLayer.getPixelPosition(),c=this.$composition.style;c.top=b.top+"px",c.left=b.left+this.$padding+"px",c.height=this.lineHeight+"px",this.hideCursor()},this.setCompositionText=function(a){e.setInnerText(this.$composition,a)},this.hideComposition=function(){this.showCursor();if(!this.$composition)return;var a=this.$composition.style;a.top="-10000px",a.left="-10000px"},this._loadTheme=function(a,b){if(!h.get("packaged"))return b();var c=a.split("/").pop(),d=h.get("themePath")+"/theme-"+c+h.get("suffix");i.loadScript(d,b)},this.setTheme=function(b){function h(a){e.importCssString(a.cssText,a.cssClass,c.container.ownerDocument),c.$theme&&e.removeCssClass(c.container,c.$theme),c.$theme=a?a.cssClass:null,c.$theme&&e.addCssClass(c.container,c.$theme),a&&a.isDark?e.addCssClass(c.container,"ace_dark"):e.removeCssClass(c.container,"ace_dark"),c.$size&&(c.$size.width=0,c.onResize())}var c=this;this.$themeValue=b;if(!b||typeof b=="string"){var d=b||"ace/theme/textmate",f;try{f=a(d)}catch(g){}if(f)return h(f);c._loadTheme(d,function(){a([d],function(a){if(c.$themeValue!==b)return;h(a)})})}else h(b)},this.getTheme=function(){return this.$themeValue},this.setStyle=function(b){e.addCssClass(this.container,b)},this.unsetStyle=function(b){e.removeCssClass(this.container,b)},this.destroy=function(){this.$textLayer.destroy(),this.$cursorLayer.destroy()}}).call(r.prototype),b.VirtualRenderer=r}),define("ace/layer/gutter",["require","exports","module","ace/lib/dom","ace/lib/oop","ace/lib/event_emitter"],function(a,b,c){"use strict";var d=a("../lib/dom"),e=a("../lib/oop"),f=a("../lib/event_emitter").EventEmitter,g=function(a){this.element=d.createElement("div"),this.element.className="ace_layer ace_gutter-layer",a.appendChild(this.element),this.setShowFoldWidgets(this.$showFoldWidgets),this.gutterWidth=0,this.$breakpoints=[],this.$annotations=[],this.$decorations=[]};(function(){e.implement(this,f),this.setSession=function(a){this.session=a},this.addGutterDecoration=function(a,b){this.$decorations[a]||(this.$decorations[a]=""),this.$decorations[a]+=" "+b},this.removeGutterDecoration=function(a,b){this.$decorations[a]=this.$decorations[a].replace(" "+b,"")},this.setBreakpoints=function(a){this.$breakpoints=a.concat()},this.setAnnotations=function(a){this.$annotations=[];for(var b in a)if(a.hasOwnProperty(b)){var c=a[b];if(!c)continue;var d=this.$annotations[b]={text:[]};for(var e=0;e<c.length;e++){var f=c[e],g=f.text.replace(/"/g,"&quot;").replace(/'/g,"&#8217;").replace(/</,"&lt;");d.text.indexOf(g)===-1&&d.text.push(g);var h=f.type;h=="error"?d.className="ace_error":h=="warning"&&d.className!="ace_error"?d.className="ace_warning":h=="info"&&!d.className&&(d.className="ace_info")}}},this.update=function(a){this.$config=a;var b={className:"",text:[]},c=[],e=a.firstRow,f=a.lastRow,g=this.session.getNextFoldLine(e),h=g?g.start.row:Infinity,i=this.$showFoldWidgets&&this.session.foldWidgets;for(;;){e>h&&(e=g.end.row+1,g=this.session.getNextFoldLine(e,g),h=g?g.start.row:Infinity);if(e>f)break;var j=this.$annotations[e]||b;c.push("<div class='ace_gutter-cell",this.$decorations[e]||"",this.$breakpoints[e]?" ace_breakpoint ":" ",j.className,"' title='",j.text.join("\n"),"' style='height:",a.lineHeight,"px;'>",e+1);if(i){var k=i[e];k==null&&(k=i[e]=this.session.getFoldWidget(e)),k&&c.push("<span class='ace_fold-widget ",k,k=="start"&&e==h&&e<g.end.row?" closed":" open","'></span>")}var l=this.session.getRowLength(e)-1;while(l--)c.push("</div><div class='ace_gutter-cell' style='height:",a.lineHeight,"px'>¦");c.push("</div>"),e++}this.element=d.setInnerHtml(this.element,c.join("")),this.element.style.height=a.minHeight+"px";var m=this.element.offsetWidth;m!==this.gutterWidth&&(this.gutterWidth=m,this._emit("changeGutterWidth",m))},this.$showFoldWidgets=!0,this.setShowFoldWidgets=function(a){a?d.addCssClass(this.element,"ace_folding-enabled"):d.removeCssClass(this.element,"ace_folding-enabled"),this.$showFoldWidgets=a},this.getShowFoldWidgets=function(){return this.$showFoldWidgets}}).call(g.prototype),b.Gutter=g}),define("ace/layer/marker",["require","exports","module","ace/range","ace/lib/dom"],function(a,b,c){"use strict";var d=a("../range").Range,e=a("../lib/dom"),f=function(a){this.element=e.createElement("div"),this.element.className="ace_layer ace_marker-layer",a.appendChild(this.element)};(function(){this.$padding=0,this.setPadding=function(a){this.$padding=a},this.setSession=function(a){this.session=a},this.setMarkers=function(a){this.markers=a},this.update=function(a){var a=a||this.config;if(!a)return;this.config=a;var b=[];for(var c in this.markers){var d=this.markers[c],f=d.range.clipRows(a.firstRow,a.lastRow);if(f.isEmpty())continue;f=f.toScreenRange(this.session);if(d.renderer){var g=this.$getTop(f.start.row,a),h=Math.round(this.$padding+f.start.column*a.characterWidth);d.renderer(b,f,h,g,a)}else f.isMultiLine()?d.type=="text"?this.drawTextMarker(b,f,d.clazz,a):this.drawMultiLineMarker(b,f,d.clazz,a,d.type):this.drawSingleLineMarker(b,f,d.clazz,a,null,d.type)}this.element=e.setInnerHtml(this.element,b.join(""))},this.$getTop=function(a,b){return(a-b.firstRowScreen)*b.lineHeight},this.drawTextMarker=function(a,b,c,e){var f=b.start.row,g=new d(f,b.start.column,f,this.session.getScreenLastRowColumn(f));this.drawSingleLineMarker(a,g,c,e,1,"text"),f=b.end.row,g=new d(f,0,f,b.end.column),this.drawSingleLineMarker(a,g,c,e,0,"text");for(f=b.start.row+1;f<b.end.row;f++)g.start.row=f,g.end.row=f,g.end.column=this.session.getScreenLastRowColumn(f),this.drawSingleLineMarker(a,g,c,e,1,"text")},this.drawMultiLineMarker=function(a,b,c,d,e){var f=e==="background"?0:this.$padding,g=d.width+2*this.$padding-f,h=d.lineHeight,i=Math.round(g-b.start.column*d.characterWidth),j=this.$getTop(b.start.row,d),k=Math.round(f+b.start.column*d.characterWidth);a.push("<div class='",c,"' style='","height:",h,"px;","width:",i,"px;","top:",j,"px;","left:",k,"px;'></div>"),j=this.$getTop(b.end.row,d),i=Math.round(b.end.column*d.characterWidth),a.push("<div class='",c,"' style='","height:",h,"px;","width:",i,"px;","top:",j,"px;","left:",f,"px;'></div>"),h=(b.end.row-b.start.row-1)*d.lineHeight;if(h<0)return;j=this.$getTop(b.start.row+1,d),a.push("<div class='",c,"' style='","height:",h,"px;","width:",g,"px;","top:",j,"px;","left:",f,"px;'></div>")},this.drawSingleLineMarker=function(a,b,c,d,e,f){var g=f==="background"?0:this.$padding,h=d.lineHeight;if(f==="background")var i=d.width;else i=Math.round((b.end.column+(e||0)-b.start.column)*d.characterWidth);var j=this.$getTop(b.start.row,d),k=Math.round(g+b.start.column*d.characterWidth);a.push("<div class='",c,"' style='","height:",h,"px;","width:",i,"px;","top:",j,"px;","left:",k,"px;'></div>")}}).call(f.prototype),b.Marker=f}),define("ace/layer/text",["require","exports","module","ace/lib/oop","ace/lib/dom","ace/lib/lang","ace/lib/useragent","ace/lib/event_emitter"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("../lib/dom"),f=a("../lib/lang"),g=a("../lib/useragent"),h=a("../lib/event_emitter").EventEmitter,i=function(a){this.element=e.createElement("div"),this.element.className="ace_layer ace_text-layer",a.appendChild(this.element),this.$characterSize=this.$measureSizes()||{width:0,height:0},this.$pollSizeChanges()};(function(){d.implement(this,h),this.EOF_CHAR="¶",this.EOL_CHAR="¬",this.TAB_CHAR="→",this.SPACE_CHAR="·",this.$padding=0,this.setPadding=function(a){this.$padding=a,this.element.style.padding="0 "+a+"px"},this.getLineHeight=function(){return this.$characterSize.height||1},this.getCharacterWidth=function(){return this.$characterSize.width||1},this.checkForSizeChanges=function(){var a=this.$measureSizes();a&&(this.$characterSize.width!==a.width||this.$characterSize.height!==a.height)&&(this.$characterSize=a,this._emit("changeCharacterSize",{data:a}))},this.$pollSizeChanges=function(){var a=this;this.$pollSizeChangesTimer=setInterval(function(){a.checkForSizeChanges()},500)},this.$fontStyles={fontFamily:1,fontSize:1,fontWeight:1,fontStyle:1,lineHeight:1},this.$measureSizes=g.isIE||g.isOldGecko?function(){var a=1e3;if(!this.$measureNode){var b=this.$measureNode=e.createElement("div"),c=b.style;c.width=c.height="auto",c.left=c.top=-a*40+"px",c.visibility="hidden",c.position="fixed",c.overflow="visible",c.whiteSpace="nowrap",b.innerHTML=f.stringRepeat("Xy",a);if(this.element.ownerDocument.body)this.element.ownerDocument.body.appendChild(b);else{var d=this.element.parentNode;while(!e.hasCssClass(d,"ace_editor"))d=d.parentNode;d.appendChild(b)}}if(!this.element.offsetWidth)return null;var c=this.$measureNode.style,g=e.computedStyle(this.element);for(var h in this.$fontStyles)c[h]=g[h];var i={height:this.$measureNode.offsetHeight,width:this.$measureNode.offsetWidth/(a*2)};return i.width==0||i.height==0?null:i}:function(){if(!this.$measureNode){var a=this.$measureNode=e.createElement("div"),b=a.style;b.width=b.height="auto",b.left=b.top="-100px",b.visibility="hidden",b.position="fixed",b.overflow="visible",b.whiteSpace="nowrap",a.innerHTML="X";var c=this.element.parentNode;while(c&&!e.hasCssClass(c,"ace_editor"))c=c.parentNode;if(!c)return this.$measureNode=null;c.appendChild(a)}var d=this.$measureNode.getBoundingClientRect(),f={height:d.height,width:d.width};return f.width==0||f.height==0?null:f},this.setSession=function(a){this.session=a},this.showInvisibles=!1,this.setShowInvisibles=function(a){return this.showInvisibles==a?!1:(this.showInvisibles=a,!0)},this.$tabStrings=[],this.$computeTabString=function(){var a=this.session.getTabSize(),b=this.$tabStrings=[0];for(var c=1;c<a+1;c++)this.showInvisibles?b.push("<span class='ace_invisible'>"+this.TAB_CHAR+(new Array(c)).join("&#160;")+"</span>"):b.push((new Array(c+1)).join("&#160;"))},this.updateLines=function(a,b,c){this.$computeTabString(),(this.config.lastRow!=a.lastRow||this.config.firstRow!=a.firstRow)&&this.scrollLines(a),this.config=a;var d=Math.max(b,a.firstRow),f=Math.min(c,a.lastRow),g=this.element.childNodes,h=0;for(var i=a.firstRow;i<d;i++){var j=this.session.getFoldLine(i);if(j){if(j.containsRow(d)){d=j.start.row;break}i=j.end.row}h++}for(var k=d;k<=f;k++){var l=g[h++];if(!l)continue;var m=[],n=this.session.getTokens(k,k);this.$renderLine(m,k,n[0].tokens,!this.$useLineGroups()),l=e.setInnerHtml(l,m.join("")),k=this.session.getRowFoldEnd(k)}},this.scrollLines=function(a){this.$computeTabString();var b=this.config;this.config=a;if(!b||b.lastRow<a.firstRow)return this.update(a);if(a.lastRow<b.firstRow)return this.update(a);var c=this.element;if(b.firstRow<a.firstRow)for(var d=this.session.getFoldedRowCount(b.firstRow,a.firstRow-1);d>0;d--)c.removeChild(c.firstChild);if(b.lastRow>a.lastRow)for(var d=this.session.getFoldedRowCount(a.lastRow+1,b.lastRow);d>0;d--)c.removeChild(c.lastChild);if(a.firstRow<b.firstRow){var e=this.$renderLinesFragment(a,a.firstRow,b.firstRow-1);c.firstChild?c.insertBefore(e,c.firstChild):c.appendChild(e)}if(a.lastRow>b.lastRow){var e=this.$renderLinesFragment(a,b.lastRow+1,a.lastRow);c.appendChild(e)}},this.$renderLinesFragment=function(a,b,c){var d=this.element.ownerDocument.createDocumentFragment(),f=b,g=this.session.getNextFoldLine(f),h=g?g.start.row:Infinity;for(;;){f>h&&(f=g.end.row+1,g=this.session.getNextFoldLine(f,g),h=g?g.start.row:Infinity);if(f>c)break;var i=e.createElement("div"),j=[],k=this.session.getTokens(f,f);k.length==1&&this.$renderLine(j,f,k[0].tokens,!1),i.innerHTML=j.join("");if(this.$useLineGroups())i.className="ace_line_group",d.appendChild(i);else{var l=i.childNodes;while(l.length)d.appendChild(l[0])}f++}return d},this.update=function(a){this.$computeTabString(),this.config=a;var b=[],c=a.firstRow,d=a.lastRow,f=c,g=this.session.getNextFoldLine(f),h=g?g.start.row:Infinity;for(;;){f>h&&(f=g.end.row+1,g=this.session.getNextFoldLine(f,g),h=g?g.start.row:Infinity);if(f>d)break;this.$useLineGroups()&&b.push("<div class='ace_line_group'>");var i=this.session.getTokens(f,f);i.length==1&&this.$renderLine(b,f,i[0].tokens,!1),this.$useLineGroups()&&b.push("</div>"),f++}this.element=e.setInnerHtml(this.element,b.join(""))},this.$textToken={text:!0,rparen:!0,lparen:!0},this.$renderToken=function(a,b,c,d){var e=this,f=/\t|&|<|( +)|([\v\f \u00a0\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u200b\u2028\u2029\u3000])|[\u1100-\u115F]|[\u11A3-\u11A7]|[\u11FA-\u11FF]|[\u2329-\u232A]|[\u2E80-\u2E99]|[\u2E9B-\u2EF3]|[\u2F00-\u2FD5]|[\u2FF0-\u2FFB]|[\u3000-\u303E]|[\u3041-\u3096]|[\u3099-\u30FF]|[\u3105-\u312D]|[\u3131-\u318E]|[\u3190-\u31BA]|[\u31C0-\u31E3]|[\u31F0-\u321E]|[\u3220-\u3247]|[\u3250-\u32FE]|[\u3300-\u4DBF]|[\u4E00-\uA48C]|[\uA490-\uA4C6]|[\uA960-\uA97C]|[\uAC00-\uD7A3]|[\uD7B0-\uD7C6]|[\uD7CB-\uD7FB]|[\uF900-\uFAFF]|[\uFE10-\uFE19]|[\uFE30-\uFE52]|[\uFE54-\uFE66]|[\uFE68-\uFE6B]|[\uFF01-\uFF60]|[\uFFE0-\uFFE6]/g,h=function(a,c,d,f,h){if(a.charCodeAt(0)==32)return(new Array(a.length+1)).join("&#160;");if(a=="	"){var i=e.session.getScreenTabSize(b+f);return b+=i-1,e.$tabStrings[i]}if(a=="&")return g.isOldGecko?"&":"&amp;";if(a=="<")return"&lt;";if(a==" "){var j=e.showInvisibles?"ace_cjk ace_invisible":"ace_cjk",k=e.showInvisibles?e.SPACE_CHAR:"";return b+=1,"<span class='"+j+"' style='width:"+e.config.characterWidth*2+"px'>"+k+"</span>"}if(a.match(/[\v\f \u00a0\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u200b\u2028\u2029\u3000]/)){if(e.showInvisibles){var k=(new Array(a.length+1)).join(e.SPACE_CHAR);return"<span class='ace_invisible'>"+k+"</span>"}return"&#160;"}return b+=1,"<span class='ace_cjk' style='width:"+e.config.characterWidth*2+"px'>"+a+"</span>"},i=d.replace(f,h);if(!this.$textToken[c.type]){var j="ace_"+c.type.replace(/\./g," ace_"),k="";c.type=="fold"&&(k=" style='width:"+c.value.length*this.config.characterWidth+"px;' "),a.push("<span class='",j,"'",k,">",i,"</span>")}else a.push(i);return b+d.length},this.$renderLineCore=function(a,b,c,d,e){var f=0,g=0,h,i=0,j=this;!d||d.length==0?h=Number.MAX_VALUE:h=d[0],e||a.push("<div class='ace_line' style='height:",this.config.lineHeight,"px","'>");for(var k=0;k<c.length;k++){var l=c[k],m=l.value;if(f+m.length<h)i=j.$renderToken(a,i,l,m),f+=m.length;else{while(f+m.length>=h)i=j.$renderToken(a,i,l,m.substring(0,h-f)),m=m.substring(h-f),f=h,e||a.push("</div>","<div class='ace_line' style='height:",this.config.lineHeight,"px","'>"),g++,i=0,h=d[g]||Number.MAX_VALUE;m.length!=0&&(f+=m.length,i=j.$renderToken(a,i,l,m))}}this.showInvisibles&&(b!==this.session.getLength()-1?a.push("<span class='ace_invisible'>"+this.EOL_CHAR+"</span>"):a.push("<span class='ace_invisible'>"+this.EOF_CHAR+"</span>")),e||a.push("</div>")},this.$renderLine=function(a,b,c,d){if(!this.session.isRowFolded(b)){var e=this.session.getRowSplitData(b);this.$renderLineCore(a,b,c,e,d)}else this.$renderFoldLine(a,b,c,d)},this.$renderFoldLine=function(a,b,c,d){function h(a,b,c){var d=0,e=0;while(e+a[d].value.length<b){e+=a[d].value.length,d++;if(d==a.length)return}if(e!=b){var f=a[d].value.substring(b-e);f.length>c-b&&(f=f.substring(0,c-b)),g.push({type:a[d].type,value:f}),e=b+f.length,d+=1}while(e<c){var f=a[d].value;f.length+e>c&&(f=f.substring(0,c-e)),g.push({type:a[d].type,value:f}),e+=f.length,d+=1}}var e=this.session,f=e.getFoldLine(b),g=[];f.walk(function(a,b,d,e,f){a?g.push({type:"fold",value:a}):(f&&(c=this.session.getTokens(b,b)[0].tokens),c.length!=0&&h(c,e,d))}.bind(this),f.end.row,this.session.getLine(f.end.row).length);var i=this.session.$useWrapMode?this.session.$wrapData[b]:null;this.$renderLineCore(a,b,g,i,d)},this.$useLineGroups=function(){return this.session.getUseWrapMode()},this.destroy=function(){clearInterval(this.$pollSizeChangesTimer),this.$measureNode&&this.$measureNode.parentNode.removeChild(this.$measureNode),delete this.$measureNode}}).call(i.prototype),b.Text=i}),define("ace/layer/cursor",["require","exports","module","ace/lib/dom"],function(a,b,c){"use strict";var d=a("../lib/dom"),e=function(a){this.element=d.createElement("div"),this.element.className="ace_layer ace_cursor-layer",a.appendChild(this.element),this.isVisible=!1,this.cursors=[],this.cursor=this.addCursor()};(function(){this.$padding=0,this.setPadding=function(a){this.$padding=a},this.setSession=function(a){this.session=a},this.addCursor=function(){var a=d.createElement("div"),b="ace_cursor";return this.isVisible||(b+=" ace_hidden"),this.overwrite&&(b+=" ace_overwrite"),a.className=b,this.element.appendChild(a),this.cursors.push(a),a},this.removeCursor=function(){if(this.cursors.length>1){var a=this.cursors.pop();return a.parentNode.removeChild(a),a}},this.hideCursor=function(){this.isVisible=!1;for(var a=this.cursors.length;a--;)d.addCssClass(this.cursors[a],"ace_hidden");clearInterval(this.blinkId)},this.showCursor=function(){this.isVisible=!0;for(var a=this.cursors.length;a--;)d.removeCssClass(this.cursors[a],"ace_hidden");this.element.style.visibility="",this.restartTimer()},this.restartTimer=function(){clearInterval(this.blinkId);if(!this.isVisible)return;var a=this.element;this.blinkId=setInterval(function(){a.style.visibility="hidden",setTimeout(function(){a.style.visibility="visible"},400)},1e3)},this.getPixelPosition=function(a,b){if(!this.config||!this.session)return{left:0,top:0};a||(a=this.session.selection.getCursor());var c=this.session.documentToScreenPosition(a),d=Math.round(this.$padding+c.column*this.config.characterWidth),e=(c.row-(b?this.config.firstRowScreen:0))*this.config.lineHeight;return{left:d,top:e}},this.update=function(a){this.config=a;if(this.session.selectionMarkerCount>1){var b=this.session.$selectionMarkers,c=0,d,e=0;for(var c=b.length;c--;){d=b[c];var f=this.getPixelPosition(d.cursor,!0),g=(this.cursors[e++]||this.addCursor()).style;g.left=f.left+"px",g.top=f.top+"px",g.width=a.characterWidth+"px",g.height=a.lineHeight+"px"}if(e>1)while(this.cursors.length>e)this.removeCursor()}else{var f=this.getPixelPosition(null,!0),g=this.cursor.style;g.left=f.left+"px",g.top=f.top+"px",g.width=a.characterWidth+"px",g.height=a.lineHeight+"px";while(this.cursors.length>1)this.removeCursor()}var h=this.session.getOverwrite();h!=this.overwrite&&this.$setOverite(h),this.restartTimer()},this.$setOverite=function(a){this.overwrite=a;for(var b=this.cursors.length;b--;)a?d.addCssClass(this.cursors[b],"ace_overwrite"):d.removeCssClass(this.cursors[b],"ace_overwrite")},this.destroy=function(){clearInterval(this.blinkId)}}).call(e.prototype),b.Cursor=e}),define("ace/scrollbar",["require","exports","module","ace/lib/oop","ace/lib/dom","ace/lib/event","ace/lib/event_emitter"],function(a,b,c){"use strict";var d=a("./lib/oop"),e=a("./lib/dom"),f=a("./lib/event"),g=a("./lib/event_emitter").EventEmitter,h=function(a){this.element=e.createElement("div"),this.element.className="ace_sb",this.inner=e.createElement("div"),this.element.appendChild(this.inner),a.appendChild(this.element),this.width=e.scrollbarWidth(a.ownerDocument),this.element.style.width=(this.width||15)+5+"px",f.addListener(this.element,"scroll",this.onScroll.bind(this))};(function(){d.implement(this,g),this.onScroll=function(){this._emit("scroll",{data:this.element.scrollTop})},this.getWidth=function(){return this.width},this.setHeight=function(a){this.element.style.height=a+"px"},this.setInnerHeight=function(a){this.inner.style.height=a+"px"},this.setScrollTop=function(a){this.element.scrollTop=a}}).call(h.prototype),b.ScrollBar=h}),define("ace/renderloop",["require","exports","module","ace/lib/event"],function(a,b,c){"use strict";var d=a("./lib/event"),e=function(a,b){this.onRender=a,this.pending=!1,this.changes=0,this.window=b||window};(function(){this.schedule=function(a){this.changes=this.changes|a;if(!this.pending){this.pending=!0;var b=this;d.nextTick(function(){b.pending=!1;var a;while(a=b.changes)b.changes=0,b.onRender(a)},this.window)}}}).call(e.prototype),b.RenderLoop=e}),define("text!ace/css/editor.css",[],"@import url(//fonts.googleapis.com/css?family=Droid+Sans+Mono);\n\n.ace_editor {\n    position: absolute;\n    overflow: hidden;\n    font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', 'Droid Sans Mono', 'Consolas', monospace;\n    font-size: 12px;\n}\n\n.ace_scroller {\n    position: absolute;\n    overflow-x: scroll;\n    overflow-y: hidden;\n}\n\n.ace_content {\n    position: absolute;\n    box-sizing: border-box;\n    -moz-box-sizing: border-box;\n    -webkit-box-sizing: border-box;\n    cursor: text;\n}\n\n.ace_composition {\n    position: absolute;\n    background: #555;\n    color: #DDD;\n    z-index: 4;\n}\n\n.ace_gutter {\n    position: absolute;\n    overflow : hidden;\n    height: 100%;\n    width: auto;\n    cursor: default;\n    z-index: 1000;\n}\n\n.ace_gutter.horscroll {\n    box-shadow: 0px 0px 20px rgba(0,0,0,0.4);\n}\n\n.ace_gutter-cell {\n    padding-left: 19px;\n    padding-right: 6px;\n}\n\n.ace_gutter-cell.ace_error {\n    background-image: url(\"data:image/gif,GIF89a%10%00%10%00%D5%00%00%F5or%F5%87%88%F5nr%F4ns%EBmq%F5z%7F%DDJT%DEKS%DFOW%F1Yc%F2ah%CE(7%CE)8%D18E%DD%40M%F2KZ%EBU%60%F4%60m%DCir%C8%16(%C8%19*%CE%255%F1%3FR%F1%3FS%E6%AB%B5%CA%5DI%CEn%5E%F7%A2%9A%C9G%3E%E0a%5B%F7%89%85%F5yy%F6%82%80%ED%82%80%FF%BF%BF%E3%C4%C4%FF%FF%FF%FF%FF%FF%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00!%F9%04%01%00%00%25%00%2C%00%00%00%00%10%00%10%00%00%06p%C0%92pH%2C%1A%8F%C8%D2H%93%E1d4%23%E4%88%D3%09mB%1DN%B48%F5%90%40%60%92G%5B%94%20%3E%22%D2%87%24%FA%20%24%C5%06A%00%20%B1%07%02B%A38%89X.v%17%82%11%13q%10%0Fi%24%0F%8B%10%7BD%12%0Ei%09%92%09%0EpD%18%15%24%0A%9Ci%05%0C%18F%18%0B%07%04%01%04%06%A0H%18%12%0D%14%0D%12%A1I%B3%B4%B5IA%00%3B\");\n    background-repeat: no-repeat;\n    background-position: 2px center;\n}\n\n.ace_gutter-cell.ace_warning {\n    background-image: url(\"data:image/gif,GIF89a%10%00%10%00%D5%00%00%FF%DBr%FF%DE%81%FF%E2%8D%FF%E2%8F%FF%E4%96%FF%E3%97%FF%E5%9D%FF%E6%9E%FF%EE%C1%FF%C8Z%FF%CDk%FF%D0s%FF%D4%81%FF%D5%82%FF%D5%83%FF%DC%97%FF%DE%9D%FF%E7%B8%FF%CCl%7BQ%13%80U%15%82W%16%81U%16%89%5B%18%87%5B%18%8C%5E%1A%94d%1D%C5%83-%C9%87%2F%C6%84.%C6%85.%CD%8B2%C9%871%CB%8A3%CD%8B5%DC%98%3F%DF%9BB%E0%9CC%E1%A5U%CB%871%CF%8B5%D1%8D6%DB%97%40%DF%9AB%DD%99B%E3%B0p%E7%CC%AE%FF%FF%FF%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00!%F9%04%01%00%00%2F%00%2C%00%00%00%00%10%00%10%00%00%06a%C0%97pH%2C%1A%8FH%A1%ABTr%25%87%2B%04%82%F4%7C%B9X%91%08%CB%99%1C!%26%13%84*iJ9(%15G%CA%84%14%01%1A%97%0C%03%80%3A%9A%3E%81%84%3E%11%08%B1%8B%20%02%12%0F%18%1A%0F%0A%03'F%1C%04%0B%10%16%18%10%0B%05%1CF%1D-%06%07%9A%9A-%1EG%1B%A0%A1%A0U%A4%A5%A6BA%00%3B\");\n    background-repeat: no-repeat;\n    background-position: 2px center;\n}\n\n.ace_gutter-cell.ace_info {\n    background-image: url(\"data:image/gif;base64,R0lGODlhEAAQAMQAAAAAAEFBQVJSUl5eXmRkZGtra39/f4WFhYmJiZGRkaampry8vMPDw8zMzNXV1dzc3OTk5Orq6vDw8P///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAkAABQALAAAAAAQABAAAAUuICWOZGmeaBml5XGwFCQSBGyXRSAwtqQIiRuiwIM5BoYVbEFIyGCQoeJGrVptIQA7\");\n    background-repeat: no-repeat;\n    background-position: 2px center;\n}\n\n.ace_editor .ace_sb {\n    position: absolute;\n    overflow-x: hidden;\n    overflow-y: scroll;\n    right: 0;\n}\n\n.ace_editor .ace_sb div {\n    position: absolute;\n    width: 1px;\n    left: 0;\n}\n\n.ace_editor .ace_print_margin_layer {\n    z-index: 0;\n    position: absolute;\n    overflow: hidden;\n    margin: 0;\n    left: 0;\n    height: 100%;\n    width: 100%;\n}\n\n.ace_editor .ace_print_margin {\n    position: absolute;\n    height: 100%;\n}\n\n.ace_editor textarea {\n    position: fixed;\n    z-index: 0;\n    width: 10px;\n    height: 30px;\n    opacity: 0;\n    background: transparent;\n    appearance: none;\n    -moz-appearance: none;\n    border: none;\n    resize: none;\n    outline: none;\n    overflow: hidden;\n}\n\n.ace_layer {\n    z-index: 1;\n    position: absolute;\n    overflow: hidden;\n    white-space: nowrap;\n    height: 100%;\n    width: 100%;\n    box-sizing: border-box;\n    -moz-box-sizing: border-box;\n    -webkit-box-sizing: border-box;\n    /* setting pointer-events: auto; on node under the mouse, which changes\n        during scroll, will break mouse wheel scrolling in Safari */\n    pointer-events: none;\n}\n\n.ace_gutter .ace_layer {\n    position: relative;\n    min-width: 40px;\n    text-align: right;\n    pointer-events: auto;\n}\n\n.ace_text-layer {\n    color: black;\n}\n\n.ace_cjk {\n    display: inline-block;\n    text-align: center;\n}\n\n.ace_cursor-layer {\n    z-index: 4;\n}\n\n.ace_cursor {\n    z-index: 4;\n    position: absolute;\n}\n\n.ace_cursor.ace_hidden {\n    opacity: 0.2;\n}\n\n.ace_line {\n    white-space: nowrap;\n}\n\n.ace_marker-layer .ace_step {\n    position: absolute;\n    z-index: 3;\n}\n\n.ace_marker-layer .ace_selection {\n    position: absolute;\n    z-index: 5;\n}\n\n.ace_marker-layer .ace_bracket {\n    position: absolute;\n    z-index: 6;\n}\n\n.ace_marker-layer .ace_active_line {\n    position: absolute;\n    z-index: 2;\n}\n\n.ace_gutter .ace_gutter_active_line{\n    background-color : #dcdcdc;\n}\n\n.ace_marker-layer .ace_selected_word {\n    position: absolute;\n    z-index: 4;\n    box-sizing: border-box;\n    -moz-box-sizing: border-box;\n    -webkit-box-sizing: border-box;\n}\n\n.ace_line .ace_fold {\n    box-sizing: border-box;\n    -moz-box-sizing: border-box;\n    -webkit-box-sizing: border-box;\n    \n    display: inline-block;\n    height: 11px;\n    margin-top: -2px;\n    vertical-align: middle;\n\n    background-image: \n        url(\"data:image/png,%89PNG%0D%0A%1A%0A%00%00%00%0DIHDR%00%00%00%11%00%00%00%09%08%06%00%00%00%D4%E8%C7%0C%00%00%03%1EiCCPICC%20Profile%00%00x%01%85T%DFk%D3P%14%FE%DAe%9D%B0%E1%8B%3Ag%11%09%3Eh%91ndStC%9C%B6kW%BA%CDZ%EA6%B7!H%9B%A6m%5C%9A%C6%24%ED~%B0%07%D9%8Bo%3A%C5w%F1%07%3E%F9%07%0C%D9%83o%7B%92%0D%C6%14a%F8%AC%88%22L%F6%22%B3%9E%9B4M'S%03%B9%F7%BB%DF%F9%EE9'%E7%E4%5E%A0%F9qZ%D3%14%2F%0F%14USO%C5%C2%FC%C4%E4%14%DF%F2%01%5E%1CC%2B%FChM%8B%86%16J%26G%40%0F%D3%B2y%EF%B3%F3%0E%1E%C6lt%EEo%DF%AB%FEc%D5%9A%95%0C%11%F0%1C%20%BE%945%C4%22%E1Y%A0i%5C%D4t%13%E0%D6%89%EF%9D15%C2%CDLsX%A7%04%09%1Fg8oc%81%E1%8C%8D%23%96f45%40%9A%09%C2%07%C5B%3AK%B8%408%98i%E0%F3%0D%D8%CE%81%14%E4'%26%A9%92.%8B%3C%ABER%2F%E5dE%B2%0C%F6%F0%1Fs%83%F2_%B0%A8%94%E9%9B%AD%E7%10%8Dm%9A%19N%D1%7C%8A%DE%1F9%7Dp%8C%E6%00%D5%C1%3F_%18%BDA%B8%9DpX6%E3%A35~B%CD%24%AE%11%26%BD%E7%EEti%98%EDe%9A%97Y)%12%25%1C%24%BCbT%AE3li%E6%0B%03%89%9A%E6%D3%ED%F4P%92%B0%9F4%BF43Y%F3%E3%EDP%95%04%EB1%C5%F5%F6KF%F4%BA%BD%D7%DB%91%93%07%E35%3E%A7)%D6%7F%40%FE%BD%F7%F5r%8A%E5y%92%F0%EB%B4%1E%8D%D5%F4%5B%92%3AV%DB%DB%E4%CD%A6%23%C3%C4wQ%3F%03HB%82%8E%1Cd(%E0%91B%0Ca%9Ac%C4%AA%F8L%16%19%22J%A4%D2itTy%B28%D6%3B(%93%96%ED%1CGx%C9_%0E%B8%5E%16%F5%5B%B2%B8%F6%E0%FB%9E%DD%25%D7%8E%BC%15%85%C5%B7%A3%D8Q%ED%B5%81%E9%BA%B2%13%9A%1B%7Fua%A5%A3n%E17%B9%E5%9B%1Bm%AB%0B%08Q%FE%8A%E5%B1H%5Ee%CAO%82Q%D7u6%E6%90S%97%FCu%0B%CF2%94%EE%25v%12X%0C%BA%AC%F0%5E%F8*l%0AO%85%17%C2%97%BF%D4%C8%CE%DE%AD%11%CB%80q%2C%3E%AB%9ES%CD%C6%EC%25%D2L%D2%EBd%B8%BF%8A%F5B%C6%18%F9%901CZ%9D%BE%24M%9C%8A9%F2%DAP%0B'%06w%82%EB%E6%E2%5C%2F%D7%07%9E%BB%CC%5D%E1%FA%B9%08%AD.r%23%8E%C2%17%F5E%7C!%F0%BE3%BE%3E_%B7o%88a%A7%DB%BE%D3d%EB%A31Z%EB%BB%D3%91%BA%A2%B1z%94%8F%DB'%F6%3D%8E%AA%13%19%B2%B1%BE%B1~V%08%2B%B4%A2cjJ%B3tO%00%03%25mN%97%F3%05%93%EF%11%84%0B%7C%88%AE-%89%8F%ABbW%90O%2B%0Ao%99%0C%5E%97%0CI%AFH%D9.%B0%3B%8F%ED%03%B6S%D6%5D%E6i_s9%F3*p%E9%1B%FD%C3%EB.7U%06%5E%19%C0%D1s.%17%A03u%E4%09%B0%7C%5E%2C%EB%15%DB%1F%3C%9E%B7%80%91%3B%DBc%AD%3Dma%BA%8B%3EV%AB%DBt.%5B%1E%01%BB%0F%AB%D5%9F%CF%AA%D5%DD%E7%E4%7F%0Bx%A3%FC%06%A9%23%0A%D6%C2%A1_2%00%00%00%09pHYs%00%00%0B%13%00%00%0B%13%01%00%9A%9C%18%00%00%00%B5IDAT(%15%A5%91%3D%0E%02!%10%85ac%E1%05%D6%CE%D6%C6%CE%D2%E8%ED%CD%DE%C0%C6%D6N.%E0V%F8%3D%9Ca%891XH%C2%BE%D9y%3F%90!%E6%9C%C3%BFk%E5%011%C6-%F5%C8N%04%DF%BD%FF%89%DFt%83DN%60%3E%F3%AB%A0%DE%1A%5Dg%BE%10Q%97%1B%40%9C%A8o%10%8F%5E%828%B4%1B%60%87%F6%02%26%85%1Ch%1E%C1%2B%5Bk%FF%86%EE%B7j%09%9A%DA%9B%ACe%A3%F9%EC%DA!9%B4%D5%A6%81%86%86%98%CC%3C%5B%40%FA%81%B3%E9%CB%23%94%C16Azo%05%D4%E1%C1%95a%3B%8A'%A0%E8%CC%17%22%85%1D%BA%00%A2%FA%DC%0A%94%D1%D1%8D%8B%3A%84%17B%C7%60%1A%25Z%FC%8D%00%00%00%00IEND%AEB%60%82\"),\n        url(\"data:image/png,%89PNG%0D%0A%1A%0A%00%00%00%0DIHDR%00%00%00%05%00%00%007%08%06%00%00%00%C4%DD%80C%00%00%03%1EiCCPICC%20Profile%00%00x%01%85T%DFk%D3P%14%FE%DAe%9D%B0%E1%8B%3Ag%11%09%3Eh%91ndStC%9C%B6kW%BA%CDZ%EA6%B7!H%9B%A6m%5C%9A%C6%24%ED~%B0%07%D9%8Bo%3A%C5w%F1%07%3E%F9%07%0C%D9%83o%7B%92%0D%C6%14a%F8%AC%88%22L%F6%22%B3%9E%9B4M'S%03%B9%F7%BB%DF%F9%EE9'%E7%E4%5E%A0%F9qZ%D3%14%2F%0F%14USO%C5%C2%FC%C4%E4%14%DF%F2%01%5E%1CC%2B%FChM%8B%86%16J%26G%40%0F%D3%B2y%EF%B3%F3%0E%1E%C6lt%EEo%DF%AB%FEc%D5%9A%95%0C%11%F0%1C%20%BE%945%C4%22%E1Y%A0i%5C%D4t%13%E0%D6%89%EF%9D15%C2%CDLsX%A7%04%09%1Fg8oc%81%E1%8C%8D%23%96f45%40%9A%09%C2%07%C5B%3AK%B8%408%98i%E0%F3%0D%D8%CE%81%14%E4'%26%A9%92.%8B%3C%ABER%2F%E5dE%B2%0C%F6%F0%1Fs%83%F2_%B0%A8%94%E9%9B%AD%E7%10%8Dm%9A%19N%D1%7C%8A%DE%1F9%7Dp%8C%E6%00%D5%C1%3F_%18%BDA%B8%9DpX6%E3%A35~B%CD%24%AE%11%26%BD%E7%EEti%98%EDe%9A%97Y)%12%25%1C%24%BCbT%AE3li%E6%0B%03%89%9A%E6%D3%ED%F4P%92%B0%9F4%BF43Y%F3%E3%EDP%95%04%EB1%C5%F5%F6KF%F4%BA%BD%D7%DB%91%93%07%E35%3E%A7)%D6%7F%40%FE%BD%F7%F5r%8A%E5y%92%F0%EB%B4%1E%8D%D5%F4%5B%92%3AV%DB%DB%E4%CD%A6%23%C3%C4wQ%3F%03HB%82%8E%1Cd(%E0%91B%0Ca%9Ac%C4%AA%F8L%16%19%22J%A4%D2itTy%B28%D6%3B(%93%96%ED%1CGx%C9_%0E%B8%5E%16%F5%5B%B2%B8%F6%E0%FB%9E%DD%25%D7%8E%BC%15%85%C5%B7%A3%D8Q%ED%B5%81%E9%BA%B2%13%9A%1B%7Fua%A5%A3n%E17%B9%E5%9B%1Bm%AB%0B%08Q%FE%8A%E5%B1H%5Ee%CAO%82Q%D7u6%E6%90S%97%FCu%0B%CF2%94%EE%25v%12X%0C%BA%AC%F0%5E%F8*l%0AO%85%17%C2%97%BF%D4%C8%CE%DE%AD%11%CB%80q%2C%3E%AB%9ES%CD%C6%EC%25%D2L%D2%EBd%B8%BF%8A%F5B%C6%18%F9%901CZ%9D%BE%24M%9C%8A9%F2%DAP%0B'%06w%82%EB%E6%E2%5C%2F%D7%07%9E%BB%CC%5D%E1%FA%B9%08%AD.r%23%8E%C2%17%F5E%7C!%F0%BE3%BE%3E_%B7o%88a%A7%DB%BE%D3d%EB%A31Z%EB%BB%D3%91%BA%A2%B1z%94%8F%DB'%F6%3D%8E%AA%13%19%B2%B1%BE%B1~V%08%2B%B4%A2cjJ%B3tO%00%03%25mN%97%F3%05%93%EF%11%84%0B%7C%88%AE-%89%8F%ABbW%90O%2B%0Ao%99%0C%5E%97%0CI%AFH%D9.%B0%3B%8F%ED%03%B6S%D6%5D%E6i_s9%F3*p%E9%1B%FD%C3%EB.7U%06%5E%19%C0%D1s.%17%A03u%E4%09%B0%7C%5E%2C%EB%15%DB%1F%3C%9E%B7%80%91%3B%DBc%AD%3Dma%BA%8B%3EV%AB%DBt.%5B%1E%01%BB%0F%AB%D5%9F%CF%AA%D5%DD%E7%E4%7F%0Bx%A3%FC%06%A9%23%0A%D6%C2%A1_2%00%00%00%09pHYs%00%00%0B%13%00%00%0B%13%01%00%9A%9C%18%00%00%00%3AIDAT8%11c%FC%FF%FF%7F%18%03%1A%60%01%F2%3F%A0%891%80%04%FF%11-%F8%17%9BJ%E2%05%B1ZD%81v%26t%E7%80%F8%A3%82h%A12%1A%20%A3%01%02%0F%01%BA%25%06%00%19%C0%0D%AEF%D5%3ES%00%00%00%00IEND%AEB%60%82\");\n    background-repeat: no-repeat, repeat-x;\n    background-position: center center, top left;\n    color: transparent;\n\n    border: 1px solid black;\n    -moz-border-radius: 2px;\n    -webkit-border-radius: 2px;\n    border-radius: 2px;\n    \n    cursor: pointer;\n    pointer-events: auto;\n}\n\n.ace_dark .ace_fold {\n}\n\n.ace_fold:hover{\n    background-image: \n        url(\"data:image/png,%89PNG%0D%0A%1A%0A%00%00%00%0DIHDR%00%00%00%11%00%00%00%09%08%06%00%00%00%D4%E8%C7%0C%00%00%03%1EiCCPICC%20Profile%00%00x%01%85T%DFk%D3P%14%FE%DAe%9D%B0%E1%8B%3Ag%11%09%3Eh%91ndStC%9C%B6kW%BA%CDZ%EA6%B7!H%9B%A6m%5C%9A%C6%24%ED~%B0%07%D9%8Bo%3A%C5w%F1%07%3E%F9%07%0C%D9%83o%7B%92%0D%C6%14a%F8%AC%88%22L%F6%22%B3%9E%9B4M'S%03%B9%F7%BB%DF%F9%EE9'%E7%E4%5E%A0%F9qZ%D3%14%2F%0F%14USO%C5%C2%FC%C4%E4%14%DF%F2%01%5E%1CC%2B%FChM%8B%86%16J%26G%40%0F%D3%B2y%EF%B3%F3%0E%1E%C6lt%EEo%DF%AB%FEc%D5%9A%95%0C%11%F0%1C%20%BE%945%C4%22%E1Y%A0i%5C%D4t%13%E0%D6%89%EF%9D15%C2%CDLsX%A7%04%09%1Fg8oc%81%E1%8C%8D%23%96f45%40%9A%09%C2%07%C5B%3AK%B8%408%98i%E0%F3%0D%D8%CE%81%14%E4'%26%A9%92.%8B%3C%ABER%2F%E5dE%B2%0C%F6%F0%1Fs%83%F2_%B0%A8%94%E9%9B%AD%E7%10%8Dm%9A%19N%D1%7C%8A%DE%1F9%7Dp%8C%E6%00%D5%C1%3F_%18%BDA%B8%9DpX6%E3%A35~B%CD%24%AE%11%26%BD%E7%EEti%98%EDe%9A%97Y)%12%25%1C%24%BCbT%AE3li%E6%0B%03%89%9A%E6%D3%ED%F4P%92%B0%9F4%BF43Y%F3%E3%EDP%95%04%EB1%C5%F5%F6KF%F4%BA%BD%D7%DB%91%93%07%E35%3E%A7)%D6%7F%40%FE%BD%F7%F5r%8A%E5y%92%F0%EB%B4%1E%8D%D5%F4%5B%92%3AV%DB%DB%E4%CD%A6%23%C3%C4wQ%3F%03HB%82%8E%1Cd(%E0%91B%0Ca%9Ac%C4%AA%F8L%16%19%22J%A4%D2itTy%B28%D6%3B(%93%96%ED%1CGx%C9_%0E%B8%5E%16%F5%5B%B2%B8%F6%E0%FB%9E%DD%25%D7%8E%BC%15%85%C5%B7%A3%D8Q%ED%B5%81%E9%BA%B2%13%9A%1B%7Fua%A5%A3n%E17%B9%E5%9B%1Bm%AB%0B%08Q%FE%8A%E5%B1H%5Ee%CAO%82Q%D7u6%E6%90S%97%FCu%0B%CF2%94%EE%25v%12X%0C%BA%AC%F0%5E%F8*l%0AO%85%17%C2%97%BF%D4%C8%CE%DE%AD%11%CB%80q%2C%3E%AB%9ES%CD%C6%EC%25%D2L%D2%EBd%B8%BF%8A%F5B%C6%18%F9%901CZ%9D%BE%24M%9C%8A9%F2%DAP%0B'%06w%82%EB%E6%E2%5C%2F%D7%07%9E%BB%CC%5D%E1%FA%B9%08%AD.r%23%8E%C2%17%F5E%7C!%F0%BE3%BE%3E_%B7o%88a%A7%DB%BE%D3d%EB%A31Z%EB%BB%D3%91%BA%A2%B1z%94%8F%DB'%F6%3D%8E%AA%13%19%B2%B1%BE%B1~V%08%2B%B4%A2cjJ%B3tO%00%03%25mN%97%F3%05%93%EF%11%84%0B%7C%88%AE-%89%8F%ABbW%90O%2B%0Ao%99%0C%5E%97%0CI%AFH%D9.%B0%3B%8F%ED%03%B6S%D6%5D%E6i_s9%F3*p%E9%1B%FD%C3%EB.7U%06%5E%19%C0%D1s.%17%A03u%E4%09%B0%7C%5E%2C%EB%15%DB%1F%3C%9E%B7%80%91%3B%DBc%AD%3Dma%BA%8B%3EV%AB%DBt.%5B%1E%01%BB%0F%AB%D5%9F%CF%AA%D5%DD%E7%E4%7F%0Bx%A3%FC%06%A9%23%0A%D6%C2%A1_2%00%00%00%09pHYs%00%00%0B%13%00%00%0B%13%01%00%9A%9C%18%00%00%00%B5IDAT(%15%A5%91%3D%0E%02!%10%85ac%E1%05%D6%CE%D6%C6%CE%D2%E8%ED%CD%DE%C0%C6%D6N.%E0V%F8%3D%9Ca%891XH%C2%BE%D9y%3F%90!%E6%9C%C3%BFk%E5%011%C6-%F5%C8N%04%DF%BD%FF%89%DFt%83DN%60%3E%F3%AB%A0%DE%1A%5Dg%BE%10Q%97%1B%40%9C%A8o%10%8F%5E%828%B4%1B%60%87%F6%02%26%85%1Ch%1E%C1%2B%5Bk%FF%86%EE%B7j%09%9A%DA%9B%ACe%A3%F9%EC%DA!9%B4%D5%A6%81%86%86%98%CC%3C%5B%40%FA%81%B3%E9%CB%23%94%C16Azo%05%D4%E1%C1%95a%3B%8A'%A0%E8%CC%17%22%85%1D%BA%00%A2%FA%DC%0A%94%D1%D1%8D%8B%3A%84%17B%C7%60%1A%25Z%FC%8D%00%00%00%00IEND%AEB%60%82\"),\n        url(\"data:image/png,%89PNG%0D%0A%1A%0A%00%00%00%0DIHDR%00%00%00%05%00%00%007%08%06%00%00%00%C4%DD%80C%00%00%03%1EiCCPICC%20Profile%00%00x%01%85T%DFk%D3P%14%FE%DAe%9D%B0%E1%8B%3Ag%11%09%3Eh%91ndStC%9C%B6kW%BA%CDZ%EA6%B7!H%9B%A6m%5C%9A%C6%24%ED~%B0%07%D9%8Bo%3A%C5w%F1%07%3E%F9%07%0C%D9%83o%7B%92%0D%C6%14a%F8%AC%88%22L%F6%22%B3%9E%9B4M'S%03%B9%F7%BB%DF%F9%EE9'%E7%E4%5E%A0%F9qZ%D3%14%2F%0F%14USO%C5%C2%FC%C4%E4%14%DF%F2%01%5E%1CC%2B%FChM%8B%86%16J%26G%40%0F%D3%B2y%EF%B3%F3%0E%1E%C6lt%EEo%DF%AB%FEc%D5%9A%95%0C%11%F0%1C%20%BE%945%C4%22%E1Y%A0i%5C%D4t%13%E0%D6%89%EF%9D15%C2%CDLsX%A7%04%09%1Fg8oc%81%E1%8C%8D%23%96f45%40%9A%09%C2%07%C5B%3AK%B8%408%98i%E0%F3%0D%D8%CE%81%14%E4'%26%A9%92.%8B%3C%ABER%2F%E5dE%B2%0C%F6%F0%1Fs%83%F2_%B0%A8%94%E9%9B%AD%E7%10%8Dm%9A%19N%D1%7C%8A%DE%1F9%7Dp%8C%E6%00%D5%C1%3F_%18%BDA%B8%9DpX6%E3%A35~B%CD%24%AE%11%26%BD%E7%EEti%98%EDe%9A%97Y)%12%25%1C%24%BCbT%AE3li%E6%0B%03%89%9A%E6%D3%ED%F4P%92%B0%9F4%BF43Y%F3%E3%EDP%95%04%EB1%C5%F5%F6KF%F4%BA%BD%D7%DB%91%93%07%E35%3E%A7)%D6%7F%40%FE%BD%F7%F5r%8A%E5y%92%F0%EB%B4%1E%8D%D5%F4%5B%92%3AV%DB%DB%E4%CD%A6%23%C3%C4wQ%3F%03HB%82%8E%1Cd(%E0%91B%0Ca%9Ac%C4%AA%F8L%16%19%22J%A4%D2itTy%B28%D6%3B(%93%96%ED%1CGx%C9_%0E%B8%5E%16%F5%5B%B2%B8%F6%E0%FB%9E%DD%25%D7%8E%BC%15%85%C5%B7%A3%D8Q%ED%B5%81%E9%BA%B2%13%9A%1B%7Fua%A5%A3n%E17%B9%E5%9B%1Bm%AB%0B%08Q%FE%8A%E5%B1H%5Ee%CAO%82Q%D7u6%E6%90S%97%FCu%0B%CF2%94%EE%25v%12X%0C%BA%AC%F0%5E%F8*l%0AO%85%17%C2%97%BF%D4%C8%CE%DE%AD%11%CB%80q%2C%3E%AB%9ES%CD%C6%EC%25%D2L%D2%EBd%B8%BF%8A%F5B%C6%18%F9%901CZ%9D%BE%24M%9C%8A9%F2%DAP%0B'%06w%82%EB%E6%E2%5C%2F%D7%07%9E%BB%CC%5D%E1%FA%B9%08%AD.r%23%8E%C2%17%F5E%7C!%F0%BE3%BE%3E_%B7o%88a%A7%DB%BE%D3d%EB%A31Z%EB%BB%D3%91%BA%A2%B1z%94%8F%DB'%F6%3D%8E%AA%13%19%B2%B1%BE%B1~V%08%2B%B4%A2cjJ%B3tO%00%03%25mN%97%F3%05%93%EF%11%84%0B%7C%88%AE-%89%8F%ABbW%90O%2B%0Ao%99%0C%5E%97%0CI%AFH%D9.%B0%3B%8F%ED%03%B6S%D6%5D%E6i_s9%F3*p%E9%1B%FD%C3%EB.7U%06%5E%19%C0%D1s.%17%A03u%E4%09%B0%7C%5E%2C%EB%15%DB%1F%3C%9E%B7%80%91%3B%DBc%AD%3Dma%BA%8B%3EV%AB%DBt.%5B%1E%01%BB%0F%AB%D5%9F%CF%AA%D5%DD%E7%E4%7F%0Bx%A3%FC%06%A9%23%0A%D6%C2%A1_2%00%00%00%09pHYs%00%00%0B%13%00%00%0B%13%01%00%9A%9C%18%00%00%003IDAT8%11c%FC%FF%FF%7F%3E%03%1A%60%01%F2%3F%A3%891%80%04%FFQ%26%F8w%C0%B43%A1%DB%0C%E2%8F%0A%A2%85%CAh%80%8C%06%08%3C%04%E8%96%18%00%A3S%0D%CD%CF%D8%C1%9D%00%00%00%00IEND%AEB%60%82\");\n    background-repeat: no-repeat, repeat-x;\n    background-position: center center, top left;\n}\n\n.ace_dragging .ace_content {\n    cursor: move;\n}\n\n.ace_folding-enabled > .ace_gutter-cell {\n    padding-right: 13px;\n}\n\n.ace_fold-widget {\n    box-sizing: border-box;\n    -moz-box-sizing: border-box;\n    -webkit-box-sizing: border-box;\n\n    margin: 0 -12px 1px 1px;\n    display: inline-block;\n    height: 14px;\n    width: 11px;\n    vertical-align: text-bottom;\n    \n    background-image: url(\"data:image/png,%89PNG%0D%0A%1A%0A%00%00%00%0DIHDR%00%00%00%05%00%00%00%05%08%06%00%00%00%8Do%26%E5%00%00%004IDATx%DAe%8A%B1%0D%000%0C%C2%F2%2CK%96%BC%D0%8F9%81%88H%E9%D0%0E%96%C0%10%92%3E%02%80%5E%82%E4%A9*-%EEsw%C8%CC%11%EE%96w%D8%DC%E9*Eh%0C%151(%00%00%00%00IEND%AEB%60%82\");\n    background-repeat: no-repeat;\n    background-position: center 5px;\n\n    border-radius: 3px;\n}\n\n.ace_fold-widget.end {\n    background-image: url(\"data:image/png,%89PNG%0D%0A%1A%0A%00%00%00%0DIHDR%00%00%00%05%00%00%00%05%08%06%00%00%00%8Do%26%E5%00%00%004IDATx%DAm%C7%C1%09%000%08C%D1%8C%ECE%C8E(%8E%EC%02)%1EZJ%F1%C1'%04%07I%E1%E5%EE%CAL%F5%A2%99%99%22%E2%D6%1FU%B5%FE0%D9x%A7%26Wz5%0E%D5%00%00%00%00IEND%AEB%60%82\");\n}\n\n.ace_fold-widget.closed {\n    background-image: url(\"data:image/png,%89PNG%0D%0A%1A%0A%00%00%00%0DIHDR%00%00%00%03%00%00%00%06%08%06%00%00%00%06%E5%24%0C%00%00%009IDATx%DA5%CA%C1%09%000%08%03%C0%AC*(%3E%04%C1%0D%BA%B1%23%A4Uh%E0%20%81%C0%CC%F8%82%81%AA%A2%AArGfr%88%08%11%11%1C%DD%7D%E0%EE%5B%F6%F6%CB%B8%05Q%2F%E9tai%D9%00%00%00%00IEND%AEB%60%82\");\n}\n\n.ace_fold-widget:hover {\n    border: 1px solid rgba(0, 0, 0, 0.3);\n    background-color: rgba(255, 255, 255, 0.2);\n    -moz-box-shadow:inset 0 1px 1px rgba(255, 255, 255, 0.7);\n    -moz-box-shadow: 0 1px 1px rgba(255, 255, 255, 0.7);\n    -webkit-box-shadow:inset 0 1px 1px rgba(255, 255, 255, 0.7);\n    -webkit-box-shadow: 0 1px 1px rgba(255, 255, 255, 0.7);\n    box-shadow:inset 0 1px 1px rgba(255, 255, 255, 0.7);\n    box-shadow: 0 1px 1px rgba(255, 255, 255, 0.7);\n    background-position: center 4px;\n}\n\n.ace_fold-widget:active {\n    border: 1px solid rgba(0, 0, 0, 0.4);\n    background-color: rgba(0, 0, 0, 0.05);\n    -moz-box-shadow:inset 0 1px 1px rgba(255, 255, 255);\n    -moz-box-shadow: 0 1px 1px rgba(255, 255, 255, 0.8);\n    -webkit-box-shadow:inset 0 1px 1px rgba(255, 255, 255);\n    -webkit-box-shadow: 0 1px 1px rgba(255, 255, 255, 0.8);\n    box-shadow:inset 0 1px 1px rgba(255, 255, 255);\n    box-shadow: 0 1px 1px rgba(255, 255, 255, 0.8);\n}\n\n.ace_fold-widget.invalid {\n    background-color: #FFB4B4;\n    border-color: #DE5555;\n}\n"),define("ace/multi_select",["require","exports","module","ace/range_list","ace/range","ace/selection","ace/mouse/multi_select_handler","ace/commands/multi_select_commands","ace/search","ace/edit_session","ace/editor"],function(a,b,c){function j(a,b,c){return i.$options.wrap=!0,i.$options.needle=b,i.$options.backwards=c==-1,i.find(a)}function m(a,b){return a.row==b.row&&a.column==b.column}function n(a){a.$onAddRange=a.$onAddRange.bind(a),a.$onRemoveRange=a.$onRemoveRange.bind(a),a.$onMultiSelect=a.$onMultiSelect.bind(a),a.$onSingleSelect=a.$onSingleSelect.bind(a),b.onSessionChange.call(a,a),a.on("changeSession",b.onSessionChange.bind(a)),a.on("mousedown",g),a.commands.addCommands(b.commands.defaultCommands)}var d=a("./range_list").RangeList,e=a("./range").Range,f=a("./selection").Selection,g=a("./mouse/multi_select_handler").onMouseDown;b.commands=a("./commands/multi_select_commands");var h=a("./search").Search,i=new h,k=a("./edit_session").EditSession;(function(){this.getSelectionMarkers=function(){return this.$selectionMarkers}}).call(k.prototype),function(){this.ranges=null,this.rangeList=null,this.addRange=function(a){if(!this.inMultiSelectMode&&this.rangeCount==0){var b=this.toOrientedRange();if(!a||!a.isEqual(b))this.rangeList.add(b),this.$onAddRange(b)}if(!a)return;a.cursor||(a.cursor=a.end);var c=this.rangeList.add(a);this.$onAddRange(a),c.length&&this.$onRemoveRange(c),this.rangeCount>0&&!this.inMultiSelectMode&&(this._emit("multiSelect"),this.inMultiSelectMode=!0,this.session.$undoSelect=!1,this.rangeList.attach(this.session))},this.toSingleRange=function(a){a=a||this.ranges[0];var b=this.rangeList.removeAll();b.length&&this.$onRemoveRange(b),a&&this.fromOrientedRange(a)},this.substractPoint=function(a){var b=this.rangeList.substractPoint(a);if(b)return this.$onRemoveRange(b),b[0]},this.mergeOverlappingRanges=function(){var a=this.rangeList.merge();a.length?this.$onRemoveRange(a):this.ranges[0]&&this.fromOrientedRange(this.ranges[0])},this.$onAddRange=function(a){this.rangeCount=this.rangeList.ranges.length,this.ranges.unshift(a),this.fromOrientedRange(a),this._emit("addRange",{range:a})},this.$onRemoveRange=function(a){this.rangeCount=this.rangeList.ranges.length;if(this.rangeCount==1&&this.inMultiSelectMode){var b=this.rangeList.ranges.pop();a.push(b),this.rangeCount=0}for(var c=a.length;c--;){var d=this.ranges.indexOf(a[c]);this.ranges.splice(d,1)}this._emit("removeRange",{ranges:a}),this.rangeCount==0&&this.inMultiSelectMode&&(this.inMultiSelectMode=!1,this._emit("singleSelect"),this.session.$undoSelect=!0,this.rangeList.detach(this.session)),b=b||this.ranges[0],b&&!b.isEqual(this.getRange())&&this.fromOrientedRange(b)},this.$initRangeList=function(){if(this.rangeList)return;this.rangeList=new d,this.ranges=[],this.rangeCount=0},this.getAllRanges=function(){return this.rangeList.ranges.concat()},this.splitIntoLines=function(){if(this.rangeCount>1){var a=this.rangeList.ranges,b=a[a.length-1],c=e.fromPoints(a[0].start,b.end);this.toSingleRange(),this.setSelectionRange(c,b.cursor==b.start)}else{var d=this.session.documentToScreenPosition(this.selectionLead),f=this.session.documentToScreenPosition(this.selectionAnchor),g=this.rectangularRangeBlock(d,f);g.forEach(this.addRange,this)}},this.rectangularRangeBlock=function(a,b,c){var d=[],f=a.column<b.column;if(f)var g=a.column,h=b.column;else var g=b.column,h=a.column;var i=a.row<b.row;if(i)var j=a.row,k=b.row;else var j=b.row,k=a.row;g<0&&(g=0),j<0&&(j=0),j==k&&(c=!0);for(var l=j;l<=k;l++){var n=e.fromPoints(this.session.screenToDocumentPosition(l,g),this.session.screenToDocumentPosition(l,h));if(n.isEmpty()){if(o&&m(n.end,o))break;var o=n.end}n.cursor=f?n.start:n.end,d.push(n)}i&&d.reverse();if(!c){var p=d.length-1;while(d[p].isEmpty()&&p>0)p--;if(p>0){var q=0;while(d[q].isEmpty())q++}for(var r=p;r>=q;r--)d[r].isEmpty()&&d.splice(r,1)}return d}}.call(f.prototype);var l=a("./editor").Editor;(function(){this.updateSelectionMarkers=function(){this.renderer.updateCursor(),this.renderer.updateBackMarkers()},this.addSelectionMarker=function(a){a.cursor||(a.cursor=a.end);var b=this.getSelectionStyle();return a.marker=this.session.addMarker(a,"ace_selection",b),this.session.$selectionMarkers.push(a),this.session.selectionMarkerCount=this.session.$selectionMarkers.length,a},this.removeSelectionMarkers=function(a){for(var b=a.length;b--;){var c=a[b];if(!c.marker)continue;this.session.removeMarker(c.marker);var d=this.session.$selectionMarkers.indexOf(c);d!=-1&&this.session.$selectionMarkers.splice(d,1)}this.session.selectionMarkerCount=this.session.$selectionMarkers.length},this.$onAddRange=function(a){this.addSelectionMarker(a.range),this.renderer.updateCursor(),this.renderer.updateBackMarkers()},this.$onRemoveRange=function(a){this.removeSelectionMarkers(a.ranges),this.renderer.updateCursor(),this.renderer.updateBackMarkers()},this.$onMultiSelect=function(a){if(this.inMultiSelectMode)return;this.inMultiSelectMode=!0,this.setStyle("multiselect"),this.keyBinding.addKeyboardHandler(b.commands.keyboardHandler),this.commands.on("exec",this.$onMultiSelectExec),this.renderer.updateCursor(),this.renderer.updateBackMarkers()},this.$onSingleSelect=function(a){if(this.session.multiSelect.inVirtualMode)return;this.inMultiSelectMode=!1,this.unsetStyle("multiselect"),this.keyBinding.removeKeyboardHandler(b.commands.keyboardHandler),this.commands.removeEventListener("exec",this.$onMultiSelectExec),this.renderer.updateCursor(),this.renderer.updateBackMarkers()},this.$onMultiSelectExec=function(a){var b=a.command,c=a.editor;b.multiSelectAction?b.multiSelectAction=="forEach"?c.forEachSelection(b,a.args):b.multiSelectAction=="single"?(c.exitMultiSelectMode(),b.exec(c,a.args||{})):b.multiSelectAction(c,a.args||{}):(b.exec(c,a.args||{}),c.multiSelect.addRange(c.multiSelect.toOrientedRange()),c.multiSelect.mergeOverlappingRanges()),a.preventDefault()},this.forEachSelection=function(a,b){if(this.inVirtualSelectionMode)return;var c=this.session,d=this.selection,e=d.rangeList,g=d._eventRegistry;d._eventRegistry={};var h=new f(c);this.inVirtualSelectionMode=!0;for(var i=e.ranges.length;i--;)h.fromOrientedRange(e.ranges[i]),this.selection=c.selection=h,a.exec(this,b||{}),h.toOrientedRange(e.ranges[i]);h.detach(),this.selection=c.selection=d,this.inVirtualSelectionMode=!1,d._eventRegistry=g,d.mergeOverlappingRanges(),this.onCursorChange(),this.onSelectionChange()},this.exitMultiSelectMode=function(){if(this.inVirtualSelectionMode)return;this.multiSelect.toSingleRange()},this.getCopyText=function(){var a="";if(this.inMultiSelectMode){var b=this.multiSelect.rangeList.ranges;a=[];for(var c=0;c<b.length;c++)a.push(this.session.getTextRange(b[c]));a=a.join(this.session.getDocument().getNewLineCharacter())}else this.selection.isEmpty()||(a=this.session.getTextRange(this.getSelectionRange()));return a},this.selectMoreLines=function(a,b){var c=this.selection.toOrientedRange(),d=c.cursor==c.end,f=this.session.documentToScreenPosition(c.cursor);this.selection.$desiredColumn&&(f.column=this.selection.$desiredColumn);var g=this.session.screenToDocumentPosition(f.row+a,f.column);if(!c.isEmpty())var h=this.session.documentToScreenPosition(d?c.end:c.start),i=this.session.screenToDocumentPosition(h.row+a,h.column);else var i=g;if(d){var j=e.fromPoints(g,i);j.cursor=j.start}else{var j=e.fromPoints(i,g);j.cursor=j.end}j.desiredColumn=f.column;if(!this.selection.inMultiSelectMode)this.selection.addRange(c);else if(b)var k=c.cursor;this.selection.addRange(j),k&&this.selection.substractPoint(k)},this.transposeSelections=function(a){var b=this.session,c=b.multiSelect,d=c.ranges;for(var e=d.length;e--;){var f=d[e];if(f.isEmpty()){var g=b.getWordRange(f.start.row,f.start.column);f.start.row=g.start.row,f.start.column=g.start.column,f.end.row=g.end.row,f.end.column=g.end.column}}c.mergeOverlappingRanges();var h=[];for(var e=d.length;e--;){var f=d[e];h.unshift(b.getTextRange(f))}a<0?h.unshift(h.pop()):h.push(h.shift());for(var e=d.length;e--;){var f=d[e],g=f.clone();b.replace(f,h[e]),f.start.row=g.start.row,f.start.column=g.start.column}},this.selectMore=function(a,b){var c=this.session,d=c.multiSelect,e=d.toOrientedRange();if(e.isEmpty()){var e=c.getWordRange(e.start.row,e.start.column);e.cursor=e.end,this.multiSelect.addRange(e)}var f=c.getTextRange(e),g=j(c,f,a);g&&(g.cursor=a==-1?g.start:g.end,this.multiSelect.addRange(g)),b&&this.multiSelect.substractPoint(e.cursor)}}).call(l.prototype),b.onSessionChange=function(a){var b=a.session;b.multiSelect||(b.$selectionMarkers=[],b.selection.$initRangeList(),b.multiSelect=b.selection),this.multiSelect=b.multiSelect;var c=a.oldSession;c&&(c.multiSelect&&c.multiSelect.editor==this&&(c.multiSelect.editor=null),b.multiSelect.removeEventListener("addRange",this.$onAddRange),b.multiSelect.removeEventListener("removeRange",this.$onRemoveRange),b.multiSelect.removeEventListener("multiSelect",this.$onMultiSelect),b.multiSelect.removeEventListener("singleSelect",this.$onSingleSelect)),b.multiSelect.on("addRange",this.$onAddRange),b.multiSelect.on("removeRange",this.$onRemoveRange),b.multiSelect.on("multiSelect",this.$onMultiSelect),b.multiSelect.on("singleSelect",this.$onSingleSelect),this.inMultiSelectMode!=b.selection.inMultiSelectMode&&(b.selection.inMultiSelectMode?this.$onMultiSelect():this.$onSingleSelect())},b.MultiSelect=n}),define("ace/range_list",["require","exports","module"],function(a,b,c){"use strict";var d=function(){this.ranges=[]};(function(){this.comparePoints=function(a,b){return a.row-b.row||a.column-b.column},this.pointIndex=function(a,b){var c=this.ranges;for(var d=b||0;d<c.length;d++){var e=c[d],f=this.comparePoints(a,e.end);if(f>0)continue;return f==0?d:(f=this.comparePoints(a,e.start),f>=0?d:-d-1)}return-d-1},this.add=function(a){var b=this.pointIndex(a.start);b<0&&(b=-b-1);var c=this.pointIndex(a.end,b);return c<0?c=-c-1:c++,this.ranges.splice(b,c-b,a)},this.addList=function(a){var b=[];for(var c=a.length;c--;)b.push.call(b,this.add(a[c]));return b},this.substractPoint=function(a){var b=this.pointIndex(a);if(b>=0)return this.ranges.splice(b,1)},this.merge=function(){var a=[],b=this.ranges,c=b[0],d;for(var e=1;e<b.length;e++){d=c,c=b[e];var f=this.comparePoints(d.end,c.start);if(f<0)continue;if(f==0&&!d.isEmpty()&&!c.isEmpty())continue;this.comparePoints(d.end,c.end)<0&&(d.end.row=c.end.row,d.end.column=c.end.column),b.splice(e,1),a.push(c),c=d,e--}return a},this.contains=function(a,b){return this.pointIndex({row:a,column:b})>=0},this.containsPoint=function(a){return this.pointIndex(a)>=0},this.rangeAtPoint=function(a){var b=this.pointIndex(a);if(b>=0)return this.ranges[b]},this.clipRows=function(a,b){var c=this.ranges;if(c[0].start.row>b||c[c.length-1].start.row<a)return[];var d=this.pointIndex({row:a,column:0});d<0&&(d=-d-1);var e=this.pointIndex({row:b,column:0},d);e<0&&(e=-e-1);var f=[];for(var g=d;g<e;g++)f.push(c[g]);return f},this.removeAll=function(){return this.ranges.splice(0,this.ranges.length)},this.attach=function(a){this.session&&this.detach(),this.session=a,this.onChange=this.$onChange.bind(this),this.session.on("change",this.onChange)},this.detach=function(){if(!this.session)return;this.session.removeListener("change",this.onChange),this.session=null},this.$onChange=function(a){var b=a.data.range;if(a.data.action[0]=="i")var c=b.start,d=b.end;else var d=b.start,c=b.end;var e=c.row,f=d.row,g=f-e,h=-c.column+d.column,i=this.ranges;for(var j=0,k=i.length;j<k;j++){var l=i[j];if(l.end.row<e)continue;if(l.start.row>e)break;l.start.row==e&&l.start.column>=c.column&&(l.start.column+=h,l.start.row+=g),l.end.row==e&&l.end.column>=c.column&&(l.end.column+=h,l.end.row+=g)}if(g!=0&&j<k)for(;j<k;j++){var l=i[j];l.start.row+=g,l.end.row+=g}}}).call(d.prototype),b.RangeList=d}),define("ace/mouse/multi_select_handler",["require","exports","module","ace/lib/event"],function(a,b,c){function e(a,b){return a.row==b.row&&a.column==b.column}function f(a){var b=a.domEvent,c=b.altKey,f=b.shiftKey,g=a.getAccelKey(),h=a.getButton();if(!g&&!c){if(a.editor.inMultiSelectMode)if(h==0)a.editor.exitMultiSelectMode();else if(h==2){var i=a.editor,j=i.selection.isEmpty();i.textInput.onContextMenu({x:a.clientX,y:a.clientY},j),d.capture(i.container,function(){},i.textInput.onContextMenuClose),a.stop()}return}var i=a.editor,k=i.selection,l=i.inMultiSelectMode,m=a.getDocumentPosition(),n=k.getCursor(),o=a.inSelection()||k.isEmpty()&&e(m,n),p=a.pageX,q=a.pageY,r=function(a){p=d.getDocumentX(a),q=d.getDocumentY(a)},s=function(){var a=i.renderer.pixelToScreenCoordinates(p,q),b=t.screenToDocumentPosition(a.row,a.column);if(e(v,a)&&e(b,k.selectionLead))return;v=a,i.selection.moveCursorToPosition(b),i.selection.clearSelection(),i.renderer.scrollCursorIntoView(),i.removeSelectionMarkers(x),x=k.rectangularRangeBlock(v,u),x.forEach(i.addSelectionMarker,i),i.updateSelectionMarkers()},t=i.session,u=i.renderer.pixelToScreenCoordinates(p,q),v=u;if(g&&!f&&!c&&h==0){if(!l&&o)return;l||k.addRange(k.toOrientedRange());var w=k.rangeList.rangeAtPoint(m);d.capture(i.container,function(){},function(){var a=k.toOrientedRange();w&&a.isEmpty()&&e(w.cursor,a.cursor)?k.substractPoint(a.cursor):k.addRange(a)})}else if(!f&&c&&h==0){a.stop(),l&&!g?k.toSingleRange():!l&&g&&k.addRange(),k.moveCursorToPosition(m),k.clearSelection();var x=[],y=function(a){clearInterval(A),i.removeSelectionMarkers(x);for(var b=0;b<x.length;b++)k.addRange(x[b])},z=s;d.capture(i.container,r,y);var A=setInterval(function(){z()},20);return a.preventDefault()}}var d=a("../lib/event");b.onMouseDown=f}),define("ace/commands/multi_select_commands",["require","exports","module","ace/keyboard/hash_handler"],function(a,b,c){b.defaultCommands=[{name:"addCursorAbove",exec:function(a){a.selectMoreLines(-1)},bindKey:{win:"Ctrl-Alt-Up",mac:"Ctrl-Alt-Up"},readonly:!0},{name:"addCursorBelow",exec:function(a){a.selectMoreLines(1)},bindKey:{win:"Ctrl-Alt-Down",mac:"Ctrl-Alt-Down"},readonly:!0},{name:"addCursorAboveSkipCurrent",exec:function(a){a.selectMoreLines(-1,!0)},bindKey:{win:"Ctrl-Alt-Shift-Up",mac:"Ctrl-Alt-Shift-Up"},readonly:!0},{name:"addCursorBelowSkipCurrent",exec:function(a){a.selectMoreLines(1,!0)},bindKey:{win:"Ctrl-Alt-Shift-Down",mac:"Ctrl-Alt-Shift-Down"},readonly:!0},{name:"selectMoreBefore",exec:function(a){a.selectMore(-1)},bindKey:{win:"Ctrl-Alt-Left",mac:"Ctrl-Alt-Left"},readonly:!0},{name:"selectMoreAfter",exec:function(a){a.selectMore(1)},bindKey:{win:"Ctrl-Alt-Right",mac:"Ctrl-Alt-Right"},readonly:!0},{name:"selectNextBefore",exec:function(a){a.selectMore(-1,!0)},bindKey:{win:"Ctrl-Alt-Shift-Left",mac:"Ctrl-Alt-Shift-Left"},readonly:!0},{name:"selectNextAfter",exec:function(a){a.selectMore(1,!0)},bindKey:{win:"Ctrl-Alt-Shift-Right",mac:"Ctrl-Alt-Shift-Right"},readonly:!0},{name:"splitIntoLines",exec:function(a){a.multiSelect.splitIntoLines()},bindKey:{win:"Ctrl-Shift-L",mac:"Ctrl-Shift-L"},readonly:!0}],b.multiEditCommands=[{name:"singleSelection",bindKey:"esc",exec:function(a){a.exitMultiSelectMode()},readonly:!0}];var d=a("../keyboard/hash_handler").HashHandler;b.keyboardHandler=new d(b.multiEditCommands)}),define("ace/worker/worker_client",["require","exports","module","ace/lib/oop","ace/lib/event_emitter","ace/config"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("../lib/event_emitter").EventEmitter,f=a("../config"),g=function(b,c,d,e){this.changeListener=this.changeListener.bind(this);if(f.get("packaged"))this.$worker=new Worker(f.get("workerPath")+"/"+c);else{var g=this.$normalizePath(a.nameToUrl("ace/worker/worker",null,"_"));this.$worker=new Worker(g);var h={};for(var i=0;i<b.length;i++){var j=b[i],k=this.$normalizePath(a.nameToUrl(j,null,"_").replace(/.js$/,""));h[j]=k}}this.$worker.postMessage({init:!0,tlns:h,module:d,classname:e}),this.callbackId=1,this.callbacks={};var l=this;this.$worker.onerror=function(a){throw window.console&&console.log&&console.log(a),a},this.$worker.onmessage=function(a){var b=a.data;switch(b.type){case"log":window.console&&console.log&&console.log(b.data);break;case"event":l._emit(b.name,{data:b.data});break;case"call":var c=l.callbacks[b.id];c&&(c(b.data),delete l.callbacks[b.id])}}};(function(){d.implement(this,e),this.$normalizePath=function(a){return a=a.replace(/^[a-z]+:\/\/[^\/]+/,""),a=location.protocol+"//"+location.host+(a.charAt(0)=="/"?"":location.pathname.replace(/\/[^\/]*$/,""))+"/"+a.replace(/^[\/]+/,""),a},this.terminate=function(){this._emit("terminate",{}),this.$worker.terminate(),this.$worker=null,this.$doc.removeEventListener("change",this.changeListener),this.$doc=null},this.send=function(a,b){this.$worker.postMessage({command:a,args:b})},this.call=function(a,b,c){if(c){var d=this.callbackId++;this.callbacks[d]=c,b.push(d)}this.send(a,b)},this.emit=function(a,b){try{this.$worker.postMessage({event:a,data:{data:b.data}})}catch(c){}},this.attachToDocument=function(a){this.$doc&&this.terminate(),this.$doc=a,this.call("setValue",[a.getValue()]),a.on("change",this.changeListener)},this.changeListener=function(a){a.range={start:a.data.range.start,end:a.data.range.end},this.emit("change",a)}}).call(g.prototype),b.WorkerClient=g}),define("ace/keyboard/state_handler",["require","exports","module"],function(a,b,c){function e(a){this.keymapping=this.$buildKeymappingRegex(a)}"use strict";var d=!1;e.prototype={$buildKeymappingRegex:function(a){for(var b in a)this.$buildBindingsRegex(a[b]);return a},$buildBindingsRegex:function(a){a.forEach(function(a){a.key?a.key=new RegExp("^"+a.key+"$"):Array.isArray(a.regex)?("key"in a||(a.key=new RegExp("^"+a.regex[1]+"$")),a.regex=new RegExp(a.regex.join("")+"$")):a.regex&&(a.regex=new RegExp(a.regex+"$"))})},$composeBuffer:function(a,b,c,d){if(a.state==null||a.buffer==null)a.state="start",a.buffer="";var e=[];b&1&&e.push("ctrl"),b&8&&e.push("command"),b&2&&e.push("option"),b&4&&e.push("shift"),c&&e.push(c);var f=e.join("-"),g=a.buffer+f;b!=2&&(a.buffer=g);var h={bufferToUse:g,symbolicName:f};return d&&(h.keyIdentifier=d.keyIdentifier),h},$find:function(a,b,c,e,f,g){var h={};return this.keymapping[a.state].some(function(i){var j;if(i.key&&!i.key.test(c))return!1;if(i.regex&&!(j=i.regex.exec(b)))return!1;if(i.match&&!i.match(b,e,f,c,g))return!1;if(i.disallowMatches)for(var k=0;k<i.disallowMatches.length;k++)if(!!j[i.disallowMatches[k]])return!1;if(i.exec){h.command=i.exec;if(i.params){var l;h.args={},i.params.forEach(function(a){a.match!=null&&j!=null?l=j[a.match]||a.defaultValue:l=a.defaultValue,a.type==="number"&&(l=parseInt(l)),h.args[a.name]=l})}a.buffer=""}return i.then&&(a.state=i.then,a.buffer=""),h.command==null&&(h.command="null"),d&&console.log("KeyboardStateMapper#find",i),!0}),h.command?h:(a.buffer="",!1)},handleKeyboard:function(a,b,c,e,f){if(b==0||c!=""&&c!=String.fromCharCode(0)){var g=this.$composeBuffer(a,b,c,f),h=g.bufferToUse,i=g.symbolicName,j=g.keyIdentifier;return g=this.$find(a,h,i,b,c,j),d&&console.log("KeyboardStateMapper#match",h,i,g),g}return null}},b.matchCharacterOnly=function(a,b,c,d){return b==0?!0:b==4&&c.length==1?!0:!1},b.StateHandler=e}),define("ace/placeholder",["require","exports","module","ace/range","ace/lib/event_emitter","ace/lib/oop"],function(a,b,c){"use strict";var d=a("./range").Range,e=a("./lib/event_emitter").EventEmitter,f=a("./lib/oop"),g=function(a,b,c,d,e,f){var g=this;this.length=b,this.session=a,this.doc=a.getDocument(),this.mainClass=e,this.othersClass=f,this.$onUpdate=this.onUpdate.bind(this),this.doc.on("change",this.$onUpdate),this.$others=d,this.$onCursorChange=function(){setTimeout(function(){g.onCursorChange()})},this.$pos=c;var h=a.getUndoManager().$undoStack||a.getUndoManager().$undostack||{length:-1};this.$undoStackDepth=h.length,this.setup(),a.selection.on("changeCursor",this.$onCursorChange)};(function(){f.implement(this,e),this.setup=function(){var a=this,b=this.doc,c=this.session,e=this.$pos;this.pos=b.createAnchor(e.row,e.column),this.markerId=c.addMarker(new d(e.row,e.column,e.row,e.column+this.length),this.mainClass,null,!1),this.pos.on("change",function(b){c.removeMarker(a.markerId),a.markerId=c.addMarker(new d(b.value.row,b.value.column,b.value.row,b.value.column+a.length),a.mainClass,null,!1)}),this.others=[],this.$others.forEach(function(c){var d=b.createAnchor(c.row,c.column);a.others.push(d)}),c.setUndoSelect(!1)},this.showOtherMarkers=function(){if(this.othersActive)return;var a=this.session,b=this;this.othersActive=!0,this.others.forEach(function(c){c.markerId=a.addMarker(new d(c.row,c.column,c.row,c.column+b.length),b.othersClass,null,!1),c.on("change",function(e){a.removeMarker(c.markerId),c.markerId=a.addMarker(new d(e.value.row,e.value.column,e.value.row,e.value.column+b.length),b.othersClass,null,!1)})})},this.hideOtherMarkers=function(){if(!this.othersActive)return;this.othersActive=!1;for(var a=0;a<this.others.length;a++)this.session.removeMarker(this.others[a].markerId)},this.onUpdate=function(a){var b=a.data,c=b.range;if(c.start.row!==c.end.row)return;if(c.start.row!==this.pos.row)return;if(this.$updating)return;this.$updating=!0;var e=b.action==="insertText"?c.end.column-c.start.column:c.start.column-c.end.column;if(c.start.column>=this.pos.column&&c.start.column<=this.pos.column+this.length+1){var f=c.start.column-this.pos.column;this.length+=e;if(!this.session.$fromUndo){if(b.action==="insertText")for(var g=this.others.length-1;g>=0;g--){var h=this.others[g],i={row:h.row,column:h.column+f};h.row===c.start.row&&c.start.column<h.column&&(i.column+=e),this.doc.insert(i,b.text)}else if(b.action==="removeText")for(var g=this.others.length-1;g>=0;g--){var h=this.others[g],i={row:h.row,column:h.column+f};h.row===c.start.row&&c.start.column<h.column&&(i.column+=e),this.doc.remove(new d(i.row,i.column,i.row,i.column-e))}c.start.column===this.pos.column&&b.action==="insertText"?setTimeout(function(){this.pos.setPosition(this.pos.row,this.pos.column-e);for(var a=0;a<this.others.length;a++){var b=this.others[a],d={row:b.row,column:b.column-e};b.row===c.start.row&&c.start.column<b.column&&(d.column+=e),b.setPosition(d.row,d.column)}}.bind(this),0):c.start.column===this.pos.column&&b.action==="removeText"&&setTimeout(function(){for(var a=0;a<this.others.length;a++){var b=this.others[a];b.row===c.start.row&&c.start.column<b.column&&b.setPosition(b.row,b.column-e)}}.bind(this),0)}this.pos._emit("change",{value:this.pos});for(var g=0;g<this.others.length;g++)this.others[g]._emit("change",{value:this.others[g]})}this.$updating=!1},this.onCursorChange=function(a){if(this.$updating)return;var b=this.session.selection.getCursor();b.row===this.pos.row&&b.column>=this.pos.column&&b.column<=this.pos.column+this.length?(this.showOtherMarkers(),this._emit("cursorEnter",a)):(this.hideOtherMarkers(),this._emit("cursorLeave",a))},this.detach=function(){this.session.removeMarker(this.markerId),this.hideOtherMarkers(),this.doc.removeEventListener("change",this.$onUpdate),this.session.selection.removeEventListener("changeCursor",this.$onCursorChange),this.pos.detach();for(var a=0;a<this.others.length;a++)this.others[a].detach();this.session.setUndoSelect(!0)},this.cancel=function(){if(this.$undoStackDepth===-1)throw Error("Canceling placeholders only supported with undo manager attached to session.");var a=this.session.getUndoManager(),b=(a.$undoStack||a.$undostack).length-this.$undoStackDepth;for(var c=0;c<b;c++)a.undo(!0)}}).call(g.prototype),b.PlaceHolder=g}),define("ace/theme/textmate",["require","exports","module","ace/lib/dom"],function(a,b,c){"use strict",b.isDark=!1,b.cssClass="ace-tm",b.cssText=".ace-tm .ace_editor {  border: 2px solid rgb(159, 159, 159);}.ace-tm .ace_editor.ace_focus {  border: 2px solid #327fbd;}.ace-tm .ace_gutter {  background: #e8e8e8;  color: #333;}.ace-tm .ace_print_margin {  width: 1px;  background: #e8e8e8;}.ace-tm .ace_fold {    background-color: #6B72E6;}.ace-tm .ace_text-layer {  cursor: text;}.ace-tm .ace_cursor {  border-left: 1px solid black;}.ace-tm .ace_cursor.ace_overwrite {  border-left: 0px;  border-bottom: 1px solid black;}        .ace-tm .ace_line .ace_invisible {  color: rgb(191, 191, 191);}.ace-tm .ace_line .ace_storage,.ace-tm .ace_line .ace_keyword {  color: blue;}.ace-tm .ace_line .ace_constant {  color: rgb(197, 6, 11);}.ace-tm .ace_line .ace_constant.ace_buildin {  color: rgb(88, 72, 246);}.ace-tm .ace_line .ace_constant.ace_language {  color: rgb(88, 92, 246);}.ace-tm .ace_line .ace_constant.ace_library {  color: rgb(6, 150, 14);}.ace-tm .ace_line .ace_invalid {  background-color: rgb(153, 0, 0);  color: white;}.ace-tm .ace_line .ace_support.ace_function {  color: rgb(60, 76, 114);}.ace-tm .ace_line .ace_support.ace_constant {  color: rgb(6, 150, 14);}.ace-tm .ace_line .ace_support.ace_type,.ace-tm .ace_line .ace_support.ace_class {  color: rgb(109, 121, 222);}.ace-tm .ace_line .ace_keyword.ace_operator {  color: rgb(104, 118, 135);}.ace-tm .ace_line .ace_string {  color: rgb(3, 106, 7);}.ace-tm .ace_line .ace_comment {  color: rgb(76, 136, 107);}.ace-tm .ace_line .ace_comment.ace_doc {  color: rgb(0, 102, 255);}.ace-tm .ace_line .ace_comment.ace_doc.ace_tag {  color: rgb(128, 159, 191);}.ace-tm .ace_line .ace_constant.ace_numeric {  color: rgb(0, 0, 205);}.ace-tm .ace_line .ace_variable {  color: rgb(49, 132, 149);}.ace-tm .ace_line .ace_xml_pe {  color: rgb(104, 104, 91);}.ace-tm .ace_entity.ace_name.ace_function {  color: #0000A2;}.ace-tm .ace_markup.ace_markupine {    text-decoration:underline;}.ace-tm .ace_markup.ace_heading {  color: rgb(12, 7, 255);}.ace-tm .ace_markup.ace_list {  color:rgb(185, 6, 144);}.ace-tm .ace_marker-layer .ace_selection {  background: rgb(181, 213, 255);}.ace-tm .ace_marker-layer .ace_step {  background: rgb(252, 255, 0);}.ace-tm .ace_marker-layer .ace_stack {  background: rgb(164, 229, 101);}.ace-tm .ace_marker-layer .ace_bracket {  margin: -1px 0 0 -1px;  border: 1px solid rgb(192, 192, 192);}.ace-tm .ace_marker-layer .ace_active_line {  background: rgba(0, 0, 0, 0.07);}.ace-tm .ace_marker-layer .ace_selected_word {  background: rgb(250, 250, 255);  border: 1px solid rgb(200, 200, 250);}.ace-tm .ace_meta.ace_tag {  color:rgb(28, 2, 255);}.ace-tm .ace_string.ace_regex {  color: rgb(255, 0, 0)}";var d=a("../lib/dom");d.importCssString(b.cssText,b.cssClass)});
+            (function() {
+                window.require(["ace/ace"], function(a) {
+                    if (!window.ace)
+                        window.ace = {};
+                    for (var key in a) if (a.hasOwnProperty(key))
+                        ace[key] = a[key];
+                });
+            })();
+        
\ No newline at end of file
diff --git a/apps/files_texteditor/js/aceeditor/keybinding-emacs-uncompressed.js b/apps/files_texteditor/js/aceeditor/keybinding-emacs-uncompressed.js
old mode 100755
new mode 100644
index 1d40eb461f47499d703c78defc7a149254206b9e..757c908c9f4c68081f4a962c48664fc753477ce8
--- a/apps/files_texteditor/js/aceeditor/keybinding-emacs-uncompressed.js
+++ b/apps/files_texteditor/js/aceeditor/keybinding-emacs-uncompressed.js
@@ -148,268 +148,3 @@ var emacsState = {
 exports.Emacs = new StateHandler(emacsState);
 
 });
-/* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is Mozilla Skywriter.
- *
- * The Initial Developer of the Original Code is
- * Mozilla.
- * Portions created by the Initial Developer are Copyright (C) 2009
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *   Julian Viereck (julian.viereck@gmail.com)
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-define('ace/keyboard/state_handler', ['require', 'exports', 'module' ], function(require, exports, module) {
-"use strict";
-
-// If you're developing a new keymapping and want to get an idea what's going
-// on, then enable debugging.
-var DEBUG = false;
-
-function StateHandler(keymapping) {
-    this.keymapping = this.$buildKeymappingRegex(keymapping);
-}
-
-StateHandler.prototype = {
-    /**
-     * Build the RegExp from the keymapping as RegExp can't stored directly
-     * in the metadata JSON and as the RegExp used to match the keys/buffer
-     * need to be adapted.
-     */
-    $buildKeymappingRegex: function(keymapping) {
-        for (var state in keymapping) {
-            this.$buildBindingsRegex(keymapping[state]);
-        }
-        return keymapping;
-    },
-
-    $buildBindingsRegex: function(bindings) {
-        // Escape a given Regex string.
-        bindings.forEach(function(binding) {
-            if (binding.key) {
-                binding.key = new RegExp('^' + binding.key + '$');
-            } else if (Array.isArray(binding.regex)) {
-                if (!('key' in binding))
-                  binding.key = new RegExp('^' + binding.regex[1] + '$');
-                binding.regex = new RegExp(binding.regex.join('') + '$');
-            } else if (binding.regex) {
-                binding.regex = new RegExp(binding.regex + '$');
-            }
-        });
-    },
-
-    $composeBuffer: function(data, hashId, key, e) {
-        // Initialize the data object.
-        if (data.state == null || data.buffer == null) {
-            data.state = "start";
-            data.buffer = "";
-        }
-
-        var keyArray = [];
-        if (hashId & 1) keyArray.push("ctrl");
-        if (hashId & 8) keyArray.push("command");
-        if (hashId & 2) keyArray.push("option");
-        if (hashId & 4) keyArray.push("shift");
-        if (key)        keyArray.push(key);
-
-        var symbolicName = keyArray.join("-");
-        var bufferToUse = data.buffer + symbolicName;
-
-        // Don't add the symbolic name to the key buffer if the alt_ key is
-        // part of the symbolic name. If it starts with alt_, this means
-        // that the user hit an alt keycombo and there will be a single,
-        // new character detected after this event, which then will be
-        // added to the buffer (e.g. alt_j will result in ∆).
-        //
-        // We test for 2 and not for & 2 as we only want to exclude the case where
-        // the option key is pressed alone.
-        if (hashId != 2) {
-            data.buffer = bufferToUse;
-        }
-
-        var bufferObj = {
-            bufferToUse: bufferToUse,
-            symbolicName: symbolicName,
-        };
-
-        if (e) {
-            bufferObj.keyIdentifier = e.keyIdentifier
-        }
-
-        return bufferObj;
-    },
-
-    $find: function(data, buffer, symbolicName, hashId, key, keyIdentifier) {
-        // Holds the command to execute and the args if a command matched.
-        var result = {};
-
-        // Loop over all the bindings of the keymap until a match is found.
-        this.keymapping[data.state].some(function(binding) {
-            var match;
-
-            // Check if the key matches.
-            if (binding.key && !binding.key.test(symbolicName)) {
-                return false;
-            }
-
-            // Check if the regex matches.
-            if (binding.regex && !(match = binding.regex.exec(buffer))) {
-                return false;
-            }
-
-            // Check if the match function matches.
-            if (binding.match && !binding.match(buffer, hashId, key, symbolicName, keyIdentifier)) {
-                return false;
-            }
-
-            // Check for disallowed matches.
-            if (binding.disallowMatches) {
-                for (var i = 0; i < binding.disallowMatches.length; i++) {
-                    if (!!match[binding.disallowMatches[i]]) {
-                        return false;
-                    }
-                }
-            }
-
-            // If there is a command to execute, then figure out the
-            // command and the arguments.
-            if (binding.exec) {
-                result.command = binding.exec;
-
-                // Build the arguments.
-                if (binding.params) {
-                    var value;
-                    result.args = {};
-                    binding.params.forEach(function(param) {
-                        if (param.match != null && match != null) {
-                            value = match[param.match] || param.defaultValue;
-                        } else {
-                            value = param.defaultValue;
-                        }
-
-                        if (param.type === 'number') {
-                            value = parseInt(value);
-                        }
-
-                        result.args[param.name] = value;
-                    });
-                }
-                data.buffer = "";
-            }
-
-            // Handle the 'then' property.
-            if (binding.then) {
-                data.state = binding.then;
-                data.buffer = "";
-            }
-
-            // If no command is set, then execute the "null" fake command.
-            if (result.command == null) {
-                result.command = "null";
-            }
-
-            if (DEBUG) {
-                console.log("KeyboardStateMapper#find", binding);
-            }
-            return true;
-        });
-
-        if (result.command) {
-            return result;
-        } else {
-            data.buffer = "";
-            return false;
-        }
-    },
-
-    /**
-     * This function is called by keyBinding.
-     */
-    handleKeyboard: function(data, hashId, key, keyCode, e) {
-        // If we pressed any command key but no other key, then ignore the input.
-        // Otherwise "shift-" is added to the buffer, and later on "shift-g"
-        // which results in "shift-shift-g" which doesn't make sense.
-        if (hashId != 0 && (key == "" || key == String.fromCharCode(0))) {
-            return null;
-        }
-
-        // Compute the current value of the keyboard input buffer.
-        var r = this.$composeBuffer(data, hashId, key, e);
-        var buffer = r.bufferToUse;
-        var symbolicName = r.symbolicName;
-        var keyId = r.keyIdentifier;
-
-        r = this.$find(data, buffer, symbolicName, hashId, key, keyId);
-        if (DEBUG) {
-            console.log("KeyboardStateMapper#match", buffer, symbolicName, r);
-        }
-
-        return r;
-    }
-}
-
-/**
- * This is a useful matching function and therefore is defined here so that
- * users of KeyboardStateMapper can use it.
- *
- * @return boolean
- *          If no command key (Command|Option|Shift|Ctrl) is pressed, it
- *          returns true. If the only the Shift key is pressed + a character
- *          true is returned as well. Otherwise, false is returned.
- *          Summing up, the function returns true whenever the user typed
- *          a normal character on the keyboard and no shortcut.
- */
-exports.matchCharacterOnly = function(buffer, hashId, key, symbolicName) {
-    // If no command keys are pressed, then catch the input.
-    if (hashId == 0) {
-        return true;
-    }
-    // If only the shift key is pressed and a character key, then
-    // catch that input as well.
-    else if ((hashId == 4) && key.length == 1) {
-        return true;
-    }
-    // Otherwise, we let the input got through.
-    else {
-        return false;
-    }
-};
-
-exports.StateHandler = StateHandler;
-});
-;
-            (function() {
-                window.require(["ace/ace"], function(a) {
-                    if (!window.ace)
-                        window.ace = {};
-                    for (var key in a) if (a.hasOwnProperty(key))
-                        ace[key] = a[key];
-                });
-            })();
-        
\ No newline at end of file
diff --git a/apps/files_texteditor/js/aceeditor/keybinding-emacs.js b/apps/files_texteditor/js/aceeditor/keybinding-emacs.js
old mode 100755
new mode 100644
index 7ddcd7623bd31c517b007c993ccbb0a16e048acf..f2eb354a9dc73d2e7c72bb27290ae8dc95ca33a2
--- a/apps/files_texteditor/js/aceeditor/keybinding-emacs.js
+++ b/apps/files_texteditor/js/aceeditor/keybinding-emacs.js
@@ -1 +1 @@
-define("ace/keyboard/keybinding/emacs",["require","exports","module","ace/keyboard/state_handler"],function(a,b,c){"use strict";var d=a("../state_handler").StateHandler,e=a("../state_handler").matchCharacterOnly,f={start:[{key:"ctrl-x",then:"c-x"},{regex:["(?:command-([0-9]*))*","(down|ctrl-n)"],exec:"golinedown",params:[{name:"times",match:1,type:"number",defaultValue:1}]},{regex:["(?:command-([0-9]*))*","(right|ctrl-f)"],exec:"gotoright",params:[{name:"times",match:1,type:"number",defaultValue:1}]},{regex:["(?:command-([0-9]*))*","(up|ctrl-p)"],exec:"golineup",params:[{name:"times",match:1,type:"number",defaultValue:1}]},{regex:["(?:command-([0-9]*))*","(left|ctrl-b)"],exec:"gotoleft",params:[{name:"times",match:1,type:"number",defaultValue:1}]},{comment:"This binding matches all printable characters except numbers as long as they are no numbers and print them n times.",regex:["(?:command-([0-9]*))","([^0-9]+)*"],match:e,exec:"inserttext",params:[{name:"times",match:1,type:"number",defaultValue:"1"},{name:"text",match:2}]},{comment:"This binding matches numbers as long as there is no meta_number in the buffer.",regex:["(command-[0-9]*)*","([0-9]+)"],match:e,disallowMatches:[1],exec:"inserttext",params:[{name:"text",match:2,type:"text"}]},{regex:["command-([0-9]*)","(command-[0-9]|[0-9])"],comment:"Stops execution if the regex /meta_[0-9]+/ matches to avoid resetting the buffer."}],"c-x":[{key:"ctrl-g",then:"start"},{key:"ctrl-s",exec:"save",then:"start"}]};b.Emacs=new d(f)}),define("ace/keyboard/state_handler",["require","exports","module"],function(a,b,c){function e(a){this.keymapping=this.$buildKeymappingRegex(a)}"use strict";var d=!1;e.prototype={$buildKeymappingRegex:function(a){for(var b in a)this.$buildBindingsRegex(a[b]);return a},$buildBindingsRegex:function(a){a.forEach(function(a){a.key?a.key=new RegExp("^"+a.key+"$"):Array.isArray(a.regex)?("key"in a||(a.key=new RegExp("^"+a.regex[1]+"$")),a.regex=new RegExp(a.regex.join("")+"$")):a.regex&&(a.regex=new RegExp(a.regex+"$"))})},$composeBuffer:function(a,b,c,d){if(a.state==null||a.buffer==null)a.state="start",a.buffer="";var e=[];b&1&&e.push("ctrl"),b&8&&e.push("command"),b&2&&e.push("option"),b&4&&e.push("shift"),c&&e.push(c);var f=e.join("-"),g=a.buffer+f;b!=2&&(a.buffer=g);var h={bufferToUse:g,symbolicName:f};return d&&(h.keyIdentifier=d.keyIdentifier),h},$find:function(a,b,c,e,f,g){var h={};return this.keymapping[a.state].some(function(i){var j;if(i.key&&!i.key.test(c))return!1;if(i.regex&&!(j=i.regex.exec(b)))return!1;if(i.match&&!i.match(b,e,f,c,g))return!1;if(i.disallowMatches)for(var k=0;k<i.disallowMatches.length;k++)if(!!j[i.disallowMatches[k]])return!1;if(i.exec){h.command=i.exec;if(i.params){var l;h.args={},i.params.forEach(function(a){a.match!=null&&j!=null?l=j[a.match]||a.defaultValue:l=a.defaultValue,a.type==="number"&&(l=parseInt(l)),h.args[a.name]=l})}a.buffer=""}return i.then&&(a.state=i.then,a.buffer=""),h.command==null&&(h.command="null"),d&&console.log("KeyboardStateMapper#find",i),!0}),h.command?h:(a.buffer="",!1)},handleKeyboard:function(a,b,c,e,f){if(b==0||c!=""&&c!=String.fromCharCode(0)){var g=this.$composeBuffer(a,b,c,f),h=g.bufferToUse,i=g.symbolicName,j=g.keyIdentifier;return g=this.$find(a,h,i,b,c,j),d&&console.log("KeyboardStateMapper#match",h,i,g),g}return null}},b.matchCharacterOnly=function(a,b,c,d){return b==0?!0:b==4&&c.length==1?!0:!1},b.StateHandler=e}),function(){window.require(["ace/ace"],function(a){window.ace||(window.ace={});for(var b in a)a.hasOwnProperty(b)&&(ace[b]=a[b])})}()
\ No newline at end of file
+define("ace/keyboard/keybinding/emacs",["require","exports","module","ace/keyboard/state_handler"],function(a,b,c){"use strict";var d=a("../state_handler").StateHandler,e=a("../state_handler").matchCharacterOnly,f={start:[{key:"ctrl-x",then:"c-x"},{regex:["(?:command-([0-9]*))*","(down|ctrl-n)"],exec:"golinedown",params:[{name:"times",match:1,type:"number",defaultValue:1}]},{regex:["(?:command-([0-9]*))*","(right|ctrl-f)"],exec:"gotoright",params:[{name:"times",match:1,type:"number",defaultValue:1}]},{regex:["(?:command-([0-9]*))*","(up|ctrl-p)"],exec:"golineup",params:[{name:"times",match:1,type:"number",defaultValue:1}]},{regex:["(?:command-([0-9]*))*","(left|ctrl-b)"],exec:"gotoleft",params:[{name:"times",match:1,type:"number",defaultValue:1}]},{comment:"This binding matches all printable characters except numbers as long as they are no numbers and print them n times.",regex:["(?:command-([0-9]*))","([^0-9]+)*"],match:e,exec:"inserttext",params:[{name:"times",match:1,type:"number",defaultValue:"1"},{name:"text",match:2}]},{comment:"This binding matches numbers as long as there is no meta_number in the buffer.",regex:["(command-[0-9]*)*","([0-9]+)"],match:e,disallowMatches:[1],exec:"inserttext",params:[{name:"text",match:2,type:"text"}]},{regex:["command-([0-9]*)","(command-[0-9]|[0-9])"],comment:"Stops execution if the regex /meta_[0-9]+/ matches to avoid resetting the buffer."}],"c-x":[{key:"ctrl-g",then:"start"},{key:"ctrl-s",exec:"save",then:"start"}]};b.Emacs=new d(f)})
\ No newline at end of file
diff --git a/apps/files_texteditor/js/aceeditor/keybinding-vim-uncompressed.js b/apps/files_texteditor/js/aceeditor/keybinding-vim-uncompressed.js
old mode 100755
new mode 100644
index bd73027847710470f6dcbb9211304a9580542ed1..3643eb3fd67f34b776fa695e556b10a0f8a5634b
--- a/apps/files_texteditor/js/aceeditor/keybinding-vim-uncompressed.js
+++ b/apps/files_texteditor/js/aceeditor/keybinding-vim-uncompressed.js
@@ -136,268 +136,3 @@ var vimStates = {
 exports.Vim = new StateHandler(vimStates);
 
 });
-/* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is Mozilla Skywriter.
- *
- * The Initial Developer of the Original Code is
- * Mozilla.
- * Portions created by the Initial Developer are Copyright (C) 2009
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *   Julian Viereck (julian.viereck@gmail.com)
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-define('ace/keyboard/state_handler', ['require', 'exports', 'module' ], function(require, exports, module) {
-"use strict";
-
-// If you're developing a new keymapping and want to get an idea what's going
-// on, then enable debugging.
-var DEBUG = false;
-
-function StateHandler(keymapping) {
-    this.keymapping = this.$buildKeymappingRegex(keymapping);
-}
-
-StateHandler.prototype = {
-    /**
-     * Build the RegExp from the keymapping as RegExp can't stored directly
-     * in the metadata JSON and as the RegExp used to match the keys/buffer
-     * need to be adapted.
-     */
-    $buildKeymappingRegex: function(keymapping) {
-        for (var state in keymapping) {
-            this.$buildBindingsRegex(keymapping[state]);
-        }
-        return keymapping;
-    },
-
-    $buildBindingsRegex: function(bindings) {
-        // Escape a given Regex string.
-        bindings.forEach(function(binding) {
-            if (binding.key) {
-                binding.key = new RegExp('^' + binding.key + '$');
-            } else if (Array.isArray(binding.regex)) {
-                if (!('key' in binding))
-                  binding.key = new RegExp('^' + binding.regex[1] + '$');
-                binding.regex = new RegExp(binding.regex.join('') + '$');
-            } else if (binding.regex) {
-                binding.regex = new RegExp(binding.regex + '$');
-            }
-        });
-    },
-
-    $composeBuffer: function(data, hashId, key, e) {
-        // Initialize the data object.
-        if (data.state == null || data.buffer == null) {
-            data.state = "start";
-            data.buffer = "";
-        }
-
-        var keyArray = [];
-        if (hashId & 1) keyArray.push("ctrl");
-        if (hashId & 8) keyArray.push("command");
-        if (hashId & 2) keyArray.push("option");
-        if (hashId & 4) keyArray.push("shift");
-        if (key)        keyArray.push(key);
-
-        var symbolicName = keyArray.join("-");
-        var bufferToUse = data.buffer + symbolicName;
-
-        // Don't add the symbolic name to the key buffer if the alt_ key is
-        // part of the symbolic name. If it starts with alt_, this means
-        // that the user hit an alt keycombo and there will be a single,
-        // new character detected after this event, which then will be
-        // added to the buffer (e.g. alt_j will result in ∆).
-        //
-        // We test for 2 and not for & 2 as we only want to exclude the case where
-        // the option key is pressed alone.
-        if (hashId != 2) {
-            data.buffer = bufferToUse;
-        }
-
-        var bufferObj = {
-            bufferToUse: bufferToUse,
-            symbolicName: symbolicName,
-        };
-
-        if (e) {
-            bufferObj.keyIdentifier = e.keyIdentifier
-        }
-
-        return bufferObj;
-    },
-
-    $find: function(data, buffer, symbolicName, hashId, key, keyIdentifier) {
-        // Holds the command to execute and the args if a command matched.
-        var result = {};
-
-        // Loop over all the bindings of the keymap until a match is found.
-        this.keymapping[data.state].some(function(binding) {
-            var match;
-
-            // Check if the key matches.
-            if (binding.key && !binding.key.test(symbolicName)) {
-                return false;
-            }
-
-            // Check if the regex matches.
-            if (binding.regex && !(match = binding.regex.exec(buffer))) {
-                return false;
-            }
-
-            // Check if the match function matches.
-            if (binding.match && !binding.match(buffer, hashId, key, symbolicName, keyIdentifier)) {
-                return false;
-            }
-
-            // Check for disallowed matches.
-            if (binding.disallowMatches) {
-                for (var i = 0; i < binding.disallowMatches.length; i++) {
-                    if (!!match[binding.disallowMatches[i]]) {
-                        return false;
-                    }
-                }
-            }
-
-            // If there is a command to execute, then figure out the
-            // command and the arguments.
-            if (binding.exec) {
-                result.command = binding.exec;
-
-                // Build the arguments.
-                if (binding.params) {
-                    var value;
-                    result.args = {};
-                    binding.params.forEach(function(param) {
-                        if (param.match != null && match != null) {
-                            value = match[param.match] || param.defaultValue;
-                        } else {
-                            value = param.defaultValue;
-                        }
-
-                        if (param.type === 'number') {
-                            value = parseInt(value);
-                        }
-
-                        result.args[param.name] = value;
-                    });
-                }
-                data.buffer = "";
-            }
-
-            // Handle the 'then' property.
-            if (binding.then) {
-                data.state = binding.then;
-                data.buffer = "";
-            }
-
-            // If no command is set, then execute the "null" fake command.
-            if (result.command == null) {
-                result.command = "null";
-            }
-
-            if (DEBUG) {
-                console.log("KeyboardStateMapper#find", binding);
-            }
-            return true;
-        });
-
-        if (result.command) {
-            return result;
-        } else {
-            data.buffer = "";
-            return false;
-        }
-    },
-
-    /**
-     * This function is called by keyBinding.
-     */
-    handleKeyboard: function(data, hashId, key, keyCode, e) {
-        // If we pressed any command key but no other key, then ignore the input.
-        // Otherwise "shift-" is added to the buffer, and later on "shift-g"
-        // which results in "shift-shift-g" which doesn't make sense.
-        if (hashId != 0 && (key == "" || key == String.fromCharCode(0))) {
-            return null;
-        }
-
-        // Compute the current value of the keyboard input buffer.
-        var r = this.$composeBuffer(data, hashId, key, e);
-        var buffer = r.bufferToUse;
-        var symbolicName = r.symbolicName;
-        var keyId = r.keyIdentifier;
-
-        r = this.$find(data, buffer, symbolicName, hashId, key, keyId);
-        if (DEBUG) {
-            console.log("KeyboardStateMapper#match", buffer, symbolicName, r);
-        }
-
-        return r;
-    }
-}
-
-/**
- * This is a useful matching function and therefore is defined here so that
- * users of KeyboardStateMapper can use it.
- *
- * @return boolean
- *          If no command key (Command|Option|Shift|Ctrl) is pressed, it
- *          returns true. If the only the Shift key is pressed + a character
- *          true is returned as well. Otherwise, false is returned.
- *          Summing up, the function returns true whenever the user typed
- *          a normal character on the keyboard and no shortcut.
- */
-exports.matchCharacterOnly = function(buffer, hashId, key, symbolicName) {
-    // If no command keys are pressed, then catch the input.
-    if (hashId == 0) {
-        return true;
-    }
-    // If only the shift key is pressed and a character key, then
-    // catch that input as well.
-    else if ((hashId == 4) && key.length == 1) {
-        return true;
-    }
-    // Otherwise, we let the input got through.
-    else {
-        return false;
-    }
-};
-
-exports.StateHandler = StateHandler;
-});
-;
-            (function() {
-                window.require(["ace/ace"], function(a) {
-                    if (!window.ace)
-                        window.ace = {};
-                    for (var key in a) if (a.hasOwnProperty(key))
-                        ace[key] = a[key];
-                });
-            })();
-        
\ No newline at end of file
diff --git a/apps/files_texteditor/js/aceeditor/keybinding-vim.js b/apps/files_texteditor/js/aceeditor/keybinding-vim.js
old mode 100755
new mode 100644
index fa94c7955f1c3d3a128a9b49464a7fd943dbac0c..124607d8e6d4d5985dbd6fb4da64972587c821f0
--- a/apps/files_texteditor/js/aceeditor/keybinding-vim.js
+++ b/apps/files_texteditor/js/aceeditor/keybinding-vim.js
@@ -1 +1 @@
-define("ace/keyboard/keybinding/vim",["require","exports","module","ace/keyboard/state_handler"],function(a,b,c){"use strict";var d=a("../state_handler").StateHandler,e=a("../state_handler").matchCharacterOnly,f=function(a,b,c){return{regex:["([0-9]*)",a],exec:b,params:[{name:"times",match:1,type:"number",defaultValue:1}],then:c}},g={start:[{key:"i",then:"insertMode"},{key:"d",then:"deleteMode"},{key:"a",exec:"gotoright",then:"insertMode"},{key:"shift-i",exec:"gotolinestart",then:"insertMode"},{key:"shift-a",exec:"gotolineend",then:"insertMode"},{key:"shift-c",exec:"removetolineend",then:"insertMode"},{key:"shift-r",exec:"overwrite",then:"replaceMode"},f("(k|up)","golineup"),f("(j|down)","golinedown"),f("(l|right)","gotoright"),f("(h|left)","gotoleft"),{key:"shift-g",exec:"gotoend"},f("b","gotowordleft"),f("e","gotowordright"),f("x","del"),f("shift-x","backspace"),f("shift-d","removetolineend"),f("u","undo"),{comment:"Catch some keyboard input to stop it here",match:e}],insertMode:[{key:"esc",then:"start"}],replaceMode:[{key:"esc",exec:"overwrite",then:"start"}],deleteMode:[{key:"d",exec:"removeline",then:"start"}]};b.Vim=new d(g)}),define("ace/keyboard/state_handler",["require","exports","module"],function(a,b,c){function e(a){this.keymapping=this.$buildKeymappingRegex(a)}"use strict";var d=!1;e.prototype={$buildKeymappingRegex:function(a){for(var b in a)this.$buildBindingsRegex(a[b]);return a},$buildBindingsRegex:function(a){a.forEach(function(a){a.key?a.key=new RegExp("^"+a.key+"$"):Array.isArray(a.regex)?("key"in a||(a.key=new RegExp("^"+a.regex[1]+"$")),a.regex=new RegExp(a.regex.join("")+"$")):a.regex&&(a.regex=new RegExp(a.regex+"$"))})},$composeBuffer:function(a,b,c,d){if(a.state==null||a.buffer==null)a.state="start",a.buffer="";var e=[];b&1&&e.push("ctrl"),b&8&&e.push("command"),b&2&&e.push("option"),b&4&&e.push("shift"),c&&e.push(c);var f=e.join("-"),g=a.buffer+f;b!=2&&(a.buffer=g);var h={bufferToUse:g,symbolicName:f};return d&&(h.keyIdentifier=d.keyIdentifier),h},$find:function(a,b,c,e,f,g){var h={};return this.keymapping[a.state].some(function(i){var j;if(i.key&&!i.key.test(c))return!1;if(i.regex&&!(j=i.regex.exec(b)))return!1;if(i.match&&!i.match(b,e,f,c,g))return!1;if(i.disallowMatches)for(var k=0;k<i.disallowMatches.length;k++)if(!!j[i.disallowMatches[k]])return!1;if(i.exec){h.command=i.exec;if(i.params){var l;h.args={},i.params.forEach(function(a){a.match!=null&&j!=null?l=j[a.match]||a.defaultValue:l=a.defaultValue,a.type==="number"&&(l=parseInt(l)),h.args[a.name]=l})}a.buffer=""}return i.then&&(a.state=i.then,a.buffer=""),h.command==null&&(h.command="null"),d&&console.log("KeyboardStateMapper#find",i),!0}),h.command?h:(a.buffer="",!1)},handleKeyboard:function(a,b,c,e,f){if(b==0||c!=""&&c!=String.fromCharCode(0)){var g=this.$composeBuffer(a,b,c,f),h=g.bufferToUse,i=g.symbolicName,j=g.keyIdentifier;return g=this.$find(a,h,i,b,c,j),d&&console.log("KeyboardStateMapper#match",h,i,g),g}return null}},b.matchCharacterOnly=function(a,b,c,d){return b==0?!0:b==4&&c.length==1?!0:!1},b.StateHandler=e}),function(){window.require(["ace/ace"],function(a){window.ace||(window.ace={});for(var b in a)a.hasOwnProperty(b)&&(ace[b]=a[b])})}()
\ No newline at end of file
+define("ace/keyboard/keybinding/vim",["require","exports","module","ace/keyboard/state_handler"],function(a,b,c){"use strict";var d=a("../state_handler").StateHandler,e=a("../state_handler").matchCharacterOnly,f=function(a,b,c){return{regex:["([0-9]*)",a],exec:b,params:[{name:"times",match:1,type:"number",defaultValue:1}],then:c}},g={start:[{key:"i",then:"insertMode"},{key:"d",then:"deleteMode"},{key:"a",exec:"gotoright",then:"insertMode"},{key:"shift-i",exec:"gotolinestart",then:"insertMode"},{key:"shift-a",exec:"gotolineend",then:"insertMode"},{key:"shift-c",exec:"removetolineend",then:"insertMode"},{key:"shift-r",exec:"overwrite",then:"replaceMode"},f("(k|up)","golineup"),f("(j|down)","golinedown"),f("(l|right)","gotoright"),f("(h|left)","gotoleft"),{key:"shift-g",exec:"gotoend"},f("b","gotowordleft"),f("e","gotowordright"),f("x","del"),f("shift-x","backspace"),f("shift-d","removetolineend"),f("u","undo"),{comment:"Catch some keyboard input to stop it here",match:e}],insertMode:[{key:"esc",then:"start"}],replaceMode:[{key:"esc",exec:"overwrite",then:"start"}],deleteMode:[{key:"d",exec:"removeline",then:"start"}]};b.Vim=new d(g)})
\ No newline at end of file
diff --git a/apps/files_texteditor/js/aceeditor/mode-c_cpp-uncompressed.js b/apps/files_texteditor/js/aceeditor/mode-c_cpp-uncompressed.js
old mode 100755
new mode 100644
index 87a8fab9dd1f07c0211de1b40d997a15ace0f155..abd3190bfbc5ee99a86265a4db6927ecbda16391
--- a/apps/files_texteditor/js/aceeditor/mode-c_cpp-uncompressed.js
+++ b/apps/files_texteditor/js/aceeditor/mode-c_cpp-uncompressed.js
@@ -541,12 +541,12 @@ var CstyleBehaviour = function () {
                 return {
                     text: '{' + selected + '}',
                     selection: false
-                }
+                };
             } else {
                 return {
                     text: '{}',
                     selection: [1, 1]
-                }
+                };
             }
         } else if (text == '}') {
             var cursor = editor.getCursorPosition();
@@ -558,7 +558,7 @@ var CstyleBehaviour = function () {
                     return {
                         text: '',
                         selection: [1, 1]
-                    }
+                    };
                 }
             }
         } else if (text == "\n") {
@@ -576,7 +576,7 @@ var CstyleBehaviour = function () {
                 return {
                     text: '\n' + indent + '\n' + next_indent,
                     selection: [1, indent.length, 1, indent.length]
-                }
+                };
             }
         }
     });
@@ -601,12 +601,12 @@ var CstyleBehaviour = function () {
                 return {
                     text: '(' + selected + ')',
                     selection: false
-                }
+                };
             } else {
                 return {
                     text: '()',
                     selection: [1, 1]
-                }
+                };
             }
         } else if (text == ')') {
             var cursor = editor.getCursorPosition();
@@ -618,7 +618,7 @@ var CstyleBehaviour = function () {
                     return {
                         text: '',
                         selection: [1, 1]
-                    }
+                    };
                 }
             }
         }
@@ -637,14 +637,15 @@ var CstyleBehaviour = function () {
     });
 
     this.add("string_dquotes", "insertion", function (state, action, editor, session, text) {
-        if (text == '"') {
+        if (text == '"' || text == "'") {
+            var quote = text;
             var selection = editor.getSelectionRange();
             var selected = session.doc.getTextRange(selection);
             if (selected !== "") {
                 return {
-                    text: '"' + selected + '"',
+                    text: quote + selected + quote,
                     selection: false
-                }
+                };
             } else {
                 var cursor = editor.getCursorPosition();
                 var line = session.doc.getLine(cursor.row);
@@ -665,7 +666,7 @@ var CstyleBehaviour = function () {
                     if (token.type == "string") {
                       quotepos = -1;
                     } else if (quotepos < 0) {
-                      quotepos = token.value.indexOf('"');
+                      quotepos = token.value.indexOf(quote);
                     }
                     if ((token.value.length + col) > selection.start.column) {
                         break;
@@ -674,19 +675,19 @@ var CstyleBehaviour = function () {
                 }
 
                 // Try and be smart about when we auto insert.
-                if (!token || (quotepos < 0 && token.type !== "comment" && (token.type !== "string" || ((selection.start.column !== token.value.length+col-1) && token.value.lastIndexOf('"') === token.value.length-1)))) {
+                if (!token || (quotepos < 0 && token.type !== "comment" && (token.type !== "string" || ((selection.start.column !== token.value.length+col-1) && token.value.lastIndexOf(quote) === token.value.length-1)))) {
                     return {
-                        text: '""',
+                        text: quote + quote,
                         selection: [1,1]
-                    }
+                    };
                 } else if (token && token.type === "string") {
                     // Ignore input and move right one if we're typing over the closing quote.
                     var rightChar = line.substring(cursor.column, cursor.column + 1);
-                    if (rightChar == '"') {
+                    if (rightChar == quote) {
                         return {
                             text: '',
                             selection: [1, 1]
-                        }
+                        };
                     }
                 }
             }
@@ -695,7 +696,7 @@ var CstyleBehaviour = function () {
 
     this.add("string_dquotes", "deletion", function (state, action, editor, session, range) {
         var selected = session.doc.getTextRange(range);
-        if (!range.isMultiLine() && selected == '"') {
+        if (!range.isMultiLine() && (selected == '"' || selected == "'")) {
             var line = session.doc.getLine(range.start.row);
             var rightChar = line.substring(range.start.column + 1, range.start.column + 2);
             if (rightChar == '"') {
@@ -705,7 +706,8 @@ var CstyleBehaviour = function () {
         }
     });
 
-}
+};
+
 oop.inherits(CstyleBehaviour, Behaviour);
 
 exports.CstyleBehaviour = CstyleBehaviour;
@@ -916,13 +918,3 @@ var FoldMode = exports.FoldMode = function() {};
 }).call(FoldMode.prototype);
 
 });
-;
-            (function() {
-                window.require(["ace/ace"], function(a) {
-                    if (!window.ace)
-                        window.ace = {};
-                    for (var key in a) if (a.hasOwnProperty(key))
-                        ace[key] = a[key];
-                });
-            })();
-        
\ No newline at end of file
diff --git a/apps/files_texteditor/js/aceeditor/mode-c_cpp.js b/apps/files_texteditor/js/aceeditor/mode-c_cpp.js
index c49e93eb937c47d98f369dbf23468f903dcedd3c..078afcaa78328f49a46902e3cd07083462469c93 100644
--- a/apps/files_texteditor/js/aceeditor/mode-c_cpp.js
+++ b/apps/files_texteditor/js/aceeditor/mode-c_cpp.js
@@ -1 +1 @@
-define("ace/mode/c_cpp",["require","exports","module","ace/lib/oop","ace/mode/text","ace/tokenizer","ace/mode/c_cpp_highlight_rules","ace/mode/matching_brace_outdent","ace/range","ace/mode/behaviour/cstyle","ace/mode/folding/cstyle"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("./text").Mode,f=a("../tokenizer").Tokenizer,g=a("./c_cpp_highlight_rules").c_cppHighlightRules,h=a("./matching_brace_outdent").MatchingBraceOutdent,i=a("../range").Range,j=a("./behaviour/cstyle").CstyleBehaviour,k=a("./folding/cstyle").FoldMode,l=function(){this.$tokenizer=new f((new g).getRules()),this.$outdent=new h,this.$behaviour=new j,this.foldingRules=new k};d.inherits(l,e),function(){this.toggleCommentLines=function(a,b,c,d){var e=!0,f=/^(\s*)\/\//;for(var g=c;g<=d;g++)if(!f.test(b.getLine(g))){e=!1;break}if(e){var h=new i(0,0,0,0);for(var g=c;g<=d;g++){var j=b.getLine(g),k=j.match(f);h.start.row=g,h.end.row=g,h.end.column=k[0].length,b.replace(h,k[1])}}else b.indentRows(c,d,"//")},this.getNextLineIndent=function(a,b,c){var d=this.$getIndent(b),e=this.$tokenizer.getLineTokens(b,a),f=e.tokens,g=e.state;if(f.length&&f[f.length-1].type=="comment")return d;if(a=="start"){var h=b.match(/^.*[\{\(\[]\s*$/);h&&(d+=c)}else if(a=="doc-start"){if(g=="start")return"";var h=b.match(/^\s*(\/?)\*/);h&&(h[1]&&(d+=" "),d+="* ")}return d},this.checkOutdent=function(a,b,c){return this.$outdent.checkOutdent(b,c)},this.autoOutdent=function(a,b,c){this.$outdent.autoOutdent(b,c)}}.call(l.prototype),b.Mode=l}),define("ace/mode/c_cpp_highlight_rules",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/mode/doc_comment_highlight_rules","ace/mode/text_highlight_rules"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("../lib/lang"),f=a("./doc_comment_highlight_rules").DocCommentHighlightRules,g=a("./text_highlight_rules").TextHighlightRules,h=function(){var a=e.arrayToMap("and|double|not_eq|throw|and_eq|dynamic_cast|operator|true|asm|else|or|try|auto|enum|or_eq|typedef|bitand|explicit|private|typeid|bitor|extern|protected|typename|bool|false|public|union|break|float|register|unsigned|case|fro|reinterpret-cast|using|catch|friend|return|virtual|char|goto|short|void|class|if|signed|volatile|compl|inline|sizeof|wchar_t|const|int|static|while|const-cast|long|static_cast|xor|continue|mutable|struct|xor_eq|default|namespace|switch|delete|new|template|do|not|this|for".split("|")),b=e.arrayToMap("NULL".split("|"));this.$rules={start:[{token:"comment",regex:"\\/\\/.*$"},(new f).getStartRule("doc-start"),{token:"comment",merge:!0,regex:"\\/\\*",next:"comment"},{token:"string",regex:'["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'},{token:"string",merge:!0,regex:'["].*\\\\$',next:"qqstring"},{token:"string",regex:"['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"},{token:"string",merge:!0,regex:"['].*\\\\$",next:"qstring"},{token:"constant.numeric",regex:"0[xX][0-9a-fA-F]+\\b"},{token:"constant.numeric",regex:"[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"},{token:"constant",regex:"<[a-zA-Z0-9.]+>"},{token:"keyword",regex:"(?:#include|#pragma|#line|#define|#undef|#ifdef|#else|#elif|#endif|#ifndef)"},{token:function(c){return c=="this"?"variable.language":a.hasOwnProperty(c)?"keyword":b.hasOwnProperty(c)?"constant.language":"identifier"},regex:"[a-zA-Z_$][a-zA-Z0-9_$]*\\b"},{token:"keyword.operator",regex:"!|\\$|%|&|\\*|\\-\\-|\\-|\\+\\+|\\+|~|==|=|!=|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\\|\\||\\?\\:|\\*=|%=|\\+=|\\-=|&=|\\^=|\\b(?:in|new|delete|typeof|void)"},{token:"punctuation.operator",regex:"\\?|\\:|\\,|\\;|\\."},{token:"paren.lparen",regex:"[[({]"},{token:"paren.rparen",regex:"[\\])}]"},{token:"text",regex:"\\s+"}],comment:[{token:"comment",regex:".*?\\*\\/",next:"start"},{token:"comment",merge:!0,regex:".+"}],qqstring:[{token:"string",regex:'(?:(?:\\\\.)|(?:[^"\\\\]))*?"',next:"start"},{token:"string",merge:!0,regex:".+"}],qstring:[{token:"string",regex:"(?:(?:\\\\.)|(?:[^'\\\\]))*?'",next:"start"},{token:"string",merge:!0,regex:".+"}]},this.embedRules(f,"doc-",[(new f).getEndRule("start")])};d.inherits(h,g),b.c_cppHighlightRules=h}),define("ace/mode/doc_comment_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("./text_highlight_rules").TextHighlightRules,f=function(){this.$rules={start:[{token:"comment.doc.tag",regex:"@[\\w\\d_]+"},{token:"comment.doc",merge:!0,regex:"\\s+"},{token:"comment.doc",merge:!0,regex:"TODO"},{token:"comment.doc",merge:!0,regex:"[^@\\*]+"},{token:"comment.doc",merge:!0,regex:"."}]}};d.inherits(f,e),function(){this.getStartRule=function(a){return{token:"comment.doc",merge:!0,regex:"\\/\\*(?=\\*)",next:a}},this.getEndRule=function(a){return{token:"comment.doc",merge:!0,regex:"\\*\\/",next:a}}}.call(f.prototype),b.DocCommentHighlightRules=f}),define("ace/mode/matching_brace_outdent",["require","exports","module","ace/range"],function(a,b,c){"use strict";var d=a("../range").Range,e=function(){};((function(){this.checkOutdent=function(a,b){return/^\s+$/.test(a)?/^\s*\}/.test(b):!1},this.autoOutdent=function(a,b){var c=a.getLine(b),e=c.match(/^(\s*\})/);if(!e)return 0;var f=e[1].length,g=a.findMatchingBracket({row:b,column:f});if(!g||g.row==b)return 0;var h=this.$getIndent(a.getLine(g.row));a.replace(new d(b,0,b,f-1),h)},this.$getIndent=function(a){var b=a.match(/^(\s+)/);return b?b[1]:""}})).call(e.prototype),b.MatchingBraceOutdent=e}),define("ace/mode/behaviour/cstyle",["require","exports","module","ace/lib/oop","ace/mode/behaviour"],function(a,b,c){"use strict";var d=a("../../lib/oop"),e=a("../behaviour").Behaviour,f=function(){this.add("braces","insertion",function(a,b,c,d,e){if(e=="{"){var f=c.getSelectionRange(),g=d.doc.getTextRange(f);return g!==""?{text:"{"+g+"}",selection:!1}:{text:"{}",selection:[1,1]}}if(e=="}"){var h=c.getCursorPosition(),i=d.doc.getLine(h.row),j=i.substring(h.column,h.column+1);if(j=="}"){var k=d.$findOpeningBracket("}",{column:h.column+1,row:h.row});if(k!==null)return{text:"",selection:[1,1]}}}else if(e=="\n"){var h=c.getCursorPosition(),i=d.doc.getLine(h.row),j=i.substring(h.column,h.column+1);if(j=="}"){var l=d.findMatchingBracket({row:h.row,column:h.column+1});if(!l)return null;var m=this.getNextLineIndent(a,i.substring(0,i.length-1),d.getTabString()),n=this.$getIndent(d.doc.getLine(l.row));return{text:"\n"+m+"\n"+n,selection:[1,m.length,1,m.length]}}}}),this.add("braces","deletion",function(a,b,c,d,e){var f=d.doc.getTextRange(e);if(!e.isMultiLine()&&f=="{"){var g=d.doc.getLine(e.start.row),h=g.substring(e.end.column,e.end.column+1);if(h=="}")return e.end.column++,e}}),this.add("parens","insertion",function(a,b,c,d,e){if(e=="("){var f=c.getSelectionRange(),g=d.doc.getTextRange(f);return g!==""?{text:"("+g+")",selection:!1}:{text:"()",selection:[1,1]}}if(e==")"){var h=c.getCursorPosition(),i=d.doc.getLine(h.row),j=i.substring(h.column,h.column+1);if(j==")"){var k=d.$findOpeningBracket(")",{column:h.column+1,row:h.row});if(k!==null)return{text:"",selection:[1,1]}}}}),this.add("parens","deletion",function(a,b,c,d,e){var f=d.doc.getTextRange(e);if(!e.isMultiLine()&&f=="("){var g=d.doc.getLine(e.start.row),h=g.substring(e.start.column+1,e.start.column+2);if(h==")")return e.end.column++,e}}),this.add("string_dquotes","insertion",function(a,b,c,d,e){if(e=='"'){var f=c.getSelectionRange(),g=d.doc.getTextRange(f);if(g!=="")return{text:'"'+g+'"',selection:!1};var h=c.getCursorPosition(),i=d.doc.getLine(h.row),j=i.substring(h.column-1,h.column);if(j=="\\")return null;var k=d.getTokens(f.start.row,f.start.row)[0].tokens,l=0,m,n=-1;for(var o=0;o<k.length;o++){m=k[o],m.type=="string"?n=-1:n<0&&(n=m.value.indexOf('"'));if(m.value.length+l>f.start.column)break;l+=k[o].value.length}if(!m||n<0&&m.type!=="comment"&&(m.type!=="string"||f.start.column!==m.value.length+l-1&&m.value.lastIndexOf('"')===m.value.length-1))return{text:'""',selection:[1,1]};if(m&&m.type==="string"){var p=i.substring(h.column,h.column+1);if(p=='"')return{text:"",selection:[1,1]}}}}),this.add("string_dquotes","deletion",function(a,b,c,d,e){var f=d.doc.getTextRange(e);if(!e.isMultiLine()&&f=='"'){var g=d.doc.getLine(e.start.row),h=g.substring(e.start.column+1,e.start.column+2);if(h=='"')return e.end.column++,e}})};d.inherits(f,e),b.CstyleBehaviour=f}),define("ace/mode/folding/cstyle",["require","exports","module","ace/lib/oop","ace/range","ace/mode/folding/fold_mode"],function(a,b,c){"use strict";var d=a("../../lib/oop"),e=a("../../range").Range,f=a("./fold_mode").FoldMode,g=b.FoldMode=function(){};d.inherits(g,f),function(){this.foldingStartMarker=/(\{|\[)[^\}\]]*$|^\s*(\/\*)/,this.foldingStopMarker=/^[^\[\{]*(\}|\])|^[\s\*]*(\*\/)/,this.getFoldWidgetRange=function(a,b,c){var d=a.getLine(c),f=d.match(this.foldingStartMarker);if(f){var g=f.index;if(f[1])return this.openingBracketBlock(a,f[1],c,g);var h=a.getCommentFoldRange(c,g+f[0].length);return h.end.column-=2,h}if(b!=="markbeginend")return;var f=d.match(this.foldingStopMarker);if(f){var g=f.index+f[0].length;if(f[2]){var h=a.getCommentFoldRange(c,g);return h.end.column-=2,h}var i={row:c,column:g},j=a.$findOpeningBracket(f[1],i);if(!j)return;return j.column++,i.column--,e.fromPoints(j,i)}}}.call(g.prototype)}),define("ace/mode/folding/fold_mode",["require","exports","module","ace/range"],function(a,b,c){"use strict";var d=a("../../range").Range,e=b.FoldMode=function(){};((function(){this.foldingStartMarker=null,this.foldingStopMarker=null,this.getFoldWidget=function(a,b,c){var d=a.getLine(c);return this.foldingStartMarker.test(d)?"start":b=="markbeginend"&&this.foldingStopMarker&&this.foldingStopMarker.test(d)?"end":""},this.getFoldWidgetRange=function(a,b,c){return null},this.indentationBlock=function(a,b,c){var e=/^\s*/,f=b,g=b,h=a.getLine(b),i=c||h.length,j=h.match(e)[0].length,k=a.getLength();while(++b<k){h=a.getLine(b);var l=h.match(e)[0].length;if(l==h.length)continue;if(l<=j)break;g=b}if(g>f){var m=a.getLine(g).length;return new d(f,i,g,m)}},this.openingBracketBlock=function(a,b,c,e){var f={row:c,column:e+1},g=a.$findClosingBracket(b,f);if(!g)return;var h=a.foldWidgets[g.row];return h==null&&(h=this.getFoldWidget(a,g.row)),h=="start"&&(g.row--,g.column=a.getLine(g.row).length),d.fromPoints(f,g)}})).call(e.prototype)}),function(){window.require(["ace/ace"],function(a){window.ace||(window.ace={});for(var b in a)a.hasOwnProperty(b)&&(ace[b]=a[b])})}()
\ No newline at end of file
+define("ace/mode/c_cpp",["require","exports","module","ace/lib/oop","ace/mode/text","ace/tokenizer","ace/mode/c_cpp_highlight_rules","ace/mode/matching_brace_outdent","ace/range","ace/mode/behaviour/cstyle","ace/mode/folding/cstyle"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("./text").Mode,f=a("../tokenizer").Tokenizer,g=a("./c_cpp_highlight_rules").c_cppHighlightRules,h=a("./matching_brace_outdent").MatchingBraceOutdent,i=a("../range").Range,j=a("./behaviour/cstyle").CstyleBehaviour,k=a("./folding/cstyle").FoldMode,l=function(){this.$tokenizer=new f((new g).getRules()),this.$outdent=new h,this.$behaviour=new j,this.foldingRules=new k};d.inherits(l,e),function(){this.toggleCommentLines=function(a,b,c,d){var e=!0,f=/^(\s*)\/\//;for(var g=c;g<=d;g++)if(!f.test(b.getLine(g))){e=!1;break}if(e){var h=new i(0,0,0,0);for(var g=c;g<=d;g++){var j=b.getLine(g),k=j.match(f);h.start.row=g,h.end.row=g,h.end.column=k[0].length,b.replace(h,k[1])}}else b.indentRows(c,d,"//")},this.getNextLineIndent=function(a,b,c){var d=this.$getIndent(b),e=this.$tokenizer.getLineTokens(b,a),f=e.tokens,g=e.state;if(f.length&&f[f.length-1].type=="comment")return d;if(a=="start"){var h=b.match(/^.*[\{\(\[]\s*$/);h&&(d+=c)}else if(a=="doc-start"){if(g=="start")return"";var h=b.match(/^\s*(\/?)\*/);h&&(h[1]&&(d+=" "),d+="* ")}return d},this.checkOutdent=function(a,b,c){return this.$outdent.checkOutdent(b,c)},this.autoOutdent=function(a,b,c){this.$outdent.autoOutdent(b,c)}}.call(l.prototype),b.Mode=l}),define("ace/mode/c_cpp_highlight_rules",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/mode/doc_comment_highlight_rules","ace/mode/text_highlight_rules"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("../lib/lang"),f=a("./doc_comment_highlight_rules").DocCommentHighlightRules,g=a("./text_highlight_rules").TextHighlightRules,h=function(){var a=e.arrayToMap("and|double|not_eq|throw|and_eq|dynamic_cast|operator|true|asm|else|or|try|auto|enum|or_eq|typedef|bitand|explicit|private|typeid|bitor|extern|protected|typename|bool|false|public|union|break|float|register|unsigned|case|fro|reinterpret-cast|using|catch|friend|return|virtual|char|goto|short|void|class|if|signed|volatile|compl|inline|sizeof|wchar_t|const|int|static|while|const-cast|long|static_cast|xor|continue|mutable|struct|xor_eq|default|namespace|switch|delete|new|template|do|not|this|for".split("|")),b=e.arrayToMap("NULL".split("|"));this.$rules={start:[{token:"comment",regex:"\\/\\/.*$"},(new f).getStartRule("doc-start"),{token:"comment",merge:!0,regex:"\\/\\*",next:"comment"},{token:"string",regex:'["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'},{token:"string",merge:!0,regex:'["].*\\\\$',next:"qqstring"},{token:"string",regex:"['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"},{token:"string",merge:!0,regex:"['].*\\\\$",next:"qstring"},{token:"constant.numeric",regex:"0[xX][0-9a-fA-F]+\\b"},{token:"constant.numeric",regex:"[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"},{token:"constant",regex:"<[a-zA-Z0-9.]+>"},{token:"keyword",regex:"(?:#include|#pragma|#line|#define|#undef|#ifdef|#else|#elif|#endif|#ifndef)"},{token:function(c){return c=="this"?"variable.language":a.hasOwnProperty(c)?"keyword":b.hasOwnProperty(c)?"constant.language":"identifier"},regex:"[a-zA-Z_$][a-zA-Z0-9_$]*\\b"},{token:"keyword.operator",regex:"!|\\$|%|&|\\*|\\-\\-|\\-|\\+\\+|\\+|~|==|=|!=|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\\|\\||\\?\\:|\\*=|%=|\\+=|\\-=|&=|\\^=|\\b(?:in|new|delete|typeof|void)"},{token:"punctuation.operator",regex:"\\?|\\:|\\,|\\;|\\."},{token:"paren.lparen",regex:"[[({]"},{token:"paren.rparen",regex:"[\\])}]"},{token:"text",regex:"\\s+"}],comment:[{token:"comment",regex:".*?\\*\\/",next:"start"},{token:"comment",merge:!0,regex:".+"}],qqstring:[{token:"string",regex:'(?:(?:\\\\.)|(?:[^"\\\\]))*?"',next:"start"},{token:"string",merge:!0,regex:".+"}],qstring:[{token:"string",regex:"(?:(?:\\\\.)|(?:[^'\\\\]))*?'",next:"start"},{token:"string",merge:!0,regex:".+"}]},this.embedRules(f,"doc-",[(new f).getEndRule("start")])};d.inherits(h,g),b.c_cppHighlightRules=h}),define("ace/mode/doc_comment_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("./text_highlight_rules").TextHighlightRules,f=function(){this.$rules={start:[{token:"comment.doc.tag",regex:"@[\\w\\d_]+"},{token:"comment.doc",merge:!0,regex:"\\s+"},{token:"comment.doc",merge:!0,regex:"TODO"},{token:"comment.doc",merge:!0,regex:"[^@\\*]+"},{token:"comment.doc",merge:!0,regex:"."}]}};d.inherits(f,e),function(){this.getStartRule=function(a){return{token:"comment.doc",merge:!0,regex:"\\/\\*(?=\\*)",next:a}},this.getEndRule=function(a){return{token:"comment.doc",merge:!0,regex:"\\*\\/",next:a}}}.call(f.prototype),b.DocCommentHighlightRules=f}),define("ace/mode/matching_brace_outdent",["require","exports","module","ace/range"],function(a,b,c){"use strict";var d=a("../range").Range,e=function(){};(function(){this.checkOutdent=function(a,b){return/^\s+$/.test(a)?/^\s*\}/.test(b):!1},this.autoOutdent=function(a,b){var c=a.getLine(b),e=c.match(/^(\s*\})/);if(!e)return 0;var f=e[1].length,g=a.findMatchingBracket({row:b,column:f});if(!g||g.row==b)return 0;var h=this.$getIndent(a.getLine(g.row));a.replace(new d(b,0,b,f-1),h)},this.$getIndent=function(a){var b=a.match(/^(\s+)/);return b?b[1]:""}}).call(e.prototype),b.MatchingBraceOutdent=e}),define("ace/mode/behaviour/cstyle",["require","exports","module","ace/lib/oop","ace/mode/behaviour"],function(a,b,c){"use strict";var d=a("../../lib/oop"),e=a("../behaviour").Behaviour,f=function(){this.add("braces","insertion",function(a,b,c,d,e){if(e=="{"){var f=c.getSelectionRange(),g=d.doc.getTextRange(f);return g!==""?{text:"{"+g+"}",selection:!1}:{text:"{}",selection:[1,1]}}if(e=="}"){var h=c.getCursorPosition(),i=d.doc.getLine(h.row),j=i.substring(h.column,h.column+1);if(j=="}"){var k=d.$findOpeningBracket("}",{column:h.column+1,row:h.row});if(k!==null)return{text:"",selection:[1,1]}}}else if(e=="\n"){var h=c.getCursorPosition(),i=d.doc.getLine(h.row),j=i.substring(h.column,h.column+1);if(j=="}"){var l=d.findMatchingBracket({row:h.row,column:h.column+1});if(!l)return null;var m=this.getNextLineIndent(a,i.substring(0,i.length-1),d.getTabString()),n=this.$getIndent(d.doc.getLine(l.row));return{text:"\n"+m+"\n"+n,selection:[1,m.length,1,m.length]}}}}),this.add("braces","deletion",function(a,b,c,d,e){var f=d.doc.getTextRange(e);if(!e.isMultiLine()&&f=="{"){var g=d.doc.getLine(e.start.row),h=g.substring(e.end.column,e.end.column+1);if(h=="}")return e.end.column++,e}}),this.add("parens","insertion",function(a,b,c,d,e){if(e=="("){var f=c.getSelectionRange(),g=d.doc.getTextRange(f);return g!==""?{text:"("+g+")",selection:!1}:{text:"()",selection:[1,1]}}if(e==")"){var h=c.getCursorPosition(),i=d.doc.getLine(h.row),j=i.substring(h.column,h.column+1);if(j==")"){var k=d.$findOpeningBracket(")",{column:h.column+1,row:h.row});if(k!==null)return{text:"",selection:[1,1]}}}}),this.add("parens","deletion",function(a,b,c,d,e){var f=d.doc.getTextRange(e);if(!e.isMultiLine()&&f=="("){var g=d.doc.getLine(e.start.row),h=g.substring(e.start.column+1,e.start.column+2);if(h==")")return e.end.column++,e}}),this.add("string_dquotes","insertion",function(a,b,c,d,e){if(e=='"'||e=="'"){var f=e,g=c.getSelectionRange(),h=d.doc.getTextRange(g);if(h!=="")return{text:f+h+f,selection:!1};var i=c.getCursorPosition(),j=d.doc.getLine(i.row),k=j.substring(i.column-1,i.column);if(k=="\\")return null;var l=d.getTokens(g.start.row,g.start.row)[0].tokens,m=0,n,o=-1;for(var p=0;p<l.length;p++){n=l[p],n.type=="string"?o=-1:o<0&&(o=n.value.indexOf(f));if(n.value.length+m>g.start.column)break;m+=l[p].value.length}if(!n||o<0&&n.type!=="comment"&&(n.type!=="string"||g.start.column!==n.value.length+m-1&&n.value.lastIndexOf(f)===n.value.length-1))return{text:f+f,selection:[1,1]};if(n&&n.type==="string"){var q=j.substring(i.column,i.column+1);if(q==f)return{text:"",selection:[1,1]}}}}),this.add("string_dquotes","deletion",function(a,b,c,d,e){var f=d.doc.getTextRange(e);if(!e.isMultiLine()&&(f=='"'||f=="'")){var g=d.doc.getLine(e.start.row),h=g.substring(e.start.column+1,e.start.column+2);if(h=='"')return e.end.column++,e}})};d.inherits(f,e),b.CstyleBehaviour=f}),define("ace/mode/folding/cstyle",["require","exports","module","ace/lib/oop","ace/range","ace/mode/folding/fold_mode"],function(a,b,c){"use strict";var d=a("../../lib/oop"),e=a("../../range").Range,f=a("./fold_mode").FoldMode,g=b.FoldMode=function(){};d.inherits(g,f),function(){this.foldingStartMarker=/(\{|\[)[^\}\]]*$|^\s*(\/\*)/,this.foldingStopMarker=/^[^\[\{]*(\}|\])|^[\s\*]*(\*\/)/,this.getFoldWidgetRange=function(a,b,c){var d=a.getLine(c),f=d.match(this.foldingStartMarker);if(f){var g=f.index;if(f[1])return this.openingBracketBlock(a,f[1],c,g);var h=a.getCommentFoldRange(c,g+f[0].length);return h.end.column-=2,h}if(b!=="markbeginend")return;var f=d.match(this.foldingStopMarker);if(f){var g=f.index+f[0].length;if(f[2]){var h=a.getCommentFoldRange(c,g);return h.end.column-=2,h}var i={row:c,column:g},j=a.$findOpeningBracket(f[1],i);if(!j)return;return j.column++,i.column--,e.fromPoints(j,i)}}}.call(g.prototype)}),define("ace/mode/folding/fold_mode",["require","exports","module","ace/range"],function(a,b,c){"use strict";var d=a("../../range").Range,e=b.FoldMode=function(){};(function(){this.foldingStartMarker=null,this.foldingStopMarker=null,this.getFoldWidget=function(a,b,c){var d=a.getLine(c);return this.foldingStartMarker.test(d)?"start":b=="markbeginend"&&this.foldingStopMarker&&this.foldingStopMarker.test(d)?"end":""},this.getFoldWidgetRange=function(a,b,c){return null},this.indentationBlock=function(a,b,c){var e=/^\s*/,f=b,g=b,h=a.getLine(b),i=c||h.length,j=h.match(e)[0].length,k=a.getLength();while(++b<k){h=a.getLine(b);var l=h.match(e)[0].length;if(l==h.length)continue;if(l<=j)break;g=b}if(g>f){var m=a.getLine(g).length;return new d(f,i,g,m)}},this.openingBracketBlock=function(a,b,c,e){var f={row:c,column:e+1},g=a.$findClosingBracket(b,f);if(!g)return;var h=a.foldWidgets[g.row];return h==null&&(h=this.getFoldWidget(a,g.row)),h=="start"&&(g.row--,g.column=a.getLine(g.row).length),d.fromPoints(f,g)}}).call(e.prototype)})
\ No newline at end of file
diff --git a/apps/files_texteditor/js/aceeditor/mode-clojure-uncompressed.js b/apps/files_texteditor/js/aceeditor/mode-clojure-uncompressed.js
old mode 100755
new mode 100644
index eb99ceb3eea3bcb86f9ee0dc21d765198f596826..cb0081316f06eb0ed22f7b2b8b18ed271063d135
--- a/apps/files_texteditor/js/aceeditor/mode-clojure-uncompressed.js
+++ b/apps/files_texteditor/js/aceeditor/mode-clojure-uncompressed.js
@@ -259,9 +259,9 @@ var ClojureHighlightRules = function() {
                 token : "comment",
                 regex : ";.*$"
             }, {
-                    token : "comment", // multi line comment
-                    regex : "^\=begin$",
-                    next : "comment"
+                token : "comment", // multi line comment
+                regex : "^=begin$",
+                next : "comment"
             }, {
                 token : "keyword", //parens
                 regex : "[\\(|\\)]"
@@ -314,17 +314,17 @@ var ClojureHighlightRules = function() {
                 regex : '["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'
             }, {
                 token : "string", // symbol
-                regex : "[:](?:[a-zA-Z]|\d)+"
+                regex : "[:](?:[a-zA-Z]|\\d)+"
             }, {
-            token : "string.regexp", //Regular Expressions
-            regex : '/#"(?:\.|(\\\")|[^\""\n])*"/g'
+                token : "string.regexp", //Regular Expressions
+                regex : '/#"(?:\\.|(?:\\\")|[^\""\n])*"/g'
             }
-              
+
         ],
         "comment" : [
             {
                 token : "comment", // closing comment
-                regex : "^\=end$",
+                regex : "^=end$",
                 next : "start"
             }, {
                 token : "comment", // comment spanning whole line
@@ -420,13 +420,3 @@ var MatchingParensOutdent = function() {};
 
 exports.MatchingParensOutdent = MatchingParensOutdent;
 });
-;
-            (function() {
-                window.require(["ace/ace"], function(a) {
-                    if (!window.ace)
-                        window.ace = {};
-                    for (var key in a) if (a.hasOwnProperty(key))
-                        ace[key] = a[key];
-                });
-            })();
-        
\ No newline at end of file
diff --git a/apps/files_texteditor/js/aceeditor/mode-clojure.js b/apps/files_texteditor/js/aceeditor/mode-clojure.js
index 74e69fb0086dbc3fd0bf6de9d788fc8eb6a43da1..3afd7673f8eaed5581ea2714758352b15be09e76 100644
--- a/apps/files_texteditor/js/aceeditor/mode-clojure.js
+++ b/apps/files_texteditor/js/aceeditor/mode-clojure.js
@@ -1 +1 @@
-define("ace/mode/clojure",["require","exports","module","ace/lib/oop","ace/mode/text","ace/tokenizer","ace/mode/clojure_highlight_rules","ace/mode/matching_parens_outdent","ace/range"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("./text").Mode,f=a("../tokenizer").Tokenizer,g=a("./clojure_highlight_rules").ClojureHighlightRules,h=a("./matching_parens_outdent").MatchingParensOutdent,i=a("../range").Range,j=function(){this.$tokenizer=new f((new g).getRules()),this.$outdent=new h};d.inherits(j,e),function(){this.toggleCommentLines=function(a,b,c,d){var e=!0,f=/^(\s*)#/;for(var g=c;g<=d;g++)if(!f.test(b.getLine(g))){e=!1;break}if(e){var h=new i(0,0,0,0);for(var g=c;g<=d;g++){var j=b.getLine(g),k=j.match(f);h.start.row=g,h.end.row=g,h.end.column=k[0].length,b.replace(h,k[1])}}else b.indentRows(c,d,";")},this.getNextLineIndent=function(a,b,c){var d=this.$getIndent(b),e=this.$tokenizer.getLineTokens(b,a),f=e.tokens;if(f.length&&f[f.length-1].type=="comment")return d;if(a=="start"){var g=b.match(/[\(\[]/);g&&(d+="  "),g=b.match(/[\)]/),g&&(d="")}return d},this.checkOutdent=function(a,b,c){return this.$outdent.checkOutdent(b,c)},this.autoOutdent=function(a,b,c){this.$outdent.autoOutdent(b,c)}}.call(j.prototype),b.Mode=j}),define("ace/mode/clojure_highlight_rules",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/mode/text_highlight_rules"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("../lib/lang"),f=a("./text_highlight_rules").TextHighlightRules,g=function(){var a=e.arrayToMap("* *1 *2 *3 *agent* *allow-unresolved-vars* *assert* *clojure-version* *command-line-args* *compile-files* *compile-path* *e *err* *file* *flush-on-newline* *in* *macro-meta* *math-context* *ns* *out* *print-dup* *print-length* *print-level* *print-meta* *print-readably* *read-eval* *source-path* *use-context-classloader* *warn-on-reflection* + - -> -&gt; ->> -&gt;&gt; .. / < &lt; <= &lt;= = == > &gt; >= &gt;= accessor aclone add-classpath add-watch agent agent-errors aget alength alias all-ns alter alter-meta! alter-var-root amap ancestors and apply areduce array-map aset aset-boolean aset-byte aset-char aset-double aset-float aset-int aset-long aset-short assert assoc assoc! assoc-in associative? atom await await-for await1 bases bean bigdec bigint binding bit-and bit-and-not bit-clear bit-flip bit-not bit-or bit-set bit-shift-left bit-shift-right bit-test bit-xor boolean boolean-array booleans bound-fn bound-fn* butlast byte byte-array bytes cast char char-array char-escape-string char-name-string char? chars chunk chunk-append chunk-buffer chunk-cons chunk-first chunk-next chunk-rest chunked-seq? class class? clear-agent-errors clojure-version coll? comment commute comp comparator compare compare-and-set! compile complement concat cond condp conj conj! cons constantly construct-proxy contains? count counted? create-ns create-struct cycle dec decimal? declare definline defmacro defmethod defmulti defn defn- defonce defstruct delay delay? deliver deref derive descendants destructure disj disj! dissoc dissoc! distinct distinct? doall doc dorun doseq dosync dotimes doto double double-array doubles drop drop-last drop-while empty empty? ensure enumeration-seq eval even? every? false? ffirst file-seq filter find find-doc find-ns find-var first float float-array float? floats flush fn fn? fnext for force format future future-call future-cancel future-cancelled? future-done? future? gen-class gen-interface gensym get get-in get-method get-proxy-class get-thread-bindings get-validator hash hash-map hash-set identical? identity if-let if-not ifn? import in-ns inc init-proxy instance? int int-array integer? interleave intern interpose into into-array ints io! isa? iterate iterator-seq juxt key keys keyword keyword? last lazy-cat lazy-seq let letfn line-seq list list* list? load load-file load-reader load-string loaded-libs locking long long-array longs loop macroexpand macroexpand-1 make-array make-hierarchy map map? mapcat max max-key memfn memoize merge merge-with meta method-sig methods min min-key mod name namespace neg? newline next nfirst nil? nnext not not-any? not-empty not-every? not= ns ns-aliases ns-imports ns-interns ns-map ns-name ns-publics ns-refers ns-resolve ns-unalias ns-unmap nth nthnext num number? odd? or parents partial partition pcalls peek persistent! pmap pop pop! pop-thread-bindings pos? pr pr-str prefer-method prefers primitives-classnames print print-ctor print-doc print-dup print-method print-namespace-doc print-simple print-special-doc print-str printf println println-str prn prn-str promise proxy proxy-call-with-super proxy-mappings proxy-name proxy-super push-thread-bindings pvalues quot rand rand-int range ratio? rational? rationalize re-find re-groups re-matcher re-matches re-pattern re-seq read read-line read-string reduce ref ref-history-count ref-max-history ref-min-history ref-set refer refer-clojure release-pending-sends rem remove remove-method remove-ns remove-watch repeat repeatedly replace replicate require reset! reset-meta! resolve rest resultset-seq reverse reversible? rseq rsubseq second select-keys send send-off seq seq? seque sequence sequential? set set-validator! set? short short-array shorts shutdown-agents slurp some sort sort-by sorted-map sorted-map-by sorted-set sorted-set-by sorted? special-form-anchor special-symbol? split-at split-with str stream? string? struct struct-map subs subseq subvec supers swap! symbol symbol? sync syntax-symbol-anchor take take-last take-nth take-while test the-ns time to-array to-array-2d trampoline transient tree-seq true? type unchecked-add unchecked-dec unchecked-divide unchecked-inc unchecked-multiply unchecked-negate unchecked-remainder unchecked-subtract underive unquote unquote-splicing update-in update-proxy use val vals var-get var-set var? vary-meta vec vector vector? when when-first when-let when-not while with-bindings with-bindings* with-in-str with-loading-context with-local-vars with-meta with-open with-out-str with-precision xml-seq zero? zipmap ".split(" ")),b=e.arrayToMap("def do fn if let loop monitor-enter monitor-exit new quote recur set! throw try var".split(" ")),c=e.arrayToMap("true false nil".split(" "));this.$rules={start:[{token:"comment",regex:";.*$"},{token:"comment",regex:"^=begin$",next:"comment"},{token:"keyword",regex:"[\\(|\\)]"},{token:"keyword",regex:"[\\'\\(]"},{token:"keyword",regex:"[\\[|\\]]"},{token:"keyword",regex:"[\\{|\\}|\\#\\{|\\#\\}]"},{token:"keyword",regex:"[\\&]"},{token:"keyword",regex:"[\\#\\^\\{]"},{token:"keyword",regex:"[\\%]"},{token:"keyword",regex:"[@]"},{token:"constant.numeric",regex:"0[xX][0-9a-fA-F]+\\b"},{token:"constant.numeric",regex:"[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"},{token:"constant.language",regex:"[!|\\$|%|&|\\*|\\-\\-|\\-|\\+\\+|\\+||=|!=|<=|>=|<>|<|>|!|&&]"},{token:function(d){return b.hasOwnProperty(d)?"keyword":c.hasOwnProperty(d)?"constant.language":a.hasOwnProperty(d)?"support.function":"identifier"},regex:"[a-zA-Z_$][a-zA-Z0-9_$]*\\b"},{token:"string",regex:'["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'},{token:"string",regex:"[:](?:[a-zA-Z]|d)+"},{token:"string.regexp",regex:'/#"(?:.|(\\")|[^""\n])*"/g'}],comment:[{token:"comment",regex:"^=end$",next:"start"},{token:"comment",merge:!0,regex:".+"}]}};d.inherits(g,f),b.ClojureHighlightRules=g}),define("ace/mode/matching_parens_outdent",["require","exports","module","ace/range"],function(a,b,c){"use strict";var d=a("../range").Range,e=function(){};((function(){this.checkOutdent=function(a,b){return/^\s+$/.test(a)?/^\s*\)/.test(b):!1},this.autoOutdent=function(a,b){var c=a.getLine(b),e=c.match(/^(\s*\))/);if(!e)return 0;var f=e[1].length,g=a.findMatchingBracket({row:b,column:f});if(!g||g.row==b)return 0;var h=this.$getIndent(a.getLine(g.row));a.replace(new d(b,0,b,f-1),h)},this.$getIndent=function(a){var b=a.match(/^(\s+)/);return b?b[1]:""}})).call(e.prototype),b.MatchingParensOutdent=e}),function(){window.require(["ace/ace"],function(a){window.ace||(window.ace={});for(var b in a)a.hasOwnProperty(b)&&(ace[b]=a[b])})}()
\ No newline at end of file
+define("ace/mode/clojure",["require","exports","module","ace/lib/oop","ace/mode/text","ace/tokenizer","ace/mode/clojure_highlight_rules","ace/mode/matching_parens_outdent","ace/range"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("./text").Mode,f=a("../tokenizer").Tokenizer,g=a("./clojure_highlight_rules").ClojureHighlightRules,h=a("./matching_parens_outdent").MatchingParensOutdent,i=a("../range").Range,j=function(){this.$tokenizer=new f((new g).getRules()),this.$outdent=new h};d.inherits(j,e),function(){this.toggleCommentLines=function(a,b,c,d){var e=!0,f=/^(\s*)#/;for(var g=c;g<=d;g++)if(!f.test(b.getLine(g))){e=!1;break}if(e){var h=new i(0,0,0,0);for(var g=c;g<=d;g++){var j=b.getLine(g),k=j.match(f);h.start.row=g,h.end.row=g,h.end.column=k[0].length,b.replace(h,k[1])}}else b.indentRows(c,d,";")},this.getNextLineIndent=function(a,b,c){var d=this.$getIndent(b),e=this.$tokenizer.getLineTokens(b,a),f=e.tokens;if(f.length&&f[f.length-1].type=="comment")return d;if(a=="start"){var g=b.match(/[\(\[]/);g&&(d+="  "),g=b.match(/[\)]/),g&&(d="")}return d},this.checkOutdent=function(a,b,c){return this.$outdent.checkOutdent(b,c)},this.autoOutdent=function(a,b,c){this.$outdent.autoOutdent(b,c)}}.call(j.prototype),b.Mode=j}),define("ace/mode/clojure_highlight_rules",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/mode/text_highlight_rules"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("../lib/lang"),f=a("./text_highlight_rules").TextHighlightRules,g=function(){var a=e.arrayToMap("* *1 *2 *3 *agent* *allow-unresolved-vars* *assert* *clojure-version* *command-line-args* *compile-files* *compile-path* *e *err* *file* *flush-on-newline* *in* *macro-meta* *math-context* *ns* *out* *print-dup* *print-length* *print-level* *print-meta* *print-readably* *read-eval* *source-path* *use-context-classloader* *warn-on-reflection* + - -> -&gt; ->> -&gt;&gt; .. / < &lt; <= &lt;= = == > &gt; >= &gt;= accessor aclone add-classpath add-watch agent agent-errors aget alength alias all-ns alter alter-meta! alter-var-root amap ancestors and apply areduce array-map aset aset-boolean aset-byte aset-char aset-double aset-float aset-int aset-long aset-short assert assoc assoc! assoc-in associative? atom await await-for await1 bases bean bigdec bigint binding bit-and bit-and-not bit-clear bit-flip bit-not bit-or bit-set bit-shift-left bit-shift-right bit-test bit-xor boolean boolean-array booleans bound-fn bound-fn* butlast byte byte-array bytes cast char char-array char-escape-string char-name-string char? chars chunk chunk-append chunk-buffer chunk-cons chunk-first chunk-next chunk-rest chunked-seq? class class? clear-agent-errors clojure-version coll? comment commute comp comparator compare compare-and-set! compile complement concat cond condp conj conj! cons constantly construct-proxy contains? count counted? create-ns create-struct cycle dec decimal? declare definline defmacro defmethod defmulti defn defn- defonce defstruct delay delay? deliver deref derive descendants destructure disj disj! dissoc dissoc! distinct distinct? doall doc dorun doseq dosync dotimes doto double double-array doubles drop drop-last drop-while empty empty? ensure enumeration-seq eval even? every? false? ffirst file-seq filter find find-doc find-ns find-var first float float-array float? floats flush fn fn? fnext for force format future future-call future-cancel future-cancelled? future-done? future? gen-class gen-interface gensym get get-in get-method get-proxy-class get-thread-bindings get-validator hash hash-map hash-set identical? identity if-let if-not ifn? import in-ns inc init-proxy instance? int int-array integer? interleave intern interpose into into-array ints io! isa? iterate iterator-seq juxt key keys keyword keyword? last lazy-cat lazy-seq let letfn line-seq list list* list? load load-file load-reader load-string loaded-libs locking long long-array longs loop macroexpand macroexpand-1 make-array make-hierarchy map map? mapcat max max-key memfn memoize merge merge-with meta method-sig methods min min-key mod name namespace neg? newline next nfirst nil? nnext not not-any? not-empty not-every? not= ns ns-aliases ns-imports ns-interns ns-map ns-name ns-publics ns-refers ns-resolve ns-unalias ns-unmap nth nthnext num number? odd? or parents partial partition pcalls peek persistent! pmap pop pop! pop-thread-bindings pos? pr pr-str prefer-method prefers primitives-classnames print print-ctor print-doc print-dup print-method print-namespace-doc print-simple print-special-doc print-str printf println println-str prn prn-str promise proxy proxy-call-with-super proxy-mappings proxy-name proxy-super push-thread-bindings pvalues quot rand rand-int range ratio? rational? rationalize re-find re-groups re-matcher re-matches re-pattern re-seq read read-line read-string reduce ref ref-history-count ref-max-history ref-min-history ref-set refer refer-clojure release-pending-sends rem remove remove-method remove-ns remove-watch repeat repeatedly replace replicate require reset! reset-meta! resolve rest resultset-seq reverse reversible? rseq rsubseq second select-keys send send-off seq seq? seque sequence sequential? set set-validator! set? short short-array shorts shutdown-agents slurp some sort sort-by sorted-map sorted-map-by sorted-set sorted-set-by sorted? special-form-anchor special-symbol? split-at split-with str stream? string? struct struct-map subs subseq subvec supers swap! symbol symbol? sync syntax-symbol-anchor take take-last take-nth take-while test the-ns time to-array to-array-2d trampoline transient tree-seq true? type unchecked-add unchecked-dec unchecked-divide unchecked-inc unchecked-multiply unchecked-negate unchecked-remainder unchecked-subtract underive unquote unquote-splicing update-in update-proxy use val vals var-get var-set var? vary-meta vec vector vector? when when-first when-let when-not while with-bindings with-bindings* with-in-str with-loading-context with-local-vars with-meta with-open with-out-str with-precision xml-seq zero? zipmap ".split(" ")),b=e.arrayToMap("def do fn if let loop monitor-enter monitor-exit new quote recur set! throw try var".split(" ")),c=e.arrayToMap("true false nil".split(" "));this.$rules={start:[{token:"comment",regex:";.*$"},{token:"comment",regex:"^=begin$",next:"comment"},{token:"keyword",regex:"[\\(|\\)]"},{token:"keyword",regex:"[\\'\\(]"},{token:"keyword",regex:"[\\[|\\]]"},{token:"keyword",regex:"[\\{|\\}|\\#\\{|\\#\\}]"},{token:"keyword",regex:"[\\&]"},{token:"keyword",regex:"[\\#\\^\\{]"},{token:"keyword",regex:"[\\%]"},{token:"keyword",regex:"[@]"},{token:"constant.numeric",regex:"0[xX][0-9a-fA-F]+\\b"},{token:"constant.numeric",regex:"[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"},{token:"constant.language",regex:"[!|\\$|%|&|\\*|\\-\\-|\\-|\\+\\+|\\+||=|!=|<=|>=|<>|<|>|!|&&]"},{token:function(d){return b.hasOwnProperty(d)?"keyword":c.hasOwnProperty(d)?"constant.language":a.hasOwnProperty(d)?"support.function":"identifier"},regex:"[a-zA-Z_$][a-zA-Z0-9_$]*\\b"},{token:"string",regex:'["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'},{token:"string",regex:"[:](?:[a-zA-Z]|\\d)+"},{token:"string.regexp",regex:'/#"(?:\\.|(?:\\")|[^""\n])*"/g'}],comment:[{token:"comment",regex:"^=end$",next:"start"},{token:"comment",merge:!0,regex:".+"}]}};d.inherits(g,f),b.ClojureHighlightRules=g}),define("ace/mode/matching_parens_outdent",["require","exports","module","ace/range"],function(a,b,c){"use strict";var d=a("../range").Range,e=function(){};(function(){this.checkOutdent=function(a,b){return/^\s+$/.test(a)?/^\s*\)/.test(b):!1},this.autoOutdent=function(a,b){var c=a.getLine(b),e=c.match(/^(\s*\))/);if(!e)return 0;var f=e[1].length,g=a.findMatchingBracket({row:b,column:f});if(!g||g.row==b)return 0;var h=this.$getIndent(a.getLine(g.row));a.replace(new d(b,0,b,f-1),h)},this.$getIndent=function(a){var b=a.match(/^(\s+)/);return b?b[1]:""}}).call(e.prototype),b.MatchingParensOutdent=e})
\ No newline at end of file
diff --git a/apps/files_texteditor/js/aceeditor/mode-coffee-uncompressed.js b/apps/files_texteditor/js/aceeditor/mode-coffee-uncompressed.js
old mode 100755
new mode 100644
index 9a06cbfcfe9f330505186877762fc8df491bf8eb..de6cbf4137c0a4df4edd47d83637c3bd0e237561
--- a/apps/files_texteditor/js/aceeditor/mode-coffee-uncompressed.js
+++ b/apps/files_texteditor/js/aceeditor/mode-coffee-uncompressed.js
@@ -603,202 +603,3 @@ var FoldMode = exports.FoldMode = function() {};
 }).call(FoldMode.prototype);
 
 });
-/* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is Ajax.org Code Editor (ACE).
- *
- * The Initial Developer of the Original Code is
- * Ajax.org B.V.
- * Portions created by the Initial Developer are Copyright (C) 2010
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *      Fabian Jakobs <fabian AT ajax DOT org>
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-define('ace/worker/worker_client', ['require', 'exports', 'module' , 'ace/lib/oop', 'ace/lib/event_emitter'], function(require, exports, module) {
-"use strict";
-
-var oop = require("../lib/oop");
-var EventEmitter = require("../lib/event_emitter").EventEmitter;
-
-var WorkerClient = function(topLevelNamespaces, packagedJs, mod, classname) {
-
-    this.changeListener = this.changeListener.bind(this);
-
-    if (module.packaged) {
-        var base = this.$guessBasePath();
-        this.$worker = new Worker(base + packagedJs);
-    }
-    else {
-        var workerUrl = this.$normalizePath(require.nameToUrl("ace/worker/worker", null, "_"));
-        this.$worker = new Worker(workerUrl);
-
-        var tlns = {};
-        for (var i=0; i<topLevelNamespaces.length; i++) {
-            var ns = topLevelNamespaces[i];
-            var path = this.$normalizePath(require.nameToUrl(ns, null, "_").replace(/.js$/, ""));
-
-            tlns[ns] = path;
-        }
-    }
-
-    this.$worker.postMessage({
-        init : true,
-        tlns: tlns,
-        module: mod,
-        classname: classname
-    });
-
-    this.callbackId = 1;
-    this.callbacks = {};
-
-    var _self = this;
-    this.$worker.onerror = function(e) {
-        window.console && console.log && console.log(e);
-        throw e;
-    };
-    this.$worker.onmessage = function(e) {
-        var msg = e.data;
-        switch(msg.type) {
-            case "log":
-                window.console && console.log && console.log(msg.data);
-                break;
-
-            case "event":
-                _self._emit(msg.name, {data: msg.data});
-                break;
-
-            case "call":
-                var callback = _self.callbacks[msg.id];
-                if (callback) {
-                    callback(msg.data);
-                    delete _self.callbacks[msg.id];
-                }
-                break;
-        }
-    };
-};
-
-(function(){
-
-    oop.implement(this, EventEmitter);
-
-    this.$normalizePath = function(path) {
-        path = path.replace(/^[a-z]+:\/\/[^\/]+\//, ""); // Remove domain name and rebuild it
-        path = location.protocol + "//" + location.host
-            // paths starting with a slash are relative to the root (host)
-            + (path.charAt(0) == "/" ? "" : location.pathname.replace(/\/[^\/]*$/, ""))
-            + "/" + path.replace(/^[\/]+/, "");
-        return path;
-    };
-
-    this.$guessBasePath = function() {
-        if (require.aceBaseUrl)
-            return require.aceBaseUrl;
-
-        var scripts = document.getElementsByTagName("script");
-        for (var i=0; i<scripts.length; i++) {
-            var script = scripts[i];
-
-            var base = script.getAttribute("data-ace-base");
-            if (base)
-                return base.replace(/\/*$/, "/");
-
-            var src = script.src || script.getAttribute("src");
-            if (!src) {
-                continue;
-            }
-            var m = src.match(/^(?:(.*\/)ace\.js|(.*\/)ace(-uncompressed)?(-noconflict)?\.js)(?:\?|$)/);
-            if (m)
-                return m[1] || m[2];
-        }
-        return "";
-    };
-
-    this.terminate = function() {
-        this._emit("terminate", {});
-        this.$worker.terminate();
-        this.$worker = null;
-        this.$doc.removeEventListener("change", this.changeListener);
-        this.$doc = null;
-    };
-
-    this.send = function(cmd, args) {
-        this.$worker.postMessage({command: cmd, args: args});
-    };
-
-    this.call = function(cmd, args, callback) {
-        if (callback) {
-            var id = this.callbackId++;
-            this.callbacks[id] = callback;
-            args.push(id);
-        }
-        this.send(cmd, args);
-    };
-
-    this.emit = function(event, data) {
-        try {
-            // firefox refuses to clone objects which have function properties
-            // TODO: cleanup event
-            this.$worker.postMessage({event: event, data: {data: data.data}});
-        }
-        catch(ex) {}
-    };
-
-    this.attachToDocument = function(doc) {
-        if(this.$doc)
-            this.terminate();
-
-        this.$doc = doc;
-        this.call("setValue", [doc.getValue()]);
-        doc.on("change", this.changeListener);
-    };
-
-    this.changeListener = function(e) {
-        e.range = {
-            start: e.data.range.start,
-            end: e.data.range.end
-        };
-        this.emit("change", e);
-    };
-
-}).call(WorkerClient.prototype);
-
-exports.WorkerClient = WorkerClient;
-
-});
-;
-            (function() {
-                window.require(["ace/ace"], function(a) {
-                    if (!window.ace)
-                        window.ace = {};
-                    for (var key in a) if (a.hasOwnProperty(key))
-                        ace[key] = a[key];
-                });
-            })();
-        
\ No newline at end of file
diff --git a/apps/files_texteditor/js/aceeditor/mode-coffee.js b/apps/files_texteditor/js/aceeditor/mode-coffee.js
index c42e1f801c0068a4a6e043dd96beb5901d8649a1..f8a9d63788f93307601f850abb23d85933111f7b 100644
--- a/apps/files_texteditor/js/aceeditor/mode-coffee.js
+++ b/apps/files_texteditor/js/aceeditor/mode-coffee.js
@@ -1 +1 @@
-define("ace/mode/coffee",["require","exports","module","ace/tokenizer","ace/mode/coffee_highlight_rules","ace/mode/matching_brace_outdent","ace/mode/folding/pythonic","ace/range","ace/mode/text","ace/worker/worker_client","ace/lib/oop"],function(a,b,c){function l(){this.$tokenizer=new d((new e).getRules()),this.$outdent=new f,this.foldingRules=new g("=|=>|->|\\s*class [^#]*")}"use strict";var d=a("../tokenizer").Tokenizer,e=a("./coffee_highlight_rules").CoffeeHighlightRules,f=a("./matching_brace_outdent").MatchingBraceOutdent,g=a("./folding/pythonic").FoldMode,h=a("../range").Range,i=a("./text").Mode,j=a("../worker/worker_client").WorkerClient,k=a("../lib/oop");k.inherits(l,i),function(){var a=/(?:[({[=:]|[-=]>|\b(?:else|switch|try|catch(?:\s*[$A-Za-z_\x7f-\uffff][$\w\x7f-\uffff]*)?|finally))\s*$/,b=/^(\s*)#/,c=/^\s*###(?!#)/,d=/^\s*/;this.getNextLineIndent=function(b,c,d){var e=this.$getIndent(c),f=this.$tokenizer.getLineTokens(c,b).tokens;return(!f.length||f[f.length-1].type!=="comment")&&b==="start"&&a.test(c)&&(e+=d),e},this.toggleCommentLines=function(a,e,f,g){console.log("toggle");var i=new h(0,0,0,0);for(var j=f;j<=g;++j){var k=e.getLine(j);if(c.test(k))continue;b.test(k)?k=k.replace(b,"$1"):k=k.replace(d,"$&#"),i.end.row=i.start.row=j,i.end.column=k.length+1,e.replace(i,k)}},this.checkOutdent=function(a,b,c){return this.$outdent.checkOutdent(b,c)},this.autoOutdent=function(a,b,c){this.$outdent.autoOutdent(b,c)},this.createWorker=function(a){var b=new j(["ace"],"worker-coffee.js","ace/mode/coffee_worker","Worker");return b.attachToDocument(a.getDocument()),b.on("error",function(b){a.setAnnotations([b.data])}),b.on("ok",function(b){a.clearAnnotations()}),b}}.call(l.prototype),b.Mode=l}),define("ace/mode/coffee_highlight_rules",["require","exports","module","ace/lib/lang","ace/lib/oop","ace/mode/text_highlight_rules"],function(a,b,c){function g(){var a="[$A-Za-z_\\x7f-\\uffff][$\\w\\x7f-\\uffff]*",b={token:"string",merge:!0,regex:".+"},c=d.arrayToMap("this|throw|then|try|typeof|super|switch|return|break|by)|continue|catch|class|in|instanceof|is|isnt|if|else|extends|for|forown|finally|function|while|when|new|no|not|delete|debugger|do|loop|of|off|or|on|unless|until|and|yes".split("|")),e=d.arrayToMap("true|false|null|undefined".split("|")),f=d.arrayToMap("case|const|default|function|var|void|with|enum|export|implements|interface|let|package|private|protected|public|static|yield|__hasProp|extends|slice|bind|indexOf".split("|")),g=d.arrayToMap("Array|Boolean|Date|Function|Number|Object|RegExp|ReferenceError|RangeError|String|SyntaxError|Error|EvalError|TypeError|URIError".split("|")),h=d.arrayToMap("Math|JSON|isNaN|isFinite|parseInt|parseFloat|encodeURI|encodeURIComponent|decodeURI|decodeURIComponent|RangeError|String|SyntaxError|Error|EvalError|TypeError|URIError".split("|"));this.$rules={start:[{token:"identifier",regex:"(?:(?:\\.|::)\\s*)"+a},{token:"variable",regex:"@(?:"+a+")?"},{token:function(a){return c.hasOwnProperty(a)?"keyword":e.hasOwnProperty(a)?"constant.language":f.hasOwnProperty(a)?"invalid.illegal":g.hasOwnProperty(a)?"language.support.class":h.hasOwnProperty(a)?"language.support.function":"identifier"},regex:a},{token:"constant.numeric",regex:"(?:0x[\\da-fA-F]+|(?:\\d+(?:\\.\\d+)?|\\.\\d+)(?:[eE][+-]?\\d+)?)"},{token:"string",merge:!0,regex:"'''",next:"qdoc"},{token:"string",merge:!0,regex:'"""',next:"qqdoc"},{token:"string",merge:!0,regex:"'",next:"qstring"},{token:"string",merge:!0,regex:'"',next:"qqstring"},{token:"string",merge:!0,regex:"`",next:"js"},{token:"string.regex",merge:!0,regex:"///",next:"heregex"},{token:"string.regex",regex:"/(?!\\s)[^[/\\n\\\\]*(?: (?:\\\\.|\\[[^\\]\\n\\\\]*(?:\\\\.[^\\]\\n\\\\]*)*\\])[^[/\\n\\\\]*)*/[imgy]{0,4}(?!\\w)"},{token:"comment",merge:!0,regex:"###(?!#)",next:"comment"},{token:"comment",regex:"#.*"},{token:"punctuation.operator",regex:"\\?|\\:|\\,|\\."},{token:"keyword.operator",regex:"(?:[\\-=]>|[-+*/%<>&|^!?=]=|>>>=?|\\-\\-|\\+\\+|::|&&=|\\|\\|=|<<=|>>=|\\?\\.|\\.{2,3}|\\!)"},{token:"paren.lparen",regex:"[({[]"},{token:"paren.rparen",regex:"[\\]})]"},{token:"text",regex:"\\s+"}],qdoc:[{token:"string",regex:".*?'''",next:"start"},b],qqdoc:[{token:"string",regex:'.*?"""',next:"start"},b],qstring:[{token:"string",regex:"[^\\\\']*(?:\\\\.[^\\\\']*)*'",merge:!0,next:"start"},b],qqstring:[{token:"string",regex:'[^\\\\"]*(?:\\\\.[^\\\\"]*)*"',merge:!0,next:"start"},b],js:[{token:"string",merge:!0,regex:"[^\\\\`]*(?:\\\\.[^\\\\`]*)*`",next:"start"},b],heregex:[{token:"string.regex",regex:".*?///[imgy]{0,4}",next:"start"},{token:"comment.regex",regex:"\\s+(?:#.*)?"},{token:"string.regex",merge:!0,regex:"\\S+"}],comment:[{token:"comment",regex:".*?###",next:"start"},{token:"comment",merge:!0,regex:".+"}]}}"use strict";var d=a("../lib/lang"),e=a("../lib/oop"),f=a("./text_highlight_rules").TextHighlightRules;e.inherits(g,f),b.CoffeeHighlightRules=g}),define("ace/mode/matching_brace_outdent",["require","exports","module","ace/range"],function(a,b,c){"use strict";var d=a("../range").Range,e=function(){};((function(){this.checkOutdent=function(a,b){return/^\s+$/.test(a)?/^\s*\}/.test(b):!1},this.autoOutdent=function(a,b){var c=a.getLine(b),e=c.match(/^(\s*\})/);if(!e)return 0;var f=e[1].length,g=a.findMatchingBracket({row:b,column:f});if(!g||g.row==b)return 0;var h=this.$getIndent(a.getLine(g.row));a.replace(new d(b,0,b,f-1),h)},this.$getIndent=function(a){var b=a.match(/^(\s+)/);return b?b[1]:""}})).call(e.prototype),b.MatchingBraceOutdent=e}),define("ace/mode/folding/pythonic",["require","exports","module","ace/lib/oop","ace/mode/folding/fold_mode"],function(a,b,c){"use strict";var d=a("../../lib/oop"),e=a("./fold_mode").FoldMode,f=b.FoldMode=function(a){this.foldingStartMarker=new RegExp("(?:([\\[{])|("+a+"))(?:\\s*)(?:#.*)?$")};d.inherits(f,e),function(){this.getFoldWidgetRange=function(a,b,c){var d=a.getLine(c),e=d.match(this.foldingStartMarker);if(e)return e[1]?this.openingBracketBlock(a,e[1],c,e.index):e[2]?this.indentationBlock(a,c,e.index+e[2].length):this.indentationBlock(a,c)}}.call(f.prototype)}),define("ace/mode/folding/fold_mode",["require","exports","module","ace/range"],function(a,b,c){"use strict";var d=a("../../range").Range,e=b.FoldMode=function(){};((function(){this.foldingStartMarker=null,this.foldingStopMarker=null,this.getFoldWidget=function(a,b,c){var d=a.getLine(c);return this.foldingStartMarker.test(d)?"start":b=="markbeginend"&&this.foldingStopMarker&&this.foldingStopMarker.test(d)?"end":""},this.getFoldWidgetRange=function(a,b,c){return null},this.indentationBlock=function(a,b,c){var e=/^\s*/,f=b,g=b,h=a.getLine(b),i=c||h.length,j=h.match(e)[0].length,k=a.getLength();while(++b<k){h=a.getLine(b);var l=h.match(e)[0].length;if(l==h.length)continue;if(l<=j)break;g=b}if(g>f){var m=a.getLine(g).length;return new d(f,i,g,m)}},this.openingBracketBlock=function(a,b,c,e){var f={row:c,column:e+1},g=a.$findClosingBracket(b,f);if(!g)return;var h=a.foldWidgets[g.row];return h==null&&(h=this.getFoldWidget(a,g.row)),h=="start"&&(g.row--,g.column=a.getLine(g.row).length),d.fromPoints(f,g)}})).call(e.prototype)}),define("ace/worker/worker_client",["require","exports","module","ace/lib/oop","ace/lib/event_emitter"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("../lib/event_emitter").EventEmitter,f=function(b,d,e,f){this.changeListener=this.changeListener.bind(this);if(c.packaged){var g=this.$guessBasePath();this.$worker=new Worker(g+d)}else{var h=this.$normalizePath(a.nameToUrl("ace/worker/worker",null,"_"));this.$worker=new Worker(h);var i={};for(var j=0;j<b.length;j++){var k=b[j],l=this.$normalizePath(a.nameToUrl(k,null,"_").replace(/.js$/,""));i[k]=l}}this.$worker.postMessage({init:!0,tlns:i,module:e,classname:f}),this.callbackId=1,this.callbacks={};var m=this;this.$worker.onerror=function(a){throw window.console&&console.log&&console.log(a),a},this.$worker.onmessage=function(a){var b=a.data;switch(b.type){case"log":window.console&&console.log&&console.log(b.data);break;case"event":m._emit(b.name,{data:b.data});break;case"call":var c=m.callbacks[b.id];c&&(c(b.data),delete m.callbacks[b.id])}}};((function(){d.implement(this,e),this.$normalizePath=function(a){return a=a.replace(/^[a-z]+:\/\/[^\/]+\//,""),a=location.protocol+"//"+location.host+(a.charAt(0)=="/"?"":location.pathname.replace(/\/[^\/]*$/,""))+"/"+a.replace(/^[\/]+/,""),a},this.$guessBasePath=function(){if(a.aceBaseUrl)return a.aceBaseUrl;var b=document.getElementsByTagName("script");for(var c=0;c<b.length;c++){var d=b[c],e=d.getAttribute("data-ace-base");if(e)return e.replace(/\/*$/,"/");var f=d.src||d.getAttribute("src");if(!f)continue;var g=f.match(/^(?:(.*\/)ace\.js|(.*\/)ace(-uncompressed)?(-noconflict)?\.js)(?:\?|$)/);if(g)return g[1]||g[2]}return""},this.terminate=function(){this._emit("terminate",{}),this.$worker.terminate(),this.$worker=null,this.$doc.removeEventListener("change",this.changeListener),this.$doc=null},this.send=function(a,b){this.$worker.postMessage({command:a,args:b})},this.call=function(a,b,c){if(c){var d=this.callbackId++;this.callbacks[d]=c,b.push(d)}this.send(a,b)},this.emit=function(a,b){try{this.$worker.postMessage({event:a,data:{data:b.data}})}catch(c){}},this.attachToDocument=function(a){this.$doc&&this.terminate(),this.$doc=a,this.call("setValue",[a.getValue()]),a.on("change",this.changeListener)},this.changeListener=function(a){a.range={start:a.data.range.start,end:a.data.range.end},this.emit("change",a)}})).call(f.prototype),b.WorkerClient=f}),function(){window.require(["ace/ace"],function(a){window.ace||(window.ace={});for(var b in a)a.hasOwnProperty(b)&&(ace[b]=a[b])})}()
\ No newline at end of file
+define("ace/mode/coffee",["require","exports","module","ace/tokenizer","ace/mode/coffee_highlight_rules","ace/mode/matching_brace_outdent","ace/mode/folding/pythonic","ace/range","ace/mode/text","ace/worker/worker_client","ace/lib/oop"],function(a,b,c){function l(){this.$tokenizer=new d((new e).getRules()),this.$outdent=new f,this.foldingRules=new g("=|=>|->|\\s*class [^#]*")}"use strict";var d=a("../tokenizer").Tokenizer,e=a("./coffee_highlight_rules").CoffeeHighlightRules,f=a("./matching_brace_outdent").MatchingBraceOutdent,g=a("./folding/pythonic").FoldMode,h=a("../range").Range,i=a("./text").Mode,j=a("../worker/worker_client").WorkerClient,k=a("../lib/oop");k.inherits(l,i),function(){var a=/(?:[({[=:]|[-=]>|\b(?:else|switch|try|catch(?:\s*[$A-Za-z_\x7f-\uffff][$\w\x7f-\uffff]*)?|finally))\s*$/,b=/^(\s*)#/,c=/^\s*###(?!#)/,d=/^\s*/;this.getNextLineIndent=function(b,c,d){var e=this.$getIndent(c),f=this.$tokenizer.getLineTokens(c,b).tokens;return(!f.length||f[f.length-1].type!=="comment")&&b==="start"&&a.test(c)&&(e+=d),e},this.toggleCommentLines=function(a,e,f,g){console.log("toggle");var i=new h(0,0,0,0);for(var j=f;j<=g;++j){var k=e.getLine(j);if(c.test(k))continue;b.test(k)?k=k.replace(b,"$1"):k=k.replace(d,"$&#"),i.end.row=i.start.row=j,i.end.column=k.length+1,e.replace(i,k)}},this.checkOutdent=function(a,b,c){return this.$outdent.checkOutdent(b,c)},this.autoOutdent=function(a,b,c){this.$outdent.autoOutdent(b,c)},this.createWorker=function(a){var b=new j(["ace"],"worker-coffee.js","ace/mode/coffee_worker","Worker");return b.attachToDocument(a.getDocument()),b.on("error",function(b){a.setAnnotations([b.data])}),b.on("ok",function(b){a.clearAnnotations()}),b}}.call(l.prototype),b.Mode=l}),define("ace/mode/coffee_highlight_rules",["require","exports","module","ace/lib/lang","ace/lib/oop","ace/mode/text_highlight_rules"],function(a,b,c){function g(){var a="[$A-Za-z_\\x7f-\\uffff][$\\w\\x7f-\\uffff]*",b={token:"string",merge:!0,regex:".+"},c=d.arrayToMap("this|throw|then|try|typeof|super|switch|return|break|by)|continue|catch|class|in|instanceof|is|isnt|if|else|extends|for|forown|finally|function|while|when|new|no|not|delete|debugger|do|loop|of|off|or|on|unless|until|and|yes".split("|")),e=d.arrayToMap("true|false|null|undefined".split("|")),f=d.arrayToMap("case|const|default|function|var|void|with|enum|export|implements|interface|let|package|private|protected|public|static|yield|__hasProp|extends|slice|bind|indexOf".split("|")),g=d.arrayToMap("Array|Boolean|Date|Function|Number|Object|RegExp|ReferenceError|RangeError|String|SyntaxError|Error|EvalError|TypeError|URIError".split("|")),h=d.arrayToMap("Math|JSON|isNaN|isFinite|parseInt|parseFloat|encodeURI|encodeURIComponent|decodeURI|decodeURIComponent|RangeError|String|SyntaxError|Error|EvalError|TypeError|URIError".split("|"));this.$rules={start:[{token:"identifier",regex:"(?:(?:\\.|::)\\s*)"+a},{token:"variable",regex:"@(?:"+a+")?"},{token:function(a){return c.hasOwnProperty(a)?"keyword":e.hasOwnProperty(a)?"constant.language":f.hasOwnProperty(a)?"invalid.illegal":g.hasOwnProperty(a)?"language.support.class":h.hasOwnProperty(a)?"language.support.function":"identifier"},regex:a},{token:"constant.numeric",regex:"(?:0x[\\da-fA-F]+|(?:\\d+(?:\\.\\d+)?|\\.\\d+)(?:[eE][+-]?\\d+)?)"},{token:"string",merge:!0,regex:"'''",next:"qdoc"},{token:"string",merge:!0,regex:'"""',next:"qqdoc"},{token:"string",merge:!0,regex:"'",next:"qstring"},{token:"string",merge:!0,regex:'"',next:"qqstring"},{token:"string",merge:!0,regex:"`",next:"js"},{token:"string.regex",merge:!0,regex:"///",next:"heregex"},{token:"string.regex",regex:"/(?!\\s)[^[/\\n\\\\]*(?: (?:\\\\.|\\[[^\\]\\n\\\\]*(?:\\\\.[^\\]\\n\\\\]*)*\\])[^[/\\n\\\\]*)*/[imgy]{0,4}(?!\\w)"},{token:"comment",merge:!0,regex:"###(?!#)",next:"comment"},{token:"comment",regex:"#.*"},{token:"punctuation.operator",regex:"\\?|\\:|\\,|\\."},{token:"keyword.operator",regex:"(?:[\\-=]>|[-+*/%<>&|^!?=]=|>>>=?|\\-\\-|\\+\\+|::|&&=|\\|\\|=|<<=|>>=|\\?\\.|\\.{2,3}|\\!)"},{token:"paren.lparen",regex:"[({[]"},{token:"paren.rparen",regex:"[\\]})]"},{token:"text",regex:"\\s+"}],qdoc:[{token:"string",regex:".*?'''",next:"start"},b],qqdoc:[{token:"string",regex:'.*?"""',next:"start"},b],qstring:[{token:"string",regex:"[^\\\\']*(?:\\\\.[^\\\\']*)*'",merge:!0,next:"start"},b],qqstring:[{token:"string",regex:'[^\\\\"]*(?:\\\\.[^\\\\"]*)*"',merge:!0,next:"start"},b],js:[{token:"string",merge:!0,regex:"[^\\\\`]*(?:\\\\.[^\\\\`]*)*`",next:"start"},b],heregex:[{token:"string.regex",regex:".*?///[imgy]{0,4}",next:"start"},{token:"comment.regex",regex:"\\s+(?:#.*)?"},{token:"string.regex",merge:!0,regex:"\\S+"}],comment:[{token:"comment",regex:".*?###",next:"start"},{token:"comment",merge:!0,regex:".+"}]}}"use strict";var d=a("../lib/lang"),e=a("../lib/oop"),f=a("./text_highlight_rules").TextHighlightRules;e.inherits(g,f),b.CoffeeHighlightRules=g}),define("ace/mode/matching_brace_outdent",["require","exports","module","ace/range"],function(a,b,c){"use strict";var d=a("../range").Range,e=function(){};(function(){this.checkOutdent=function(a,b){return/^\s+$/.test(a)?/^\s*\}/.test(b):!1},this.autoOutdent=function(a,b){var c=a.getLine(b),e=c.match(/^(\s*\})/);if(!e)return 0;var f=e[1].length,g=a.findMatchingBracket({row:b,column:f});if(!g||g.row==b)return 0;var h=this.$getIndent(a.getLine(g.row));a.replace(new d(b,0,b,f-1),h)},this.$getIndent=function(a){var b=a.match(/^(\s+)/);return b?b[1]:""}}).call(e.prototype),b.MatchingBraceOutdent=e}),define("ace/mode/folding/pythonic",["require","exports","module","ace/lib/oop","ace/mode/folding/fold_mode"],function(a,b,c){"use strict";var d=a("../../lib/oop"),e=a("./fold_mode").FoldMode,f=b.FoldMode=function(a){this.foldingStartMarker=new RegExp("(?:([\\[{])|("+a+"))(?:\\s*)(?:#.*)?$")};d.inherits(f,e),function(){this.getFoldWidgetRange=function(a,b,c){var d=a.getLine(c),e=d.match(this.foldingStartMarker);if(e)return e[1]?this.openingBracketBlock(a,e[1],c,e.index):e[2]?this.indentationBlock(a,c,e.index+e[2].length):this.indentationBlock(a,c)}}.call(f.prototype)}),define("ace/mode/folding/fold_mode",["require","exports","module","ace/range"],function(a,b,c){"use strict";var d=a("../../range").Range,e=b.FoldMode=function(){};(function(){this.foldingStartMarker=null,this.foldingStopMarker=null,this.getFoldWidget=function(a,b,c){var d=a.getLine(c);return this.foldingStartMarker.test(d)?"start":b=="markbeginend"&&this.foldingStopMarker&&this.foldingStopMarker.test(d)?"end":""},this.getFoldWidgetRange=function(a,b,c){return null},this.indentationBlock=function(a,b,c){var e=/^\s*/,f=b,g=b,h=a.getLine(b),i=c||h.length,j=h.match(e)[0].length,k=a.getLength();while(++b<k){h=a.getLine(b);var l=h.match(e)[0].length;if(l==h.length)continue;if(l<=j)break;g=b}if(g>f){var m=a.getLine(g).length;return new d(f,i,g,m)}},this.openingBracketBlock=function(a,b,c,e){var f={row:c,column:e+1},g=a.$findClosingBracket(b,f);if(!g)return;var h=a.foldWidgets[g.row];return h==null&&(h=this.getFoldWidget(a,g.row)),h=="start"&&(g.row--,g.column=a.getLine(g.row).length),d.fromPoints(f,g)}}).call(e.prototype)})
\ No newline at end of file
diff --git a/apps/files_texteditor/js/aceeditor/mode-coldfusion-uncompressed.js b/apps/files_texteditor/js/aceeditor/mode-coldfusion-uncompressed.js
old mode 100755
new mode 100644
index c9092a5e0c2c45536dccbcdf1af659c99e959576..af5e3914b569bd2d662273eca66e480b2a36fd84
--- a/apps/files_texteditor/js/aceeditor/mode-coldfusion-uncompressed.js
+++ b/apps/files_texteditor/js/aceeditor/mode-coldfusion-uncompressed.js
@@ -195,6 +195,9 @@ var XmlHighlightRules = function() {
             merge : true,
             regex : "<\\!--",
             next : "comment"
+        }, {
+            token : "xml_pe",
+            regex : "<\\!.*?>"
         }, {
             token : "meta.tag", // opening tag
             regex : "<\\/?",
@@ -202,6 +205,9 @@ var XmlHighlightRules = function() {
         }, {
             token : "text",
             regex : "\\s+"
+        }, {
+            token : "constant.character.entity",
+            regex : "(?:&#[0-9]+;)|(?:&#x[0-9a-fA-F]+;)|(?:&[a-zA-Z0-9_:\\.-]+;)"
         }, {
             token : "text",
             regex : "[^<]+"
@@ -295,7 +301,7 @@ function string(state) {
         token : "string", // multi line string start
         merge : true,
         regex : '["].*',
-        next : state + "-qqstring"
+        next : state + "_qqstring"
     }, {
         token : "string",
         regex : "'.*?'"
@@ -303,7 +309,7 @@ function string(state) {
         token : "string", // multi line string start
         merge : true,
         regex : "['].*",
-        next : state + "-qstring"
+        next : state + "_qstring"
     }];
 }
 
@@ -351,18 +357,18 @@ exports.tag = function(states, name, nextState) {
             }
         },        
         merge : true,
-        regex : "[-_a-zA-Z0-9:!]+",
-        next : name + "embed-attribute-list" 
+        regex : "[-_a-zA-Z0-9:]+",
+        next : name + "_embed_attribute_list" 
     }, {
         token: "empty",
         regex: "",
-        next : name + "embed-attribute-list"
+        next : name + "_embed_attribute_list"
     }];
 
-    states[name + "-qstring"] = multiLineString("'", name + "embed-attribute-list");
-    states[name + "-qqstring"] = multiLineString("\"", name + "embed-attribute-list");
+    states[name + "_qstring"] = multiLineString("'", name + "_embed_attribute_list");
+    states[name + "_qqstring"] = multiLineString("\"", name + "_embed_attribute_list");
     
-    states[name + "embed-attribute-list"] = [{
+    states[name + "_embed_attribute_list"] = [{
         token : "meta.tag",
         merge : true,
         regex : "\/?>",
@@ -528,12 +534,12 @@ var CstyleBehaviour = function () {
                 return {
                     text: '{' + selected + '}',
                     selection: false
-                }
+                };
             } else {
                 return {
                     text: '{}',
                     selection: [1, 1]
-                }
+                };
             }
         } else if (text == '}') {
             var cursor = editor.getCursorPosition();
@@ -545,7 +551,7 @@ var CstyleBehaviour = function () {
                     return {
                         text: '',
                         selection: [1, 1]
-                    }
+                    };
                 }
             }
         } else if (text == "\n") {
@@ -563,7 +569,7 @@ var CstyleBehaviour = function () {
                 return {
                     text: '\n' + indent + '\n' + next_indent,
                     selection: [1, indent.length, 1, indent.length]
-                }
+                };
             }
         }
     });
@@ -588,12 +594,12 @@ var CstyleBehaviour = function () {
                 return {
                     text: '(' + selected + ')',
                     selection: false
-                }
+                };
             } else {
                 return {
                     text: '()',
                     selection: [1, 1]
-                }
+                };
             }
         } else if (text == ')') {
             var cursor = editor.getCursorPosition();
@@ -605,7 +611,7 @@ var CstyleBehaviour = function () {
                     return {
                         text: '',
                         selection: [1, 1]
-                    }
+                    };
                 }
             }
         }
@@ -624,14 +630,15 @@ var CstyleBehaviour = function () {
     });
 
     this.add("string_dquotes", "insertion", function (state, action, editor, session, text) {
-        if (text == '"') {
+        if (text == '"' || text == "'") {
+            var quote = text;
             var selection = editor.getSelectionRange();
             var selected = session.doc.getTextRange(selection);
             if (selected !== "") {
                 return {
-                    text: '"' + selected + '"',
+                    text: quote + selected + quote,
                     selection: false
-                }
+                };
             } else {
                 var cursor = editor.getCursorPosition();
                 var line = session.doc.getLine(cursor.row);
@@ -652,7 +659,7 @@ var CstyleBehaviour = function () {
                     if (token.type == "string") {
                       quotepos = -1;
                     } else if (quotepos < 0) {
-                      quotepos = token.value.indexOf('"');
+                      quotepos = token.value.indexOf(quote);
                     }
                     if ((token.value.length + col) > selection.start.column) {
                         break;
@@ -661,19 +668,19 @@ var CstyleBehaviour = function () {
                 }
 
                 // Try and be smart about when we auto insert.
-                if (!token || (quotepos < 0 && token.type !== "comment" && (token.type !== "string" || ((selection.start.column !== token.value.length+col-1) && token.value.lastIndexOf('"') === token.value.length-1)))) {
+                if (!token || (quotepos < 0 && token.type !== "comment" && (token.type !== "string" || ((selection.start.column !== token.value.length+col-1) && token.value.lastIndexOf(quote) === token.value.length-1)))) {
                     return {
-                        text: '""',
+                        text: quote + quote,
                         selection: [1,1]
-                    }
+                    };
                 } else if (token && token.type === "string") {
                     // Ignore input and move right one if we're typing over the closing quote.
                     var rightChar = line.substring(cursor.column, cursor.column + 1);
-                    if (rightChar == '"') {
+                    if (rightChar == quote) {
                         return {
                             text: '',
                             selection: [1, 1]
-                        }
+                        };
                     }
                 }
             }
@@ -682,7 +689,7 @@ var CstyleBehaviour = function () {
 
     this.add("string_dquotes", "deletion", function (state, action, editor, session, range) {
         var selected = session.doc.getTextRange(range);
-        if (!range.isMultiLine() && selected == '"') {
+        if (!range.isMultiLine() && (selected == '"' || selected == "'")) {
             var line = session.doc.getLine(range.start.row);
             var rightChar = line.substring(range.start.column + 1, range.start.column + 2);
             if (rightChar == '"') {
@@ -692,7 +699,8 @@ var CstyleBehaviour = function () {
         }
     });
 
-}
+};
+
 oop.inherits(CstyleBehaviour, Behaviour);
 
 exports.CstyleBehaviour = CstyleBehaviour;
@@ -1329,12 +1337,20 @@ var JavaScriptHighlightRules = function() {
     );
 
     // TODO: Unicode escape sequences
-    var identifierRe = "[" + unicode.packages.L + "\\$_][" 
+    var identifierRe = "[" + unicode.packages.L + "\\$_]["
         + unicode.packages.L
         + unicode.packages.Mn + unicode.packages.Mc
         + unicode.packages.Nd
         + unicode.packages.Pc + "\\$_]*\\b";
-        
+
+    var escapedRe = "\\\\(?:x[0-9a-fA-F]{2}|" + // hex
+        "u[0-9a-fA-F]{4}|" + // unicode
+        "[0-2][0-7]{0,2}|" + // oct
+        "3[0-6][0-7]?|" + // oct
+        "37[0-7]?|" + // oct
+        "[4-7][0-7]?|" + //oct
+        ".)";
+
     // regexp must not have capturing parentheses. Use (?:) instead.
     // regexps are ordered -> the first match is used
 
@@ -1342,46 +1358,139 @@ var JavaScriptHighlightRules = function() {
         "start" : [
             {
                 token : "comment",
-                regex : "\\/\\/.*$"
+                regex : /\/\/.*$/
             },
             new DocCommentHighlightRules().getStartRule("doc-start"),
             {
                 token : "comment", // multi line comment
                 merge : true,
-                regex : "\\/\\*",
+                regex : /\/\*/,
                 next : "comment"
             }, {
-                token : "string", // single line
-                regex : '["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'
-            }, {
-                token : "string", // multi line string start
-                merge : true,
-                regex : '["].*\\\\$',
-                next : "qqstring"
-            }, {
-                token : "string", // single line
-                regex : "['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"
+                token : "string",
+                regex : "'",
+                next  : "qstring"
             }, {
-                token : "string", // multi line string start
-                merge : true,
-                regex : "['].*\\\\$",
-                next : "qstring"
+                token : "string",
+                regex : '"',
+                next  : "qqstring"
             }, {
                 token : "constant.numeric", // hex
-                regex : "0[xX][0-9a-fA-F]+\\b"
+                regex : /0[xX][0-9a-fA-F]+\b/
             }, {
                 token : "constant.numeric", // float
-                regex : "[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"
-            }, {
-                token : ["keyword.definition", "text", "entity.name.function"],
-                regex : "(function)(\\s+)(" + identifierRe + ")"
+                regex : /[+-]?\d+(?:(?:\.\d*)?(?:[eE][+-]?\d+)?)?\b/
+            }, { // match stuff like: Sound.prototype.play = function() { }
+                token : [
+                    "storage.type",
+                    "punctuation.operator",
+                    "support.function",
+                    "punctuation.operator",
+                    "entity.name.function",
+                    "text",
+                    "keyword.operator",
+                    "text",
+                    "storage.type",
+                    "text",
+                    "paren.lparen",
+                    "variable.parameter",
+                    "paren.rparen"
+                ],
+                regex : "(" + identifierRe + ")(\\.)(prototype)(\\.)(" + identifierRe +")(\\s*)(=)(\\s*)(function)(\\s*)(\\()(.*?)(\\))"
+            }, { // match stuff like: Sound.prototype.play = myfunc
+                token : [
+                    "storage.type",
+                    "punctuation.operator",
+                    "support.function",
+                    "punctuation.operator",
+                    "entity.name.function",
+                    "text",
+                    "keyword.operator",
+                    "text"
+                ],
+                regex : "(" + identifierRe + ")(\\.)(prototype)(\\.)(" + identifierRe +")(\\s*)(=)(\\s*)"
+            }, { // match stuff like: Sound.play = function() {  }
+                token : [
+                    "storage.type",
+                    "punctuation.operator",
+                    "entity.name.function",
+                    "text",
+                    "keyword.operator",
+                    "text",
+                    "storage.type",
+                    "text",
+                    "paren.lparen",
+                    "variable.parameter",
+                    "paren.rparen"
+                ],
+                regex : "(" + identifierRe + ")(\\.)(" + identifierRe +")(\\s*)(=)(\\s*)(function)(\\s*)(\\()(.*?)(\\))"
+            }, { // match stuff like: play = function() {  }
+                token : [
+                    "entity.name.function",
+                    "text",
+                    "keyword.operator",
+                    "text",
+                    "storage.type",
+                    "text",
+                    "paren.lparen",
+                    "variable.parameter",
+                    "paren.rparen"
+                ],
+                regex : "(" + identifierRe +")(\\s*)(=)(\\s*)(function)(\\s*)(\\()(.*?)(\\))"
+            }, { // match regular function like: function myFunc(arg) { }
+                token : [
+                    "storage.type",
+                    "text",
+                    "entity.name.function",
+                    "text",
+                    "paren.lparen",
+                    "variable.parameter",
+                    "paren.rparen"
+                ],
+                regex : "(function)(\\s+)(" + identifierRe + ")(\\s*)(\\()(.*?)(\\))"
+            }, { // match stuff like: foobar: function() { }
+                token : [
+                    "entity.name.function",
+                    "text",
+                    "punctuation.operator",
+                    "text",
+                    "storage.type",
+                    "text",
+                    "paren.lparen",
+                    "variable.parameter",
+                    "paren.rparen"
+                ],
+                regex : "(" + identifierRe + ")(\\s*)(:)(\\s*)(function)(\\s*)(\\()(.*?)(\\))"
+            }, { // Attempt to match : function() { } (this is for issues with 'foo': function() { })
+                token : [
+                    "text",
+                    "text",
+                    "storage.type",
+                    "text",
+                    "paren.lparen",
+                    "variable.parameter",
+                    "paren.rparen"
+                ],
+                regex : "(:)(\\s*)(function)?(\\s*)(\\()([^)]*)(\\))"
             }, {
                 token : "constant.language.boolean",
-                regex : "(?:true|false)\\b"
+                regex : /(?:true|false)\b/
             }, {
                 token : "keyword",
                 regex : "(?:" + kwBeforeRe + ")\\b",
                 next : "regex_allowed"
+            }, {
+                token : ["punctuation.operator", "support.function"],
+                regex : /(\.)(s(?:h(?:ift|ow(?:Mod(?:elessDialog|alDialog)|Help))|croll(?:X|By(?:Pages|Lines)?|Y|To)?|t(?:opzzzz|rike)|i(?:n|zeToContent|debar|gnText)|ort|u(?:p|b(?:str(?:ing)?)?)|pli(?:ce|t)|e(?:nd|t(?:Re(?:sizable|questHeader)|M(?:i(?:nutes|lliseconds)|onth)|Seconds|Ho(?:tKeys|urs)|Year|Cursor|Time(?:out)?|Interval|ZOptions|Date|UTC(?:M(?:i(?:nutes|lliseconds)|onth)|Seconds|Hours|Date|FullYear)|FullYear|Active)|arch)|qrt|lice|avePreferences|mall)|h(?:ome|andleEvent)|navigate|c(?:har(?:CodeAt|At)|o(?:s|n(?:cat|textual|firm)|mpile)|eil|lear(?:Timeout|Interval)?|a(?:ptureEvents|ll)|reate(?:StyleSheet|Popup|EventObject))|t(?:o(?:GMTString|S(?:tring|ource)|U(?:TCString|pperCase)|Lo(?:caleString|werCase))|est|a(?:n|int(?:Enabled)?))|i(?:s(?:NaN|Finite)|ndexOf|talics)|d(?:isableExternalCapture|ump|etachEvent)|u(?:n(?:shift|taint|escape|watch)|pdateCommands)|j(?:oin|avaEnabled)|p(?:o(?:p|w)|ush|lugins.refresh|a(?:ddings|rse(?:Int|Float)?)|r(?:int|ompt|eference))|e(?:scape|nableExternalCapture|val|lementFromPoint|x(?:p|ec(?:Script|Command)?))|valueOf|UTC|queryCommand(?:State|Indeterm|Enabled|Value)|f(?:i(?:nd|le(?:ModifiedDate|Size|CreatedDate|UpdatedDate)|xed)|o(?:nt(?:size|color)|rward)|loor|romCharCode)|watch|l(?:ink|o(?:ad|g)|astIndexOf)|a(?:sin|nchor|cos|t(?:tachEvent|ob|an(?:2)?)|pply|lert|b(?:s|ort))|r(?:ou(?:nd|teEvents)|e(?:size(?:By|To)|calc|turnValue|place|verse|l(?:oad|ease(?:Capture|Events)))|andom)|g(?:o|et(?:ResponseHeader|M(?:i(?:nutes|lliseconds)|onth)|Se(?:conds|lection)|Hours|Year|Time(?:zoneOffset)?|Da(?:y|te)|UTC(?:M(?:i(?:nutes|lliseconds)|onth)|Seconds|Hours|Da(?:y|te)|FullYear)|FullYear|A(?:ttention|llResponseHeaders)))|m(?:in|ove(?:B(?:y|elow)|To(?:Absolute)?|Above)|ergeAttributes|a(?:tch|rgins|x))|b(?:toa|ig|o(?:ld|rderWidths)|link|ack))\b(?=\()/
+            }, {
+                token : ["punctuation.operator", "support.function.dom"],
+                regex : /(\.)(s(?:ub(?:stringData|mit)|plitText|e(?:t(?:NamedItem|Attribute(?:Node)?)|lect))|has(?:ChildNodes|Feature)|namedItem|c(?:l(?:ick|o(?:se|neNode))|reate(?:C(?:omment|DATASection|aption)|T(?:Head|extNode|Foot)|DocumentFragment|ProcessingInstruction|E(?:ntityReference|lement)|Attribute))|tabIndex|i(?:nsert(?:Row|Before|Cell|Data)|tem)|open|delete(?:Row|C(?:ell|aption)|T(?:Head|Foot)|Data)|focus|write(?:ln)?|a(?:dd|ppend(?:Child|Data))|re(?:set|place(?:Child|Data)|move(?:NamedItem|Child|Attribute(?:Node)?)?)|get(?:NamedItem|Element(?:sBy(?:Name|TagName)|ById)|Attribute(?:Node)?)|blur)\b(?=\()/
+            }, {
+                token : ["punctuation.operator", "support.constant"],
+                regex : /(\.)(s(?:ystemLanguage|cr(?:ipts|ollbars|een(?:X|Y|Top|Left))|t(?:yle(?:Sheets)?|atus(?:Text|bar)?)|ibling(?:Below|Above)|ource|uffixes|e(?:curity(?:Policy)?|l(?:ection|f)))|h(?:istory|ost(?:name)?|as(?:h|Focus))|y|X(?:MLDocument|SLDocument)|n(?:ext|ame(?:space(?:s|URI)|Prop))|M(?:IN_VALUE|AX_VALUE)|c(?:haracterSet|o(?:n(?:structor|trollers)|okieEnabled|lorDepth|mp(?:onents|lete))|urrent|puClass|l(?:i(?:p(?:boardData)?|entInformation)|osed|asses)|alle(?:e|r)|rypto)|t(?:o(?:olbar|p)|ext(?:Transform|Indent|Decoration|Align)|ags)|SQRT(?:1_2|2)|i(?:n(?:ner(?:Height|Width)|put)|ds|gnoreCase)|zIndex|o(?:scpu|n(?:readystatechange|Line)|uter(?:Height|Width)|p(?:sProfile|ener)|ffscreenBuffering)|NEGATIVE_INFINITY|d(?:i(?:splay|alog(?:Height|Top|Width|Left|Arguments)|rectories)|e(?:scription|fault(?:Status|Ch(?:ecked|arset)|View)))|u(?:ser(?:Profile|Language|Agent)|n(?:iqueID|defined)|pdateInterval)|_content|p(?:ixelDepth|ort|ersonalbar|kcs11|l(?:ugins|atform)|a(?:thname|dding(?:Right|Bottom|Top|Left)|rent(?:Window|Layer)?|ge(?:X(?:Offset)?|Y(?:Offset)?))|r(?:o(?:to(?:col|type)|duct(?:Sub)?|mpter)|e(?:vious|fix)))|e(?:n(?:coding|abledPlugin)|x(?:ternal|pando)|mbeds)|v(?:isibility|endor(?:Sub)?|Linkcolor)|URLUnencoded|P(?:I|OSITIVE_INFINITY)|f(?:ilename|o(?:nt(?:Size|Family|Weight)|rmName)|rame(?:s|Element)|gColor)|E|whiteSpace|l(?:i(?:stStyleType|n(?:eHeight|kColor))|o(?:ca(?:tion(?:bar)?|lName)|wsrc)|e(?:ngth|ft(?:Context)?)|a(?:st(?:M(?:odified|atch)|Index|Paren)|yer(?:s|X)|nguage))|a(?:pp(?:MinorVersion|Name|Co(?:deName|re)|Version)|vail(?:Height|Top|Width|Left)|ll|r(?:ity|guments)|Linkcolor|bove)|r(?:ight(?:Context)?|e(?:sponse(?:XML|Text)|adyState))|global|x|m(?:imeTypes|ultiline|enubar|argin(?:Right|Bottom|Top|Left))|L(?:N(?:10|2)|OG(?:10E|2E))|b(?:o(?:ttom|rder(?:Width|RightWidth|BottomWidth|Style|Color|TopWidth|LeftWidth))|ufferDepth|elow|ackground(?:Color|Image)))\b/
+            }, {
+                token : ["storage.type", "punctuation.operator", "support.function.firebug"],
+                regex : /(console)(\.)(warn|info|log|error|time|timeEnd|assert)\b/
             }, {
                 token : function(value) {
                     if (globals.hasOwnProperty(value))
@@ -1389,7 +1498,7 @@ var JavaScriptHighlightRules = function() {
                     else if (deprecated.hasOwnProperty(value))
                         return "invalid.deprecated";
                     else if (definitions.hasOwnProperty(value))
-                        return "keyword.definition";
+                        return "storage.type";
                     else if (keywords.hasOwnProperty(value))
                         return "keyword";
                     else if (buildinConstants.hasOwnProperty(value))
@@ -1404,29 +1513,29 @@ var JavaScriptHighlightRules = function() {
                 regex : identifierRe
             }, {
                 token : "keyword.operator",
-                regex : "!|\\$|%|&|\\*|\\-\\-|\\-|\\+\\+|\\+|~|===|==|=|!=|!==|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\\|\\||\\?\\:|\\*=|%=|\\+=|\\-=|&=|\\^=|\\b(?:in|instanceof|new|delete|typeof|void)",
+                regex : /!|\$|%|&|\*|\-\-|\-|\+\+|\+|~|===|==|=|!=|!==|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\|\||\?\:|\*=|%=|\+=|\-=|&=|\^=|\b(?:in|instanceof|new|delete|typeof|void)/,
                 next  : "regex_allowed"
             }, {
                 token : "punctuation.operator",
-                regex : "\\?|\\:|\\,|\\;|\\.",
+                regex : /\?|\:|\,|\;|\./,
                 next  : "regex_allowed"
             }, {
                 token : "paren.lparen",
-                regex : "[[({]",
+                regex : /[\[({]/,
                 next  : "regex_allowed"
             }, {
                 token : "paren.rparen",
-                regex : "[\\])}]"
+                regex : /[\])}]/
             }, {
                 token : "keyword.operator",
-                regex : "\\/=?",
+                regex : /\/=?/,
                 next  : "regex_allowed"
             }, {
                 token: "comment",
-                regex: "^#!.*$" 
+                regex: /^#!.*$/
             }, {
                 token : "text",
-                regex : "\\s+"
+                regex : /\s+/
             }
         ],
         // regular expressions are only allowed after certain tokens. This
@@ -1451,7 +1560,7 @@ var JavaScriptHighlightRules = function() {
             }, {
                 // immediately return to the start mode without matching
                 // anything
-                token: "empty", 
+                token: "empty",
                 regex: "",
                 next: "start"
             }
@@ -1463,10 +1572,10 @@ var JavaScriptHighlightRules = function() {
                 next: "regex"
             }, {
 				// flag
-                token: "string.regexp", 
+                token: "string.regexp",
                 regex: "/\\w*",
                 next: "start",
-                merge: true 
+                merge: true
             }, {
                 token: "string.regexp",
                 regex: "[^\\\\/\\[]+",
@@ -1478,9 +1587,9 @@ var JavaScriptHighlightRules = function() {
                 next: "regex_character_class",
                 merge: true
             }, {
-                token: "empty", 
+                token: "empty",
                 regex: "",
-                next: "start" 
+                next: "start"
             }
         ],
         "regex_character_class": [
@@ -1499,9 +1608,9 @@ var JavaScriptHighlightRules = function() {
                 next: "regex_character_class",
                 merge: true
             }, {
-                token: "empty", 
+                token: "empty",
                 regex: "",
-                next: "start" 
+                next: "start"
             }
         ],
         "comment_regex_allowed" : [
@@ -1530,28 +1639,32 @@ var JavaScriptHighlightRules = function() {
         ],
         "qqstring" : [
             {
+                token : "constant.language.escape",
+                regex : escapedRe
+            }, {
                 token : "string",
-                regex : '(?:(?:\\\\.)|(?:[^"\\\\]))*?"',
-                next : "start"
+                regex : '[^"\\\\]+'
             }, {
                 token : "string",
-                merge : true,
-                regex : '.+'
+                regex : '"',
+                next  : "start"
             }
         ],
         "qstring" : [
             {
+                token : "constant.language.escape",
+                regex : escapedRe
+            }, {
                 token : "string",
-                regex : "(?:(?:\\\\.)|(?:[^'\\\\]))*?'",
-                next : "start"
+                regex : "[^'\\\\]+"
             }, {
                 token : "string",
-                merge : true,
-                regex : '.+'
+                regex : "'",
+                next  : "start"
             }
         ]
     };
-    
+
     this.embedRules(DocCommentHighlightRules, "doc-",
         [ new DocCommentHighlightRules().getEndRule("start") ]);
 };
@@ -1736,195 +1849,6 @@ var MatchingBraceOutdent = function() {};
 }).call(MatchingBraceOutdent.prototype);
 
 exports.MatchingBraceOutdent = MatchingBraceOutdent;
-});
-/* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is Ajax.org Code Editor (ACE).
- *
- * The Initial Developer of the Original Code is
- * Ajax.org B.V.
- * Portions created by the Initial Developer are Copyright (C) 2010
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *      Fabian Jakobs <fabian AT ajax DOT org>
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-define('ace/worker/worker_client', ['require', 'exports', 'module' , 'ace/lib/oop', 'ace/lib/event_emitter'], function(require, exports, module) {
-"use strict";
-
-var oop = require("../lib/oop");
-var EventEmitter = require("../lib/event_emitter").EventEmitter;
-
-var WorkerClient = function(topLevelNamespaces, packagedJs, mod, classname) {
-
-    this.changeListener = this.changeListener.bind(this);
-
-    if (module.packaged) {
-        var base = this.$guessBasePath();
-        this.$worker = new Worker(base + packagedJs);
-    }
-    else {
-        var workerUrl = this.$normalizePath(require.nameToUrl("ace/worker/worker", null, "_"));
-        this.$worker = new Worker(workerUrl);
-
-        var tlns = {};
-        for (var i=0; i<topLevelNamespaces.length; i++) {
-            var ns = topLevelNamespaces[i];
-            var path = this.$normalizePath(require.nameToUrl(ns, null, "_").replace(/.js$/, ""));
-
-            tlns[ns] = path;
-        }
-    }
-
-    this.$worker.postMessage({
-        init : true,
-        tlns: tlns,
-        module: mod,
-        classname: classname
-    });
-
-    this.callbackId = 1;
-    this.callbacks = {};
-
-    var _self = this;
-    this.$worker.onerror = function(e) {
-        window.console && console.log && console.log(e);
-        throw e;
-    };
-    this.$worker.onmessage = function(e) {
-        var msg = e.data;
-        switch(msg.type) {
-            case "log":
-                window.console && console.log && console.log(msg.data);
-                break;
-
-            case "event":
-                _self._emit(msg.name, {data: msg.data});
-                break;
-
-            case "call":
-                var callback = _self.callbacks[msg.id];
-                if (callback) {
-                    callback(msg.data);
-                    delete _self.callbacks[msg.id];
-                }
-                break;
-        }
-    };
-};
-
-(function(){
-
-    oop.implement(this, EventEmitter);
-
-    this.$normalizePath = function(path) {
-        path = path.replace(/^[a-z]+:\/\/[^\/]+\//, ""); // Remove domain name and rebuild it
-        path = location.protocol + "//" + location.host
-            // paths starting with a slash are relative to the root (host)
-            + (path.charAt(0) == "/" ? "" : location.pathname.replace(/\/[^\/]*$/, ""))
-            + "/" + path.replace(/^[\/]+/, "");
-        return path;
-    };
-
-    this.$guessBasePath = function() {
-        if (require.aceBaseUrl)
-            return require.aceBaseUrl;
-
-        var scripts = document.getElementsByTagName("script");
-        for (var i=0; i<scripts.length; i++) {
-            var script = scripts[i];
-
-            var base = script.getAttribute("data-ace-base");
-            if (base)
-                return base.replace(/\/*$/, "/");
-
-            var src = script.src || script.getAttribute("src");
-            if (!src) {
-                continue;
-            }
-            var m = src.match(/^(?:(.*\/)ace\.js|(.*\/)ace(-uncompressed)?(-noconflict)?\.js)(?:\?|$)/);
-            if (m)
-                return m[1] || m[2];
-        }
-        return "";
-    };
-
-    this.terminate = function() {
-        this._emit("terminate", {});
-        this.$worker.terminate();
-        this.$worker = null;
-        this.$doc.removeEventListener("change", this.changeListener);
-        this.$doc = null;
-    };
-
-    this.send = function(cmd, args) {
-        this.$worker.postMessage({command: cmd, args: args});
-    };
-
-    this.call = function(cmd, args, callback) {
-        if (callback) {
-            var id = this.callbackId++;
-            this.callbacks[id] = callback;
-            args.push(id);
-        }
-        this.send(cmd, args);
-    };
-
-    this.emit = function(event, data) {
-        try {
-            // firefox refuses to clone objects which have function properties
-            // TODO: cleanup event
-            this.$worker.postMessage({event: event, data: {data: data.data}});
-        }
-        catch(ex) {}
-    };
-
-    this.attachToDocument = function(doc) {
-        if(this.$doc)
-            this.terminate();
-
-        this.$doc = doc;
-        this.call("setValue", [doc.getValue()]);
-        doc.on("change", this.changeListener);
-    };
-
-    this.changeListener = function(e) {
-        e.range = {
-            start: e.data.range.start,
-            end: e.data.range.end
-        };
-        this.emit("change", e);
-    };
-
-}).call(WorkerClient.prototype);
-
-exports.WorkerClient = WorkerClient;
-
 });
 /* ***** BEGIN LICENSE BLOCK *****
  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
@@ -2177,31 +2101,7 @@ var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
 var CssHighlightRules = function() {
 
     var properties = lang.arrayToMap(
-        ("-moz-appearance|-moz-box-sizing|-webkit-box-sizing|-moz-outline-radius|-moz-transform|-webkit-transform|" +
-        "appearance|azimuth|background-attachment|background-color|background-image|" +
-        "background-origin|background-position|background-repeat|background|border-bottom-color|" +
-        "border-bottom-style|border-bottom-width|border-bottom|border-collapse|" +
-        "border-color|border-left-color|border-left-style|border-left-width|" +
-        "border-left|border-right-color|border-right-style|border-right-width|" +
-        "border-right|border-spacing|border-style|border-top-color|" +
-        "border-top-style|border-top-width|border-top|border-width|border|" +
-        "bottom|box-sizing|caption-side|clear|clip|color|content|counter-increment|" +
-        "counter-reset|cue-after|cue-before|cue|cursor|direction|display|" +
-        "elevation|empty-cells|float|font-family|font-size-adjust|font-size|" +
-        "font-stretch|font-style|font-variant|font-weight|font|height|left|" +
-        "letter-spacing|line-height|list-style-image|list-style-position|" +
-        "list-style-type|list-style|margin-bottom|margin-left|margin-right|" +
-        "margin-top|marker-offset|margin|marks|max-height|max-width|min-height|" +
-        "min-width|-moz-border-radius|opacity|orphans|outline-color|outline-offset|outline-radius|" +
-        "outline-style|outline-width|outline|overflow|overflow-x|overflow-y|padding-bottom|" +
-        "padding-left|padding-right|padding-top|padding|page-break-after|" +
-        "page-break-before|page-break-inside|page|pause-after|pause-before|" +
-        "pause|pitch-range|pitch|play-during|pointer-events|position|quotes|resize|richness|right|" +
-        "size|speak-header|speak-numeral|speak-punctuation|speech-rate|speak|" +
-        "stress|table-layout|text-align|text-decoration|text-indent|" +
-        "text-shadow|text-transform|top|transform|unicode-bidi|vertical-align|" +
-        "visibility|voice-family|volume|white-space|widows|width|word-spacing|" +
-        "z-index").split("|")
+        ("animation-fill-mode|alignment-adjust|alignment-baseline|animation-delay|animation-direction|animation-duration|animation-iteration-count|animation-name|animation-play-state|animation-timing-function|animation|appearance|azimuth|backface-visibility|background-attachment|background-break|background-clip|background-color|background-image|background-origin|background-position|background-repeat|background-size|background|baseline-shift|binding|bleed|bookmark-label|bookmark-level|bookmark-state|bookmark-target|border-bottom|border-bottom-color|border-bottom-left-radius|border-bottom-right-radius|border-bottom-style|border-bottom-width|border-collapse|border-color|border-image|border-image-outset|border-image-repeat|border-image-slice|border-image-source|border-image-width|border-left|border-left-color|border-left-style|border-left-width|border-radius|border-right|border-right-color|border-right-style|border-right-width|border-spacing|border-style|border-top|border-top-color|border-top-left-radius|border-top-right-radius|border-top-style|border-top-width|border-width|border|bottom|box-align|box-decoration-break|box-direction|box-flex-group|box-flex|box-lines|box-ordinal-group|box-orient|box-pack|box-shadow|box-sizing|break-after|break-before|break-inside|caption-side|clear|clip|color-profile|color|column-count|column-fill|column-gap|column-rule|column-rule-color|column-rule-style|column-rule-width|column-span|column-width|columns|content|counter-increment|counter-reset|crop|cue-after|cue-before|cue|cursor|direction|display|dominant-baseline|drop-initial-after-adjust|drop-initial-after-align|drop-initial-before-adjust|drop-initial-before-align|drop-initial-size|drop-initial-value|elevation|empty-cells|fit|fit-position|float-offset|float|font-family|font-size|font-size-adjust|font-stretch|font-style|font-variant|font-weight|font|grid-columns|grid-rows|hanging-punctuation|height|hyphenate-after|hyphenate-before|hyphenate-character|hyphenate-lines|hyphenate-resource|hyphens|icon|image-orientation|image-rendering|image-resolution|inline-box-align|left|letter-spacing|line-height|line-stacking-ruby|line-stacking-shift|line-stacking-strategy|line-stacking|list-style-image|list-style-position|list-style-type|list-style|margin-bottom|margin-left|margin-right|margin-top|margin|mark-after|mark-before|mark|marks|marquee-direction|marquee-play-count|marquee-speed|marquee-style|max-height|max-width|min-height|min-width|move-to|nav-down|nav-index|nav-left|nav-right|nav-up|opacity|orphans|outline-color|outline-offset|outline-style|outline-width|outline|overflow-style|overflow-x|overflow-y|overflow|padding-bottom|padding-left|padding-right|padding-top|padding|page-break-after|page-break-before|page-break-inside|page-policy|page|pause-after|pause-before|pause|perspective-origin|perspective|phonemes|pitch-range|pitch|play-during|position|presentation-level|punctuation-trim|quotes|rendering-intent|resize|rest-after|rest-before|rest|richness|right|rotation-point|rotation|ruby-align|ruby-overhang|ruby-position|ruby-span|size|speak-header|speak-numeral|speak-punctuation|speak|speech-rate|stress|string-set|table-layout|target-name|target-new|target-position|target|text-align-last|text-align|text-decoration|text-emphasis|text-height|text-indent|text-justify|text-outline|text-shadow|text-transform|text-wrap|top|transform-origin|transform-style|transform|transition-delay|transition-duration|transition-property|transition-timing-function|transition|unicode-bidi|vertical-align|visibility|voice-balance|voice-duration|voice-family|voice-pitch-range|voice-pitch|voice-rate|voice-stress|voice-volume|volume|white-space-collapse|white-space|widows|width|word-break|word-spacing|word-wrap|z-index").split("|")
     );
 
     var functions = lang.arrayToMap(
@@ -2209,27 +2109,7 @@ var CssHighlightRules = function() {
     );
 
     var constants = lang.arrayToMap(
-        ("absolute|all-scroll|always|armenian|auto|baseline|below|bidi-override|" +
-        "block|bold|bolder|border-box|both|bottom|break-all|break-word|capitalize|center|" +
-        "char|circle|cjk-ideographic|col-resize|collapse|content-box|crosshair|dashed|" +
-        "decimal-leading-zero|decimal|default|disabled|disc|" +
-        "distribute-all-lines|distribute-letter|distribute-space|" +
-        "distribute|dotted|double|e-resize|ellipsis|fixed|georgian|groove|" +
-        "hand|hebrew|help|hidden|hiragana-iroha|hiragana|horizontal|" +
-        "ideograph-alpha|ideograph-numeric|ideograph-parenthesis|" +
-        "ideograph-space|inactive|inherit|inline-block|inline|inset|inside|" +
-        "inter-ideograph|inter-word|italic|justify|katakana-iroha|katakana|" +
-        "keep-all|left|lighter|line-edge|line-through|line|list-item|loose|" +
-        "lower-alpha|lower-greek|lower-latin|lower-roman|lowercase|lr-tb|ltr|" +
-        "medium|middle|move|n-resize|ne-resize|newspaper|no-drop|no-repeat|" +
-        "nw-resize|none|normal|not-allowed|nowrap|oblique|outset|outside|" +
-        "overline|pointer|progress|relative|repeat-x|repeat-y|repeat|right|" +
-        "ridge|row-resize|rtl|s-resize|scroll|se-resize|separate|small-caps|" +
-        "solid|square|static|strict|super|sw-resize|table-footer-group|" +
-        "table-header-group|tb-rl|text-bottom|text-top|text|thick|thin|top|" +
-        "transparent|underline|upper-alpha|upper-latin|upper-roman|uppercase|" +
-        "vertical-ideographic|vertical-text|visible|w-resize|wait|whitespace|" +
-        "zero").split("|")
+        ("absolute|after-edge|after|all-scroll|all|alphabetic|always|antialiased|armenian|auto|avoid-column|avoid-page|avoid|balance|baseline|before-edge|before|below|bidi-override|block-line-height|block|bold|bolder|border-box|both|bottom|box|break-all|break-word|capitalize|caps-height|caption|center|central|char|circle|cjk-ideographic|clone|close-quote|col-resize|collapse|column|consider-shifts|contain|content-box|cover|crosshair|cubic-bezier|dashed|decimal-leading-zero|decimal|default|disabled|disc|disregard-shifts|distribute-all-lines|distribute-letter|distribute-space|distribute|dotted|double|e-resize|ease-in|ease-in-out|ease-out|ease|ellipsis|end|exclude-ruby|fill|fixed|font-size|font|georgian|glyphs|grid-height|groove|hand|hanging|hebrew|help|hidden|hiragana-iroha|hiragana|horizontal|icon|ideograph-alpha|ideograph-numeric|ideograph-parenthesis|ideograph-space|ideographic|inactive|include-ruby|inherit|initial|inline-block|inline-box|inline-line-height|inline-table|inline|inset|inside|inter-ideograph|inter-word|invert|italic|justify|katakana-iroha|katakana|keep-all|last|left|lighter|line-edge|line-through|line|linear|list-item|local|loose|lower-alpha|lower-greek|lower-latin|lower-roman|lowercase|lr-tb|ltr|mathematical|max-height|max-size|medium|menu|message-box|middle|move|n-resize|ne-resize|newspaper|no-change|no-close-quote|no-drop|no-open-quote|no-repeat|none|normal|not-allowed|nowrap|nw-resize|oblique|open-quote|outset|outside|overline|padding-box|page|pointer|pre-line|pre-wrap|pre|preserve-3d|progress|relative|repeat-x|repeat-y|repeat|replaced|reset-size|ridge|right|round|row-resize|rtl|s-resize|scroll|se-resize|separate|slice|small-caps|small-caption|solid|space|square|start|static|status-bar|step-end|step-start|steps|stretch|strict|sub|super|sw-resize|table-caption|table-cell|table-column-group|table-column|table-footer-group|table-header-group|table-row-group|table-row|table|tb-rl|text-after-edge|text-before-edge|text-bottom|text-size|text-top|text|thick|thin|top|transparent|underline|upper-alpha|upper-latin|upper-roman|uppercase|use-script|vertical-ideographic|vertical-text|visible|w-resize|wait|whitespace|z-index|zero").split("|")
     );
 
     var colors = lang.arrayToMap(
@@ -2237,32 +2117,49 @@ var CssHighlightRules = function() {
         "purple|red|silver|teal|white|yellow").split("|")
     );
 
+    var fonts = lang.arrayToMap(
+        ("arial|century|comic|courier|garamond|georgia|helvetica|impact|lucida|" +
+        "symbol|system|tahoma|times|trebuchet|utopia|verdana|webdings|sans-serif|" +
+        "serif|monospace").split("|")
+    );
+    
     // regexp must not have capturing parentheses. Use (?:) instead.
     // regexps are ordered -> the first match is used
 
     var numRe = "\\-?(?:(?:[0-9]+)|(?:[0-9]*\\.[0-9]+))";
-
+    var pseudoElements = "(\\:+)\\b(after|before|first-letter|first-line|moz-selection|selection)\\b";
+    var pseudoClasses = "(:)\\b(active|checked|disabled|empty|enabled|first-child|first-of-type|focus|hover|indeterminate|invalid|last-child|last-of-type|link|not|nth-child|nth-last-child|nth-last-of-type|nth-of-type|only-child|only-of-type|required|root|target|valid|visited)\\b";
+    
     var base_ruleset = [
         {
             token : "comment", // multi line comment
             merge : true,
             regex : "\\/\\*",
             next : "ruleset_comment"
-        },{
+        }, {
             token : "string", // single line
             regex : '["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'
         }, {
             token : "string", // single line
             regex : "['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"
         }, {
-            token : "constant.numeric",
-            regex : numRe + "(?:em|ex|px|cm|mm|in|pt|pc|deg|rad|grad|ms|s|hz|khz|%)"
+            token : ["constant.numeric", "keyword"],
+            regex : "(" + numRe + ")(ch|cm|deg|em|ex|fr|gd|grad|Hz|in|kHz|mm|ms|pc|pt|px|rad|rem|s|turn|vh|vm|vw|%)"
+        }, {
+            token : ["constant.numeric"],
+            regex : "([0-9]+)"
         }, {
             token : "constant.numeric",  // hex6 color
             regex : "#[a-f0-9]{6}"
         }, {
             token : "constant.numeric", // hex3 color
             regex : "#[a-f0-9]{3}"
+        }, {
+            token : ["punctuation", "entity.other.attribute-name.pseudo-element.css"], 
+            regex : pseudoElements
+        }, {
+            token : ["punctuation", "entity.other.attribute-name.pseudo-class.css"], 
+            regex : pseudoClasses
         }, {
             token : function(value) {
                 if (properties.hasOwnProperty(value.toLowerCase())) {
@@ -2277,12 +2174,15 @@ var CssHighlightRules = function() {
                 else if (colors.hasOwnProperty(value.toLowerCase())) {
                     return "support.constant.color";
                 }
+                else if (fonts.hasOwnProperty(value.toLowerCase())) {
+                    return "support.constant.fonts";
+                }
                 else {
                     return "text";
                 }
             },
             regex : "\\-?[a-zA-Z_][a-zA-Z0-9_\\-]*"
-        }
+        } 
       ];
 
     var ruleset = lang.copyArray(base_ruleset);
@@ -2468,7 +2368,7 @@ var ColdfusionHighlightRules = function() {
         }, {
             token : "meta.tag",
             regex : "<(?=\s*style)",
-            next : "css"
+            next : "style"
         }, {
             token : "meta.tag", // opening tag
             regex : "<\\/?",
@@ -2507,7 +2407,7 @@ var ColdfusionHighlightRules = function() {
     };
     
     xml_util.tag(this.$rules, "tag", "start");
-    xml_util.tag(this.$rules, "css", "css-start");
+    xml_util.tag(this.$rules, "style", "css-start");
     xml_util.tag(this.$rules, "script", "js-start");
     
     this.embedRules(JavaScriptHighlightRules, "js-", [{
@@ -2531,13 +2431,3 @@ oop.inherits(ColdfusionHighlightRules, TextHighlightRules);
 
 exports.ColdfusionHighlightRules = ColdfusionHighlightRules;
 });
-;
-            (function() {
-                window.require(["ace/ace"], function(a) {
-                    if (!window.ace)
-                        window.ace = {};
-                    for (var key in a) if (a.hasOwnProperty(key))
-                        ace[key] = a[key];
-                });
-            })();
-        
\ No newline at end of file
diff --git a/apps/files_texteditor/js/aceeditor/mode-coldfusion.js b/apps/files_texteditor/js/aceeditor/mode-coldfusion.js
old mode 100755
new mode 100644
index fa8693e6d1db85b7b6ac65be7dc49a24e32413cf..7080a63534ca4639c311c3a38a831a1efd99bb2c
--- a/apps/files_texteditor/js/aceeditor/mode-coldfusion.js
+++ b/apps/files_texteditor/js/aceeditor/mode-coldfusion.js
@@ -1 +1 @@
-define("ace/mode/coldfusion",["require","exports","module","ace/lib/oop","ace/mode/xml","ace/mode/javascript","ace/mode/css","ace/tokenizer","ace/mode/coldfusion_highlight_rules"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("./xml").Mode,f=a("./javascript").Mode,g=a("./css").Mode,h=a("../tokenizer").Tokenizer,i=a("./coldfusion_highlight_rules").ColdfusionHighlightRules,j=function(){e.call(this);var a=new i;this.$tokenizer=new h(a.getRules()),this.$embeds=a.getEmbeds(),this.createModeDelegates({"js-":f,"css-":g})};d.inherits(j,e),function(){this.getNextLineIndent=function(a,b,c){return this.$getIndent(b)}}.call(j.prototype),b.Mode=j}),define("ace/mode/xml",["require","exports","module","ace/lib/oop","ace/mode/text","ace/tokenizer","ace/mode/xml_highlight_rules","ace/mode/behaviour/xml","ace/mode/folding/xml"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("./text").Mode,f=a("../tokenizer").Tokenizer,g=a("./xml_highlight_rules").XmlHighlightRules,h=a("./behaviour/xml").XmlBehaviour,i=a("./folding/xml").FoldMode,j=function(){this.$tokenizer=new f((new g).getRules()),this.$behaviour=new h,this.foldingRules=new i};d.inherits(j,e),function(){this.getNextLineIndent=function(a,b,c){return this.$getIndent(b)}}.call(j.prototype),b.Mode=j}),define("ace/mode/xml_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/xml_util","ace/mode/text_highlight_rules"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("./xml_util"),f=a("./text_highlight_rules").TextHighlightRules,g=function(){this.$rules={start:[{token:"text",regex:"<\\!\\[CDATA\\[",next:"cdata"},{token:"xml_pe",regex:"<\\?.*?\\?>"},{token:"comment",merge:!0,regex:"<\\!--",next:"comment"},{token:"meta.tag",regex:"<\\/?",next:"tag"},{token:"text",regex:"\\s+"},{token:"text",regex:"[^<]+"}],cdata:[{token:"text",regex:"\\]\\]>",next:"start"},{token:"text",regex:"\\s+"},{token:"text",regex:"(?:[^\\]]|\\](?!\\]>))+"}],comment:[{token:"comment",regex:".*?-->",next:"start"},{token:"comment",merge:!0,regex:".+"}]},e.tag(this.$rules,"tag","start")};d.inherits(g,f),b.XmlHighlightRules=g}),define("ace/mode/xml_util",["require","exports","module","ace/lib/lang"],function(a,b,c){function g(a){return[{token:"string",regex:'".*?"'},{token:"string",merge:!0,regex:'["].*',next:a+"-qqstring"},{token:"string",regex:"'.*?'"},{token:"string",merge:!0,regex:"['].*",next:a+"-qstring"}]}function h(a,b){return[{token:"string",merge:!0,regex:".*?"+a,next:b},{token:"string",merge:!0,regex:".+"}]}"use strict";var d=a("../lib/lang"),e=d.arrayToMap("button|form|input|label|select|textarea".split("|")),f=d.arrayToMap("table|tbody|td|tfoot|th|tr".split("|"));b.tag=function(a,b,c){a[b]=[{token:"text",regex:"\\s+"},{token:function(a){return a==="a"?"meta.tag.anchor":a==="img"?"meta.tag.image":a==="script"?"meta.tag.script":a==="style"?"meta.tag.style":e.hasOwnProperty(a.toLowerCase())?"meta.tag.form":f.hasOwnProperty(a.toLowerCase())?"meta.tag.table":"meta.tag"},merge:!0,regex:"[-_a-zA-Z0-9:!]+",next:b+"embed-attribute-list"},{token:"empty",regex:"",next:b+"embed-attribute-list"}],a[b+"-qstring"]=h("'",b+"embed-attribute-list"),a[b+"-qqstring"]=h('"',b+"embed-attribute-list"),a[b+"embed-attribute-list"]=[{token:"meta.tag",merge:!0,regex:"/?>",next:c},{token:"keyword.operator",regex:"="},{token:"entity.other.attribute-name",regex:"[-_a-zA-Z0-9:]+"},{token:"constant.numeric",regex:"[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"},{token:"text",regex:"\\s+"}].concat(g(b))}}),define("ace/mode/behaviour/xml",["require","exports","module","ace/lib/oop","ace/mode/behaviour","ace/mode/behaviour/cstyle"],function(a,b,c){"use strict";var d=a("../../lib/oop"),e=a("../behaviour").Behaviour,f=a("./cstyle").CstyleBehaviour,g=function(){this.inherit(f,["string_dquotes"]),this.add("brackets","insertion",function(a,b,c,d,e){if(e=="<"){var f=c.getSelectionRange(),g=d.doc.getTextRange(f);return g!==""?!1:{text:"<>",selection:[1,1]}}if(e==">"){var h=c.getCursorPosition(),i=d.doc.getLine(h.row),j=i.substring(h.column,h.column+1);if(j==">")return{text:"",selection:[1,1]}}else if(e=="\n"){var h=c.getCursorPosition(),i=d.doc.getLine(h.row),k=i.substring(h.column,h.column+2);if(k=="</"){var l=this.$getIndent(d.doc.getLine(h.row))+d.getTabString(),m=this.$getIndent(d.doc.getLine(h.row));return{text:"\n"+l+"\n"+m,selection:[1,l.length,1,l.length]}}}})};d.inherits(g,e),b.XmlBehaviour=g}),define("ace/mode/behaviour/cstyle",["require","exports","module","ace/lib/oop","ace/mode/behaviour"],function(a,b,c){"use strict";var d=a("../../lib/oop"),e=a("../behaviour").Behaviour,f=function(){this.add("braces","insertion",function(a,b,c,d,e){if(e=="{"){var f=c.getSelectionRange(),g=d.doc.getTextRange(f);return g!==""?{text:"{"+g+"}",selection:!1}:{text:"{}",selection:[1,1]}}if(e=="}"){var h=c.getCursorPosition(),i=d.doc.getLine(h.row),j=i.substring(h.column,h.column+1);if(j=="}"){var k=d.$findOpeningBracket("}",{column:h.column+1,row:h.row});if(k!==null)return{text:"",selection:[1,1]}}}else if(e=="\n"){var h=c.getCursorPosition(),i=d.doc.getLine(h.row),j=i.substring(h.column,h.column+1);if(j=="}"){var l=d.findMatchingBracket({row:h.row,column:h.column+1});if(!l)return null;var m=this.getNextLineIndent(a,i.substring(0,i.length-1),d.getTabString()),n=this.$getIndent(d.doc.getLine(l.row));return{text:"\n"+m+"\n"+n,selection:[1,m.length,1,m.length]}}}}),this.add("braces","deletion",function(a,b,c,d,e){var f=d.doc.getTextRange(e);if(!e.isMultiLine()&&f=="{"){var g=d.doc.getLine(e.start.row),h=g.substring(e.end.column,e.end.column+1);if(h=="}")return e.end.column++,e}}),this.add("parens","insertion",function(a,b,c,d,e){if(e=="("){var f=c.getSelectionRange(),g=d.doc.getTextRange(f);return g!==""?{text:"("+g+")",selection:!1}:{text:"()",selection:[1,1]}}if(e==")"){var h=c.getCursorPosition(),i=d.doc.getLine(h.row),j=i.substring(h.column,h.column+1);if(j==")"){var k=d.$findOpeningBracket(")",{column:h.column+1,row:h.row});if(k!==null)return{text:"",selection:[1,1]}}}}),this.add("parens","deletion",function(a,b,c,d,e){var f=d.doc.getTextRange(e);if(!e.isMultiLine()&&f=="("){var g=d.doc.getLine(e.start.row),h=g.substring(e.start.column+1,e.start.column+2);if(h==")")return e.end.column++,e}}),this.add("string_dquotes","insertion",function(a,b,c,d,e){if(e=='"'){var f=c.getSelectionRange(),g=d.doc.getTextRange(f);if(g!=="")return{text:'"'+g+'"',selection:!1};var h=c.getCursorPosition(),i=d.doc.getLine(h.row),j=i.substring(h.column-1,h.column);if(j=="\\")return null;var k=d.getTokens(f.start.row,f.start.row)[0].tokens,l=0,m,n=-1;for(var o=0;o<k.length;o++){m=k[o],m.type=="string"?n=-1:n<0&&(n=m.value.indexOf('"'));if(m.value.length+l>f.start.column)break;l+=k[o].value.length}if(!m||n<0&&m.type!=="comment"&&(m.type!=="string"||f.start.column!==m.value.length+l-1&&m.value.lastIndexOf('"')===m.value.length-1))return{text:'""',selection:[1,1]};if(m&&m.type==="string"){var p=i.substring(h.column,h.column+1);if(p=='"')return{text:"",selection:[1,1]}}}}),this.add("string_dquotes","deletion",function(a,b,c,d,e){var f=d.doc.getTextRange(e);if(!e.isMultiLine()&&f=='"'){var g=d.doc.getLine(e.start.row),h=g.substring(e.start.column+1,e.start.column+2);if(h=='"')return e.end.column++,e}})};d.inherits(f,e),b.CstyleBehaviour=f}),define("ace/mode/folding/xml",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/range","ace/mode/folding/fold_mode","ace/token_iterator"],function(a,b,c){"use strict";var d=a("../../lib/oop"),e=a("../../lib/lang"),f=a("../../range").Range,g=a("./fold_mode").FoldMode,h=a("../../token_iterator").TokenIterator,i=b.FoldMode=function(a){g.call(this),this.voidElements=a||{}};d.inherits(i,g),function(){this.getFoldWidget=function(a,b,c){var d=this._getFirstTagInLine(a,c);return d.closing?b=="markbeginend"?"end":"":!d.tagName||this.voidElements[d.tagName.toLowerCase()]?"":d.selfClosing?"":d.value.indexOf("/"+d.tagName)!==-1?"":"start"},this._getFirstTagInLine=function(a,b){var c=a.getTokens(b,b)[0].tokens,d="";for(var f=0;f<c.length;f++){var g=c[f];g.type.indexOf("meta.tag")===0?d+=g.value:d+=e.stringRepeat(" ",g.value.length)}return this._parseTag(d)},this.tagRe=/^(\s*)(<?(\/?)([-_a-zA-Z0-9:!]*)\s*(\/?)>?)/,this._parseTag=function(a){var b=this.tagRe.exec(a),c=this.tagRe.lastIndex||0;return this.tagRe.lastIndex=0,{value:a,match:b?b[2]:"",closing:b?!!b[3]:!1,selfClosing:b?!!b[5]||b[2]=="/>":!1,tagName:b?b[4]:"",column:b[1]?c+b[1].length:c}},this._readTagForward=function(a){var b=a.getCurrentToken();if(!b)return null;var c="",d;do if(b.type.indexOf("meta.tag")===0){if(!d)var d={row:a.getCurrentTokenRow(),column:a.getCurrentTokenColumn()};c+=b.value;if(c.indexOf(">")!==-1){var e=this._parseTag(c);return e.start=d,e.end={row:a.getCurrentTokenRow(),column:a.getCurrentTokenColumn()+b.value.length},a.stepForward(),e}}while(b=a.stepForward());return null},this._readTagBackward=function(a){var b=a.getCurrentToken();if(!b)return null;var c="",d;do if(b.type.indexOf("meta.tag")===0){d||(d={row:a.getCurrentTokenRow(),column:a.getCurrentTokenColumn()+b.value.length}),c=b.value+c;if(c.indexOf("<")!==-1){var e=this._parseTag(c);return e.end=d,e.start={row:a.getCurrentTokenRow(),column:a.getCurrentTokenColumn()},a.stepBackward(),e}}while(b=a.stepBackward());return null},this._pop=function(a,b){while(a.length){var c=a[a.length-1];if(!b||c.tagName==b.tagName)return a.pop();if(this.voidElements[b.tagName])return;if(this.voidElements[c.tagName]){a.pop();continue}return null}},this.getFoldWidgetRange=function(a,b,c){var d=this._getFirstTagInLine(a,c);if(!d.match)return null;var e=d.closing||d.selfClosing,g=[],i;if(!e){var j=new h(a,c,d.column),k={row:c,column:d.column+d.tagName.length+2};while(i=this._readTagForward(j)){if(i.selfClosing){if(!g.length)return i.start.column+=i.tagName.length+2,i.end.column-=2,f.fromPoints(i.start,i.end);continue}if(i.closing){this._pop(g,i);if(g.length==0)return f.fromPoints(k,i.start)}else g.push(i)}}else{var j=new h(a,c,d.column+d.match.length),l={row:c,column:d.column};while(i=this._readTagBackward(j)){if(i.selfClosing){if(!g.length)return i.start.column+=i.tagName.length+2,i.end.column-=2,f.fromPoints(i.start,i.end);continue}if(!i.closing){this._pop(g,i);if(g.length==0)return i.start.column+=i.tagName.length+2,f.fromPoints(i.start,l)}else g.push(i)}}}}.call(i.prototype)}),define("ace/mode/folding/fold_mode",["require","exports","module","ace/range"],function(a,b,c){"use strict";var d=a("../../range").Range,e=b.FoldMode=function(){};((function(){this.foldingStartMarker=null,this.foldingStopMarker=null,this.getFoldWidget=function(a,b,c){var d=a.getLine(c);return this.foldingStartMarker.test(d)?"start":b=="markbeginend"&&this.foldingStopMarker&&this.foldingStopMarker.test(d)?"end":""},this.getFoldWidgetRange=function(a,b,c){return null},this.indentationBlock=function(a,b,c){var e=/^\s*/,f=b,g=b,h=a.getLine(b),i=c||h.length,j=h.match(e)[0].length,k=a.getLength();while(++b<k){h=a.getLine(b);var l=h.match(e)[0].length;if(l==h.length)continue;if(l<=j)break;g=b}if(g>f){var m=a.getLine(g).length;return new d(f,i,g,m)}},this.openingBracketBlock=function(a,b,c,e){var f={row:c,column:e+1},g=a.$findClosingBracket(b,f);if(!g)return;var h=a.foldWidgets[g.row];return h==null&&(h=this.getFoldWidget(a,g.row)),h=="start"&&(g.row--,g.column=a.getLine(g.row).length),d.fromPoints(f,g)}})).call(e.prototype)}),define("ace/mode/javascript",["require","exports","module","ace/lib/oop","ace/mode/text","ace/tokenizer","ace/mode/javascript_highlight_rules","ace/mode/matching_brace_outdent","ace/range","ace/worker/worker_client","ace/mode/behaviour/cstyle","ace/mode/folding/cstyle"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("./text").Mode,f=a("../tokenizer").Tokenizer,g=a("./javascript_highlight_rules").JavaScriptHighlightRules,h=a("./matching_brace_outdent").MatchingBraceOutdent,i=a("../range").Range,j=a("../worker/worker_client").WorkerClient,k=a("./behaviour/cstyle").CstyleBehaviour,l=a("./folding/cstyle").FoldMode,m=function(){this.$tokenizer=new f((new g).getRules()),this.$outdent=new h,this.$behaviour=new k,this.foldingRules=new l};d.inherits(m,e),function(){this.toggleCommentLines=function(a,b,c,d){var e=!0,f=/^(\s*)\/\//;for(var g=c;g<=d;g++)if(!f.test(b.getLine(g))){e=!1;break}if(e){var h=new i(0,0,0,0);for(var g=c;g<=d;g++){var j=b.getLine(g),k=j.match(f);h.start.row=g,h.end.row=g,h.end.column=k[0].length,b.replace(h,k[1])}}else b.indentRows(c,d,"//")},this.getNextLineIndent=function(a,b,c){var d=this.$getIndent(b),e=this.$tokenizer.getLineTokens(b,a),f=e.tokens,g=e.state;if(f.length&&f[f.length-1].type=="comment")return d;if(a=="start"||a=="regex_allowed"){var h=b.match(/^.*(?:\bcase\b.*\:|[\{\(\[])\s*$/);h&&(d+=c)}else if(a=="doc-start"){if(g=="start"||a=="regex_allowed")return"";var h=b.match(/^\s*(\/?)\*/);h&&(h[1]&&(d+=" "),d+="* ")}return d},this.checkOutdent=function(a,b,c){return this.$outdent.checkOutdent(b,c)},this.autoOutdent=function(a,b,c){this.$outdent.autoOutdent(b,c)},this.createWorker=function(a){var b=new j(["ace"],"worker-javascript.js","ace/mode/javascript_worker","JavaScriptWorker");return b.attachToDocument(a.getDocument()),b.on("jslint",function(b){var c=[];for(var d=0;d<b.data.length;d++){var e=b.data[d];e&&c.push({row:e.line-1,column:e.character-1,text:e.reason,type:"warning",lint:e})}a.setAnnotations(c)}),b.on("narcissus",function(b){a.setAnnotations([b.data])}),b.on("terminate",function(){a.clearAnnotations()}),b}}.call(m.prototype),b.Mode=m}),define("ace/mode/javascript_highlight_rules",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/unicode","ace/mode/doc_comment_highlight_rules","ace/mode/text_highlight_rules"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("../lib/lang"),f=a("../unicode"),g=a("./doc_comment_highlight_rules").DocCommentHighlightRules,h=a("./text_highlight_rules").TextHighlightRules,i=function(){var a=e.arrayToMap("Array|Boolean|Date|Function|Iterator|Number|Object|RegExp|String|Proxy|Namespace|QName|XML|XMLList|ArrayBuffer|Float32Array|Float64Array|Int16Array|Int32Array|Int8Array|Uint16Array|Uint32Array|Uint8Array|Uint8ClampedArray|Error|EvalError|InternalError|RangeError|ReferenceError|StopIteration|SyntaxError|TypeError|URIError|decodeURI|decodeURIComponent|encodeURI|encodeURIComponent|eval|isFinite|isNaN|parseFloat|parseInt|JSON|Math|this|arguments|prototype|window|document".split("|")),b=e.arrayToMap("break|case|catch|continue|default|delete|do|else|finally|for|function|if|in|instanceof|new|return|switch|throw|try|typeof|let|var|while|with|const|yield|import|get|set".split("|")),c="case|do|else|finally|in|instanceof|return|throw|try|typeof|yield",d=e.arrayToMap("__parent__|__count__|escape|unescape|with|__proto__".split("|")),h=e.arrayToMap("const|let|var|function".split("|")),i=e.arrayToMap("null|Infinity|NaN|undefined".split("|")),j=e.arrayToMap("class|enum|extends|super|export|implements|private|public|interface|package|protected|static".split("|")),k="["+f.packages.L+"\\$_]["+f.packages.L+f.packages.Mn+f.packages.Mc+f.packages.Nd+f.packages.Pc+"\\$_]*\\b";this.$rules={start:[{token:"comment",regex:"\\/\\/.*$"},(new g).getStartRule("doc-start"),{token:"comment",merge:!0,regex:"\\/\\*",next:"comment"},{token:"string",regex:'["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'},{token:"string",merge:!0,regex:'["].*\\\\$',next:"qqstring"},{token:"string",regex:"['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"},{token:"string",merge:!0,regex:"['].*\\\\$",next:"qstring"},{token:"constant.numeric",regex:"0[xX][0-9a-fA-F]+\\b"},{token:"constant.numeric",regex:"[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"},{token:["keyword.definition","text","entity.name.function"],regex:"(function)(\\s+)("+k+")"},{token:"constant.language.boolean",regex:"(?:true|false)\\b"},{token:"keyword",regex:"(?:"+c+")\\b",next:"regex_allowed"},{token:function(c){return a.hasOwnProperty(c)?"variable.language":d.hasOwnProperty(c)?"invalid.deprecated":h.hasOwnProperty(c)?"keyword.definition":b.hasOwnProperty(c)?"keyword":i.hasOwnProperty(c)?"constant.language":j.hasOwnProperty(c)?"invalid.illegal":c=="debugger"?"invalid.deprecated":"identifier"},regex:k},{token:"keyword.operator",regex:"!|\\$|%|&|\\*|\\-\\-|\\-|\\+\\+|\\+|~|===|==|=|!=|!==|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\\|\\||\\?\\:|\\*=|%=|\\+=|\\-=|&=|\\^=|\\b(?:in|instanceof|new|delete|typeof|void)",next:"regex_allowed"},{token:"punctuation.operator",regex:"\\?|\\:|\\,|\\;|\\.",next:"regex_allowed"},{token:"paren.lparen",regex:"[[({]",next:"regex_allowed"},{token:"paren.rparen",regex:"[\\])}]"},{token:"keyword.operator",regex:"\\/=?",next:"regex_allowed"},{token:"comment",regex:"^#!.*$"},{token:"text",regex:"\\s+"}],regex_allowed:[{token:"comment",merge:!0,regex:"\\/\\*",next:"comment_regex_allowed"},{token:"comment",regex:"\\/\\/.*$"},{token:"string.regexp",regex:"\\/",next:"regex",merge:!0},{token:"text",regex:"\\s+"},{token:"empty",regex:"",next:"start"}],regex:[{token:"regexp.keyword.operator",regex:"\\\\(?:u[\\da-fA-F]{4}|x[\\da-fA-F]{2}|.)",next:"regex"},{token:"string.regexp",regex:"/\\w*",next:"start",merge:!0},{token:"string.regexp",regex:"[^\\\\/\\[]+",next:"regex",merge:!0},{token:"string.regexp.charachterclass",regex:"\\[",next:"regex_character_class",merge:!0},{token:"empty",regex:"",next:"start"}],regex_character_class:[{token:"regexp.keyword.operator",regex:"\\\\(?:u[\\da-fA-F]{4}|x[\\da-fA-F]{2}|.)",next:"regex_character_class"},{token:"string.regexp.charachterclass",regex:"]",next:"regex",merge:!0},{token:"string.regexp.charachterclass",regex:"[^\\\\\\]]+",next:"regex_character_class",merge:!0},{token:"empty",regex:"",next:"start"}],comment_regex_allowed:[{token:"comment",regex:".*?\\*\\/",merge:!0,next:"regex_allowed"},{token:"comment",merge:!0,regex:".+"}],comment:[{token:"comment",regex:".*?\\*\\/",merge:!0,next:"start"},{token:"comment",merge:!0,regex:".+"}],qqstring:[{token:"string",regex:'(?:(?:\\\\.)|(?:[^"\\\\]))*?"',next:"start"},{token:"string",merge:!0,regex:".+"}],qstring:[{token:"string",regex:"(?:(?:\\\\.)|(?:[^'\\\\]))*?'",next:"start"},{token:"string",merge:!0,regex:".+"}]},this.embedRules(g,"doc-",[(new g).getEndRule("start")])};d.inherits(i,h),b.JavaScriptHighlightRules=i}),define("ace/mode/doc_comment_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("./text_highlight_rules").TextHighlightRules,f=function(){this.$rules={start:[{token:"comment.doc.tag",regex:"@[\\w\\d_]+"},{token:"comment.doc",merge:!0,regex:"\\s+"},{token:"comment.doc",merge:!0,regex:"TODO"},{token:"comment.doc",merge:!0,regex:"[^@\\*]+"},{token:"comment.doc",merge:!0,regex:"."}]}};d.inherits(f,e),function(){this.getStartRule=function(a){return{token:"comment.doc",merge:!0,regex:"\\/\\*(?=\\*)",next:a}},this.getEndRule=function(a){return{token:"comment.doc",merge:!0,regex:"\\*\\/",next:a}}}.call(f.prototype),b.DocCommentHighlightRules=f}),define("ace/mode/matching_brace_outdent",["require","exports","module","ace/range"],function(a,b,c){"use strict";var d=a("../range").Range,e=function(){};((function(){this.checkOutdent=function(a,b){return/^\s+$/.test(a)?/^\s*\}/.test(b):!1},this.autoOutdent=function(a,b){var c=a.getLine(b),e=c.match(/^(\s*\})/);if(!e)return 0;var f=e[1].length,g=a.findMatchingBracket({row:b,column:f});if(!g||g.row==b)return 0;var h=this.$getIndent(a.getLine(g.row));a.replace(new d(b,0,b,f-1),h)},this.$getIndent=function(a){var b=a.match(/^(\s+)/);return b?b[1]:""}})).call(e.prototype),b.MatchingBraceOutdent=e}),define("ace/worker/worker_client",["require","exports","module","ace/lib/oop","ace/lib/event_emitter"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("../lib/event_emitter").EventEmitter,f=function(b,d,e,f){this.changeListener=this.changeListener.bind(this);if(c.packaged){var g=this.$guessBasePath();this.$worker=new Worker(g+d)}else{var h=this.$normalizePath(a.nameToUrl("ace/worker/worker",null,"_"));this.$worker=new Worker(h);var i={};for(var j=0;j<b.length;j++){var k=b[j],l=this.$normalizePath(a.nameToUrl(k,null,"_").replace(/.js$/,""));i[k]=l}}this.$worker.postMessage({init:!0,tlns:i,module:e,classname:f}),this.callbackId=1,this.callbacks={};var m=this;this.$worker.onerror=function(a){throw window.console&&console.log&&console.log(a),a},this.$worker.onmessage=function(a){var b=a.data;switch(b.type){case"log":window.console&&console.log&&console.log(b.data);break;case"event":m._emit(b.name,{data:b.data});break;case"call":var c=m.callbacks[b.id];c&&(c(b.data),delete m.callbacks[b.id])}}};((function(){d.implement(this,e),this.$normalizePath=function(a){return a=a.replace(/^[a-z]+:\/\/[^\/]+\//,""),a=location.protocol+"//"+location.host+(a.charAt(0)=="/"?"":location.pathname.replace(/\/[^\/]*$/,""))+"/"+a.replace(/^[\/]+/,""),a},this.$guessBasePath=function(){if(a.aceBaseUrl)return a.aceBaseUrl;var b=document.getElementsByTagName("script");for(var c=0;c<b.length;c++){var d=b[c],e=d.getAttribute("data-ace-base");if(e)return e.replace(/\/*$/,"/");var f=d.src||d.getAttribute("src");if(!f)continue;var g=f.match(/^(?:(.*\/)ace\.js|(.*\/)ace(-uncompressed)?(-noconflict)?\.js)(?:\?|$)/);if(g)return g[1]||g[2]}return""},this.terminate=function(){this._emit("terminate",{}),this.$worker.terminate(),this.$worker=null,this.$doc.removeEventListener("change",this.changeListener),this.$doc=null},this.send=function(a,b){this.$worker.postMessage({command:a,args:b})},this.call=function(a,b,c){if(c){var d=this.callbackId++;this.callbacks[d]=c,b.push(d)}this.send(a,b)},this.emit=function(a,b){try{this.$worker.postMessage({event:a,data:{data:b.data}})}catch(c){}},this.attachToDocument=function(a){this.$doc&&this.terminate(),this.$doc=a,this.call("setValue",[a.getValue()]),a.on("change",this.changeListener)},this.changeListener=function(a){a.range={start:a.data.range.start,end:a.data.range.end},this.emit("change",a)}})).call(f.prototype),b.WorkerClient=f}),define("ace/mode/folding/cstyle",["require","exports","module","ace/lib/oop","ace/range","ace/mode/folding/fold_mode"],function(a,b,c){"use strict";var d=a("../../lib/oop"),e=a("../../range").Range,f=a("./fold_mode").FoldMode,g=b.FoldMode=function(){};d.inherits(g,f),function(){this.foldingStartMarker=/(\{|\[)[^\}\]]*$|^\s*(\/\*)/,this.foldingStopMarker=/^[^\[\{]*(\}|\])|^[\s\*]*(\*\/)/,this.getFoldWidgetRange=function(a,b,c){var d=a.getLine(c),f=d.match(this.foldingStartMarker);if(f){var g=f.index;if(f[1])return this.openingBracketBlock(a,f[1],c,g);var h=a.getCommentFoldRange(c,g+f[0].length);return h.end.column-=2,h}if(b!=="markbeginend")return;var f=d.match(this.foldingStopMarker);if(f){var g=f.index+f[0].length;if(f[2]){var h=a.getCommentFoldRange(c,g);return h.end.column-=2,h}var i={row:c,column:g},j=a.$findOpeningBracket(f[1],i);if(!j)return;return j.column++,i.column--,e.fromPoints(j,i)}}}.call(g.prototype)}),define("ace/mode/css",["require","exports","module","ace/lib/oop","ace/mode/text","ace/tokenizer","ace/mode/css_highlight_rules","ace/mode/matching_brace_outdent","ace/worker/worker_client","ace/mode/folding/cstyle"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("./text").Mode,f=a("../tokenizer").Tokenizer,g=a("./css_highlight_rules").CssHighlightRules,h=a("./matching_brace_outdent").MatchingBraceOutdent,i=a("../worker/worker_client").WorkerClient,j=a("./folding/cstyle").FoldMode,k=function(){this.$tokenizer=new f((new g).getRules(),"i"),this.$outdent=new h,this.foldingRules=new j};d.inherits(k,e),function(){this.foldingRules="cStyle",this.getNextLineIndent=function(a,b,c){var d=this.$getIndent(b),e=this.$tokenizer.getLineTokens(b,a).tokens;if(e.length&&e[e.length-1].type=="comment")return d;var f=b.match(/^.*\{\s*$/);return f&&(d+=c),d},this.checkOutdent=function(a,b,c){return this.$outdent.checkOutdent(b,c)},this.autoOutdent=function(a,b,c){this.$outdent.autoOutdent(b,c)},this.createWorker=function(a){var b=new i(["ace"],"worker-css.js","ace/mode/css_worker","Worker");return b.attachToDocument(a.getDocument()),b.on("csslint",function(b){var c=[];b.data.forEach(function(a){c.push({row:a.line-1,column:a.col-1,text:a.message,type:a.type,lint:a})}),a.setAnnotations(c)}),b}}.call(k.prototype),b.Mode=k}),define("ace/mode/css_highlight_rules",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/mode/text_highlight_rules"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("../lib/lang"),f=a("./text_highlight_rules").TextHighlightRules,g=function(){var a=e.arrayToMap("-moz-appearance|-moz-box-sizing|-webkit-box-sizing|-moz-outline-radius|-moz-transform|-webkit-transform|appearance|azimuth|background-attachment|background-color|background-image|background-origin|background-position|background-repeat|background|border-bottom-color|border-bottom-style|border-bottom-width|border-bottom|border-collapse|border-color|border-left-color|border-left-style|border-left-width|border-left|border-right-color|border-right-style|border-right-width|border-right|border-spacing|border-style|border-top-color|border-top-style|border-top-width|border-top|border-width|border|bottom|box-sizing|caption-side|clear|clip|color|content|counter-increment|counter-reset|cue-after|cue-before|cue|cursor|direction|display|elevation|empty-cells|float|font-family|font-size-adjust|font-size|font-stretch|font-style|font-variant|font-weight|font|height|left|letter-spacing|line-height|list-style-image|list-style-position|list-style-type|list-style|margin-bottom|margin-left|margin-right|margin-top|marker-offset|margin|marks|max-height|max-width|min-height|min-width|-moz-border-radius|opacity|orphans|outline-color|outline-offset|outline-radius|outline-style|outline-width|outline|overflow|overflow-x|overflow-y|padding-bottom|padding-left|padding-right|padding-top|padding|page-break-after|page-break-before|page-break-inside|page|pause-after|pause-before|pause|pitch-range|pitch|play-during|pointer-events|position|quotes|resize|richness|right|size|speak-header|speak-numeral|speak-punctuation|speech-rate|speak|stress|table-layout|text-align|text-decoration|text-indent|text-shadow|text-transform|top|transform|unicode-bidi|vertical-align|visibility|voice-family|volume|white-space|widows|width|word-spacing|z-index".split("|")),b=e.arrayToMap("rgb|rgba|url|attr|counter|counters".split("|")),c=e.arrayToMap("absolute|all-scroll|always|armenian|auto|baseline|below|bidi-override|block|bold|bolder|border-box|both|bottom|break-all|break-word|capitalize|center|char|circle|cjk-ideographic|col-resize|collapse|content-box|crosshair|dashed|decimal-leading-zero|decimal|default|disabled|disc|distribute-all-lines|distribute-letter|distribute-space|distribute|dotted|double|e-resize|ellipsis|fixed|georgian|groove|hand|hebrew|help|hidden|hiragana-iroha|hiragana|horizontal|ideograph-alpha|ideograph-numeric|ideograph-parenthesis|ideograph-space|inactive|inherit|inline-block|inline|inset|inside|inter-ideograph|inter-word|italic|justify|katakana-iroha|katakana|keep-all|left|lighter|line-edge|line-through|line|list-item|loose|lower-alpha|lower-greek|lower-latin|lower-roman|lowercase|lr-tb|ltr|medium|middle|move|n-resize|ne-resize|newspaper|no-drop|no-repeat|nw-resize|none|normal|not-allowed|nowrap|oblique|outset|outside|overline|pointer|progress|relative|repeat-x|repeat-y|repeat|right|ridge|row-resize|rtl|s-resize|scroll|se-resize|separate|small-caps|solid|square|static|strict|super|sw-resize|table-footer-group|table-header-group|tb-rl|text-bottom|text-top|text|thick|thin|top|transparent|underline|upper-alpha|upper-latin|upper-roman|uppercase|vertical-ideographic|vertical-text|visible|w-resize|wait|whitespace|zero".split("|")),d=e.arrayToMap("aqua|black|blue|fuchsia|gray|green|lime|maroon|navy|olive|orange|purple|red|silver|teal|white|yellow".split("|")),f="\\-?(?:(?:[0-9]+)|(?:[0-9]*\\.[0-9]+))",g=[{token:"comment",merge:!0,regex:"\\/\\*",next:"ruleset_comment"},{token:"string",regex:'["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'},{token:"string",regex:"['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"},{token:"constant.numeric",regex:f+"(?:em|ex|px|cm|mm|in|pt|pc|deg|rad|grad|ms|s|hz|khz|%)"},{token:"constant.numeric",regex:"#[a-f0-9]{6}"},{token:"constant.numeric",regex:"#[a-f0-9]{3}"},{token:function(e){return a.hasOwnProperty(e.toLowerCase())?"support.type":b.hasOwnProperty(e.toLowerCase())?"support.function":c.hasOwnProperty(e.toLowerCase())?"support.constant":d.hasOwnProperty(e.toLowerCase())?"support.constant.color":"text"},regex:"\\-?[a-zA-Z_][a-zA-Z0-9_\\-]*"}],h=e.copyArray(g);h.unshift({token:"paren.rparen",regex:"\\}",next:"start"});var i=e.copyArray(g);i.unshift({token:"paren.rparen",regex:"\\}",next:"media"});var j=[{token:"comment",merge:!0,regex:".+"}],k=e.copyArray(j);k.unshift({token:"comment",regex:".*?\\*\\/",next:"start"});var l=e.copyArray(j);l.unshift({token:"comment",regex:".*?\\*\\/",next:"media"});var m=e.copyArray(j);m.unshift({token:"comment",regex:".*?\\*\\/",next:"ruleset"}),this.$rules={start:[{token:"comment",merge:!0,regex:"\\/\\*",next:"comment"},{token:"paren.lparen",regex:"\\{",next:"ruleset"},{token:"string",regex:"@.*?{",next:"media"},{token:"keyword",regex:"#[a-z0-9-_]+"},{token:"variable",regex:"\\.[a-z0-9-_]+"},{token:"string",regex:":[a-z0-9-_]+"},{token:"constant",regex:"[a-z0-9-_]+"}],media:[{token:"comment",merge:!0,regex:"\\/\\*",next:"media_comment"},{token:"paren.lparen",regex:"\\{",next:"media_ruleset"},{token:"string",regex:"\\}",next:"start"},{token:"keyword",regex:"#[a-z0-9-_]+"},{token:"variable",regex:"\\.[a-z0-9-_]+"},{token:"string",regex:":[a-z0-9-_]+"},{token:"constant",regex:"[a-z0-9-_]+"}],comment:k,ruleset:h,ruleset_comment:m,media_ruleset:i,media_comment:l}};d.inherits(g,f),b.CssHighlightRules=g}),define("ace/mode/coldfusion_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/css_highlight_rules","ace/mode/javascript_highlight_rules","ace/mode/text_highlight_rules","ace/mode/xml_util"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("./css_highlight_rules").CssHighlightRules,f=a("./javascript_highlight_rules").JavaScriptHighlightRules,g=a("./text_highlight_rules").TextHighlightRules,h=a("./xml_util"),i=function(){this.$rules={start:[{token:"text",merge:!0,regex:"<\\!\\[CDATA\\[",next:"cdata"},{token:"xml_pe",regex:"<\\?.*?\\?>"},{token:"comment",merge:!0,regex:"<\\!--",next:"comment"},{token:"meta.tag",regex:"<(?=s*script)",next:"script"},{token:"meta.tag",regex:"<(?=s*style)",next:"css"},{token:"meta.tag",regex:"<\\/?",next:"tag"},{token:"text",regex:"\\s+"},{token:"text",regex:"[^<]+"}],cdata:[{token:"text",regex:"\\]\\]>",next:"start"},{token:"text",merge:!0,regex:"\\s+"},{token:"text",merge:!0,regex:".+"}],comment:[{token:"comment",regex:".*?-->",next:"start"},{token:"comment",merge:!0,regex:".+"}]},h.tag(this.$rules,"tag","start"),h.tag(this.$rules,"css","css-start"),h.tag(this.$rules,"script","js-start"),this.embedRules(f,"js-",[{token:"comment",regex:"\\/\\/.*(?=<\\/script>)",next:"tag"},{token:"meta.tag",regex:"<\\/(?=script)",next:"tag"}]),this.embedRules(e,"css-",[{token:"meta.tag",regex:"<\\/(?=style)",next:"tag"}])};d.inherits(i,g),b.ColdfusionHighlightRules=i}),function(){window.require(["ace/ace"],function(a){window.ace||(window.ace={});for(var b in a)a.hasOwnProperty(b)&&(ace[b]=a[b])})}()
\ No newline at end of file
+define("ace/mode/coldfusion",["require","exports","module","ace/lib/oop","ace/mode/xml","ace/mode/javascript","ace/mode/css","ace/tokenizer","ace/mode/coldfusion_highlight_rules"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("./xml").Mode,f=a("./javascript").Mode,g=a("./css").Mode,h=a("../tokenizer").Tokenizer,i=a("./coldfusion_highlight_rules").ColdfusionHighlightRules,j=function(){e.call(this);var a=new i;this.$tokenizer=new h(a.getRules()),this.$embeds=a.getEmbeds(),this.createModeDelegates({"js-":f,"css-":g})};d.inherits(j,e),function(){this.getNextLineIndent=function(a,b,c){return this.$getIndent(b)}}.call(j.prototype),b.Mode=j}),define("ace/mode/xml",["require","exports","module","ace/lib/oop","ace/mode/text","ace/tokenizer","ace/mode/xml_highlight_rules","ace/mode/behaviour/xml","ace/mode/folding/xml"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("./text").Mode,f=a("../tokenizer").Tokenizer,g=a("./xml_highlight_rules").XmlHighlightRules,h=a("./behaviour/xml").XmlBehaviour,i=a("./folding/xml").FoldMode,j=function(){this.$tokenizer=new f((new g).getRules()),this.$behaviour=new h,this.foldingRules=new i};d.inherits(j,e),function(){this.getNextLineIndent=function(a,b,c){return this.$getIndent(b)}}.call(j.prototype),b.Mode=j}),define("ace/mode/xml_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/xml_util","ace/mode/text_highlight_rules"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("./xml_util"),f=a("./text_highlight_rules").TextHighlightRules,g=function(){this.$rules={start:[{token:"text",regex:"<\\!\\[CDATA\\[",next:"cdata"},{token:"xml_pe",regex:"<\\?.*?\\?>"},{token:"comment",merge:!0,regex:"<\\!--",next:"comment"},{token:"xml_pe",regex:"<\\!.*?>"},{token:"meta.tag",regex:"<\\/?",next:"tag"},{token:"text",regex:"\\s+"},{token:"constant.character.entity",regex:"(?:&#[0-9]+;)|(?:&#x[0-9a-fA-F]+;)|(?:&[a-zA-Z0-9_:\\.-]+;)"},{token:"text",regex:"[^<]+"}],cdata:[{token:"text",regex:"\\]\\]>",next:"start"},{token:"text",regex:"\\s+"},{token:"text",regex:"(?:[^\\]]|\\](?!\\]>))+"}],comment:[{token:"comment",regex:".*?-->",next:"start"},{token:"comment",merge:!0,regex:".+"}]},e.tag(this.$rules,"tag","start")};d.inherits(g,f),b.XmlHighlightRules=g}),define("ace/mode/xml_util",["require","exports","module","ace/lib/lang"],function(a,b,c){function g(a){return[{token:"string",regex:'".*?"'},{token:"string",merge:!0,regex:'["].*',next:a+"_qqstring"},{token:"string",regex:"'.*?'"},{token:"string",merge:!0,regex:"['].*",next:a+"_qstring"}]}function h(a,b){return[{token:"string",merge:!0,regex:".*?"+a,next:b},{token:"string",merge:!0,regex:".+"}]}"use strict";var d=a("../lib/lang"),e=d.arrayToMap("button|form|input|label|select|textarea".split("|")),f=d.arrayToMap("table|tbody|td|tfoot|th|tr".split("|"));b.tag=function(a,b,c){a[b]=[{token:"text",regex:"\\s+"},{token:function(a){return a==="a"?"meta.tag.anchor":a==="img"?"meta.tag.image":a==="script"?"meta.tag.script":a==="style"?"meta.tag.style":e.hasOwnProperty(a.toLowerCase())?"meta.tag.form":f.hasOwnProperty(a.toLowerCase())?"meta.tag.table":"meta.tag"},merge:!0,regex:"[-_a-zA-Z0-9:]+",next:b+"_embed_attribute_list"},{token:"empty",regex:"",next:b+"_embed_attribute_list"}],a[b+"_qstring"]=h("'",b+"_embed_attribute_list"),a[b+"_qqstring"]=h('"',b+"_embed_attribute_list"),a[b+"_embed_attribute_list"]=[{token:"meta.tag",merge:!0,regex:"/?>",next:c},{token:"keyword.operator",regex:"="},{token:"entity.other.attribute-name",regex:"[-_a-zA-Z0-9:]+"},{token:"constant.numeric",regex:"[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"},{token:"text",regex:"\\s+"}].concat(g(b))}}),define("ace/mode/behaviour/xml",["require","exports","module","ace/lib/oop","ace/mode/behaviour","ace/mode/behaviour/cstyle"],function(a,b,c){"use strict";var d=a("../../lib/oop"),e=a("../behaviour").Behaviour,f=a("./cstyle").CstyleBehaviour,g=function(){this.inherit(f,["string_dquotes"]),this.add("brackets","insertion",function(a,b,c,d,e){if(e=="<"){var f=c.getSelectionRange(),g=d.doc.getTextRange(f);return g!==""?!1:{text:"<>",selection:[1,1]}}if(e==">"){var h=c.getCursorPosition(),i=d.doc.getLine(h.row),j=i.substring(h.column,h.column+1);if(j==">")return{text:"",selection:[1,1]}}else if(e=="\n"){var h=c.getCursorPosition(),i=d.doc.getLine(h.row),k=i.substring(h.column,h.column+2);if(k=="</"){var l=this.$getIndent(d.doc.getLine(h.row))+d.getTabString(),m=this.$getIndent(d.doc.getLine(h.row));return{text:"\n"+l+"\n"+m,selection:[1,l.length,1,l.length]}}}})};d.inherits(g,e),b.XmlBehaviour=g}),define("ace/mode/behaviour/cstyle",["require","exports","module","ace/lib/oop","ace/mode/behaviour"],function(a,b,c){"use strict";var d=a("../../lib/oop"),e=a("../behaviour").Behaviour,f=function(){this.add("braces","insertion",function(a,b,c,d,e){if(e=="{"){var f=c.getSelectionRange(),g=d.doc.getTextRange(f);return g!==""?{text:"{"+g+"}",selection:!1}:{text:"{}",selection:[1,1]}}if(e=="}"){var h=c.getCursorPosition(),i=d.doc.getLine(h.row),j=i.substring(h.column,h.column+1);if(j=="}"){var k=d.$findOpeningBracket("}",{column:h.column+1,row:h.row});if(k!==null)return{text:"",selection:[1,1]}}}else if(e=="\n"){var h=c.getCursorPosition(),i=d.doc.getLine(h.row),j=i.substring(h.column,h.column+1);if(j=="}"){var l=d.findMatchingBracket({row:h.row,column:h.column+1});if(!l)return null;var m=this.getNextLineIndent(a,i.substring(0,i.length-1),d.getTabString()),n=this.$getIndent(d.doc.getLine(l.row));return{text:"\n"+m+"\n"+n,selection:[1,m.length,1,m.length]}}}}),this.add("braces","deletion",function(a,b,c,d,e){var f=d.doc.getTextRange(e);if(!e.isMultiLine()&&f=="{"){var g=d.doc.getLine(e.start.row),h=g.substring(e.end.column,e.end.column+1);if(h=="}")return e.end.column++,e}}),this.add("parens","insertion",function(a,b,c,d,e){if(e=="("){var f=c.getSelectionRange(),g=d.doc.getTextRange(f);return g!==""?{text:"("+g+")",selection:!1}:{text:"()",selection:[1,1]}}if(e==")"){var h=c.getCursorPosition(),i=d.doc.getLine(h.row),j=i.substring(h.column,h.column+1);if(j==")"){var k=d.$findOpeningBracket(")",{column:h.column+1,row:h.row});if(k!==null)return{text:"",selection:[1,1]}}}}),this.add("parens","deletion",function(a,b,c,d,e){var f=d.doc.getTextRange(e);if(!e.isMultiLine()&&f=="("){var g=d.doc.getLine(e.start.row),h=g.substring(e.start.column+1,e.start.column+2);if(h==")")return e.end.column++,e}}),this.add("string_dquotes","insertion",function(a,b,c,d,e){if(e=='"'||e=="'"){var f=e,g=c.getSelectionRange(),h=d.doc.getTextRange(g);if(h!=="")return{text:f+h+f,selection:!1};var i=c.getCursorPosition(),j=d.doc.getLine(i.row),k=j.substring(i.column-1,i.column);if(k=="\\")return null;var l=d.getTokens(g.start.row,g.start.row)[0].tokens,m=0,n,o=-1;for(var p=0;p<l.length;p++){n=l[p],n.type=="string"?o=-1:o<0&&(o=n.value.indexOf(f));if(n.value.length+m>g.start.column)break;m+=l[p].value.length}if(!n||o<0&&n.type!=="comment"&&(n.type!=="string"||g.start.column!==n.value.length+m-1&&n.value.lastIndexOf(f)===n.value.length-1))return{text:f+f,selection:[1,1]};if(n&&n.type==="string"){var q=j.substring(i.column,i.column+1);if(q==f)return{text:"",selection:[1,1]}}}}),this.add("string_dquotes","deletion",function(a,b,c,d,e){var f=d.doc.getTextRange(e);if(!e.isMultiLine()&&(f=='"'||f=="'")){var g=d.doc.getLine(e.start.row),h=g.substring(e.start.column+1,e.start.column+2);if(h=='"')return e.end.column++,e}})};d.inherits(f,e),b.CstyleBehaviour=f}),define("ace/mode/folding/xml",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/range","ace/mode/folding/fold_mode","ace/token_iterator"],function(a,b,c){"use strict";var d=a("../../lib/oop"),e=a("../../lib/lang"),f=a("../../range").Range,g=a("./fold_mode").FoldMode,h=a("../../token_iterator").TokenIterator,i=b.FoldMode=function(a){g.call(this),this.voidElements=a||{}};d.inherits(i,g),function(){this.getFoldWidget=function(a,b,c){var d=this._getFirstTagInLine(a,c);return d.closing?b=="markbeginend"?"end":"":!d.tagName||this.voidElements[d.tagName.toLowerCase()]?"":d.selfClosing?"":d.value.indexOf("/"+d.tagName)!==-1?"":"start"},this._getFirstTagInLine=function(a,b){var c=a.getTokens(b,b)[0].tokens,d="";for(var f=0;f<c.length;f++){var g=c[f];g.type.indexOf("meta.tag")===0?d+=g.value:d+=e.stringRepeat(" ",g.value.length)}return this._parseTag(d)},this.tagRe=/^(\s*)(<?(\/?)([-_a-zA-Z0-9:!]*)\s*(\/?)>?)/,this._parseTag=function(a){var b=this.tagRe.exec(a),c=this.tagRe.lastIndex||0;return this.tagRe.lastIndex=0,{value:a,match:b?b[2]:"",closing:b?!!b[3]:!1,selfClosing:b?!!b[5]||b[2]=="/>":!1,tagName:b?b[4]:"",column:b[1]?c+b[1].length:c}},this._readTagForward=function(a){var b=a.getCurrentToken();if(!b)return null;var c="",d;do if(b.type.indexOf("meta.tag")===0){if(!d)var d={row:a.getCurrentTokenRow(),column:a.getCurrentTokenColumn()};c+=b.value;if(c.indexOf(">")!==-1){var e=this._parseTag(c);return e.start=d,e.end={row:a.getCurrentTokenRow(),column:a.getCurrentTokenColumn()+b.value.length},a.stepForward(),e}}while(b=a.stepForward());return null},this._readTagBackward=function(a){var b=a.getCurrentToken();if(!b)return null;var c="",d;do if(b.type.indexOf("meta.tag")===0){d||(d={row:a.getCurrentTokenRow(),column:a.getCurrentTokenColumn()+b.value.length}),c=b.value+c;if(c.indexOf("<")!==-1){var e=this._parseTag(c);return e.end=d,e.start={row:a.getCurrentTokenRow(),column:a.getCurrentTokenColumn()},a.stepBackward(),e}}while(b=a.stepBackward());return null},this._pop=function(a,b){while(a.length){var c=a[a.length-1];if(!b||c.tagName==b.tagName)return a.pop();if(this.voidElements[b.tagName])return;if(this.voidElements[c.tagName]){a.pop();continue}return null}},this.getFoldWidgetRange=function(a,b,c){var d=this._getFirstTagInLine(a,c);if(!d.match)return null;var e=d.closing||d.selfClosing,g=[],i;if(!e){var j=new h(a,c,d.column),k={row:c,column:d.column+d.tagName.length+2};while(i=this._readTagForward(j)){if(i.selfClosing){if(!g.length)return i.start.column+=i.tagName.length+2,i.end.column-=2,f.fromPoints(i.start,i.end);continue}if(i.closing){this._pop(g,i);if(g.length==0)return f.fromPoints(k,i.start)}else g.push(i)}}else{var j=new h(a,c,d.column+d.match.length),l={row:c,column:d.column};while(i=this._readTagBackward(j)){if(i.selfClosing){if(!g.length)return i.start.column+=i.tagName.length+2,i.end.column-=2,f.fromPoints(i.start,i.end);continue}if(!i.closing){this._pop(g,i);if(g.length==0)return i.start.column+=i.tagName.length+2,f.fromPoints(i.start,l)}else g.push(i)}}}}.call(i.prototype)}),define("ace/mode/folding/fold_mode",["require","exports","module","ace/range"],function(a,b,c){"use strict";var d=a("../../range").Range,e=b.FoldMode=function(){};(function(){this.foldingStartMarker=null,this.foldingStopMarker=null,this.getFoldWidget=function(a,b,c){var d=a.getLine(c);return this.foldingStartMarker.test(d)?"start":b=="markbeginend"&&this.foldingStopMarker&&this.foldingStopMarker.test(d)?"end":""},this.getFoldWidgetRange=function(a,b,c){return null},this.indentationBlock=function(a,b,c){var e=/^\s*/,f=b,g=b,h=a.getLine(b),i=c||h.length,j=h.match(e)[0].length,k=a.getLength();while(++b<k){h=a.getLine(b);var l=h.match(e)[0].length;if(l==h.length)continue;if(l<=j)break;g=b}if(g>f){var m=a.getLine(g).length;return new d(f,i,g,m)}},this.openingBracketBlock=function(a,b,c,e){var f={row:c,column:e+1},g=a.$findClosingBracket(b,f);if(!g)return;var h=a.foldWidgets[g.row];return h==null&&(h=this.getFoldWidget(a,g.row)),h=="start"&&(g.row--,g.column=a.getLine(g.row).length),d.fromPoints(f,g)}}).call(e.prototype)}),define("ace/mode/javascript",["require","exports","module","ace/lib/oop","ace/mode/text","ace/tokenizer","ace/mode/javascript_highlight_rules","ace/mode/matching_brace_outdent","ace/range","ace/worker/worker_client","ace/mode/behaviour/cstyle","ace/mode/folding/cstyle"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("./text").Mode,f=a("../tokenizer").Tokenizer,g=a("./javascript_highlight_rules").JavaScriptHighlightRules,h=a("./matching_brace_outdent").MatchingBraceOutdent,i=a("../range").Range,j=a("../worker/worker_client").WorkerClient,k=a("./behaviour/cstyle").CstyleBehaviour,l=a("./folding/cstyle").FoldMode,m=function(){this.$tokenizer=new f((new g).getRules()),this.$outdent=new h,this.$behaviour=new k,this.foldingRules=new l};d.inherits(m,e),function(){this.toggleCommentLines=function(a,b,c,d){var e=!0,f=/^(\s*)\/\//;for(var g=c;g<=d;g++)if(!f.test(b.getLine(g))){e=!1;break}if(e){var h=new i(0,0,0,0);for(var g=c;g<=d;g++){var j=b.getLine(g),k=j.match(f);h.start.row=g,h.end.row=g,h.end.column=k[0].length,b.replace(h,k[1])}}else b.indentRows(c,d,"//")},this.getNextLineIndent=function(a,b,c){var d=this.$getIndent(b),e=this.$tokenizer.getLineTokens(b,a),f=e.tokens,g=e.state;if(f.length&&f[f.length-1].type=="comment")return d;if(a=="start"||a=="regex_allowed"){var h=b.match(/^.*(?:\bcase\b.*\:|[\{\(\[])\s*$/);h&&(d+=c)}else if(a=="doc-start"){if(g=="start"||a=="regex_allowed")return"";var h=b.match(/^\s*(\/?)\*/);h&&(h[1]&&(d+=" "),d+="* ")}return d},this.checkOutdent=function(a,b,c){return this.$outdent.checkOutdent(b,c)},this.autoOutdent=function(a,b,c){this.$outdent.autoOutdent(b,c)},this.createWorker=function(a){var b=new j(["ace"],"worker-javascript.js","ace/mode/javascript_worker","JavaScriptWorker");return b.attachToDocument(a.getDocument()),b.on("jslint",function(b){var c=[];for(var d=0;d<b.data.length;d++){var e=b.data[d];e&&c.push({row:e.line-1,column:e.character-1,text:e.reason,type:"warning",lint:e})}a.setAnnotations(c)}),b.on("narcissus",function(b){a.setAnnotations([b.data])}),b.on("terminate",function(){a.clearAnnotations()}),b}}.call(m.prototype),b.Mode=m}),define("ace/mode/javascript_highlight_rules",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/unicode","ace/mode/doc_comment_highlight_rules","ace/mode/text_highlight_rules"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("../lib/lang"),f=a("../unicode"),g=a("./doc_comment_highlight_rules").DocCommentHighlightRules,h=a("./text_highlight_rules").TextHighlightRules,i=function(){var a=e.arrayToMap("Array|Boolean|Date|Function|Iterator|Number|Object|RegExp|String|Proxy|Namespace|QName|XML|XMLList|ArrayBuffer|Float32Array|Float64Array|Int16Array|Int32Array|Int8Array|Uint16Array|Uint32Array|Uint8Array|Uint8ClampedArray|Error|EvalError|InternalError|RangeError|ReferenceError|StopIteration|SyntaxError|TypeError|URIError|decodeURI|decodeURIComponent|encodeURI|encodeURIComponent|eval|isFinite|isNaN|parseFloat|parseInt|JSON|Math|this|arguments|prototype|window|document".split("|")),b=e.arrayToMap("break|case|catch|continue|default|delete|do|else|finally|for|function|if|in|instanceof|new|return|switch|throw|try|typeof|let|var|while|with|const|yield|import|get|set".split("|")),c="case|do|else|finally|in|instanceof|return|throw|try|typeof|yield",d=e.arrayToMap("__parent__|__count__|escape|unescape|with|__proto__".split("|")),h=e.arrayToMap("const|let|var|function".split("|")),i=e.arrayToMap("null|Infinity|NaN|undefined".split("|")),j=e.arrayToMap("class|enum|extends|super|export|implements|private|public|interface|package|protected|static".split("|")),k="["+f.packages.L+"\\$_]["+f.packages.L+f.packages.Mn+f.packages.Mc+f.packages.Nd+f.packages.Pc+"\\$_]*\\b",l="\\\\(?:x[0-9a-fA-F]{2}|u[0-9a-fA-F]{4}|[0-2][0-7]{0,2}|3[0-6][0-7]?|37[0-7]?|[4-7][0-7]?|.)";this.$rules={start:[{token:"comment",regex:/\/\/.*$/},(new g).getStartRule("doc-start"),{token:"comment",merge:!0,regex:/\/\*/,next:"comment"},{token:"string",regex:"'",next:"qstring"},{token:"string",regex:'"',next:"qqstring"},{token:"constant.numeric",regex:/0[xX][0-9a-fA-F]+\b/},{token:"constant.numeric",regex:/[+-]?\d+(?:(?:\.\d*)?(?:[eE][+-]?\d+)?)?\b/},{token:["storage.type","punctuation.operator","support.function","punctuation.operator","entity.name.function","text","keyword.operator","text","storage.type","text","paren.lparen","variable.parameter","paren.rparen"],regex:"("+k+")(\\.)(prototype)(\\.)("+k+")(\\s*)(=)(\\s*)(function)(\\s*)(\\()(.*?)(\\))"},{token:["storage.type","punctuation.operator","support.function","punctuation.operator","entity.name.function","text","keyword.operator","text"],regex:"("+k+")(\\.)(prototype)(\\.)("+k+")(\\s*)(=)(\\s*)"},{token:["storage.type","punctuation.operator","entity.name.function","text","keyword.operator","text","storage.type","text","paren.lparen","variable.parameter","paren.rparen"],regex:"("+k+")(\\.)("+k+")(\\s*)(=)(\\s*)(function)(\\s*)(\\()(.*?)(\\))"},{token:["entity.name.function","text","keyword.operator","text","storage.type","text","paren.lparen","variable.parameter","paren.rparen"],regex:"("+k+")(\\s*)(=)(\\s*)(function)(\\s*)(\\()(.*?)(\\))"},{token:["storage.type","text","entity.name.function","text","paren.lparen","variable.parameter","paren.rparen"],regex:"(function)(\\s+)("+k+")(\\s*)(\\()(.*?)(\\))"},{token:["entity.name.function","text","punctuation.operator","text","storage.type","text","paren.lparen","variable.parameter","paren.rparen"],regex:"("+k+")(\\s*)(:)(\\s*)(function)(\\s*)(\\()(.*?)(\\))"},{token:["text","text","storage.type","text","paren.lparen","variable.parameter","paren.rparen"],regex:"(:)(\\s*)(function)?(\\s*)(\\()([^)]*)(\\))"},{token:"constant.language.boolean",regex:/(?:true|false)\b/},{token:"keyword",regex:"(?:"+c+")\\b",next:"regex_allowed"},{token:["punctuation.operator","support.function"],regex:/(\.)(s(?:h(?:ift|ow(?:Mod(?:elessDialog|alDialog)|Help))|croll(?:X|By(?:Pages|Lines)?|Y|To)?|t(?:opzzzz|rike)|i(?:n|zeToContent|debar|gnText)|ort|u(?:p|b(?:str(?:ing)?)?)|pli(?:ce|t)|e(?:nd|t(?:Re(?:sizable|questHeader)|M(?:i(?:nutes|lliseconds)|onth)|Seconds|Ho(?:tKeys|urs)|Year|Cursor|Time(?:out)?|Interval|ZOptions|Date|UTC(?:M(?:i(?:nutes|lliseconds)|onth)|Seconds|Hours|Date|FullYear)|FullYear|Active)|arch)|qrt|lice|avePreferences|mall)|h(?:ome|andleEvent)|navigate|c(?:har(?:CodeAt|At)|o(?:s|n(?:cat|textual|firm)|mpile)|eil|lear(?:Timeout|Interval)?|a(?:ptureEvents|ll)|reate(?:StyleSheet|Popup|EventObject))|t(?:o(?:GMTString|S(?:tring|ource)|U(?:TCString|pperCase)|Lo(?:caleString|werCase))|est|a(?:n|int(?:Enabled)?))|i(?:s(?:NaN|Finite)|ndexOf|talics)|d(?:isableExternalCapture|ump|etachEvent)|u(?:n(?:shift|taint|escape|watch)|pdateCommands)|j(?:oin|avaEnabled)|p(?:o(?:p|w)|ush|lugins.refresh|a(?:ddings|rse(?:Int|Float)?)|r(?:int|ompt|eference))|e(?:scape|nableExternalCapture|val|lementFromPoint|x(?:p|ec(?:Script|Command)?))|valueOf|UTC|queryCommand(?:State|Indeterm|Enabled|Value)|f(?:i(?:nd|le(?:ModifiedDate|Size|CreatedDate|UpdatedDate)|xed)|o(?:nt(?:size|color)|rward)|loor|romCharCode)|watch|l(?:ink|o(?:ad|g)|astIndexOf)|a(?:sin|nchor|cos|t(?:tachEvent|ob|an(?:2)?)|pply|lert|b(?:s|ort))|r(?:ou(?:nd|teEvents)|e(?:size(?:By|To)|calc|turnValue|place|verse|l(?:oad|ease(?:Capture|Events)))|andom)|g(?:o|et(?:ResponseHeader|M(?:i(?:nutes|lliseconds)|onth)|Se(?:conds|lection)|Hours|Year|Time(?:zoneOffset)?|Da(?:y|te)|UTC(?:M(?:i(?:nutes|lliseconds)|onth)|Seconds|Hours|Da(?:y|te)|FullYear)|FullYear|A(?:ttention|llResponseHeaders)))|m(?:in|ove(?:B(?:y|elow)|To(?:Absolute)?|Above)|ergeAttributes|a(?:tch|rgins|x))|b(?:toa|ig|o(?:ld|rderWidths)|link|ack))\b(?=\()/},{token:["punctuation.operator","support.function.dom"],regex:/(\.)(s(?:ub(?:stringData|mit)|plitText|e(?:t(?:NamedItem|Attribute(?:Node)?)|lect))|has(?:ChildNodes|Feature)|namedItem|c(?:l(?:ick|o(?:se|neNode))|reate(?:C(?:omment|DATASection|aption)|T(?:Head|extNode|Foot)|DocumentFragment|ProcessingInstruction|E(?:ntityReference|lement)|Attribute))|tabIndex|i(?:nsert(?:Row|Before|Cell|Data)|tem)|open|delete(?:Row|C(?:ell|aption)|T(?:Head|Foot)|Data)|focus|write(?:ln)?|a(?:dd|ppend(?:Child|Data))|re(?:set|place(?:Child|Data)|move(?:NamedItem|Child|Attribute(?:Node)?)?)|get(?:NamedItem|Element(?:sBy(?:Name|TagName)|ById)|Attribute(?:Node)?)|blur)\b(?=\()/},{token:["punctuation.operator","support.constant"],regex:/(\.)(s(?:ystemLanguage|cr(?:ipts|ollbars|een(?:X|Y|Top|Left))|t(?:yle(?:Sheets)?|atus(?:Text|bar)?)|ibling(?:Below|Above)|ource|uffixes|e(?:curity(?:Policy)?|l(?:ection|f)))|h(?:istory|ost(?:name)?|as(?:h|Focus))|y|X(?:MLDocument|SLDocument)|n(?:ext|ame(?:space(?:s|URI)|Prop))|M(?:IN_VALUE|AX_VALUE)|c(?:haracterSet|o(?:n(?:structor|trollers)|okieEnabled|lorDepth|mp(?:onents|lete))|urrent|puClass|l(?:i(?:p(?:boardData)?|entInformation)|osed|asses)|alle(?:e|r)|rypto)|t(?:o(?:olbar|p)|ext(?:Transform|Indent|Decoration|Align)|ags)|SQRT(?:1_2|2)|i(?:n(?:ner(?:Height|Width)|put)|ds|gnoreCase)|zIndex|o(?:scpu|n(?:readystatechange|Line)|uter(?:Height|Width)|p(?:sProfile|ener)|ffscreenBuffering)|NEGATIVE_INFINITY|d(?:i(?:splay|alog(?:Height|Top|Width|Left|Arguments)|rectories)|e(?:scription|fault(?:Status|Ch(?:ecked|arset)|View)))|u(?:ser(?:Profile|Language|Agent)|n(?:iqueID|defined)|pdateInterval)|_content|p(?:ixelDepth|ort|ersonalbar|kcs11|l(?:ugins|atform)|a(?:thname|dding(?:Right|Bottom|Top|Left)|rent(?:Window|Layer)?|ge(?:X(?:Offset)?|Y(?:Offset)?))|r(?:o(?:to(?:col|type)|duct(?:Sub)?|mpter)|e(?:vious|fix)))|e(?:n(?:coding|abledPlugin)|x(?:ternal|pando)|mbeds)|v(?:isibility|endor(?:Sub)?|Linkcolor)|URLUnencoded|P(?:I|OSITIVE_INFINITY)|f(?:ilename|o(?:nt(?:Size|Family|Weight)|rmName)|rame(?:s|Element)|gColor)|E|whiteSpace|l(?:i(?:stStyleType|n(?:eHeight|kColor))|o(?:ca(?:tion(?:bar)?|lName)|wsrc)|e(?:ngth|ft(?:Context)?)|a(?:st(?:M(?:odified|atch)|Index|Paren)|yer(?:s|X)|nguage))|a(?:pp(?:MinorVersion|Name|Co(?:deName|re)|Version)|vail(?:Height|Top|Width|Left)|ll|r(?:ity|guments)|Linkcolor|bove)|r(?:ight(?:Context)?|e(?:sponse(?:XML|Text)|adyState))|global|x|m(?:imeTypes|ultiline|enubar|argin(?:Right|Bottom|Top|Left))|L(?:N(?:10|2)|OG(?:10E|2E))|b(?:o(?:ttom|rder(?:Width|RightWidth|BottomWidth|Style|Color|TopWidth|LeftWidth))|ufferDepth|elow|ackground(?:Color|Image)))\b/},{token:["storage.type","punctuation.operator","support.function.firebug"],regex:/(console)(\.)(warn|info|log|error|time|timeEnd|assert)\b/},{token:function(c){return a.hasOwnProperty(c)?"variable.language":d.hasOwnProperty(c)?"invalid.deprecated":h.hasOwnProperty(c)?"storage.type":b.hasOwnProperty(c)?"keyword":i.hasOwnProperty(c)?"constant.language":j.hasOwnProperty(c)?"invalid.illegal":c=="debugger"?"invalid.deprecated":"identifier"},regex:k},{token:"keyword.operator",regex:/!|\$|%|&|\*|\-\-|\-|\+\+|\+|~|===|==|=|!=|!==|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\|\||\?\:|\*=|%=|\+=|\-=|&=|\^=|\b(?:in|instanceof|new|delete|typeof|void)/,next:"regex_allowed"},{token:"punctuation.operator",regex:/\?|\:|\,|\;|\./,next:"regex_allowed"},{token:"paren.lparen",regex:/[\[({]/,next:"regex_allowed"},{token:"paren.rparen",regex:/[\])}]/},{token:"keyword.operator",regex:/\/=?/,next:"regex_allowed"},{token:"comment",regex:/^#!.*$/},{token:"text",regex:/\s+/}],regex_allowed:[{token:"comment",merge:!0,regex:"\\/\\*",next:"comment_regex_allowed"},{token:"comment",regex:"\\/\\/.*$"},{token:"string.regexp",regex:"\\/",next:"regex",merge:!0},{token:"text",regex:"\\s+"},{token:"empty",regex:"",next:"start"}],regex:[{token:"regexp.keyword.operator",regex:"\\\\(?:u[\\da-fA-F]{4}|x[\\da-fA-F]{2}|.)",next:"regex"},{token:"string.regexp",regex:"/\\w*",next:"start",merge:!0},{token:"string.regexp",regex:"[^\\\\/\\[]+",next:"regex",merge:!0},{token:"string.regexp.charachterclass",regex:"\\[",next:"regex_character_class",merge:!0},{token:"empty",regex:"",next:"start"}],regex_character_class:[{token:"regexp.keyword.operator",regex:"\\\\(?:u[\\da-fA-F]{4}|x[\\da-fA-F]{2}|.)",next:"regex_character_class"},{token:"string.regexp.charachterclass",regex:"]",next:"regex",merge:!0},{token:"string.regexp.charachterclass",regex:"[^\\\\\\]]+",next:"regex_character_class",merge:!0},{token:"empty",regex:"",next:"start"}],comment_regex_allowed:[{token:"comment",regex:".*?\\*\\/",merge:!0,next:"regex_allowed"},{token:"comment",merge:!0,regex:".+"}],comment:[{token:"comment",regex:".*?\\*\\/",merge:!0,next:"start"},{token:"comment",merge:!0,regex:".+"}],qqstring:[{token:"constant.language.escape",regex:l},{token:"string",regex:'[^"\\\\]+'},{token:"string",regex:'"',next:"start"}],qstring:[{token:"constant.language.escape",regex:l},{token:"string",regex:"[^'\\\\]+"},{token:"string",regex:"'",next:"start"}]},this.embedRules(g,"doc-",[(new g).getEndRule("start")])};d.inherits(i,h),b.JavaScriptHighlightRules=i}),define("ace/mode/doc_comment_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("./text_highlight_rules").TextHighlightRules,f=function(){this.$rules={start:[{token:"comment.doc.tag",regex:"@[\\w\\d_]+"},{token:"comment.doc",merge:!0,regex:"\\s+"},{token:"comment.doc",merge:!0,regex:"TODO"},{token:"comment.doc",merge:!0,regex:"[^@\\*]+"},{token:"comment.doc",merge:!0,regex:"."}]}};d.inherits(f,e),function(){this.getStartRule=function(a){return{token:"comment.doc",merge:!0,regex:"\\/\\*(?=\\*)",next:a}},this.getEndRule=function(a){return{token:"comment.doc",merge:!0,regex:"\\*\\/",next:a}}}.call(f.prototype),b.DocCommentHighlightRules=f}),define("ace/mode/matching_brace_outdent",["require","exports","module","ace/range"],function(a,b,c){"use strict";var d=a("../range").Range,e=function(){};(function(){this.checkOutdent=function(a,b){return/^\s+$/.test(a)?/^\s*\}/.test(b):!1},this.autoOutdent=function(a,b){var c=a.getLine(b),e=c.match(/^(\s*\})/);if(!e)return 0;var f=e[1].length,g=a.findMatchingBracket({row:b,column:f});if(!g||g.row==b)return 0;var h=this.$getIndent(a.getLine(g.row));a.replace(new d(b,0,b,f-1),h)},this.$getIndent=function(a){var b=a.match(/^(\s+)/);return b?b[1]:""}}).call(e.prototype),b.MatchingBraceOutdent=e}),define("ace/mode/folding/cstyle",["require","exports","module","ace/lib/oop","ace/range","ace/mode/folding/fold_mode"],function(a,b,c){"use strict";var d=a("../../lib/oop"),e=a("../../range").Range,f=a("./fold_mode").FoldMode,g=b.FoldMode=function(){};d.inherits(g,f),function(){this.foldingStartMarker=/(\{|\[)[^\}\]]*$|^\s*(\/\*)/,this.foldingStopMarker=/^[^\[\{]*(\}|\])|^[\s\*]*(\*\/)/,this.getFoldWidgetRange=function(a,b,c){var d=a.getLine(c),f=d.match(this.foldingStartMarker);if(f){var g=f.index;if(f[1])return this.openingBracketBlock(a,f[1],c,g);var h=a.getCommentFoldRange(c,g+f[0].length);return h.end.column-=2,h}if(b!=="markbeginend")return;var f=d.match(this.foldingStopMarker);if(f){var g=f.index+f[0].length;if(f[2]){var h=a.getCommentFoldRange(c,g);return h.end.column-=2,h}var i={row:c,column:g},j=a.$findOpeningBracket(f[1],i);if(!j)return;return j.column++,i.column--,e.fromPoints(j,i)}}}.call(g.prototype)}),define("ace/mode/css",["require","exports","module","ace/lib/oop","ace/mode/text","ace/tokenizer","ace/mode/css_highlight_rules","ace/mode/matching_brace_outdent","ace/worker/worker_client","ace/mode/folding/cstyle"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("./text").Mode,f=a("../tokenizer").Tokenizer,g=a("./css_highlight_rules").CssHighlightRules,h=a("./matching_brace_outdent").MatchingBraceOutdent,i=a("../worker/worker_client").WorkerClient,j=a("./folding/cstyle").FoldMode,k=function(){this.$tokenizer=new f((new g).getRules(),"i"),this.$outdent=new h,this.foldingRules=new j};d.inherits(k,e),function(){this.foldingRules="cStyle",this.getNextLineIndent=function(a,b,c){var d=this.$getIndent(b),e=this.$tokenizer.getLineTokens(b,a).tokens;if(e.length&&e[e.length-1].type=="comment")return d;var f=b.match(/^.*\{\s*$/);return f&&(d+=c),d},this.checkOutdent=function(a,b,c){return this.$outdent.checkOutdent(b,c)},this.autoOutdent=function(a,b,c){this.$outdent.autoOutdent(b,c)},this.createWorker=function(a){var b=new i(["ace"],"worker-css.js","ace/mode/css_worker","Worker");return b.attachToDocument(a.getDocument()),b.on("csslint",function(b){var c=[];b.data.forEach(function(a){c.push({row:a.line-1,column:a.col-1,text:a.message,type:a.type,lint:a})}),a.setAnnotations(c)}),b}}.call(k.prototype),b.Mode=k}),define("ace/mode/css_highlight_rules",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/mode/text_highlight_rules"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("../lib/lang"),f=a("./text_highlight_rules").TextHighlightRules,g=function(){var a=e.arrayToMap("animation-fill-mode|alignment-adjust|alignment-baseline|animation-delay|animation-direction|animation-duration|animation-iteration-count|animation-name|animation-play-state|animation-timing-function|animation|appearance|azimuth|backface-visibility|background-attachment|background-break|background-clip|background-color|background-image|background-origin|background-position|background-repeat|background-size|background|baseline-shift|binding|bleed|bookmark-label|bookmark-level|bookmark-state|bookmark-target|border-bottom|border-bottom-color|border-bottom-left-radius|border-bottom-right-radius|border-bottom-style|border-bottom-width|border-collapse|border-color|border-image|border-image-outset|border-image-repeat|border-image-slice|border-image-source|border-image-width|border-left|border-left-color|border-left-style|border-left-width|border-radius|border-right|border-right-color|border-right-style|border-right-width|border-spacing|border-style|border-top|border-top-color|border-top-left-radius|border-top-right-radius|border-top-style|border-top-width|border-width|border|bottom|box-align|box-decoration-break|box-direction|box-flex-group|box-flex|box-lines|box-ordinal-group|box-orient|box-pack|box-shadow|box-sizing|break-after|break-before|break-inside|caption-side|clear|clip|color-profile|color|column-count|column-fill|column-gap|column-rule|column-rule-color|column-rule-style|column-rule-width|column-span|column-width|columns|content|counter-increment|counter-reset|crop|cue-after|cue-before|cue|cursor|direction|display|dominant-baseline|drop-initial-after-adjust|drop-initial-after-align|drop-initial-before-adjust|drop-initial-before-align|drop-initial-size|drop-initial-value|elevation|empty-cells|fit|fit-position|float-offset|float|font-family|font-size|font-size-adjust|font-stretch|font-style|font-variant|font-weight|font|grid-columns|grid-rows|hanging-punctuation|height|hyphenate-after|hyphenate-before|hyphenate-character|hyphenate-lines|hyphenate-resource|hyphens|icon|image-orientation|image-rendering|image-resolution|inline-box-align|left|letter-spacing|line-height|line-stacking-ruby|line-stacking-shift|line-stacking-strategy|line-stacking|list-style-image|list-style-position|list-style-type|list-style|margin-bottom|margin-left|margin-right|margin-top|margin|mark-after|mark-before|mark|marks|marquee-direction|marquee-play-count|marquee-speed|marquee-style|max-height|max-width|min-height|min-width|move-to|nav-down|nav-index|nav-left|nav-right|nav-up|opacity|orphans|outline-color|outline-offset|outline-style|outline-width|outline|overflow-style|overflow-x|overflow-y|overflow|padding-bottom|padding-left|padding-right|padding-top|padding|page-break-after|page-break-before|page-break-inside|page-policy|page|pause-after|pause-before|pause|perspective-origin|perspective|phonemes|pitch-range|pitch|play-during|position|presentation-level|punctuation-trim|quotes|rendering-intent|resize|rest-after|rest-before|rest|richness|right|rotation-point|rotation|ruby-align|ruby-overhang|ruby-position|ruby-span|size|speak-header|speak-numeral|speak-punctuation|speak|speech-rate|stress|string-set|table-layout|target-name|target-new|target-position|target|text-align-last|text-align|text-decoration|text-emphasis|text-height|text-indent|text-justify|text-outline|text-shadow|text-transform|text-wrap|top|transform-origin|transform-style|transform|transition-delay|transition-duration|transition-property|transition-timing-function|transition|unicode-bidi|vertical-align|visibility|voice-balance|voice-duration|voice-family|voice-pitch-range|voice-pitch|voice-rate|voice-stress|voice-volume|volume|white-space-collapse|white-space|widows|width|word-break|word-spacing|word-wrap|z-index".split("|")),b=e.arrayToMap("rgb|rgba|url|attr|counter|counters".split("|")),c=e.arrayToMap("absolute|after-edge|after|all-scroll|all|alphabetic|always|antialiased|armenian|auto|avoid-column|avoid-page|avoid|balance|baseline|before-edge|before|below|bidi-override|block-line-height|block|bold|bolder|border-box|both|bottom|box|break-all|break-word|capitalize|caps-height|caption|center|central|char|circle|cjk-ideographic|clone|close-quote|col-resize|collapse|column|consider-shifts|contain|content-box|cover|crosshair|cubic-bezier|dashed|decimal-leading-zero|decimal|default|disabled|disc|disregard-shifts|distribute-all-lines|distribute-letter|distribute-space|distribute|dotted|double|e-resize|ease-in|ease-in-out|ease-out|ease|ellipsis|end|exclude-ruby|fill|fixed|font-size|font|georgian|glyphs|grid-height|groove|hand|hanging|hebrew|help|hidden|hiragana-iroha|hiragana|horizontal|icon|ideograph-alpha|ideograph-numeric|ideograph-parenthesis|ideograph-space|ideographic|inactive|include-ruby|inherit|initial|inline-block|inline-box|inline-line-height|inline-table|inline|inset|inside|inter-ideograph|inter-word|invert|italic|justify|katakana-iroha|katakana|keep-all|last|left|lighter|line-edge|line-through|line|linear|list-item|local|loose|lower-alpha|lower-greek|lower-latin|lower-roman|lowercase|lr-tb|ltr|mathematical|max-height|max-size|medium|menu|message-box|middle|move|n-resize|ne-resize|newspaper|no-change|no-close-quote|no-drop|no-open-quote|no-repeat|none|normal|not-allowed|nowrap|nw-resize|oblique|open-quote|outset|outside|overline|padding-box|page|pointer|pre-line|pre-wrap|pre|preserve-3d|progress|relative|repeat-x|repeat-y|repeat|replaced|reset-size|ridge|right|round|row-resize|rtl|s-resize|scroll|se-resize|separate|slice|small-caps|small-caption|solid|space|square|start|static|status-bar|step-end|step-start|steps|stretch|strict|sub|super|sw-resize|table-caption|table-cell|table-column-group|table-column|table-footer-group|table-header-group|table-row-group|table-row|table|tb-rl|text-after-edge|text-before-edge|text-bottom|text-size|text-top|text|thick|thin|top|transparent|underline|upper-alpha|upper-latin|upper-roman|uppercase|use-script|vertical-ideographic|vertical-text|visible|w-resize|wait|whitespace|z-index|zero".split("|")),d=e.arrayToMap("aqua|black|blue|fuchsia|gray|green|lime|maroon|navy|olive|orange|purple|red|silver|teal|white|yellow".split("|")),f=e.arrayToMap("arial|century|comic|courier|garamond|georgia|helvetica|impact|lucida|symbol|system|tahoma|times|trebuchet|utopia|verdana|webdings|sans-serif|serif|monospace".split("|")),g="\\-?(?:(?:[0-9]+)|(?:[0-9]*\\.[0-9]+))",h="(\\:+)\\b(after|before|first-letter|first-line|moz-selection|selection)\\b",i="(:)\\b(active|checked|disabled|empty|enabled|first-child|first-of-type|focus|hover|indeterminate|invalid|last-child|last-of-type|link|not|nth-child|nth-last-child|nth-last-of-type|nth-of-type|only-child|only-of-type|required|root|target|valid|visited)\\b",j=[{token:"comment",merge:!0,regex:"\\/\\*",next:"ruleset_comment"},{token:"string",regex:'["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'},{token:"string",regex:"['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"},{token:["constant.numeric","keyword"],regex:"("+g+")(ch|cm|deg|em|ex|fr|gd|grad|Hz|in|kHz|mm|ms|pc|pt|px|rad|rem|s|turn|vh|vm|vw|%)"},{token:["constant.numeric"],regex:"([0-9]+)"},{token:"constant.numeric",regex:"#[a-f0-9]{6}"},{token:"constant.numeric",regex:"#[a-f0-9]{3}"},{token:["punctuation","entity.other.attribute-name.pseudo-element.css"],regex:h},{token:["punctuation","entity.other.attribute-name.pseudo-class.css"],regex:i},{token:function(e){return a.hasOwnProperty(e.toLowerCase())?"support.type":b.hasOwnProperty(e.toLowerCase())?"support.function":c.hasOwnProperty(e.toLowerCase())?"support.constant":d.hasOwnProperty(e.toLowerCase())?"support.constant.color":f.hasOwnProperty(e.toLowerCase())?"support.constant.fonts":"text"},regex:"\\-?[a-zA-Z_][a-zA-Z0-9_\\-]*"}],k=e.copyArray(j);k.unshift({token:"paren.rparen",regex:"\\}",next:"start"});var l=e.copyArray(j);l.unshift({token:"paren.rparen",regex:"\\}",next:"media"});var m=[{token:"comment",merge:!0,regex:".+"}],n=e.copyArray(m);n.unshift({token:"comment",regex:".*?\\*\\/",next:"start"});var o=e.copyArray(m);o.unshift({token:"comment",regex:".*?\\*\\/",next:"media"});var p=e.copyArray(m);p.unshift({token:"comment",regex:".*?\\*\\/",next:"ruleset"}),this.$rules={start:[{token:"comment",merge:!0,regex:"\\/\\*",next:"comment"},{token:"paren.lparen",regex:"\\{",next:"ruleset"},{token:"string",regex:"@.*?{",next:"media"},{token:"keyword",regex:"#[a-z0-9-_]+"},{token:"variable",regex:"\\.[a-z0-9-_]+"},{token:"string",regex:":[a-z0-9-_]+"},{token:"constant",regex:"[a-z0-9-_]+"}],media:[{token:"comment",merge:!0,regex:"\\/\\*",next:"media_comment"},{token:"paren.lparen",regex:"\\{",next:"media_ruleset"},{token:"string",regex:"\\}",next:"start"},{token:"keyword",regex:"#[a-z0-9-_]+"},{token:"variable",regex:"\\.[a-z0-9-_]+"},{token:"string",regex:":[a-z0-9-_]+"},{token:"constant",regex:"[a-z0-9-_]+"}],comment:n,ruleset:k,ruleset_comment:p,media_ruleset:l,media_comment:o}};d.inherits(g,f),b.CssHighlightRules=g}),define("ace/mode/coldfusion_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/css_highlight_rules","ace/mode/javascript_highlight_rules","ace/mode/text_highlight_rules","ace/mode/xml_util"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("./css_highlight_rules").CssHighlightRules,f=a("./javascript_highlight_rules").JavaScriptHighlightRules,g=a("./text_highlight_rules").TextHighlightRules,h=a("./xml_util"),i=function(){this.$rules={start:[{token:"text",merge:!0,regex:"<\\!\\[CDATA\\[",next:"cdata"},{token:"xml_pe",regex:"<\\?.*?\\?>"},{token:"comment",merge:!0,regex:"<\\!--",next:"comment"},{token:"meta.tag",regex:"<(?=s*script)",next:"script"},{token:"meta.tag",regex:"<(?=s*style)",next:"style"},{token:"meta.tag",regex:"<\\/?",next:"tag"},{token:"text",regex:"\\s+"},{token:"text",regex:"[^<]+"}],cdata:[{token:"text",regex:"\\]\\]>",next:"start"},{token:"text",merge:!0,regex:"\\s+"},{token:"text",merge:!0,regex:".+"}],comment:[{token:"comment",regex:".*?-->",next:"start"},{token:"comment",merge:!0,regex:".+"}]},h.tag(this.$rules,"tag","start"),h.tag(this.$rules,"style","css-start"),h.tag(this.$rules,"script","js-start"),this.embedRules(f,"js-",[{token:"comment",regex:"\\/\\/.*(?=<\\/script>)",next:"tag"},{token:"meta.tag",regex:"<\\/(?=script)",next:"tag"}]),this.embedRules(e,"css-",[{token:"meta.tag",regex:"<\\/(?=style)",next:"tag"}])};d.inherits(i,g),b.ColdfusionHighlightRules=i})
\ No newline at end of file
diff --git a/apps/files_texteditor/js/aceeditor/mode-csharp-uncompressed.js b/apps/files_texteditor/js/aceeditor/mode-csharp-uncompressed.js
old mode 100755
new mode 100644
index 492e2ff98474682e327ab39c42ff04590bf255a3..3e83d27d72c63542da5628a09b1360867b1ba580
--- a/apps/files_texteditor/js/aceeditor/mode-csharp-uncompressed.js
+++ b/apps/files_texteditor/js/aceeditor/mode-csharp-uncompressed.js
@@ -391,12 +391,12 @@ var CstyleBehaviour = function () {
                 return {
                     text: '{' + selected + '}',
                     selection: false
-                }
+                };
             } else {
                 return {
                     text: '{}',
                     selection: [1, 1]
-                }
+                };
             }
         } else if (text == '}') {
             var cursor = editor.getCursorPosition();
@@ -408,7 +408,7 @@ var CstyleBehaviour = function () {
                     return {
                         text: '',
                         selection: [1, 1]
-                    }
+                    };
                 }
             }
         } else if (text == "\n") {
@@ -426,7 +426,7 @@ var CstyleBehaviour = function () {
                 return {
                     text: '\n' + indent + '\n' + next_indent,
                     selection: [1, indent.length, 1, indent.length]
-                }
+                };
             }
         }
     });
@@ -451,12 +451,12 @@ var CstyleBehaviour = function () {
                 return {
                     text: '(' + selected + ')',
                     selection: false
-                }
+                };
             } else {
                 return {
                     text: '()',
                     selection: [1, 1]
-                }
+                };
             }
         } else if (text == ')') {
             var cursor = editor.getCursorPosition();
@@ -468,7 +468,7 @@ var CstyleBehaviour = function () {
                     return {
                         text: '',
                         selection: [1, 1]
-                    }
+                    };
                 }
             }
         }
@@ -487,14 +487,15 @@ var CstyleBehaviour = function () {
     });
 
     this.add("string_dquotes", "insertion", function (state, action, editor, session, text) {
-        if (text == '"') {
+        if (text == '"' || text == "'") {
+            var quote = text;
             var selection = editor.getSelectionRange();
             var selected = session.doc.getTextRange(selection);
             if (selected !== "") {
                 return {
-                    text: '"' + selected + '"',
+                    text: quote + selected + quote,
                     selection: false
-                }
+                };
             } else {
                 var cursor = editor.getCursorPosition();
                 var line = session.doc.getLine(cursor.row);
@@ -515,7 +516,7 @@ var CstyleBehaviour = function () {
                     if (token.type == "string") {
                       quotepos = -1;
                     } else if (quotepos < 0) {
-                      quotepos = token.value.indexOf('"');
+                      quotepos = token.value.indexOf(quote);
                     }
                     if ((token.value.length + col) > selection.start.column) {
                         break;
@@ -524,19 +525,19 @@ var CstyleBehaviour = function () {
                 }
 
                 // Try and be smart about when we auto insert.
-                if (!token || (quotepos < 0 && token.type !== "comment" && (token.type !== "string" || ((selection.start.column !== token.value.length+col-1) && token.value.lastIndexOf('"') === token.value.length-1)))) {
+                if (!token || (quotepos < 0 && token.type !== "comment" && (token.type !== "string" || ((selection.start.column !== token.value.length+col-1) && token.value.lastIndexOf(quote) === token.value.length-1)))) {
                     return {
-                        text: '""',
+                        text: quote + quote,
                         selection: [1,1]
-                    }
+                    };
                 } else if (token && token.type === "string") {
                     // Ignore input and move right one if we're typing over the closing quote.
                     var rightChar = line.substring(cursor.column, cursor.column + 1);
-                    if (rightChar == '"') {
+                    if (rightChar == quote) {
                         return {
                             text: '',
                             selection: [1, 1]
-                        }
+                        };
                     }
                 }
             }
@@ -545,7 +546,7 @@ var CstyleBehaviour = function () {
 
     this.add("string_dquotes", "deletion", function (state, action, editor, session, range) {
         var selected = session.doc.getTextRange(range);
-        if (!range.isMultiLine() && selected == '"') {
+        if (!range.isMultiLine() && (selected == '"' || selected == "'")) {
             var line = session.doc.getLine(range.start.row);
             var rightChar = line.substring(range.start.column + 1, range.start.column + 2);
             if (rightChar == '"') {
@@ -555,7 +556,8 @@ var CstyleBehaviour = function () {
         }
     });
 
-}
+};
+
 oop.inherits(CstyleBehaviour, Behaviour);
 
 exports.CstyleBehaviour = CstyleBehaviour;
@@ -766,13 +768,3 @@ var FoldMode = exports.FoldMode = function() {};
 }).call(FoldMode.prototype);
 
 });
-;
-            (function() {
-                window.require(["ace/ace"], function(a) {
-                    if (!window.ace)
-                        window.ace = {};
-                    for (var key in a) if (a.hasOwnProperty(key))
-                        ace[key] = a[key];
-                });
-            })();
-        
\ No newline at end of file
diff --git a/apps/files_texteditor/js/aceeditor/mode-csharp.js b/apps/files_texteditor/js/aceeditor/mode-csharp.js
index b4c06059661097c149c965d2eddddd2525fc92e0..642ee6e7b19c8cf97afb853bf117177efeaa5a51 100644
--- a/apps/files_texteditor/js/aceeditor/mode-csharp.js
+++ b/apps/files_texteditor/js/aceeditor/mode-csharp.js
@@ -1 +1 @@
-define("ace/mode/csharp",["require","exports","module","ace/lib/oop","ace/mode/text","ace/tokenizer","ace/mode/csharp_highlight_rules","ace/mode/matching_brace_outdent","ace/mode/behaviour/cstyle","ace/mode/folding/cstyle"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("./text").Mode,f=a("../tokenizer").Tokenizer,g=a("./csharp_highlight_rules").CSharpHighlightRules,h=a("./matching_brace_outdent").MatchingBraceOutdent,i=a("./behaviour/cstyle").CstyleBehaviour,j=a("./folding/cstyle").FoldMode,k=function(){this.$tokenizer=new f((new g).getRules()),this.$outdent=new h,this.$behaviour=new i,this.foldingRules=new j};d.inherits(k,e),function(){this.getNextLineIndent=function(a,b,c){var d=this.$getIndent(b),e=this.$tokenizer.getLineTokens(b,a),f=e.tokens;if(f.length&&f[f.length-1].type=="comment")return d;if(a=="start"){var g=b.match(/^.*[\{\(\[]\s*$/);g&&(d+=c)}return d},this.checkOutdent=function(a,b,c){return this.$outdent.checkOutdent(b,c)},this.autoOutdent=function(a,b,c){this.$outdent.autoOutdent(b,c)},this.createWorker=function(a){return null}}.call(k.prototype),b.Mode=k}),define("ace/mode/csharp_highlight_rules",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/mode/doc_comment_highlight_rules","ace/mode/text_highlight_rules"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("../lib/lang"),f=a("./doc_comment_highlight_rules").DocCommentHighlightRules,g=a("./text_highlight_rules").TextHighlightRules,h=function(){var a=e.arrayToMap("abstract|event|new|struct|as|explicit|null|switch|base|extern|object|this|bool|false|operator|throw|break|finally|out|true|byte|fixed|override|try|case|float|params|typeof|catch|for|private|uint|char|foreach|protected|ulong|checked|goto|public|unchecked|class|if|readonly|unsafe|const|implicit|ref|ushort|continue|in|return|using|decimal|int|sbyte|virtual|default|interface|sealed|volatile|delegate|internal|short|void|do|is|sizeof|while|double|lock|stackalloc|else|long|static|enum|namespace|string|var|dynamic".split("|")),b=e.arrayToMap("null|true|false".split("|"));this.$rules={start:[{token:"comment",regex:"\\/\\/.*$"},(new f).getStartRule("doc-start"),{token:"comment",regex:"\\/\\*",merge:!0,next:"comment"},{token:"string.regexp",regex:"[/](?:(?:\\[(?:\\\\]|[^\\]])+\\])|(?:\\\\/|[^\\]/]))*[/]\\w*\\s*(?=[).,;]|$)"},{token:"string",regex:'["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'},{token:"string",regex:"['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"},{token:"constant.numeric",regex:"0[xX][0-9a-fA-F]+\\b"},{token:"constant.numeric",regex:"[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"},{token:"constant.language.boolean",regex:"(?:true|false)\\b"},{token:function(c){return c=="this"?"variable.language":a.hasOwnProperty(c)?"keyword":b.hasOwnProperty(c)?"constant.language":"identifier"},regex:"[a-zA-Z_$][a-zA-Z0-9_$]*\\b"},{token:"keyword.operator",regex:"!|\\$|%|&|\\*|\\-\\-|\\-|\\+\\+|\\+|~|===|==|=|!=|!==|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\\|\\||\\?\\:|\\*=|%=|\\+=|\\-=|&=|\\^=|\\b(?:in|instanceof|new|delete|typeof|void)"},{token:"punctuation.operator",regex:"\\?|\\:|\\,|\\;|\\."},{token:"paren.lparen",regex:"[[({]"},{token:"paren.rparen",regex:"[\\])}]"},{token:"text",regex:"\\s+"}],comment:[{token:"comment",regex:".*?\\*\\/",next:"start"},{token:"comment",merge:!0,regex:".+"}]},this.embedRules(f,"doc-",[(new f).getEndRule("start")])};d.inherits(h,g),b.CSharpHighlightRules=h}),define("ace/mode/doc_comment_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("./text_highlight_rules").TextHighlightRules,f=function(){this.$rules={start:[{token:"comment.doc.tag",regex:"@[\\w\\d_]+"},{token:"comment.doc",merge:!0,regex:"\\s+"},{token:"comment.doc",merge:!0,regex:"TODO"},{token:"comment.doc",merge:!0,regex:"[^@\\*]+"},{token:"comment.doc",merge:!0,regex:"."}]}};d.inherits(f,e),function(){this.getStartRule=function(a){return{token:"comment.doc",merge:!0,regex:"\\/\\*(?=\\*)",next:a}},this.getEndRule=function(a){return{token:"comment.doc",merge:!0,regex:"\\*\\/",next:a}}}.call(f.prototype),b.DocCommentHighlightRules=f}),define("ace/mode/matching_brace_outdent",["require","exports","module","ace/range"],function(a,b,c){"use strict";var d=a("../range").Range,e=function(){};((function(){this.checkOutdent=function(a,b){return/^\s+$/.test(a)?/^\s*\}/.test(b):!1},this.autoOutdent=function(a,b){var c=a.getLine(b),e=c.match(/^(\s*\})/);if(!e)return 0;var f=e[1].length,g=a.findMatchingBracket({row:b,column:f});if(!g||g.row==b)return 0;var h=this.$getIndent(a.getLine(g.row));a.replace(new d(b,0,b,f-1),h)},this.$getIndent=function(a){var b=a.match(/^(\s+)/);return b?b[1]:""}})).call(e.prototype),b.MatchingBraceOutdent=e}),define("ace/mode/behaviour/cstyle",["require","exports","module","ace/lib/oop","ace/mode/behaviour"],function(a,b,c){"use strict";var d=a("../../lib/oop"),e=a("../behaviour").Behaviour,f=function(){this.add("braces","insertion",function(a,b,c,d,e){if(e=="{"){var f=c.getSelectionRange(),g=d.doc.getTextRange(f);return g!==""?{text:"{"+g+"}",selection:!1}:{text:"{}",selection:[1,1]}}if(e=="}"){var h=c.getCursorPosition(),i=d.doc.getLine(h.row),j=i.substring(h.column,h.column+1);if(j=="}"){var k=d.$findOpeningBracket("}",{column:h.column+1,row:h.row});if(k!==null)return{text:"",selection:[1,1]}}}else if(e=="\n"){var h=c.getCursorPosition(),i=d.doc.getLine(h.row),j=i.substring(h.column,h.column+1);if(j=="}"){var l=d.findMatchingBracket({row:h.row,column:h.column+1});if(!l)return null;var m=this.getNextLineIndent(a,i.substring(0,i.length-1),d.getTabString()),n=this.$getIndent(d.doc.getLine(l.row));return{text:"\n"+m+"\n"+n,selection:[1,m.length,1,m.length]}}}}),this.add("braces","deletion",function(a,b,c,d,e){var f=d.doc.getTextRange(e);if(!e.isMultiLine()&&f=="{"){var g=d.doc.getLine(e.start.row),h=g.substring(e.end.column,e.end.column+1);if(h=="}")return e.end.column++,e}}),this.add("parens","insertion",function(a,b,c,d,e){if(e=="("){var f=c.getSelectionRange(),g=d.doc.getTextRange(f);return g!==""?{text:"("+g+")",selection:!1}:{text:"()",selection:[1,1]}}if(e==")"){var h=c.getCursorPosition(),i=d.doc.getLine(h.row),j=i.substring(h.column,h.column+1);if(j==")"){var k=d.$findOpeningBracket(")",{column:h.column+1,row:h.row});if(k!==null)return{text:"",selection:[1,1]}}}}),this.add("parens","deletion",function(a,b,c,d,e){var f=d.doc.getTextRange(e);if(!e.isMultiLine()&&f=="("){var g=d.doc.getLine(e.start.row),h=g.substring(e.start.column+1,e.start.column+2);if(h==")")return e.end.column++,e}}),this.add("string_dquotes","insertion",function(a,b,c,d,e){if(e=='"'){var f=c.getSelectionRange(),g=d.doc.getTextRange(f);if(g!=="")return{text:'"'+g+'"',selection:!1};var h=c.getCursorPosition(),i=d.doc.getLine(h.row),j=i.substring(h.column-1,h.column);if(j=="\\")return null;var k=d.getTokens(f.start.row,f.start.row)[0].tokens,l=0,m,n=-1;for(var o=0;o<k.length;o++){m=k[o],m.type=="string"?n=-1:n<0&&(n=m.value.indexOf('"'));if(m.value.length+l>f.start.column)break;l+=k[o].value.length}if(!m||n<0&&m.type!=="comment"&&(m.type!=="string"||f.start.column!==m.value.length+l-1&&m.value.lastIndexOf('"')===m.value.length-1))return{text:'""',selection:[1,1]};if(m&&m.type==="string"){var p=i.substring(h.column,h.column+1);if(p=='"')return{text:"",selection:[1,1]}}}}),this.add("string_dquotes","deletion",function(a,b,c,d,e){var f=d.doc.getTextRange(e);if(!e.isMultiLine()&&f=='"'){var g=d.doc.getLine(e.start.row),h=g.substring(e.start.column+1,e.start.column+2);if(h=='"')return e.end.column++,e}})};d.inherits(f,e),b.CstyleBehaviour=f}),define("ace/mode/folding/cstyle",["require","exports","module","ace/lib/oop","ace/range","ace/mode/folding/fold_mode"],function(a,b,c){"use strict";var d=a("../../lib/oop"),e=a("../../range").Range,f=a("./fold_mode").FoldMode,g=b.FoldMode=function(){};d.inherits(g,f),function(){this.foldingStartMarker=/(\{|\[)[^\}\]]*$|^\s*(\/\*)/,this.foldingStopMarker=/^[^\[\{]*(\}|\])|^[\s\*]*(\*\/)/,this.getFoldWidgetRange=function(a,b,c){var d=a.getLine(c),f=d.match(this.foldingStartMarker);if(f){var g=f.index;if(f[1])return this.openingBracketBlock(a,f[1],c,g);var h=a.getCommentFoldRange(c,g+f[0].length);return h.end.column-=2,h}if(b!=="markbeginend")return;var f=d.match(this.foldingStopMarker);if(f){var g=f.index+f[0].length;if(f[2]){var h=a.getCommentFoldRange(c,g);return h.end.column-=2,h}var i={row:c,column:g},j=a.$findOpeningBracket(f[1],i);if(!j)return;return j.column++,i.column--,e.fromPoints(j,i)}}}.call(g.prototype)}),define("ace/mode/folding/fold_mode",["require","exports","module","ace/range"],function(a,b,c){"use strict";var d=a("../../range").Range,e=b.FoldMode=function(){};((function(){this.foldingStartMarker=null,this.foldingStopMarker=null,this.getFoldWidget=function(a,b,c){var d=a.getLine(c);return this.foldingStartMarker.test(d)?"start":b=="markbeginend"&&this.foldingStopMarker&&this.foldingStopMarker.test(d)?"end":""},this.getFoldWidgetRange=function(a,b,c){return null},this.indentationBlock=function(a,b,c){var e=/^\s*/,f=b,g=b,h=a.getLine(b),i=c||h.length,j=h.match(e)[0].length,k=a.getLength();while(++b<k){h=a.getLine(b);var l=h.match(e)[0].length;if(l==h.length)continue;if(l<=j)break;g=b}if(g>f){var m=a.getLine(g).length;return new d(f,i,g,m)}},this.openingBracketBlock=function(a,b,c,e){var f={row:c,column:e+1},g=a.$findClosingBracket(b,f);if(!g)return;var h=a.foldWidgets[g.row];return h==null&&(h=this.getFoldWidget(a,g.row)),h=="start"&&(g.row--,g.column=a.getLine(g.row).length),d.fromPoints(f,g)}})).call(e.prototype)}),function(){window.require(["ace/ace"],function(a){window.ace||(window.ace={});for(var b in a)a.hasOwnProperty(b)&&(ace[b]=a[b])})}()
\ No newline at end of file
+define("ace/mode/csharp",["require","exports","module","ace/lib/oop","ace/mode/text","ace/tokenizer","ace/mode/csharp_highlight_rules","ace/mode/matching_brace_outdent","ace/mode/behaviour/cstyle","ace/mode/folding/cstyle"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("./text").Mode,f=a("../tokenizer").Tokenizer,g=a("./csharp_highlight_rules").CSharpHighlightRules,h=a("./matching_brace_outdent").MatchingBraceOutdent,i=a("./behaviour/cstyle").CstyleBehaviour,j=a("./folding/cstyle").FoldMode,k=function(){this.$tokenizer=new f((new g).getRules()),this.$outdent=new h,this.$behaviour=new i,this.foldingRules=new j};d.inherits(k,e),function(){this.getNextLineIndent=function(a,b,c){var d=this.$getIndent(b),e=this.$tokenizer.getLineTokens(b,a),f=e.tokens;if(f.length&&f[f.length-1].type=="comment")return d;if(a=="start"){var g=b.match(/^.*[\{\(\[]\s*$/);g&&(d+=c)}return d},this.checkOutdent=function(a,b,c){return this.$outdent.checkOutdent(b,c)},this.autoOutdent=function(a,b,c){this.$outdent.autoOutdent(b,c)},this.createWorker=function(a){return null}}.call(k.prototype),b.Mode=k}),define("ace/mode/csharp_highlight_rules",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/mode/doc_comment_highlight_rules","ace/mode/text_highlight_rules"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("../lib/lang"),f=a("./doc_comment_highlight_rules").DocCommentHighlightRules,g=a("./text_highlight_rules").TextHighlightRules,h=function(){var a=e.arrayToMap("abstract|event|new|struct|as|explicit|null|switch|base|extern|object|this|bool|false|operator|throw|break|finally|out|true|byte|fixed|override|try|case|float|params|typeof|catch|for|private|uint|char|foreach|protected|ulong|checked|goto|public|unchecked|class|if|readonly|unsafe|const|implicit|ref|ushort|continue|in|return|using|decimal|int|sbyte|virtual|default|interface|sealed|volatile|delegate|internal|short|void|do|is|sizeof|while|double|lock|stackalloc|else|long|static|enum|namespace|string|var|dynamic".split("|")),b=e.arrayToMap("null|true|false".split("|"));this.$rules={start:[{token:"comment",regex:"\\/\\/.*$"},(new f).getStartRule("doc-start"),{token:"comment",regex:"\\/\\*",merge:!0,next:"comment"},{token:"string.regexp",regex:"[/](?:(?:\\[(?:\\\\]|[^\\]])+\\])|(?:\\\\/|[^\\]/]))*[/]\\w*\\s*(?=[).,;]|$)"},{token:"string",regex:'["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'},{token:"string",regex:"['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"},{token:"constant.numeric",regex:"0[xX][0-9a-fA-F]+\\b"},{token:"constant.numeric",regex:"[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"},{token:"constant.language.boolean",regex:"(?:true|false)\\b"},{token:function(c){return c=="this"?"variable.language":a.hasOwnProperty(c)?"keyword":b.hasOwnProperty(c)?"constant.language":"identifier"},regex:"[a-zA-Z_$][a-zA-Z0-9_$]*\\b"},{token:"keyword.operator",regex:"!|\\$|%|&|\\*|\\-\\-|\\-|\\+\\+|\\+|~|===|==|=|!=|!==|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\\|\\||\\?\\:|\\*=|%=|\\+=|\\-=|&=|\\^=|\\b(?:in|instanceof|new|delete|typeof|void)"},{token:"punctuation.operator",regex:"\\?|\\:|\\,|\\;|\\."},{token:"paren.lparen",regex:"[[({]"},{token:"paren.rparen",regex:"[\\])}]"},{token:"text",regex:"\\s+"}],comment:[{token:"comment",regex:".*?\\*\\/",next:"start"},{token:"comment",merge:!0,regex:".+"}]},this.embedRules(f,"doc-",[(new f).getEndRule("start")])};d.inherits(h,g),b.CSharpHighlightRules=h}),define("ace/mode/doc_comment_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("./text_highlight_rules").TextHighlightRules,f=function(){this.$rules={start:[{token:"comment.doc.tag",regex:"@[\\w\\d_]+"},{token:"comment.doc",merge:!0,regex:"\\s+"},{token:"comment.doc",merge:!0,regex:"TODO"},{token:"comment.doc",merge:!0,regex:"[^@\\*]+"},{token:"comment.doc",merge:!0,regex:"."}]}};d.inherits(f,e),function(){this.getStartRule=function(a){return{token:"comment.doc",merge:!0,regex:"\\/\\*(?=\\*)",next:a}},this.getEndRule=function(a){return{token:"comment.doc",merge:!0,regex:"\\*\\/",next:a}}}.call(f.prototype),b.DocCommentHighlightRules=f}),define("ace/mode/matching_brace_outdent",["require","exports","module","ace/range"],function(a,b,c){"use strict";var d=a("../range").Range,e=function(){};(function(){this.checkOutdent=function(a,b){return/^\s+$/.test(a)?/^\s*\}/.test(b):!1},this.autoOutdent=function(a,b){var c=a.getLine(b),e=c.match(/^(\s*\})/);if(!e)return 0;var f=e[1].length,g=a.findMatchingBracket({row:b,column:f});if(!g||g.row==b)return 0;var h=this.$getIndent(a.getLine(g.row));a.replace(new d(b,0,b,f-1),h)},this.$getIndent=function(a){var b=a.match(/^(\s+)/);return b?b[1]:""}}).call(e.prototype),b.MatchingBraceOutdent=e}),define("ace/mode/behaviour/cstyle",["require","exports","module","ace/lib/oop","ace/mode/behaviour"],function(a,b,c){"use strict";var d=a("../../lib/oop"),e=a("../behaviour").Behaviour,f=function(){this.add("braces","insertion",function(a,b,c,d,e){if(e=="{"){var f=c.getSelectionRange(),g=d.doc.getTextRange(f);return g!==""?{text:"{"+g+"}",selection:!1}:{text:"{}",selection:[1,1]}}if(e=="}"){var h=c.getCursorPosition(),i=d.doc.getLine(h.row),j=i.substring(h.column,h.column+1);if(j=="}"){var k=d.$findOpeningBracket("}",{column:h.column+1,row:h.row});if(k!==null)return{text:"",selection:[1,1]}}}else if(e=="\n"){var h=c.getCursorPosition(),i=d.doc.getLine(h.row),j=i.substring(h.column,h.column+1);if(j=="}"){var l=d.findMatchingBracket({row:h.row,column:h.column+1});if(!l)return null;var m=this.getNextLineIndent(a,i.substring(0,i.length-1),d.getTabString()),n=this.$getIndent(d.doc.getLine(l.row));return{text:"\n"+m+"\n"+n,selection:[1,m.length,1,m.length]}}}}),this.add("braces","deletion",function(a,b,c,d,e){var f=d.doc.getTextRange(e);if(!e.isMultiLine()&&f=="{"){var g=d.doc.getLine(e.start.row),h=g.substring(e.end.column,e.end.column+1);if(h=="}")return e.end.column++,e}}),this.add("parens","insertion",function(a,b,c,d,e){if(e=="("){var f=c.getSelectionRange(),g=d.doc.getTextRange(f);return g!==""?{text:"("+g+")",selection:!1}:{text:"()",selection:[1,1]}}if(e==")"){var h=c.getCursorPosition(),i=d.doc.getLine(h.row),j=i.substring(h.column,h.column+1);if(j==")"){var k=d.$findOpeningBracket(")",{column:h.column+1,row:h.row});if(k!==null)return{text:"",selection:[1,1]}}}}),this.add("parens","deletion",function(a,b,c,d,e){var f=d.doc.getTextRange(e);if(!e.isMultiLine()&&f=="("){var g=d.doc.getLine(e.start.row),h=g.substring(e.start.column+1,e.start.column+2);if(h==")")return e.end.column++,e}}),this.add("string_dquotes","insertion",function(a,b,c,d,e){if(e=='"'||e=="'"){var f=e,g=c.getSelectionRange(),h=d.doc.getTextRange(g);if(h!=="")return{text:f+h+f,selection:!1};var i=c.getCursorPosition(),j=d.doc.getLine(i.row),k=j.substring(i.column-1,i.column);if(k=="\\")return null;var l=d.getTokens(g.start.row,g.start.row)[0].tokens,m=0,n,o=-1;for(var p=0;p<l.length;p++){n=l[p],n.type=="string"?o=-1:o<0&&(o=n.value.indexOf(f));if(n.value.length+m>g.start.column)break;m+=l[p].value.length}if(!n||o<0&&n.type!=="comment"&&(n.type!=="string"||g.start.column!==n.value.length+m-1&&n.value.lastIndexOf(f)===n.value.length-1))return{text:f+f,selection:[1,1]};if(n&&n.type==="string"){var q=j.substring(i.column,i.column+1);if(q==f)return{text:"",selection:[1,1]}}}}),this.add("string_dquotes","deletion",function(a,b,c,d,e){var f=d.doc.getTextRange(e);if(!e.isMultiLine()&&(f=='"'||f=="'")){var g=d.doc.getLine(e.start.row),h=g.substring(e.start.column+1,e.start.column+2);if(h=='"')return e.end.column++,e}})};d.inherits(f,e),b.CstyleBehaviour=f}),define("ace/mode/folding/cstyle",["require","exports","module","ace/lib/oop","ace/range","ace/mode/folding/fold_mode"],function(a,b,c){"use strict";var d=a("../../lib/oop"),e=a("../../range").Range,f=a("./fold_mode").FoldMode,g=b.FoldMode=function(){};d.inherits(g,f),function(){this.foldingStartMarker=/(\{|\[)[^\}\]]*$|^\s*(\/\*)/,this.foldingStopMarker=/^[^\[\{]*(\}|\])|^[\s\*]*(\*\/)/,this.getFoldWidgetRange=function(a,b,c){var d=a.getLine(c),f=d.match(this.foldingStartMarker);if(f){var g=f.index;if(f[1])return this.openingBracketBlock(a,f[1],c,g);var h=a.getCommentFoldRange(c,g+f[0].length);return h.end.column-=2,h}if(b!=="markbeginend")return;var f=d.match(this.foldingStopMarker);if(f){var g=f.index+f[0].length;if(f[2]){var h=a.getCommentFoldRange(c,g);return h.end.column-=2,h}var i={row:c,column:g},j=a.$findOpeningBracket(f[1],i);if(!j)return;return j.column++,i.column--,e.fromPoints(j,i)}}}.call(g.prototype)}),define("ace/mode/folding/fold_mode",["require","exports","module","ace/range"],function(a,b,c){"use strict";var d=a("../../range").Range,e=b.FoldMode=function(){};(function(){this.foldingStartMarker=null,this.foldingStopMarker=null,this.getFoldWidget=function(a,b,c){var d=a.getLine(c);return this.foldingStartMarker.test(d)?"start":b=="markbeginend"&&this.foldingStopMarker&&this.foldingStopMarker.test(d)?"end":""},this.getFoldWidgetRange=function(a,b,c){return null},this.indentationBlock=function(a,b,c){var e=/^\s*/,f=b,g=b,h=a.getLine(b),i=c||h.length,j=h.match(e)[0].length,k=a.getLength();while(++b<k){h=a.getLine(b);var l=h.match(e)[0].length;if(l==h.length)continue;if(l<=j)break;g=b}if(g>f){var m=a.getLine(g).length;return new d(f,i,g,m)}},this.openingBracketBlock=function(a,b,c,e){var f={row:c,column:e+1},g=a.$findClosingBracket(b,f);if(!g)return;var h=a.foldWidgets[g.row];return h==null&&(h=this.getFoldWidget(a,g.row)),h=="start"&&(g.row--,g.column=a.getLine(g.row).length),d.fromPoints(f,g)}}).call(e.prototype)})
\ No newline at end of file
diff --git a/apps/files_texteditor/js/aceeditor/mode-css-uncompressed.js b/apps/files_texteditor/js/aceeditor/mode-css-uncompressed.js
old mode 100755
new mode 100644
index 17a7738b47778d9f5b7e8db6cda08f91ce52ad5c..44505d19b62aafa0fe844d7dcfecfec74381e166
--- a/apps/files_texteditor/js/aceeditor/mode-css-uncompressed.js
+++ b/apps/files_texteditor/js/aceeditor/mode-css-uncompressed.js
@@ -155,31 +155,7 @@ var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
 var CssHighlightRules = function() {
 
     var properties = lang.arrayToMap(
-        ("-moz-appearance|-moz-box-sizing|-webkit-box-sizing|-moz-outline-radius|-moz-transform|-webkit-transform|" +
-        "appearance|azimuth|background-attachment|background-color|background-image|" +
-        "background-origin|background-position|background-repeat|background|border-bottom-color|" +
-        "border-bottom-style|border-bottom-width|border-bottom|border-collapse|" +
-        "border-color|border-left-color|border-left-style|border-left-width|" +
-        "border-left|border-right-color|border-right-style|border-right-width|" +
-        "border-right|border-spacing|border-style|border-top-color|" +
-        "border-top-style|border-top-width|border-top|border-width|border|" +
-        "bottom|box-sizing|caption-side|clear|clip|color|content|counter-increment|" +
-        "counter-reset|cue-after|cue-before|cue|cursor|direction|display|" +
-        "elevation|empty-cells|float|font-family|font-size-adjust|font-size|" +
-        "font-stretch|font-style|font-variant|font-weight|font|height|left|" +
-        "letter-spacing|line-height|list-style-image|list-style-position|" +
-        "list-style-type|list-style|margin-bottom|margin-left|margin-right|" +
-        "margin-top|marker-offset|margin|marks|max-height|max-width|min-height|" +
-        "min-width|-moz-border-radius|opacity|orphans|outline-color|outline-offset|outline-radius|" +
-        "outline-style|outline-width|outline|overflow|overflow-x|overflow-y|padding-bottom|" +
-        "padding-left|padding-right|padding-top|padding|page-break-after|" +
-        "page-break-before|page-break-inside|page|pause-after|pause-before|" +
-        "pause|pitch-range|pitch|play-during|pointer-events|position|quotes|resize|richness|right|" +
-        "size|speak-header|speak-numeral|speak-punctuation|speech-rate|speak|" +
-        "stress|table-layout|text-align|text-decoration|text-indent|" +
-        "text-shadow|text-transform|top|transform|unicode-bidi|vertical-align|" +
-        "visibility|voice-family|volume|white-space|widows|width|word-spacing|" +
-        "z-index").split("|")
+        ("animation-fill-mode|alignment-adjust|alignment-baseline|animation-delay|animation-direction|animation-duration|animation-iteration-count|animation-name|animation-play-state|animation-timing-function|animation|appearance|azimuth|backface-visibility|background-attachment|background-break|background-clip|background-color|background-image|background-origin|background-position|background-repeat|background-size|background|baseline-shift|binding|bleed|bookmark-label|bookmark-level|bookmark-state|bookmark-target|border-bottom|border-bottom-color|border-bottom-left-radius|border-bottom-right-radius|border-bottom-style|border-bottom-width|border-collapse|border-color|border-image|border-image-outset|border-image-repeat|border-image-slice|border-image-source|border-image-width|border-left|border-left-color|border-left-style|border-left-width|border-radius|border-right|border-right-color|border-right-style|border-right-width|border-spacing|border-style|border-top|border-top-color|border-top-left-radius|border-top-right-radius|border-top-style|border-top-width|border-width|border|bottom|box-align|box-decoration-break|box-direction|box-flex-group|box-flex|box-lines|box-ordinal-group|box-orient|box-pack|box-shadow|box-sizing|break-after|break-before|break-inside|caption-side|clear|clip|color-profile|color|column-count|column-fill|column-gap|column-rule|column-rule-color|column-rule-style|column-rule-width|column-span|column-width|columns|content|counter-increment|counter-reset|crop|cue-after|cue-before|cue|cursor|direction|display|dominant-baseline|drop-initial-after-adjust|drop-initial-after-align|drop-initial-before-adjust|drop-initial-before-align|drop-initial-size|drop-initial-value|elevation|empty-cells|fit|fit-position|float-offset|float|font-family|font-size|font-size-adjust|font-stretch|font-style|font-variant|font-weight|font|grid-columns|grid-rows|hanging-punctuation|height|hyphenate-after|hyphenate-before|hyphenate-character|hyphenate-lines|hyphenate-resource|hyphens|icon|image-orientation|image-rendering|image-resolution|inline-box-align|left|letter-spacing|line-height|line-stacking-ruby|line-stacking-shift|line-stacking-strategy|line-stacking|list-style-image|list-style-position|list-style-type|list-style|margin-bottom|margin-left|margin-right|margin-top|margin|mark-after|mark-before|mark|marks|marquee-direction|marquee-play-count|marquee-speed|marquee-style|max-height|max-width|min-height|min-width|move-to|nav-down|nav-index|nav-left|nav-right|nav-up|opacity|orphans|outline-color|outline-offset|outline-style|outline-width|outline|overflow-style|overflow-x|overflow-y|overflow|padding-bottom|padding-left|padding-right|padding-top|padding|page-break-after|page-break-before|page-break-inside|page-policy|page|pause-after|pause-before|pause|perspective-origin|perspective|phonemes|pitch-range|pitch|play-during|position|presentation-level|punctuation-trim|quotes|rendering-intent|resize|rest-after|rest-before|rest|richness|right|rotation-point|rotation|ruby-align|ruby-overhang|ruby-position|ruby-span|size|speak-header|speak-numeral|speak-punctuation|speak|speech-rate|stress|string-set|table-layout|target-name|target-new|target-position|target|text-align-last|text-align|text-decoration|text-emphasis|text-height|text-indent|text-justify|text-outline|text-shadow|text-transform|text-wrap|top|transform-origin|transform-style|transform|transition-delay|transition-duration|transition-property|transition-timing-function|transition|unicode-bidi|vertical-align|visibility|voice-balance|voice-duration|voice-family|voice-pitch-range|voice-pitch|voice-rate|voice-stress|voice-volume|volume|white-space-collapse|white-space|widows|width|word-break|word-spacing|word-wrap|z-index").split("|")
     );
 
     var functions = lang.arrayToMap(
@@ -187,27 +163,7 @@ var CssHighlightRules = function() {
     );
 
     var constants = lang.arrayToMap(
-        ("absolute|all-scroll|always|armenian|auto|baseline|below|bidi-override|" +
-        "block|bold|bolder|border-box|both|bottom|break-all|break-word|capitalize|center|" +
-        "char|circle|cjk-ideographic|col-resize|collapse|content-box|crosshair|dashed|" +
-        "decimal-leading-zero|decimal|default|disabled|disc|" +
-        "distribute-all-lines|distribute-letter|distribute-space|" +
-        "distribute|dotted|double|e-resize|ellipsis|fixed|georgian|groove|" +
-        "hand|hebrew|help|hidden|hiragana-iroha|hiragana|horizontal|" +
-        "ideograph-alpha|ideograph-numeric|ideograph-parenthesis|" +
-        "ideograph-space|inactive|inherit|inline-block|inline|inset|inside|" +
-        "inter-ideograph|inter-word|italic|justify|katakana-iroha|katakana|" +
-        "keep-all|left|lighter|line-edge|line-through|line|list-item|loose|" +
-        "lower-alpha|lower-greek|lower-latin|lower-roman|lowercase|lr-tb|ltr|" +
-        "medium|middle|move|n-resize|ne-resize|newspaper|no-drop|no-repeat|" +
-        "nw-resize|none|normal|not-allowed|nowrap|oblique|outset|outside|" +
-        "overline|pointer|progress|relative|repeat-x|repeat-y|repeat|right|" +
-        "ridge|row-resize|rtl|s-resize|scroll|se-resize|separate|small-caps|" +
-        "solid|square|static|strict|super|sw-resize|table-footer-group|" +
-        "table-header-group|tb-rl|text-bottom|text-top|text|thick|thin|top|" +
-        "transparent|underline|upper-alpha|upper-latin|upper-roman|uppercase|" +
-        "vertical-ideographic|vertical-text|visible|w-resize|wait|whitespace|" +
-        "zero").split("|")
+        ("absolute|after-edge|after|all-scroll|all|alphabetic|always|antialiased|armenian|auto|avoid-column|avoid-page|avoid|balance|baseline|before-edge|before|below|bidi-override|block-line-height|block|bold|bolder|border-box|both|bottom|box|break-all|break-word|capitalize|caps-height|caption|center|central|char|circle|cjk-ideographic|clone|close-quote|col-resize|collapse|column|consider-shifts|contain|content-box|cover|crosshair|cubic-bezier|dashed|decimal-leading-zero|decimal|default|disabled|disc|disregard-shifts|distribute-all-lines|distribute-letter|distribute-space|distribute|dotted|double|e-resize|ease-in|ease-in-out|ease-out|ease|ellipsis|end|exclude-ruby|fill|fixed|font-size|font|georgian|glyphs|grid-height|groove|hand|hanging|hebrew|help|hidden|hiragana-iroha|hiragana|horizontal|icon|ideograph-alpha|ideograph-numeric|ideograph-parenthesis|ideograph-space|ideographic|inactive|include-ruby|inherit|initial|inline-block|inline-box|inline-line-height|inline-table|inline|inset|inside|inter-ideograph|inter-word|invert|italic|justify|katakana-iroha|katakana|keep-all|last|left|lighter|line-edge|line-through|line|linear|list-item|local|loose|lower-alpha|lower-greek|lower-latin|lower-roman|lowercase|lr-tb|ltr|mathematical|max-height|max-size|medium|menu|message-box|middle|move|n-resize|ne-resize|newspaper|no-change|no-close-quote|no-drop|no-open-quote|no-repeat|none|normal|not-allowed|nowrap|nw-resize|oblique|open-quote|outset|outside|overline|padding-box|page|pointer|pre-line|pre-wrap|pre|preserve-3d|progress|relative|repeat-x|repeat-y|repeat|replaced|reset-size|ridge|right|round|row-resize|rtl|s-resize|scroll|se-resize|separate|slice|small-caps|small-caption|solid|space|square|start|static|status-bar|step-end|step-start|steps|stretch|strict|sub|super|sw-resize|table-caption|table-cell|table-column-group|table-column|table-footer-group|table-header-group|table-row-group|table-row|table|tb-rl|text-after-edge|text-before-edge|text-bottom|text-size|text-top|text|thick|thin|top|transparent|underline|upper-alpha|upper-latin|upper-roman|uppercase|use-script|vertical-ideographic|vertical-text|visible|w-resize|wait|whitespace|z-index|zero").split("|")
     );
 
     var colors = lang.arrayToMap(
@@ -215,32 +171,49 @@ var CssHighlightRules = function() {
         "purple|red|silver|teal|white|yellow").split("|")
     );
 
+    var fonts = lang.arrayToMap(
+        ("arial|century|comic|courier|garamond|georgia|helvetica|impact|lucida|" +
+        "symbol|system|tahoma|times|trebuchet|utopia|verdana|webdings|sans-serif|" +
+        "serif|monospace").split("|")
+    );
+    
     // regexp must not have capturing parentheses. Use (?:) instead.
     // regexps are ordered -> the first match is used
 
     var numRe = "\\-?(?:(?:[0-9]+)|(?:[0-9]*\\.[0-9]+))";
-
+    var pseudoElements = "(\\:+)\\b(after|before|first-letter|first-line|moz-selection|selection)\\b";
+    var pseudoClasses = "(:)\\b(active|checked|disabled|empty|enabled|first-child|first-of-type|focus|hover|indeterminate|invalid|last-child|last-of-type|link|not|nth-child|nth-last-child|nth-last-of-type|nth-of-type|only-child|only-of-type|required|root|target|valid|visited)\\b";
+    
     var base_ruleset = [
         {
             token : "comment", // multi line comment
             merge : true,
             regex : "\\/\\*",
             next : "ruleset_comment"
-        },{
+        }, {
             token : "string", // single line
             regex : '["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'
         }, {
             token : "string", // single line
             regex : "['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"
         }, {
-            token : "constant.numeric",
-            regex : numRe + "(?:em|ex|px|cm|mm|in|pt|pc|deg|rad|grad|ms|s|hz|khz|%)"
+            token : ["constant.numeric", "keyword"],
+            regex : "(" + numRe + ")(ch|cm|deg|em|ex|fr|gd|grad|Hz|in|kHz|mm|ms|pc|pt|px|rad|rem|s|turn|vh|vm|vw|%)"
+        }, {
+            token : ["constant.numeric"],
+            regex : "([0-9]+)"
         }, {
             token : "constant.numeric",  // hex6 color
             regex : "#[a-f0-9]{6}"
         }, {
             token : "constant.numeric", // hex3 color
             regex : "#[a-f0-9]{3}"
+        }, {
+            token : ["punctuation", "entity.other.attribute-name.pseudo-element.css"], 
+            regex : pseudoElements
+        }, {
+            token : ["punctuation", "entity.other.attribute-name.pseudo-class.css"], 
+            regex : pseudoClasses
         }, {
             token : function(value) {
                 if (properties.hasOwnProperty(value.toLowerCase())) {
@@ -255,12 +228,15 @@ var CssHighlightRules = function() {
                 else if (colors.hasOwnProperty(value.toLowerCase())) {
                     return "support.constant.color";
                 }
+                else if (fonts.hasOwnProperty(value.toLowerCase())) {
+                    return "support.constant.fonts";
+                }
                 else {
                     return "text";
                 }
             },
             regex : "\\-?[a-zA-Z_][a-zA-Z0-9_\\-]*"
-        }
+        } 
       ];
 
     var ruleset = lang.copyArray(base_ruleset);
@@ -454,195 +430,6 @@ var MatchingBraceOutdent = function() {};
 }).call(MatchingBraceOutdent.prototype);
 
 exports.MatchingBraceOutdent = MatchingBraceOutdent;
-});
-/* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is Ajax.org Code Editor (ACE).
- *
- * The Initial Developer of the Original Code is
- * Ajax.org B.V.
- * Portions created by the Initial Developer are Copyright (C) 2010
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *      Fabian Jakobs <fabian AT ajax DOT org>
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-define('ace/worker/worker_client', ['require', 'exports', 'module' , 'ace/lib/oop', 'ace/lib/event_emitter'], function(require, exports, module) {
-"use strict";
-
-var oop = require("../lib/oop");
-var EventEmitter = require("../lib/event_emitter").EventEmitter;
-
-var WorkerClient = function(topLevelNamespaces, packagedJs, mod, classname) {
-
-    this.changeListener = this.changeListener.bind(this);
-
-    if (module.packaged) {
-        var base = this.$guessBasePath();
-        this.$worker = new Worker(base + packagedJs);
-    }
-    else {
-        var workerUrl = this.$normalizePath(require.nameToUrl("ace/worker/worker", null, "_"));
-        this.$worker = new Worker(workerUrl);
-
-        var tlns = {};
-        for (var i=0; i<topLevelNamespaces.length; i++) {
-            var ns = topLevelNamespaces[i];
-            var path = this.$normalizePath(require.nameToUrl(ns, null, "_").replace(/.js$/, ""));
-
-            tlns[ns] = path;
-        }
-    }
-
-    this.$worker.postMessage({
-        init : true,
-        tlns: tlns,
-        module: mod,
-        classname: classname
-    });
-
-    this.callbackId = 1;
-    this.callbacks = {};
-
-    var _self = this;
-    this.$worker.onerror = function(e) {
-        window.console && console.log && console.log(e);
-        throw e;
-    };
-    this.$worker.onmessage = function(e) {
-        var msg = e.data;
-        switch(msg.type) {
-            case "log":
-                window.console && console.log && console.log(msg.data);
-                break;
-
-            case "event":
-                _self._emit(msg.name, {data: msg.data});
-                break;
-
-            case "call":
-                var callback = _self.callbacks[msg.id];
-                if (callback) {
-                    callback(msg.data);
-                    delete _self.callbacks[msg.id];
-                }
-                break;
-        }
-    };
-};
-
-(function(){
-
-    oop.implement(this, EventEmitter);
-
-    this.$normalizePath = function(path) {
-        path = path.replace(/^[a-z]+:\/\/[^\/]+\//, ""); // Remove domain name and rebuild it
-        path = location.protocol + "//" + location.host
-            // paths starting with a slash are relative to the root (host)
-            + (path.charAt(0) == "/" ? "" : location.pathname.replace(/\/[^\/]*$/, ""))
-            + "/" + path.replace(/^[\/]+/, "");
-        return path;
-    };
-
-    this.$guessBasePath = function() {
-        if (require.aceBaseUrl)
-            return require.aceBaseUrl;
-
-        var scripts = document.getElementsByTagName("script");
-        for (var i=0; i<scripts.length; i++) {
-            var script = scripts[i];
-
-            var base = script.getAttribute("data-ace-base");
-            if (base)
-                return base.replace(/\/*$/, "/");
-
-            var src = script.src || script.getAttribute("src");
-            if (!src) {
-                continue;
-            }
-            var m = src.match(/^(?:(.*\/)ace\.js|(.*\/)ace(-uncompressed)?(-noconflict)?\.js)(?:\?|$)/);
-            if (m)
-                return m[1] || m[2];
-        }
-        return "";
-    };
-
-    this.terminate = function() {
-        this._emit("terminate", {});
-        this.$worker.terminate();
-        this.$worker = null;
-        this.$doc.removeEventListener("change", this.changeListener);
-        this.$doc = null;
-    };
-
-    this.send = function(cmd, args) {
-        this.$worker.postMessage({command: cmd, args: args});
-    };
-
-    this.call = function(cmd, args, callback) {
-        if (callback) {
-            var id = this.callbackId++;
-            this.callbacks[id] = callback;
-            args.push(id);
-        }
-        this.send(cmd, args);
-    };
-
-    this.emit = function(event, data) {
-        try {
-            // firefox refuses to clone objects which have function properties
-            // TODO: cleanup event
-            this.$worker.postMessage({event: event, data: {data: data.data}});
-        }
-        catch(ex) {}
-    };
-
-    this.attachToDocument = function(doc) {
-        if(this.$doc)
-            this.terminate();
-
-        this.$doc = doc;
-        this.call("setValue", [doc.getValue()]);
-        doc.on("change", this.changeListener);
-    };
-
-    this.changeListener = function(e) {
-        e.range = {
-            start: e.data.range.start,
-            end: e.data.range.end
-        };
-        this.emit("change", e);
-    };
-
-}).call(WorkerClient.prototype);
-
-exports.WorkerClient = WorkerClient;
-
 });
 /* ***** BEGIN LICENSE BLOCK *****
  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
@@ -851,13 +638,3 @@ var FoldMode = exports.FoldMode = function() {};
 }).call(FoldMode.prototype);
 
 });
-;
-            (function() {
-                window.require(["ace/ace"], function(a) {
-                    if (!window.ace)
-                        window.ace = {};
-                    for (var key in a) if (a.hasOwnProperty(key))
-                        ace[key] = a[key];
-                });
-            })();
-        
\ No newline at end of file
diff --git a/apps/files_texteditor/js/aceeditor/mode-css.js b/apps/files_texteditor/js/aceeditor/mode-css.js
index 0a6f1bde58d435f24f8d4803a4ad3665ff37fa88..16e482516e25097fced44c8dd76562f5fa9a3ba8 100644
--- a/apps/files_texteditor/js/aceeditor/mode-css.js
+++ b/apps/files_texteditor/js/aceeditor/mode-css.js
@@ -1 +1 @@
-define("ace/mode/css",["require","exports","module","ace/lib/oop","ace/mode/text","ace/tokenizer","ace/mode/css_highlight_rules","ace/mode/matching_brace_outdent","ace/worker/worker_client","ace/mode/folding/cstyle"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("./text").Mode,f=a("../tokenizer").Tokenizer,g=a("./css_highlight_rules").CssHighlightRules,h=a("./matching_brace_outdent").MatchingBraceOutdent,i=a("../worker/worker_client").WorkerClient,j=a("./folding/cstyle").FoldMode,k=function(){this.$tokenizer=new f((new g).getRules(),"i"),this.$outdent=new h,this.foldingRules=new j};d.inherits(k,e),function(){this.foldingRules="cStyle",this.getNextLineIndent=function(a,b,c){var d=this.$getIndent(b),e=this.$tokenizer.getLineTokens(b,a).tokens;if(e.length&&e[e.length-1].type=="comment")return d;var f=b.match(/^.*\{\s*$/);return f&&(d+=c),d},this.checkOutdent=function(a,b,c){return this.$outdent.checkOutdent(b,c)},this.autoOutdent=function(a,b,c){this.$outdent.autoOutdent(b,c)},this.createWorker=function(a){var b=new i(["ace"],"worker-css.js","ace/mode/css_worker","Worker");return b.attachToDocument(a.getDocument()),b.on("csslint",function(b){var c=[];b.data.forEach(function(a){c.push({row:a.line-1,column:a.col-1,text:a.message,type:a.type,lint:a})}),a.setAnnotations(c)}),b}}.call(k.prototype),b.Mode=k}),define("ace/mode/css_highlight_rules",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/mode/text_highlight_rules"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("../lib/lang"),f=a("./text_highlight_rules").TextHighlightRules,g=function(){var a=e.arrayToMap("-moz-appearance|-moz-box-sizing|-webkit-box-sizing|-moz-outline-radius|-moz-transform|-webkit-transform|appearance|azimuth|background-attachment|background-color|background-image|background-origin|background-position|background-repeat|background|border-bottom-color|border-bottom-style|border-bottom-width|border-bottom|border-collapse|border-color|border-left-color|border-left-style|border-left-width|border-left|border-right-color|border-right-style|border-right-width|border-right|border-spacing|border-style|border-top-color|border-top-style|border-top-width|border-top|border-width|border|bottom|box-sizing|caption-side|clear|clip|color|content|counter-increment|counter-reset|cue-after|cue-before|cue|cursor|direction|display|elevation|empty-cells|float|font-family|font-size-adjust|font-size|font-stretch|font-style|font-variant|font-weight|font|height|left|letter-spacing|line-height|list-style-image|list-style-position|list-style-type|list-style|margin-bottom|margin-left|margin-right|margin-top|marker-offset|margin|marks|max-height|max-width|min-height|min-width|-moz-border-radius|opacity|orphans|outline-color|outline-offset|outline-radius|outline-style|outline-width|outline|overflow|overflow-x|overflow-y|padding-bottom|padding-left|padding-right|padding-top|padding|page-break-after|page-break-before|page-break-inside|page|pause-after|pause-before|pause|pitch-range|pitch|play-during|pointer-events|position|quotes|resize|richness|right|size|speak-header|speak-numeral|speak-punctuation|speech-rate|speak|stress|table-layout|text-align|text-decoration|text-indent|text-shadow|text-transform|top|transform|unicode-bidi|vertical-align|visibility|voice-family|volume|white-space|widows|width|word-spacing|z-index".split("|")),b=e.arrayToMap("rgb|rgba|url|attr|counter|counters".split("|")),c=e.arrayToMap("absolute|all-scroll|always|armenian|auto|baseline|below|bidi-override|block|bold|bolder|border-box|both|bottom|break-all|break-word|capitalize|center|char|circle|cjk-ideographic|col-resize|collapse|content-box|crosshair|dashed|decimal-leading-zero|decimal|default|disabled|disc|distribute-all-lines|distribute-letter|distribute-space|distribute|dotted|double|e-resize|ellipsis|fixed|georgian|groove|hand|hebrew|help|hidden|hiragana-iroha|hiragana|horizontal|ideograph-alpha|ideograph-numeric|ideograph-parenthesis|ideograph-space|inactive|inherit|inline-block|inline|inset|inside|inter-ideograph|inter-word|italic|justify|katakana-iroha|katakana|keep-all|left|lighter|line-edge|line-through|line|list-item|loose|lower-alpha|lower-greek|lower-latin|lower-roman|lowercase|lr-tb|ltr|medium|middle|move|n-resize|ne-resize|newspaper|no-drop|no-repeat|nw-resize|none|normal|not-allowed|nowrap|oblique|outset|outside|overline|pointer|progress|relative|repeat-x|repeat-y|repeat|right|ridge|row-resize|rtl|s-resize|scroll|se-resize|separate|small-caps|solid|square|static|strict|super|sw-resize|table-footer-group|table-header-group|tb-rl|text-bottom|text-top|text|thick|thin|top|transparent|underline|upper-alpha|upper-latin|upper-roman|uppercase|vertical-ideographic|vertical-text|visible|w-resize|wait|whitespace|zero".split("|")),d=e.arrayToMap("aqua|black|blue|fuchsia|gray|green|lime|maroon|navy|olive|orange|purple|red|silver|teal|white|yellow".split("|")),f="\\-?(?:(?:[0-9]+)|(?:[0-9]*\\.[0-9]+))",g=[{token:"comment",merge:!0,regex:"\\/\\*",next:"ruleset_comment"},{token:"string",regex:'["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'},{token:"string",regex:"['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"},{token:"constant.numeric",regex:f+"(?:em|ex|px|cm|mm|in|pt|pc|deg|rad|grad|ms|s|hz|khz|%)"},{token:"constant.numeric",regex:"#[a-f0-9]{6}"},{token:"constant.numeric",regex:"#[a-f0-9]{3}"},{token:function(e){return a.hasOwnProperty(e.toLowerCase())?"support.type":b.hasOwnProperty(e.toLowerCase())?"support.function":c.hasOwnProperty(e.toLowerCase())?"support.constant":d.hasOwnProperty(e.toLowerCase())?"support.constant.color":"text"},regex:"\\-?[a-zA-Z_][a-zA-Z0-9_\\-]*"}],h=e.copyArray(g);h.unshift({token:"paren.rparen",regex:"\\}",next:"start"});var i=e.copyArray(g);i.unshift({token:"paren.rparen",regex:"\\}",next:"media"});var j=[{token:"comment",merge:!0,regex:".+"}],k=e.copyArray(j);k.unshift({token:"comment",regex:".*?\\*\\/",next:"start"});var l=e.copyArray(j);l.unshift({token:"comment",regex:".*?\\*\\/",next:"media"});var m=e.copyArray(j);m.unshift({token:"comment",regex:".*?\\*\\/",next:"ruleset"}),this.$rules={start:[{token:"comment",merge:!0,regex:"\\/\\*",next:"comment"},{token:"paren.lparen",regex:"\\{",next:"ruleset"},{token:"string",regex:"@.*?{",next:"media"},{token:"keyword",regex:"#[a-z0-9-_]+"},{token:"variable",regex:"\\.[a-z0-9-_]+"},{token:"string",regex:":[a-z0-9-_]+"},{token:"constant",regex:"[a-z0-9-_]+"}],media:[{token:"comment",merge:!0,regex:"\\/\\*",next:"media_comment"},{token:"paren.lparen",regex:"\\{",next:"media_ruleset"},{token:"string",regex:"\\}",next:"start"},{token:"keyword",regex:"#[a-z0-9-_]+"},{token:"variable",regex:"\\.[a-z0-9-_]+"},{token:"string",regex:":[a-z0-9-_]+"},{token:"constant",regex:"[a-z0-9-_]+"}],comment:k,ruleset:h,ruleset_comment:m,media_ruleset:i,media_comment:l}};d.inherits(g,f),b.CssHighlightRules=g}),define("ace/mode/matching_brace_outdent",["require","exports","module","ace/range"],function(a,b,c){"use strict";var d=a("../range").Range,e=function(){};((function(){this.checkOutdent=function(a,b){return/^\s+$/.test(a)?/^\s*\}/.test(b):!1},this.autoOutdent=function(a,b){var c=a.getLine(b),e=c.match(/^(\s*\})/);if(!e)return 0;var f=e[1].length,g=a.findMatchingBracket({row:b,column:f});if(!g||g.row==b)return 0;var h=this.$getIndent(a.getLine(g.row));a.replace(new d(b,0,b,f-1),h)},this.$getIndent=function(a){var b=a.match(/^(\s+)/);return b?b[1]:""}})).call(e.prototype),b.MatchingBraceOutdent=e}),define("ace/worker/worker_client",["require","exports","module","ace/lib/oop","ace/lib/event_emitter"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("../lib/event_emitter").EventEmitter,f=function(b,d,e,f){this.changeListener=this.changeListener.bind(this);if(c.packaged){var g=this.$guessBasePath();this.$worker=new Worker(g+d)}else{var h=this.$normalizePath(a.nameToUrl("ace/worker/worker",null,"_"));this.$worker=new Worker(h);var i={};for(var j=0;j<b.length;j++){var k=b[j],l=this.$normalizePath(a.nameToUrl(k,null,"_").replace(/.js$/,""));i[k]=l}}this.$worker.postMessage({init:!0,tlns:i,module:e,classname:f}),this.callbackId=1,this.callbacks={};var m=this;this.$worker.onerror=function(a){throw window.console&&console.log&&console.log(a),a},this.$worker.onmessage=function(a){var b=a.data;switch(b.type){case"log":window.console&&console.log&&console.log(b.data);break;case"event":m._emit(b.name,{data:b.data});break;case"call":var c=m.callbacks[b.id];c&&(c(b.data),delete m.callbacks[b.id])}}};((function(){d.implement(this,e),this.$normalizePath=function(a){return a=a.replace(/^[a-z]+:\/\/[^\/]+\//,""),a=location.protocol+"//"+location.host+(a.charAt(0)=="/"?"":location.pathname.replace(/\/[^\/]*$/,""))+"/"+a.replace(/^[\/]+/,""),a},this.$guessBasePath=function(){if(a.aceBaseUrl)return a.aceBaseUrl;var b=document.getElementsByTagName("script");for(var c=0;c<b.length;c++){var d=b[c],e=d.getAttribute("data-ace-base");if(e)return e.replace(/\/*$/,"/");var f=d.src||d.getAttribute("src");if(!f)continue;var g=f.match(/^(?:(.*\/)ace\.js|(.*\/)ace(-uncompressed)?(-noconflict)?\.js)(?:\?|$)/);if(g)return g[1]||g[2]}return""},this.terminate=function(){this._emit("terminate",{}),this.$worker.terminate(),this.$worker=null,this.$doc.removeEventListener("change",this.changeListener),this.$doc=null},this.send=function(a,b){this.$worker.postMessage({command:a,args:b})},this.call=function(a,b,c){if(c){var d=this.callbackId++;this.callbacks[d]=c,b.push(d)}this.send(a,b)},this.emit=function(a,b){try{this.$worker.postMessage({event:a,data:{data:b.data}})}catch(c){}},this.attachToDocument=function(a){this.$doc&&this.terminate(),this.$doc=a,this.call("setValue",[a.getValue()]),a.on("change",this.changeListener)},this.changeListener=function(a){a.range={start:a.data.range.start,end:a.data.range.end},this.emit("change",a)}})).call(f.prototype),b.WorkerClient=f}),define("ace/mode/folding/cstyle",["require","exports","module","ace/lib/oop","ace/range","ace/mode/folding/fold_mode"],function(a,b,c){"use strict";var d=a("../../lib/oop"),e=a("../../range").Range,f=a("./fold_mode").FoldMode,g=b.FoldMode=function(){};d.inherits(g,f),function(){this.foldingStartMarker=/(\{|\[)[^\}\]]*$|^\s*(\/\*)/,this.foldingStopMarker=/^[^\[\{]*(\}|\])|^[\s\*]*(\*\/)/,this.getFoldWidgetRange=function(a,b,c){var d=a.getLine(c),f=d.match(this.foldingStartMarker);if(f){var g=f.index;if(f[1])return this.openingBracketBlock(a,f[1],c,g);var h=a.getCommentFoldRange(c,g+f[0].length);return h.end.column-=2,h}if(b!=="markbeginend")return;var f=d.match(this.foldingStopMarker);if(f){var g=f.index+f[0].length;if(f[2]){var h=a.getCommentFoldRange(c,g);return h.end.column-=2,h}var i={row:c,column:g},j=a.$findOpeningBracket(f[1],i);if(!j)return;return j.column++,i.column--,e.fromPoints(j,i)}}}.call(g.prototype)}),define("ace/mode/folding/fold_mode",["require","exports","module","ace/range"],function(a,b,c){"use strict";var d=a("../../range").Range,e=b.FoldMode=function(){};((function(){this.foldingStartMarker=null,this.foldingStopMarker=null,this.getFoldWidget=function(a,b,c){var d=a.getLine(c);return this.foldingStartMarker.test(d)?"start":b=="markbeginend"&&this.foldingStopMarker&&this.foldingStopMarker.test(d)?"end":""},this.getFoldWidgetRange=function(a,b,c){return null},this.indentationBlock=function(a,b,c){var e=/^\s*/,f=b,g=b,h=a.getLine(b),i=c||h.length,j=h.match(e)[0].length,k=a.getLength();while(++b<k){h=a.getLine(b);var l=h.match(e)[0].length;if(l==h.length)continue;if(l<=j)break;g=b}if(g>f){var m=a.getLine(g).length;return new d(f,i,g,m)}},this.openingBracketBlock=function(a,b,c,e){var f={row:c,column:e+1},g=a.$findClosingBracket(b,f);if(!g)return;var h=a.foldWidgets[g.row];return h==null&&(h=this.getFoldWidget(a,g.row)),h=="start"&&(g.row--,g.column=a.getLine(g.row).length),d.fromPoints(f,g)}})).call(e.prototype)}),function(){window.require(["ace/ace"],function(a){window.ace||(window.ace={});for(var b in a)a.hasOwnProperty(b)&&(ace[b]=a[b])})}()
\ No newline at end of file
+define("ace/mode/css",["require","exports","module","ace/lib/oop","ace/mode/text","ace/tokenizer","ace/mode/css_highlight_rules","ace/mode/matching_brace_outdent","ace/worker/worker_client","ace/mode/folding/cstyle"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("./text").Mode,f=a("../tokenizer").Tokenizer,g=a("./css_highlight_rules").CssHighlightRules,h=a("./matching_brace_outdent").MatchingBraceOutdent,i=a("../worker/worker_client").WorkerClient,j=a("./folding/cstyle").FoldMode,k=function(){this.$tokenizer=new f((new g).getRules(),"i"),this.$outdent=new h,this.foldingRules=new j};d.inherits(k,e),function(){this.foldingRules="cStyle",this.getNextLineIndent=function(a,b,c){var d=this.$getIndent(b),e=this.$tokenizer.getLineTokens(b,a).tokens;if(e.length&&e[e.length-1].type=="comment")return d;var f=b.match(/^.*\{\s*$/);return f&&(d+=c),d},this.checkOutdent=function(a,b,c){return this.$outdent.checkOutdent(b,c)},this.autoOutdent=function(a,b,c){this.$outdent.autoOutdent(b,c)},this.createWorker=function(a){var b=new i(["ace"],"worker-css.js","ace/mode/css_worker","Worker");return b.attachToDocument(a.getDocument()),b.on("csslint",function(b){var c=[];b.data.forEach(function(a){c.push({row:a.line-1,column:a.col-1,text:a.message,type:a.type,lint:a})}),a.setAnnotations(c)}),b}}.call(k.prototype),b.Mode=k}),define("ace/mode/css_highlight_rules",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/mode/text_highlight_rules"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("../lib/lang"),f=a("./text_highlight_rules").TextHighlightRules,g=function(){var a=e.arrayToMap("animation-fill-mode|alignment-adjust|alignment-baseline|animation-delay|animation-direction|animation-duration|animation-iteration-count|animation-name|animation-play-state|animation-timing-function|animation|appearance|azimuth|backface-visibility|background-attachment|background-break|background-clip|background-color|background-image|background-origin|background-position|background-repeat|background-size|background|baseline-shift|binding|bleed|bookmark-label|bookmark-level|bookmark-state|bookmark-target|border-bottom|border-bottom-color|border-bottom-left-radius|border-bottom-right-radius|border-bottom-style|border-bottom-width|border-collapse|border-color|border-image|border-image-outset|border-image-repeat|border-image-slice|border-image-source|border-image-width|border-left|border-left-color|border-left-style|border-left-width|border-radius|border-right|border-right-color|border-right-style|border-right-width|border-spacing|border-style|border-top|border-top-color|border-top-left-radius|border-top-right-radius|border-top-style|border-top-width|border-width|border|bottom|box-align|box-decoration-break|box-direction|box-flex-group|box-flex|box-lines|box-ordinal-group|box-orient|box-pack|box-shadow|box-sizing|break-after|break-before|break-inside|caption-side|clear|clip|color-profile|color|column-count|column-fill|column-gap|column-rule|column-rule-color|column-rule-style|column-rule-width|column-span|column-width|columns|content|counter-increment|counter-reset|crop|cue-after|cue-before|cue|cursor|direction|display|dominant-baseline|drop-initial-after-adjust|drop-initial-after-align|drop-initial-before-adjust|drop-initial-before-align|drop-initial-size|drop-initial-value|elevation|empty-cells|fit|fit-position|float-offset|float|font-family|font-size|font-size-adjust|font-stretch|font-style|font-variant|font-weight|font|grid-columns|grid-rows|hanging-punctuation|height|hyphenate-after|hyphenate-before|hyphenate-character|hyphenate-lines|hyphenate-resource|hyphens|icon|image-orientation|image-rendering|image-resolution|inline-box-align|left|letter-spacing|line-height|line-stacking-ruby|line-stacking-shift|line-stacking-strategy|line-stacking|list-style-image|list-style-position|list-style-type|list-style|margin-bottom|margin-left|margin-right|margin-top|margin|mark-after|mark-before|mark|marks|marquee-direction|marquee-play-count|marquee-speed|marquee-style|max-height|max-width|min-height|min-width|move-to|nav-down|nav-index|nav-left|nav-right|nav-up|opacity|orphans|outline-color|outline-offset|outline-style|outline-width|outline|overflow-style|overflow-x|overflow-y|overflow|padding-bottom|padding-left|padding-right|padding-top|padding|page-break-after|page-break-before|page-break-inside|page-policy|page|pause-after|pause-before|pause|perspective-origin|perspective|phonemes|pitch-range|pitch|play-during|position|presentation-level|punctuation-trim|quotes|rendering-intent|resize|rest-after|rest-before|rest|richness|right|rotation-point|rotation|ruby-align|ruby-overhang|ruby-position|ruby-span|size|speak-header|speak-numeral|speak-punctuation|speak|speech-rate|stress|string-set|table-layout|target-name|target-new|target-position|target|text-align-last|text-align|text-decoration|text-emphasis|text-height|text-indent|text-justify|text-outline|text-shadow|text-transform|text-wrap|top|transform-origin|transform-style|transform|transition-delay|transition-duration|transition-property|transition-timing-function|transition|unicode-bidi|vertical-align|visibility|voice-balance|voice-duration|voice-family|voice-pitch-range|voice-pitch|voice-rate|voice-stress|voice-volume|volume|white-space-collapse|white-space|widows|width|word-break|word-spacing|word-wrap|z-index".split("|")),b=e.arrayToMap("rgb|rgba|url|attr|counter|counters".split("|")),c=e.arrayToMap("absolute|after-edge|after|all-scroll|all|alphabetic|always|antialiased|armenian|auto|avoid-column|avoid-page|avoid|balance|baseline|before-edge|before|below|bidi-override|block-line-height|block|bold|bolder|border-box|both|bottom|box|break-all|break-word|capitalize|caps-height|caption|center|central|char|circle|cjk-ideographic|clone|close-quote|col-resize|collapse|column|consider-shifts|contain|content-box|cover|crosshair|cubic-bezier|dashed|decimal-leading-zero|decimal|default|disabled|disc|disregard-shifts|distribute-all-lines|distribute-letter|distribute-space|distribute|dotted|double|e-resize|ease-in|ease-in-out|ease-out|ease|ellipsis|end|exclude-ruby|fill|fixed|font-size|font|georgian|glyphs|grid-height|groove|hand|hanging|hebrew|help|hidden|hiragana-iroha|hiragana|horizontal|icon|ideograph-alpha|ideograph-numeric|ideograph-parenthesis|ideograph-space|ideographic|inactive|include-ruby|inherit|initial|inline-block|inline-box|inline-line-height|inline-table|inline|inset|inside|inter-ideograph|inter-word|invert|italic|justify|katakana-iroha|katakana|keep-all|last|left|lighter|line-edge|line-through|line|linear|list-item|local|loose|lower-alpha|lower-greek|lower-latin|lower-roman|lowercase|lr-tb|ltr|mathematical|max-height|max-size|medium|menu|message-box|middle|move|n-resize|ne-resize|newspaper|no-change|no-close-quote|no-drop|no-open-quote|no-repeat|none|normal|not-allowed|nowrap|nw-resize|oblique|open-quote|outset|outside|overline|padding-box|page|pointer|pre-line|pre-wrap|pre|preserve-3d|progress|relative|repeat-x|repeat-y|repeat|replaced|reset-size|ridge|right|round|row-resize|rtl|s-resize|scroll|se-resize|separate|slice|small-caps|small-caption|solid|space|square|start|static|status-bar|step-end|step-start|steps|stretch|strict|sub|super|sw-resize|table-caption|table-cell|table-column-group|table-column|table-footer-group|table-header-group|table-row-group|table-row|table|tb-rl|text-after-edge|text-before-edge|text-bottom|text-size|text-top|text|thick|thin|top|transparent|underline|upper-alpha|upper-latin|upper-roman|uppercase|use-script|vertical-ideographic|vertical-text|visible|w-resize|wait|whitespace|z-index|zero".split("|")),d=e.arrayToMap("aqua|black|blue|fuchsia|gray|green|lime|maroon|navy|olive|orange|purple|red|silver|teal|white|yellow".split("|")),f=e.arrayToMap("arial|century|comic|courier|garamond|georgia|helvetica|impact|lucida|symbol|system|tahoma|times|trebuchet|utopia|verdana|webdings|sans-serif|serif|monospace".split("|")),g="\\-?(?:(?:[0-9]+)|(?:[0-9]*\\.[0-9]+))",h="(\\:+)\\b(after|before|first-letter|first-line|moz-selection|selection)\\b",i="(:)\\b(active|checked|disabled|empty|enabled|first-child|first-of-type|focus|hover|indeterminate|invalid|last-child|last-of-type|link|not|nth-child|nth-last-child|nth-last-of-type|nth-of-type|only-child|only-of-type|required|root|target|valid|visited)\\b",j=[{token:"comment",merge:!0,regex:"\\/\\*",next:"ruleset_comment"},{token:"string",regex:'["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'},{token:"string",regex:"['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"},{token:["constant.numeric","keyword"],regex:"("+g+")(ch|cm|deg|em|ex|fr|gd|grad|Hz|in|kHz|mm|ms|pc|pt|px|rad|rem|s|turn|vh|vm|vw|%)"},{token:["constant.numeric"],regex:"([0-9]+)"},{token:"constant.numeric",regex:"#[a-f0-9]{6}"},{token:"constant.numeric",regex:"#[a-f0-9]{3}"},{token:["punctuation","entity.other.attribute-name.pseudo-element.css"],regex:h},{token:["punctuation","entity.other.attribute-name.pseudo-class.css"],regex:i},{token:function(e){return a.hasOwnProperty(e.toLowerCase())?"support.type":b.hasOwnProperty(e.toLowerCase())?"support.function":c.hasOwnProperty(e.toLowerCase())?"support.constant":d.hasOwnProperty(e.toLowerCase())?"support.constant.color":f.hasOwnProperty(e.toLowerCase())?"support.constant.fonts":"text"},regex:"\\-?[a-zA-Z_][a-zA-Z0-9_\\-]*"}],k=e.copyArray(j);k.unshift({token:"paren.rparen",regex:"\\}",next:"start"});var l=e.copyArray(j);l.unshift({token:"paren.rparen",regex:"\\}",next:"media"});var m=[{token:"comment",merge:!0,regex:".+"}],n=e.copyArray(m);n.unshift({token:"comment",regex:".*?\\*\\/",next:"start"});var o=e.copyArray(m);o.unshift({token:"comment",regex:".*?\\*\\/",next:"media"});var p=e.copyArray(m);p.unshift({token:"comment",regex:".*?\\*\\/",next:"ruleset"}),this.$rules={start:[{token:"comment",merge:!0,regex:"\\/\\*",next:"comment"},{token:"paren.lparen",regex:"\\{",next:"ruleset"},{token:"string",regex:"@.*?{",next:"media"},{token:"keyword",regex:"#[a-z0-9-_]+"},{token:"variable",regex:"\\.[a-z0-9-_]+"},{token:"string",regex:":[a-z0-9-_]+"},{token:"constant",regex:"[a-z0-9-_]+"}],media:[{token:"comment",merge:!0,regex:"\\/\\*",next:"media_comment"},{token:"paren.lparen",regex:"\\{",next:"media_ruleset"},{token:"string",regex:"\\}",next:"start"},{token:"keyword",regex:"#[a-z0-9-_]+"},{token:"variable",regex:"\\.[a-z0-9-_]+"},{token:"string",regex:":[a-z0-9-_]+"},{token:"constant",regex:"[a-z0-9-_]+"}],comment:n,ruleset:k,ruleset_comment:p,media_ruleset:l,media_comment:o}};d.inherits(g,f),b.CssHighlightRules=g}),define("ace/mode/matching_brace_outdent",["require","exports","module","ace/range"],function(a,b,c){"use strict";var d=a("../range").Range,e=function(){};(function(){this.checkOutdent=function(a,b){return/^\s+$/.test(a)?/^\s*\}/.test(b):!1},this.autoOutdent=function(a,b){var c=a.getLine(b),e=c.match(/^(\s*\})/);if(!e)return 0;var f=e[1].length,g=a.findMatchingBracket({row:b,column:f});if(!g||g.row==b)return 0;var h=this.$getIndent(a.getLine(g.row));a.replace(new d(b,0,b,f-1),h)},this.$getIndent=function(a){var b=a.match(/^(\s+)/);return b?b[1]:""}}).call(e.prototype),b.MatchingBraceOutdent=e}),define("ace/mode/folding/cstyle",["require","exports","module","ace/lib/oop","ace/range","ace/mode/folding/fold_mode"],function(a,b,c){"use strict";var d=a("../../lib/oop"),e=a("../../range").Range,f=a("./fold_mode").FoldMode,g=b.FoldMode=function(){};d.inherits(g,f),function(){this.foldingStartMarker=/(\{|\[)[^\}\]]*$|^\s*(\/\*)/,this.foldingStopMarker=/^[^\[\{]*(\}|\])|^[\s\*]*(\*\/)/,this.getFoldWidgetRange=function(a,b,c){var d=a.getLine(c),f=d.match(this.foldingStartMarker);if(f){var g=f.index;if(f[1])return this.openingBracketBlock(a,f[1],c,g);var h=a.getCommentFoldRange(c,g+f[0].length);return h.end.column-=2,h}if(b!=="markbeginend")return;var f=d.match(this.foldingStopMarker);if(f){var g=f.index+f[0].length;if(f[2]){var h=a.getCommentFoldRange(c,g);return h.end.column-=2,h}var i={row:c,column:g},j=a.$findOpeningBracket(f[1],i);if(!j)return;return j.column++,i.column--,e.fromPoints(j,i)}}}.call(g.prototype)}),define("ace/mode/folding/fold_mode",["require","exports","module","ace/range"],function(a,b,c){"use strict";var d=a("../../range").Range,e=b.FoldMode=function(){};(function(){this.foldingStartMarker=null,this.foldingStopMarker=null,this.getFoldWidget=function(a,b,c){var d=a.getLine(c);return this.foldingStartMarker.test(d)?"start":b=="markbeginend"&&this.foldingStopMarker&&this.foldingStopMarker.test(d)?"end":""},this.getFoldWidgetRange=function(a,b,c){return null},this.indentationBlock=function(a,b,c){var e=/^\s*/,f=b,g=b,h=a.getLine(b),i=c||h.length,j=h.match(e)[0].length,k=a.getLength();while(++b<k){h=a.getLine(b);var l=h.match(e)[0].length;if(l==h.length)continue;if(l<=j)break;g=b}if(g>f){var m=a.getLine(g).length;return new d(f,i,g,m)}},this.openingBracketBlock=function(a,b,c,e){var f={row:c,column:e+1},g=a.$findClosingBracket(b,f);if(!g)return;var h=a.foldWidgets[g.row];return h==null&&(h=this.getFoldWidget(a,g.row)),h=="start"&&(g.row--,g.column=a.getLine(g.row).length),d.fromPoints(f,g)}}).call(e.prototype)})
\ No newline at end of file
diff --git a/apps/files_texteditor/js/aceeditor/mode-groovy-uncompressed.js b/apps/files_texteditor/js/aceeditor/mode-groovy-uncompressed.js
old mode 100755
new mode 100644
index b6067e877735798ad4ccd1e0a2720173a9e61833..8fc01d4054cd48d1c2a4b923b9d21a93cfb27123
--- a/apps/files_texteditor/js/aceeditor/mode-groovy-uncompressed.js
+++ b/apps/files_texteditor/js/aceeditor/mode-groovy-uncompressed.js
@@ -281,12 +281,20 @@ var JavaScriptHighlightRules = function() {
     );
 
     // TODO: Unicode escape sequences
-    var identifierRe = "[" + unicode.packages.L + "\\$_][" 
+    var identifierRe = "[" + unicode.packages.L + "\\$_]["
         + unicode.packages.L
         + unicode.packages.Mn + unicode.packages.Mc
         + unicode.packages.Nd
         + unicode.packages.Pc + "\\$_]*\\b";
-        
+
+    var escapedRe = "\\\\(?:x[0-9a-fA-F]{2}|" + // hex
+        "u[0-9a-fA-F]{4}|" + // unicode
+        "[0-2][0-7]{0,2}|" + // oct
+        "3[0-6][0-7]?|" + // oct
+        "37[0-7]?|" + // oct
+        "[4-7][0-7]?|" + //oct
+        ".)";
+
     // regexp must not have capturing parentheses. Use (?:) instead.
     // regexps are ordered -> the first match is used
 
@@ -294,46 +302,139 @@ var JavaScriptHighlightRules = function() {
         "start" : [
             {
                 token : "comment",
-                regex : "\\/\\/.*$"
+                regex : /\/\/.*$/
             },
             new DocCommentHighlightRules().getStartRule("doc-start"),
             {
                 token : "comment", // multi line comment
                 merge : true,
-                regex : "\\/\\*",
+                regex : /\/\*/,
                 next : "comment"
             }, {
-                token : "string", // single line
-                regex : '["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'
-            }, {
-                token : "string", // multi line string start
-                merge : true,
-                regex : '["].*\\\\$',
-                next : "qqstring"
-            }, {
-                token : "string", // single line
-                regex : "['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"
+                token : "string",
+                regex : "'",
+                next  : "qstring"
             }, {
-                token : "string", // multi line string start
-                merge : true,
-                regex : "['].*\\\\$",
-                next : "qstring"
+                token : "string",
+                regex : '"',
+                next  : "qqstring"
             }, {
                 token : "constant.numeric", // hex
-                regex : "0[xX][0-9a-fA-F]+\\b"
+                regex : /0[xX][0-9a-fA-F]+\b/
             }, {
                 token : "constant.numeric", // float
-                regex : "[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"
-            }, {
-                token : ["keyword.definition", "text", "entity.name.function"],
-                regex : "(function)(\\s+)(" + identifierRe + ")"
+                regex : /[+-]?\d+(?:(?:\.\d*)?(?:[eE][+-]?\d+)?)?\b/
+            }, { // match stuff like: Sound.prototype.play = function() { }
+                token : [
+                    "storage.type",
+                    "punctuation.operator",
+                    "support.function",
+                    "punctuation.operator",
+                    "entity.name.function",
+                    "text",
+                    "keyword.operator",
+                    "text",
+                    "storage.type",
+                    "text",
+                    "paren.lparen",
+                    "variable.parameter",
+                    "paren.rparen"
+                ],
+                regex : "(" + identifierRe + ")(\\.)(prototype)(\\.)(" + identifierRe +")(\\s*)(=)(\\s*)(function)(\\s*)(\\()(.*?)(\\))"
+            }, { // match stuff like: Sound.prototype.play = myfunc
+                token : [
+                    "storage.type",
+                    "punctuation.operator",
+                    "support.function",
+                    "punctuation.operator",
+                    "entity.name.function",
+                    "text",
+                    "keyword.operator",
+                    "text"
+                ],
+                regex : "(" + identifierRe + ")(\\.)(prototype)(\\.)(" + identifierRe +")(\\s*)(=)(\\s*)"
+            }, { // match stuff like: Sound.play = function() {  }
+                token : [
+                    "storage.type",
+                    "punctuation.operator",
+                    "entity.name.function",
+                    "text",
+                    "keyword.operator",
+                    "text",
+                    "storage.type",
+                    "text",
+                    "paren.lparen",
+                    "variable.parameter",
+                    "paren.rparen"
+                ],
+                regex : "(" + identifierRe + ")(\\.)(" + identifierRe +")(\\s*)(=)(\\s*)(function)(\\s*)(\\()(.*?)(\\))"
+            }, { // match stuff like: play = function() {  }
+                token : [
+                    "entity.name.function",
+                    "text",
+                    "keyword.operator",
+                    "text",
+                    "storage.type",
+                    "text",
+                    "paren.lparen",
+                    "variable.parameter",
+                    "paren.rparen"
+                ],
+                regex : "(" + identifierRe +")(\\s*)(=)(\\s*)(function)(\\s*)(\\()(.*?)(\\))"
+            }, { // match regular function like: function myFunc(arg) { }
+                token : [
+                    "storage.type",
+                    "text",
+                    "entity.name.function",
+                    "text",
+                    "paren.lparen",
+                    "variable.parameter",
+                    "paren.rparen"
+                ],
+                regex : "(function)(\\s+)(" + identifierRe + ")(\\s*)(\\()(.*?)(\\))"
+            }, { // match stuff like: foobar: function() { }
+                token : [
+                    "entity.name.function",
+                    "text",
+                    "punctuation.operator",
+                    "text",
+                    "storage.type",
+                    "text",
+                    "paren.lparen",
+                    "variable.parameter",
+                    "paren.rparen"
+                ],
+                regex : "(" + identifierRe + ")(\\s*)(:)(\\s*)(function)(\\s*)(\\()(.*?)(\\))"
+            }, { // Attempt to match : function() { } (this is for issues with 'foo': function() { })
+                token : [
+                    "text",
+                    "text",
+                    "storage.type",
+                    "text",
+                    "paren.lparen",
+                    "variable.parameter",
+                    "paren.rparen"
+                ],
+                regex : "(:)(\\s*)(function)?(\\s*)(\\()([^)]*)(\\))"
             }, {
                 token : "constant.language.boolean",
-                regex : "(?:true|false)\\b"
+                regex : /(?:true|false)\b/
             }, {
                 token : "keyword",
                 regex : "(?:" + kwBeforeRe + ")\\b",
                 next : "regex_allowed"
+            }, {
+                token : ["punctuation.operator", "support.function"],
+                regex : /(\.)(s(?:h(?:ift|ow(?:Mod(?:elessDialog|alDialog)|Help))|croll(?:X|By(?:Pages|Lines)?|Y|To)?|t(?:opzzzz|rike)|i(?:n|zeToContent|debar|gnText)|ort|u(?:p|b(?:str(?:ing)?)?)|pli(?:ce|t)|e(?:nd|t(?:Re(?:sizable|questHeader)|M(?:i(?:nutes|lliseconds)|onth)|Seconds|Ho(?:tKeys|urs)|Year|Cursor|Time(?:out)?|Interval|ZOptions|Date|UTC(?:M(?:i(?:nutes|lliseconds)|onth)|Seconds|Hours|Date|FullYear)|FullYear|Active)|arch)|qrt|lice|avePreferences|mall)|h(?:ome|andleEvent)|navigate|c(?:har(?:CodeAt|At)|o(?:s|n(?:cat|textual|firm)|mpile)|eil|lear(?:Timeout|Interval)?|a(?:ptureEvents|ll)|reate(?:StyleSheet|Popup|EventObject))|t(?:o(?:GMTString|S(?:tring|ource)|U(?:TCString|pperCase)|Lo(?:caleString|werCase))|est|a(?:n|int(?:Enabled)?))|i(?:s(?:NaN|Finite)|ndexOf|talics)|d(?:isableExternalCapture|ump|etachEvent)|u(?:n(?:shift|taint|escape|watch)|pdateCommands)|j(?:oin|avaEnabled)|p(?:o(?:p|w)|ush|lugins.refresh|a(?:ddings|rse(?:Int|Float)?)|r(?:int|ompt|eference))|e(?:scape|nableExternalCapture|val|lementFromPoint|x(?:p|ec(?:Script|Command)?))|valueOf|UTC|queryCommand(?:State|Indeterm|Enabled|Value)|f(?:i(?:nd|le(?:ModifiedDate|Size|CreatedDate|UpdatedDate)|xed)|o(?:nt(?:size|color)|rward)|loor|romCharCode)|watch|l(?:ink|o(?:ad|g)|astIndexOf)|a(?:sin|nchor|cos|t(?:tachEvent|ob|an(?:2)?)|pply|lert|b(?:s|ort))|r(?:ou(?:nd|teEvents)|e(?:size(?:By|To)|calc|turnValue|place|verse|l(?:oad|ease(?:Capture|Events)))|andom)|g(?:o|et(?:ResponseHeader|M(?:i(?:nutes|lliseconds)|onth)|Se(?:conds|lection)|Hours|Year|Time(?:zoneOffset)?|Da(?:y|te)|UTC(?:M(?:i(?:nutes|lliseconds)|onth)|Seconds|Hours|Da(?:y|te)|FullYear)|FullYear|A(?:ttention|llResponseHeaders)))|m(?:in|ove(?:B(?:y|elow)|To(?:Absolute)?|Above)|ergeAttributes|a(?:tch|rgins|x))|b(?:toa|ig|o(?:ld|rderWidths)|link|ack))\b(?=\()/
+            }, {
+                token : ["punctuation.operator", "support.function.dom"],
+                regex : /(\.)(s(?:ub(?:stringData|mit)|plitText|e(?:t(?:NamedItem|Attribute(?:Node)?)|lect))|has(?:ChildNodes|Feature)|namedItem|c(?:l(?:ick|o(?:se|neNode))|reate(?:C(?:omment|DATASection|aption)|T(?:Head|extNode|Foot)|DocumentFragment|ProcessingInstruction|E(?:ntityReference|lement)|Attribute))|tabIndex|i(?:nsert(?:Row|Before|Cell|Data)|tem)|open|delete(?:Row|C(?:ell|aption)|T(?:Head|Foot)|Data)|focus|write(?:ln)?|a(?:dd|ppend(?:Child|Data))|re(?:set|place(?:Child|Data)|move(?:NamedItem|Child|Attribute(?:Node)?)?)|get(?:NamedItem|Element(?:sBy(?:Name|TagName)|ById)|Attribute(?:Node)?)|blur)\b(?=\()/
+            }, {
+                token : ["punctuation.operator", "support.constant"],
+                regex : /(\.)(s(?:ystemLanguage|cr(?:ipts|ollbars|een(?:X|Y|Top|Left))|t(?:yle(?:Sheets)?|atus(?:Text|bar)?)|ibling(?:Below|Above)|ource|uffixes|e(?:curity(?:Policy)?|l(?:ection|f)))|h(?:istory|ost(?:name)?|as(?:h|Focus))|y|X(?:MLDocument|SLDocument)|n(?:ext|ame(?:space(?:s|URI)|Prop))|M(?:IN_VALUE|AX_VALUE)|c(?:haracterSet|o(?:n(?:structor|trollers)|okieEnabled|lorDepth|mp(?:onents|lete))|urrent|puClass|l(?:i(?:p(?:boardData)?|entInformation)|osed|asses)|alle(?:e|r)|rypto)|t(?:o(?:olbar|p)|ext(?:Transform|Indent|Decoration|Align)|ags)|SQRT(?:1_2|2)|i(?:n(?:ner(?:Height|Width)|put)|ds|gnoreCase)|zIndex|o(?:scpu|n(?:readystatechange|Line)|uter(?:Height|Width)|p(?:sProfile|ener)|ffscreenBuffering)|NEGATIVE_INFINITY|d(?:i(?:splay|alog(?:Height|Top|Width|Left|Arguments)|rectories)|e(?:scription|fault(?:Status|Ch(?:ecked|arset)|View)))|u(?:ser(?:Profile|Language|Agent)|n(?:iqueID|defined)|pdateInterval)|_content|p(?:ixelDepth|ort|ersonalbar|kcs11|l(?:ugins|atform)|a(?:thname|dding(?:Right|Bottom|Top|Left)|rent(?:Window|Layer)?|ge(?:X(?:Offset)?|Y(?:Offset)?))|r(?:o(?:to(?:col|type)|duct(?:Sub)?|mpter)|e(?:vious|fix)))|e(?:n(?:coding|abledPlugin)|x(?:ternal|pando)|mbeds)|v(?:isibility|endor(?:Sub)?|Linkcolor)|URLUnencoded|P(?:I|OSITIVE_INFINITY)|f(?:ilename|o(?:nt(?:Size|Family|Weight)|rmName)|rame(?:s|Element)|gColor)|E|whiteSpace|l(?:i(?:stStyleType|n(?:eHeight|kColor))|o(?:ca(?:tion(?:bar)?|lName)|wsrc)|e(?:ngth|ft(?:Context)?)|a(?:st(?:M(?:odified|atch)|Index|Paren)|yer(?:s|X)|nguage))|a(?:pp(?:MinorVersion|Name|Co(?:deName|re)|Version)|vail(?:Height|Top|Width|Left)|ll|r(?:ity|guments)|Linkcolor|bove)|r(?:ight(?:Context)?|e(?:sponse(?:XML|Text)|adyState))|global|x|m(?:imeTypes|ultiline|enubar|argin(?:Right|Bottom|Top|Left))|L(?:N(?:10|2)|OG(?:10E|2E))|b(?:o(?:ttom|rder(?:Width|RightWidth|BottomWidth|Style|Color|TopWidth|LeftWidth))|ufferDepth|elow|ackground(?:Color|Image)))\b/
+            }, {
+                token : ["storage.type", "punctuation.operator", "support.function.firebug"],
+                regex : /(console)(\.)(warn|info|log|error|time|timeEnd|assert)\b/
             }, {
                 token : function(value) {
                     if (globals.hasOwnProperty(value))
@@ -341,7 +442,7 @@ var JavaScriptHighlightRules = function() {
                     else if (deprecated.hasOwnProperty(value))
                         return "invalid.deprecated";
                     else if (definitions.hasOwnProperty(value))
-                        return "keyword.definition";
+                        return "storage.type";
                     else if (keywords.hasOwnProperty(value))
                         return "keyword";
                     else if (buildinConstants.hasOwnProperty(value))
@@ -356,29 +457,29 @@ var JavaScriptHighlightRules = function() {
                 regex : identifierRe
             }, {
                 token : "keyword.operator",
-                regex : "!|\\$|%|&|\\*|\\-\\-|\\-|\\+\\+|\\+|~|===|==|=|!=|!==|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\\|\\||\\?\\:|\\*=|%=|\\+=|\\-=|&=|\\^=|\\b(?:in|instanceof|new|delete|typeof|void)",
+                regex : /!|\$|%|&|\*|\-\-|\-|\+\+|\+|~|===|==|=|!=|!==|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\|\||\?\:|\*=|%=|\+=|\-=|&=|\^=|\b(?:in|instanceof|new|delete|typeof|void)/,
                 next  : "regex_allowed"
             }, {
                 token : "punctuation.operator",
-                regex : "\\?|\\:|\\,|\\;|\\.",
+                regex : /\?|\:|\,|\;|\./,
                 next  : "regex_allowed"
             }, {
                 token : "paren.lparen",
-                regex : "[[({]",
+                regex : /[\[({]/,
                 next  : "regex_allowed"
             }, {
                 token : "paren.rparen",
-                regex : "[\\])}]"
+                regex : /[\])}]/
             }, {
                 token : "keyword.operator",
-                regex : "\\/=?",
+                regex : /\/=?/,
                 next  : "regex_allowed"
             }, {
                 token: "comment",
-                regex: "^#!.*$" 
+                regex: /^#!.*$/
             }, {
                 token : "text",
-                regex : "\\s+"
+                regex : /\s+/
             }
         ],
         // regular expressions are only allowed after certain tokens. This
@@ -403,7 +504,7 @@ var JavaScriptHighlightRules = function() {
             }, {
                 // immediately return to the start mode without matching
                 // anything
-                token: "empty", 
+                token: "empty",
                 regex: "",
                 next: "start"
             }
@@ -415,10 +516,10 @@ var JavaScriptHighlightRules = function() {
                 next: "regex"
             }, {
 				// flag
-                token: "string.regexp", 
+                token: "string.regexp",
                 regex: "/\\w*",
                 next: "start",
-                merge: true 
+                merge: true
             }, {
                 token: "string.regexp",
                 regex: "[^\\\\/\\[]+",
@@ -430,9 +531,9 @@ var JavaScriptHighlightRules = function() {
                 next: "regex_character_class",
                 merge: true
             }, {
-                token: "empty", 
+                token: "empty",
                 regex: "",
-                next: "start" 
+                next: "start"
             }
         ],
         "regex_character_class": [
@@ -451,9 +552,9 @@ var JavaScriptHighlightRules = function() {
                 next: "regex_character_class",
                 merge: true
             }, {
-                token: "empty", 
+                token: "empty",
                 regex: "",
-                next: "start" 
+                next: "start"
             }
         ],
         "comment_regex_allowed" : [
@@ -482,28 +583,32 @@ var JavaScriptHighlightRules = function() {
         ],
         "qqstring" : [
             {
+                token : "constant.language.escape",
+                regex : escapedRe
+            }, {
                 token : "string",
-                regex : '(?:(?:\\\\.)|(?:[^"\\\\]))*?"',
-                next : "start"
+                regex : '[^"\\\\]+'
             }, {
                 token : "string",
-                merge : true,
-                regex : '.+'
+                regex : '"',
+                next  : "start"
             }
         ],
         "qstring" : [
             {
+                token : "constant.language.escape",
+                regex : escapedRe
+            }, {
                 token : "string",
-                regex : "(?:(?:\\\\.)|(?:[^'\\\\]))*?'",
-                next : "start"
+                regex : "[^'\\\\]+"
             }, {
                 token : "string",
-                merge : true,
-                regex : '.+'
+                regex : "'",
+                next  : "start"
             }
         ]
     };
-    
+
     this.embedRules(DocCommentHighlightRules, "doc-",
         [ new DocCommentHighlightRules().getEndRule("start") ]);
 };
@@ -688,195 +793,6 @@ var MatchingBraceOutdent = function() {};
 }).call(MatchingBraceOutdent.prototype);
 
 exports.MatchingBraceOutdent = MatchingBraceOutdent;
-});
-/* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is Ajax.org Code Editor (ACE).
- *
- * The Initial Developer of the Original Code is
- * Ajax.org B.V.
- * Portions created by the Initial Developer are Copyright (C) 2010
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *      Fabian Jakobs <fabian AT ajax DOT org>
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-define('ace/worker/worker_client', ['require', 'exports', 'module' , 'ace/lib/oop', 'ace/lib/event_emitter'], function(require, exports, module) {
-"use strict";
-
-var oop = require("../lib/oop");
-var EventEmitter = require("../lib/event_emitter").EventEmitter;
-
-var WorkerClient = function(topLevelNamespaces, packagedJs, mod, classname) {
-
-    this.changeListener = this.changeListener.bind(this);
-
-    if (module.packaged) {
-        var base = this.$guessBasePath();
-        this.$worker = new Worker(base + packagedJs);
-    }
-    else {
-        var workerUrl = this.$normalizePath(require.nameToUrl("ace/worker/worker", null, "_"));
-        this.$worker = new Worker(workerUrl);
-
-        var tlns = {};
-        for (var i=0; i<topLevelNamespaces.length; i++) {
-            var ns = topLevelNamespaces[i];
-            var path = this.$normalizePath(require.nameToUrl(ns, null, "_").replace(/.js$/, ""));
-
-            tlns[ns] = path;
-        }
-    }
-
-    this.$worker.postMessage({
-        init : true,
-        tlns: tlns,
-        module: mod,
-        classname: classname
-    });
-
-    this.callbackId = 1;
-    this.callbacks = {};
-
-    var _self = this;
-    this.$worker.onerror = function(e) {
-        window.console && console.log && console.log(e);
-        throw e;
-    };
-    this.$worker.onmessage = function(e) {
-        var msg = e.data;
-        switch(msg.type) {
-            case "log":
-                window.console && console.log && console.log(msg.data);
-                break;
-
-            case "event":
-                _self._emit(msg.name, {data: msg.data});
-                break;
-
-            case "call":
-                var callback = _self.callbacks[msg.id];
-                if (callback) {
-                    callback(msg.data);
-                    delete _self.callbacks[msg.id];
-                }
-                break;
-        }
-    };
-};
-
-(function(){
-
-    oop.implement(this, EventEmitter);
-
-    this.$normalizePath = function(path) {
-        path = path.replace(/^[a-z]+:\/\/[^\/]+\//, ""); // Remove domain name and rebuild it
-        path = location.protocol + "//" + location.host
-            // paths starting with a slash are relative to the root (host)
-            + (path.charAt(0) == "/" ? "" : location.pathname.replace(/\/[^\/]*$/, ""))
-            + "/" + path.replace(/^[\/]+/, "");
-        return path;
-    };
-
-    this.$guessBasePath = function() {
-        if (require.aceBaseUrl)
-            return require.aceBaseUrl;
-
-        var scripts = document.getElementsByTagName("script");
-        for (var i=0; i<scripts.length; i++) {
-            var script = scripts[i];
-
-            var base = script.getAttribute("data-ace-base");
-            if (base)
-                return base.replace(/\/*$/, "/");
-
-            var src = script.src || script.getAttribute("src");
-            if (!src) {
-                continue;
-            }
-            var m = src.match(/^(?:(.*\/)ace\.js|(.*\/)ace(-uncompressed)?(-noconflict)?\.js)(?:\?|$)/);
-            if (m)
-                return m[1] || m[2];
-        }
-        return "";
-    };
-
-    this.terminate = function() {
-        this._emit("terminate", {});
-        this.$worker.terminate();
-        this.$worker = null;
-        this.$doc.removeEventListener("change", this.changeListener);
-        this.$doc = null;
-    };
-
-    this.send = function(cmd, args) {
-        this.$worker.postMessage({command: cmd, args: args});
-    };
-
-    this.call = function(cmd, args, callback) {
-        if (callback) {
-            var id = this.callbackId++;
-            this.callbacks[id] = callback;
-            args.push(id);
-        }
-        this.send(cmd, args);
-    };
-
-    this.emit = function(event, data) {
-        try {
-            // firefox refuses to clone objects which have function properties
-            // TODO: cleanup event
-            this.$worker.postMessage({event: event, data: {data: data.data}});
-        }
-        catch(ex) {}
-    };
-
-    this.attachToDocument = function(doc) {
-        if(this.$doc)
-            this.terminate();
-
-        this.$doc = doc;
-        this.call("setValue", [doc.getValue()]);
-        doc.on("change", this.changeListener);
-    };
-
-    this.changeListener = function(e) {
-        e.range = {
-            start: e.data.range.start,
-            end: e.data.range.end
-        };
-        this.emit("change", e);
-    };
-
-}).call(WorkerClient.prototype);
-
-exports.WorkerClient = WorkerClient;
-
 });
 /* vim:ts=4:sts=4:sw=4:
  * ***** BEGIN LICENSE BLOCK *****
@@ -932,12 +848,12 @@ var CstyleBehaviour = function () {
                 return {
                     text: '{' + selected + '}',
                     selection: false
-                }
+                };
             } else {
                 return {
                     text: '{}',
                     selection: [1, 1]
-                }
+                };
             }
         } else if (text == '}') {
             var cursor = editor.getCursorPosition();
@@ -949,7 +865,7 @@ var CstyleBehaviour = function () {
                     return {
                         text: '',
                         selection: [1, 1]
-                    }
+                    };
                 }
             }
         } else if (text == "\n") {
@@ -967,7 +883,7 @@ var CstyleBehaviour = function () {
                 return {
                     text: '\n' + indent + '\n' + next_indent,
                     selection: [1, indent.length, 1, indent.length]
-                }
+                };
             }
         }
     });
@@ -992,12 +908,12 @@ var CstyleBehaviour = function () {
                 return {
                     text: '(' + selected + ')',
                     selection: false
-                }
+                };
             } else {
                 return {
                     text: '()',
                     selection: [1, 1]
-                }
+                };
             }
         } else if (text == ')') {
             var cursor = editor.getCursorPosition();
@@ -1009,7 +925,7 @@ var CstyleBehaviour = function () {
                     return {
                         text: '',
                         selection: [1, 1]
-                    }
+                    };
                 }
             }
         }
@@ -1028,14 +944,15 @@ var CstyleBehaviour = function () {
     });
 
     this.add("string_dquotes", "insertion", function (state, action, editor, session, text) {
-        if (text == '"') {
+        if (text == '"' || text == "'") {
+            var quote = text;
             var selection = editor.getSelectionRange();
             var selected = session.doc.getTextRange(selection);
             if (selected !== "") {
                 return {
-                    text: '"' + selected + '"',
+                    text: quote + selected + quote,
                     selection: false
-                }
+                };
             } else {
                 var cursor = editor.getCursorPosition();
                 var line = session.doc.getLine(cursor.row);
@@ -1056,7 +973,7 @@ var CstyleBehaviour = function () {
                     if (token.type == "string") {
                       quotepos = -1;
                     } else if (quotepos < 0) {
-                      quotepos = token.value.indexOf('"');
+                      quotepos = token.value.indexOf(quote);
                     }
                     if ((token.value.length + col) > selection.start.column) {
                         break;
@@ -1065,19 +982,19 @@ var CstyleBehaviour = function () {
                 }
 
                 // Try and be smart about when we auto insert.
-                if (!token || (quotepos < 0 && token.type !== "comment" && (token.type !== "string" || ((selection.start.column !== token.value.length+col-1) && token.value.lastIndexOf('"') === token.value.length-1)))) {
+                if (!token || (quotepos < 0 && token.type !== "comment" && (token.type !== "string" || ((selection.start.column !== token.value.length+col-1) && token.value.lastIndexOf(quote) === token.value.length-1)))) {
                     return {
-                        text: '""',
+                        text: quote + quote,
                         selection: [1,1]
-                    }
+                    };
                 } else if (token && token.type === "string") {
                     // Ignore input and move right one if we're typing over the closing quote.
                     var rightChar = line.substring(cursor.column, cursor.column + 1);
-                    if (rightChar == '"') {
+                    if (rightChar == quote) {
                         return {
                             text: '',
                             selection: [1, 1]
-                        }
+                        };
                     }
                 }
             }
@@ -1086,7 +1003,7 @@ var CstyleBehaviour = function () {
 
     this.add("string_dquotes", "deletion", function (state, action, editor, session, range) {
         var selected = session.doc.getTextRange(range);
-        if (!range.isMultiLine() && selected == '"') {
+        if (!range.isMultiLine() && (selected == '"' || selected == "'")) {
             var line = session.doc.getLine(range.start.row);
             var rightChar = line.substring(range.start.column + 1, range.start.column + 2);
             if (rightChar == '"') {
@@ -1096,7 +1013,8 @@ var CstyleBehaviour = function () {
         }
     });
 
-}
+};
+
 oop.inherits(CstyleBehaviour, Behaviour);
 
 exports.CstyleBehaviour = CstyleBehaviour;
@@ -1450,13 +1368,3 @@ oop.inherits(GroovyHighlightRules, TextHighlightRules);
 
 exports.GroovyHighlightRules = GroovyHighlightRules;
 });
-;
-            (function() {
-                window.require(["ace/ace"], function(a) {
-                    if (!window.ace)
-                        window.ace = {};
-                    for (var key in a) if (a.hasOwnProperty(key))
-                        ace[key] = a[key];
-                });
-            })();
-        
\ No newline at end of file
diff --git a/apps/files_texteditor/js/aceeditor/mode-groovy.js b/apps/files_texteditor/js/aceeditor/mode-groovy.js
index c71ada2bf84dd46735f68e69bf3c3c9d2cb2018d..1a036a462c71565cbe68b20a800b5c229f055a1e 100644
--- a/apps/files_texteditor/js/aceeditor/mode-groovy.js
+++ b/apps/files_texteditor/js/aceeditor/mode-groovy.js
@@ -1 +1 @@
-define("ace/mode/groovy",["require","exports","module","ace/lib/oop","ace/mode/javascript","ace/tokenizer","ace/mode/groovy_highlight_rules"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("./javascript").Mode,f=a("../tokenizer").Tokenizer,g=a("./groovy_highlight_rules").GroovyHighlightRules,h=function(){e.call(this),this.$tokenizer=new f((new g).getRules())};d.inherits(h,e),function(){this.createWorker=function(a){return null}}.call(h.prototype),b.Mode=h}),define("ace/mode/javascript",["require","exports","module","ace/lib/oop","ace/mode/text","ace/tokenizer","ace/mode/javascript_highlight_rules","ace/mode/matching_brace_outdent","ace/range","ace/worker/worker_client","ace/mode/behaviour/cstyle","ace/mode/folding/cstyle"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("./text").Mode,f=a("../tokenizer").Tokenizer,g=a("./javascript_highlight_rules").JavaScriptHighlightRules,h=a("./matching_brace_outdent").MatchingBraceOutdent,i=a("../range").Range,j=a("../worker/worker_client").WorkerClient,k=a("./behaviour/cstyle").CstyleBehaviour,l=a("./folding/cstyle").FoldMode,m=function(){this.$tokenizer=new f((new g).getRules()),this.$outdent=new h,this.$behaviour=new k,this.foldingRules=new l};d.inherits(m,e),function(){this.toggleCommentLines=function(a,b,c,d){var e=!0,f=/^(\s*)\/\//;for(var g=c;g<=d;g++)if(!f.test(b.getLine(g))){e=!1;break}if(e){var h=new i(0,0,0,0);for(var g=c;g<=d;g++){var j=b.getLine(g),k=j.match(f);h.start.row=g,h.end.row=g,h.end.column=k[0].length,b.replace(h,k[1])}}else b.indentRows(c,d,"//")},this.getNextLineIndent=function(a,b,c){var d=this.$getIndent(b),e=this.$tokenizer.getLineTokens(b,a),f=e.tokens,g=e.state;if(f.length&&f[f.length-1].type=="comment")return d;if(a=="start"||a=="regex_allowed"){var h=b.match(/^.*(?:\bcase\b.*\:|[\{\(\[])\s*$/);h&&(d+=c)}else if(a=="doc-start"){if(g=="start"||a=="regex_allowed")return"";var h=b.match(/^\s*(\/?)\*/);h&&(h[1]&&(d+=" "),d+="* ")}return d},this.checkOutdent=function(a,b,c){return this.$outdent.checkOutdent(b,c)},this.autoOutdent=function(a,b,c){this.$outdent.autoOutdent(b,c)},this.createWorker=function(a){var b=new j(["ace"],"worker-javascript.js","ace/mode/javascript_worker","JavaScriptWorker");return b.attachToDocument(a.getDocument()),b.on("jslint",function(b){var c=[];for(var d=0;d<b.data.length;d++){var e=b.data[d];e&&c.push({row:e.line-1,column:e.character-1,text:e.reason,type:"warning",lint:e})}a.setAnnotations(c)}),b.on("narcissus",function(b){a.setAnnotations([b.data])}),b.on("terminate",function(){a.clearAnnotations()}),b}}.call(m.prototype),b.Mode=m}),define("ace/mode/javascript_highlight_rules",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/unicode","ace/mode/doc_comment_highlight_rules","ace/mode/text_highlight_rules"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("../lib/lang"),f=a("../unicode"),g=a("./doc_comment_highlight_rules").DocCommentHighlightRules,h=a("./text_highlight_rules").TextHighlightRules,i=function(){var a=e.arrayToMap("Array|Boolean|Date|Function|Iterator|Number|Object|RegExp|String|Proxy|Namespace|QName|XML|XMLList|ArrayBuffer|Float32Array|Float64Array|Int16Array|Int32Array|Int8Array|Uint16Array|Uint32Array|Uint8Array|Uint8ClampedArray|Error|EvalError|InternalError|RangeError|ReferenceError|StopIteration|SyntaxError|TypeError|URIError|decodeURI|decodeURIComponent|encodeURI|encodeURIComponent|eval|isFinite|isNaN|parseFloat|parseInt|JSON|Math|this|arguments|prototype|window|document".split("|")),b=e.arrayToMap("break|case|catch|continue|default|delete|do|else|finally|for|function|if|in|instanceof|new|return|switch|throw|try|typeof|let|var|while|with|const|yield|import|get|set".split("|")),c="case|do|else|finally|in|instanceof|return|throw|try|typeof|yield",d=e.arrayToMap("__parent__|__count__|escape|unescape|with|__proto__".split("|")),h=e.arrayToMap("const|let|var|function".split("|")),i=e.arrayToMap("null|Infinity|NaN|undefined".split("|")),j=e.arrayToMap("class|enum|extends|super|export|implements|private|public|interface|package|protected|static".split("|")),k="["+f.packages.L+"\\$_]["+f.packages.L+f.packages.Mn+f.packages.Mc+f.packages.Nd+f.packages.Pc+"\\$_]*\\b";this.$rules={start:[{token:"comment",regex:"\\/\\/.*$"},(new g).getStartRule("doc-start"),{token:"comment",merge:!0,regex:"\\/\\*",next:"comment"},{token:"string",regex:'["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'},{token:"string",merge:!0,regex:'["].*\\\\$',next:"qqstring"},{token:"string",regex:"['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"},{token:"string",merge:!0,regex:"['].*\\\\$",next:"qstring"},{token:"constant.numeric",regex:"0[xX][0-9a-fA-F]+\\b"},{token:"constant.numeric",regex:"[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"},{token:["keyword.definition","text","entity.name.function"],regex:"(function)(\\s+)("+k+")"},{token:"constant.language.boolean",regex:"(?:true|false)\\b"},{token:"keyword",regex:"(?:"+c+")\\b",next:"regex_allowed"},{token:function(c){return a.hasOwnProperty(c)?"variable.language":d.hasOwnProperty(c)?"invalid.deprecated":h.hasOwnProperty(c)?"keyword.definition":b.hasOwnProperty(c)?"keyword":i.hasOwnProperty(c)?"constant.language":j.hasOwnProperty(c)?"invalid.illegal":c=="debugger"?"invalid.deprecated":"identifier"},regex:k},{token:"keyword.operator",regex:"!|\\$|%|&|\\*|\\-\\-|\\-|\\+\\+|\\+|~|===|==|=|!=|!==|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\\|\\||\\?\\:|\\*=|%=|\\+=|\\-=|&=|\\^=|\\b(?:in|instanceof|new|delete|typeof|void)",next:"regex_allowed"},{token:"punctuation.operator",regex:"\\?|\\:|\\,|\\;|\\.",next:"regex_allowed"},{token:"paren.lparen",regex:"[[({]",next:"regex_allowed"},{token:"paren.rparen",regex:"[\\])}]"},{token:"keyword.operator",regex:"\\/=?",next:"regex_allowed"},{token:"comment",regex:"^#!.*$"},{token:"text",regex:"\\s+"}],regex_allowed:[{token:"comment",merge:!0,regex:"\\/\\*",next:"comment_regex_allowed"},{token:"comment",regex:"\\/\\/.*$"},{token:"string.regexp",regex:"\\/",next:"regex",merge:!0},{token:"text",regex:"\\s+"},{token:"empty",regex:"",next:"start"}],regex:[{token:"regexp.keyword.operator",regex:"\\\\(?:u[\\da-fA-F]{4}|x[\\da-fA-F]{2}|.)",next:"regex"},{token:"string.regexp",regex:"/\\w*",next:"start",merge:!0},{token:"string.regexp",regex:"[^\\\\/\\[]+",next:"regex",merge:!0},{token:"string.regexp.charachterclass",regex:"\\[",next:"regex_character_class",merge:!0},{token:"empty",regex:"",next:"start"}],regex_character_class:[{token:"regexp.keyword.operator",regex:"\\\\(?:u[\\da-fA-F]{4}|x[\\da-fA-F]{2}|.)",next:"regex_character_class"},{token:"string.regexp.charachterclass",regex:"]",next:"regex",merge:!0},{token:"string.regexp.charachterclass",regex:"[^\\\\\\]]+",next:"regex_character_class",merge:!0},{token:"empty",regex:"",next:"start"}],comment_regex_allowed:[{token:"comment",regex:".*?\\*\\/",merge:!0,next:"regex_allowed"},{token:"comment",merge:!0,regex:".+"}],comment:[{token:"comment",regex:".*?\\*\\/",merge:!0,next:"start"},{token:"comment",merge:!0,regex:".+"}],qqstring:[{token:"string",regex:'(?:(?:\\\\.)|(?:[^"\\\\]))*?"',next:"start"},{token:"string",merge:!0,regex:".+"}],qstring:[{token:"string",regex:"(?:(?:\\\\.)|(?:[^'\\\\]))*?'",next:"start"},{token:"string",merge:!0,regex:".+"}]},this.embedRules(g,"doc-",[(new g).getEndRule("start")])};d.inherits(i,h),b.JavaScriptHighlightRules=i}),define("ace/mode/doc_comment_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("./text_highlight_rules").TextHighlightRules,f=function(){this.$rules={start:[{token:"comment.doc.tag",regex:"@[\\w\\d_]+"},{token:"comment.doc",merge:!0,regex:"\\s+"},{token:"comment.doc",merge:!0,regex:"TODO"},{token:"comment.doc",merge:!0,regex:"[^@\\*]+"},{token:"comment.doc",merge:!0,regex:"."}]}};d.inherits(f,e),function(){this.getStartRule=function(a){return{token:"comment.doc",merge:!0,regex:"\\/\\*(?=\\*)",next:a}},this.getEndRule=function(a){return{token:"comment.doc",merge:!0,regex:"\\*\\/",next:a}}}.call(f.prototype),b.DocCommentHighlightRules=f}),define("ace/mode/matching_brace_outdent",["require","exports","module","ace/range"],function(a,b,c){"use strict";var d=a("../range").Range,e=function(){};((function(){this.checkOutdent=function(a,b){return/^\s+$/.test(a)?/^\s*\}/.test(b):!1},this.autoOutdent=function(a,b){var c=a.getLine(b),e=c.match(/^(\s*\})/);if(!e)return 0;var f=e[1].length,g=a.findMatchingBracket({row:b,column:f});if(!g||g.row==b)return 0;var h=this.$getIndent(a.getLine(g.row));a.replace(new d(b,0,b,f-1),h)},this.$getIndent=function(a){var b=a.match(/^(\s+)/);return b?b[1]:""}})).call(e.prototype),b.MatchingBraceOutdent=e}),define("ace/worker/worker_client",["require","exports","module","ace/lib/oop","ace/lib/event_emitter"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("../lib/event_emitter").EventEmitter,f=function(b,d,e,f){this.changeListener=this.changeListener.bind(this);if(c.packaged){var g=this.$guessBasePath();this.$worker=new Worker(g+d)}else{var h=this.$normalizePath(a.nameToUrl("ace/worker/worker",null,"_"));this.$worker=new Worker(h);var i={};for(var j=0;j<b.length;j++){var k=b[j],l=this.$normalizePath(a.nameToUrl(k,null,"_").replace(/.js$/,""));i[k]=l}}this.$worker.postMessage({init:!0,tlns:i,module:e,classname:f}),this.callbackId=1,this.callbacks={};var m=this;this.$worker.onerror=function(a){throw window.console&&console.log&&console.log(a),a},this.$worker.onmessage=function(a){var b=a.data;switch(b.type){case"log":window.console&&console.log&&console.log(b.data);break;case"event":m._emit(b.name,{data:b.data});break;case"call":var c=m.callbacks[b.id];c&&(c(b.data),delete m.callbacks[b.id])}}};((function(){d.implement(this,e),this.$normalizePath=function(a){return a=a.replace(/^[a-z]+:\/\/[^\/]+\//,""),a=location.protocol+"//"+location.host+(a.charAt(0)=="/"?"":location.pathname.replace(/\/[^\/]*$/,""))+"/"+a.replace(/^[\/]+/,""),a},this.$guessBasePath=function(){if(a.aceBaseUrl)return a.aceBaseUrl;var b=document.getElementsByTagName("script");for(var c=0;c<b.length;c++){var d=b[c],e=d.getAttribute("data-ace-base");if(e)return e.replace(/\/*$/,"/");var f=d.src||d.getAttribute("src");if(!f)continue;var g=f.match(/^(?:(.*\/)ace\.js|(.*\/)ace(-uncompressed)?(-noconflict)?\.js)(?:\?|$)/);if(g)return g[1]||g[2]}return""},this.terminate=function(){this._emit("terminate",{}),this.$worker.terminate(),this.$worker=null,this.$doc.removeEventListener("change",this.changeListener),this.$doc=null},this.send=function(a,b){this.$worker.postMessage({command:a,args:b})},this.call=function(a,b,c){if(c){var d=this.callbackId++;this.callbacks[d]=c,b.push(d)}this.send(a,b)},this.emit=function(a,b){try{this.$worker.postMessage({event:a,data:{data:b.data}})}catch(c){}},this.attachToDocument=function(a){this.$doc&&this.terminate(),this.$doc=a,this.call("setValue",[a.getValue()]),a.on("change",this.changeListener)},this.changeListener=function(a){a.range={start:a.data.range.start,end:a.data.range.end},this.emit("change",a)}})).call(f.prototype),b.WorkerClient=f}),define("ace/mode/behaviour/cstyle",["require","exports","module","ace/lib/oop","ace/mode/behaviour"],function(a,b,c){"use strict";var d=a("../../lib/oop"),e=a("../behaviour").Behaviour,f=function(){this.add("braces","insertion",function(a,b,c,d,e){if(e=="{"){var f=c.getSelectionRange(),g=d.doc.getTextRange(f);return g!==""?{text:"{"+g+"}",selection:!1}:{text:"{}",selection:[1,1]}}if(e=="}"){var h=c.getCursorPosition(),i=d.doc.getLine(h.row),j=i.substring(h.column,h.column+1);if(j=="}"){var k=d.$findOpeningBracket("}",{column:h.column+1,row:h.row});if(k!==null)return{text:"",selection:[1,1]}}}else if(e=="\n"){var h=c.getCursorPosition(),i=d.doc.getLine(h.row),j=i.substring(h.column,h.column+1);if(j=="}"){var l=d.findMatchingBracket({row:h.row,column:h.column+1});if(!l)return null;var m=this.getNextLineIndent(a,i.substring(0,i.length-1),d.getTabString()),n=this.$getIndent(d.doc.getLine(l.row));return{text:"\n"+m+"\n"+n,selection:[1,m.length,1,m.length]}}}}),this.add("braces","deletion",function(a,b,c,d,e){var f=d.doc.getTextRange(e);if(!e.isMultiLine()&&f=="{"){var g=d.doc.getLine(e.start.row),h=g.substring(e.end.column,e.end.column+1);if(h=="}")return e.end.column++,e}}),this.add("parens","insertion",function(a,b,c,d,e){if(e=="("){var f=c.getSelectionRange(),g=d.doc.getTextRange(f);return g!==""?{text:"("+g+")",selection:!1}:{text:"()",selection:[1,1]}}if(e==")"){var h=c.getCursorPosition(),i=d.doc.getLine(h.row),j=i.substring(h.column,h.column+1);if(j==")"){var k=d.$findOpeningBracket(")",{column:h.column+1,row:h.row});if(k!==null)return{text:"",selection:[1,1]}}}}),this.add("parens","deletion",function(a,b,c,d,e){var f=d.doc.getTextRange(e);if(!e.isMultiLine()&&f=="("){var g=d.doc.getLine(e.start.row),h=g.substring(e.start.column+1,e.start.column+2);if(h==")")return e.end.column++,e}}),this.add("string_dquotes","insertion",function(a,b,c,d,e){if(e=='"'){var f=c.getSelectionRange(),g=d.doc.getTextRange(f);if(g!=="")return{text:'"'+g+'"',selection:!1};var h=c.getCursorPosition(),i=d.doc.getLine(h.row),j=i.substring(h.column-1,h.column);if(j=="\\")return null;var k=d.getTokens(f.start.row,f.start.row)[0].tokens,l=0,m,n=-1;for(var o=0;o<k.length;o++){m=k[o],m.type=="string"?n=-1:n<0&&(n=m.value.indexOf('"'));if(m.value.length+l>f.start.column)break;l+=k[o].value.length}if(!m||n<0&&m.type!=="comment"&&(m.type!=="string"||f.start.column!==m.value.length+l-1&&m.value.lastIndexOf('"')===m.value.length-1))return{text:'""',selection:[1,1]};if(m&&m.type==="string"){var p=i.substring(h.column,h.column+1);if(p=='"')return{text:"",selection:[1,1]}}}}),this.add("string_dquotes","deletion",function(a,b,c,d,e){var f=d.doc.getTextRange(e);if(!e.isMultiLine()&&f=='"'){var g=d.doc.getLine(e.start.row),h=g.substring(e.start.column+1,e.start.column+2);if(h=='"')return e.end.column++,e}})};d.inherits(f,e),b.CstyleBehaviour=f}),define("ace/mode/folding/cstyle",["require","exports","module","ace/lib/oop","ace/range","ace/mode/folding/fold_mode"],function(a,b,c){"use strict";var d=a("../../lib/oop"),e=a("../../range").Range,f=a("./fold_mode").FoldMode,g=b.FoldMode=function(){};d.inherits(g,f),function(){this.foldingStartMarker=/(\{|\[)[^\}\]]*$|^\s*(\/\*)/,this.foldingStopMarker=/^[^\[\{]*(\}|\])|^[\s\*]*(\*\/)/,this.getFoldWidgetRange=function(a,b,c){var d=a.getLine(c),f=d.match(this.foldingStartMarker);if(f){var g=f.index;if(f[1])return this.openingBracketBlock(a,f[1],c,g);var h=a.getCommentFoldRange(c,g+f[0].length);return h.end.column-=2,h}if(b!=="markbeginend")return;var f=d.match(this.foldingStopMarker);if(f){var g=f.index+f[0].length;if(f[2]){var h=a.getCommentFoldRange(c,g);return h.end.column-=2,h}var i={row:c,column:g},j=a.$findOpeningBracket(f[1],i);if(!j)return;return j.column++,i.column--,e.fromPoints(j,i)}}}.call(g.prototype)}),define("ace/mode/folding/fold_mode",["require","exports","module","ace/range"],function(a,b,c){"use strict";var d=a("../../range").Range,e=b.FoldMode=function(){};((function(){this.foldingStartMarker=null,this.foldingStopMarker=null,this.getFoldWidget=function(a,b,c){var d=a.getLine(c);return this.foldingStartMarker.test(d)?"start":b=="markbeginend"&&this.foldingStopMarker&&this.foldingStopMarker.test(d)?"end":""},this.getFoldWidgetRange=function(a,b,c){return null},this.indentationBlock=function(a,b,c){var e=/^\s*/,f=b,g=b,h=a.getLine(b),i=c||h.length,j=h.match(e)[0].length,k=a.getLength();while(++b<k){h=a.getLine(b);var l=h.match(e)[0].length;if(l==h.length)continue;if(l<=j)break;g=b}if(g>f){var m=a.getLine(g).length;return new d(f,i,g,m)}},this.openingBracketBlock=function(a,b,c,e){var f={row:c,column:e+1},g=a.$findClosingBracket(b,f);if(!g)return;var h=a.foldWidgets[g.row];return h==null&&(h=this.getFoldWidget(a,g.row)),h=="start"&&(g.row--,g.column=a.getLine(g.row).length),d.fromPoints(f,g)}})).call(e.prototype)}),define("ace/mode/groovy_highlight_rules",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/mode/doc_comment_highlight_rules","ace/mode/text_highlight_rules"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("../lib/lang"),f=a("./doc_comment_highlight_rules").DocCommentHighlightRules,g=a("./text_highlight_rules").TextHighlightRules,h=function(){var a=e.arrayToMap("assert|with|abstract|continue|for|new|switch|assert|default|goto|package|synchronized|boolean|do|if|private|this|break|double|implements|protected|throw|byte|else|import|public|throws|case|enum|instanceof|return|transient|catch|extends|int|short|try|char|final|interface|static|void|class|finally|long|strictfp|volatile|def|float|native|super|while".split("|")),b=e.arrayToMap("null|Infinity|NaN|undefined".split("|")),c=e.arrayToMap("AbstractMethodError|AssertionError|ClassCircularityError|ClassFormatError|Deprecated|EnumConstantNotPresentException|ExceptionInInitializerError|IllegalAccessError|IllegalThreadStateException|InstantiationError|InternalError|NegativeArraySizeException|NoSuchFieldError|Override|Process|ProcessBuilder|SecurityManager|StringIndexOutOfBoundsException|SuppressWarnings|TypeNotPresentException|UnknownError|UnsatisfiedLinkError|UnsupportedClassVersionError|VerifyError|InstantiationException|IndexOutOfBoundsException|ArrayIndexOutOfBoundsException|CloneNotSupportedException|NoSuchFieldException|IllegalArgumentException|NumberFormatException|SecurityException|Void|InheritableThreadLocal|IllegalStateException|InterruptedException|NoSuchMethodException|IllegalAccessException|UnsupportedOperationException|Enum|StrictMath|Package|Compiler|Readable|Runtime|StringBuilder|Math|IncompatibleClassChangeError|NoSuchMethodError|ThreadLocal|RuntimePermission|ArithmeticException|NullPointerException|Long|Integer|Short|Byte|Double|Number|Float|Character|Boolean|StackTraceElement|Appendable|StringBuffer|Iterable|ThreadGroup|Runnable|Thread|IllegalMonitorStateException|StackOverflowError|OutOfMemoryError|VirtualMachineError|ArrayStoreException|ClassCastException|LinkageError|NoClassDefFoundError|ClassNotFoundException|RuntimeException|Exception|ThreadDeath|Error|Throwable|System|ClassLoader|Cloneable|Class|CharSequence|Comparable|String|Object".split("|")),d=e.arrayToMap("".split("|"));this.$rules={start:[{token:"comment",regex:"\\/\\/.*$"},(new f).getStartRule("doc-start"),{token:"comment",merge:!0,regex:"\\/\\*",next:"comment"},{token:"string.regexp",regex:"[/](?:(?:\\[(?:\\\\]|[^\\]])+\\])|(?:\\\\/|[^\\]/]))*[/]\\w*\\s*(?=[).,;]|$)"},{token:"string",regex:'["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'},{token:"string",regex:"['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"},{token:"constant.numeric",regex:"0[xX][0-9a-fA-F]+\\b"},{token:"constant.numeric",regex:"[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"},{token:"constant.language.boolean",regex:"(?:true|false)\\b"},{token:function(e){return e=="this"?"variable.language":a.hasOwnProperty(e)?"keyword":c.hasOwnProperty(e)?"support.function":d.hasOwnProperty(e)?"support.function":b.hasOwnProperty(e)?"constant.language":"identifier"},regex:"[a-zA-Z_$][a-zA-Z0-9_$]*\\b"},{token:"keyword.operator",regex:"\\?:|\\?\\.|\\*\\.|<=>|=~|==~|\\.@|\\*\\.@|\\.&|as|in|is|!|\\$|%|&|\\*|\\-\\-|\\-|\\+\\+|\\+|~|===|==|=|!=|!==|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\\|\\||\\?\\:|\\*=|%=|\\+=|\\-=|&=|\\^=|\\b(?:in|instanceof|new|delete|typeof|void)"},{token:"lparen",regex:"[[({]"},{token:"rparen",regex:"[\\])}]"},{token:"text",regex:"\\s+"}],comment:[{token:"comment",regex:".*?\\*\\/",next:"start"},{token:"comment",merge:!0,regex:".+"}]},this.embedRules(f,"doc-",[(new f).getEndRule("start")])};d.inherits(h,g),b.GroovyHighlightRules=h}),function(){window.require(["ace/ace"],function(a){window.ace||(window.ace={});for(var b in a)a.hasOwnProperty(b)&&(ace[b]=a[b])})}()
\ No newline at end of file
+define("ace/mode/groovy",["require","exports","module","ace/lib/oop","ace/mode/javascript","ace/tokenizer","ace/mode/groovy_highlight_rules"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("./javascript").Mode,f=a("../tokenizer").Tokenizer,g=a("./groovy_highlight_rules").GroovyHighlightRules,h=function(){e.call(this),this.$tokenizer=new f((new g).getRules())};d.inherits(h,e),function(){this.createWorker=function(a){return null}}.call(h.prototype),b.Mode=h}),define("ace/mode/javascript",["require","exports","module","ace/lib/oop","ace/mode/text","ace/tokenizer","ace/mode/javascript_highlight_rules","ace/mode/matching_brace_outdent","ace/range","ace/worker/worker_client","ace/mode/behaviour/cstyle","ace/mode/folding/cstyle"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("./text").Mode,f=a("../tokenizer").Tokenizer,g=a("./javascript_highlight_rules").JavaScriptHighlightRules,h=a("./matching_brace_outdent").MatchingBraceOutdent,i=a("../range").Range,j=a("../worker/worker_client").WorkerClient,k=a("./behaviour/cstyle").CstyleBehaviour,l=a("./folding/cstyle").FoldMode,m=function(){this.$tokenizer=new f((new g).getRules()),this.$outdent=new h,this.$behaviour=new k,this.foldingRules=new l};d.inherits(m,e),function(){this.toggleCommentLines=function(a,b,c,d){var e=!0,f=/^(\s*)\/\//;for(var g=c;g<=d;g++)if(!f.test(b.getLine(g))){e=!1;break}if(e){var h=new i(0,0,0,0);for(var g=c;g<=d;g++){var j=b.getLine(g),k=j.match(f);h.start.row=g,h.end.row=g,h.end.column=k[0].length,b.replace(h,k[1])}}else b.indentRows(c,d,"//")},this.getNextLineIndent=function(a,b,c){var d=this.$getIndent(b),e=this.$tokenizer.getLineTokens(b,a),f=e.tokens,g=e.state;if(f.length&&f[f.length-1].type=="comment")return d;if(a=="start"||a=="regex_allowed"){var h=b.match(/^.*(?:\bcase\b.*\:|[\{\(\[])\s*$/);h&&(d+=c)}else if(a=="doc-start"){if(g=="start"||a=="regex_allowed")return"";var h=b.match(/^\s*(\/?)\*/);h&&(h[1]&&(d+=" "),d+="* ")}return d},this.checkOutdent=function(a,b,c){return this.$outdent.checkOutdent(b,c)},this.autoOutdent=function(a,b,c){this.$outdent.autoOutdent(b,c)},this.createWorker=function(a){var b=new j(["ace"],"worker-javascript.js","ace/mode/javascript_worker","JavaScriptWorker");return b.attachToDocument(a.getDocument()),b.on("jslint",function(b){var c=[];for(var d=0;d<b.data.length;d++){var e=b.data[d];e&&c.push({row:e.line-1,column:e.character-1,text:e.reason,type:"warning",lint:e})}a.setAnnotations(c)}),b.on("narcissus",function(b){a.setAnnotations([b.data])}),b.on("terminate",function(){a.clearAnnotations()}),b}}.call(m.prototype),b.Mode=m}),define("ace/mode/javascript_highlight_rules",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/unicode","ace/mode/doc_comment_highlight_rules","ace/mode/text_highlight_rules"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("../lib/lang"),f=a("../unicode"),g=a("./doc_comment_highlight_rules").DocCommentHighlightRules,h=a("./text_highlight_rules").TextHighlightRules,i=function(){var a=e.arrayToMap("Array|Boolean|Date|Function|Iterator|Number|Object|RegExp|String|Proxy|Namespace|QName|XML|XMLList|ArrayBuffer|Float32Array|Float64Array|Int16Array|Int32Array|Int8Array|Uint16Array|Uint32Array|Uint8Array|Uint8ClampedArray|Error|EvalError|InternalError|RangeError|ReferenceError|StopIteration|SyntaxError|TypeError|URIError|decodeURI|decodeURIComponent|encodeURI|encodeURIComponent|eval|isFinite|isNaN|parseFloat|parseInt|JSON|Math|this|arguments|prototype|window|document".split("|")),b=e.arrayToMap("break|case|catch|continue|default|delete|do|else|finally|for|function|if|in|instanceof|new|return|switch|throw|try|typeof|let|var|while|with|const|yield|import|get|set".split("|")),c="case|do|else|finally|in|instanceof|return|throw|try|typeof|yield",d=e.arrayToMap("__parent__|__count__|escape|unescape|with|__proto__".split("|")),h=e.arrayToMap("const|let|var|function".split("|")),i=e.arrayToMap("null|Infinity|NaN|undefined".split("|")),j=e.arrayToMap("class|enum|extends|super|export|implements|private|public|interface|package|protected|static".split("|")),k="["+f.packages.L+"\\$_]["+f.packages.L+f.packages.Mn+f.packages.Mc+f.packages.Nd+f.packages.Pc+"\\$_]*\\b",l="\\\\(?:x[0-9a-fA-F]{2}|u[0-9a-fA-F]{4}|[0-2][0-7]{0,2}|3[0-6][0-7]?|37[0-7]?|[4-7][0-7]?|.)";this.$rules={start:[{token:"comment",regex:/\/\/.*$/},(new g).getStartRule("doc-start"),{token:"comment",merge:!0,regex:/\/\*/,next:"comment"},{token:"string",regex:"'",next:"qstring"},{token:"string",regex:'"',next:"qqstring"},{token:"constant.numeric",regex:/0[xX][0-9a-fA-F]+\b/},{token:"constant.numeric",regex:/[+-]?\d+(?:(?:\.\d*)?(?:[eE][+-]?\d+)?)?\b/},{token:["storage.type","punctuation.operator","support.function","punctuation.operator","entity.name.function","text","keyword.operator","text","storage.type","text","paren.lparen","variable.parameter","paren.rparen"],regex:"("+k+")(\\.)(prototype)(\\.)("+k+")(\\s*)(=)(\\s*)(function)(\\s*)(\\()(.*?)(\\))"},{token:["storage.type","punctuation.operator","support.function","punctuation.operator","entity.name.function","text","keyword.operator","text"],regex:"("+k+")(\\.)(prototype)(\\.)("+k+")(\\s*)(=)(\\s*)"},{token:["storage.type","punctuation.operator","entity.name.function","text","keyword.operator","text","storage.type","text","paren.lparen","variable.parameter","paren.rparen"],regex:"("+k+")(\\.)("+k+")(\\s*)(=)(\\s*)(function)(\\s*)(\\()(.*?)(\\))"},{token:["entity.name.function","text","keyword.operator","text","storage.type","text","paren.lparen","variable.parameter","paren.rparen"],regex:"("+k+")(\\s*)(=)(\\s*)(function)(\\s*)(\\()(.*?)(\\))"},{token:["storage.type","text","entity.name.function","text","paren.lparen","variable.parameter","paren.rparen"],regex:"(function)(\\s+)("+k+")(\\s*)(\\()(.*?)(\\))"},{token:["entity.name.function","text","punctuation.operator","text","storage.type","text","paren.lparen","variable.parameter","paren.rparen"],regex:"("+k+")(\\s*)(:)(\\s*)(function)(\\s*)(\\()(.*?)(\\))"},{token:["text","text","storage.type","text","paren.lparen","variable.parameter","paren.rparen"],regex:"(:)(\\s*)(function)?(\\s*)(\\()([^)]*)(\\))"},{token:"constant.language.boolean",regex:/(?:true|false)\b/},{token:"keyword",regex:"(?:"+c+")\\b",next:"regex_allowed"},{token:["punctuation.operator","support.function"],regex:/(\.)(s(?:h(?:ift|ow(?:Mod(?:elessDialog|alDialog)|Help))|croll(?:X|By(?:Pages|Lines)?|Y|To)?|t(?:opzzzz|rike)|i(?:n|zeToContent|debar|gnText)|ort|u(?:p|b(?:str(?:ing)?)?)|pli(?:ce|t)|e(?:nd|t(?:Re(?:sizable|questHeader)|M(?:i(?:nutes|lliseconds)|onth)|Seconds|Ho(?:tKeys|urs)|Year|Cursor|Time(?:out)?|Interval|ZOptions|Date|UTC(?:M(?:i(?:nutes|lliseconds)|onth)|Seconds|Hours|Date|FullYear)|FullYear|Active)|arch)|qrt|lice|avePreferences|mall)|h(?:ome|andleEvent)|navigate|c(?:har(?:CodeAt|At)|o(?:s|n(?:cat|textual|firm)|mpile)|eil|lear(?:Timeout|Interval)?|a(?:ptureEvents|ll)|reate(?:StyleSheet|Popup|EventObject))|t(?:o(?:GMTString|S(?:tring|ource)|U(?:TCString|pperCase)|Lo(?:caleString|werCase))|est|a(?:n|int(?:Enabled)?))|i(?:s(?:NaN|Finite)|ndexOf|talics)|d(?:isableExternalCapture|ump|etachEvent)|u(?:n(?:shift|taint|escape|watch)|pdateCommands)|j(?:oin|avaEnabled)|p(?:o(?:p|w)|ush|lugins.refresh|a(?:ddings|rse(?:Int|Float)?)|r(?:int|ompt|eference))|e(?:scape|nableExternalCapture|val|lementFromPoint|x(?:p|ec(?:Script|Command)?))|valueOf|UTC|queryCommand(?:State|Indeterm|Enabled|Value)|f(?:i(?:nd|le(?:ModifiedDate|Size|CreatedDate|UpdatedDate)|xed)|o(?:nt(?:size|color)|rward)|loor|romCharCode)|watch|l(?:ink|o(?:ad|g)|astIndexOf)|a(?:sin|nchor|cos|t(?:tachEvent|ob|an(?:2)?)|pply|lert|b(?:s|ort))|r(?:ou(?:nd|teEvents)|e(?:size(?:By|To)|calc|turnValue|place|verse|l(?:oad|ease(?:Capture|Events)))|andom)|g(?:o|et(?:ResponseHeader|M(?:i(?:nutes|lliseconds)|onth)|Se(?:conds|lection)|Hours|Year|Time(?:zoneOffset)?|Da(?:y|te)|UTC(?:M(?:i(?:nutes|lliseconds)|onth)|Seconds|Hours|Da(?:y|te)|FullYear)|FullYear|A(?:ttention|llResponseHeaders)))|m(?:in|ove(?:B(?:y|elow)|To(?:Absolute)?|Above)|ergeAttributes|a(?:tch|rgins|x))|b(?:toa|ig|o(?:ld|rderWidths)|link|ack))\b(?=\()/},{token:["punctuation.operator","support.function.dom"],regex:/(\.)(s(?:ub(?:stringData|mit)|plitText|e(?:t(?:NamedItem|Attribute(?:Node)?)|lect))|has(?:ChildNodes|Feature)|namedItem|c(?:l(?:ick|o(?:se|neNode))|reate(?:C(?:omment|DATASection|aption)|T(?:Head|extNode|Foot)|DocumentFragment|ProcessingInstruction|E(?:ntityReference|lement)|Attribute))|tabIndex|i(?:nsert(?:Row|Before|Cell|Data)|tem)|open|delete(?:Row|C(?:ell|aption)|T(?:Head|Foot)|Data)|focus|write(?:ln)?|a(?:dd|ppend(?:Child|Data))|re(?:set|place(?:Child|Data)|move(?:NamedItem|Child|Attribute(?:Node)?)?)|get(?:NamedItem|Element(?:sBy(?:Name|TagName)|ById)|Attribute(?:Node)?)|blur)\b(?=\()/},{token:["punctuation.operator","support.constant"],regex:/(\.)(s(?:ystemLanguage|cr(?:ipts|ollbars|een(?:X|Y|Top|Left))|t(?:yle(?:Sheets)?|atus(?:Text|bar)?)|ibling(?:Below|Above)|ource|uffixes|e(?:curity(?:Policy)?|l(?:ection|f)))|h(?:istory|ost(?:name)?|as(?:h|Focus))|y|X(?:MLDocument|SLDocument)|n(?:ext|ame(?:space(?:s|URI)|Prop))|M(?:IN_VALUE|AX_VALUE)|c(?:haracterSet|o(?:n(?:structor|trollers)|okieEnabled|lorDepth|mp(?:onents|lete))|urrent|puClass|l(?:i(?:p(?:boardData)?|entInformation)|osed|asses)|alle(?:e|r)|rypto)|t(?:o(?:olbar|p)|ext(?:Transform|Indent|Decoration|Align)|ags)|SQRT(?:1_2|2)|i(?:n(?:ner(?:Height|Width)|put)|ds|gnoreCase)|zIndex|o(?:scpu|n(?:readystatechange|Line)|uter(?:Height|Width)|p(?:sProfile|ener)|ffscreenBuffering)|NEGATIVE_INFINITY|d(?:i(?:splay|alog(?:Height|Top|Width|Left|Arguments)|rectories)|e(?:scription|fault(?:Status|Ch(?:ecked|arset)|View)))|u(?:ser(?:Profile|Language|Agent)|n(?:iqueID|defined)|pdateInterval)|_content|p(?:ixelDepth|ort|ersonalbar|kcs11|l(?:ugins|atform)|a(?:thname|dding(?:Right|Bottom|Top|Left)|rent(?:Window|Layer)?|ge(?:X(?:Offset)?|Y(?:Offset)?))|r(?:o(?:to(?:col|type)|duct(?:Sub)?|mpter)|e(?:vious|fix)))|e(?:n(?:coding|abledPlugin)|x(?:ternal|pando)|mbeds)|v(?:isibility|endor(?:Sub)?|Linkcolor)|URLUnencoded|P(?:I|OSITIVE_INFINITY)|f(?:ilename|o(?:nt(?:Size|Family|Weight)|rmName)|rame(?:s|Element)|gColor)|E|whiteSpace|l(?:i(?:stStyleType|n(?:eHeight|kColor))|o(?:ca(?:tion(?:bar)?|lName)|wsrc)|e(?:ngth|ft(?:Context)?)|a(?:st(?:M(?:odified|atch)|Index|Paren)|yer(?:s|X)|nguage))|a(?:pp(?:MinorVersion|Name|Co(?:deName|re)|Version)|vail(?:Height|Top|Width|Left)|ll|r(?:ity|guments)|Linkcolor|bove)|r(?:ight(?:Context)?|e(?:sponse(?:XML|Text)|adyState))|global|x|m(?:imeTypes|ultiline|enubar|argin(?:Right|Bottom|Top|Left))|L(?:N(?:10|2)|OG(?:10E|2E))|b(?:o(?:ttom|rder(?:Width|RightWidth|BottomWidth|Style|Color|TopWidth|LeftWidth))|ufferDepth|elow|ackground(?:Color|Image)))\b/},{token:["storage.type","punctuation.operator","support.function.firebug"],regex:/(console)(\.)(warn|info|log|error|time|timeEnd|assert)\b/},{token:function(c){return a.hasOwnProperty(c)?"variable.language":d.hasOwnProperty(c)?"invalid.deprecated":h.hasOwnProperty(c)?"storage.type":b.hasOwnProperty(c)?"keyword":i.hasOwnProperty(c)?"constant.language":j.hasOwnProperty(c)?"invalid.illegal":c=="debugger"?"invalid.deprecated":"identifier"},regex:k},{token:"keyword.operator",regex:/!|\$|%|&|\*|\-\-|\-|\+\+|\+|~|===|==|=|!=|!==|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\|\||\?\:|\*=|%=|\+=|\-=|&=|\^=|\b(?:in|instanceof|new|delete|typeof|void)/,next:"regex_allowed"},{token:"punctuation.operator",regex:/\?|\:|\,|\;|\./,next:"regex_allowed"},{token:"paren.lparen",regex:/[\[({]/,next:"regex_allowed"},{token:"paren.rparen",regex:/[\])}]/},{token:"keyword.operator",regex:/\/=?/,next:"regex_allowed"},{token:"comment",regex:/^#!.*$/},{token:"text",regex:/\s+/}],regex_allowed:[{token:"comment",merge:!0,regex:"\\/\\*",next:"comment_regex_allowed"},{token:"comment",regex:"\\/\\/.*$"},{token:"string.regexp",regex:"\\/",next:"regex",merge:!0},{token:"text",regex:"\\s+"},{token:"empty",regex:"",next:"start"}],regex:[{token:"regexp.keyword.operator",regex:"\\\\(?:u[\\da-fA-F]{4}|x[\\da-fA-F]{2}|.)",next:"regex"},{token:"string.regexp",regex:"/\\w*",next:"start",merge:!0},{token:"string.regexp",regex:"[^\\\\/\\[]+",next:"regex",merge:!0},{token:"string.regexp.charachterclass",regex:"\\[",next:"regex_character_class",merge:!0},{token:"empty",regex:"",next:"start"}],regex_character_class:[{token:"regexp.keyword.operator",regex:"\\\\(?:u[\\da-fA-F]{4}|x[\\da-fA-F]{2}|.)",next:"regex_character_class"},{token:"string.regexp.charachterclass",regex:"]",next:"regex",merge:!0},{token:"string.regexp.charachterclass",regex:"[^\\\\\\]]+",next:"regex_character_class",merge:!0},{token:"empty",regex:"",next:"start"}],comment_regex_allowed:[{token:"comment",regex:".*?\\*\\/",merge:!0,next:"regex_allowed"},{token:"comment",merge:!0,regex:".+"}],comment:[{token:"comment",regex:".*?\\*\\/",merge:!0,next:"start"},{token:"comment",merge:!0,regex:".+"}],qqstring:[{token:"constant.language.escape",regex:l},{token:"string",regex:'[^"\\\\]+'},{token:"string",regex:'"',next:"start"}],qstring:[{token:"constant.language.escape",regex:l},{token:"string",regex:"[^'\\\\]+"},{token:"string",regex:"'",next:"start"}]},this.embedRules(g,"doc-",[(new g).getEndRule("start")])};d.inherits(i,h),b.JavaScriptHighlightRules=i}),define("ace/mode/doc_comment_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("./text_highlight_rules").TextHighlightRules,f=function(){this.$rules={start:[{token:"comment.doc.tag",regex:"@[\\w\\d_]+"},{token:"comment.doc",merge:!0,regex:"\\s+"},{token:"comment.doc",merge:!0,regex:"TODO"},{token:"comment.doc",merge:!0,regex:"[^@\\*]+"},{token:"comment.doc",merge:!0,regex:"."}]}};d.inherits(f,e),function(){this.getStartRule=function(a){return{token:"comment.doc",merge:!0,regex:"\\/\\*(?=\\*)",next:a}},this.getEndRule=function(a){return{token:"comment.doc",merge:!0,regex:"\\*\\/",next:a}}}.call(f.prototype),b.DocCommentHighlightRules=f}),define("ace/mode/matching_brace_outdent",["require","exports","module","ace/range"],function(a,b,c){"use strict";var d=a("../range").Range,e=function(){};(function(){this.checkOutdent=function(a,b){return/^\s+$/.test(a)?/^\s*\}/.test(b):!1},this.autoOutdent=function(a,b){var c=a.getLine(b),e=c.match(/^(\s*\})/);if(!e)return 0;var f=e[1].length,g=a.findMatchingBracket({row:b,column:f});if(!g||g.row==b)return 0;var h=this.$getIndent(a.getLine(g.row));a.replace(new d(b,0,b,f-1),h)},this.$getIndent=function(a){var b=a.match(/^(\s+)/);return b?b[1]:""}}).call(e.prototype),b.MatchingBraceOutdent=e}),define("ace/mode/behaviour/cstyle",["require","exports","module","ace/lib/oop","ace/mode/behaviour"],function(a,b,c){"use strict";var d=a("../../lib/oop"),e=a("../behaviour").Behaviour,f=function(){this.add("braces","insertion",function(a,b,c,d,e){if(e=="{"){var f=c.getSelectionRange(),g=d.doc.getTextRange(f);return g!==""?{text:"{"+g+"}",selection:!1}:{text:"{}",selection:[1,1]}}if(e=="}"){var h=c.getCursorPosition(),i=d.doc.getLine(h.row),j=i.substring(h.column,h.column+1);if(j=="}"){var k=d.$findOpeningBracket("}",{column:h.column+1,row:h.row});if(k!==null)return{text:"",selection:[1,1]}}}else if(e=="\n"){var h=c.getCursorPosition(),i=d.doc.getLine(h.row),j=i.substring(h.column,h.column+1);if(j=="}"){var l=d.findMatchingBracket({row:h.row,column:h.column+1});if(!l)return null;var m=this.getNextLineIndent(a,i.substring(0,i.length-1),d.getTabString()),n=this.$getIndent(d.doc.getLine(l.row));return{text:"\n"+m+"\n"+n,selection:[1,m.length,1,m.length]}}}}),this.add("braces","deletion",function(a,b,c,d,e){var f=d.doc.getTextRange(e);if(!e.isMultiLine()&&f=="{"){var g=d.doc.getLine(e.start.row),h=g.substring(e.end.column,e.end.column+1);if(h=="}")return e.end.column++,e}}),this.add("parens","insertion",function(a,b,c,d,e){if(e=="("){var f=c.getSelectionRange(),g=d.doc.getTextRange(f);return g!==""?{text:"("+g+")",selection:!1}:{text:"()",selection:[1,1]}}if(e==")"){var h=c.getCursorPosition(),i=d.doc.getLine(h.row),j=i.substring(h.column,h.column+1);if(j==")"){var k=d.$findOpeningBracket(")",{column:h.column+1,row:h.row});if(k!==null)return{text:"",selection:[1,1]}}}}),this.add("parens","deletion",function(a,b,c,d,e){var f=d.doc.getTextRange(e);if(!e.isMultiLine()&&f=="("){var g=d.doc.getLine(e.start.row),h=g.substring(e.start.column+1,e.start.column+2);if(h==")")return e.end.column++,e}}),this.add("string_dquotes","insertion",function(a,b,c,d,e){if(e=='"'||e=="'"){var f=e,g=c.getSelectionRange(),h=d.doc.getTextRange(g);if(h!=="")return{text:f+h+f,selection:!1};var i=c.getCursorPosition(),j=d.doc.getLine(i.row),k=j.substring(i.column-1,i.column);if(k=="\\")return null;var l=d.getTokens(g.start.row,g.start.row)[0].tokens,m=0,n,o=-1;for(var p=0;p<l.length;p++){n=l[p],n.type=="string"?o=-1:o<0&&(o=n.value.indexOf(f));if(n.value.length+m>g.start.column)break;m+=l[p].value.length}if(!n||o<0&&n.type!=="comment"&&(n.type!=="string"||g.start.column!==n.value.length+m-1&&n.value.lastIndexOf(f)===n.value.length-1))return{text:f+f,selection:[1,1]};if(n&&n.type==="string"){var q=j.substring(i.column,i.column+1);if(q==f)return{text:"",selection:[1,1]}}}}),this.add("string_dquotes","deletion",function(a,b,c,d,e){var f=d.doc.getTextRange(e);if(!e.isMultiLine()&&(f=='"'||f=="'")){var g=d.doc.getLine(e.start.row),h=g.substring(e.start.column+1,e.start.column+2);if(h=='"')return e.end.column++,e}})};d.inherits(f,e),b.CstyleBehaviour=f}),define("ace/mode/folding/cstyle",["require","exports","module","ace/lib/oop","ace/range","ace/mode/folding/fold_mode"],function(a,b,c){"use strict";var d=a("../../lib/oop"),e=a("../../range").Range,f=a("./fold_mode").FoldMode,g=b.FoldMode=function(){};d.inherits(g,f),function(){this.foldingStartMarker=/(\{|\[)[^\}\]]*$|^\s*(\/\*)/,this.foldingStopMarker=/^[^\[\{]*(\}|\])|^[\s\*]*(\*\/)/,this.getFoldWidgetRange=function(a,b,c){var d=a.getLine(c),f=d.match(this.foldingStartMarker);if(f){var g=f.index;if(f[1])return this.openingBracketBlock(a,f[1],c,g);var h=a.getCommentFoldRange(c,g+f[0].length);return h.end.column-=2,h}if(b!=="markbeginend")return;var f=d.match(this.foldingStopMarker);if(f){var g=f.index+f[0].length;if(f[2]){var h=a.getCommentFoldRange(c,g);return h.end.column-=2,h}var i={row:c,column:g},j=a.$findOpeningBracket(f[1],i);if(!j)return;return j.column++,i.column--,e.fromPoints(j,i)}}}.call(g.prototype)}),define("ace/mode/folding/fold_mode",["require","exports","module","ace/range"],function(a,b,c){"use strict";var d=a("../../range").Range,e=b.FoldMode=function(){};(function(){this.foldingStartMarker=null,this.foldingStopMarker=null,this.getFoldWidget=function(a,b,c){var d=a.getLine(c);return this.foldingStartMarker.test(d)?"start":b=="markbeginend"&&this.foldingStopMarker&&this.foldingStopMarker.test(d)?"end":""},this.getFoldWidgetRange=function(a,b,c){return null},this.indentationBlock=function(a,b,c){var e=/^\s*/,f=b,g=b,h=a.getLine(b),i=c||h.length,j=h.match(e)[0].length,k=a.getLength();while(++b<k){h=a.getLine(b);var l=h.match(e)[0].length;if(l==h.length)continue;if(l<=j)break;g=b}if(g>f){var m=a.getLine(g).length;return new d(f,i,g,m)}},this.openingBracketBlock=function(a,b,c,e){var f={row:c,column:e+1},g=a.$findClosingBracket(b,f);if(!g)return;var h=a.foldWidgets[g.row];return h==null&&(h=this.getFoldWidget(a,g.row)),h=="start"&&(g.row--,g.column=a.getLine(g.row).length),d.fromPoints(f,g)}}).call(e.prototype)}),define("ace/mode/groovy_highlight_rules",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/mode/doc_comment_highlight_rules","ace/mode/text_highlight_rules"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("../lib/lang"),f=a("./doc_comment_highlight_rules").DocCommentHighlightRules,g=a("./text_highlight_rules").TextHighlightRules,h=function(){var a=e.arrayToMap("assert|with|abstract|continue|for|new|switch|assert|default|goto|package|synchronized|boolean|do|if|private|this|break|double|implements|protected|throw|byte|else|import|public|throws|case|enum|instanceof|return|transient|catch|extends|int|short|try|char|final|interface|static|void|class|finally|long|strictfp|volatile|def|float|native|super|while".split("|")),b=e.arrayToMap("null|Infinity|NaN|undefined".split("|")),c=e.arrayToMap("AbstractMethodError|AssertionError|ClassCircularityError|ClassFormatError|Deprecated|EnumConstantNotPresentException|ExceptionInInitializerError|IllegalAccessError|IllegalThreadStateException|InstantiationError|InternalError|NegativeArraySizeException|NoSuchFieldError|Override|Process|ProcessBuilder|SecurityManager|StringIndexOutOfBoundsException|SuppressWarnings|TypeNotPresentException|UnknownError|UnsatisfiedLinkError|UnsupportedClassVersionError|VerifyError|InstantiationException|IndexOutOfBoundsException|ArrayIndexOutOfBoundsException|CloneNotSupportedException|NoSuchFieldException|IllegalArgumentException|NumberFormatException|SecurityException|Void|InheritableThreadLocal|IllegalStateException|InterruptedException|NoSuchMethodException|IllegalAccessException|UnsupportedOperationException|Enum|StrictMath|Package|Compiler|Readable|Runtime|StringBuilder|Math|IncompatibleClassChangeError|NoSuchMethodError|ThreadLocal|RuntimePermission|ArithmeticException|NullPointerException|Long|Integer|Short|Byte|Double|Number|Float|Character|Boolean|StackTraceElement|Appendable|StringBuffer|Iterable|ThreadGroup|Runnable|Thread|IllegalMonitorStateException|StackOverflowError|OutOfMemoryError|VirtualMachineError|ArrayStoreException|ClassCastException|LinkageError|NoClassDefFoundError|ClassNotFoundException|RuntimeException|Exception|ThreadDeath|Error|Throwable|System|ClassLoader|Cloneable|Class|CharSequence|Comparable|String|Object".split("|")),d=e.arrayToMap("".split("|"));this.$rules={start:[{token:"comment",regex:"\\/\\/.*$"},(new f).getStartRule("doc-start"),{token:"comment",merge:!0,regex:"\\/\\*",next:"comment"},{token:"string.regexp",regex:"[/](?:(?:\\[(?:\\\\]|[^\\]])+\\])|(?:\\\\/|[^\\]/]))*[/]\\w*\\s*(?=[).,;]|$)"},{token:"string",regex:'["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'},{token:"string",regex:"['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"},{token:"constant.numeric",regex:"0[xX][0-9a-fA-F]+\\b"},{token:"constant.numeric",regex:"[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"},{token:"constant.language.boolean",regex:"(?:true|false)\\b"},{token:function(e){return e=="this"?"variable.language":a.hasOwnProperty(e)?"keyword":c.hasOwnProperty(e)?"support.function":d.hasOwnProperty(e)?"support.function":b.hasOwnProperty(e)?"constant.language":"identifier"},regex:"[a-zA-Z_$][a-zA-Z0-9_$]*\\b"},{token:"keyword.operator",regex:"\\?:|\\?\\.|\\*\\.|<=>|=~|==~|\\.@|\\*\\.@|\\.&|as|in|is|!|\\$|%|&|\\*|\\-\\-|\\-|\\+\\+|\\+|~|===|==|=|!=|!==|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\\|\\||\\?\\:|\\*=|%=|\\+=|\\-=|&=|\\^=|\\b(?:in|instanceof|new|delete|typeof|void)"},{token:"lparen",regex:"[[({]"},{token:"rparen",regex:"[\\])}]"},{token:"text",regex:"\\s+"}],comment:[{token:"comment",regex:".*?\\*\\/",next:"start"},{token:"comment",merge:!0,regex:".+"}]},this.embedRules(f,"doc-",[(new f).getEndRule("start")])};d.inherits(h,g),b.GroovyHighlightRules=h})
\ No newline at end of file
diff --git a/apps/files_texteditor/js/aceeditor/mode-haxe-uncompressed.js b/apps/files_texteditor/js/aceeditor/mode-haxe-uncompressed.js
old mode 100755
new mode 100644
index 5496580ed3396370d8d6c795fff8c12216d5f429..7efa04c5f679e802e7f2b61ca0c0ad67625cce7c
--- a/apps/files_texteditor/js/aceeditor/mode-haxe-uncompressed.js
+++ b/apps/files_texteditor/js/aceeditor/mode-haxe-uncompressed.js
@@ -391,12 +391,12 @@ var CstyleBehaviour = function () {
                 return {
                     text: '{' + selected + '}',
                     selection: false
-                }
+                };
             } else {
                 return {
                     text: '{}',
                     selection: [1, 1]
-                }
+                };
             }
         } else if (text == '}') {
             var cursor = editor.getCursorPosition();
@@ -408,7 +408,7 @@ var CstyleBehaviour = function () {
                     return {
                         text: '',
                         selection: [1, 1]
-                    }
+                    };
                 }
             }
         } else if (text == "\n") {
@@ -426,7 +426,7 @@ var CstyleBehaviour = function () {
                 return {
                     text: '\n' + indent + '\n' + next_indent,
                     selection: [1, indent.length, 1, indent.length]
-                }
+                };
             }
         }
     });
@@ -451,12 +451,12 @@ var CstyleBehaviour = function () {
                 return {
                     text: '(' + selected + ')',
                     selection: false
-                }
+                };
             } else {
                 return {
                     text: '()',
                     selection: [1, 1]
-                }
+                };
             }
         } else if (text == ')') {
             var cursor = editor.getCursorPosition();
@@ -468,7 +468,7 @@ var CstyleBehaviour = function () {
                     return {
                         text: '',
                         selection: [1, 1]
-                    }
+                    };
                 }
             }
         }
@@ -487,14 +487,15 @@ var CstyleBehaviour = function () {
     });
 
     this.add("string_dquotes", "insertion", function (state, action, editor, session, text) {
-        if (text == '"') {
+        if (text == '"' || text == "'") {
+            var quote = text;
             var selection = editor.getSelectionRange();
             var selected = session.doc.getTextRange(selection);
             if (selected !== "") {
                 return {
-                    text: '"' + selected + '"',
+                    text: quote + selected + quote,
                     selection: false
-                }
+                };
             } else {
                 var cursor = editor.getCursorPosition();
                 var line = session.doc.getLine(cursor.row);
@@ -515,7 +516,7 @@ var CstyleBehaviour = function () {
                     if (token.type == "string") {
                       quotepos = -1;
                     } else if (quotepos < 0) {
-                      quotepos = token.value.indexOf('"');
+                      quotepos = token.value.indexOf(quote);
                     }
                     if ((token.value.length + col) > selection.start.column) {
                         break;
@@ -524,19 +525,19 @@ var CstyleBehaviour = function () {
                 }
 
                 // Try and be smart about when we auto insert.
-                if (!token || (quotepos < 0 && token.type !== "comment" && (token.type !== "string" || ((selection.start.column !== token.value.length+col-1) && token.value.lastIndexOf('"') === token.value.length-1)))) {
+                if (!token || (quotepos < 0 && token.type !== "comment" && (token.type !== "string" || ((selection.start.column !== token.value.length+col-1) && token.value.lastIndexOf(quote) === token.value.length-1)))) {
                     return {
-                        text: '""',
+                        text: quote + quote,
                         selection: [1,1]
-                    }
+                    };
                 } else if (token && token.type === "string") {
                     // Ignore input and move right one if we're typing over the closing quote.
                     var rightChar = line.substring(cursor.column, cursor.column + 1);
-                    if (rightChar == '"') {
+                    if (rightChar == quote) {
                         return {
                             text: '',
                             selection: [1, 1]
-                        }
+                        };
                     }
                 }
             }
@@ -545,7 +546,7 @@ var CstyleBehaviour = function () {
 
     this.add("string_dquotes", "deletion", function (state, action, editor, session, range) {
         var selected = session.doc.getTextRange(range);
-        if (!range.isMultiLine() && selected == '"') {
+        if (!range.isMultiLine() && (selected == '"' || selected == "'")) {
             var line = session.doc.getLine(range.start.row);
             var rightChar = line.substring(range.start.column + 1, range.start.column + 2);
             if (rightChar == '"') {
@@ -555,7 +556,8 @@ var CstyleBehaviour = function () {
         }
     });
 
-}
+};
+
 oop.inherits(CstyleBehaviour, Behaviour);
 
 exports.CstyleBehaviour = CstyleBehaviour;
@@ -766,13 +768,3 @@ var FoldMode = exports.FoldMode = function() {};
 }).call(FoldMode.prototype);
 
 });
-;
-            (function() {
-                window.require(["ace/ace"], function(a) {
-                    if (!window.ace)
-                        window.ace = {};
-                    for (var key in a) if (a.hasOwnProperty(key))
-                        ace[key] = a[key];
-                });
-            })();
-        
\ No newline at end of file
diff --git a/apps/files_texteditor/js/aceeditor/mode-haxe.js b/apps/files_texteditor/js/aceeditor/mode-haxe.js
old mode 100755
new mode 100644
index 88818b1371a917a2f1e4a282a04586b59e96fc3d..0c0d15f39351decb9236120461607f7e826aa7d3
--- a/apps/files_texteditor/js/aceeditor/mode-haxe.js
+++ b/apps/files_texteditor/js/aceeditor/mode-haxe.js
@@ -1 +1 @@
-define("ace/mode/haxe",["require","exports","module","ace/lib/oop","ace/mode/text","ace/tokenizer","ace/mode/haxe_highlight_rules","ace/mode/matching_brace_outdent","ace/mode/behaviour/cstyle","ace/mode/folding/cstyle"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("./text").Mode,f=a("../tokenizer").Tokenizer,g=a("./haxe_highlight_rules").HaxeHighlightRules,h=a("./matching_brace_outdent").MatchingBraceOutdent,i=a("./behaviour/cstyle").CstyleBehaviour,j=a("./folding/cstyle").FoldMode,k=function(){this.$tokenizer=new f((new g).getRules()),this.$outdent=new h,this.$behaviour=new i,this.foldingRules=new j};d.inherits(k,e),function(){this.getNextLineIndent=function(a,b,c){var d=this.$getIndent(b),e=this.$tokenizer.getLineTokens(b,a),f=e.tokens;if(f.length&&f[f.length-1].type=="comment")return d;if(a=="start"){var g=b.match(/^.*[\{\(\[]\s*$/);g&&(d+=c)}return d},this.checkOutdent=function(a,b,c){return this.$outdent.checkOutdent(b,c)},this.autoOutdent=function(a,b,c){this.$outdent.autoOutdent(b,c)},this.createWorker=function(a){return null}}.call(k.prototype),b.Mode=k}),define("ace/mode/haxe_highlight_rules",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/mode/doc_comment_highlight_rules","ace/mode/text_highlight_rules"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("../lib/lang"),f=a("./doc_comment_highlight_rules").DocCommentHighlightRules,g=a("./text_highlight_rules").TextHighlightRules,h=function(){var a=e.arrayToMap("break|case|cast|catch|class|continue|default|else|enum|extends|for|function|if|implements|import|in|inline|interface|new|override|package|private|public|return|static|super|switch|this|throw|trace|try|typedef|untyped|var|while|Array|Void|Bool|Int|UInt|Float|Dynamic|String|List|Hash|IntHash|Error|Unknown|Type|Std".split("|")),b=e.arrayToMap("null|true|false".split("|"));this.$rules={start:[{token:"comment",regex:"\\/\\/.*$"},(new f).getStartRule("doc-start"),{token:"comment",regex:"\\/\\*",merge:!0,next:"comment"},{token:"string.regexp",regex:"[/](?:(?:\\[(?:\\\\]|[^\\]])+\\])|(?:\\\\/|[^\\]/]))*[/]\\w*\\s*(?=[).,;]|$)"},{token:"string",regex:'["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'},{token:"string",regex:"['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"},{token:"constant.numeric",regex:"0[xX][0-9a-fA-F]+\\b"},{token:"constant.numeric",regex:"[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"},{token:"constant.language.boolean",regex:"(?:true|false)\\b"},{token:function(c){return c=="this"?"variable.language":a.hasOwnProperty(c)?"keyword":b.hasOwnProperty(c)?"constant.language":"identifier"},regex:"[a-zA-Z_$][a-zA-Z0-9_$]*\\b"},{token:"keyword.operator",regex:"!|\\$|%|&|\\*|\\-\\-|\\-|\\+\\+|\\+|~|===|==|=|!=|!==|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\\|\\||\\?\\:|\\*=|%=|\\+=|\\-=|&=|\\^=|\\b(?:in|instanceof|new|delete|typeof|void)"},{token:"punctuation.operator",regex:"\\?|\\:|\\,|\\;|\\."},{token:"paren.lparen",regex:"[[({<]"},{token:"paren.rparen",regex:"[\\])}>]"},{token:"text",regex:"\\s+"}],comment:[{token:"comment",regex:".*?\\*\\/",next:"start"},{token:"comment",merge:!0,regex:".+"}]},this.embedRules(f,"doc-",[(new f).getEndRule("start")])};d.inherits(h,g),b.HaxeHighlightRules=h}),define("ace/mode/doc_comment_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("./text_highlight_rules").TextHighlightRules,f=function(){this.$rules={start:[{token:"comment.doc.tag",regex:"@[\\w\\d_]+"},{token:"comment.doc",merge:!0,regex:"\\s+"},{token:"comment.doc",merge:!0,regex:"TODO"},{token:"comment.doc",merge:!0,regex:"[^@\\*]+"},{token:"comment.doc",merge:!0,regex:"."}]}};d.inherits(f,e),function(){this.getStartRule=function(a){return{token:"comment.doc",merge:!0,regex:"\\/\\*(?=\\*)",next:a}},this.getEndRule=function(a){return{token:"comment.doc",merge:!0,regex:"\\*\\/",next:a}}}.call(f.prototype),b.DocCommentHighlightRules=f}),define("ace/mode/matching_brace_outdent",["require","exports","module","ace/range"],function(a,b,c){"use strict";var d=a("../range").Range,e=function(){};((function(){this.checkOutdent=function(a,b){return/^\s+$/.test(a)?/^\s*\}/.test(b):!1},this.autoOutdent=function(a,b){var c=a.getLine(b),e=c.match(/^(\s*\})/);if(!e)return 0;var f=e[1].length,g=a.findMatchingBracket({row:b,column:f});if(!g||g.row==b)return 0;var h=this.$getIndent(a.getLine(g.row));a.replace(new d(b,0,b,f-1),h)},this.$getIndent=function(a){var b=a.match(/^(\s+)/);return b?b[1]:""}})).call(e.prototype),b.MatchingBraceOutdent=e}),define("ace/mode/behaviour/cstyle",["require","exports","module","ace/lib/oop","ace/mode/behaviour"],function(a,b,c){"use strict";var d=a("../../lib/oop"),e=a("../behaviour").Behaviour,f=function(){this.add("braces","insertion",function(a,b,c,d,e){if(e=="{"){var f=c.getSelectionRange(),g=d.doc.getTextRange(f);return g!==""?{text:"{"+g+"}",selection:!1}:{text:"{}",selection:[1,1]}}if(e=="}"){var h=c.getCursorPosition(),i=d.doc.getLine(h.row),j=i.substring(h.column,h.column+1);if(j=="}"){var k=d.$findOpeningBracket("}",{column:h.column+1,row:h.row});if(k!==null)return{text:"",selection:[1,1]}}}else if(e=="\n"){var h=c.getCursorPosition(),i=d.doc.getLine(h.row),j=i.substring(h.column,h.column+1);if(j=="}"){var l=d.findMatchingBracket({row:h.row,column:h.column+1});if(!l)return null;var m=this.getNextLineIndent(a,i.substring(0,i.length-1),d.getTabString()),n=this.$getIndent(d.doc.getLine(l.row));return{text:"\n"+m+"\n"+n,selection:[1,m.length,1,m.length]}}}}),this.add("braces","deletion",function(a,b,c,d,e){var f=d.doc.getTextRange(e);if(!e.isMultiLine()&&f=="{"){var g=d.doc.getLine(e.start.row),h=g.substring(e.end.column,e.end.column+1);if(h=="}")return e.end.column++,e}}),this.add("parens","insertion",function(a,b,c,d,e){if(e=="("){var f=c.getSelectionRange(),g=d.doc.getTextRange(f);return g!==""?{text:"("+g+")",selection:!1}:{text:"()",selection:[1,1]}}if(e==")"){var h=c.getCursorPosition(),i=d.doc.getLine(h.row),j=i.substring(h.column,h.column+1);if(j==")"){var k=d.$findOpeningBracket(")",{column:h.column+1,row:h.row});if(k!==null)return{text:"",selection:[1,1]}}}}),this.add("parens","deletion",function(a,b,c,d,e){var f=d.doc.getTextRange(e);if(!e.isMultiLine()&&f=="("){var g=d.doc.getLine(e.start.row),h=g.substring(e.start.column+1,e.start.column+2);if(h==")")return e.end.column++,e}}),this.add("string_dquotes","insertion",function(a,b,c,d,e){if(e=='"'){var f=c.getSelectionRange(),g=d.doc.getTextRange(f);if(g!=="")return{text:'"'+g+'"',selection:!1};var h=c.getCursorPosition(),i=d.doc.getLine(h.row),j=i.substring(h.column-1,h.column);if(j=="\\")return null;var k=d.getTokens(f.start.row,f.start.row)[0].tokens,l=0,m,n=-1;for(var o=0;o<k.length;o++){m=k[o],m.type=="string"?n=-1:n<0&&(n=m.value.indexOf('"'));if(m.value.length+l>f.start.column)break;l+=k[o].value.length}if(!m||n<0&&m.type!=="comment"&&(m.type!=="string"||f.start.column!==m.value.length+l-1&&m.value.lastIndexOf('"')===m.value.length-1))return{text:'""',selection:[1,1]};if(m&&m.type==="string"){var p=i.substring(h.column,h.column+1);if(p=='"')return{text:"",selection:[1,1]}}}}),this.add("string_dquotes","deletion",function(a,b,c,d,e){var f=d.doc.getTextRange(e);if(!e.isMultiLine()&&f=='"'){var g=d.doc.getLine(e.start.row),h=g.substring(e.start.column+1,e.start.column+2);if(h=='"')return e.end.column++,e}})};d.inherits(f,e),b.CstyleBehaviour=f}),define("ace/mode/folding/cstyle",["require","exports","module","ace/lib/oop","ace/range","ace/mode/folding/fold_mode"],function(a,b,c){"use strict";var d=a("../../lib/oop"),e=a("../../range").Range,f=a("./fold_mode").FoldMode,g=b.FoldMode=function(){};d.inherits(g,f),function(){this.foldingStartMarker=/(\{|\[)[^\}\]]*$|^\s*(\/\*)/,this.foldingStopMarker=/^[^\[\{]*(\}|\])|^[\s\*]*(\*\/)/,this.getFoldWidgetRange=function(a,b,c){var d=a.getLine(c),f=d.match(this.foldingStartMarker);if(f){var g=f.index;if(f[1])return this.openingBracketBlock(a,f[1],c,g);var h=a.getCommentFoldRange(c,g+f[0].length);return h.end.column-=2,h}if(b!=="markbeginend")return;var f=d.match(this.foldingStopMarker);if(f){var g=f.index+f[0].length;if(f[2]){var h=a.getCommentFoldRange(c,g);return h.end.column-=2,h}var i={row:c,column:g},j=a.$findOpeningBracket(f[1],i);if(!j)return;return j.column++,i.column--,e.fromPoints(j,i)}}}.call(g.prototype)}),define("ace/mode/folding/fold_mode",["require","exports","module","ace/range"],function(a,b,c){"use strict";var d=a("../../range").Range,e=b.FoldMode=function(){};((function(){this.foldingStartMarker=null,this.foldingStopMarker=null,this.getFoldWidget=function(a,b,c){var d=a.getLine(c);return this.foldingStartMarker.test(d)?"start":b=="markbeginend"&&this.foldingStopMarker&&this.foldingStopMarker.test(d)?"end":""},this.getFoldWidgetRange=function(a,b,c){return null},this.indentationBlock=function(a,b,c){var e=/^\s*/,f=b,g=b,h=a.getLine(b),i=c||h.length,j=h.match(e)[0].length,k=a.getLength();while(++b<k){h=a.getLine(b);var l=h.match(e)[0].length;if(l==h.length)continue;if(l<=j)break;g=b}if(g>f){var m=a.getLine(g).length;return new d(f,i,g,m)}},this.openingBracketBlock=function(a,b,c,e){var f={row:c,column:e+1},g=a.$findClosingBracket(b,f);if(!g)return;var h=a.foldWidgets[g.row];return h==null&&(h=this.getFoldWidget(a,g.row)),h=="start"&&(g.row--,g.column=a.getLine(g.row).length),d.fromPoints(f,g)}})).call(e.prototype)}),function(){window.require(["ace/ace"],function(a){window.ace||(window.ace={});for(var b in a)a.hasOwnProperty(b)&&(ace[b]=a[b])})}()
\ No newline at end of file
+define("ace/mode/haxe",["require","exports","module","ace/lib/oop","ace/mode/text","ace/tokenizer","ace/mode/haxe_highlight_rules","ace/mode/matching_brace_outdent","ace/mode/behaviour/cstyle","ace/mode/folding/cstyle"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("./text").Mode,f=a("../tokenizer").Tokenizer,g=a("./haxe_highlight_rules").HaxeHighlightRules,h=a("./matching_brace_outdent").MatchingBraceOutdent,i=a("./behaviour/cstyle").CstyleBehaviour,j=a("./folding/cstyle").FoldMode,k=function(){this.$tokenizer=new f((new g).getRules()),this.$outdent=new h,this.$behaviour=new i,this.foldingRules=new j};d.inherits(k,e),function(){this.getNextLineIndent=function(a,b,c){var d=this.$getIndent(b),e=this.$tokenizer.getLineTokens(b,a),f=e.tokens;if(f.length&&f[f.length-1].type=="comment")return d;if(a=="start"){var g=b.match(/^.*[\{\(\[]\s*$/);g&&(d+=c)}return d},this.checkOutdent=function(a,b,c){return this.$outdent.checkOutdent(b,c)},this.autoOutdent=function(a,b,c){this.$outdent.autoOutdent(b,c)},this.createWorker=function(a){return null}}.call(k.prototype),b.Mode=k}),define("ace/mode/haxe_highlight_rules",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/mode/doc_comment_highlight_rules","ace/mode/text_highlight_rules"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("../lib/lang"),f=a("./doc_comment_highlight_rules").DocCommentHighlightRules,g=a("./text_highlight_rules").TextHighlightRules,h=function(){var a=e.arrayToMap("break|case|cast|catch|class|continue|default|else|enum|extends|for|function|if|implements|import|in|inline|interface|new|override|package|private|public|return|static|super|switch|this|throw|trace|try|typedef|untyped|var|while|Array|Void|Bool|Int|UInt|Float|Dynamic|String|List|Hash|IntHash|Error|Unknown|Type|Std".split("|")),b=e.arrayToMap("null|true|false".split("|"));this.$rules={start:[{token:"comment",regex:"\\/\\/.*$"},(new f).getStartRule("doc-start"),{token:"comment",regex:"\\/\\*",merge:!0,next:"comment"},{token:"string.regexp",regex:"[/](?:(?:\\[(?:\\\\]|[^\\]])+\\])|(?:\\\\/|[^\\]/]))*[/]\\w*\\s*(?=[).,;]|$)"},{token:"string",regex:'["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'},{token:"string",regex:"['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"},{token:"constant.numeric",regex:"0[xX][0-9a-fA-F]+\\b"},{token:"constant.numeric",regex:"[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"},{token:"constant.language.boolean",regex:"(?:true|false)\\b"},{token:function(c){return c=="this"?"variable.language":a.hasOwnProperty(c)?"keyword":b.hasOwnProperty(c)?"constant.language":"identifier"},regex:"[a-zA-Z_$][a-zA-Z0-9_$]*\\b"},{token:"keyword.operator",regex:"!|\\$|%|&|\\*|\\-\\-|\\-|\\+\\+|\\+|~|===|==|=|!=|!==|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\\|\\||\\?\\:|\\*=|%=|\\+=|\\-=|&=|\\^=|\\b(?:in|instanceof|new|delete|typeof|void)"},{token:"punctuation.operator",regex:"\\?|\\:|\\,|\\;|\\."},{token:"paren.lparen",regex:"[[({<]"},{token:"paren.rparen",regex:"[\\])}>]"},{token:"text",regex:"\\s+"}],comment:[{token:"comment",regex:".*?\\*\\/",next:"start"},{token:"comment",merge:!0,regex:".+"}]},this.embedRules(f,"doc-",[(new f).getEndRule("start")])};d.inherits(h,g),b.HaxeHighlightRules=h}),define("ace/mode/doc_comment_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("./text_highlight_rules").TextHighlightRules,f=function(){this.$rules={start:[{token:"comment.doc.tag",regex:"@[\\w\\d_]+"},{token:"comment.doc",merge:!0,regex:"\\s+"},{token:"comment.doc",merge:!0,regex:"TODO"},{token:"comment.doc",merge:!0,regex:"[^@\\*]+"},{token:"comment.doc",merge:!0,regex:"."}]}};d.inherits(f,e),function(){this.getStartRule=function(a){return{token:"comment.doc",merge:!0,regex:"\\/\\*(?=\\*)",next:a}},this.getEndRule=function(a){return{token:"comment.doc",merge:!0,regex:"\\*\\/",next:a}}}.call(f.prototype),b.DocCommentHighlightRules=f}),define("ace/mode/matching_brace_outdent",["require","exports","module","ace/range"],function(a,b,c){"use strict";var d=a("../range").Range,e=function(){};(function(){this.checkOutdent=function(a,b){return/^\s+$/.test(a)?/^\s*\}/.test(b):!1},this.autoOutdent=function(a,b){var c=a.getLine(b),e=c.match(/^(\s*\})/);if(!e)return 0;var f=e[1].length,g=a.findMatchingBracket({row:b,column:f});if(!g||g.row==b)return 0;var h=this.$getIndent(a.getLine(g.row));a.replace(new d(b,0,b,f-1),h)},this.$getIndent=function(a){var b=a.match(/^(\s+)/);return b?b[1]:""}}).call(e.prototype),b.MatchingBraceOutdent=e}),define("ace/mode/behaviour/cstyle",["require","exports","module","ace/lib/oop","ace/mode/behaviour"],function(a,b,c){"use strict";var d=a("../../lib/oop"),e=a("../behaviour").Behaviour,f=function(){this.add("braces","insertion",function(a,b,c,d,e){if(e=="{"){var f=c.getSelectionRange(),g=d.doc.getTextRange(f);return g!==""?{text:"{"+g+"}",selection:!1}:{text:"{}",selection:[1,1]}}if(e=="}"){var h=c.getCursorPosition(),i=d.doc.getLine(h.row),j=i.substring(h.column,h.column+1);if(j=="}"){var k=d.$findOpeningBracket("}",{column:h.column+1,row:h.row});if(k!==null)return{text:"",selection:[1,1]}}}else if(e=="\n"){var h=c.getCursorPosition(),i=d.doc.getLine(h.row),j=i.substring(h.column,h.column+1);if(j=="}"){var l=d.findMatchingBracket({row:h.row,column:h.column+1});if(!l)return null;var m=this.getNextLineIndent(a,i.substring(0,i.length-1),d.getTabString()),n=this.$getIndent(d.doc.getLine(l.row));return{text:"\n"+m+"\n"+n,selection:[1,m.length,1,m.length]}}}}),this.add("braces","deletion",function(a,b,c,d,e){var f=d.doc.getTextRange(e);if(!e.isMultiLine()&&f=="{"){var g=d.doc.getLine(e.start.row),h=g.substring(e.end.column,e.end.column+1);if(h=="}")return e.end.column++,e}}),this.add("parens","insertion",function(a,b,c,d,e){if(e=="("){var f=c.getSelectionRange(),g=d.doc.getTextRange(f);return g!==""?{text:"("+g+")",selection:!1}:{text:"()",selection:[1,1]}}if(e==")"){var h=c.getCursorPosition(),i=d.doc.getLine(h.row),j=i.substring(h.column,h.column+1);if(j==")"){var k=d.$findOpeningBracket(")",{column:h.column+1,row:h.row});if(k!==null)return{text:"",selection:[1,1]}}}}),this.add("parens","deletion",function(a,b,c,d,e){var f=d.doc.getTextRange(e);if(!e.isMultiLine()&&f=="("){var g=d.doc.getLine(e.start.row),h=g.substring(e.start.column+1,e.start.column+2);if(h==")")return e.end.column++,e}}),this.add("string_dquotes","insertion",function(a,b,c,d,e){if(e=='"'||e=="'"){var f=e,g=c.getSelectionRange(),h=d.doc.getTextRange(g);if(h!=="")return{text:f+h+f,selection:!1};var i=c.getCursorPosition(),j=d.doc.getLine(i.row),k=j.substring(i.column-1,i.column);if(k=="\\")return null;var l=d.getTokens(g.start.row,g.start.row)[0].tokens,m=0,n,o=-1;for(var p=0;p<l.length;p++){n=l[p],n.type=="string"?o=-1:o<0&&(o=n.value.indexOf(f));if(n.value.length+m>g.start.column)break;m+=l[p].value.length}if(!n||o<0&&n.type!=="comment"&&(n.type!=="string"||g.start.column!==n.value.length+m-1&&n.value.lastIndexOf(f)===n.value.length-1))return{text:f+f,selection:[1,1]};if(n&&n.type==="string"){var q=j.substring(i.column,i.column+1);if(q==f)return{text:"",selection:[1,1]}}}}),this.add("string_dquotes","deletion",function(a,b,c,d,e){var f=d.doc.getTextRange(e);if(!e.isMultiLine()&&(f=='"'||f=="'")){var g=d.doc.getLine(e.start.row),h=g.substring(e.start.column+1,e.start.column+2);if(h=='"')return e.end.column++,e}})};d.inherits(f,e),b.CstyleBehaviour=f}),define("ace/mode/folding/cstyle",["require","exports","module","ace/lib/oop","ace/range","ace/mode/folding/fold_mode"],function(a,b,c){"use strict";var d=a("../../lib/oop"),e=a("../../range").Range,f=a("./fold_mode").FoldMode,g=b.FoldMode=function(){};d.inherits(g,f),function(){this.foldingStartMarker=/(\{|\[)[^\}\]]*$|^\s*(\/\*)/,this.foldingStopMarker=/^[^\[\{]*(\}|\])|^[\s\*]*(\*\/)/,this.getFoldWidgetRange=function(a,b,c){var d=a.getLine(c),f=d.match(this.foldingStartMarker);if(f){var g=f.index;if(f[1])return this.openingBracketBlock(a,f[1],c,g);var h=a.getCommentFoldRange(c,g+f[0].length);return h.end.column-=2,h}if(b!=="markbeginend")return;var f=d.match(this.foldingStopMarker);if(f){var g=f.index+f[0].length;if(f[2]){var h=a.getCommentFoldRange(c,g);return h.end.column-=2,h}var i={row:c,column:g},j=a.$findOpeningBracket(f[1],i);if(!j)return;return j.column++,i.column--,e.fromPoints(j,i)}}}.call(g.prototype)}),define("ace/mode/folding/fold_mode",["require","exports","module","ace/range"],function(a,b,c){"use strict";var d=a("../../range").Range,e=b.FoldMode=function(){};(function(){this.foldingStartMarker=null,this.foldingStopMarker=null,this.getFoldWidget=function(a,b,c){var d=a.getLine(c);return this.foldingStartMarker.test(d)?"start":b=="markbeginend"&&this.foldingStopMarker&&this.foldingStopMarker.test(d)?"end":""},this.getFoldWidgetRange=function(a,b,c){return null},this.indentationBlock=function(a,b,c){var e=/^\s*/,f=b,g=b,h=a.getLine(b),i=c||h.length,j=h.match(e)[0].length,k=a.getLength();while(++b<k){h=a.getLine(b);var l=h.match(e)[0].length;if(l==h.length)continue;if(l<=j)break;g=b}if(g>f){var m=a.getLine(g).length;return new d(f,i,g,m)}},this.openingBracketBlock=function(a,b,c,e){var f={row:c,column:e+1},g=a.$findClosingBracket(b,f);if(!g)return;var h=a.foldWidgets[g.row];return h==null&&(h=this.getFoldWidget(a,g.row)),h=="start"&&(g.row--,g.column=a.getLine(g.row).length),d.fromPoints(f,g)}}).call(e.prototype)})
\ No newline at end of file
diff --git a/apps/files_texteditor/js/aceeditor/mode-html-uncompressed.js b/apps/files_texteditor/js/aceeditor/mode-html-uncompressed.js
old mode 100755
new mode 100644
index e994e2e06ef16d8a41c8ebb88224f329871ce8d3..62d0ce14393520ead7b82bd3c3ed6ad2d204a68e
--- a/apps/files_texteditor/js/aceeditor/mode-html-uncompressed.js
+++ b/apps/files_texteditor/js/aceeditor/mode-html-uncompressed.js
@@ -340,12 +340,20 @@ var JavaScriptHighlightRules = function() {
     );
 
     // TODO: Unicode escape sequences
-    var identifierRe = "[" + unicode.packages.L + "\\$_][" 
+    var identifierRe = "[" + unicode.packages.L + "\\$_]["
         + unicode.packages.L
         + unicode.packages.Mn + unicode.packages.Mc
         + unicode.packages.Nd
         + unicode.packages.Pc + "\\$_]*\\b";
-        
+
+    var escapedRe = "\\\\(?:x[0-9a-fA-F]{2}|" + // hex
+        "u[0-9a-fA-F]{4}|" + // unicode
+        "[0-2][0-7]{0,2}|" + // oct
+        "3[0-6][0-7]?|" + // oct
+        "37[0-7]?|" + // oct
+        "[4-7][0-7]?|" + //oct
+        ".)";
+
     // regexp must not have capturing parentheses. Use (?:) instead.
     // regexps are ordered -> the first match is used
 
@@ -353,46 +361,139 @@ var JavaScriptHighlightRules = function() {
         "start" : [
             {
                 token : "comment",
-                regex : "\\/\\/.*$"
+                regex : /\/\/.*$/
             },
             new DocCommentHighlightRules().getStartRule("doc-start"),
             {
                 token : "comment", // multi line comment
                 merge : true,
-                regex : "\\/\\*",
+                regex : /\/\*/,
                 next : "comment"
             }, {
-                token : "string", // single line
-                regex : '["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'
-            }, {
-                token : "string", // multi line string start
-                merge : true,
-                regex : '["].*\\\\$',
-                next : "qqstring"
-            }, {
-                token : "string", // single line
-                regex : "['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"
+                token : "string",
+                regex : "'",
+                next  : "qstring"
             }, {
-                token : "string", // multi line string start
-                merge : true,
-                regex : "['].*\\\\$",
-                next : "qstring"
+                token : "string",
+                regex : '"',
+                next  : "qqstring"
             }, {
                 token : "constant.numeric", // hex
-                regex : "0[xX][0-9a-fA-F]+\\b"
+                regex : /0[xX][0-9a-fA-F]+\b/
             }, {
                 token : "constant.numeric", // float
-                regex : "[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"
-            }, {
-                token : ["keyword.definition", "text", "entity.name.function"],
-                regex : "(function)(\\s+)(" + identifierRe + ")"
+                regex : /[+-]?\d+(?:(?:\.\d*)?(?:[eE][+-]?\d+)?)?\b/
+            }, { // match stuff like: Sound.prototype.play = function() { }
+                token : [
+                    "storage.type",
+                    "punctuation.operator",
+                    "support.function",
+                    "punctuation.operator",
+                    "entity.name.function",
+                    "text",
+                    "keyword.operator",
+                    "text",
+                    "storage.type",
+                    "text",
+                    "paren.lparen",
+                    "variable.parameter",
+                    "paren.rparen"
+                ],
+                regex : "(" + identifierRe + ")(\\.)(prototype)(\\.)(" + identifierRe +")(\\s*)(=)(\\s*)(function)(\\s*)(\\()(.*?)(\\))"
+            }, { // match stuff like: Sound.prototype.play = myfunc
+                token : [
+                    "storage.type",
+                    "punctuation.operator",
+                    "support.function",
+                    "punctuation.operator",
+                    "entity.name.function",
+                    "text",
+                    "keyword.operator",
+                    "text"
+                ],
+                regex : "(" + identifierRe + ")(\\.)(prototype)(\\.)(" + identifierRe +")(\\s*)(=)(\\s*)"
+            }, { // match stuff like: Sound.play = function() {  }
+                token : [
+                    "storage.type",
+                    "punctuation.operator",
+                    "entity.name.function",
+                    "text",
+                    "keyword.operator",
+                    "text",
+                    "storage.type",
+                    "text",
+                    "paren.lparen",
+                    "variable.parameter",
+                    "paren.rparen"
+                ],
+                regex : "(" + identifierRe + ")(\\.)(" + identifierRe +")(\\s*)(=)(\\s*)(function)(\\s*)(\\()(.*?)(\\))"
+            }, { // match stuff like: play = function() {  }
+                token : [
+                    "entity.name.function",
+                    "text",
+                    "keyword.operator",
+                    "text",
+                    "storage.type",
+                    "text",
+                    "paren.lparen",
+                    "variable.parameter",
+                    "paren.rparen"
+                ],
+                regex : "(" + identifierRe +")(\\s*)(=)(\\s*)(function)(\\s*)(\\()(.*?)(\\))"
+            }, { // match regular function like: function myFunc(arg) { }
+                token : [
+                    "storage.type",
+                    "text",
+                    "entity.name.function",
+                    "text",
+                    "paren.lparen",
+                    "variable.parameter",
+                    "paren.rparen"
+                ],
+                regex : "(function)(\\s+)(" + identifierRe + ")(\\s*)(\\()(.*?)(\\))"
+            }, { // match stuff like: foobar: function() { }
+                token : [
+                    "entity.name.function",
+                    "text",
+                    "punctuation.operator",
+                    "text",
+                    "storage.type",
+                    "text",
+                    "paren.lparen",
+                    "variable.parameter",
+                    "paren.rparen"
+                ],
+                regex : "(" + identifierRe + ")(\\s*)(:)(\\s*)(function)(\\s*)(\\()(.*?)(\\))"
+            }, { // Attempt to match : function() { } (this is for issues with 'foo': function() { })
+                token : [
+                    "text",
+                    "text",
+                    "storage.type",
+                    "text",
+                    "paren.lparen",
+                    "variable.parameter",
+                    "paren.rparen"
+                ],
+                regex : "(:)(\\s*)(function)?(\\s*)(\\()([^)]*)(\\))"
             }, {
                 token : "constant.language.boolean",
-                regex : "(?:true|false)\\b"
+                regex : /(?:true|false)\b/
             }, {
                 token : "keyword",
                 regex : "(?:" + kwBeforeRe + ")\\b",
                 next : "regex_allowed"
+            }, {
+                token : ["punctuation.operator", "support.function"],
+                regex : /(\.)(s(?:h(?:ift|ow(?:Mod(?:elessDialog|alDialog)|Help))|croll(?:X|By(?:Pages|Lines)?|Y|To)?|t(?:opzzzz|rike)|i(?:n|zeToContent|debar|gnText)|ort|u(?:p|b(?:str(?:ing)?)?)|pli(?:ce|t)|e(?:nd|t(?:Re(?:sizable|questHeader)|M(?:i(?:nutes|lliseconds)|onth)|Seconds|Ho(?:tKeys|urs)|Year|Cursor|Time(?:out)?|Interval|ZOptions|Date|UTC(?:M(?:i(?:nutes|lliseconds)|onth)|Seconds|Hours|Date|FullYear)|FullYear|Active)|arch)|qrt|lice|avePreferences|mall)|h(?:ome|andleEvent)|navigate|c(?:har(?:CodeAt|At)|o(?:s|n(?:cat|textual|firm)|mpile)|eil|lear(?:Timeout|Interval)?|a(?:ptureEvents|ll)|reate(?:StyleSheet|Popup|EventObject))|t(?:o(?:GMTString|S(?:tring|ource)|U(?:TCString|pperCase)|Lo(?:caleString|werCase))|est|a(?:n|int(?:Enabled)?))|i(?:s(?:NaN|Finite)|ndexOf|talics)|d(?:isableExternalCapture|ump|etachEvent)|u(?:n(?:shift|taint|escape|watch)|pdateCommands)|j(?:oin|avaEnabled)|p(?:o(?:p|w)|ush|lugins.refresh|a(?:ddings|rse(?:Int|Float)?)|r(?:int|ompt|eference))|e(?:scape|nableExternalCapture|val|lementFromPoint|x(?:p|ec(?:Script|Command)?))|valueOf|UTC|queryCommand(?:State|Indeterm|Enabled|Value)|f(?:i(?:nd|le(?:ModifiedDate|Size|CreatedDate|UpdatedDate)|xed)|o(?:nt(?:size|color)|rward)|loor|romCharCode)|watch|l(?:ink|o(?:ad|g)|astIndexOf)|a(?:sin|nchor|cos|t(?:tachEvent|ob|an(?:2)?)|pply|lert|b(?:s|ort))|r(?:ou(?:nd|teEvents)|e(?:size(?:By|To)|calc|turnValue|place|verse|l(?:oad|ease(?:Capture|Events)))|andom)|g(?:o|et(?:ResponseHeader|M(?:i(?:nutes|lliseconds)|onth)|Se(?:conds|lection)|Hours|Year|Time(?:zoneOffset)?|Da(?:y|te)|UTC(?:M(?:i(?:nutes|lliseconds)|onth)|Seconds|Hours|Da(?:y|te)|FullYear)|FullYear|A(?:ttention|llResponseHeaders)))|m(?:in|ove(?:B(?:y|elow)|To(?:Absolute)?|Above)|ergeAttributes|a(?:tch|rgins|x))|b(?:toa|ig|o(?:ld|rderWidths)|link|ack))\b(?=\()/
+            }, {
+                token : ["punctuation.operator", "support.function.dom"],
+                regex : /(\.)(s(?:ub(?:stringData|mit)|plitText|e(?:t(?:NamedItem|Attribute(?:Node)?)|lect))|has(?:ChildNodes|Feature)|namedItem|c(?:l(?:ick|o(?:se|neNode))|reate(?:C(?:omment|DATASection|aption)|T(?:Head|extNode|Foot)|DocumentFragment|ProcessingInstruction|E(?:ntityReference|lement)|Attribute))|tabIndex|i(?:nsert(?:Row|Before|Cell|Data)|tem)|open|delete(?:Row|C(?:ell|aption)|T(?:Head|Foot)|Data)|focus|write(?:ln)?|a(?:dd|ppend(?:Child|Data))|re(?:set|place(?:Child|Data)|move(?:NamedItem|Child|Attribute(?:Node)?)?)|get(?:NamedItem|Element(?:sBy(?:Name|TagName)|ById)|Attribute(?:Node)?)|blur)\b(?=\()/
+            }, {
+                token : ["punctuation.operator", "support.constant"],
+                regex : /(\.)(s(?:ystemLanguage|cr(?:ipts|ollbars|een(?:X|Y|Top|Left))|t(?:yle(?:Sheets)?|atus(?:Text|bar)?)|ibling(?:Below|Above)|ource|uffixes|e(?:curity(?:Policy)?|l(?:ection|f)))|h(?:istory|ost(?:name)?|as(?:h|Focus))|y|X(?:MLDocument|SLDocument)|n(?:ext|ame(?:space(?:s|URI)|Prop))|M(?:IN_VALUE|AX_VALUE)|c(?:haracterSet|o(?:n(?:structor|trollers)|okieEnabled|lorDepth|mp(?:onents|lete))|urrent|puClass|l(?:i(?:p(?:boardData)?|entInformation)|osed|asses)|alle(?:e|r)|rypto)|t(?:o(?:olbar|p)|ext(?:Transform|Indent|Decoration|Align)|ags)|SQRT(?:1_2|2)|i(?:n(?:ner(?:Height|Width)|put)|ds|gnoreCase)|zIndex|o(?:scpu|n(?:readystatechange|Line)|uter(?:Height|Width)|p(?:sProfile|ener)|ffscreenBuffering)|NEGATIVE_INFINITY|d(?:i(?:splay|alog(?:Height|Top|Width|Left|Arguments)|rectories)|e(?:scription|fault(?:Status|Ch(?:ecked|arset)|View)))|u(?:ser(?:Profile|Language|Agent)|n(?:iqueID|defined)|pdateInterval)|_content|p(?:ixelDepth|ort|ersonalbar|kcs11|l(?:ugins|atform)|a(?:thname|dding(?:Right|Bottom|Top|Left)|rent(?:Window|Layer)?|ge(?:X(?:Offset)?|Y(?:Offset)?))|r(?:o(?:to(?:col|type)|duct(?:Sub)?|mpter)|e(?:vious|fix)))|e(?:n(?:coding|abledPlugin)|x(?:ternal|pando)|mbeds)|v(?:isibility|endor(?:Sub)?|Linkcolor)|URLUnencoded|P(?:I|OSITIVE_INFINITY)|f(?:ilename|o(?:nt(?:Size|Family|Weight)|rmName)|rame(?:s|Element)|gColor)|E|whiteSpace|l(?:i(?:stStyleType|n(?:eHeight|kColor))|o(?:ca(?:tion(?:bar)?|lName)|wsrc)|e(?:ngth|ft(?:Context)?)|a(?:st(?:M(?:odified|atch)|Index|Paren)|yer(?:s|X)|nguage))|a(?:pp(?:MinorVersion|Name|Co(?:deName|re)|Version)|vail(?:Height|Top|Width|Left)|ll|r(?:ity|guments)|Linkcolor|bove)|r(?:ight(?:Context)?|e(?:sponse(?:XML|Text)|adyState))|global|x|m(?:imeTypes|ultiline|enubar|argin(?:Right|Bottom|Top|Left))|L(?:N(?:10|2)|OG(?:10E|2E))|b(?:o(?:ttom|rder(?:Width|RightWidth|BottomWidth|Style|Color|TopWidth|LeftWidth))|ufferDepth|elow|ackground(?:Color|Image)))\b/
+            }, {
+                token : ["storage.type", "punctuation.operator", "support.function.firebug"],
+                regex : /(console)(\.)(warn|info|log|error|time|timeEnd|assert)\b/
             }, {
                 token : function(value) {
                     if (globals.hasOwnProperty(value))
@@ -400,7 +501,7 @@ var JavaScriptHighlightRules = function() {
                     else if (deprecated.hasOwnProperty(value))
                         return "invalid.deprecated";
                     else if (definitions.hasOwnProperty(value))
-                        return "keyword.definition";
+                        return "storage.type";
                     else if (keywords.hasOwnProperty(value))
                         return "keyword";
                     else if (buildinConstants.hasOwnProperty(value))
@@ -415,29 +516,29 @@ var JavaScriptHighlightRules = function() {
                 regex : identifierRe
             }, {
                 token : "keyword.operator",
-                regex : "!|\\$|%|&|\\*|\\-\\-|\\-|\\+\\+|\\+|~|===|==|=|!=|!==|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\\|\\||\\?\\:|\\*=|%=|\\+=|\\-=|&=|\\^=|\\b(?:in|instanceof|new|delete|typeof|void)",
+                regex : /!|\$|%|&|\*|\-\-|\-|\+\+|\+|~|===|==|=|!=|!==|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\|\||\?\:|\*=|%=|\+=|\-=|&=|\^=|\b(?:in|instanceof|new|delete|typeof|void)/,
                 next  : "regex_allowed"
             }, {
                 token : "punctuation.operator",
-                regex : "\\?|\\:|\\,|\\;|\\.",
+                regex : /\?|\:|\,|\;|\./,
                 next  : "regex_allowed"
             }, {
                 token : "paren.lparen",
-                regex : "[[({]",
+                regex : /[\[({]/,
                 next  : "regex_allowed"
             }, {
                 token : "paren.rparen",
-                regex : "[\\])}]"
+                regex : /[\])}]/
             }, {
                 token : "keyword.operator",
-                regex : "\\/=?",
+                regex : /\/=?/,
                 next  : "regex_allowed"
             }, {
                 token: "comment",
-                regex: "^#!.*$" 
+                regex: /^#!.*$/
             }, {
                 token : "text",
-                regex : "\\s+"
+                regex : /\s+/
             }
         ],
         // regular expressions are only allowed after certain tokens. This
@@ -462,7 +563,7 @@ var JavaScriptHighlightRules = function() {
             }, {
                 // immediately return to the start mode without matching
                 // anything
-                token: "empty", 
+                token: "empty",
                 regex: "",
                 next: "start"
             }
@@ -474,10 +575,10 @@ var JavaScriptHighlightRules = function() {
                 next: "regex"
             }, {
 				// flag
-                token: "string.regexp", 
+                token: "string.regexp",
                 regex: "/\\w*",
                 next: "start",
-                merge: true 
+                merge: true
             }, {
                 token: "string.regexp",
                 regex: "[^\\\\/\\[]+",
@@ -489,9 +590,9 @@ var JavaScriptHighlightRules = function() {
                 next: "regex_character_class",
                 merge: true
             }, {
-                token: "empty", 
+                token: "empty",
                 regex: "",
-                next: "start" 
+                next: "start"
             }
         ],
         "regex_character_class": [
@@ -510,9 +611,9 @@ var JavaScriptHighlightRules = function() {
                 next: "regex_character_class",
                 merge: true
             }, {
-                token: "empty", 
+                token: "empty",
                 regex: "",
-                next: "start" 
+                next: "start"
             }
         ],
         "comment_regex_allowed" : [
@@ -541,28 +642,32 @@ var JavaScriptHighlightRules = function() {
         ],
         "qqstring" : [
             {
+                token : "constant.language.escape",
+                regex : escapedRe
+            }, {
                 token : "string",
-                regex : '(?:(?:\\\\.)|(?:[^"\\\\]))*?"',
-                next : "start"
+                regex : '[^"\\\\]+'
             }, {
                 token : "string",
-                merge : true,
-                regex : '.+'
+                regex : '"',
+                next  : "start"
             }
         ],
         "qstring" : [
             {
+                token : "constant.language.escape",
+                regex : escapedRe
+            }, {
                 token : "string",
-                regex : "(?:(?:\\\\.)|(?:[^'\\\\]))*?'",
-                next : "start"
+                regex : "[^'\\\\]+"
             }, {
                 token : "string",
-                merge : true,
-                regex : '.+'
+                regex : "'",
+                next  : "start"
             }
         ]
     };
-    
+
     this.embedRules(DocCommentHighlightRules, "doc-",
         [ new DocCommentHighlightRules().getEndRule("start") ]);
 };
@@ -747,195 +852,6 @@ var MatchingBraceOutdent = function() {};
 }).call(MatchingBraceOutdent.prototype);
 
 exports.MatchingBraceOutdent = MatchingBraceOutdent;
-});
-/* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is Ajax.org Code Editor (ACE).
- *
- * The Initial Developer of the Original Code is
- * Ajax.org B.V.
- * Portions created by the Initial Developer are Copyright (C) 2010
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *      Fabian Jakobs <fabian AT ajax DOT org>
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-define('ace/worker/worker_client', ['require', 'exports', 'module' , 'ace/lib/oop', 'ace/lib/event_emitter'], function(require, exports, module) {
-"use strict";
-
-var oop = require("../lib/oop");
-var EventEmitter = require("../lib/event_emitter").EventEmitter;
-
-var WorkerClient = function(topLevelNamespaces, packagedJs, mod, classname) {
-
-    this.changeListener = this.changeListener.bind(this);
-
-    if (module.packaged) {
-        var base = this.$guessBasePath();
-        this.$worker = new Worker(base + packagedJs);
-    }
-    else {
-        var workerUrl = this.$normalizePath(require.nameToUrl("ace/worker/worker", null, "_"));
-        this.$worker = new Worker(workerUrl);
-
-        var tlns = {};
-        for (var i=0; i<topLevelNamespaces.length; i++) {
-            var ns = topLevelNamespaces[i];
-            var path = this.$normalizePath(require.nameToUrl(ns, null, "_").replace(/.js$/, ""));
-
-            tlns[ns] = path;
-        }
-    }
-
-    this.$worker.postMessage({
-        init : true,
-        tlns: tlns,
-        module: mod,
-        classname: classname
-    });
-
-    this.callbackId = 1;
-    this.callbacks = {};
-
-    var _self = this;
-    this.$worker.onerror = function(e) {
-        window.console && console.log && console.log(e);
-        throw e;
-    };
-    this.$worker.onmessage = function(e) {
-        var msg = e.data;
-        switch(msg.type) {
-            case "log":
-                window.console && console.log && console.log(msg.data);
-                break;
-
-            case "event":
-                _self._emit(msg.name, {data: msg.data});
-                break;
-
-            case "call":
-                var callback = _self.callbacks[msg.id];
-                if (callback) {
-                    callback(msg.data);
-                    delete _self.callbacks[msg.id];
-                }
-                break;
-        }
-    };
-};
-
-(function(){
-
-    oop.implement(this, EventEmitter);
-
-    this.$normalizePath = function(path) {
-        path = path.replace(/^[a-z]+:\/\/[^\/]+\//, ""); // Remove domain name and rebuild it
-        path = location.protocol + "//" + location.host
-            // paths starting with a slash are relative to the root (host)
-            + (path.charAt(0) == "/" ? "" : location.pathname.replace(/\/[^\/]*$/, ""))
-            + "/" + path.replace(/^[\/]+/, "");
-        return path;
-    };
-
-    this.$guessBasePath = function() {
-        if (require.aceBaseUrl)
-            return require.aceBaseUrl;
-
-        var scripts = document.getElementsByTagName("script");
-        for (var i=0; i<scripts.length; i++) {
-            var script = scripts[i];
-
-            var base = script.getAttribute("data-ace-base");
-            if (base)
-                return base.replace(/\/*$/, "/");
-
-            var src = script.src || script.getAttribute("src");
-            if (!src) {
-                continue;
-            }
-            var m = src.match(/^(?:(.*\/)ace\.js|(.*\/)ace(-uncompressed)?(-noconflict)?\.js)(?:\?|$)/);
-            if (m)
-                return m[1] || m[2];
-        }
-        return "";
-    };
-
-    this.terminate = function() {
-        this._emit("terminate", {});
-        this.$worker.terminate();
-        this.$worker = null;
-        this.$doc.removeEventListener("change", this.changeListener);
-        this.$doc = null;
-    };
-
-    this.send = function(cmd, args) {
-        this.$worker.postMessage({command: cmd, args: args});
-    };
-
-    this.call = function(cmd, args, callback) {
-        if (callback) {
-            var id = this.callbackId++;
-            this.callbacks[id] = callback;
-            args.push(id);
-        }
-        this.send(cmd, args);
-    };
-
-    this.emit = function(event, data) {
-        try {
-            // firefox refuses to clone objects which have function properties
-            // TODO: cleanup event
-            this.$worker.postMessage({event: event, data: {data: data.data}});
-        }
-        catch(ex) {}
-    };
-
-    this.attachToDocument = function(doc) {
-        if(this.$doc)
-            this.terminate();
-
-        this.$doc = doc;
-        this.call("setValue", [doc.getValue()]);
-        doc.on("change", this.changeListener);
-    };
-
-    this.changeListener = function(e) {
-        e.range = {
-            start: e.data.range.start,
-            end: e.data.range.end
-        };
-        this.emit("change", e);
-    };
-
-}).call(WorkerClient.prototype);
-
-exports.WorkerClient = WorkerClient;
-
 });
 /* vim:ts=4:sts=4:sw=4:
  * ***** BEGIN LICENSE BLOCK *****
@@ -991,12 +907,12 @@ var CstyleBehaviour = function () {
                 return {
                     text: '{' + selected + '}',
                     selection: false
-                }
+                };
             } else {
                 return {
                     text: '{}',
                     selection: [1, 1]
-                }
+                };
             }
         } else if (text == '}') {
             var cursor = editor.getCursorPosition();
@@ -1008,7 +924,7 @@ var CstyleBehaviour = function () {
                     return {
                         text: '',
                         selection: [1, 1]
-                    }
+                    };
                 }
             }
         } else if (text == "\n") {
@@ -1026,7 +942,7 @@ var CstyleBehaviour = function () {
                 return {
                     text: '\n' + indent + '\n' + next_indent,
                     selection: [1, indent.length, 1, indent.length]
-                }
+                };
             }
         }
     });
@@ -1051,12 +967,12 @@ var CstyleBehaviour = function () {
                 return {
                     text: '(' + selected + ')',
                     selection: false
-                }
+                };
             } else {
                 return {
                     text: '()',
                     selection: [1, 1]
-                }
+                };
             }
         } else if (text == ')') {
             var cursor = editor.getCursorPosition();
@@ -1068,7 +984,7 @@ var CstyleBehaviour = function () {
                     return {
                         text: '',
                         selection: [1, 1]
-                    }
+                    };
                 }
             }
         }
@@ -1087,14 +1003,15 @@ var CstyleBehaviour = function () {
     });
 
     this.add("string_dquotes", "insertion", function (state, action, editor, session, text) {
-        if (text == '"') {
+        if (text == '"' || text == "'") {
+            var quote = text;
             var selection = editor.getSelectionRange();
             var selected = session.doc.getTextRange(selection);
             if (selected !== "") {
                 return {
-                    text: '"' + selected + '"',
+                    text: quote + selected + quote,
                     selection: false
-                }
+                };
             } else {
                 var cursor = editor.getCursorPosition();
                 var line = session.doc.getLine(cursor.row);
@@ -1115,7 +1032,7 @@ var CstyleBehaviour = function () {
                     if (token.type == "string") {
                       quotepos = -1;
                     } else if (quotepos < 0) {
-                      quotepos = token.value.indexOf('"');
+                      quotepos = token.value.indexOf(quote);
                     }
                     if ((token.value.length + col) > selection.start.column) {
                         break;
@@ -1124,19 +1041,19 @@ var CstyleBehaviour = function () {
                 }
 
                 // Try and be smart about when we auto insert.
-                if (!token || (quotepos < 0 && token.type !== "comment" && (token.type !== "string" || ((selection.start.column !== token.value.length+col-1) && token.value.lastIndexOf('"') === token.value.length-1)))) {
+                if (!token || (quotepos < 0 && token.type !== "comment" && (token.type !== "string" || ((selection.start.column !== token.value.length+col-1) && token.value.lastIndexOf(quote) === token.value.length-1)))) {
                     return {
-                        text: '""',
+                        text: quote + quote,
                         selection: [1,1]
-                    }
+                    };
                 } else if (token && token.type === "string") {
                     // Ignore input and move right one if we're typing over the closing quote.
                     var rightChar = line.substring(cursor.column, cursor.column + 1);
-                    if (rightChar == '"') {
+                    if (rightChar == quote) {
                         return {
                             text: '',
                             selection: [1, 1]
-                        }
+                        };
                     }
                 }
             }
@@ -1145,7 +1062,7 @@ var CstyleBehaviour = function () {
 
     this.add("string_dquotes", "deletion", function (state, action, editor, session, range) {
         var selected = session.doc.getTextRange(range);
-        if (!range.isMultiLine() && selected == '"') {
+        if (!range.isMultiLine() && (selected == '"' || selected == "'")) {
             var line = session.doc.getLine(range.start.row);
             var rightChar = line.substring(range.start.column + 1, range.start.column + 2);
             if (rightChar == '"') {
@@ -1155,7 +1072,8 @@ var CstyleBehaviour = function () {
         }
     });
 
-}
+};
+
 oop.inherits(CstyleBehaviour, Behaviour);
 
 exports.CstyleBehaviour = CstyleBehaviour;
@@ -1523,31 +1441,7 @@ var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
 var CssHighlightRules = function() {
 
     var properties = lang.arrayToMap(
-        ("-moz-appearance|-moz-box-sizing|-webkit-box-sizing|-moz-outline-radius|-moz-transform|-webkit-transform|" +
-        "appearance|azimuth|background-attachment|background-color|background-image|" +
-        "background-origin|background-position|background-repeat|background|border-bottom-color|" +
-        "border-bottom-style|border-bottom-width|border-bottom|border-collapse|" +
-        "border-color|border-left-color|border-left-style|border-left-width|" +
-        "border-left|border-right-color|border-right-style|border-right-width|" +
-        "border-right|border-spacing|border-style|border-top-color|" +
-        "border-top-style|border-top-width|border-top|border-width|border|" +
-        "bottom|box-sizing|caption-side|clear|clip|color|content|counter-increment|" +
-        "counter-reset|cue-after|cue-before|cue|cursor|direction|display|" +
-        "elevation|empty-cells|float|font-family|font-size-adjust|font-size|" +
-        "font-stretch|font-style|font-variant|font-weight|font|height|left|" +
-        "letter-spacing|line-height|list-style-image|list-style-position|" +
-        "list-style-type|list-style|margin-bottom|margin-left|margin-right|" +
-        "margin-top|marker-offset|margin|marks|max-height|max-width|min-height|" +
-        "min-width|-moz-border-radius|opacity|orphans|outline-color|outline-offset|outline-radius|" +
-        "outline-style|outline-width|outline|overflow|overflow-x|overflow-y|padding-bottom|" +
-        "padding-left|padding-right|padding-top|padding|page-break-after|" +
-        "page-break-before|page-break-inside|page|pause-after|pause-before|" +
-        "pause|pitch-range|pitch|play-during|pointer-events|position|quotes|resize|richness|right|" +
-        "size|speak-header|speak-numeral|speak-punctuation|speech-rate|speak|" +
-        "stress|table-layout|text-align|text-decoration|text-indent|" +
-        "text-shadow|text-transform|top|transform|unicode-bidi|vertical-align|" +
-        "visibility|voice-family|volume|white-space|widows|width|word-spacing|" +
-        "z-index").split("|")
+        ("animation-fill-mode|alignment-adjust|alignment-baseline|animation-delay|animation-direction|animation-duration|animation-iteration-count|animation-name|animation-play-state|animation-timing-function|animation|appearance|azimuth|backface-visibility|background-attachment|background-break|background-clip|background-color|background-image|background-origin|background-position|background-repeat|background-size|background|baseline-shift|binding|bleed|bookmark-label|bookmark-level|bookmark-state|bookmark-target|border-bottom|border-bottom-color|border-bottom-left-radius|border-bottom-right-radius|border-bottom-style|border-bottom-width|border-collapse|border-color|border-image|border-image-outset|border-image-repeat|border-image-slice|border-image-source|border-image-width|border-left|border-left-color|border-left-style|border-left-width|border-radius|border-right|border-right-color|border-right-style|border-right-width|border-spacing|border-style|border-top|border-top-color|border-top-left-radius|border-top-right-radius|border-top-style|border-top-width|border-width|border|bottom|box-align|box-decoration-break|box-direction|box-flex-group|box-flex|box-lines|box-ordinal-group|box-orient|box-pack|box-shadow|box-sizing|break-after|break-before|break-inside|caption-side|clear|clip|color-profile|color|column-count|column-fill|column-gap|column-rule|column-rule-color|column-rule-style|column-rule-width|column-span|column-width|columns|content|counter-increment|counter-reset|crop|cue-after|cue-before|cue|cursor|direction|display|dominant-baseline|drop-initial-after-adjust|drop-initial-after-align|drop-initial-before-adjust|drop-initial-before-align|drop-initial-size|drop-initial-value|elevation|empty-cells|fit|fit-position|float-offset|float|font-family|font-size|font-size-adjust|font-stretch|font-style|font-variant|font-weight|font|grid-columns|grid-rows|hanging-punctuation|height|hyphenate-after|hyphenate-before|hyphenate-character|hyphenate-lines|hyphenate-resource|hyphens|icon|image-orientation|image-rendering|image-resolution|inline-box-align|left|letter-spacing|line-height|line-stacking-ruby|line-stacking-shift|line-stacking-strategy|line-stacking|list-style-image|list-style-position|list-style-type|list-style|margin-bottom|margin-left|margin-right|margin-top|margin|mark-after|mark-before|mark|marks|marquee-direction|marquee-play-count|marquee-speed|marquee-style|max-height|max-width|min-height|min-width|move-to|nav-down|nav-index|nav-left|nav-right|nav-up|opacity|orphans|outline-color|outline-offset|outline-style|outline-width|outline|overflow-style|overflow-x|overflow-y|overflow|padding-bottom|padding-left|padding-right|padding-top|padding|page-break-after|page-break-before|page-break-inside|page-policy|page|pause-after|pause-before|pause|perspective-origin|perspective|phonemes|pitch-range|pitch|play-during|position|presentation-level|punctuation-trim|quotes|rendering-intent|resize|rest-after|rest-before|rest|richness|right|rotation-point|rotation|ruby-align|ruby-overhang|ruby-position|ruby-span|size|speak-header|speak-numeral|speak-punctuation|speak|speech-rate|stress|string-set|table-layout|target-name|target-new|target-position|target|text-align-last|text-align|text-decoration|text-emphasis|text-height|text-indent|text-justify|text-outline|text-shadow|text-transform|text-wrap|top|transform-origin|transform-style|transform|transition-delay|transition-duration|transition-property|transition-timing-function|transition|unicode-bidi|vertical-align|visibility|voice-balance|voice-duration|voice-family|voice-pitch-range|voice-pitch|voice-rate|voice-stress|voice-volume|volume|white-space-collapse|white-space|widows|width|word-break|word-spacing|word-wrap|z-index").split("|")
     );
 
     var functions = lang.arrayToMap(
@@ -1555,27 +1449,7 @@ var CssHighlightRules = function() {
     );
 
     var constants = lang.arrayToMap(
-        ("absolute|all-scroll|always|armenian|auto|baseline|below|bidi-override|" +
-        "block|bold|bolder|border-box|both|bottom|break-all|break-word|capitalize|center|" +
-        "char|circle|cjk-ideographic|col-resize|collapse|content-box|crosshair|dashed|" +
-        "decimal-leading-zero|decimal|default|disabled|disc|" +
-        "distribute-all-lines|distribute-letter|distribute-space|" +
-        "distribute|dotted|double|e-resize|ellipsis|fixed|georgian|groove|" +
-        "hand|hebrew|help|hidden|hiragana-iroha|hiragana|horizontal|" +
-        "ideograph-alpha|ideograph-numeric|ideograph-parenthesis|" +
-        "ideograph-space|inactive|inherit|inline-block|inline|inset|inside|" +
-        "inter-ideograph|inter-word|italic|justify|katakana-iroha|katakana|" +
-        "keep-all|left|lighter|line-edge|line-through|line|list-item|loose|" +
-        "lower-alpha|lower-greek|lower-latin|lower-roman|lowercase|lr-tb|ltr|" +
-        "medium|middle|move|n-resize|ne-resize|newspaper|no-drop|no-repeat|" +
-        "nw-resize|none|normal|not-allowed|nowrap|oblique|outset|outside|" +
-        "overline|pointer|progress|relative|repeat-x|repeat-y|repeat|right|" +
-        "ridge|row-resize|rtl|s-resize|scroll|se-resize|separate|small-caps|" +
-        "solid|square|static|strict|super|sw-resize|table-footer-group|" +
-        "table-header-group|tb-rl|text-bottom|text-top|text|thick|thin|top|" +
-        "transparent|underline|upper-alpha|upper-latin|upper-roman|uppercase|" +
-        "vertical-ideographic|vertical-text|visible|w-resize|wait|whitespace|" +
-        "zero").split("|")
+        ("absolute|after-edge|after|all-scroll|all|alphabetic|always|antialiased|armenian|auto|avoid-column|avoid-page|avoid|balance|baseline|before-edge|before|below|bidi-override|block-line-height|block|bold|bolder|border-box|both|bottom|box|break-all|break-word|capitalize|caps-height|caption|center|central|char|circle|cjk-ideographic|clone|close-quote|col-resize|collapse|column|consider-shifts|contain|content-box|cover|crosshair|cubic-bezier|dashed|decimal-leading-zero|decimal|default|disabled|disc|disregard-shifts|distribute-all-lines|distribute-letter|distribute-space|distribute|dotted|double|e-resize|ease-in|ease-in-out|ease-out|ease|ellipsis|end|exclude-ruby|fill|fixed|font-size|font|georgian|glyphs|grid-height|groove|hand|hanging|hebrew|help|hidden|hiragana-iroha|hiragana|horizontal|icon|ideograph-alpha|ideograph-numeric|ideograph-parenthesis|ideograph-space|ideographic|inactive|include-ruby|inherit|initial|inline-block|inline-box|inline-line-height|inline-table|inline|inset|inside|inter-ideograph|inter-word|invert|italic|justify|katakana-iroha|katakana|keep-all|last|left|lighter|line-edge|line-through|line|linear|list-item|local|loose|lower-alpha|lower-greek|lower-latin|lower-roman|lowercase|lr-tb|ltr|mathematical|max-height|max-size|medium|menu|message-box|middle|move|n-resize|ne-resize|newspaper|no-change|no-close-quote|no-drop|no-open-quote|no-repeat|none|normal|not-allowed|nowrap|nw-resize|oblique|open-quote|outset|outside|overline|padding-box|page|pointer|pre-line|pre-wrap|pre|preserve-3d|progress|relative|repeat-x|repeat-y|repeat|replaced|reset-size|ridge|right|round|row-resize|rtl|s-resize|scroll|se-resize|separate|slice|small-caps|small-caption|solid|space|square|start|static|status-bar|step-end|step-start|steps|stretch|strict|sub|super|sw-resize|table-caption|table-cell|table-column-group|table-column|table-footer-group|table-header-group|table-row-group|table-row|table|tb-rl|text-after-edge|text-before-edge|text-bottom|text-size|text-top|text|thick|thin|top|transparent|underline|upper-alpha|upper-latin|upper-roman|uppercase|use-script|vertical-ideographic|vertical-text|visible|w-resize|wait|whitespace|z-index|zero").split("|")
     );
 
     var colors = lang.arrayToMap(
@@ -1583,32 +1457,49 @@ var CssHighlightRules = function() {
         "purple|red|silver|teal|white|yellow").split("|")
     );
 
+    var fonts = lang.arrayToMap(
+        ("arial|century|comic|courier|garamond|georgia|helvetica|impact|lucida|" +
+        "symbol|system|tahoma|times|trebuchet|utopia|verdana|webdings|sans-serif|" +
+        "serif|monospace").split("|")
+    );
+    
     // regexp must not have capturing parentheses. Use (?:) instead.
     // regexps are ordered -> the first match is used
 
     var numRe = "\\-?(?:(?:[0-9]+)|(?:[0-9]*\\.[0-9]+))";
-
+    var pseudoElements = "(\\:+)\\b(after|before|first-letter|first-line|moz-selection|selection)\\b";
+    var pseudoClasses = "(:)\\b(active|checked|disabled|empty|enabled|first-child|first-of-type|focus|hover|indeterminate|invalid|last-child|last-of-type|link|not|nth-child|nth-last-child|nth-last-of-type|nth-of-type|only-child|only-of-type|required|root|target|valid|visited)\\b";
+    
     var base_ruleset = [
         {
             token : "comment", // multi line comment
             merge : true,
             regex : "\\/\\*",
             next : "ruleset_comment"
-        },{
+        }, {
             token : "string", // single line
             regex : '["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'
         }, {
             token : "string", // single line
             regex : "['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"
         }, {
-            token : "constant.numeric",
-            regex : numRe + "(?:em|ex|px|cm|mm|in|pt|pc|deg|rad|grad|ms|s|hz|khz|%)"
+            token : ["constant.numeric", "keyword"],
+            regex : "(" + numRe + ")(ch|cm|deg|em|ex|fr|gd|grad|Hz|in|kHz|mm|ms|pc|pt|px|rad|rem|s|turn|vh|vm|vw|%)"
+        }, {
+            token : ["constant.numeric"],
+            regex : "([0-9]+)"
         }, {
             token : "constant.numeric",  // hex6 color
             regex : "#[a-f0-9]{6}"
         }, {
             token : "constant.numeric", // hex3 color
             regex : "#[a-f0-9]{3}"
+        }, {
+            token : ["punctuation", "entity.other.attribute-name.pseudo-element.css"], 
+            regex : pseudoElements
+        }, {
+            token : ["punctuation", "entity.other.attribute-name.pseudo-class.css"], 
+            regex : pseudoClasses
         }, {
             token : function(value) {
                 if (properties.hasOwnProperty(value.toLowerCase())) {
@@ -1623,12 +1514,15 @@ var CssHighlightRules = function() {
                 else if (colors.hasOwnProperty(value.toLowerCase())) {
                     return "support.constant.color";
                 }
+                else if (fonts.hasOwnProperty(value.toLowerCase())) {
+                    return "support.constant.fonts";
+                }
                 else {
                     return "text";
                 }
             },
             regex : "\\-?[a-zA-Z_][a-zA-Z0-9_\\-]*"
-        }
+        } 
       ];
 
     var ruleset = lang.copyArray(base_ruleset);
@@ -1806,6 +1700,9 @@ var HtmlHighlightRules = function() {
             merge : true,
             regex : "<\\!--",
             next : "comment"
+        }, {
+            token : "xml_pe",
+            regex : "<\\!.*?>"
         }, {
             token : "meta.tag",
             regex : "<(?=\s*script\\b)",
@@ -1813,7 +1710,7 @@ var HtmlHighlightRules = function() {
         }, {
             token : "meta.tag",
             regex : "<(?=\s*style\\b)",
-            next : "css"
+            next : "style"
         }, {
             token : "meta.tag", // opening tag
             regex : "<\\/?",
@@ -1821,6 +1718,9 @@ var HtmlHighlightRules = function() {
         }, {
             token : "text",
             regex : "\\s+"
+        }, {
+            token : "constant.character.entity",
+            regex : "(?:&#[0-9]+;)|(?:&#x[0-9a-fA-F]+;)|(?:&[a-zA-Z0-9_:\\.-]+;)"
         }, {
             token : "text",
             regex : "[^<]+"
@@ -1852,7 +1752,7 @@ var HtmlHighlightRules = function() {
     };
     
     xmlUtil.tag(this.$rules, "tag", "start");
-    xmlUtil.tag(this.$rules, "css", "css-start");
+    xmlUtil.tag(this.$rules, "style", "css-start");
     xmlUtil.tag(this.$rules, "script", "js-start");
     
     this.embedRules(JavaScriptHighlightRules, "js-", [{
@@ -1934,7 +1834,7 @@ function string(state) {
         token : "string", // multi line string start
         merge : true,
         regex : '["].*',
-        next : state + "-qqstring"
+        next : state + "_qqstring"
     }, {
         token : "string",
         regex : "'.*?'"
@@ -1942,7 +1842,7 @@ function string(state) {
         token : "string", // multi line string start
         merge : true,
         regex : "['].*",
-        next : state + "-qstring"
+        next : state + "_qstring"
     }];
 }
 
@@ -1990,18 +1890,18 @@ exports.tag = function(states, name, nextState) {
             }
         },        
         merge : true,
-        regex : "[-_a-zA-Z0-9:!]+",
-        next : name + "embed-attribute-list" 
+        regex : "[-_a-zA-Z0-9:]+",
+        next : name + "_embed_attribute_list" 
     }, {
         token: "empty",
         regex: "",
-        next : name + "embed-attribute-list"
+        next : name + "_embed_attribute_list"
     }];
 
-    states[name + "-qstring"] = multiLineString("'", name + "embed-attribute-list");
-    states[name + "-qqstring"] = multiLineString("\"", name + "embed-attribute-list");
+    states[name + "_qstring"] = multiLineString("'", name + "_embed_attribute_list");
+    states[name + "_qqstring"] = multiLineString("\"", name + "_embed_attribute_list");
     
-    states[name + "embed-attribute-list"] = [{
+    states[name + "_embed_attribute_list"] = [{
         token : "meta.tag",
         merge : true,
         regex : "\/?>",
@@ -2546,13 +2446,4 @@ oop.inherits(FoldMode, BaseFoldMode);
 
 }).call(FoldMode.prototype);
 
-});;
-            (function() {
-                window.require(["ace/ace"], function(a) {
-                    if (!window.ace)
-                        window.ace = {};
-                    for (var key in a) if (a.hasOwnProperty(key))
-                        ace[key] = a[key];
-                });
-            })();
-        
\ No newline at end of file
+});
\ No newline at end of file
diff --git a/apps/files_texteditor/js/aceeditor/mode-html.js b/apps/files_texteditor/js/aceeditor/mode-html.js
index f4f806059e4389540b4e0f85e7b947e5c58d0639..78701813b25b869d99ab23c3976f6a0b6467712f 100644
--- a/apps/files_texteditor/js/aceeditor/mode-html.js
+++ b/apps/files_texteditor/js/aceeditor/mode-html.js
@@ -1 +1 @@
-define("ace/mode/html",["require","exports","module","ace/lib/oop","ace/mode/text","ace/mode/javascript","ace/mode/css","ace/tokenizer","ace/mode/html_highlight_rules","ace/mode/behaviour/xml","ace/mode/folding/html"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("./text").Mode,f=a("./javascript").Mode,g=a("./css").Mode,h=a("../tokenizer").Tokenizer,i=a("./html_highlight_rules").HtmlHighlightRules,j=a("./behaviour/xml").XmlBehaviour,k=a("./folding/html").FoldMode,l=function(){var a=new i;this.$tokenizer=new h(a.getRules()),this.$behaviour=new j,this.$embeds=a.getEmbeds(),this.createModeDelegates({"js-":f,"css-":g}),this.foldingRules=new k};d.inherits(l,e),function(){this.toggleCommentLines=function(a,b,c,d){return 0},this.getNextLineIndent=function(a,b,c){return this.$getIndent(b)},this.checkOutdent=function(a,b,c){return!1}}.call(l.prototype),b.Mode=l}),define("ace/mode/javascript",["require","exports","module","ace/lib/oop","ace/mode/text","ace/tokenizer","ace/mode/javascript_highlight_rules","ace/mode/matching_brace_outdent","ace/range","ace/worker/worker_client","ace/mode/behaviour/cstyle","ace/mode/folding/cstyle"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("./text").Mode,f=a("../tokenizer").Tokenizer,g=a("./javascript_highlight_rules").JavaScriptHighlightRules,h=a("./matching_brace_outdent").MatchingBraceOutdent,i=a("../range").Range,j=a("../worker/worker_client").WorkerClient,k=a("./behaviour/cstyle").CstyleBehaviour,l=a("./folding/cstyle").FoldMode,m=function(){this.$tokenizer=new f((new g).getRules()),this.$outdent=new h,this.$behaviour=new k,this.foldingRules=new l};d.inherits(m,e),function(){this.toggleCommentLines=function(a,b,c,d){var e=!0,f=/^(\s*)\/\//;for(var g=c;g<=d;g++)if(!f.test(b.getLine(g))){e=!1;break}if(e){var h=new i(0,0,0,0);for(var g=c;g<=d;g++){var j=b.getLine(g),k=j.match(f);h.start.row=g,h.end.row=g,h.end.column=k[0].length,b.replace(h,k[1])}}else b.indentRows(c,d,"//")},this.getNextLineIndent=function(a,b,c){var d=this.$getIndent(b),e=this.$tokenizer.getLineTokens(b,a),f=e.tokens,g=e.state;if(f.length&&f[f.length-1].type=="comment")return d;if(a=="start"||a=="regex_allowed"){var h=b.match(/^.*(?:\bcase\b.*\:|[\{\(\[])\s*$/);h&&(d+=c)}else if(a=="doc-start"){if(g=="start"||a=="regex_allowed")return"";var h=b.match(/^\s*(\/?)\*/);h&&(h[1]&&(d+=" "),d+="* ")}return d},this.checkOutdent=function(a,b,c){return this.$outdent.checkOutdent(b,c)},this.autoOutdent=function(a,b,c){this.$outdent.autoOutdent(b,c)},this.createWorker=function(a){var b=new j(["ace"],"worker-javascript.js","ace/mode/javascript_worker","JavaScriptWorker");return b.attachToDocument(a.getDocument()),b.on("jslint",function(b){var c=[];for(var d=0;d<b.data.length;d++){var e=b.data[d];e&&c.push({row:e.line-1,column:e.character-1,text:e.reason,type:"warning",lint:e})}a.setAnnotations(c)}),b.on("narcissus",function(b){a.setAnnotations([b.data])}),b.on("terminate",function(){a.clearAnnotations()}),b}}.call(m.prototype),b.Mode=m}),define("ace/mode/javascript_highlight_rules",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/unicode","ace/mode/doc_comment_highlight_rules","ace/mode/text_highlight_rules"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("../lib/lang"),f=a("../unicode"),g=a("./doc_comment_highlight_rules").DocCommentHighlightRules,h=a("./text_highlight_rules").TextHighlightRules,i=function(){var a=e.arrayToMap("Array|Boolean|Date|Function|Iterator|Number|Object|RegExp|String|Proxy|Namespace|QName|XML|XMLList|ArrayBuffer|Float32Array|Float64Array|Int16Array|Int32Array|Int8Array|Uint16Array|Uint32Array|Uint8Array|Uint8ClampedArray|Error|EvalError|InternalError|RangeError|ReferenceError|StopIteration|SyntaxError|TypeError|URIError|decodeURI|decodeURIComponent|encodeURI|encodeURIComponent|eval|isFinite|isNaN|parseFloat|parseInt|JSON|Math|this|arguments|prototype|window|document".split("|")),b=e.arrayToMap("break|case|catch|continue|default|delete|do|else|finally|for|function|if|in|instanceof|new|return|switch|throw|try|typeof|let|var|while|with|const|yield|import|get|set".split("|")),c="case|do|else|finally|in|instanceof|return|throw|try|typeof|yield",d=e.arrayToMap("__parent__|__count__|escape|unescape|with|__proto__".split("|")),h=e.arrayToMap("const|let|var|function".split("|")),i=e.arrayToMap("null|Infinity|NaN|undefined".split("|")),j=e.arrayToMap("class|enum|extends|super|export|implements|private|public|interface|package|protected|static".split("|")),k="["+f.packages.L+"\\$_]["+f.packages.L+f.packages.Mn+f.packages.Mc+f.packages.Nd+f.packages.Pc+"\\$_]*\\b";this.$rules={start:[{token:"comment",regex:"\\/\\/.*$"},(new g).getStartRule("doc-start"),{token:"comment",merge:!0,regex:"\\/\\*",next:"comment"},{token:"string",regex:'["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'},{token:"string",merge:!0,regex:'["].*\\\\$',next:"qqstring"},{token:"string",regex:"['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"},{token:"string",merge:!0,regex:"['].*\\\\$",next:"qstring"},{token:"constant.numeric",regex:"0[xX][0-9a-fA-F]+\\b"},{token:"constant.numeric",regex:"[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"},{token:["keyword.definition","text","entity.name.function"],regex:"(function)(\\s+)("+k+")"},{token:"constant.language.boolean",regex:"(?:true|false)\\b"},{token:"keyword",regex:"(?:"+c+")\\b",next:"regex_allowed"},{token:function(c){return a.hasOwnProperty(c)?"variable.language":d.hasOwnProperty(c)?"invalid.deprecated":h.hasOwnProperty(c)?"keyword.definition":b.hasOwnProperty(c)?"keyword":i.hasOwnProperty(c)?"constant.language":j.hasOwnProperty(c)?"invalid.illegal":c=="debugger"?"invalid.deprecated":"identifier"},regex:k},{token:"keyword.operator",regex:"!|\\$|%|&|\\*|\\-\\-|\\-|\\+\\+|\\+|~|===|==|=|!=|!==|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\\|\\||\\?\\:|\\*=|%=|\\+=|\\-=|&=|\\^=|\\b(?:in|instanceof|new|delete|typeof|void)",next:"regex_allowed"},{token:"punctuation.operator",regex:"\\?|\\:|\\,|\\;|\\.",next:"regex_allowed"},{token:"paren.lparen",regex:"[[({]",next:"regex_allowed"},{token:"paren.rparen",regex:"[\\])}]"},{token:"keyword.operator",regex:"\\/=?",next:"regex_allowed"},{token:"comment",regex:"^#!.*$"},{token:"text",regex:"\\s+"}],regex_allowed:[{token:"comment",merge:!0,regex:"\\/\\*",next:"comment_regex_allowed"},{token:"comment",regex:"\\/\\/.*$"},{token:"string.regexp",regex:"\\/",next:"regex",merge:!0},{token:"text",regex:"\\s+"},{token:"empty",regex:"",next:"start"}],regex:[{token:"regexp.keyword.operator",regex:"\\\\(?:u[\\da-fA-F]{4}|x[\\da-fA-F]{2}|.)",next:"regex"},{token:"string.regexp",regex:"/\\w*",next:"start",merge:!0},{token:"string.regexp",regex:"[^\\\\/\\[]+",next:"regex",merge:!0},{token:"string.regexp.charachterclass",regex:"\\[",next:"regex_character_class",merge:!0},{token:"empty",regex:"",next:"start"}],regex_character_class:[{token:"regexp.keyword.operator",regex:"\\\\(?:u[\\da-fA-F]{4}|x[\\da-fA-F]{2}|.)",next:"regex_character_class"},{token:"string.regexp.charachterclass",regex:"]",next:"regex",merge:!0},{token:"string.regexp.charachterclass",regex:"[^\\\\\\]]+",next:"regex_character_class",merge:!0},{token:"empty",regex:"",next:"start"}],comment_regex_allowed:[{token:"comment",regex:".*?\\*\\/",merge:!0,next:"regex_allowed"},{token:"comment",merge:!0,regex:".+"}],comment:[{token:"comment",regex:".*?\\*\\/",merge:!0,next:"start"},{token:"comment",merge:!0,regex:".+"}],qqstring:[{token:"string",regex:'(?:(?:\\\\.)|(?:[^"\\\\]))*?"',next:"start"},{token:"string",merge:!0,regex:".+"}],qstring:[{token:"string",regex:"(?:(?:\\\\.)|(?:[^'\\\\]))*?'",next:"start"},{token:"string",merge:!0,regex:".+"}]},this.embedRules(g,"doc-",[(new g).getEndRule("start")])};d.inherits(i,h),b.JavaScriptHighlightRules=i}),define("ace/mode/doc_comment_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("./text_highlight_rules").TextHighlightRules,f=function(){this.$rules={start:[{token:"comment.doc.tag",regex:"@[\\w\\d_]+"},{token:"comment.doc",merge:!0,regex:"\\s+"},{token:"comment.doc",merge:!0,regex:"TODO"},{token:"comment.doc",merge:!0,regex:"[^@\\*]+"},{token:"comment.doc",merge:!0,regex:"."}]}};d.inherits(f,e),function(){this.getStartRule=function(a){return{token:"comment.doc",merge:!0,regex:"\\/\\*(?=\\*)",next:a}},this.getEndRule=function(a){return{token:"comment.doc",merge:!0,regex:"\\*\\/",next:a}}}.call(f.prototype),b.DocCommentHighlightRules=f}),define("ace/mode/matching_brace_outdent",["require","exports","module","ace/range"],function(a,b,c){"use strict";var d=a("../range").Range,e=function(){};((function(){this.checkOutdent=function(a,b){return/^\s+$/.test(a)?/^\s*\}/.test(b):!1},this.autoOutdent=function(a,b){var c=a.getLine(b),e=c.match(/^(\s*\})/);if(!e)return 0;var f=e[1].length,g=a.findMatchingBracket({row:b,column:f});if(!g||g.row==b)return 0;var h=this.$getIndent(a.getLine(g.row));a.replace(new d(b,0,b,f-1),h)},this.$getIndent=function(a){var b=a.match(/^(\s+)/);return b?b[1]:""}})).call(e.prototype),b.MatchingBraceOutdent=e}),define("ace/worker/worker_client",["require","exports","module","ace/lib/oop","ace/lib/event_emitter"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("../lib/event_emitter").EventEmitter,f=function(b,d,e,f){this.changeListener=this.changeListener.bind(this);if(c.packaged){var g=this.$guessBasePath();this.$worker=new Worker(g+d)}else{var h=this.$normalizePath(a.nameToUrl("ace/worker/worker",null,"_"));this.$worker=new Worker(h);var i={};for(var j=0;j<b.length;j++){var k=b[j],l=this.$normalizePath(a.nameToUrl(k,null,"_").replace(/.js$/,""));i[k]=l}}this.$worker.postMessage({init:!0,tlns:i,module:e,classname:f}),this.callbackId=1,this.callbacks={};var m=this;this.$worker.onerror=function(a){throw window.console&&console.log&&console.log(a),a},this.$worker.onmessage=function(a){var b=a.data;switch(b.type){case"log":window.console&&console.log&&console.log(b.data);break;case"event":m._emit(b.name,{data:b.data});break;case"call":var c=m.callbacks[b.id];c&&(c(b.data),delete m.callbacks[b.id])}}};((function(){d.implement(this,e),this.$normalizePath=function(a){return a=a.replace(/^[a-z]+:\/\/[^\/]+\//,""),a=location.protocol+"//"+location.host+(a.charAt(0)=="/"?"":location.pathname.replace(/\/[^\/]*$/,""))+"/"+a.replace(/^[\/]+/,""),a},this.$guessBasePath=function(){if(a.aceBaseUrl)return a.aceBaseUrl;var b=document.getElementsByTagName("script");for(var c=0;c<b.length;c++){var d=b[c],e=d.getAttribute("data-ace-base");if(e)return e.replace(/\/*$/,"/");var f=d.src||d.getAttribute("src");if(!f)continue;var g=f.match(/^(?:(.*\/)ace\.js|(.*\/)ace(-uncompressed)?(-noconflict)?\.js)(?:\?|$)/);if(g)return g[1]||g[2]}return""},this.terminate=function(){this._emit("terminate",{}),this.$worker.terminate(),this.$worker=null,this.$doc.removeEventListener("change",this.changeListener),this.$doc=null},this.send=function(a,b){this.$worker.postMessage({command:a,args:b})},this.call=function(a,b,c){if(c){var d=this.callbackId++;this.callbacks[d]=c,b.push(d)}this.send(a,b)},this.emit=function(a,b){try{this.$worker.postMessage({event:a,data:{data:b.data}})}catch(c){}},this.attachToDocument=function(a){this.$doc&&this.terminate(),this.$doc=a,this.call("setValue",[a.getValue()]),a.on("change",this.changeListener)},this.changeListener=function(a){a.range={start:a.data.range.start,end:a.data.range.end},this.emit("change",a)}})).call(f.prototype),b.WorkerClient=f}),define("ace/mode/behaviour/cstyle",["require","exports","module","ace/lib/oop","ace/mode/behaviour"],function(a,b,c){"use strict";var d=a("../../lib/oop"),e=a("../behaviour").Behaviour,f=function(){this.add("braces","insertion",function(a,b,c,d,e){if(e=="{"){var f=c.getSelectionRange(),g=d.doc.getTextRange(f);return g!==""?{text:"{"+g+"}",selection:!1}:{text:"{}",selection:[1,1]}}if(e=="}"){var h=c.getCursorPosition(),i=d.doc.getLine(h.row),j=i.substring(h.column,h.column+1);if(j=="}"){var k=d.$findOpeningBracket("}",{column:h.column+1,row:h.row});if(k!==null)return{text:"",selection:[1,1]}}}else if(e=="\n"){var h=c.getCursorPosition(),i=d.doc.getLine(h.row),j=i.substring(h.column,h.column+1);if(j=="}"){var l=d.findMatchingBracket({row:h.row,column:h.column+1});if(!l)return null;var m=this.getNextLineIndent(a,i.substring(0,i.length-1),d.getTabString()),n=this.$getIndent(d.doc.getLine(l.row));return{text:"\n"+m+"\n"+n,selection:[1,m.length,1,m.length]}}}}),this.add("braces","deletion",function(a,b,c,d,e){var f=d.doc.getTextRange(e);if(!e.isMultiLine()&&f=="{"){var g=d.doc.getLine(e.start.row),h=g.substring(e.end.column,e.end.column+1);if(h=="}")return e.end.column++,e}}),this.add("parens","insertion",function(a,b,c,d,e){if(e=="("){var f=c.getSelectionRange(),g=d.doc.getTextRange(f);return g!==""?{text:"("+g+")",selection:!1}:{text:"()",selection:[1,1]}}if(e==")"){var h=c.getCursorPosition(),i=d.doc.getLine(h.row),j=i.substring(h.column,h.column+1);if(j==")"){var k=d.$findOpeningBracket(")",{column:h.column+1,row:h.row});if(k!==null)return{text:"",selection:[1,1]}}}}),this.add("parens","deletion",function(a,b,c,d,e){var f=d.doc.getTextRange(e);if(!e.isMultiLine()&&f=="("){var g=d.doc.getLine(e.start.row),h=g.substring(e.start.column+1,e.start.column+2);if(h==")")return e.end.column++,e}}),this.add("string_dquotes","insertion",function(a,b,c,d,e){if(e=='"'){var f=c.getSelectionRange(),g=d.doc.getTextRange(f);if(g!=="")return{text:'"'+g+'"',selection:!1};var h=c.getCursorPosition(),i=d.doc.getLine(h.row),j=i.substring(h.column-1,h.column);if(j=="\\")return null;var k=d.getTokens(f.start.row,f.start.row)[0].tokens,l=0,m,n=-1;for(var o=0;o<k.length;o++){m=k[o],m.type=="string"?n=-1:n<0&&(n=m.value.indexOf('"'));if(m.value.length+l>f.start.column)break;l+=k[o].value.length}if(!m||n<0&&m.type!=="comment"&&(m.type!=="string"||f.start.column!==m.value.length+l-1&&m.value.lastIndexOf('"')===m.value.length-1))return{text:'""',selection:[1,1]};if(m&&m.type==="string"){var p=i.substring(h.column,h.column+1);if(p=='"')return{text:"",selection:[1,1]}}}}),this.add("string_dquotes","deletion",function(a,b,c,d,e){var f=d.doc.getTextRange(e);if(!e.isMultiLine()&&f=='"'){var g=d.doc.getLine(e.start.row),h=g.substring(e.start.column+1,e.start.column+2);if(h=='"')return e.end.column++,e}})};d.inherits(f,e),b.CstyleBehaviour=f}),define("ace/mode/folding/cstyle",["require","exports","module","ace/lib/oop","ace/range","ace/mode/folding/fold_mode"],function(a,b,c){"use strict";var d=a("../../lib/oop"),e=a("../../range").Range,f=a("./fold_mode").FoldMode,g=b.FoldMode=function(){};d.inherits(g,f),function(){this.foldingStartMarker=/(\{|\[)[^\}\]]*$|^\s*(\/\*)/,this.foldingStopMarker=/^[^\[\{]*(\}|\])|^[\s\*]*(\*\/)/,this.getFoldWidgetRange=function(a,b,c){var d=a.getLine(c),f=d.match(this.foldingStartMarker);if(f){var g=f.index;if(f[1])return this.openingBracketBlock(a,f[1],c,g);var h=a.getCommentFoldRange(c,g+f[0].length);return h.end.column-=2,h}if(b!=="markbeginend")return;var f=d.match(this.foldingStopMarker);if(f){var g=f.index+f[0].length;if(f[2]){var h=a.getCommentFoldRange(c,g);return h.end.column-=2,h}var i={row:c,column:g},j=a.$findOpeningBracket(f[1],i);if(!j)return;return j.column++,i.column--,e.fromPoints(j,i)}}}.call(g.prototype)}),define("ace/mode/folding/fold_mode",["require","exports","module","ace/range"],function(a,b,c){"use strict";var d=a("../../range").Range,e=b.FoldMode=function(){};((function(){this.foldingStartMarker=null,this.foldingStopMarker=null,this.getFoldWidget=function(a,b,c){var d=a.getLine(c);return this.foldingStartMarker.test(d)?"start":b=="markbeginend"&&this.foldingStopMarker&&this.foldingStopMarker.test(d)?"end":""},this.getFoldWidgetRange=function(a,b,c){return null},this.indentationBlock=function(a,b,c){var e=/^\s*/,f=b,g=b,h=a.getLine(b),i=c||h.length,j=h.match(e)[0].length,k=a.getLength();while(++b<k){h=a.getLine(b);var l=h.match(e)[0].length;if(l==h.length)continue;if(l<=j)break;g=b}if(g>f){var m=a.getLine(g).length;return new d(f,i,g,m)}},this.openingBracketBlock=function(a,b,c,e){var f={row:c,column:e+1},g=a.$findClosingBracket(b,f);if(!g)return;var h=a.foldWidgets[g.row];return h==null&&(h=this.getFoldWidget(a,g.row)),h=="start"&&(g.row--,g.column=a.getLine(g.row).length),d.fromPoints(f,g)}})).call(e.prototype)}),define("ace/mode/css",["require","exports","module","ace/lib/oop","ace/mode/text","ace/tokenizer","ace/mode/css_highlight_rules","ace/mode/matching_brace_outdent","ace/worker/worker_client","ace/mode/folding/cstyle"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("./text").Mode,f=a("../tokenizer").Tokenizer,g=a("./css_highlight_rules").CssHighlightRules,h=a("./matching_brace_outdent").MatchingBraceOutdent,i=a("../worker/worker_client").WorkerClient,j=a("./folding/cstyle").FoldMode,k=function(){this.$tokenizer=new f((new g).getRules(),"i"),this.$outdent=new h,this.foldingRules=new j};d.inherits(k,e),function(){this.foldingRules="cStyle",this.getNextLineIndent=function(a,b,c){var d=this.$getIndent(b),e=this.$tokenizer.getLineTokens(b,a).tokens;if(e.length&&e[e.length-1].type=="comment")return d;var f=b.match(/^.*\{\s*$/);return f&&(d+=c),d},this.checkOutdent=function(a,b,c){return this.$outdent.checkOutdent(b,c)},this.autoOutdent=function(a,b,c){this.$outdent.autoOutdent(b,c)},this.createWorker=function(a){var b=new i(["ace"],"worker-css.js","ace/mode/css_worker","Worker");return b.attachToDocument(a.getDocument()),b.on("csslint",function(b){var c=[];b.data.forEach(function(a){c.push({row:a.line-1,column:a.col-1,text:a.message,type:a.type,lint:a})}),a.setAnnotations(c)}),b}}.call(k.prototype),b.Mode=k}),define("ace/mode/css_highlight_rules",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/mode/text_highlight_rules"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("../lib/lang"),f=a("./text_highlight_rules").TextHighlightRules,g=function(){var a=e.arrayToMap("-moz-appearance|-moz-box-sizing|-webkit-box-sizing|-moz-outline-radius|-moz-transform|-webkit-transform|appearance|azimuth|background-attachment|background-color|background-image|background-origin|background-position|background-repeat|background|border-bottom-color|border-bottom-style|border-bottom-width|border-bottom|border-collapse|border-color|border-left-color|border-left-style|border-left-width|border-left|border-right-color|border-right-style|border-right-width|border-right|border-spacing|border-style|border-top-color|border-top-style|border-top-width|border-top|border-width|border|bottom|box-sizing|caption-side|clear|clip|color|content|counter-increment|counter-reset|cue-after|cue-before|cue|cursor|direction|display|elevation|empty-cells|float|font-family|font-size-adjust|font-size|font-stretch|font-style|font-variant|font-weight|font|height|left|letter-spacing|line-height|list-style-image|list-style-position|list-style-type|list-style|margin-bottom|margin-left|margin-right|margin-top|marker-offset|margin|marks|max-height|max-width|min-height|min-width|-moz-border-radius|opacity|orphans|outline-color|outline-offset|outline-radius|outline-style|outline-width|outline|overflow|overflow-x|overflow-y|padding-bottom|padding-left|padding-right|padding-top|padding|page-break-after|page-break-before|page-break-inside|page|pause-after|pause-before|pause|pitch-range|pitch|play-during|pointer-events|position|quotes|resize|richness|right|size|speak-header|speak-numeral|speak-punctuation|speech-rate|speak|stress|table-layout|text-align|text-decoration|text-indent|text-shadow|text-transform|top|transform|unicode-bidi|vertical-align|visibility|voice-family|volume|white-space|widows|width|word-spacing|z-index".split("|")),b=e.arrayToMap("rgb|rgba|url|attr|counter|counters".split("|")),c=e.arrayToMap("absolute|all-scroll|always|armenian|auto|baseline|below|bidi-override|block|bold|bolder|border-box|both|bottom|break-all|break-word|capitalize|center|char|circle|cjk-ideographic|col-resize|collapse|content-box|crosshair|dashed|decimal-leading-zero|decimal|default|disabled|disc|distribute-all-lines|distribute-letter|distribute-space|distribute|dotted|double|e-resize|ellipsis|fixed|georgian|groove|hand|hebrew|help|hidden|hiragana-iroha|hiragana|horizontal|ideograph-alpha|ideograph-numeric|ideograph-parenthesis|ideograph-space|inactive|inherit|inline-block|inline|inset|inside|inter-ideograph|inter-word|italic|justify|katakana-iroha|katakana|keep-all|left|lighter|line-edge|line-through|line|list-item|loose|lower-alpha|lower-greek|lower-latin|lower-roman|lowercase|lr-tb|ltr|medium|middle|move|n-resize|ne-resize|newspaper|no-drop|no-repeat|nw-resize|none|normal|not-allowed|nowrap|oblique|outset|outside|overline|pointer|progress|relative|repeat-x|repeat-y|repeat|right|ridge|row-resize|rtl|s-resize|scroll|se-resize|separate|small-caps|solid|square|static|strict|super|sw-resize|table-footer-group|table-header-group|tb-rl|text-bottom|text-top|text|thick|thin|top|transparent|underline|upper-alpha|upper-latin|upper-roman|uppercase|vertical-ideographic|vertical-text|visible|w-resize|wait|whitespace|zero".split("|")),d=e.arrayToMap("aqua|black|blue|fuchsia|gray|green|lime|maroon|navy|olive|orange|purple|red|silver|teal|white|yellow".split("|")),f="\\-?(?:(?:[0-9]+)|(?:[0-9]*\\.[0-9]+))",g=[{token:"comment",merge:!0,regex:"\\/\\*",next:"ruleset_comment"},{token:"string",regex:'["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'},{token:"string",regex:"['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"},{token:"constant.numeric",regex:f+"(?:em|ex|px|cm|mm|in|pt|pc|deg|rad|grad|ms|s|hz|khz|%)"},{token:"constant.numeric",regex:"#[a-f0-9]{6}"},{token:"constant.numeric",regex:"#[a-f0-9]{3}"},{token:function(e){return a.hasOwnProperty(e.toLowerCase())?"support.type":b.hasOwnProperty(e.toLowerCase())?"support.function":c.hasOwnProperty(e.toLowerCase())?"support.constant":d.hasOwnProperty(e.toLowerCase())?"support.constant.color":"text"},regex:"\\-?[a-zA-Z_][a-zA-Z0-9_\\-]*"}],h=e.copyArray(g);h.unshift({token:"paren.rparen",regex:"\\}",next:"start"});var i=e.copyArray(g);i.unshift({token:"paren.rparen",regex:"\\}",next:"media"});var j=[{token:"comment",merge:!0,regex:".+"}],k=e.copyArray(j);k.unshift({token:"comment",regex:".*?\\*\\/",next:"start"});var l=e.copyArray(j);l.unshift({token:"comment",regex:".*?\\*\\/",next:"media"});var m=e.copyArray(j);m.unshift({token:"comment",regex:".*?\\*\\/",next:"ruleset"}),this.$rules={start:[{token:"comment",merge:!0,regex:"\\/\\*",next:"comment"},{token:"paren.lparen",regex:"\\{",next:"ruleset"},{token:"string",regex:"@.*?{",next:"media"},{token:"keyword",regex:"#[a-z0-9-_]+"},{token:"variable",regex:"\\.[a-z0-9-_]+"},{token:"string",regex:":[a-z0-9-_]+"},{token:"constant",regex:"[a-z0-9-_]+"}],media:[{token:"comment",merge:!0,regex:"\\/\\*",next:"media_comment"},{token:"paren.lparen",regex:"\\{",next:"media_ruleset"},{token:"string",regex:"\\}",next:"start"},{token:"keyword",regex:"#[a-z0-9-_]+"},{token:"variable",regex:"\\.[a-z0-9-_]+"},{token:"string",regex:":[a-z0-9-_]+"},{token:"constant",regex:"[a-z0-9-_]+"}],comment:k,ruleset:h,ruleset_comment:m,media_ruleset:i,media_comment:l}};d.inherits(g,f),b.CssHighlightRules=g}),define("ace/mode/html_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/css_highlight_rules","ace/mode/javascript_highlight_rules","ace/mode/xml_util","ace/mode/text_highlight_rules"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("./css_highlight_rules").CssHighlightRules,f=a("./javascript_highlight_rules").JavaScriptHighlightRules,g=a("./xml_util"),h=a("./text_highlight_rules").TextHighlightRules,i=function(){this.$rules={start:[{token:"text",merge:!0,regex:"<\\!\\[CDATA\\[",next:"cdata"},{token:"xml_pe",regex:"<\\?.*?\\?>"},{token:"comment",merge:!0,regex:"<\\!--",next:"comment"},{token:"meta.tag",regex:"<(?=s*script\\b)",next:"script"},{token:"meta.tag",regex:"<(?=s*style\\b)",next:"css"},{token:"meta.tag",regex:"<\\/?",next:"tag"},{token:"text",regex:"\\s+"},{token:"text",regex:"[^<]+"}],cdata:[{token:"text",regex:"\\]\\]>",next:"start"},{token:"text",merge:!0,regex:"\\s+"},{token:"text",merge:!0,regex:".+"}],comment:[{token:"comment",regex:".*?-->",next:"start"},{token:"comment",merge:!0,regex:".+"}]},g.tag(this.$rules,"tag","start"),g.tag(this.$rules,"css","css-start"),g.tag(this.$rules,"script","js-start"),this.embedRules(f,"js-",[{token:"comment",regex:"\\/\\/.*(?=<\\/script>)",next:"tag"},{token:"meta.tag",regex:"<\\/(?=script)",next:"tag"}]),this.embedRules(e,"css-",[{token:"meta.tag",regex:"<\\/(?=style)",next:"tag"}])};d.inherits(i,h),b.HtmlHighlightRules=i}),define("ace/mode/xml_util",["require","exports","module","ace/lib/lang"],function(a,b,c){function g(a){return[{token:"string",regex:'".*?"'},{token:"string",merge:!0,regex:'["].*',next:a+"-qqstring"},{token:"string",regex:"'.*?'"},{token:"string",merge:!0,regex:"['].*",next:a+"-qstring"}]}function h(a,b){return[{token:"string",merge:!0,regex:".*?"+a,next:b},{token:"string",merge:!0,regex:".+"}]}"use strict";var d=a("../lib/lang"),e=d.arrayToMap("button|form|input|label|select|textarea".split("|")),f=d.arrayToMap("table|tbody|td|tfoot|th|tr".split("|"));b.tag=function(a,b,c){a[b]=[{token:"text",regex:"\\s+"},{token:function(a){return a==="a"?"meta.tag.anchor":a==="img"?"meta.tag.image":a==="script"?"meta.tag.script":a==="style"?"meta.tag.style":e.hasOwnProperty(a.toLowerCase())?"meta.tag.form":f.hasOwnProperty(a.toLowerCase())?"meta.tag.table":"meta.tag"},merge:!0,regex:"[-_a-zA-Z0-9:!]+",next:b+"embed-attribute-list"},{token:"empty",regex:"",next:b+"embed-attribute-list"}],a[b+"-qstring"]=h("'",b+"embed-attribute-list"),a[b+"-qqstring"]=h('"',b+"embed-attribute-list"),a[b+"embed-attribute-list"]=[{token:"meta.tag",merge:!0,regex:"/?>",next:c},{token:"keyword.operator",regex:"="},{token:"entity.other.attribute-name",regex:"[-_a-zA-Z0-9:]+"},{token:"constant.numeric",regex:"[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"},{token:"text",regex:"\\s+"}].concat(g(b))}}),define("ace/mode/behaviour/xml",["require","exports","module","ace/lib/oop","ace/mode/behaviour","ace/mode/behaviour/cstyle"],function(a,b,c){"use strict";var d=a("../../lib/oop"),e=a("../behaviour").Behaviour,f=a("./cstyle").CstyleBehaviour,g=function(){this.inherit(f,["string_dquotes"]),this.add("brackets","insertion",function(a,b,c,d,e){if(e=="<"){var f=c.getSelectionRange(),g=d.doc.getTextRange(f);return g!==""?!1:{text:"<>",selection:[1,1]}}if(e==">"){var h=c.getCursorPosition(),i=d.doc.getLine(h.row),j=i.substring(h.column,h.column+1);if(j==">")return{text:"",selection:[1,1]}}else if(e=="\n"){var h=c.getCursorPosition(),i=d.doc.getLine(h.row),k=i.substring(h.column,h.column+2);if(k=="</"){var l=this.$getIndent(d.doc.getLine(h.row))+d.getTabString(),m=this.$getIndent(d.doc.getLine(h.row));return{text:"\n"+l+"\n"+m,selection:[1,l.length,1,l.length]}}}})};d.inherits(g,e),b.XmlBehaviour=g}),define("ace/mode/folding/html",["require","exports","module","ace/lib/oop","ace/mode/folding/mixed","ace/mode/folding/xml","ace/mode/folding/cstyle"],function(a,b,c){"use strict";var d=a("../../lib/oop"),e=a("./mixed").FoldMode,f=a("./xml").FoldMode,g=a("./cstyle").FoldMode,h=b.FoldMode=function(){e.call(this,new f({area:1,base:1,br:1,col:1,command:1,embed:1,hr:1,img:1,input:1,keygen:1,link:1,meta:1,param:1,source:1,track:1,wbr:1,li:1,dt:1,dd:1,p:1,rt:1,rp:1,optgroup:1,option:1,colgroup:1,td:1,th:1}),{"js-":new g,"css-":new g})};d.inherits(h,e)}),define("ace/mode/folding/mixed",["require","exports","module","ace/lib/oop","ace/mode/folding/fold_mode"],function(a,b,c){"use strict";var d=a("../../lib/oop"),e=a("./fold_mode").FoldMode,f=b.FoldMode=function(a,b){this.defaultMode=a,this.subModes=b};d.inherits(f,e),function(){this.$getMode=function(a){for(var b in this.subModes)if(a.indexOf(b)===0)return this.subModes[b];return null},this.$tryMode=function(a,b,c,d){var e=this.$getMode(a);return e?e.getFoldWidget(b,c,d):""},this.getFoldWidget=function(a,b,c){return this.$tryMode(a.getState(c-1),a,b,c)||this.$tryMode(a.getState(c),a,b,c)||this.defaultMode.getFoldWidget(a,b,c)},this.getFoldWidgetRange=function(a,b,c){var d=this.$getMode(a.getState(c-1));if(!d||!d.getFoldWidget(a,b,c))d=this.$getMode(a.getState(c));if(!d||!d.getFoldWidget(a,b,c))d=this.defaultMode;return d.getFoldWidgetRange(a,b,c)}}.call(f.prototype)}),define("ace/mode/folding/xml",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/range","ace/mode/folding/fold_mode","ace/token_iterator"],function(a,b,c){"use strict";var d=a("../../lib/oop"),e=a("../../lib/lang"),f=a("../../range").Range,g=a("./fold_mode").FoldMode,h=a("../../token_iterator").TokenIterator,i=b.FoldMode=function(a){g.call(this),this.voidElements=a||{}};d.inherits(i,g),function(){this.getFoldWidget=function(a,b,c){var d=this._getFirstTagInLine(a,c);return d.closing?b=="markbeginend"?"end":"":!d.tagName||this.voidElements[d.tagName.toLowerCase()]?"":d.selfClosing?"":d.value.indexOf("/"+d.tagName)!==-1?"":"start"},this._getFirstTagInLine=function(a,b){var c=a.getTokens(b,b)[0].tokens,d="";for(var f=0;f<c.length;f++){var g=c[f];g.type.indexOf("meta.tag")===0?d+=g.value:d+=e.stringRepeat(" ",g.value.length)}return this._parseTag(d)},this.tagRe=/^(\s*)(<?(\/?)([-_a-zA-Z0-9:!]*)\s*(\/?)>?)/,this._parseTag=function(a){var b=this.tagRe.exec(a),c=this.tagRe.lastIndex||0;return this.tagRe.lastIndex=0,{value:a,match:b?b[2]:"",closing:b?!!b[3]:!1,selfClosing:b?!!b[5]||b[2]=="/>":!1,tagName:b?b[4]:"",column:b[1]?c+b[1].length:c}},this._readTagForward=function(a){var b=a.getCurrentToken();if(!b)return null;var c="",d;do if(b.type.indexOf("meta.tag")===0){if(!d)var d={row:a.getCurrentTokenRow(),column:a.getCurrentTokenColumn()};c+=b.value;if(c.indexOf(">")!==-1){var e=this._parseTag(c);return e.start=d,e.end={row:a.getCurrentTokenRow(),column:a.getCurrentTokenColumn()+b.value.length},a.stepForward(),e}}while(b=a.stepForward());return null},this._readTagBackward=function(a){var b=a.getCurrentToken();if(!b)return null;var c="",d;do if(b.type.indexOf("meta.tag")===0){d||(d={row:a.getCurrentTokenRow(),column:a.getCurrentTokenColumn()+b.value.length}),c=b.value+c;if(c.indexOf("<")!==-1){var e=this._parseTag(c);return e.end=d,e.start={row:a.getCurrentTokenRow(),column:a.getCurrentTokenColumn()},a.stepBackward(),e}}while(b=a.stepBackward());return null},this._pop=function(a,b){while(a.length){var c=a[a.length-1];if(!b||c.tagName==b.tagName)return a.pop();if(this.voidElements[b.tagName])return;if(this.voidElements[c.tagName]){a.pop();continue}return null}},this.getFoldWidgetRange=function(a,b,c){var d=this._getFirstTagInLine(a,c);if(!d.match)return null;var e=d.closing||d.selfClosing,g=[],i;if(!e){var j=new h(a,c,d.column),k={row:c,column:d.column+d.tagName.length+2};while(i=this._readTagForward(j)){if(i.selfClosing){if(!g.length)return i.start.column+=i.tagName.length+2,i.end.column-=2,f.fromPoints(i.start,i.end);continue}if(i.closing){this._pop(g,i);if(g.length==0)return f.fromPoints(k,i.start)}else g.push(i)}}else{var j=new h(a,c,d.column+d.match.length),l={row:c,column:d.column};while(i=this._readTagBackward(j)){if(i.selfClosing){if(!g.length)return i.start.column+=i.tagName.length+2,i.end.column-=2,f.fromPoints(i.start,i.end);continue}if(!i.closing){this._pop(g,i);if(g.length==0)return i.start.column+=i.tagName.length+2,f.fromPoints(i.start,l)}else g.push(i)}}}}.call(i.prototype)}),function(){window.require(["ace/ace"],function(a){window.ace||(window.ace={});for(var b in a)a.hasOwnProperty(b)&&(ace[b]=a[b])})}()
\ No newline at end of file
+define("ace/mode/html",["require","exports","module","ace/lib/oop","ace/mode/text","ace/mode/javascript","ace/mode/css","ace/tokenizer","ace/mode/html_highlight_rules","ace/mode/behaviour/xml","ace/mode/folding/html"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("./text").Mode,f=a("./javascript").Mode,g=a("./css").Mode,h=a("../tokenizer").Tokenizer,i=a("./html_highlight_rules").HtmlHighlightRules,j=a("./behaviour/xml").XmlBehaviour,k=a("./folding/html").FoldMode,l=function(){var a=new i;this.$tokenizer=new h(a.getRules()),this.$behaviour=new j,this.$embeds=a.getEmbeds(),this.createModeDelegates({"js-":f,"css-":g}),this.foldingRules=new k};d.inherits(l,e),function(){this.toggleCommentLines=function(a,b,c,d){return 0},this.getNextLineIndent=function(a,b,c){return this.$getIndent(b)},this.checkOutdent=function(a,b,c){return!1}}.call(l.prototype),b.Mode=l}),define("ace/mode/javascript",["require","exports","module","ace/lib/oop","ace/mode/text","ace/tokenizer","ace/mode/javascript_highlight_rules","ace/mode/matching_brace_outdent","ace/range","ace/worker/worker_client","ace/mode/behaviour/cstyle","ace/mode/folding/cstyle"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("./text").Mode,f=a("../tokenizer").Tokenizer,g=a("./javascript_highlight_rules").JavaScriptHighlightRules,h=a("./matching_brace_outdent").MatchingBraceOutdent,i=a("../range").Range,j=a("../worker/worker_client").WorkerClient,k=a("./behaviour/cstyle").CstyleBehaviour,l=a("./folding/cstyle").FoldMode,m=function(){this.$tokenizer=new f((new g).getRules()),this.$outdent=new h,this.$behaviour=new k,this.foldingRules=new l};d.inherits(m,e),function(){this.toggleCommentLines=function(a,b,c,d){var e=!0,f=/^(\s*)\/\//;for(var g=c;g<=d;g++)if(!f.test(b.getLine(g))){e=!1;break}if(e){var h=new i(0,0,0,0);for(var g=c;g<=d;g++){var j=b.getLine(g),k=j.match(f);h.start.row=g,h.end.row=g,h.end.column=k[0].length,b.replace(h,k[1])}}else b.indentRows(c,d,"//")},this.getNextLineIndent=function(a,b,c){var d=this.$getIndent(b),e=this.$tokenizer.getLineTokens(b,a),f=e.tokens,g=e.state;if(f.length&&f[f.length-1].type=="comment")return d;if(a=="start"||a=="regex_allowed"){var h=b.match(/^.*(?:\bcase\b.*\:|[\{\(\[])\s*$/);h&&(d+=c)}else if(a=="doc-start"){if(g=="start"||a=="regex_allowed")return"";var h=b.match(/^\s*(\/?)\*/);h&&(h[1]&&(d+=" "),d+="* ")}return d},this.checkOutdent=function(a,b,c){return this.$outdent.checkOutdent(b,c)},this.autoOutdent=function(a,b,c){this.$outdent.autoOutdent(b,c)},this.createWorker=function(a){var b=new j(["ace"],"worker-javascript.js","ace/mode/javascript_worker","JavaScriptWorker");return b.attachToDocument(a.getDocument()),b.on("jslint",function(b){var c=[];for(var d=0;d<b.data.length;d++){var e=b.data[d];e&&c.push({row:e.line-1,column:e.character-1,text:e.reason,type:"warning",lint:e})}a.setAnnotations(c)}),b.on("narcissus",function(b){a.setAnnotations([b.data])}),b.on("terminate",function(){a.clearAnnotations()}),b}}.call(m.prototype),b.Mode=m}),define("ace/mode/javascript_highlight_rules",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/unicode","ace/mode/doc_comment_highlight_rules","ace/mode/text_highlight_rules"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("../lib/lang"),f=a("../unicode"),g=a("./doc_comment_highlight_rules").DocCommentHighlightRules,h=a("./text_highlight_rules").TextHighlightRules,i=function(){var a=e.arrayToMap("Array|Boolean|Date|Function|Iterator|Number|Object|RegExp|String|Proxy|Namespace|QName|XML|XMLList|ArrayBuffer|Float32Array|Float64Array|Int16Array|Int32Array|Int8Array|Uint16Array|Uint32Array|Uint8Array|Uint8ClampedArray|Error|EvalError|InternalError|RangeError|ReferenceError|StopIteration|SyntaxError|TypeError|URIError|decodeURI|decodeURIComponent|encodeURI|encodeURIComponent|eval|isFinite|isNaN|parseFloat|parseInt|JSON|Math|this|arguments|prototype|window|document".split("|")),b=e.arrayToMap("break|case|catch|continue|default|delete|do|else|finally|for|function|if|in|instanceof|new|return|switch|throw|try|typeof|let|var|while|with|const|yield|import|get|set".split("|")),c="case|do|else|finally|in|instanceof|return|throw|try|typeof|yield",d=e.arrayToMap("__parent__|__count__|escape|unescape|with|__proto__".split("|")),h=e.arrayToMap("const|let|var|function".split("|")),i=e.arrayToMap("null|Infinity|NaN|undefined".split("|")),j=e.arrayToMap("class|enum|extends|super|export|implements|private|public|interface|package|protected|static".split("|")),k="["+f.packages.L+"\\$_]["+f.packages.L+f.packages.Mn+f.packages.Mc+f.packages.Nd+f.packages.Pc+"\\$_]*\\b",l="\\\\(?:x[0-9a-fA-F]{2}|u[0-9a-fA-F]{4}|[0-2][0-7]{0,2}|3[0-6][0-7]?|37[0-7]?|[4-7][0-7]?|.)";this.$rules={start:[{token:"comment",regex:/\/\/.*$/},(new g).getStartRule("doc-start"),{token:"comment",merge:!0,regex:/\/\*/,next:"comment"},{token:"string",regex:"'",next:"qstring"},{token:"string",regex:'"',next:"qqstring"},{token:"constant.numeric",regex:/0[xX][0-9a-fA-F]+\b/},{token:"constant.numeric",regex:/[+-]?\d+(?:(?:\.\d*)?(?:[eE][+-]?\d+)?)?\b/},{token:["storage.type","punctuation.operator","support.function","punctuation.operator","entity.name.function","text","keyword.operator","text","storage.type","text","paren.lparen","variable.parameter","paren.rparen"],regex:"("+k+")(\\.)(prototype)(\\.)("+k+")(\\s*)(=)(\\s*)(function)(\\s*)(\\()(.*?)(\\))"},{token:["storage.type","punctuation.operator","support.function","punctuation.operator","entity.name.function","text","keyword.operator","text"],regex:"("+k+")(\\.)(prototype)(\\.)("+k+")(\\s*)(=)(\\s*)"},{token:["storage.type","punctuation.operator","entity.name.function","text","keyword.operator","text","storage.type","text","paren.lparen","variable.parameter","paren.rparen"],regex:"("+k+")(\\.)("+k+")(\\s*)(=)(\\s*)(function)(\\s*)(\\()(.*?)(\\))"},{token:["entity.name.function","text","keyword.operator","text","storage.type","text","paren.lparen","variable.parameter","paren.rparen"],regex:"("+k+")(\\s*)(=)(\\s*)(function)(\\s*)(\\()(.*?)(\\))"},{token:["storage.type","text","entity.name.function","text","paren.lparen","variable.parameter","paren.rparen"],regex:"(function)(\\s+)("+k+")(\\s*)(\\()(.*?)(\\))"},{token:["entity.name.function","text","punctuation.operator","text","storage.type","text","paren.lparen","variable.parameter","paren.rparen"],regex:"("+k+")(\\s*)(:)(\\s*)(function)(\\s*)(\\()(.*?)(\\))"},{token:["text","text","storage.type","text","paren.lparen","variable.parameter","paren.rparen"],regex:"(:)(\\s*)(function)?(\\s*)(\\()([^)]*)(\\))"},{token:"constant.language.boolean",regex:/(?:true|false)\b/},{token:"keyword",regex:"(?:"+c+")\\b",next:"regex_allowed"},{token:["punctuation.operator","support.function"],regex:/(\.)(s(?:h(?:ift|ow(?:Mod(?:elessDialog|alDialog)|Help))|croll(?:X|By(?:Pages|Lines)?|Y|To)?|t(?:opzzzz|rike)|i(?:n|zeToContent|debar|gnText)|ort|u(?:p|b(?:str(?:ing)?)?)|pli(?:ce|t)|e(?:nd|t(?:Re(?:sizable|questHeader)|M(?:i(?:nutes|lliseconds)|onth)|Seconds|Ho(?:tKeys|urs)|Year|Cursor|Time(?:out)?|Interval|ZOptions|Date|UTC(?:M(?:i(?:nutes|lliseconds)|onth)|Seconds|Hours|Date|FullYear)|FullYear|Active)|arch)|qrt|lice|avePreferences|mall)|h(?:ome|andleEvent)|navigate|c(?:har(?:CodeAt|At)|o(?:s|n(?:cat|textual|firm)|mpile)|eil|lear(?:Timeout|Interval)?|a(?:ptureEvents|ll)|reate(?:StyleSheet|Popup|EventObject))|t(?:o(?:GMTString|S(?:tring|ource)|U(?:TCString|pperCase)|Lo(?:caleString|werCase))|est|a(?:n|int(?:Enabled)?))|i(?:s(?:NaN|Finite)|ndexOf|talics)|d(?:isableExternalCapture|ump|etachEvent)|u(?:n(?:shift|taint|escape|watch)|pdateCommands)|j(?:oin|avaEnabled)|p(?:o(?:p|w)|ush|lugins.refresh|a(?:ddings|rse(?:Int|Float)?)|r(?:int|ompt|eference))|e(?:scape|nableExternalCapture|val|lementFromPoint|x(?:p|ec(?:Script|Command)?))|valueOf|UTC|queryCommand(?:State|Indeterm|Enabled|Value)|f(?:i(?:nd|le(?:ModifiedDate|Size|CreatedDate|UpdatedDate)|xed)|o(?:nt(?:size|color)|rward)|loor|romCharCode)|watch|l(?:ink|o(?:ad|g)|astIndexOf)|a(?:sin|nchor|cos|t(?:tachEvent|ob|an(?:2)?)|pply|lert|b(?:s|ort))|r(?:ou(?:nd|teEvents)|e(?:size(?:By|To)|calc|turnValue|place|verse|l(?:oad|ease(?:Capture|Events)))|andom)|g(?:o|et(?:ResponseHeader|M(?:i(?:nutes|lliseconds)|onth)|Se(?:conds|lection)|Hours|Year|Time(?:zoneOffset)?|Da(?:y|te)|UTC(?:M(?:i(?:nutes|lliseconds)|onth)|Seconds|Hours|Da(?:y|te)|FullYear)|FullYear|A(?:ttention|llResponseHeaders)))|m(?:in|ove(?:B(?:y|elow)|To(?:Absolute)?|Above)|ergeAttributes|a(?:tch|rgins|x))|b(?:toa|ig|o(?:ld|rderWidths)|link|ack))\b(?=\()/},{token:["punctuation.operator","support.function.dom"],regex:/(\.)(s(?:ub(?:stringData|mit)|plitText|e(?:t(?:NamedItem|Attribute(?:Node)?)|lect))|has(?:ChildNodes|Feature)|namedItem|c(?:l(?:ick|o(?:se|neNode))|reate(?:C(?:omment|DATASection|aption)|T(?:Head|extNode|Foot)|DocumentFragment|ProcessingInstruction|E(?:ntityReference|lement)|Attribute))|tabIndex|i(?:nsert(?:Row|Before|Cell|Data)|tem)|open|delete(?:Row|C(?:ell|aption)|T(?:Head|Foot)|Data)|focus|write(?:ln)?|a(?:dd|ppend(?:Child|Data))|re(?:set|place(?:Child|Data)|move(?:NamedItem|Child|Attribute(?:Node)?)?)|get(?:NamedItem|Element(?:sBy(?:Name|TagName)|ById)|Attribute(?:Node)?)|blur)\b(?=\()/},{token:["punctuation.operator","support.constant"],regex:/(\.)(s(?:ystemLanguage|cr(?:ipts|ollbars|een(?:X|Y|Top|Left))|t(?:yle(?:Sheets)?|atus(?:Text|bar)?)|ibling(?:Below|Above)|ource|uffixes|e(?:curity(?:Policy)?|l(?:ection|f)))|h(?:istory|ost(?:name)?|as(?:h|Focus))|y|X(?:MLDocument|SLDocument)|n(?:ext|ame(?:space(?:s|URI)|Prop))|M(?:IN_VALUE|AX_VALUE)|c(?:haracterSet|o(?:n(?:structor|trollers)|okieEnabled|lorDepth|mp(?:onents|lete))|urrent|puClass|l(?:i(?:p(?:boardData)?|entInformation)|osed|asses)|alle(?:e|r)|rypto)|t(?:o(?:olbar|p)|ext(?:Transform|Indent|Decoration|Align)|ags)|SQRT(?:1_2|2)|i(?:n(?:ner(?:Height|Width)|put)|ds|gnoreCase)|zIndex|o(?:scpu|n(?:readystatechange|Line)|uter(?:Height|Width)|p(?:sProfile|ener)|ffscreenBuffering)|NEGATIVE_INFINITY|d(?:i(?:splay|alog(?:Height|Top|Width|Left|Arguments)|rectories)|e(?:scription|fault(?:Status|Ch(?:ecked|arset)|View)))|u(?:ser(?:Profile|Language|Agent)|n(?:iqueID|defined)|pdateInterval)|_content|p(?:ixelDepth|ort|ersonalbar|kcs11|l(?:ugins|atform)|a(?:thname|dding(?:Right|Bottom|Top|Left)|rent(?:Window|Layer)?|ge(?:X(?:Offset)?|Y(?:Offset)?))|r(?:o(?:to(?:col|type)|duct(?:Sub)?|mpter)|e(?:vious|fix)))|e(?:n(?:coding|abledPlugin)|x(?:ternal|pando)|mbeds)|v(?:isibility|endor(?:Sub)?|Linkcolor)|URLUnencoded|P(?:I|OSITIVE_INFINITY)|f(?:ilename|o(?:nt(?:Size|Family|Weight)|rmName)|rame(?:s|Element)|gColor)|E|whiteSpace|l(?:i(?:stStyleType|n(?:eHeight|kColor))|o(?:ca(?:tion(?:bar)?|lName)|wsrc)|e(?:ngth|ft(?:Context)?)|a(?:st(?:M(?:odified|atch)|Index|Paren)|yer(?:s|X)|nguage))|a(?:pp(?:MinorVersion|Name|Co(?:deName|re)|Version)|vail(?:Height|Top|Width|Left)|ll|r(?:ity|guments)|Linkcolor|bove)|r(?:ight(?:Context)?|e(?:sponse(?:XML|Text)|adyState))|global|x|m(?:imeTypes|ultiline|enubar|argin(?:Right|Bottom|Top|Left))|L(?:N(?:10|2)|OG(?:10E|2E))|b(?:o(?:ttom|rder(?:Width|RightWidth|BottomWidth|Style|Color|TopWidth|LeftWidth))|ufferDepth|elow|ackground(?:Color|Image)))\b/},{token:["storage.type","punctuation.operator","support.function.firebug"],regex:/(console)(\.)(warn|info|log|error|time|timeEnd|assert)\b/},{token:function(c){return a.hasOwnProperty(c)?"variable.language":d.hasOwnProperty(c)?"invalid.deprecated":h.hasOwnProperty(c)?"storage.type":b.hasOwnProperty(c)?"keyword":i.hasOwnProperty(c)?"constant.language":j.hasOwnProperty(c)?"invalid.illegal":c=="debugger"?"invalid.deprecated":"identifier"},regex:k},{token:"keyword.operator",regex:/!|\$|%|&|\*|\-\-|\-|\+\+|\+|~|===|==|=|!=|!==|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\|\||\?\:|\*=|%=|\+=|\-=|&=|\^=|\b(?:in|instanceof|new|delete|typeof|void)/,next:"regex_allowed"},{token:"punctuation.operator",regex:/\?|\:|\,|\;|\./,next:"regex_allowed"},{token:"paren.lparen",regex:/[\[({]/,next:"regex_allowed"},{token:"paren.rparen",regex:/[\])}]/},{token:"keyword.operator",regex:/\/=?/,next:"regex_allowed"},{token:"comment",regex:/^#!.*$/},{token:"text",regex:/\s+/}],regex_allowed:[{token:"comment",merge:!0,regex:"\\/\\*",next:"comment_regex_allowed"},{token:"comment",regex:"\\/\\/.*$"},{token:"string.regexp",regex:"\\/",next:"regex",merge:!0},{token:"text",regex:"\\s+"},{token:"empty",regex:"",next:"start"}],regex:[{token:"regexp.keyword.operator",regex:"\\\\(?:u[\\da-fA-F]{4}|x[\\da-fA-F]{2}|.)",next:"regex"},{token:"string.regexp",regex:"/\\w*",next:"start",merge:!0},{token:"string.regexp",regex:"[^\\\\/\\[]+",next:"regex",merge:!0},{token:"string.regexp.charachterclass",regex:"\\[",next:"regex_character_class",merge:!0},{token:"empty",regex:"",next:"start"}],regex_character_class:[{token:"regexp.keyword.operator",regex:"\\\\(?:u[\\da-fA-F]{4}|x[\\da-fA-F]{2}|.)",next:"regex_character_class"},{token:"string.regexp.charachterclass",regex:"]",next:"regex",merge:!0},{token:"string.regexp.charachterclass",regex:"[^\\\\\\]]+",next:"regex_character_class",merge:!0},{token:"empty",regex:"",next:"start"}],comment_regex_allowed:[{token:"comment",regex:".*?\\*\\/",merge:!0,next:"regex_allowed"},{token:"comment",merge:!0,regex:".+"}],comment:[{token:"comment",regex:".*?\\*\\/",merge:!0,next:"start"},{token:"comment",merge:!0,regex:".+"}],qqstring:[{token:"constant.language.escape",regex:l},{token:"string",regex:'[^"\\\\]+'},{token:"string",regex:'"',next:"start"}],qstring:[{token:"constant.language.escape",regex:l},{token:"string",regex:"[^'\\\\]+"},{token:"string",regex:"'",next:"start"}]},this.embedRules(g,"doc-",[(new g).getEndRule("start")])};d.inherits(i,h),b.JavaScriptHighlightRules=i}),define("ace/mode/doc_comment_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("./text_highlight_rules").TextHighlightRules,f=function(){this.$rules={start:[{token:"comment.doc.tag",regex:"@[\\w\\d_]+"},{token:"comment.doc",merge:!0,regex:"\\s+"},{token:"comment.doc",merge:!0,regex:"TODO"},{token:"comment.doc",merge:!0,regex:"[^@\\*]+"},{token:"comment.doc",merge:!0,regex:"."}]}};d.inherits(f,e),function(){this.getStartRule=function(a){return{token:"comment.doc",merge:!0,regex:"\\/\\*(?=\\*)",next:a}},this.getEndRule=function(a){return{token:"comment.doc",merge:!0,regex:"\\*\\/",next:a}}}.call(f.prototype),b.DocCommentHighlightRules=f}),define("ace/mode/matching_brace_outdent",["require","exports","module","ace/range"],function(a,b,c){"use strict";var d=a("../range").Range,e=function(){};(function(){this.checkOutdent=function(a,b){return/^\s+$/.test(a)?/^\s*\}/.test(b):!1},this.autoOutdent=function(a,b){var c=a.getLine(b),e=c.match(/^(\s*\})/);if(!e)return 0;var f=e[1].length,g=a.findMatchingBracket({row:b,column:f});if(!g||g.row==b)return 0;var h=this.$getIndent(a.getLine(g.row));a.replace(new d(b,0,b,f-1),h)},this.$getIndent=function(a){var b=a.match(/^(\s+)/);return b?b[1]:""}}).call(e.prototype),b.MatchingBraceOutdent=e}),define("ace/mode/behaviour/cstyle",["require","exports","module","ace/lib/oop","ace/mode/behaviour"],function(a,b,c){"use strict";var d=a("../../lib/oop"),e=a("../behaviour").Behaviour,f=function(){this.add("braces","insertion",function(a,b,c,d,e){if(e=="{"){var f=c.getSelectionRange(),g=d.doc.getTextRange(f);return g!==""?{text:"{"+g+"}",selection:!1}:{text:"{}",selection:[1,1]}}if(e=="}"){var h=c.getCursorPosition(),i=d.doc.getLine(h.row),j=i.substring(h.column,h.column+1);if(j=="}"){var k=d.$findOpeningBracket("}",{column:h.column+1,row:h.row});if(k!==null)return{text:"",selection:[1,1]}}}else if(e=="\n"){var h=c.getCursorPosition(),i=d.doc.getLine(h.row),j=i.substring(h.column,h.column+1);if(j=="}"){var l=d.findMatchingBracket({row:h.row,column:h.column+1});if(!l)return null;var m=this.getNextLineIndent(a,i.substring(0,i.length-1),d.getTabString()),n=this.$getIndent(d.doc.getLine(l.row));return{text:"\n"+m+"\n"+n,selection:[1,m.length,1,m.length]}}}}),this.add("braces","deletion",function(a,b,c,d,e){var f=d.doc.getTextRange(e);if(!e.isMultiLine()&&f=="{"){var g=d.doc.getLine(e.start.row),h=g.substring(e.end.column,e.end.column+1);if(h=="}")return e.end.column++,e}}),this.add("parens","insertion",function(a,b,c,d,e){if(e=="("){var f=c.getSelectionRange(),g=d.doc.getTextRange(f);return g!==""?{text:"("+g+")",selection:!1}:{text:"()",selection:[1,1]}}if(e==")"){var h=c.getCursorPosition(),i=d.doc.getLine(h.row),j=i.substring(h.column,h.column+1);if(j==")"){var k=d.$findOpeningBracket(")",{column:h.column+1,row:h.row});if(k!==null)return{text:"",selection:[1,1]}}}}),this.add("parens","deletion",function(a,b,c,d,e){var f=d.doc.getTextRange(e);if(!e.isMultiLine()&&f=="("){var g=d.doc.getLine(e.start.row),h=g.substring(e.start.column+1,e.start.column+2);if(h==")")return e.end.column++,e}}),this.add("string_dquotes","insertion",function(a,b,c,d,e){if(e=='"'||e=="'"){var f=e,g=c.getSelectionRange(),h=d.doc.getTextRange(g);if(h!=="")return{text:f+h+f,selection:!1};var i=c.getCursorPosition(),j=d.doc.getLine(i.row),k=j.substring(i.column-1,i.column);if(k=="\\")return null;var l=d.getTokens(g.start.row,g.start.row)[0].tokens,m=0,n,o=-1;for(var p=0;p<l.length;p++){n=l[p],n.type=="string"?o=-1:o<0&&(o=n.value.indexOf(f));if(n.value.length+m>g.start.column)break;m+=l[p].value.length}if(!n||o<0&&n.type!=="comment"&&(n.type!=="string"||g.start.column!==n.value.length+m-1&&n.value.lastIndexOf(f)===n.value.length-1))return{text:f+f,selection:[1,1]};if(n&&n.type==="string"){var q=j.substring(i.column,i.column+1);if(q==f)return{text:"",selection:[1,1]}}}}),this.add("string_dquotes","deletion",function(a,b,c,d,e){var f=d.doc.getTextRange(e);if(!e.isMultiLine()&&(f=='"'||f=="'")){var g=d.doc.getLine(e.start.row),h=g.substring(e.start.column+1,e.start.column+2);if(h=='"')return e.end.column++,e}})};d.inherits(f,e),b.CstyleBehaviour=f}),define("ace/mode/folding/cstyle",["require","exports","module","ace/lib/oop","ace/range","ace/mode/folding/fold_mode"],function(a,b,c){"use strict";var d=a("../../lib/oop"),e=a("../../range").Range,f=a("./fold_mode").FoldMode,g=b.FoldMode=function(){};d.inherits(g,f),function(){this.foldingStartMarker=/(\{|\[)[^\}\]]*$|^\s*(\/\*)/,this.foldingStopMarker=/^[^\[\{]*(\}|\])|^[\s\*]*(\*\/)/,this.getFoldWidgetRange=function(a,b,c){var d=a.getLine(c),f=d.match(this.foldingStartMarker);if(f){var g=f.index;if(f[1])return this.openingBracketBlock(a,f[1],c,g);var h=a.getCommentFoldRange(c,g+f[0].length);return h.end.column-=2,h}if(b!=="markbeginend")return;var f=d.match(this.foldingStopMarker);if(f){var g=f.index+f[0].length;if(f[2]){var h=a.getCommentFoldRange(c,g);return h.end.column-=2,h}var i={row:c,column:g},j=a.$findOpeningBracket(f[1],i);if(!j)return;return j.column++,i.column--,e.fromPoints(j,i)}}}.call(g.prototype)}),define("ace/mode/folding/fold_mode",["require","exports","module","ace/range"],function(a,b,c){"use strict";var d=a("../../range").Range,e=b.FoldMode=function(){};(function(){this.foldingStartMarker=null,this.foldingStopMarker=null,this.getFoldWidget=function(a,b,c){var d=a.getLine(c);return this.foldingStartMarker.test(d)?"start":b=="markbeginend"&&this.foldingStopMarker&&this.foldingStopMarker.test(d)?"end":""},this.getFoldWidgetRange=function(a,b,c){return null},this.indentationBlock=function(a,b,c){var e=/^\s*/,f=b,g=b,h=a.getLine(b),i=c||h.length,j=h.match(e)[0].length,k=a.getLength();while(++b<k){h=a.getLine(b);var l=h.match(e)[0].length;if(l==h.length)continue;if(l<=j)break;g=b}if(g>f){var m=a.getLine(g).length;return new d(f,i,g,m)}},this.openingBracketBlock=function(a,b,c,e){var f={row:c,column:e+1},g=a.$findClosingBracket(b,f);if(!g)return;var h=a.foldWidgets[g.row];return h==null&&(h=this.getFoldWidget(a,g.row)),h=="start"&&(g.row--,g.column=a.getLine(g.row).length),d.fromPoints(f,g)}}).call(e.prototype)}),define("ace/mode/css",["require","exports","module","ace/lib/oop","ace/mode/text","ace/tokenizer","ace/mode/css_highlight_rules","ace/mode/matching_brace_outdent","ace/worker/worker_client","ace/mode/folding/cstyle"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("./text").Mode,f=a("../tokenizer").Tokenizer,g=a("./css_highlight_rules").CssHighlightRules,h=a("./matching_brace_outdent").MatchingBraceOutdent,i=a("../worker/worker_client").WorkerClient,j=a("./folding/cstyle").FoldMode,k=function(){this.$tokenizer=new f((new g).getRules(),"i"),this.$outdent=new h,this.foldingRules=new j};d.inherits(k,e),function(){this.foldingRules="cStyle",this.getNextLineIndent=function(a,b,c){var d=this.$getIndent(b),e=this.$tokenizer.getLineTokens(b,a).tokens;if(e.length&&e[e.length-1].type=="comment")return d;var f=b.match(/^.*\{\s*$/);return f&&(d+=c),d},this.checkOutdent=function(a,b,c){return this.$outdent.checkOutdent(b,c)},this.autoOutdent=function(a,b,c){this.$outdent.autoOutdent(b,c)},this.createWorker=function(a){var b=new i(["ace"],"worker-css.js","ace/mode/css_worker","Worker");return b.attachToDocument(a.getDocument()),b.on("csslint",function(b){var c=[];b.data.forEach(function(a){c.push({row:a.line-1,column:a.col-1,text:a.message,type:a.type,lint:a})}),a.setAnnotations(c)}),b}}.call(k.prototype),b.Mode=k}),define("ace/mode/css_highlight_rules",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/mode/text_highlight_rules"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("../lib/lang"),f=a("./text_highlight_rules").TextHighlightRules,g=function(){var a=e.arrayToMap("animation-fill-mode|alignment-adjust|alignment-baseline|animation-delay|animation-direction|animation-duration|animation-iteration-count|animation-name|animation-play-state|animation-timing-function|animation|appearance|azimuth|backface-visibility|background-attachment|background-break|background-clip|background-color|background-image|background-origin|background-position|background-repeat|background-size|background|baseline-shift|binding|bleed|bookmark-label|bookmark-level|bookmark-state|bookmark-target|border-bottom|border-bottom-color|border-bottom-left-radius|border-bottom-right-radius|border-bottom-style|border-bottom-width|border-collapse|border-color|border-image|border-image-outset|border-image-repeat|border-image-slice|border-image-source|border-image-width|border-left|border-left-color|border-left-style|border-left-width|border-radius|border-right|border-right-color|border-right-style|border-right-width|border-spacing|border-style|border-top|border-top-color|border-top-left-radius|border-top-right-radius|border-top-style|border-top-width|border-width|border|bottom|box-align|box-decoration-break|box-direction|box-flex-group|box-flex|box-lines|box-ordinal-group|box-orient|box-pack|box-shadow|box-sizing|break-after|break-before|break-inside|caption-side|clear|clip|color-profile|color|column-count|column-fill|column-gap|column-rule|column-rule-color|column-rule-style|column-rule-width|column-span|column-width|columns|content|counter-increment|counter-reset|crop|cue-after|cue-before|cue|cursor|direction|display|dominant-baseline|drop-initial-after-adjust|drop-initial-after-align|drop-initial-before-adjust|drop-initial-before-align|drop-initial-size|drop-initial-value|elevation|empty-cells|fit|fit-position|float-offset|float|font-family|font-size|font-size-adjust|font-stretch|font-style|font-variant|font-weight|font|grid-columns|grid-rows|hanging-punctuation|height|hyphenate-after|hyphenate-before|hyphenate-character|hyphenate-lines|hyphenate-resource|hyphens|icon|image-orientation|image-rendering|image-resolution|inline-box-align|left|letter-spacing|line-height|line-stacking-ruby|line-stacking-shift|line-stacking-strategy|line-stacking|list-style-image|list-style-position|list-style-type|list-style|margin-bottom|margin-left|margin-right|margin-top|margin|mark-after|mark-before|mark|marks|marquee-direction|marquee-play-count|marquee-speed|marquee-style|max-height|max-width|min-height|min-width|move-to|nav-down|nav-index|nav-left|nav-right|nav-up|opacity|orphans|outline-color|outline-offset|outline-style|outline-width|outline|overflow-style|overflow-x|overflow-y|overflow|padding-bottom|padding-left|padding-right|padding-top|padding|page-break-after|page-break-before|page-break-inside|page-policy|page|pause-after|pause-before|pause|perspective-origin|perspective|phonemes|pitch-range|pitch|play-during|position|presentation-level|punctuation-trim|quotes|rendering-intent|resize|rest-after|rest-before|rest|richness|right|rotation-point|rotation|ruby-align|ruby-overhang|ruby-position|ruby-span|size|speak-header|speak-numeral|speak-punctuation|speak|speech-rate|stress|string-set|table-layout|target-name|target-new|target-position|target|text-align-last|text-align|text-decoration|text-emphasis|text-height|text-indent|text-justify|text-outline|text-shadow|text-transform|text-wrap|top|transform-origin|transform-style|transform|transition-delay|transition-duration|transition-property|transition-timing-function|transition|unicode-bidi|vertical-align|visibility|voice-balance|voice-duration|voice-family|voice-pitch-range|voice-pitch|voice-rate|voice-stress|voice-volume|volume|white-space-collapse|white-space|widows|width|word-break|word-spacing|word-wrap|z-index".split("|")),b=e.arrayToMap("rgb|rgba|url|attr|counter|counters".split("|")),c=e.arrayToMap("absolute|after-edge|after|all-scroll|all|alphabetic|always|antialiased|armenian|auto|avoid-column|avoid-page|avoid|balance|baseline|before-edge|before|below|bidi-override|block-line-height|block|bold|bolder|border-box|both|bottom|box|break-all|break-word|capitalize|caps-height|caption|center|central|char|circle|cjk-ideographic|clone|close-quote|col-resize|collapse|column|consider-shifts|contain|content-box|cover|crosshair|cubic-bezier|dashed|decimal-leading-zero|decimal|default|disabled|disc|disregard-shifts|distribute-all-lines|distribute-letter|distribute-space|distribute|dotted|double|e-resize|ease-in|ease-in-out|ease-out|ease|ellipsis|end|exclude-ruby|fill|fixed|font-size|font|georgian|glyphs|grid-height|groove|hand|hanging|hebrew|help|hidden|hiragana-iroha|hiragana|horizontal|icon|ideograph-alpha|ideograph-numeric|ideograph-parenthesis|ideograph-space|ideographic|inactive|include-ruby|inherit|initial|inline-block|inline-box|inline-line-height|inline-table|inline|inset|inside|inter-ideograph|inter-word|invert|italic|justify|katakana-iroha|katakana|keep-all|last|left|lighter|line-edge|line-through|line|linear|list-item|local|loose|lower-alpha|lower-greek|lower-latin|lower-roman|lowercase|lr-tb|ltr|mathematical|max-height|max-size|medium|menu|message-box|middle|move|n-resize|ne-resize|newspaper|no-change|no-close-quote|no-drop|no-open-quote|no-repeat|none|normal|not-allowed|nowrap|nw-resize|oblique|open-quote|outset|outside|overline|padding-box|page|pointer|pre-line|pre-wrap|pre|preserve-3d|progress|relative|repeat-x|repeat-y|repeat|replaced|reset-size|ridge|right|round|row-resize|rtl|s-resize|scroll|se-resize|separate|slice|small-caps|small-caption|solid|space|square|start|static|status-bar|step-end|step-start|steps|stretch|strict|sub|super|sw-resize|table-caption|table-cell|table-column-group|table-column|table-footer-group|table-header-group|table-row-group|table-row|table|tb-rl|text-after-edge|text-before-edge|text-bottom|text-size|text-top|text|thick|thin|top|transparent|underline|upper-alpha|upper-latin|upper-roman|uppercase|use-script|vertical-ideographic|vertical-text|visible|w-resize|wait|whitespace|z-index|zero".split("|")),d=e.arrayToMap("aqua|black|blue|fuchsia|gray|green|lime|maroon|navy|olive|orange|purple|red|silver|teal|white|yellow".split("|")),f=e.arrayToMap("arial|century|comic|courier|garamond|georgia|helvetica|impact|lucida|symbol|system|tahoma|times|trebuchet|utopia|verdana|webdings|sans-serif|serif|monospace".split("|")),g="\\-?(?:(?:[0-9]+)|(?:[0-9]*\\.[0-9]+))",h="(\\:+)\\b(after|before|first-letter|first-line|moz-selection|selection)\\b",i="(:)\\b(active|checked|disabled|empty|enabled|first-child|first-of-type|focus|hover|indeterminate|invalid|last-child|last-of-type|link|not|nth-child|nth-last-child|nth-last-of-type|nth-of-type|only-child|only-of-type|required|root|target|valid|visited)\\b",j=[{token:"comment",merge:!0,regex:"\\/\\*",next:"ruleset_comment"},{token:"string",regex:'["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'},{token:"string",regex:"['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"},{token:["constant.numeric","keyword"],regex:"("+g+")(ch|cm|deg|em|ex|fr|gd|grad|Hz|in|kHz|mm|ms|pc|pt|px|rad|rem|s|turn|vh|vm|vw|%)"},{token:["constant.numeric"],regex:"([0-9]+)"},{token:"constant.numeric",regex:"#[a-f0-9]{6}"},{token:"constant.numeric",regex:"#[a-f0-9]{3}"},{token:["punctuation","entity.other.attribute-name.pseudo-element.css"],regex:h},{token:["punctuation","entity.other.attribute-name.pseudo-class.css"],regex:i},{token:function(e){return a.hasOwnProperty(e.toLowerCase())?"support.type":b.hasOwnProperty(e.toLowerCase())?"support.function":c.hasOwnProperty(e.toLowerCase())?"support.constant":d.hasOwnProperty(e.toLowerCase())?"support.constant.color":f.hasOwnProperty(e.toLowerCase())?"support.constant.fonts":"text"},regex:"\\-?[a-zA-Z_][a-zA-Z0-9_\\-]*"}],k=e.copyArray(j);k.unshift({token:"paren.rparen",regex:"\\}",next:"start"});var l=e.copyArray(j);l.unshift({token:"paren.rparen",regex:"\\}",next:"media"});var m=[{token:"comment",merge:!0,regex:".+"}],n=e.copyArray(m);n.unshift({token:"comment",regex:".*?\\*\\/",next:"start"});var o=e.copyArray(m);o.unshift({token:"comment",regex:".*?\\*\\/",next:"media"});var p=e.copyArray(m);p.unshift({token:"comment",regex:".*?\\*\\/",next:"ruleset"}),this.$rules={start:[{token:"comment",merge:!0,regex:"\\/\\*",next:"comment"},{token:"paren.lparen",regex:"\\{",next:"ruleset"},{token:"string",regex:"@.*?{",next:"media"},{token:"keyword",regex:"#[a-z0-9-_]+"},{token:"variable",regex:"\\.[a-z0-9-_]+"},{token:"string",regex:":[a-z0-9-_]+"},{token:"constant",regex:"[a-z0-9-_]+"}],media:[{token:"comment",merge:!0,regex:"\\/\\*",next:"media_comment"},{token:"paren.lparen",regex:"\\{",next:"media_ruleset"},{token:"string",regex:"\\}",next:"start"},{token:"keyword",regex:"#[a-z0-9-_]+"},{token:"variable",regex:"\\.[a-z0-9-_]+"},{token:"string",regex:":[a-z0-9-_]+"},{token:"constant",regex:"[a-z0-9-_]+"}],comment:n,ruleset:k,ruleset_comment:p,media_ruleset:l,media_comment:o}};d.inherits(g,f),b.CssHighlightRules=g}),define("ace/mode/html_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/css_highlight_rules","ace/mode/javascript_highlight_rules","ace/mode/xml_util","ace/mode/text_highlight_rules"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("./css_highlight_rules").CssHighlightRules,f=a("./javascript_highlight_rules").JavaScriptHighlightRules,g=a("./xml_util"),h=a("./text_highlight_rules").TextHighlightRules,i=function(){this.$rules={start:[{token:"text",merge:!0,regex:"<\\!\\[CDATA\\[",next:"cdata"},{token:"xml_pe",regex:"<\\?.*?\\?>"},{token:"comment",merge:!0,regex:"<\\!--",next:"comment"},{token:"xml_pe",regex:"<\\!.*?>"},{token:"meta.tag",regex:"<(?=s*script\\b)",next:"script"},{token:"meta.tag",regex:"<(?=s*style\\b)",next:"style"},{token:"meta.tag",regex:"<\\/?",next:"tag"},{token:"text",regex:"\\s+"},{token:"constant.character.entity",regex:"(?:&#[0-9]+;)|(?:&#x[0-9a-fA-F]+;)|(?:&[a-zA-Z0-9_:\\.-]+;)"},{token:"text",regex:"[^<]+"}],cdata:[{token:"text",regex:"\\]\\]>",next:"start"},{token:"text",merge:!0,regex:"\\s+"},{token:"text",merge:!0,regex:".+"}],comment:[{token:"comment",regex:".*?-->",next:"start"},{token:"comment",merge:!0,regex:".+"}]},g.tag(this.$rules,"tag","start"),g.tag(this.$rules,"style","css-start"),g.tag(this.$rules,"script","js-start"),this.embedRules(f,"js-",[{token:"comment",regex:"\\/\\/.*(?=<\\/script>)",next:"tag"},{token:"meta.tag",regex:"<\\/(?=script)",next:"tag"}]),this.embedRules(e,"css-",[{token:"meta.tag",regex:"<\\/(?=style)",next:"tag"}])};d.inherits(i,h),b.HtmlHighlightRules=i}),define("ace/mode/xml_util",["require","exports","module","ace/lib/lang"],function(a,b,c){function g(a){return[{token:"string",regex:'".*?"'},{token:"string",merge:!0,regex:'["].*',next:a+"_qqstring"},{token:"string",regex:"'.*?'"},{token:"string",merge:!0,regex:"['].*",next:a+"_qstring"}]}function h(a,b){return[{token:"string",merge:!0,regex:".*?"+a,next:b},{token:"string",merge:!0,regex:".+"}]}"use strict";var d=a("../lib/lang"),e=d.arrayToMap("button|form|input|label|select|textarea".split("|")),f=d.arrayToMap("table|tbody|td|tfoot|th|tr".split("|"));b.tag=function(a,b,c){a[b]=[{token:"text",regex:"\\s+"},{token:function(a){return a==="a"?"meta.tag.anchor":a==="img"?"meta.tag.image":a==="script"?"meta.tag.script":a==="style"?"meta.tag.style":e.hasOwnProperty(a.toLowerCase())?"meta.tag.form":f.hasOwnProperty(a.toLowerCase())?"meta.tag.table":"meta.tag"},merge:!0,regex:"[-_a-zA-Z0-9:]+",next:b+"_embed_attribute_list"},{token:"empty",regex:"",next:b+"_embed_attribute_list"}],a[b+"_qstring"]=h("'",b+"_embed_attribute_list"),a[b+"_qqstring"]=h('"',b+"_embed_attribute_list"),a[b+"_embed_attribute_list"]=[{token:"meta.tag",merge:!0,regex:"/?>",next:c},{token:"keyword.operator",regex:"="},{token:"entity.other.attribute-name",regex:"[-_a-zA-Z0-9:]+"},{token:"constant.numeric",regex:"[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"},{token:"text",regex:"\\s+"}].concat(g(b))}}),define("ace/mode/behaviour/xml",["require","exports","module","ace/lib/oop","ace/mode/behaviour","ace/mode/behaviour/cstyle"],function(a,b,c){"use strict";var d=a("../../lib/oop"),e=a("../behaviour").Behaviour,f=a("./cstyle").CstyleBehaviour,g=function(){this.inherit(f,["string_dquotes"]),this.add("brackets","insertion",function(a,b,c,d,e){if(e=="<"){var f=c.getSelectionRange(),g=d.doc.getTextRange(f);return g!==""?!1:{text:"<>",selection:[1,1]}}if(e==">"){var h=c.getCursorPosition(),i=d.doc.getLine(h.row),j=i.substring(h.column,h.column+1);if(j==">")return{text:"",selection:[1,1]}}else if(e=="\n"){var h=c.getCursorPosition(),i=d.doc.getLine(h.row),k=i.substring(h.column,h.column+2);if(k=="</"){var l=this.$getIndent(d.doc.getLine(h.row))+d.getTabString(),m=this.$getIndent(d.doc.getLine(h.row));return{text:"\n"+l+"\n"+m,selection:[1,l.length,1,l.length]}}}})};d.inherits(g,e),b.XmlBehaviour=g}),define("ace/mode/folding/html",["require","exports","module","ace/lib/oop","ace/mode/folding/mixed","ace/mode/folding/xml","ace/mode/folding/cstyle"],function(a,b,c){"use strict";var d=a("../../lib/oop"),e=a("./mixed").FoldMode,f=a("./xml").FoldMode,g=a("./cstyle").FoldMode,h=b.FoldMode=function(){e.call(this,new f({area:1,base:1,br:1,col:1,command:1,embed:1,hr:1,img:1,input:1,keygen:1,link:1,meta:1,param:1,source:1,track:1,wbr:1,li:1,dt:1,dd:1,p:1,rt:1,rp:1,optgroup:1,option:1,colgroup:1,td:1,th:1}),{"js-":new g,"css-":new g})};d.inherits(h,e)}),define("ace/mode/folding/mixed",["require","exports","module","ace/lib/oop","ace/mode/folding/fold_mode"],function(a,b,c){"use strict";var d=a("../../lib/oop"),e=a("./fold_mode").FoldMode,f=b.FoldMode=function(a,b){this.defaultMode=a,this.subModes=b};d.inherits(f,e),function(){this.$getMode=function(a){for(var b in this.subModes)if(a.indexOf(b)===0)return this.subModes[b];return null},this.$tryMode=function(a,b,c,d){var e=this.$getMode(a);return e?e.getFoldWidget(b,c,d):""},this.getFoldWidget=function(a,b,c){return this.$tryMode(a.getState(c-1),a,b,c)||this.$tryMode(a.getState(c),a,b,c)||this.defaultMode.getFoldWidget(a,b,c)},this.getFoldWidgetRange=function(a,b,c){var d=this.$getMode(a.getState(c-1));if(!d||!d.getFoldWidget(a,b,c))d=this.$getMode(a.getState(c));if(!d||!d.getFoldWidget(a,b,c))d=this.defaultMode;return d.getFoldWidgetRange(a,b,c)}}.call(f.prototype)}),define("ace/mode/folding/xml",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/range","ace/mode/folding/fold_mode","ace/token_iterator"],function(a,b,c){"use strict";var d=a("../../lib/oop"),e=a("../../lib/lang"),f=a("../../range").Range,g=a("./fold_mode").FoldMode,h=a("../../token_iterator").TokenIterator,i=b.FoldMode=function(a){g.call(this),this.voidElements=a||{}};d.inherits(i,g),function(){this.getFoldWidget=function(a,b,c){var d=this._getFirstTagInLine(a,c);return d.closing?b=="markbeginend"?"end":"":!d.tagName||this.voidElements[d.tagName.toLowerCase()]?"":d.selfClosing?"":d.value.indexOf("/"+d.tagName)!==-1?"":"start"},this._getFirstTagInLine=function(a,b){var c=a.getTokens(b,b)[0].tokens,d="";for(var f=0;f<c.length;f++){var g=c[f];g.type.indexOf("meta.tag")===0?d+=g.value:d+=e.stringRepeat(" ",g.value.length)}return this._parseTag(d)},this.tagRe=/^(\s*)(<?(\/?)([-_a-zA-Z0-9:!]*)\s*(\/?)>?)/,this._parseTag=function(a){var b=this.tagRe.exec(a),c=this.tagRe.lastIndex||0;return this.tagRe.lastIndex=0,{value:a,match:b?b[2]:"",closing:b?!!b[3]:!1,selfClosing:b?!!b[5]||b[2]=="/>":!1,tagName:b?b[4]:"",column:b[1]?c+b[1].length:c}},this._readTagForward=function(a){var b=a.getCurrentToken();if(!b)return null;var c="",d;do if(b.type.indexOf("meta.tag")===0){if(!d)var d={row:a.getCurrentTokenRow(),column:a.getCurrentTokenColumn()};c+=b.value;if(c.indexOf(">")!==-1){var e=this._parseTag(c);return e.start=d,e.end={row:a.getCurrentTokenRow(),column:a.getCurrentTokenColumn()+b.value.length},a.stepForward(),e}}while(b=a.stepForward());return null},this._readTagBackward=function(a){var b=a.getCurrentToken();if(!b)return null;var c="",d;do if(b.type.indexOf("meta.tag")===0){d||(d={row:a.getCurrentTokenRow(),column:a.getCurrentTokenColumn()+b.value.length}),c=b.value+c;if(c.indexOf("<")!==-1){var e=this._parseTag(c);return e.end=d,e.start={row:a.getCurrentTokenRow(),column:a.getCurrentTokenColumn()},a.stepBackward(),e}}while(b=a.stepBackward());return null},this._pop=function(a,b){while(a.length){var c=a[a.length-1];if(!b||c.tagName==b.tagName)return a.pop();if(this.voidElements[b.tagName])return;if(this.voidElements[c.tagName]){a.pop();continue}return null}},this.getFoldWidgetRange=function(a,b,c){var d=this._getFirstTagInLine(a,c);if(!d.match)return null;var e=d.closing||d.selfClosing,g=[],i;if(!e){var j=new h(a,c,d.column),k={row:c,column:d.column+d.tagName.length+2};while(i=this._readTagForward(j)){if(i.selfClosing){if(!g.length)return i.start.column+=i.tagName.length+2,i.end.column-=2,f.fromPoints(i.start,i.end);continue}if(i.closing){this._pop(g,i);if(g.length==0)return f.fromPoints(k,i.start)}else g.push(i)}}else{var j=new h(a,c,d.column+d.match.length),l={row:c,column:d.column};while(i=this._readTagBackward(j)){if(i.selfClosing){if(!g.length)return i.start.column+=i.tagName.length+2,i.end.column-=2,f.fromPoints(i.start,i.end);continue}if(!i.closing){this._pop(g,i);if(g.length==0)return i.start.column+=i.tagName.length+2,f.fromPoints(i.start,l)}else g.push(i)}}}}.call(i.prototype)})
\ No newline at end of file
diff --git a/apps/files_texteditor/js/aceeditor/mode-java-uncompressed.js b/apps/files_texteditor/js/aceeditor/mode-java-uncompressed.js
old mode 100755
new mode 100644
index 7263df5894c44a6d89ad8fa5f5e613ba8243d064..f241de365d7915f9bf9f839c23c8163ba732d728
--- a/apps/files_texteditor/js/aceeditor/mode-java-uncompressed.js
+++ b/apps/files_texteditor/js/aceeditor/mode-java-uncompressed.js
@@ -282,12 +282,20 @@ var JavaScriptHighlightRules = function() {
     );
 
     // TODO: Unicode escape sequences
-    var identifierRe = "[" + unicode.packages.L + "\\$_][" 
+    var identifierRe = "[" + unicode.packages.L + "\\$_]["
         + unicode.packages.L
         + unicode.packages.Mn + unicode.packages.Mc
         + unicode.packages.Nd
         + unicode.packages.Pc + "\\$_]*\\b";
-        
+
+    var escapedRe = "\\\\(?:x[0-9a-fA-F]{2}|" + // hex
+        "u[0-9a-fA-F]{4}|" + // unicode
+        "[0-2][0-7]{0,2}|" + // oct
+        "3[0-6][0-7]?|" + // oct
+        "37[0-7]?|" + // oct
+        "[4-7][0-7]?|" + //oct
+        ".)";
+
     // regexp must not have capturing parentheses. Use (?:) instead.
     // regexps are ordered -> the first match is used
 
@@ -295,46 +303,139 @@ var JavaScriptHighlightRules = function() {
         "start" : [
             {
                 token : "comment",
-                regex : "\\/\\/.*$"
+                regex : /\/\/.*$/
             },
             new DocCommentHighlightRules().getStartRule("doc-start"),
             {
                 token : "comment", // multi line comment
                 merge : true,
-                regex : "\\/\\*",
+                regex : /\/\*/,
                 next : "comment"
             }, {
-                token : "string", // single line
-                regex : '["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'
-            }, {
-                token : "string", // multi line string start
-                merge : true,
-                regex : '["].*\\\\$',
-                next : "qqstring"
-            }, {
-                token : "string", // single line
-                regex : "['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"
+                token : "string",
+                regex : "'",
+                next  : "qstring"
             }, {
-                token : "string", // multi line string start
-                merge : true,
-                regex : "['].*\\\\$",
-                next : "qstring"
+                token : "string",
+                regex : '"',
+                next  : "qqstring"
             }, {
                 token : "constant.numeric", // hex
-                regex : "0[xX][0-9a-fA-F]+\\b"
+                regex : /0[xX][0-9a-fA-F]+\b/
             }, {
                 token : "constant.numeric", // float
-                regex : "[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"
-            }, {
-                token : ["keyword.definition", "text", "entity.name.function"],
-                regex : "(function)(\\s+)(" + identifierRe + ")"
+                regex : /[+-]?\d+(?:(?:\.\d*)?(?:[eE][+-]?\d+)?)?\b/
+            }, { // match stuff like: Sound.prototype.play = function() { }
+                token : [
+                    "storage.type",
+                    "punctuation.operator",
+                    "support.function",
+                    "punctuation.operator",
+                    "entity.name.function",
+                    "text",
+                    "keyword.operator",
+                    "text",
+                    "storage.type",
+                    "text",
+                    "paren.lparen",
+                    "variable.parameter",
+                    "paren.rparen"
+                ],
+                regex : "(" + identifierRe + ")(\\.)(prototype)(\\.)(" + identifierRe +")(\\s*)(=)(\\s*)(function)(\\s*)(\\()(.*?)(\\))"
+            }, { // match stuff like: Sound.prototype.play = myfunc
+                token : [
+                    "storage.type",
+                    "punctuation.operator",
+                    "support.function",
+                    "punctuation.operator",
+                    "entity.name.function",
+                    "text",
+                    "keyword.operator",
+                    "text"
+                ],
+                regex : "(" + identifierRe + ")(\\.)(prototype)(\\.)(" + identifierRe +")(\\s*)(=)(\\s*)"
+            }, { // match stuff like: Sound.play = function() {  }
+                token : [
+                    "storage.type",
+                    "punctuation.operator",
+                    "entity.name.function",
+                    "text",
+                    "keyword.operator",
+                    "text",
+                    "storage.type",
+                    "text",
+                    "paren.lparen",
+                    "variable.parameter",
+                    "paren.rparen"
+                ],
+                regex : "(" + identifierRe + ")(\\.)(" + identifierRe +")(\\s*)(=)(\\s*)(function)(\\s*)(\\()(.*?)(\\))"
+            }, { // match stuff like: play = function() {  }
+                token : [
+                    "entity.name.function",
+                    "text",
+                    "keyword.operator",
+                    "text",
+                    "storage.type",
+                    "text",
+                    "paren.lparen",
+                    "variable.parameter",
+                    "paren.rparen"
+                ],
+                regex : "(" + identifierRe +")(\\s*)(=)(\\s*)(function)(\\s*)(\\()(.*?)(\\))"
+            }, { // match regular function like: function myFunc(arg) { }
+                token : [
+                    "storage.type",
+                    "text",
+                    "entity.name.function",
+                    "text",
+                    "paren.lparen",
+                    "variable.parameter",
+                    "paren.rparen"
+                ],
+                regex : "(function)(\\s+)(" + identifierRe + ")(\\s*)(\\()(.*?)(\\))"
+            }, { // match stuff like: foobar: function() { }
+                token : [
+                    "entity.name.function",
+                    "text",
+                    "punctuation.operator",
+                    "text",
+                    "storage.type",
+                    "text",
+                    "paren.lparen",
+                    "variable.parameter",
+                    "paren.rparen"
+                ],
+                regex : "(" + identifierRe + ")(\\s*)(:)(\\s*)(function)(\\s*)(\\()(.*?)(\\))"
+            }, { // Attempt to match : function() { } (this is for issues with 'foo': function() { })
+                token : [
+                    "text",
+                    "text",
+                    "storage.type",
+                    "text",
+                    "paren.lparen",
+                    "variable.parameter",
+                    "paren.rparen"
+                ],
+                regex : "(:)(\\s*)(function)?(\\s*)(\\()([^)]*)(\\))"
             }, {
                 token : "constant.language.boolean",
-                regex : "(?:true|false)\\b"
+                regex : /(?:true|false)\b/
             }, {
                 token : "keyword",
                 regex : "(?:" + kwBeforeRe + ")\\b",
                 next : "regex_allowed"
+            }, {
+                token : ["punctuation.operator", "support.function"],
+                regex : /(\.)(s(?:h(?:ift|ow(?:Mod(?:elessDialog|alDialog)|Help))|croll(?:X|By(?:Pages|Lines)?|Y|To)?|t(?:opzzzz|rike)|i(?:n|zeToContent|debar|gnText)|ort|u(?:p|b(?:str(?:ing)?)?)|pli(?:ce|t)|e(?:nd|t(?:Re(?:sizable|questHeader)|M(?:i(?:nutes|lliseconds)|onth)|Seconds|Ho(?:tKeys|urs)|Year|Cursor|Time(?:out)?|Interval|ZOptions|Date|UTC(?:M(?:i(?:nutes|lliseconds)|onth)|Seconds|Hours|Date|FullYear)|FullYear|Active)|arch)|qrt|lice|avePreferences|mall)|h(?:ome|andleEvent)|navigate|c(?:har(?:CodeAt|At)|o(?:s|n(?:cat|textual|firm)|mpile)|eil|lear(?:Timeout|Interval)?|a(?:ptureEvents|ll)|reate(?:StyleSheet|Popup|EventObject))|t(?:o(?:GMTString|S(?:tring|ource)|U(?:TCString|pperCase)|Lo(?:caleString|werCase))|est|a(?:n|int(?:Enabled)?))|i(?:s(?:NaN|Finite)|ndexOf|talics)|d(?:isableExternalCapture|ump|etachEvent)|u(?:n(?:shift|taint|escape|watch)|pdateCommands)|j(?:oin|avaEnabled)|p(?:o(?:p|w)|ush|lugins.refresh|a(?:ddings|rse(?:Int|Float)?)|r(?:int|ompt|eference))|e(?:scape|nableExternalCapture|val|lementFromPoint|x(?:p|ec(?:Script|Command)?))|valueOf|UTC|queryCommand(?:State|Indeterm|Enabled|Value)|f(?:i(?:nd|le(?:ModifiedDate|Size|CreatedDate|UpdatedDate)|xed)|o(?:nt(?:size|color)|rward)|loor|romCharCode)|watch|l(?:ink|o(?:ad|g)|astIndexOf)|a(?:sin|nchor|cos|t(?:tachEvent|ob|an(?:2)?)|pply|lert|b(?:s|ort))|r(?:ou(?:nd|teEvents)|e(?:size(?:By|To)|calc|turnValue|place|verse|l(?:oad|ease(?:Capture|Events)))|andom)|g(?:o|et(?:ResponseHeader|M(?:i(?:nutes|lliseconds)|onth)|Se(?:conds|lection)|Hours|Year|Time(?:zoneOffset)?|Da(?:y|te)|UTC(?:M(?:i(?:nutes|lliseconds)|onth)|Seconds|Hours|Da(?:y|te)|FullYear)|FullYear|A(?:ttention|llResponseHeaders)))|m(?:in|ove(?:B(?:y|elow)|To(?:Absolute)?|Above)|ergeAttributes|a(?:tch|rgins|x))|b(?:toa|ig|o(?:ld|rderWidths)|link|ack))\b(?=\()/
+            }, {
+                token : ["punctuation.operator", "support.function.dom"],
+                regex : /(\.)(s(?:ub(?:stringData|mit)|plitText|e(?:t(?:NamedItem|Attribute(?:Node)?)|lect))|has(?:ChildNodes|Feature)|namedItem|c(?:l(?:ick|o(?:se|neNode))|reate(?:C(?:omment|DATASection|aption)|T(?:Head|extNode|Foot)|DocumentFragment|ProcessingInstruction|E(?:ntityReference|lement)|Attribute))|tabIndex|i(?:nsert(?:Row|Before|Cell|Data)|tem)|open|delete(?:Row|C(?:ell|aption)|T(?:Head|Foot)|Data)|focus|write(?:ln)?|a(?:dd|ppend(?:Child|Data))|re(?:set|place(?:Child|Data)|move(?:NamedItem|Child|Attribute(?:Node)?)?)|get(?:NamedItem|Element(?:sBy(?:Name|TagName)|ById)|Attribute(?:Node)?)|blur)\b(?=\()/
+            }, {
+                token : ["punctuation.operator", "support.constant"],
+                regex : /(\.)(s(?:ystemLanguage|cr(?:ipts|ollbars|een(?:X|Y|Top|Left))|t(?:yle(?:Sheets)?|atus(?:Text|bar)?)|ibling(?:Below|Above)|ource|uffixes|e(?:curity(?:Policy)?|l(?:ection|f)))|h(?:istory|ost(?:name)?|as(?:h|Focus))|y|X(?:MLDocument|SLDocument)|n(?:ext|ame(?:space(?:s|URI)|Prop))|M(?:IN_VALUE|AX_VALUE)|c(?:haracterSet|o(?:n(?:structor|trollers)|okieEnabled|lorDepth|mp(?:onents|lete))|urrent|puClass|l(?:i(?:p(?:boardData)?|entInformation)|osed|asses)|alle(?:e|r)|rypto)|t(?:o(?:olbar|p)|ext(?:Transform|Indent|Decoration|Align)|ags)|SQRT(?:1_2|2)|i(?:n(?:ner(?:Height|Width)|put)|ds|gnoreCase)|zIndex|o(?:scpu|n(?:readystatechange|Line)|uter(?:Height|Width)|p(?:sProfile|ener)|ffscreenBuffering)|NEGATIVE_INFINITY|d(?:i(?:splay|alog(?:Height|Top|Width|Left|Arguments)|rectories)|e(?:scription|fault(?:Status|Ch(?:ecked|arset)|View)))|u(?:ser(?:Profile|Language|Agent)|n(?:iqueID|defined)|pdateInterval)|_content|p(?:ixelDepth|ort|ersonalbar|kcs11|l(?:ugins|atform)|a(?:thname|dding(?:Right|Bottom|Top|Left)|rent(?:Window|Layer)?|ge(?:X(?:Offset)?|Y(?:Offset)?))|r(?:o(?:to(?:col|type)|duct(?:Sub)?|mpter)|e(?:vious|fix)))|e(?:n(?:coding|abledPlugin)|x(?:ternal|pando)|mbeds)|v(?:isibility|endor(?:Sub)?|Linkcolor)|URLUnencoded|P(?:I|OSITIVE_INFINITY)|f(?:ilename|o(?:nt(?:Size|Family|Weight)|rmName)|rame(?:s|Element)|gColor)|E|whiteSpace|l(?:i(?:stStyleType|n(?:eHeight|kColor))|o(?:ca(?:tion(?:bar)?|lName)|wsrc)|e(?:ngth|ft(?:Context)?)|a(?:st(?:M(?:odified|atch)|Index|Paren)|yer(?:s|X)|nguage))|a(?:pp(?:MinorVersion|Name|Co(?:deName|re)|Version)|vail(?:Height|Top|Width|Left)|ll|r(?:ity|guments)|Linkcolor|bove)|r(?:ight(?:Context)?|e(?:sponse(?:XML|Text)|adyState))|global|x|m(?:imeTypes|ultiline|enubar|argin(?:Right|Bottom|Top|Left))|L(?:N(?:10|2)|OG(?:10E|2E))|b(?:o(?:ttom|rder(?:Width|RightWidth|BottomWidth|Style|Color|TopWidth|LeftWidth))|ufferDepth|elow|ackground(?:Color|Image)))\b/
+            }, {
+                token : ["storage.type", "punctuation.operator", "support.function.firebug"],
+                regex : /(console)(\.)(warn|info|log|error|time|timeEnd|assert)\b/
             }, {
                 token : function(value) {
                     if (globals.hasOwnProperty(value))
@@ -342,7 +443,7 @@ var JavaScriptHighlightRules = function() {
                     else if (deprecated.hasOwnProperty(value))
                         return "invalid.deprecated";
                     else if (definitions.hasOwnProperty(value))
-                        return "keyword.definition";
+                        return "storage.type";
                     else if (keywords.hasOwnProperty(value))
                         return "keyword";
                     else if (buildinConstants.hasOwnProperty(value))
@@ -357,29 +458,29 @@ var JavaScriptHighlightRules = function() {
                 regex : identifierRe
             }, {
                 token : "keyword.operator",
-                regex : "!|\\$|%|&|\\*|\\-\\-|\\-|\\+\\+|\\+|~|===|==|=|!=|!==|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\\|\\||\\?\\:|\\*=|%=|\\+=|\\-=|&=|\\^=|\\b(?:in|instanceof|new|delete|typeof|void)",
+                regex : /!|\$|%|&|\*|\-\-|\-|\+\+|\+|~|===|==|=|!=|!==|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\|\||\?\:|\*=|%=|\+=|\-=|&=|\^=|\b(?:in|instanceof|new|delete|typeof|void)/,
                 next  : "regex_allowed"
             }, {
                 token : "punctuation.operator",
-                regex : "\\?|\\:|\\,|\\;|\\.",
+                regex : /\?|\:|\,|\;|\./,
                 next  : "regex_allowed"
             }, {
                 token : "paren.lparen",
-                regex : "[[({]",
+                regex : /[\[({]/,
                 next  : "regex_allowed"
             }, {
                 token : "paren.rparen",
-                regex : "[\\])}]"
+                regex : /[\])}]/
             }, {
                 token : "keyword.operator",
-                regex : "\\/=?",
+                regex : /\/=?/,
                 next  : "regex_allowed"
             }, {
                 token: "comment",
-                regex: "^#!.*$" 
+                regex: /^#!.*$/
             }, {
                 token : "text",
-                regex : "\\s+"
+                regex : /\s+/
             }
         ],
         // regular expressions are only allowed after certain tokens. This
@@ -404,7 +505,7 @@ var JavaScriptHighlightRules = function() {
             }, {
                 // immediately return to the start mode without matching
                 // anything
-                token: "empty", 
+                token: "empty",
                 regex: "",
                 next: "start"
             }
@@ -416,10 +517,10 @@ var JavaScriptHighlightRules = function() {
                 next: "regex"
             }, {
 				// flag
-                token: "string.regexp", 
+                token: "string.regexp",
                 regex: "/\\w*",
                 next: "start",
-                merge: true 
+                merge: true
             }, {
                 token: "string.regexp",
                 regex: "[^\\\\/\\[]+",
@@ -431,9 +532,9 @@ var JavaScriptHighlightRules = function() {
                 next: "regex_character_class",
                 merge: true
             }, {
-                token: "empty", 
+                token: "empty",
                 regex: "",
-                next: "start" 
+                next: "start"
             }
         ],
         "regex_character_class": [
@@ -452,9 +553,9 @@ var JavaScriptHighlightRules = function() {
                 next: "regex_character_class",
                 merge: true
             }, {
-                token: "empty", 
+                token: "empty",
                 regex: "",
-                next: "start" 
+                next: "start"
             }
         ],
         "comment_regex_allowed" : [
@@ -483,28 +584,32 @@ var JavaScriptHighlightRules = function() {
         ],
         "qqstring" : [
             {
+                token : "constant.language.escape",
+                regex : escapedRe
+            }, {
                 token : "string",
-                regex : '(?:(?:\\\\.)|(?:[^"\\\\]))*?"',
-                next : "start"
+                regex : '[^"\\\\]+'
             }, {
                 token : "string",
-                merge : true,
-                regex : '.+'
+                regex : '"',
+                next  : "start"
             }
         ],
         "qstring" : [
             {
+                token : "constant.language.escape",
+                regex : escapedRe
+            }, {
                 token : "string",
-                regex : "(?:(?:\\\\.)|(?:[^'\\\\]))*?'",
-                next : "start"
+                regex : "[^'\\\\]+"
             }, {
                 token : "string",
-                merge : true,
-                regex : '.+'
+                regex : "'",
+                next  : "start"
             }
         ]
     };
-    
+
     this.embedRules(DocCommentHighlightRules, "doc-",
         [ new DocCommentHighlightRules().getEndRule("start") ]);
 };
@@ -689,195 +794,6 @@ var MatchingBraceOutdent = function() {};
 }).call(MatchingBraceOutdent.prototype);
 
 exports.MatchingBraceOutdent = MatchingBraceOutdent;
-});
-/* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is Ajax.org Code Editor (ACE).
- *
- * The Initial Developer of the Original Code is
- * Ajax.org B.V.
- * Portions created by the Initial Developer are Copyright (C) 2010
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *      Fabian Jakobs <fabian AT ajax DOT org>
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-define('ace/worker/worker_client', ['require', 'exports', 'module' , 'ace/lib/oop', 'ace/lib/event_emitter'], function(require, exports, module) {
-"use strict";
-
-var oop = require("../lib/oop");
-var EventEmitter = require("../lib/event_emitter").EventEmitter;
-
-var WorkerClient = function(topLevelNamespaces, packagedJs, mod, classname) {
-
-    this.changeListener = this.changeListener.bind(this);
-
-    if (module.packaged) {
-        var base = this.$guessBasePath();
-        this.$worker = new Worker(base + packagedJs);
-    }
-    else {
-        var workerUrl = this.$normalizePath(require.nameToUrl("ace/worker/worker", null, "_"));
-        this.$worker = new Worker(workerUrl);
-
-        var tlns = {};
-        for (var i=0; i<topLevelNamespaces.length; i++) {
-            var ns = topLevelNamespaces[i];
-            var path = this.$normalizePath(require.nameToUrl(ns, null, "_").replace(/.js$/, ""));
-
-            tlns[ns] = path;
-        }
-    }
-
-    this.$worker.postMessage({
-        init : true,
-        tlns: tlns,
-        module: mod,
-        classname: classname
-    });
-
-    this.callbackId = 1;
-    this.callbacks = {};
-
-    var _self = this;
-    this.$worker.onerror = function(e) {
-        window.console && console.log && console.log(e);
-        throw e;
-    };
-    this.$worker.onmessage = function(e) {
-        var msg = e.data;
-        switch(msg.type) {
-            case "log":
-                window.console && console.log && console.log(msg.data);
-                break;
-
-            case "event":
-                _self._emit(msg.name, {data: msg.data});
-                break;
-
-            case "call":
-                var callback = _self.callbacks[msg.id];
-                if (callback) {
-                    callback(msg.data);
-                    delete _self.callbacks[msg.id];
-                }
-                break;
-        }
-    };
-};
-
-(function(){
-
-    oop.implement(this, EventEmitter);
-
-    this.$normalizePath = function(path) {
-        path = path.replace(/^[a-z]+:\/\/[^\/]+\//, ""); // Remove domain name and rebuild it
-        path = location.protocol + "//" + location.host
-            // paths starting with a slash are relative to the root (host)
-            + (path.charAt(0) == "/" ? "" : location.pathname.replace(/\/[^\/]*$/, ""))
-            + "/" + path.replace(/^[\/]+/, "");
-        return path;
-    };
-
-    this.$guessBasePath = function() {
-        if (require.aceBaseUrl)
-            return require.aceBaseUrl;
-
-        var scripts = document.getElementsByTagName("script");
-        for (var i=0; i<scripts.length; i++) {
-            var script = scripts[i];
-
-            var base = script.getAttribute("data-ace-base");
-            if (base)
-                return base.replace(/\/*$/, "/");
-
-            var src = script.src || script.getAttribute("src");
-            if (!src) {
-                continue;
-            }
-            var m = src.match(/^(?:(.*\/)ace\.js|(.*\/)ace(-uncompressed)?(-noconflict)?\.js)(?:\?|$)/);
-            if (m)
-                return m[1] || m[2];
-        }
-        return "";
-    };
-
-    this.terminate = function() {
-        this._emit("terminate", {});
-        this.$worker.terminate();
-        this.$worker = null;
-        this.$doc.removeEventListener("change", this.changeListener);
-        this.$doc = null;
-    };
-
-    this.send = function(cmd, args) {
-        this.$worker.postMessage({command: cmd, args: args});
-    };
-
-    this.call = function(cmd, args, callback) {
-        if (callback) {
-            var id = this.callbackId++;
-            this.callbacks[id] = callback;
-            args.push(id);
-        }
-        this.send(cmd, args);
-    };
-
-    this.emit = function(event, data) {
-        try {
-            // firefox refuses to clone objects which have function properties
-            // TODO: cleanup event
-            this.$worker.postMessage({event: event, data: {data: data.data}});
-        }
-        catch(ex) {}
-    };
-
-    this.attachToDocument = function(doc) {
-        if(this.$doc)
-            this.terminate();
-
-        this.$doc = doc;
-        this.call("setValue", [doc.getValue()]);
-        doc.on("change", this.changeListener);
-    };
-
-    this.changeListener = function(e) {
-        e.range = {
-            start: e.data.range.start,
-            end: e.data.range.end
-        };
-        this.emit("change", e);
-    };
-
-}).call(WorkerClient.prototype);
-
-exports.WorkerClient = WorkerClient;
-
 });
 /* vim:ts=4:sts=4:sw=4:
  * ***** BEGIN LICENSE BLOCK *****
@@ -933,12 +849,12 @@ var CstyleBehaviour = function () {
                 return {
                     text: '{' + selected + '}',
                     selection: false
-                }
+                };
             } else {
                 return {
                     text: '{}',
                     selection: [1, 1]
-                }
+                };
             }
         } else if (text == '}') {
             var cursor = editor.getCursorPosition();
@@ -950,7 +866,7 @@ var CstyleBehaviour = function () {
                     return {
                         text: '',
                         selection: [1, 1]
-                    }
+                    };
                 }
             }
         } else if (text == "\n") {
@@ -968,7 +884,7 @@ var CstyleBehaviour = function () {
                 return {
                     text: '\n' + indent + '\n' + next_indent,
                     selection: [1, indent.length, 1, indent.length]
-                }
+                };
             }
         }
     });
@@ -993,12 +909,12 @@ var CstyleBehaviour = function () {
                 return {
                     text: '(' + selected + ')',
                     selection: false
-                }
+                };
             } else {
                 return {
                     text: '()',
                     selection: [1, 1]
-                }
+                };
             }
         } else if (text == ')') {
             var cursor = editor.getCursorPosition();
@@ -1010,7 +926,7 @@ var CstyleBehaviour = function () {
                     return {
                         text: '',
                         selection: [1, 1]
-                    }
+                    };
                 }
             }
         }
@@ -1029,14 +945,15 @@ var CstyleBehaviour = function () {
     });
 
     this.add("string_dquotes", "insertion", function (state, action, editor, session, text) {
-        if (text == '"') {
+        if (text == '"' || text == "'") {
+            var quote = text;
             var selection = editor.getSelectionRange();
             var selected = session.doc.getTextRange(selection);
             if (selected !== "") {
                 return {
-                    text: '"' + selected + '"',
+                    text: quote + selected + quote,
                     selection: false
-                }
+                };
             } else {
                 var cursor = editor.getCursorPosition();
                 var line = session.doc.getLine(cursor.row);
@@ -1057,7 +974,7 @@ var CstyleBehaviour = function () {
                     if (token.type == "string") {
                       quotepos = -1;
                     } else if (quotepos < 0) {
-                      quotepos = token.value.indexOf('"');
+                      quotepos = token.value.indexOf(quote);
                     }
                     if ((token.value.length + col) > selection.start.column) {
                         break;
@@ -1066,19 +983,19 @@ var CstyleBehaviour = function () {
                 }
 
                 // Try and be smart about when we auto insert.
-                if (!token || (quotepos < 0 && token.type !== "comment" && (token.type !== "string" || ((selection.start.column !== token.value.length+col-1) && token.value.lastIndexOf('"') === token.value.length-1)))) {
+                if (!token || (quotepos < 0 && token.type !== "comment" && (token.type !== "string" || ((selection.start.column !== token.value.length+col-1) && token.value.lastIndexOf(quote) === token.value.length-1)))) {
                     return {
-                        text: '""',
+                        text: quote + quote,
                         selection: [1,1]
-                    }
+                    };
                 } else if (token && token.type === "string") {
                     // Ignore input and move right one if we're typing over the closing quote.
                     var rightChar = line.substring(cursor.column, cursor.column + 1);
-                    if (rightChar == '"') {
+                    if (rightChar == quote) {
                         return {
                             text: '',
                             selection: [1, 1]
-                        }
+                        };
                     }
                 }
             }
@@ -1087,7 +1004,7 @@ var CstyleBehaviour = function () {
 
     this.add("string_dquotes", "deletion", function (state, action, editor, session, range) {
         var selected = session.doc.getTextRange(range);
-        if (!range.isMultiLine() && selected == '"') {
+        if (!range.isMultiLine() && (selected == '"' || selected == "'")) {
             var line = session.doc.getLine(range.start.row);
             var rightChar = line.substring(range.start.column + 1, range.start.column + 2);
             if (rightChar == '"') {
@@ -1097,7 +1014,8 @@ var CstyleBehaviour = function () {
         }
     });
 
-}
+};
+
 oop.inherits(CstyleBehaviour, Behaviour);
 
 exports.CstyleBehaviour = CstyleBehaviour;
@@ -1452,13 +1370,3 @@ oop.inherits(JavaHighlightRules, TextHighlightRules);
 
 exports.JavaHighlightRules = JavaHighlightRules;
 });
-;
-            (function() {
-                window.require(["ace/ace"], function(a) {
-                    if (!window.ace)
-                        window.ace = {};
-                    for (var key in a) if (a.hasOwnProperty(key))
-                        ace[key] = a[key];
-                });
-            })();
-        
\ No newline at end of file
diff --git a/apps/files_texteditor/js/aceeditor/mode-java.js b/apps/files_texteditor/js/aceeditor/mode-java.js
index 84c21daba22b4db2facf44d8c6519e29be1daa52..9398464a18e68582d1b06524fd2aa4cd8d3adf95 100644
--- a/apps/files_texteditor/js/aceeditor/mode-java.js
+++ b/apps/files_texteditor/js/aceeditor/mode-java.js
@@ -1 +1 @@
-define("ace/mode/java",["require","exports","module","ace/lib/oop","ace/mode/javascript","ace/tokenizer","ace/mode/java_highlight_rules"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("./javascript").Mode,f=a("../tokenizer").Tokenizer,g=a("./java_highlight_rules").JavaHighlightRules,h=function(){e.call(this),this.$tokenizer=new f((new g).getRules())};d.inherits(h,e),function(){this.createWorker=function(a){return null}}.call(h.prototype),b.Mode=h}),define("ace/mode/javascript",["require","exports","module","ace/lib/oop","ace/mode/text","ace/tokenizer","ace/mode/javascript_highlight_rules","ace/mode/matching_brace_outdent","ace/range","ace/worker/worker_client","ace/mode/behaviour/cstyle","ace/mode/folding/cstyle"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("./text").Mode,f=a("../tokenizer").Tokenizer,g=a("./javascript_highlight_rules").JavaScriptHighlightRules,h=a("./matching_brace_outdent").MatchingBraceOutdent,i=a("../range").Range,j=a("../worker/worker_client").WorkerClient,k=a("./behaviour/cstyle").CstyleBehaviour,l=a("./folding/cstyle").FoldMode,m=function(){this.$tokenizer=new f((new g).getRules()),this.$outdent=new h,this.$behaviour=new k,this.foldingRules=new l};d.inherits(m,e),function(){this.toggleCommentLines=function(a,b,c,d){var e=!0,f=/^(\s*)\/\//;for(var g=c;g<=d;g++)if(!f.test(b.getLine(g))){e=!1;break}if(e){var h=new i(0,0,0,0);for(var g=c;g<=d;g++){var j=b.getLine(g),k=j.match(f);h.start.row=g,h.end.row=g,h.end.column=k[0].length,b.replace(h,k[1])}}else b.indentRows(c,d,"//")},this.getNextLineIndent=function(a,b,c){var d=this.$getIndent(b),e=this.$tokenizer.getLineTokens(b,a),f=e.tokens,g=e.state;if(f.length&&f[f.length-1].type=="comment")return d;if(a=="start"||a=="regex_allowed"){var h=b.match(/^.*(?:\bcase\b.*\:|[\{\(\[])\s*$/);h&&(d+=c)}else if(a=="doc-start"){if(g=="start"||a=="regex_allowed")return"";var h=b.match(/^\s*(\/?)\*/);h&&(h[1]&&(d+=" "),d+="* ")}return d},this.checkOutdent=function(a,b,c){return this.$outdent.checkOutdent(b,c)},this.autoOutdent=function(a,b,c){this.$outdent.autoOutdent(b,c)},this.createWorker=function(a){var b=new j(["ace"],"worker-javascript.js","ace/mode/javascript_worker","JavaScriptWorker");return b.attachToDocument(a.getDocument()),b.on("jslint",function(b){var c=[];for(var d=0;d<b.data.length;d++){var e=b.data[d];e&&c.push({row:e.line-1,column:e.character-1,text:e.reason,type:"warning",lint:e})}a.setAnnotations(c)}),b.on("narcissus",function(b){a.setAnnotations([b.data])}),b.on("terminate",function(){a.clearAnnotations()}),b}}.call(m.prototype),b.Mode=m}),define("ace/mode/javascript_highlight_rules",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/unicode","ace/mode/doc_comment_highlight_rules","ace/mode/text_highlight_rules"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("../lib/lang"),f=a("../unicode"),g=a("./doc_comment_highlight_rules").DocCommentHighlightRules,h=a("./text_highlight_rules").TextHighlightRules,i=function(){var a=e.arrayToMap("Array|Boolean|Date|Function|Iterator|Number|Object|RegExp|String|Proxy|Namespace|QName|XML|XMLList|ArrayBuffer|Float32Array|Float64Array|Int16Array|Int32Array|Int8Array|Uint16Array|Uint32Array|Uint8Array|Uint8ClampedArray|Error|EvalError|InternalError|RangeError|ReferenceError|StopIteration|SyntaxError|TypeError|URIError|decodeURI|decodeURIComponent|encodeURI|encodeURIComponent|eval|isFinite|isNaN|parseFloat|parseInt|JSON|Math|this|arguments|prototype|window|document".split("|")),b=e.arrayToMap("break|case|catch|continue|default|delete|do|else|finally|for|function|if|in|instanceof|new|return|switch|throw|try|typeof|let|var|while|with|const|yield|import|get|set".split("|")),c="case|do|else|finally|in|instanceof|return|throw|try|typeof|yield",d=e.arrayToMap("__parent__|__count__|escape|unescape|with|__proto__".split("|")),h=e.arrayToMap("const|let|var|function".split("|")),i=e.arrayToMap("null|Infinity|NaN|undefined".split("|")),j=e.arrayToMap("class|enum|extends|super|export|implements|private|public|interface|package|protected|static".split("|")),k="["+f.packages.L+"\\$_]["+f.packages.L+f.packages.Mn+f.packages.Mc+f.packages.Nd+f.packages.Pc+"\\$_]*\\b";this.$rules={start:[{token:"comment",regex:"\\/\\/.*$"},(new g).getStartRule("doc-start"),{token:"comment",merge:!0,regex:"\\/\\*",next:"comment"},{token:"string",regex:'["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'},{token:"string",merge:!0,regex:'["].*\\\\$',next:"qqstring"},{token:"string",regex:"['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"},{token:"string",merge:!0,regex:"['].*\\\\$",next:"qstring"},{token:"constant.numeric",regex:"0[xX][0-9a-fA-F]+\\b"},{token:"constant.numeric",regex:"[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"},{token:["keyword.definition","text","entity.name.function"],regex:"(function)(\\s+)("+k+")"},{token:"constant.language.boolean",regex:"(?:true|false)\\b"},{token:"keyword",regex:"(?:"+c+")\\b",next:"regex_allowed"},{token:function(c){return a.hasOwnProperty(c)?"variable.language":d.hasOwnProperty(c)?"invalid.deprecated":h.hasOwnProperty(c)?"keyword.definition":b.hasOwnProperty(c)?"keyword":i.hasOwnProperty(c)?"constant.language":j.hasOwnProperty(c)?"invalid.illegal":c=="debugger"?"invalid.deprecated":"identifier"},regex:k},{token:"keyword.operator",regex:"!|\\$|%|&|\\*|\\-\\-|\\-|\\+\\+|\\+|~|===|==|=|!=|!==|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\\|\\||\\?\\:|\\*=|%=|\\+=|\\-=|&=|\\^=|\\b(?:in|instanceof|new|delete|typeof|void)",next:"regex_allowed"},{token:"punctuation.operator",regex:"\\?|\\:|\\,|\\;|\\.",next:"regex_allowed"},{token:"paren.lparen",regex:"[[({]",next:"regex_allowed"},{token:"paren.rparen",regex:"[\\])}]"},{token:"keyword.operator",regex:"\\/=?",next:"regex_allowed"},{token:"comment",regex:"^#!.*$"},{token:"text",regex:"\\s+"}],regex_allowed:[{token:"comment",merge:!0,regex:"\\/\\*",next:"comment_regex_allowed"},{token:"comment",regex:"\\/\\/.*$"},{token:"string.regexp",regex:"\\/",next:"regex",merge:!0},{token:"text",regex:"\\s+"},{token:"empty",regex:"",next:"start"}],regex:[{token:"regexp.keyword.operator",regex:"\\\\(?:u[\\da-fA-F]{4}|x[\\da-fA-F]{2}|.)",next:"regex"},{token:"string.regexp",regex:"/\\w*",next:"start",merge:!0},{token:"string.regexp",regex:"[^\\\\/\\[]+",next:"regex",merge:!0},{token:"string.regexp.charachterclass",regex:"\\[",next:"regex_character_class",merge:!0},{token:"empty",regex:"",next:"start"}],regex_character_class:[{token:"regexp.keyword.operator",regex:"\\\\(?:u[\\da-fA-F]{4}|x[\\da-fA-F]{2}|.)",next:"regex_character_class"},{token:"string.regexp.charachterclass",regex:"]",next:"regex",merge:!0},{token:"string.regexp.charachterclass",regex:"[^\\\\\\]]+",next:"regex_character_class",merge:!0},{token:"empty",regex:"",next:"start"}],comment_regex_allowed:[{token:"comment",regex:".*?\\*\\/",merge:!0,next:"regex_allowed"},{token:"comment",merge:!0,regex:".+"}],comment:[{token:"comment",regex:".*?\\*\\/",merge:!0,next:"start"},{token:"comment",merge:!0,regex:".+"}],qqstring:[{token:"string",regex:'(?:(?:\\\\.)|(?:[^"\\\\]))*?"',next:"start"},{token:"string",merge:!0,regex:".+"}],qstring:[{token:"string",regex:"(?:(?:\\\\.)|(?:[^'\\\\]))*?'",next:"start"},{token:"string",merge:!0,regex:".+"}]},this.embedRules(g,"doc-",[(new g).getEndRule("start")])};d.inherits(i,h),b.JavaScriptHighlightRules=i}),define("ace/mode/doc_comment_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("./text_highlight_rules").TextHighlightRules,f=function(){this.$rules={start:[{token:"comment.doc.tag",regex:"@[\\w\\d_]+"},{token:"comment.doc",merge:!0,regex:"\\s+"},{token:"comment.doc",merge:!0,regex:"TODO"},{token:"comment.doc",merge:!0,regex:"[^@\\*]+"},{token:"comment.doc",merge:!0,regex:"."}]}};d.inherits(f,e),function(){this.getStartRule=function(a){return{token:"comment.doc",merge:!0,regex:"\\/\\*(?=\\*)",next:a}},this.getEndRule=function(a){return{token:"comment.doc",merge:!0,regex:"\\*\\/",next:a}}}.call(f.prototype),b.DocCommentHighlightRules=f}),define("ace/mode/matching_brace_outdent",["require","exports","module","ace/range"],function(a,b,c){"use strict";var d=a("../range").Range,e=function(){};((function(){this.checkOutdent=function(a,b){return/^\s+$/.test(a)?/^\s*\}/.test(b):!1},this.autoOutdent=function(a,b){var c=a.getLine(b),e=c.match(/^(\s*\})/);if(!e)return 0;var f=e[1].length,g=a.findMatchingBracket({row:b,column:f});if(!g||g.row==b)return 0;var h=this.$getIndent(a.getLine(g.row));a.replace(new d(b,0,b,f-1),h)},this.$getIndent=function(a){var b=a.match(/^(\s+)/);return b?b[1]:""}})).call(e.prototype),b.MatchingBraceOutdent=e}),define("ace/worker/worker_client",["require","exports","module","ace/lib/oop","ace/lib/event_emitter"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("../lib/event_emitter").EventEmitter,f=function(b,d,e,f){this.changeListener=this.changeListener.bind(this);if(c.packaged){var g=this.$guessBasePath();this.$worker=new Worker(g+d)}else{var h=this.$normalizePath(a.nameToUrl("ace/worker/worker",null,"_"));this.$worker=new Worker(h);var i={};for(var j=0;j<b.length;j++){var k=b[j],l=this.$normalizePath(a.nameToUrl(k,null,"_").replace(/.js$/,""));i[k]=l}}this.$worker.postMessage({init:!0,tlns:i,module:e,classname:f}),this.callbackId=1,this.callbacks={};var m=this;this.$worker.onerror=function(a){throw window.console&&console.log&&console.log(a),a},this.$worker.onmessage=function(a){var b=a.data;switch(b.type){case"log":window.console&&console.log&&console.log(b.data);break;case"event":m._emit(b.name,{data:b.data});break;case"call":var c=m.callbacks[b.id];c&&(c(b.data),delete m.callbacks[b.id])}}};((function(){d.implement(this,e),this.$normalizePath=function(a){return a=a.replace(/^[a-z]+:\/\/[^\/]+\//,""),a=location.protocol+"//"+location.host+(a.charAt(0)=="/"?"":location.pathname.replace(/\/[^\/]*$/,""))+"/"+a.replace(/^[\/]+/,""),a},this.$guessBasePath=function(){if(a.aceBaseUrl)return a.aceBaseUrl;var b=document.getElementsByTagName("script");for(var c=0;c<b.length;c++){var d=b[c],e=d.getAttribute("data-ace-base");if(e)return e.replace(/\/*$/,"/");var f=d.src||d.getAttribute("src");if(!f)continue;var g=f.match(/^(?:(.*\/)ace\.js|(.*\/)ace(-uncompressed)?(-noconflict)?\.js)(?:\?|$)/);if(g)return g[1]||g[2]}return""},this.terminate=function(){this._emit("terminate",{}),this.$worker.terminate(),this.$worker=null,this.$doc.removeEventListener("change",this.changeListener),this.$doc=null},this.send=function(a,b){this.$worker.postMessage({command:a,args:b})},this.call=function(a,b,c){if(c){var d=this.callbackId++;this.callbacks[d]=c,b.push(d)}this.send(a,b)},this.emit=function(a,b){try{this.$worker.postMessage({event:a,data:{data:b.data}})}catch(c){}},this.attachToDocument=function(a){this.$doc&&this.terminate(),this.$doc=a,this.call("setValue",[a.getValue()]),a.on("change",this.changeListener)},this.changeListener=function(a){a.range={start:a.data.range.start,end:a.data.range.end},this.emit("change",a)}})).call(f.prototype),b.WorkerClient=f}),define("ace/mode/behaviour/cstyle",["require","exports","module","ace/lib/oop","ace/mode/behaviour"],function(a,b,c){"use strict";var d=a("../../lib/oop"),e=a("../behaviour").Behaviour,f=function(){this.add("braces","insertion",function(a,b,c,d,e){if(e=="{"){var f=c.getSelectionRange(),g=d.doc.getTextRange(f);return g!==""?{text:"{"+g+"}",selection:!1}:{text:"{}",selection:[1,1]}}if(e=="}"){var h=c.getCursorPosition(),i=d.doc.getLine(h.row),j=i.substring(h.column,h.column+1);if(j=="}"){var k=d.$findOpeningBracket("}",{column:h.column+1,row:h.row});if(k!==null)return{text:"",selection:[1,1]}}}else if(e=="\n"){var h=c.getCursorPosition(),i=d.doc.getLine(h.row),j=i.substring(h.column,h.column+1);if(j=="}"){var l=d.findMatchingBracket({row:h.row,column:h.column+1});if(!l)return null;var m=this.getNextLineIndent(a,i.substring(0,i.length-1),d.getTabString()),n=this.$getIndent(d.doc.getLine(l.row));return{text:"\n"+m+"\n"+n,selection:[1,m.length,1,m.length]}}}}),this.add("braces","deletion",function(a,b,c,d,e){var f=d.doc.getTextRange(e);if(!e.isMultiLine()&&f=="{"){var g=d.doc.getLine(e.start.row),h=g.substring(e.end.column,e.end.column+1);if(h=="}")return e.end.column++,e}}),this.add("parens","insertion",function(a,b,c,d,e){if(e=="("){var f=c.getSelectionRange(),g=d.doc.getTextRange(f);return g!==""?{text:"("+g+")",selection:!1}:{text:"()",selection:[1,1]}}if(e==")"){var h=c.getCursorPosition(),i=d.doc.getLine(h.row),j=i.substring(h.column,h.column+1);if(j==")"){var k=d.$findOpeningBracket(")",{column:h.column+1,row:h.row});if(k!==null)return{text:"",selection:[1,1]}}}}),this.add("parens","deletion",function(a,b,c,d,e){var f=d.doc.getTextRange(e);if(!e.isMultiLine()&&f=="("){var g=d.doc.getLine(e.start.row),h=g.substring(e.start.column+1,e.start.column+2);if(h==")")return e.end.column++,e}}),this.add("string_dquotes","insertion",function(a,b,c,d,e){if(e=='"'){var f=c.getSelectionRange(),g=d.doc.getTextRange(f);if(g!=="")return{text:'"'+g+'"',selection:!1};var h=c.getCursorPosition(),i=d.doc.getLine(h.row),j=i.substring(h.column-1,h.column);if(j=="\\")return null;var k=d.getTokens(f.start.row,f.start.row)[0].tokens,l=0,m,n=-1;for(var o=0;o<k.length;o++){m=k[o],m.type=="string"?n=-1:n<0&&(n=m.value.indexOf('"'));if(m.value.length+l>f.start.column)break;l+=k[o].value.length}if(!m||n<0&&m.type!=="comment"&&(m.type!=="string"||f.start.column!==m.value.length+l-1&&m.value.lastIndexOf('"')===m.value.length-1))return{text:'""',selection:[1,1]};if(m&&m.type==="string"){var p=i.substring(h.column,h.column+1);if(p=='"')return{text:"",selection:[1,1]}}}}),this.add("string_dquotes","deletion",function(a,b,c,d,e){var f=d.doc.getTextRange(e);if(!e.isMultiLine()&&f=='"'){var g=d.doc.getLine(e.start.row),h=g.substring(e.start.column+1,e.start.column+2);if(h=='"')return e.end.column++,e}})};d.inherits(f,e),b.CstyleBehaviour=f}),define("ace/mode/folding/cstyle",["require","exports","module","ace/lib/oop","ace/range","ace/mode/folding/fold_mode"],function(a,b,c){"use strict";var d=a("../../lib/oop"),e=a("../../range").Range,f=a("./fold_mode").FoldMode,g=b.FoldMode=function(){};d.inherits(g,f),function(){this.foldingStartMarker=/(\{|\[)[^\}\]]*$|^\s*(\/\*)/,this.foldingStopMarker=/^[^\[\{]*(\}|\])|^[\s\*]*(\*\/)/,this.getFoldWidgetRange=function(a,b,c){var d=a.getLine(c),f=d.match(this.foldingStartMarker);if(f){var g=f.index;if(f[1])return this.openingBracketBlock(a,f[1],c,g);var h=a.getCommentFoldRange(c,g+f[0].length);return h.end.column-=2,h}if(b!=="markbeginend")return;var f=d.match(this.foldingStopMarker);if(f){var g=f.index+f[0].length;if(f[2]){var h=a.getCommentFoldRange(c,g);return h.end.column-=2,h}var i={row:c,column:g},j=a.$findOpeningBracket(f[1],i);if(!j)return;return j.column++,i.column--,e.fromPoints(j,i)}}}.call(g.prototype)}),define("ace/mode/folding/fold_mode",["require","exports","module","ace/range"],function(a,b,c){"use strict";var d=a("../../range").Range,e=b.FoldMode=function(){};((function(){this.foldingStartMarker=null,this.foldingStopMarker=null,this.getFoldWidget=function(a,b,c){var d=a.getLine(c);return this.foldingStartMarker.test(d)?"start":b=="markbeginend"&&this.foldingStopMarker&&this.foldingStopMarker.test(d)?"end":""},this.getFoldWidgetRange=function(a,b,c){return null},this.indentationBlock=function(a,b,c){var e=/^\s*/,f=b,g=b,h=a.getLine(b),i=c||h.length,j=h.match(e)[0].length,k=a.getLength();while(++b<k){h=a.getLine(b);var l=h.match(e)[0].length;if(l==h.length)continue;if(l<=j)break;g=b}if(g>f){var m=a.getLine(g).length;return new d(f,i,g,m)}},this.openingBracketBlock=function(a,b,c,e){var f={row:c,column:e+1},g=a.$findClosingBracket(b,f);if(!g)return;var h=a.foldWidgets[g.row];return h==null&&(h=this.getFoldWidget(a,g.row)),h=="start"&&(g.row--,g.column=a.getLine(g.row).length),d.fromPoints(f,g)}})).call(e.prototype)}),define("ace/mode/java_highlight_rules",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/mode/doc_comment_highlight_rules","ace/mode/text_highlight_rules"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("../lib/lang"),f=a("./doc_comment_highlight_rules").DocCommentHighlightRules,g=a("./text_highlight_rules").TextHighlightRules,h=function(){var a=e.arrayToMap("abstract|continue|for|new|switch|assert|default|goto|package|synchronized|boolean|do|if|private|this|break|double|implements|protected|throw|byte|else|import|public|throws|case|enum|instanceof|return|transient|catch|extends|int|short|try|char|final|interface|static|void|class|finally|long|strictfp|volatile|const|float|native|super|while".split("|")),b=e.arrayToMap("null|Infinity|NaN|undefined".split("|")),c=e.arrayToMap("AbstractMethodError|AssertionError|ClassCircularityError|ClassFormatError|Deprecated|EnumConstantNotPresentException|ExceptionInInitializerError|IllegalAccessError|IllegalThreadStateException|InstantiationError|InternalError|NegativeArraySizeException|NoSuchFieldError|Override|Process|ProcessBuilder|SecurityManager|StringIndexOutOfBoundsException|SuppressWarnings|TypeNotPresentException|UnknownError|UnsatisfiedLinkError|UnsupportedClassVersionError|VerifyError|InstantiationException|IndexOutOfBoundsException|ArrayIndexOutOfBoundsException|CloneNotSupportedException|NoSuchFieldException|IllegalArgumentException|NumberFormatException|SecurityException|Void|InheritableThreadLocal|IllegalStateException|InterruptedException|NoSuchMethodException|IllegalAccessException|UnsupportedOperationException|Enum|StrictMath|Package|Compiler|Readable|Runtime|StringBuilder|Math|IncompatibleClassChangeError|NoSuchMethodError|ThreadLocal|RuntimePermission|ArithmeticException|NullPointerException|Long|Integer|Short|Byte|Double|Number|Float|Character|Boolean|StackTraceElement|Appendable|StringBuffer|Iterable|ThreadGroup|Runnable|Thread|IllegalMonitorStateException|StackOverflowError|OutOfMemoryError|VirtualMachineError|ArrayStoreException|ClassCastException|LinkageError|NoClassDefFoundError|ClassNotFoundException|RuntimeException|Exception|ThreadDeath|Error|Throwable|System|ClassLoader|Cloneable|Class|CharSequence|Comparable|String|Object".split("|")),d=e.arrayToMap("".split("|"));this.$rules={start:[{token:"comment",regex:"\\/\\/.*$"},(new f).getStartRule("doc-start"),{token:"comment",merge:!0,regex:"\\/\\*",next:"comment"},{token:"string.regexp",regex:"[/](?:(?:\\[(?:\\\\]|[^\\]])+\\])|(?:\\\\/|[^\\]/]))*[/]\\w*\\s*(?=[).,;]|$)"},{token:"string",regex:'["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'},{token:"string",regex:"['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"},{token:"constant.numeric",regex:"0[xX][0-9a-fA-F]+\\b"},{token:"constant.numeric",regex:"[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"},{token:"constant.language.boolean",regex:"(?:true|false)\\b"},{token:function(e){return e=="this"?"variable.language":a.hasOwnProperty(e)?"keyword":c.hasOwnProperty(e)?"support.function":d.hasOwnProperty(e)?"support.function":b.hasOwnProperty(e)?"constant.language":"identifier"},regex:"[a-zA-Z_$][a-zA-Z0-9_$]*\\b"},{token:"keyword.operator",regex:"!|\\$|%|&|\\*|\\-\\-|\\-|\\+\\+|\\+|~|===|==|=|!=|!==|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\\|\\||\\?\\:|\\*=|%=|\\+=|\\-=|&=|\\^=|\\b(?:in|instanceof|new|delete|typeof|void)"},{token:"lparen",regex:"[[({]"},{token:"rparen",regex:"[\\])}]"},{token:"text",regex:"\\s+"}],comment:[{token:"comment",regex:".*?\\*\\/",next:"start"},{token:"comment",merge:!0,regex:".+"}]},this.embedRules(f,"doc-",[(new f).getEndRule("start")])};d.inherits(h,g),b.JavaHighlightRules=h}),function(){window.require(["ace/ace"],function(a){window.ace||(window.ace={});for(var b in a)a.hasOwnProperty(b)&&(ace[b]=a[b])})}()
\ No newline at end of file
+define("ace/mode/java",["require","exports","module","ace/lib/oop","ace/mode/javascript","ace/tokenizer","ace/mode/java_highlight_rules"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("./javascript").Mode,f=a("../tokenizer").Tokenizer,g=a("./java_highlight_rules").JavaHighlightRules,h=function(){e.call(this),this.$tokenizer=new f((new g).getRules())};d.inherits(h,e),function(){this.createWorker=function(a){return null}}.call(h.prototype),b.Mode=h}),define("ace/mode/javascript",["require","exports","module","ace/lib/oop","ace/mode/text","ace/tokenizer","ace/mode/javascript_highlight_rules","ace/mode/matching_brace_outdent","ace/range","ace/worker/worker_client","ace/mode/behaviour/cstyle","ace/mode/folding/cstyle"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("./text").Mode,f=a("../tokenizer").Tokenizer,g=a("./javascript_highlight_rules").JavaScriptHighlightRules,h=a("./matching_brace_outdent").MatchingBraceOutdent,i=a("../range").Range,j=a("../worker/worker_client").WorkerClient,k=a("./behaviour/cstyle").CstyleBehaviour,l=a("./folding/cstyle").FoldMode,m=function(){this.$tokenizer=new f((new g).getRules()),this.$outdent=new h,this.$behaviour=new k,this.foldingRules=new l};d.inherits(m,e),function(){this.toggleCommentLines=function(a,b,c,d){var e=!0,f=/^(\s*)\/\//;for(var g=c;g<=d;g++)if(!f.test(b.getLine(g))){e=!1;break}if(e){var h=new i(0,0,0,0);for(var g=c;g<=d;g++){var j=b.getLine(g),k=j.match(f);h.start.row=g,h.end.row=g,h.end.column=k[0].length,b.replace(h,k[1])}}else b.indentRows(c,d,"//")},this.getNextLineIndent=function(a,b,c){var d=this.$getIndent(b),e=this.$tokenizer.getLineTokens(b,a),f=e.tokens,g=e.state;if(f.length&&f[f.length-1].type=="comment")return d;if(a=="start"||a=="regex_allowed"){var h=b.match(/^.*(?:\bcase\b.*\:|[\{\(\[])\s*$/);h&&(d+=c)}else if(a=="doc-start"){if(g=="start"||a=="regex_allowed")return"";var h=b.match(/^\s*(\/?)\*/);h&&(h[1]&&(d+=" "),d+="* ")}return d},this.checkOutdent=function(a,b,c){return this.$outdent.checkOutdent(b,c)},this.autoOutdent=function(a,b,c){this.$outdent.autoOutdent(b,c)},this.createWorker=function(a){var b=new j(["ace"],"worker-javascript.js","ace/mode/javascript_worker","JavaScriptWorker");return b.attachToDocument(a.getDocument()),b.on("jslint",function(b){var c=[];for(var d=0;d<b.data.length;d++){var e=b.data[d];e&&c.push({row:e.line-1,column:e.character-1,text:e.reason,type:"warning",lint:e})}a.setAnnotations(c)}),b.on("narcissus",function(b){a.setAnnotations([b.data])}),b.on("terminate",function(){a.clearAnnotations()}),b}}.call(m.prototype),b.Mode=m}),define("ace/mode/javascript_highlight_rules",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/unicode","ace/mode/doc_comment_highlight_rules","ace/mode/text_highlight_rules"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("../lib/lang"),f=a("../unicode"),g=a("./doc_comment_highlight_rules").DocCommentHighlightRules,h=a("./text_highlight_rules").TextHighlightRules,i=function(){var a=e.arrayToMap("Array|Boolean|Date|Function|Iterator|Number|Object|RegExp|String|Proxy|Namespace|QName|XML|XMLList|ArrayBuffer|Float32Array|Float64Array|Int16Array|Int32Array|Int8Array|Uint16Array|Uint32Array|Uint8Array|Uint8ClampedArray|Error|EvalError|InternalError|RangeError|ReferenceError|StopIteration|SyntaxError|TypeError|URIError|decodeURI|decodeURIComponent|encodeURI|encodeURIComponent|eval|isFinite|isNaN|parseFloat|parseInt|JSON|Math|this|arguments|prototype|window|document".split("|")),b=e.arrayToMap("break|case|catch|continue|default|delete|do|else|finally|for|function|if|in|instanceof|new|return|switch|throw|try|typeof|let|var|while|with|const|yield|import|get|set".split("|")),c="case|do|else|finally|in|instanceof|return|throw|try|typeof|yield",d=e.arrayToMap("__parent__|__count__|escape|unescape|with|__proto__".split("|")),h=e.arrayToMap("const|let|var|function".split("|")),i=e.arrayToMap("null|Infinity|NaN|undefined".split("|")),j=e.arrayToMap("class|enum|extends|super|export|implements|private|public|interface|package|protected|static".split("|")),k="["+f.packages.L+"\\$_]["+f.packages.L+f.packages.Mn+f.packages.Mc+f.packages.Nd+f.packages.Pc+"\\$_]*\\b",l="\\\\(?:x[0-9a-fA-F]{2}|u[0-9a-fA-F]{4}|[0-2][0-7]{0,2}|3[0-6][0-7]?|37[0-7]?|[4-7][0-7]?|.)";this.$rules={start:[{token:"comment",regex:/\/\/.*$/},(new g).getStartRule("doc-start"),{token:"comment",merge:!0,regex:/\/\*/,next:"comment"},{token:"string",regex:"'",next:"qstring"},{token:"string",regex:'"',next:"qqstring"},{token:"constant.numeric",regex:/0[xX][0-9a-fA-F]+\b/},{token:"constant.numeric",regex:/[+-]?\d+(?:(?:\.\d*)?(?:[eE][+-]?\d+)?)?\b/},{token:["storage.type","punctuation.operator","support.function","punctuation.operator","entity.name.function","text","keyword.operator","text","storage.type","text","paren.lparen","variable.parameter","paren.rparen"],regex:"("+k+")(\\.)(prototype)(\\.)("+k+")(\\s*)(=)(\\s*)(function)(\\s*)(\\()(.*?)(\\))"},{token:["storage.type","punctuation.operator","support.function","punctuation.operator","entity.name.function","text","keyword.operator","text"],regex:"("+k+")(\\.)(prototype)(\\.)("+k+")(\\s*)(=)(\\s*)"},{token:["storage.type","punctuation.operator","entity.name.function","text","keyword.operator","text","storage.type","text","paren.lparen","variable.parameter","paren.rparen"],regex:"("+k+")(\\.)("+k+")(\\s*)(=)(\\s*)(function)(\\s*)(\\()(.*?)(\\))"},{token:["entity.name.function","text","keyword.operator","text","storage.type","text","paren.lparen","variable.parameter","paren.rparen"],regex:"("+k+")(\\s*)(=)(\\s*)(function)(\\s*)(\\()(.*?)(\\))"},{token:["storage.type","text","entity.name.function","text","paren.lparen","variable.parameter","paren.rparen"],regex:"(function)(\\s+)("+k+")(\\s*)(\\()(.*?)(\\))"},{token:["entity.name.function","text","punctuation.operator","text","storage.type","text","paren.lparen","variable.parameter","paren.rparen"],regex:"("+k+")(\\s*)(:)(\\s*)(function)(\\s*)(\\()(.*?)(\\))"},{token:["text","text","storage.type","text","paren.lparen","variable.parameter","paren.rparen"],regex:"(:)(\\s*)(function)?(\\s*)(\\()([^)]*)(\\))"},{token:"constant.language.boolean",regex:/(?:true|false)\b/},{token:"keyword",regex:"(?:"+c+")\\b",next:"regex_allowed"},{token:["punctuation.operator","support.function"],regex:/(\.)(s(?:h(?:ift|ow(?:Mod(?:elessDialog|alDialog)|Help))|croll(?:X|By(?:Pages|Lines)?|Y|To)?|t(?:opzzzz|rike)|i(?:n|zeToContent|debar|gnText)|ort|u(?:p|b(?:str(?:ing)?)?)|pli(?:ce|t)|e(?:nd|t(?:Re(?:sizable|questHeader)|M(?:i(?:nutes|lliseconds)|onth)|Seconds|Ho(?:tKeys|urs)|Year|Cursor|Time(?:out)?|Interval|ZOptions|Date|UTC(?:M(?:i(?:nutes|lliseconds)|onth)|Seconds|Hours|Date|FullYear)|FullYear|Active)|arch)|qrt|lice|avePreferences|mall)|h(?:ome|andleEvent)|navigate|c(?:har(?:CodeAt|At)|o(?:s|n(?:cat|textual|firm)|mpile)|eil|lear(?:Timeout|Interval)?|a(?:ptureEvents|ll)|reate(?:StyleSheet|Popup|EventObject))|t(?:o(?:GMTString|S(?:tring|ource)|U(?:TCString|pperCase)|Lo(?:caleString|werCase))|est|a(?:n|int(?:Enabled)?))|i(?:s(?:NaN|Finite)|ndexOf|talics)|d(?:isableExternalCapture|ump|etachEvent)|u(?:n(?:shift|taint|escape|watch)|pdateCommands)|j(?:oin|avaEnabled)|p(?:o(?:p|w)|ush|lugins.refresh|a(?:ddings|rse(?:Int|Float)?)|r(?:int|ompt|eference))|e(?:scape|nableExternalCapture|val|lementFromPoint|x(?:p|ec(?:Script|Command)?))|valueOf|UTC|queryCommand(?:State|Indeterm|Enabled|Value)|f(?:i(?:nd|le(?:ModifiedDate|Size|CreatedDate|UpdatedDate)|xed)|o(?:nt(?:size|color)|rward)|loor|romCharCode)|watch|l(?:ink|o(?:ad|g)|astIndexOf)|a(?:sin|nchor|cos|t(?:tachEvent|ob|an(?:2)?)|pply|lert|b(?:s|ort))|r(?:ou(?:nd|teEvents)|e(?:size(?:By|To)|calc|turnValue|place|verse|l(?:oad|ease(?:Capture|Events)))|andom)|g(?:o|et(?:ResponseHeader|M(?:i(?:nutes|lliseconds)|onth)|Se(?:conds|lection)|Hours|Year|Time(?:zoneOffset)?|Da(?:y|te)|UTC(?:M(?:i(?:nutes|lliseconds)|onth)|Seconds|Hours|Da(?:y|te)|FullYear)|FullYear|A(?:ttention|llResponseHeaders)))|m(?:in|ove(?:B(?:y|elow)|To(?:Absolute)?|Above)|ergeAttributes|a(?:tch|rgins|x))|b(?:toa|ig|o(?:ld|rderWidths)|link|ack))\b(?=\()/},{token:["punctuation.operator","support.function.dom"],regex:/(\.)(s(?:ub(?:stringData|mit)|plitText|e(?:t(?:NamedItem|Attribute(?:Node)?)|lect))|has(?:ChildNodes|Feature)|namedItem|c(?:l(?:ick|o(?:se|neNode))|reate(?:C(?:omment|DATASection|aption)|T(?:Head|extNode|Foot)|DocumentFragment|ProcessingInstruction|E(?:ntityReference|lement)|Attribute))|tabIndex|i(?:nsert(?:Row|Before|Cell|Data)|tem)|open|delete(?:Row|C(?:ell|aption)|T(?:Head|Foot)|Data)|focus|write(?:ln)?|a(?:dd|ppend(?:Child|Data))|re(?:set|place(?:Child|Data)|move(?:NamedItem|Child|Attribute(?:Node)?)?)|get(?:NamedItem|Element(?:sBy(?:Name|TagName)|ById)|Attribute(?:Node)?)|blur)\b(?=\()/},{token:["punctuation.operator","support.constant"],regex:/(\.)(s(?:ystemLanguage|cr(?:ipts|ollbars|een(?:X|Y|Top|Left))|t(?:yle(?:Sheets)?|atus(?:Text|bar)?)|ibling(?:Below|Above)|ource|uffixes|e(?:curity(?:Policy)?|l(?:ection|f)))|h(?:istory|ost(?:name)?|as(?:h|Focus))|y|X(?:MLDocument|SLDocument)|n(?:ext|ame(?:space(?:s|URI)|Prop))|M(?:IN_VALUE|AX_VALUE)|c(?:haracterSet|o(?:n(?:structor|trollers)|okieEnabled|lorDepth|mp(?:onents|lete))|urrent|puClass|l(?:i(?:p(?:boardData)?|entInformation)|osed|asses)|alle(?:e|r)|rypto)|t(?:o(?:olbar|p)|ext(?:Transform|Indent|Decoration|Align)|ags)|SQRT(?:1_2|2)|i(?:n(?:ner(?:Height|Width)|put)|ds|gnoreCase)|zIndex|o(?:scpu|n(?:readystatechange|Line)|uter(?:Height|Width)|p(?:sProfile|ener)|ffscreenBuffering)|NEGATIVE_INFINITY|d(?:i(?:splay|alog(?:Height|Top|Width|Left|Arguments)|rectories)|e(?:scription|fault(?:Status|Ch(?:ecked|arset)|View)))|u(?:ser(?:Profile|Language|Agent)|n(?:iqueID|defined)|pdateInterval)|_content|p(?:ixelDepth|ort|ersonalbar|kcs11|l(?:ugins|atform)|a(?:thname|dding(?:Right|Bottom|Top|Left)|rent(?:Window|Layer)?|ge(?:X(?:Offset)?|Y(?:Offset)?))|r(?:o(?:to(?:col|type)|duct(?:Sub)?|mpter)|e(?:vious|fix)))|e(?:n(?:coding|abledPlugin)|x(?:ternal|pando)|mbeds)|v(?:isibility|endor(?:Sub)?|Linkcolor)|URLUnencoded|P(?:I|OSITIVE_INFINITY)|f(?:ilename|o(?:nt(?:Size|Family|Weight)|rmName)|rame(?:s|Element)|gColor)|E|whiteSpace|l(?:i(?:stStyleType|n(?:eHeight|kColor))|o(?:ca(?:tion(?:bar)?|lName)|wsrc)|e(?:ngth|ft(?:Context)?)|a(?:st(?:M(?:odified|atch)|Index|Paren)|yer(?:s|X)|nguage))|a(?:pp(?:MinorVersion|Name|Co(?:deName|re)|Version)|vail(?:Height|Top|Width|Left)|ll|r(?:ity|guments)|Linkcolor|bove)|r(?:ight(?:Context)?|e(?:sponse(?:XML|Text)|adyState))|global|x|m(?:imeTypes|ultiline|enubar|argin(?:Right|Bottom|Top|Left))|L(?:N(?:10|2)|OG(?:10E|2E))|b(?:o(?:ttom|rder(?:Width|RightWidth|BottomWidth|Style|Color|TopWidth|LeftWidth))|ufferDepth|elow|ackground(?:Color|Image)))\b/},{token:["storage.type","punctuation.operator","support.function.firebug"],regex:/(console)(\.)(warn|info|log|error|time|timeEnd|assert)\b/},{token:function(c){return a.hasOwnProperty(c)?"variable.language":d.hasOwnProperty(c)?"invalid.deprecated":h.hasOwnProperty(c)?"storage.type":b.hasOwnProperty(c)?"keyword":i.hasOwnProperty(c)?"constant.language":j.hasOwnProperty(c)?"invalid.illegal":c=="debugger"?"invalid.deprecated":"identifier"},regex:k},{token:"keyword.operator",regex:/!|\$|%|&|\*|\-\-|\-|\+\+|\+|~|===|==|=|!=|!==|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\|\||\?\:|\*=|%=|\+=|\-=|&=|\^=|\b(?:in|instanceof|new|delete|typeof|void)/,next:"regex_allowed"},{token:"punctuation.operator",regex:/\?|\:|\,|\;|\./,next:"regex_allowed"},{token:"paren.lparen",regex:/[\[({]/,next:"regex_allowed"},{token:"paren.rparen",regex:/[\])}]/},{token:"keyword.operator",regex:/\/=?/,next:"regex_allowed"},{token:"comment",regex:/^#!.*$/},{token:"text",regex:/\s+/}],regex_allowed:[{token:"comment",merge:!0,regex:"\\/\\*",next:"comment_regex_allowed"},{token:"comment",regex:"\\/\\/.*$"},{token:"string.regexp",regex:"\\/",next:"regex",merge:!0},{token:"text",regex:"\\s+"},{token:"empty",regex:"",next:"start"}],regex:[{token:"regexp.keyword.operator",regex:"\\\\(?:u[\\da-fA-F]{4}|x[\\da-fA-F]{2}|.)",next:"regex"},{token:"string.regexp",regex:"/\\w*",next:"start",merge:!0},{token:"string.regexp",regex:"[^\\\\/\\[]+",next:"regex",merge:!0},{token:"string.regexp.charachterclass",regex:"\\[",next:"regex_character_class",merge:!0},{token:"empty",regex:"",next:"start"}],regex_character_class:[{token:"regexp.keyword.operator",regex:"\\\\(?:u[\\da-fA-F]{4}|x[\\da-fA-F]{2}|.)",next:"regex_character_class"},{token:"string.regexp.charachterclass",regex:"]",next:"regex",merge:!0},{token:"string.regexp.charachterclass",regex:"[^\\\\\\]]+",next:"regex_character_class",merge:!0},{token:"empty",regex:"",next:"start"}],comment_regex_allowed:[{token:"comment",regex:".*?\\*\\/",merge:!0,next:"regex_allowed"},{token:"comment",merge:!0,regex:".+"}],comment:[{token:"comment",regex:".*?\\*\\/",merge:!0,next:"start"},{token:"comment",merge:!0,regex:".+"}],qqstring:[{token:"constant.language.escape",regex:l},{token:"string",regex:'[^"\\\\]+'},{token:"string",regex:'"',next:"start"}],qstring:[{token:"constant.language.escape",regex:l},{token:"string",regex:"[^'\\\\]+"},{token:"string",regex:"'",next:"start"}]},this.embedRules(g,"doc-",[(new g).getEndRule("start")])};d.inherits(i,h),b.JavaScriptHighlightRules=i}),define("ace/mode/doc_comment_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("./text_highlight_rules").TextHighlightRules,f=function(){this.$rules={start:[{token:"comment.doc.tag",regex:"@[\\w\\d_]+"},{token:"comment.doc",merge:!0,regex:"\\s+"},{token:"comment.doc",merge:!0,regex:"TODO"},{token:"comment.doc",merge:!0,regex:"[^@\\*]+"},{token:"comment.doc",merge:!0,regex:"."}]}};d.inherits(f,e),function(){this.getStartRule=function(a){return{token:"comment.doc",merge:!0,regex:"\\/\\*(?=\\*)",next:a}},this.getEndRule=function(a){return{token:"comment.doc",merge:!0,regex:"\\*\\/",next:a}}}.call(f.prototype),b.DocCommentHighlightRules=f}),define("ace/mode/matching_brace_outdent",["require","exports","module","ace/range"],function(a,b,c){"use strict";var d=a("../range").Range,e=function(){};(function(){this.checkOutdent=function(a,b){return/^\s+$/.test(a)?/^\s*\}/.test(b):!1},this.autoOutdent=function(a,b){var c=a.getLine(b),e=c.match(/^(\s*\})/);if(!e)return 0;var f=e[1].length,g=a.findMatchingBracket({row:b,column:f});if(!g||g.row==b)return 0;var h=this.$getIndent(a.getLine(g.row));a.replace(new d(b,0,b,f-1),h)},this.$getIndent=function(a){var b=a.match(/^(\s+)/);return b?b[1]:""}}).call(e.prototype),b.MatchingBraceOutdent=e}),define("ace/mode/behaviour/cstyle",["require","exports","module","ace/lib/oop","ace/mode/behaviour"],function(a,b,c){"use strict";var d=a("../../lib/oop"),e=a("../behaviour").Behaviour,f=function(){this.add("braces","insertion",function(a,b,c,d,e){if(e=="{"){var f=c.getSelectionRange(),g=d.doc.getTextRange(f);return g!==""?{text:"{"+g+"}",selection:!1}:{text:"{}",selection:[1,1]}}if(e=="}"){var h=c.getCursorPosition(),i=d.doc.getLine(h.row),j=i.substring(h.column,h.column+1);if(j=="}"){var k=d.$findOpeningBracket("}",{column:h.column+1,row:h.row});if(k!==null)return{text:"",selection:[1,1]}}}else if(e=="\n"){var h=c.getCursorPosition(),i=d.doc.getLine(h.row),j=i.substring(h.column,h.column+1);if(j=="}"){var l=d.findMatchingBracket({row:h.row,column:h.column+1});if(!l)return null;var m=this.getNextLineIndent(a,i.substring(0,i.length-1),d.getTabString()),n=this.$getIndent(d.doc.getLine(l.row));return{text:"\n"+m+"\n"+n,selection:[1,m.length,1,m.length]}}}}),this.add("braces","deletion",function(a,b,c,d,e){var f=d.doc.getTextRange(e);if(!e.isMultiLine()&&f=="{"){var g=d.doc.getLine(e.start.row),h=g.substring(e.end.column,e.end.column+1);if(h=="}")return e.end.column++,e}}),this.add("parens","insertion",function(a,b,c,d,e){if(e=="("){var f=c.getSelectionRange(),g=d.doc.getTextRange(f);return g!==""?{text:"("+g+")",selection:!1}:{text:"()",selection:[1,1]}}if(e==")"){var h=c.getCursorPosition(),i=d.doc.getLine(h.row),j=i.substring(h.column,h.column+1);if(j==")"){var k=d.$findOpeningBracket(")",{column:h.column+1,row:h.row});if(k!==null)return{text:"",selection:[1,1]}}}}),this.add("parens","deletion",function(a,b,c,d,e){var f=d.doc.getTextRange(e);if(!e.isMultiLine()&&f=="("){var g=d.doc.getLine(e.start.row),h=g.substring(e.start.column+1,e.start.column+2);if(h==")")return e.end.column++,e}}),this.add("string_dquotes","insertion",function(a,b,c,d,e){if(e=='"'||e=="'"){var f=e,g=c.getSelectionRange(),h=d.doc.getTextRange(g);if(h!=="")return{text:f+h+f,selection:!1};var i=c.getCursorPosition(),j=d.doc.getLine(i.row),k=j.substring(i.column-1,i.column);if(k=="\\")return null;var l=d.getTokens(g.start.row,g.start.row)[0].tokens,m=0,n,o=-1;for(var p=0;p<l.length;p++){n=l[p],n.type=="string"?o=-1:o<0&&(o=n.value.indexOf(f));if(n.value.length+m>g.start.column)break;m+=l[p].value.length}if(!n||o<0&&n.type!=="comment"&&(n.type!=="string"||g.start.column!==n.value.length+m-1&&n.value.lastIndexOf(f)===n.value.length-1))return{text:f+f,selection:[1,1]};if(n&&n.type==="string"){var q=j.substring(i.column,i.column+1);if(q==f)return{text:"",selection:[1,1]}}}}),this.add("string_dquotes","deletion",function(a,b,c,d,e){var f=d.doc.getTextRange(e);if(!e.isMultiLine()&&(f=='"'||f=="'")){var g=d.doc.getLine(e.start.row),h=g.substring(e.start.column+1,e.start.column+2);if(h=='"')return e.end.column++,e}})};d.inherits(f,e),b.CstyleBehaviour=f}),define("ace/mode/folding/cstyle",["require","exports","module","ace/lib/oop","ace/range","ace/mode/folding/fold_mode"],function(a,b,c){"use strict";var d=a("../../lib/oop"),e=a("../../range").Range,f=a("./fold_mode").FoldMode,g=b.FoldMode=function(){};d.inherits(g,f),function(){this.foldingStartMarker=/(\{|\[)[^\}\]]*$|^\s*(\/\*)/,this.foldingStopMarker=/^[^\[\{]*(\}|\])|^[\s\*]*(\*\/)/,this.getFoldWidgetRange=function(a,b,c){var d=a.getLine(c),f=d.match(this.foldingStartMarker);if(f){var g=f.index;if(f[1])return this.openingBracketBlock(a,f[1],c,g);var h=a.getCommentFoldRange(c,g+f[0].length);return h.end.column-=2,h}if(b!=="markbeginend")return;var f=d.match(this.foldingStopMarker);if(f){var g=f.index+f[0].length;if(f[2]){var h=a.getCommentFoldRange(c,g);return h.end.column-=2,h}var i={row:c,column:g},j=a.$findOpeningBracket(f[1],i);if(!j)return;return j.column++,i.column--,e.fromPoints(j,i)}}}.call(g.prototype)}),define("ace/mode/folding/fold_mode",["require","exports","module","ace/range"],function(a,b,c){"use strict";var d=a("../../range").Range,e=b.FoldMode=function(){};(function(){this.foldingStartMarker=null,this.foldingStopMarker=null,this.getFoldWidget=function(a,b,c){var d=a.getLine(c);return this.foldingStartMarker.test(d)?"start":b=="markbeginend"&&this.foldingStopMarker&&this.foldingStopMarker.test(d)?"end":""},this.getFoldWidgetRange=function(a,b,c){return null},this.indentationBlock=function(a,b,c){var e=/^\s*/,f=b,g=b,h=a.getLine(b),i=c||h.length,j=h.match(e)[0].length,k=a.getLength();while(++b<k){h=a.getLine(b);var l=h.match(e)[0].length;if(l==h.length)continue;if(l<=j)break;g=b}if(g>f){var m=a.getLine(g).length;return new d(f,i,g,m)}},this.openingBracketBlock=function(a,b,c,e){var f={row:c,column:e+1},g=a.$findClosingBracket(b,f);if(!g)return;var h=a.foldWidgets[g.row];return h==null&&(h=this.getFoldWidget(a,g.row)),h=="start"&&(g.row--,g.column=a.getLine(g.row).length),d.fromPoints(f,g)}}).call(e.prototype)}),define("ace/mode/java_highlight_rules",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/mode/doc_comment_highlight_rules","ace/mode/text_highlight_rules"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("../lib/lang"),f=a("./doc_comment_highlight_rules").DocCommentHighlightRules,g=a("./text_highlight_rules").TextHighlightRules,h=function(){var a=e.arrayToMap("abstract|continue|for|new|switch|assert|default|goto|package|synchronized|boolean|do|if|private|this|break|double|implements|protected|throw|byte|else|import|public|throws|case|enum|instanceof|return|transient|catch|extends|int|short|try|char|final|interface|static|void|class|finally|long|strictfp|volatile|const|float|native|super|while".split("|")),b=e.arrayToMap("null|Infinity|NaN|undefined".split("|")),c=e.arrayToMap("AbstractMethodError|AssertionError|ClassCircularityError|ClassFormatError|Deprecated|EnumConstantNotPresentException|ExceptionInInitializerError|IllegalAccessError|IllegalThreadStateException|InstantiationError|InternalError|NegativeArraySizeException|NoSuchFieldError|Override|Process|ProcessBuilder|SecurityManager|StringIndexOutOfBoundsException|SuppressWarnings|TypeNotPresentException|UnknownError|UnsatisfiedLinkError|UnsupportedClassVersionError|VerifyError|InstantiationException|IndexOutOfBoundsException|ArrayIndexOutOfBoundsException|CloneNotSupportedException|NoSuchFieldException|IllegalArgumentException|NumberFormatException|SecurityException|Void|InheritableThreadLocal|IllegalStateException|InterruptedException|NoSuchMethodException|IllegalAccessException|UnsupportedOperationException|Enum|StrictMath|Package|Compiler|Readable|Runtime|StringBuilder|Math|IncompatibleClassChangeError|NoSuchMethodError|ThreadLocal|RuntimePermission|ArithmeticException|NullPointerException|Long|Integer|Short|Byte|Double|Number|Float|Character|Boolean|StackTraceElement|Appendable|StringBuffer|Iterable|ThreadGroup|Runnable|Thread|IllegalMonitorStateException|StackOverflowError|OutOfMemoryError|VirtualMachineError|ArrayStoreException|ClassCastException|LinkageError|NoClassDefFoundError|ClassNotFoundException|RuntimeException|Exception|ThreadDeath|Error|Throwable|System|ClassLoader|Cloneable|Class|CharSequence|Comparable|String|Object".split("|")),d=e.arrayToMap("".split("|"));this.$rules={start:[{token:"comment",regex:"\\/\\/.*$"},(new f).getStartRule("doc-start"),{token:"comment",merge:!0,regex:"\\/\\*",next:"comment"},{token:"string.regexp",regex:"[/](?:(?:\\[(?:\\\\]|[^\\]])+\\])|(?:\\\\/|[^\\]/]))*[/]\\w*\\s*(?=[).,;]|$)"},{token:"string",regex:'["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'},{token:"string",regex:"['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"},{token:"constant.numeric",regex:"0[xX][0-9a-fA-F]+\\b"},{token:"constant.numeric",regex:"[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"},{token:"constant.language.boolean",regex:"(?:true|false)\\b"},{token:function(e){return e=="this"?"variable.language":a.hasOwnProperty(e)?"keyword":c.hasOwnProperty(e)?"support.function":d.hasOwnProperty(e)?"support.function":b.hasOwnProperty(e)?"constant.language":"identifier"},regex:"[a-zA-Z_$][a-zA-Z0-9_$]*\\b"},{token:"keyword.operator",regex:"!|\\$|%|&|\\*|\\-\\-|\\-|\\+\\+|\\+|~|===|==|=|!=|!==|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\\|\\||\\?\\:|\\*=|%=|\\+=|\\-=|&=|\\^=|\\b(?:in|instanceof|new|delete|typeof|void)"},{token:"lparen",regex:"[[({]"},{token:"rparen",regex:"[\\])}]"},{token:"text",regex:"\\s+"}],comment:[{token:"comment",regex:".*?\\*\\/",next:"start"},{token:"comment",merge:!0,regex:".+"}]},this.embedRules(f,"doc-",[(new f).getEndRule("start")])};d.inherits(h,g),b.JavaHighlightRules=h})
\ No newline at end of file
diff --git a/apps/files_texteditor/js/aceeditor/mode-javascript-uncompressed.js b/apps/files_texteditor/js/aceeditor/mode-javascript-uncompressed.js
old mode 100755
new mode 100644
index ba30b9e438f92c81960ed48aae17b9ebebf07a2a..8afe93503a962930c67da47bd8332537da0f5842
--- a/apps/files_texteditor/js/aceeditor/mode-javascript-uncompressed.js
+++ b/apps/files_texteditor/js/aceeditor/mode-javascript-uncompressed.js
@@ -257,12 +257,20 @@ var JavaScriptHighlightRules = function() {
     );
 
     // TODO: Unicode escape sequences
-    var identifierRe = "[" + unicode.packages.L + "\\$_][" 
+    var identifierRe = "[" + unicode.packages.L + "\\$_]["
         + unicode.packages.L
         + unicode.packages.Mn + unicode.packages.Mc
         + unicode.packages.Nd
         + unicode.packages.Pc + "\\$_]*\\b";
-        
+
+    var escapedRe = "\\\\(?:x[0-9a-fA-F]{2}|" + // hex
+        "u[0-9a-fA-F]{4}|" + // unicode
+        "[0-2][0-7]{0,2}|" + // oct
+        "3[0-6][0-7]?|" + // oct
+        "37[0-7]?|" + // oct
+        "[4-7][0-7]?|" + //oct
+        ".)";
+
     // regexp must not have capturing parentheses. Use (?:) instead.
     // regexps are ordered -> the first match is used
 
@@ -270,46 +278,139 @@ var JavaScriptHighlightRules = function() {
         "start" : [
             {
                 token : "comment",
-                regex : "\\/\\/.*$"
+                regex : /\/\/.*$/
             },
             new DocCommentHighlightRules().getStartRule("doc-start"),
             {
                 token : "comment", // multi line comment
                 merge : true,
-                regex : "\\/\\*",
+                regex : /\/\*/,
                 next : "comment"
             }, {
-                token : "string", // single line
-                regex : '["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'
-            }, {
-                token : "string", // multi line string start
-                merge : true,
-                regex : '["].*\\\\$',
-                next : "qqstring"
-            }, {
-                token : "string", // single line
-                regex : "['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"
+                token : "string",
+                regex : "'",
+                next  : "qstring"
             }, {
-                token : "string", // multi line string start
-                merge : true,
-                regex : "['].*\\\\$",
-                next : "qstring"
+                token : "string",
+                regex : '"',
+                next  : "qqstring"
             }, {
                 token : "constant.numeric", // hex
-                regex : "0[xX][0-9a-fA-F]+\\b"
+                regex : /0[xX][0-9a-fA-F]+\b/
             }, {
                 token : "constant.numeric", // float
-                regex : "[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"
-            }, {
-                token : ["keyword.definition", "text", "entity.name.function"],
-                regex : "(function)(\\s+)(" + identifierRe + ")"
+                regex : /[+-]?\d+(?:(?:\.\d*)?(?:[eE][+-]?\d+)?)?\b/
+            }, { // match stuff like: Sound.prototype.play = function() { }
+                token : [
+                    "storage.type",
+                    "punctuation.operator",
+                    "support.function",
+                    "punctuation.operator",
+                    "entity.name.function",
+                    "text",
+                    "keyword.operator",
+                    "text",
+                    "storage.type",
+                    "text",
+                    "paren.lparen",
+                    "variable.parameter",
+                    "paren.rparen"
+                ],
+                regex : "(" + identifierRe + ")(\\.)(prototype)(\\.)(" + identifierRe +")(\\s*)(=)(\\s*)(function)(\\s*)(\\()(.*?)(\\))"
+            }, { // match stuff like: Sound.prototype.play = myfunc
+                token : [
+                    "storage.type",
+                    "punctuation.operator",
+                    "support.function",
+                    "punctuation.operator",
+                    "entity.name.function",
+                    "text",
+                    "keyword.operator",
+                    "text"
+                ],
+                regex : "(" + identifierRe + ")(\\.)(prototype)(\\.)(" + identifierRe +")(\\s*)(=)(\\s*)"
+            }, { // match stuff like: Sound.play = function() {  }
+                token : [
+                    "storage.type",
+                    "punctuation.operator",
+                    "entity.name.function",
+                    "text",
+                    "keyword.operator",
+                    "text",
+                    "storage.type",
+                    "text",
+                    "paren.lparen",
+                    "variable.parameter",
+                    "paren.rparen"
+                ],
+                regex : "(" + identifierRe + ")(\\.)(" + identifierRe +")(\\s*)(=)(\\s*)(function)(\\s*)(\\()(.*?)(\\))"
+            }, { // match stuff like: play = function() {  }
+                token : [
+                    "entity.name.function",
+                    "text",
+                    "keyword.operator",
+                    "text",
+                    "storage.type",
+                    "text",
+                    "paren.lparen",
+                    "variable.parameter",
+                    "paren.rparen"
+                ],
+                regex : "(" + identifierRe +")(\\s*)(=)(\\s*)(function)(\\s*)(\\()(.*?)(\\))"
+            }, { // match regular function like: function myFunc(arg) { }
+                token : [
+                    "storage.type",
+                    "text",
+                    "entity.name.function",
+                    "text",
+                    "paren.lparen",
+                    "variable.parameter",
+                    "paren.rparen"
+                ],
+                regex : "(function)(\\s+)(" + identifierRe + ")(\\s*)(\\()(.*?)(\\))"
+            }, { // match stuff like: foobar: function() { }
+                token : [
+                    "entity.name.function",
+                    "text",
+                    "punctuation.operator",
+                    "text",
+                    "storage.type",
+                    "text",
+                    "paren.lparen",
+                    "variable.parameter",
+                    "paren.rparen"
+                ],
+                regex : "(" + identifierRe + ")(\\s*)(:)(\\s*)(function)(\\s*)(\\()(.*?)(\\))"
+            }, { // Attempt to match : function() { } (this is for issues with 'foo': function() { })
+                token : [
+                    "text",
+                    "text",
+                    "storage.type",
+                    "text",
+                    "paren.lparen",
+                    "variable.parameter",
+                    "paren.rparen"
+                ],
+                regex : "(:)(\\s*)(function)?(\\s*)(\\()([^)]*)(\\))"
             }, {
                 token : "constant.language.boolean",
-                regex : "(?:true|false)\\b"
+                regex : /(?:true|false)\b/
             }, {
                 token : "keyword",
                 regex : "(?:" + kwBeforeRe + ")\\b",
                 next : "regex_allowed"
+            }, {
+                token : ["punctuation.operator", "support.function"],
+                regex : /(\.)(s(?:h(?:ift|ow(?:Mod(?:elessDialog|alDialog)|Help))|croll(?:X|By(?:Pages|Lines)?|Y|To)?|t(?:opzzzz|rike)|i(?:n|zeToContent|debar|gnText)|ort|u(?:p|b(?:str(?:ing)?)?)|pli(?:ce|t)|e(?:nd|t(?:Re(?:sizable|questHeader)|M(?:i(?:nutes|lliseconds)|onth)|Seconds|Ho(?:tKeys|urs)|Year|Cursor|Time(?:out)?|Interval|ZOptions|Date|UTC(?:M(?:i(?:nutes|lliseconds)|onth)|Seconds|Hours|Date|FullYear)|FullYear|Active)|arch)|qrt|lice|avePreferences|mall)|h(?:ome|andleEvent)|navigate|c(?:har(?:CodeAt|At)|o(?:s|n(?:cat|textual|firm)|mpile)|eil|lear(?:Timeout|Interval)?|a(?:ptureEvents|ll)|reate(?:StyleSheet|Popup|EventObject))|t(?:o(?:GMTString|S(?:tring|ource)|U(?:TCString|pperCase)|Lo(?:caleString|werCase))|est|a(?:n|int(?:Enabled)?))|i(?:s(?:NaN|Finite)|ndexOf|talics)|d(?:isableExternalCapture|ump|etachEvent)|u(?:n(?:shift|taint|escape|watch)|pdateCommands)|j(?:oin|avaEnabled)|p(?:o(?:p|w)|ush|lugins.refresh|a(?:ddings|rse(?:Int|Float)?)|r(?:int|ompt|eference))|e(?:scape|nableExternalCapture|val|lementFromPoint|x(?:p|ec(?:Script|Command)?))|valueOf|UTC|queryCommand(?:State|Indeterm|Enabled|Value)|f(?:i(?:nd|le(?:ModifiedDate|Size|CreatedDate|UpdatedDate)|xed)|o(?:nt(?:size|color)|rward)|loor|romCharCode)|watch|l(?:ink|o(?:ad|g)|astIndexOf)|a(?:sin|nchor|cos|t(?:tachEvent|ob|an(?:2)?)|pply|lert|b(?:s|ort))|r(?:ou(?:nd|teEvents)|e(?:size(?:By|To)|calc|turnValue|place|verse|l(?:oad|ease(?:Capture|Events)))|andom)|g(?:o|et(?:ResponseHeader|M(?:i(?:nutes|lliseconds)|onth)|Se(?:conds|lection)|Hours|Year|Time(?:zoneOffset)?|Da(?:y|te)|UTC(?:M(?:i(?:nutes|lliseconds)|onth)|Seconds|Hours|Da(?:y|te)|FullYear)|FullYear|A(?:ttention|llResponseHeaders)))|m(?:in|ove(?:B(?:y|elow)|To(?:Absolute)?|Above)|ergeAttributes|a(?:tch|rgins|x))|b(?:toa|ig|o(?:ld|rderWidths)|link|ack))\b(?=\()/
+            }, {
+                token : ["punctuation.operator", "support.function.dom"],
+                regex : /(\.)(s(?:ub(?:stringData|mit)|plitText|e(?:t(?:NamedItem|Attribute(?:Node)?)|lect))|has(?:ChildNodes|Feature)|namedItem|c(?:l(?:ick|o(?:se|neNode))|reate(?:C(?:omment|DATASection|aption)|T(?:Head|extNode|Foot)|DocumentFragment|ProcessingInstruction|E(?:ntityReference|lement)|Attribute))|tabIndex|i(?:nsert(?:Row|Before|Cell|Data)|tem)|open|delete(?:Row|C(?:ell|aption)|T(?:Head|Foot)|Data)|focus|write(?:ln)?|a(?:dd|ppend(?:Child|Data))|re(?:set|place(?:Child|Data)|move(?:NamedItem|Child|Attribute(?:Node)?)?)|get(?:NamedItem|Element(?:sBy(?:Name|TagName)|ById)|Attribute(?:Node)?)|blur)\b(?=\()/
+            }, {
+                token : ["punctuation.operator", "support.constant"],
+                regex : /(\.)(s(?:ystemLanguage|cr(?:ipts|ollbars|een(?:X|Y|Top|Left))|t(?:yle(?:Sheets)?|atus(?:Text|bar)?)|ibling(?:Below|Above)|ource|uffixes|e(?:curity(?:Policy)?|l(?:ection|f)))|h(?:istory|ost(?:name)?|as(?:h|Focus))|y|X(?:MLDocument|SLDocument)|n(?:ext|ame(?:space(?:s|URI)|Prop))|M(?:IN_VALUE|AX_VALUE)|c(?:haracterSet|o(?:n(?:structor|trollers)|okieEnabled|lorDepth|mp(?:onents|lete))|urrent|puClass|l(?:i(?:p(?:boardData)?|entInformation)|osed|asses)|alle(?:e|r)|rypto)|t(?:o(?:olbar|p)|ext(?:Transform|Indent|Decoration|Align)|ags)|SQRT(?:1_2|2)|i(?:n(?:ner(?:Height|Width)|put)|ds|gnoreCase)|zIndex|o(?:scpu|n(?:readystatechange|Line)|uter(?:Height|Width)|p(?:sProfile|ener)|ffscreenBuffering)|NEGATIVE_INFINITY|d(?:i(?:splay|alog(?:Height|Top|Width|Left|Arguments)|rectories)|e(?:scription|fault(?:Status|Ch(?:ecked|arset)|View)))|u(?:ser(?:Profile|Language|Agent)|n(?:iqueID|defined)|pdateInterval)|_content|p(?:ixelDepth|ort|ersonalbar|kcs11|l(?:ugins|atform)|a(?:thname|dding(?:Right|Bottom|Top|Left)|rent(?:Window|Layer)?|ge(?:X(?:Offset)?|Y(?:Offset)?))|r(?:o(?:to(?:col|type)|duct(?:Sub)?|mpter)|e(?:vious|fix)))|e(?:n(?:coding|abledPlugin)|x(?:ternal|pando)|mbeds)|v(?:isibility|endor(?:Sub)?|Linkcolor)|URLUnencoded|P(?:I|OSITIVE_INFINITY)|f(?:ilename|o(?:nt(?:Size|Family|Weight)|rmName)|rame(?:s|Element)|gColor)|E|whiteSpace|l(?:i(?:stStyleType|n(?:eHeight|kColor))|o(?:ca(?:tion(?:bar)?|lName)|wsrc)|e(?:ngth|ft(?:Context)?)|a(?:st(?:M(?:odified|atch)|Index|Paren)|yer(?:s|X)|nguage))|a(?:pp(?:MinorVersion|Name|Co(?:deName|re)|Version)|vail(?:Height|Top|Width|Left)|ll|r(?:ity|guments)|Linkcolor|bove)|r(?:ight(?:Context)?|e(?:sponse(?:XML|Text)|adyState))|global|x|m(?:imeTypes|ultiline|enubar|argin(?:Right|Bottom|Top|Left))|L(?:N(?:10|2)|OG(?:10E|2E))|b(?:o(?:ttom|rder(?:Width|RightWidth|BottomWidth|Style|Color|TopWidth|LeftWidth))|ufferDepth|elow|ackground(?:Color|Image)))\b/
+            }, {
+                token : ["storage.type", "punctuation.operator", "support.function.firebug"],
+                regex : /(console)(\.)(warn|info|log|error|time|timeEnd|assert)\b/
             }, {
                 token : function(value) {
                     if (globals.hasOwnProperty(value))
@@ -317,7 +418,7 @@ var JavaScriptHighlightRules = function() {
                     else if (deprecated.hasOwnProperty(value))
                         return "invalid.deprecated";
                     else if (definitions.hasOwnProperty(value))
-                        return "keyword.definition";
+                        return "storage.type";
                     else if (keywords.hasOwnProperty(value))
                         return "keyword";
                     else if (buildinConstants.hasOwnProperty(value))
@@ -332,29 +433,29 @@ var JavaScriptHighlightRules = function() {
                 regex : identifierRe
             }, {
                 token : "keyword.operator",
-                regex : "!|\\$|%|&|\\*|\\-\\-|\\-|\\+\\+|\\+|~|===|==|=|!=|!==|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\\|\\||\\?\\:|\\*=|%=|\\+=|\\-=|&=|\\^=|\\b(?:in|instanceof|new|delete|typeof|void)",
+                regex : /!|\$|%|&|\*|\-\-|\-|\+\+|\+|~|===|==|=|!=|!==|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\|\||\?\:|\*=|%=|\+=|\-=|&=|\^=|\b(?:in|instanceof|new|delete|typeof|void)/,
                 next  : "regex_allowed"
             }, {
                 token : "punctuation.operator",
-                regex : "\\?|\\:|\\,|\\;|\\.",
+                regex : /\?|\:|\,|\;|\./,
                 next  : "regex_allowed"
             }, {
                 token : "paren.lparen",
-                regex : "[[({]",
+                regex : /[\[({]/,
                 next  : "regex_allowed"
             }, {
                 token : "paren.rparen",
-                regex : "[\\])}]"
+                regex : /[\])}]/
             }, {
                 token : "keyword.operator",
-                regex : "\\/=?",
+                regex : /\/=?/,
                 next  : "regex_allowed"
             }, {
                 token: "comment",
-                regex: "^#!.*$" 
+                regex: /^#!.*$/
             }, {
                 token : "text",
-                regex : "\\s+"
+                regex : /\s+/
             }
         ],
         // regular expressions are only allowed after certain tokens. This
@@ -379,7 +480,7 @@ var JavaScriptHighlightRules = function() {
             }, {
                 // immediately return to the start mode without matching
                 // anything
-                token: "empty", 
+                token: "empty",
                 regex: "",
                 next: "start"
             }
@@ -391,10 +492,10 @@ var JavaScriptHighlightRules = function() {
                 next: "regex"
             }, {
 				// flag
-                token: "string.regexp", 
+                token: "string.regexp",
                 regex: "/\\w*",
                 next: "start",
-                merge: true 
+                merge: true
             }, {
                 token: "string.regexp",
                 regex: "[^\\\\/\\[]+",
@@ -406,9 +507,9 @@ var JavaScriptHighlightRules = function() {
                 next: "regex_character_class",
                 merge: true
             }, {
-                token: "empty", 
+                token: "empty",
                 regex: "",
-                next: "start" 
+                next: "start"
             }
         ],
         "regex_character_class": [
@@ -427,9 +528,9 @@ var JavaScriptHighlightRules = function() {
                 next: "regex_character_class",
                 merge: true
             }, {
-                token: "empty", 
+                token: "empty",
                 regex: "",
-                next: "start" 
+                next: "start"
             }
         ],
         "comment_regex_allowed" : [
@@ -458,28 +559,32 @@ var JavaScriptHighlightRules = function() {
         ],
         "qqstring" : [
             {
+                token : "constant.language.escape",
+                regex : escapedRe
+            }, {
                 token : "string",
-                regex : '(?:(?:\\\\.)|(?:[^"\\\\]))*?"',
-                next : "start"
+                regex : '[^"\\\\]+'
             }, {
                 token : "string",
-                merge : true,
-                regex : '.+'
+                regex : '"',
+                next  : "start"
             }
         ],
         "qstring" : [
             {
+                token : "constant.language.escape",
+                regex : escapedRe
+            }, {
                 token : "string",
-                regex : "(?:(?:\\\\.)|(?:[^'\\\\]))*?'",
-                next : "start"
+                regex : "[^'\\\\]+"
             }, {
                 token : "string",
-                merge : true,
-                regex : '.+'
+                regex : "'",
+                next  : "start"
             }
         ]
     };
-    
+
     this.embedRules(DocCommentHighlightRules, "doc-",
         [ new DocCommentHighlightRules().getEndRule("start") ]);
 };
@@ -664,195 +769,6 @@ var MatchingBraceOutdent = function() {};
 }).call(MatchingBraceOutdent.prototype);
 
 exports.MatchingBraceOutdent = MatchingBraceOutdent;
-});
-/* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is Ajax.org Code Editor (ACE).
- *
- * The Initial Developer of the Original Code is
- * Ajax.org B.V.
- * Portions created by the Initial Developer are Copyright (C) 2010
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *      Fabian Jakobs <fabian AT ajax DOT org>
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-define('ace/worker/worker_client', ['require', 'exports', 'module' , 'ace/lib/oop', 'ace/lib/event_emitter'], function(require, exports, module) {
-"use strict";
-
-var oop = require("../lib/oop");
-var EventEmitter = require("../lib/event_emitter").EventEmitter;
-
-var WorkerClient = function(topLevelNamespaces, packagedJs, mod, classname) {
-
-    this.changeListener = this.changeListener.bind(this);
-
-    if (module.packaged) {
-        var base = this.$guessBasePath();
-        this.$worker = new Worker(base + packagedJs);
-    }
-    else {
-        var workerUrl = this.$normalizePath(require.nameToUrl("ace/worker/worker", null, "_"));
-        this.$worker = new Worker(workerUrl);
-
-        var tlns = {};
-        for (var i=0; i<topLevelNamespaces.length; i++) {
-            var ns = topLevelNamespaces[i];
-            var path = this.$normalizePath(require.nameToUrl(ns, null, "_").replace(/.js$/, ""));
-
-            tlns[ns] = path;
-        }
-    }
-
-    this.$worker.postMessage({
-        init : true,
-        tlns: tlns,
-        module: mod,
-        classname: classname
-    });
-
-    this.callbackId = 1;
-    this.callbacks = {};
-
-    var _self = this;
-    this.$worker.onerror = function(e) {
-        window.console && console.log && console.log(e);
-        throw e;
-    };
-    this.$worker.onmessage = function(e) {
-        var msg = e.data;
-        switch(msg.type) {
-            case "log":
-                window.console && console.log && console.log(msg.data);
-                break;
-
-            case "event":
-                _self._emit(msg.name, {data: msg.data});
-                break;
-
-            case "call":
-                var callback = _self.callbacks[msg.id];
-                if (callback) {
-                    callback(msg.data);
-                    delete _self.callbacks[msg.id];
-                }
-                break;
-        }
-    };
-};
-
-(function(){
-
-    oop.implement(this, EventEmitter);
-
-    this.$normalizePath = function(path) {
-        path = path.replace(/^[a-z]+:\/\/[^\/]+\//, ""); // Remove domain name and rebuild it
-        path = location.protocol + "//" + location.host
-            // paths starting with a slash are relative to the root (host)
-            + (path.charAt(0) == "/" ? "" : location.pathname.replace(/\/[^\/]*$/, ""))
-            + "/" + path.replace(/^[\/]+/, "");
-        return path;
-    };
-
-    this.$guessBasePath = function() {
-        if (require.aceBaseUrl)
-            return require.aceBaseUrl;
-
-        var scripts = document.getElementsByTagName("script");
-        for (var i=0; i<scripts.length; i++) {
-            var script = scripts[i];
-
-            var base = script.getAttribute("data-ace-base");
-            if (base)
-                return base.replace(/\/*$/, "/");
-
-            var src = script.src || script.getAttribute("src");
-            if (!src) {
-                continue;
-            }
-            var m = src.match(/^(?:(.*\/)ace\.js|(.*\/)ace(-uncompressed)?(-noconflict)?\.js)(?:\?|$)/);
-            if (m)
-                return m[1] || m[2];
-        }
-        return "";
-    };
-
-    this.terminate = function() {
-        this._emit("terminate", {});
-        this.$worker.terminate();
-        this.$worker = null;
-        this.$doc.removeEventListener("change", this.changeListener);
-        this.$doc = null;
-    };
-
-    this.send = function(cmd, args) {
-        this.$worker.postMessage({command: cmd, args: args});
-    };
-
-    this.call = function(cmd, args, callback) {
-        if (callback) {
-            var id = this.callbackId++;
-            this.callbacks[id] = callback;
-            args.push(id);
-        }
-        this.send(cmd, args);
-    };
-
-    this.emit = function(event, data) {
-        try {
-            // firefox refuses to clone objects which have function properties
-            // TODO: cleanup event
-            this.$worker.postMessage({event: event, data: {data: data.data}});
-        }
-        catch(ex) {}
-    };
-
-    this.attachToDocument = function(doc) {
-        if(this.$doc)
-            this.terminate();
-
-        this.$doc = doc;
-        this.call("setValue", [doc.getValue()]);
-        doc.on("change", this.changeListener);
-    };
-
-    this.changeListener = function(e) {
-        e.range = {
-            start: e.data.range.start,
-            end: e.data.range.end
-        };
-        this.emit("change", e);
-    };
-
-}).call(WorkerClient.prototype);
-
-exports.WorkerClient = WorkerClient;
-
 });
 /* vim:ts=4:sts=4:sw=4:
  * ***** BEGIN LICENSE BLOCK *****
@@ -908,12 +824,12 @@ var CstyleBehaviour = function () {
                 return {
                     text: '{' + selected + '}',
                     selection: false
-                }
+                };
             } else {
                 return {
                     text: '{}',
                     selection: [1, 1]
-                }
+                };
             }
         } else if (text == '}') {
             var cursor = editor.getCursorPosition();
@@ -925,7 +841,7 @@ var CstyleBehaviour = function () {
                     return {
                         text: '',
                         selection: [1, 1]
-                    }
+                    };
                 }
             }
         } else if (text == "\n") {
@@ -943,7 +859,7 @@ var CstyleBehaviour = function () {
                 return {
                     text: '\n' + indent + '\n' + next_indent,
                     selection: [1, indent.length, 1, indent.length]
-                }
+                };
             }
         }
     });
@@ -968,12 +884,12 @@ var CstyleBehaviour = function () {
                 return {
                     text: '(' + selected + ')',
                     selection: false
-                }
+                };
             } else {
                 return {
                     text: '()',
                     selection: [1, 1]
-                }
+                };
             }
         } else if (text == ')') {
             var cursor = editor.getCursorPosition();
@@ -985,7 +901,7 @@ var CstyleBehaviour = function () {
                     return {
                         text: '',
                         selection: [1, 1]
-                    }
+                    };
                 }
             }
         }
@@ -1004,14 +920,15 @@ var CstyleBehaviour = function () {
     });
 
     this.add("string_dquotes", "insertion", function (state, action, editor, session, text) {
-        if (text == '"') {
+        if (text == '"' || text == "'") {
+            var quote = text;
             var selection = editor.getSelectionRange();
             var selected = session.doc.getTextRange(selection);
             if (selected !== "") {
                 return {
-                    text: '"' + selected + '"',
+                    text: quote + selected + quote,
                     selection: false
-                }
+                };
             } else {
                 var cursor = editor.getCursorPosition();
                 var line = session.doc.getLine(cursor.row);
@@ -1032,7 +949,7 @@ var CstyleBehaviour = function () {
                     if (token.type == "string") {
                       quotepos = -1;
                     } else if (quotepos < 0) {
-                      quotepos = token.value.indexOf('"');
+                      quotepos = token.value.indexOf(quote);
                     }
                     if ((token.value.length + col) > selection.start.column) {
                         break;
@@ -1041,19 +958,19 @@ var CstyleBehaviour = function () {
                 }
 
                 // Try and be smart about when we auto insert.
-                if (!token || (quotepos < 0 && token.type !== "comment" && (token.type !== "string" || ((selection.start.column !== token.value.length+col-1) && token.value.lastIndexOf('"') === token.value.length-1)))) {
+                if (!token || (quotepos < 0 && token.type !== "comment" && (token.type !== "string" || ((selection.start.column !== token.value.length+col-1) && token.value.lastIndexOf(quote) === token.value.length-1)))) {
                     return {
-                        text: '""',
+                        text: quote + quote,
                         selection: [1,1]
-                    }
+                    };
                 } else if (token && token.type === "string") {
                     // Ignore input and move right one if we're typing over the closing quote.
                     var rightChar = line.substring(cursor.column, cursor.column + 1);
-                    if (rightChar == '"') {
+                    if (rightChar == quote) {
                         return {
                             text: '',
                             selection: [1, 1]
-                        }
+                        };
                     }
                 }
             }
@@ -1062,7 +979,7 @@ var CstyleBehaviour = function () {
 
     this.add("string_dquotes", "deletion", function (state, action, editor, session, range) {
         var selected = session.doc.getTextRange(range);
-        if (!range.isMultiLine() && selected == '"') {
+        if (!range.isMultiLine() && (selected == '"' || selected == "'")) {
             var line = session.doc.getLine(range.start.row);
             var rightChar = line.substring(range.start.column + 1, range.start.column + 2);
             if (rightChar == '"') {
@@ -1072,7 +989,8 @@ var CstyleBehaviour = function () {
         }
     });
 
-}
+};
+
 oop.inherits(CstyleBehaviour, Behaviour);
 
 exports.CstyleBehaviour = CstyleBehaviour;
@@ -1283,13 +1201,3 @@ var FoldMode = exports.FoldMode = function() {};
 }).call(FoldMode.prototype);
 
 });
-;
-            (function() {
-                window.require(["ace/ace"], function(a) {
-                    if (!window.ace)
-                        window.ace = {};
-                    for (var key in a) if (a.hasOwnProperty(key))
-                        ace[key] = a[key];
-                });
-            })();
-        
\ No newline at end of file
diff --git a/apps/files_texteditor/js/aceeditor/mode-javascript.js b/apps/files_texteditor/js/aceeditor/mode-javascript.js
index 2f242387fff09048e5e0f9ca8195fd5c0c3ec6fb..a456dad386b8e7dc42bac5723c41bb489bcd4756 100644
--- a/apps/files_texteditor/js/aceeditor/mode-javascript.js
+++ b/apps/files_texteditor/js/aceeditor/mode-javascript.js
@@ -1 +1 @@
-define("ace/mode/javascript",["require","exports","module","ace/lib/oop","ace/mode/text","ace/tokenizer","ace/mode/javascript_highlight_rules","ace/mode/matching_brace_outdent","ace/range","ace/worker/worker_client","ace/mode/behaviour/cstyle","ace/mode/folding/cstyle"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("./text").Mode,f=a("../tokenizer").Tokenizer,g=a("./javascript_highlight_rules").JavaScriptHighlightRules,h=a("./matching_brace_outdent").MatchingBraceOutdent,i=a("../range").Range,j=a("../worker/worker_client").WorkerClient,k=a("./behaviour/cstyle").CstyleBehaviour,l=a("./folding/cstyle").FoldMode,m=function(){this.$tokenizer=new f((new g).getRules()),this.$outdent=new h,this.$behaviour=new k,this.foldingRules=new l};d.inherits(m,e),function(){this.toggleCommentLines=function(a,b,c,d){var e=!0,f=/^(\s*)\/\//;for(var g=c;g<=d;g++)if(!f.test(b.getLine(g))){e=!1;break}if(e){var h=new i(0,0,0,0);for(var g=c;g<=d;g++){var j=b.getLine(g),k=j.match(f);h.start.row=g,h.end.row=g,h.end.column=k[0].length,b.replace(h,k[1])}}else b.indentRows(c,d,"//")},this.getNextLineIndent=function(a,b,c){var d=this.$getIndent(b),e=this.$tokenizer.getLineTokens(b,a),f=e.tokens,g=e.state;if(f.length&&f[f.length-1].type=="comment")return d;if(a=="start"||a=="regex_allowed"){var h=b.match(/^.*(?:\bcase\b.*\:|[\{\(\[])\s*$/);h&&(d+=c)}else if(a=="doc-start"){if(g=="start"||a=="regex_allowed")return"";var h=b.match(/^\s*(\/?)\*/);h&&(h[1]&&(d+=" "),d+="* ")}return d},this.checkOutdent=function(a,b,c){return this.$outdent.checkOutdent(b,c)},this.autoOutdent=function(a,b,c){this.$outdent.autoOutdent(b,c)},this.createWorker=function(a){var b=new j(["ace"],"worker-javascript.js","ace/mode/javascript_worker","JavaScriptWorker");return b.attachToDocument(a.getDocument()),b.on("jslint",function(b){var c=[];for(var d=0;d<b.data.length;d++){var e=b.data[d];e&&c.push({row:e.line-1,column:e.character-1,text:e.reason,type:"warning",lint:e})}a.setAnnotations(c)}),b.on("narcissus",function(b){a.setAnnotations([b.data])}),b.on("terminate",function(){a.clearAnnotations()}),b}}.call(m.prototype),b.Mode=m}),define("ace/mode/javascript_highlight_rules",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/unicode","ace/mode/doc_comment_highlight_rules","ace/mode/text_highlight_rules"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("../lib/lang"),f=a("../unicode"),g=a("./doc_comment_highlight_rules").DocCommentHighlightRules,h=a("./text_highlight_rules").TextHighlightRules,i=function(){var a=e.arrayToMap("Array|Boolean|Date|Function|Iterator|Number|Object|RegExp|String|Proxy|Namespace|QName|XML|XMLList|ArrayBuffer|Float32Array|Float64Array|Int16Array|Int32Array|Int8Array|Uint16Array|Uint32Array|Uint8Array|Uint8ClampedArray|Error|EvalError|InternalError|RangeError|ReferenceError|StopIteration|SyntaxError|TypeError|URIError|decodeURI|decodeURIComponent|encodeURI|encodeURIComponent|eval|isFinite|isNaN|parseFloat|parseInt|JSON|Math|this|arguments|prototype|window|document".split("|")),b=e.arrayToMap("break|case|catch|continue|default|delete|do|else|finally|for|function|if|in|instanceof|new|return|switch|throw|try|typeof|let|var|while|with|const|yield|import|get|set".split("|")),c="case|do|else|finally|in|instanceof|return|throw|try|typeof|yield",d=e.arrayToMap("__parent__|__count__|escape|unescape|with|__proto__".split("|")),h=e.arrayToMap("const|let|var|function".split("|")),i=e.arrayToMap("null|Infinity|NaN|undefined".split("|")),j=e.arrayToMap("class|enum|extends|super|export|implements|private|public|interface|package|protected|static".split("|")),k="["+f.packages.L+"\\$_]["+f.packages.L+f.packages.Mn+f.packages.Mc+f.packages.Nd+f.packages.Pc+"\\$_]*\\b";this.$rules={start:[{token:"comment",regex:"\\/\\/.*$"},(new g).getStartRule("doc-start"),{token:"comment",merge:!0,regex:"\\/\\*",next:"comment"},{token:"string",regex:'["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'},{token:"string",merge:!0,regex:'["].*\\\\$',next:"qqstring"},{token:"string",regex:"['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"},{token:"string",merge:!0,regex:"['].*\\\\$",next:"qstring"},{token:"constant.numeric",regex:"0[xX][0-9a-fA-F]+\\b"},{token:"constant.numeric",regex:"[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"},{token:["keyword.definition","text","entity.name.function"],regex:"(function)(\\s+)("+k+")"},{token:"constant.language.boolean",regex:"(?:true|false)\\b"},{token:"keyword",regex:"(?:"+c+")\\b",next:"regex_allowed"},{token:function(c){return a.hasOwnProperty(c)?"variable.language":d.hasOwnProperty(c)?"invalid.deprecated":h.hasOwnProperty(c)?"keyword.definition":b.hasOwnProperty(c)?"keyword":i.hasOwnProperty(c)?"constant.language":j.hasOwnProperty(c)?"invalid.illegal":c=="debugger"?"invalid.deprecated":"identifier"},regex:k},{token:"keyword.operator",regex:"!|\\$|%|&|\\*|\\-\\-|\\-|\\+\\+|\\+|~|===|==|=|!=|!==|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\\|\\||\\?\\:|\\*=|%=|\\+=|\\-=|&=|\\^=|\\b(?:in|instanceof|new|delete|typeof|void)",next:"regex_allowed"},{token:"punctuation.operator",regex:"\\?|\\:|\\,|\\;|\\.",next:"regex_allowed"},{token:"paren.lparen",regex:"[[({]",next:"regex_allowed"},{token:"paren.rparen",regex:"[\\])}]"},{token:"keyword.operator",regex:"\\/=?",next:"regex_allowed"},{token:"comment",regex:"^#!.*$"},{token:"text",regex:"\\s+"}],regex_allowed:[{token:"comment",merge:!0,regex:"\\/\\*",next:"comment_regex_allowed"},{token:"comment",regex:"\\/\\/.*$"},{token:"string.regexp",regex:"\\/",next:"regex",merge:!0},{token:"text",regex:"\\s+"},{token:"empty",regex:"",next:"start"}],regex:[{token:"regexp.keyword.operator",regex:"\\\\(?:u[\\da-fA-F]{4}|x[\\da-fA-F]{2}|.)",next:"regex"},{token:"string.regexp",regex:"/\\w*",next:"start",merge:!0},{token:"string.regexp",regex:"[^\\\\/\\[]+",next:"regex",merge:!0},{token:"string.regexp.charachterclass",regex:"\\[",next:"regex_character_class",merge:!0},{token:"empty",regex:"",next:"start"}],regex_character_class:[{token:"regexp.keyword.operator",regex:"\\\\(?:u[\\da-fA-F]{4}|x[\\da-fA-F]{2}|.)",next:"regex_character_class"},{token:"string.regexp.charachterclass",regex:"]",next:"regex",merge:!0},{token:"string.regexp.charachterclass",regex:"[^\\\\\\]]+",next:"regex_character_class",merge:!0},{token:"empty",regex:"",next:"start"}],comment_regex_allowed:[{token:"comment",regex:".*?\\*\\/",merge:!0,next:"regex_allowed"},{token:"comment",merge:!0,regex:".+"}],comment:[{token:"comment",regex:".*?\\*\\/",merge:!0,next:"start"},{token:"comment",merge:!0,regex:".+"}],qqstring:[{token:"string",regex:'(?:(?:\\\\.)|(?:[^"\\\\]))*?"',next:"start"},{token:"string",merge:!0,regex:".+"}],qstring:[{token:"string",regex:"(?:(?:\\\\.)|(?:[^'\\\\]))*?'",next:"start"},{token:"string",merge:!0,regex:".+"}]},this.embedRules(g,"doc-",[(new g).getEndRule("start")])};d.inherits(i,h),b.JavaScriptHighlightRules=i}),define("ace/mode/doc_comment_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("./text_highlight_rules").TextHighlightRules,f=function(){this.$rules={start:[{token:"comment.doc.tag",regex:"@[\\w\\d_]+"},{token:"comment.doc",merge:!0,regex:"\\s+"},{token:"comment.doc",merge:!0,regex:"TODO"},{token:"comment.doc",merge:!0,regex:"[^@\\*]+"},{token:"comment.doc",merge:!0,regex:"."}]}};d.inherits(f,e),function(){this.getStartRule=function(a){return{token:"comment.doc",merge:!0,regex:"\\/\\*(?=\\*)",next:a}},this.getEndRule=function(a){return{token:"comment.doc",merge:!0,regex:"\\*\\/",next:a}}}.call(f.prototype),b.DocCommentHighlightRules=f}),define("ace/mode/matching_brace_outdent",["require","exports","module","ace/range"],function(a,b,c){"use strict";var d=a("../range").Range,e=function(){};((function(){this.checkOutdent=function(a,b){return/^\s+$/.test(a)?/^\s*\}/.test(b):!1},this.autoOutdent=function(a,b){var c=a.getLine(b),e=c.match(/^(\s*\})/);if(!e)return 0;var f=e[1].length,g=a.findMatchingBracket({row:b,column:f});if(!g||g.row==b)return 0;var h=this.$getIndent(a.getLine(g.row));a.replace(new d(b,0,b,f-1),h)},this.$getIndent=function(a){var b=a.match(/^(\s+)/);return b?b[1]:""}})).call(e.prototype),b.MatchingBraceOutdent=e}),define("ace/worker/worker_client",["require","exports","module","ace/lib/oop","ace/lib/event_emitter"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("../lib/event_emitter").EventEmitter,f=function(b,d,e,f){this.changeListener=this.changeListener.bind(this);if(c.packaged){var g=this.$guessBasePath();this.$worker=new Worker(g+d)}else{var h=this.$normalizePath(a.nameToUrl("ace/worker/worker",null,"_"));this.$worker=new Worker(h);var i={};for(var j=0;j<b.length;j++){var k=b[j],l=this.$normalizePath(a.nameToUrl(k,null,"_").replace(/.js$/,""));i[k]=l}}this.$worker.postMessage({init:!0,tlns:i,module:e,classname:f}),this.callbackId=1,this.callbacks={};var m=this;this.$worker.onerror=function(a){throw window.console&&console.log&&console.log(a),a},this.$worker.onmessage=function(a){var b=a.data;switch(b.type){case"log":window.console&&console.log&&console.log(b.data);break;case"event":m._emit(b.name,{data:b.data});break;case"call":var c=m.callbacks[b.id];c&&(c(b.data),delete m.callbacks[b.id])}}};((function(){d.implement(this,e),this.$normalizePath=function(a){return a=a.replace(/^[a-z]+:\/\/[^\/]+\//,""),a=location.protocol+"//"+location.host+(a.charAt(0)=="/"?"":location.pathname.replace(/\/[^\/]*$/,""))+"/"+a.replace(/^[\/]+/,""),a},this.$guessBasePath=function(){if(a.aceBaseUrl)return a.aceBaseUrl;var b=document.getElementsByTagName("script");for(var c=0;c<b.length;c++){var d=b[c],e=d.getAttribute("data-ace-base");if(e)return e.replace(/\/*$/,"/");var f=d.src||d.getAttribute("src");if(!f)continue;var g=f.match(/^(?:(.*\/)ace\.js|(.*\/)ace(-uncompressed)?(-noconflict)?\.js)(?:\?|$)/);if(g)return g[1]||g[2]}return""},this.terminate=function(){this._emit("terminate",{}),this.$worker.terminate(),this.$worker=null,this.$doc.removeEventListener("change",this.changeListener),this.$doc=null},this.send=function(a,b){this.$worker.postMessage({command:a,args:b})},this.call=function(a,b,c){if(c){var d=this.callbackId++;this.callbacks[d]=c,b.push(d)}this.send(a,b)},this.emit=function(a,b){try{this.$worker.postMessage({event:a,data:{data:b.data}})}catch(c){}},this.attachToDocument=function(a){this.$doc&&this.terminate(),this.$doc=a,this.call("setValue",[a.getValue()]),a.on("change",this.changeListener)},this.changeListener=function(a){a.range={start:a.data.range.start,end:a.data.range.end},this.emit("change",a)}})).call(f.prototype),b.WorkerClient=f}),define("ace/mode/behaviour/cstyle",["require","exports","module","ace/lib/oop","ace/mode/behaviour"],function(a,b,c){"use strict";var d=a("../../lib/oop"),e=a("../behaviour").Behaviour,f=function(){this.add("braces","insertion",function(a,b,c,d,e){if(e=="{"){var f=c.getSelectionRange(),g=d.doc.getTextRange(f);return g!==""?{text:"{"+g+"}",selection:!1}:{text:"{}",selection:[1,1]}}if(e=="}"){var h=c.getCursorPosition(),i=d.doc.getLine(h.row),j=i.substring(h.column,h.column+1);if(j=="}"){var k=d.$findOpeningBracket("}",{column:h.column+1,row:h.row});if(k!==null)return{text:"",selection:[1,1]}}}else if(e=="\n"){var h=c.getCursorPosition(),i=d.doc.getLine(h.row),j=i.substring(h.column,h.column+1);if(j=="}"){var l=d.findMatchingBracket({row:h.row,column:h.column+1});if(!l)return null;var m=this.getNextLineIndent(a,i.substring(0,i.length-1),d.getTabString()),n=this.$getIndent(d.doc.getLine(l.row));return{text:"\n"+m+"\n"+n,selection:[1,m.length,1,m.length]}}}}),this.add("braces","deletion",function(a,b,c,d,e){var f=d.doc.getTextRange(e);if(!e.isMultiLine()&&f=="{"){var g=d.doc.getLine(e.start.row),h=g.substring(e.end.column,e.end.column+1);if(h=="}")return e.end.column++,e}}),this.add("parens","insertion",function(a,b,c,d,e){if(e=="("){var f=c.getSelectionRange(),g=d.doc.getTextRange(f);return g!==""?{text:"("+g+")",selection:!1}:{text:"()",selection:[1,1]}}if(e==")"){var h=c.getCursorPosition(),i=d.doc.getLine(h.row),j=i.substring(h.column,h.column+1);if(j==")"){var k=d.$findOpeningBracket(")",{column:h.column+1,row:h.row});if(k!==null)return{text:"",selection:[1,1]}}}}),this.add("parens","deletion",function(a,b,c,d,e){var f=d.doc.getTextRange(e);if(!e.isMultiLine()&&f=="("){var g=d.doc.getLine(e.start.row),h=g.substring(e.start.column+1,e.start.column+2);if(h==")")return e.end.column++,e}}),this.add("string_dquotes","insertion",function(a,b,c,d,e){if(e=='"'){var f=c.getSelectionRange(),g=d.doc.getTextRange(f);if(g!=="")return{text:'"'+g+'"',selection:!1};var h=c.getCursorPosition(),i=d.doc.getLine(h.row),j=i.substring(h.column-1,h.column);if(j=="\\")return null;var k=d.getTokens(f.start.row,f.start.row)[0].tokens,l=0,m,n=-1;for(var o=0;o<k.length;o++){m=k[o],m.type=="string"?n=-1:n<0&&(n=m.value.indexOf('"'));if(m.value.length+l>f.start.column)break;l+=k[o].value.length}if(!m||n<0&&m.type!=="comment"&&(m.type!=="string"||f.start.column!==m.value.length+l-1&&m.value.lastIndexOf('"')===m.value.length-1))return{text:'""',selection:[1,1]};if(m&&m.type==="string"){var p=i.substring(h.column,h.column+1);if(p=='"')return{text:"",selection:[1,1]}}}}),this.add("string_dquotes","deletion",function(a,b,c,d,e){var f=d.doc.getTextRange(e);if(!e.isMultiLine()&&f=='"'){var g=d.doc.getLine(e.start.row),h=g.substring(e.start.column+1,e.start.column+2);if(h=='"')return e.end.column++,e}})};d.inherits(f,e),b.CstyleBehaviour=f}),define("ace/mode/folding/cstyle",["require","exports","module","ace/lib/oop","ace/range","ace/mode/folding/fold_mode"],function(a,b,c){"use strict";var d=a("../../lib/oop"),e=a("../../range").Range,f=a("./fold_mode").FoldMode,g=b.FoldMode=function(){};d.inherits(g,f),function(){this.foldingStartMarker=/(\{|\[)[^\}\]]*$|^\s*(\/\*)/,this.foldingStopMarker=/^[^\[\{]*(\}|\])|^[\s\*]*(\*\/)/,this.getFoldWidgetRange=function(a,b,c){var d=a.getLine(c),f=d.match(this.foldingStartMarker);if(f){var g=f.index;if(f[1])return this.openingBracketBlock(a,f[1],c,g);var h=a.getCommentFoldRange(c,g+f[0].length);return h.end.column-=2,h}if(b!=="markbeginend")return;var f=d.match(this.foldingStopMarker);if(f){var g=f.index+f[0].length;if(f[2]){var h=a.getCommentFoldRange(c,g);return h.end.column-=2,h}var i={row:c,column:g},j=a.$findOpeningBracket(f[1],i);if(!j)return;return j.column++,i.column--,e.fromPoints(j,i)}}}.call(g.prototype)}),define("ace/mode/folding/fold_mode",["require","exports","module","ace/range"],function(a,b,c){"use strict";var d=a("../../range").Range,e=b.FoldMode=function(){};((function(){this.foldingStartMarker=null,this.foldingStopMarker=null,this.getFoldWidget=function(a,b,c){var d=a.getLine(c);return this.foldingStartMarker.test(d)?"start":b=="markbeginend"&&this.foldingStopMarker&&this.foldingStopMarker.test(d)?"end":""},this.getFoldWidgetRange=function(a,b,c){return null},this.indentationBlock=function(a,b,c){var e=/^\s*/,f=b,g=b,h=a.getLine(b),i=c||h.length,j=h.match(e)[0].length,k=a.getLength();while(++b<k){h=a.getLine(b);var l=h.match(e)[0].length;if(l==h.length)continue;if(l<=j)break;g=b}if(g>f){var m=a.getLine(g).length;return new d(f,i,g,m)}},this.openingBracketBlock=function(a,b,c,e){var f={row:c,column:e+1},g=a.$findClosingBracket(b,f);if(!g)return;var h=a.foldWidgets[g.row];return h==null&&(h=this.getFoldWidget(a,g.row)),h=="start"&&(g.row--,g.column=a.getLine(g.row).length),d.fromPoints(f,g)}})).call(e.prototype)}),function(){window.require(["ace/ace"],function(a){window.ace||(window.ace={});for(var b in a)a.hasOwnProperty(b)&&(ace[b]=a[b])})}()
\ No newline at end of file
+define("ace/mode/javascript",["require","exports","module","ace/lib/oop","ace/mode/text","ace/tokenizer","ace/mode/javascript_highlight_rules","ace/mode/matching_brace_outdent","ace/range","ace/worker/worker_client","ace/mode/behaviour/cstyle","ace/mode/folding/cstyle"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("./text").Mode,f=a("../tokenizer").Tokenizer,g=a("./javascript_highlight_rules").JavaScriptHighlightRules,h=a("./matching_brace_outdent").MatchingBraceOutdent,i=a("../range").Range,j=a("../worker/worker_client").WorkerClient,k=a("./behaviour/cstyle").CstyleBehaviour,l=a("./folding/cstyle").FoldMode,m=function(){this.$tokenizer=new f((new g).getRules()),this.$outdent=new h,this.$behaviour=new k,this.foldingRules=new l};d.inherits(m,e),function(){this.toggleCommentLines=function(a,b,c,d){var e=!0,f=/^(\s*)\/\//;for(var g=c;g<=d;g++)if(!f.test(b.getLine(g))){e=!1;break}if(e){var h=new i(0,0,0,0);for(var g=c;g<=d;g++){var j=b.getLine(g),k=j.match(f);h.start.row=g,h.end.row=g,h.end.column=k[0].length,b.replace(h,k[1])}}else b.indentRows(c,d,"//")},this.getNextLineIndent=function(a,b,c){var d=this.$getIndent(b),e=this.$tokenizer.getLineTokens(b,a),f=e.tokens,g=e.state;if(f.length&&f[f.length-1].type=="comment")return d;if(a=="start"||a=="regex_allowed"){var h=b.match(/^.*(?:\bcase\b.*\:|[\{\(\[])\s*$/);h&&(d+=c)}else if(a=="doc-start"){if(g=="start"||a=="regex_allowed")return"";var h=b.match(/^\s*(\/?)\*/);h&&(h[1]&&(d+=" "),d+="* ")}return d},this.checkOutdent=function(a,b,c){return this.$outdent.checkOutdent(b,c)},this.autoOutdent=function(a,b,c){this.$outdent.autoOutdent(b,c)},this.createWorker=function(a){var b=new j(["ace"],"worker-javascript.js","ace/mode/javascript_worker","JavaScriptWorker");return b.attachToDocument(a.getDocument()),b.on("jslint",function(b){var c=[];for(var d=0;d<b.data.length;d++){var e=b.data[d];e&&c.push({row:e.line-1,column:e.character-1,text:e.reason,type:"warning",lint:e})}a.setAnnotations(c)}),b.on("narcissus",function(b){a.setAnnotations([b.data])}),b.on("terminate",function(){a.clearAnnotations()}),b}}.call(m.prototype),b.Mode=m}),define("ace/mode/javascript_highlight_rules",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/unicode","ace/mode/doc_comment_highlight_rules","ace/mode/text_highlight_rules"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("../lib/lang"),f=a("../unicode"),g=a("./doc_comment_highlight_rules").DocCommentHighlightRules,h=a("./text_highlight_rules").TextHighlightRules,i=function(){var a=e.arrayToMap("Array|Boolean|Date|Function|Iterator|Number|Object|RegExp|String|Proxy|Namespace|QName|XML|XMLList|ArrayBuffer|Float32Array|Float64Array|Int16Array|Int32Array|Int8Array|Uint16Array|Uint32Array|Uint8Array|Uint8ClampedArray|Error|EvalError|InternalError|RangeError|ReferenceError|StopIteration|SyntaxError|TypeError|URIError|decodeURI|decodeURIComponent|encodeURI|encodeURIComponent|eval|isFinite|isNaN|parseFloat|parseInt|JSON|Math|this|arguments|prototype|window|document".split("|")),b=e.arrayToMap("break|case|catch|continue|default|delete|do|else|finally|for|function|if|in|instanceof|new|return|switch|throw|try|typeof|let|var|while|with|const|yield|import|get|set".split("|")),c="case|do|else|finally|in|instanceof|return|throw|try|typeof|yield",d=e.arrayToMap("__parent__|__count__|escape|unescape|with|__proto__".split("|")),h=e.arrayToMap("const|let|var|function".split("|")),i=e.arrayToMap("null|Infinity|NaN|undefined".split("|")),j=e.arrayToMap("class|enum|extends|super|export|implements|private|public|interface|package|protected|static".split("|")),k="["+f.packages.L+"\\$_]["+f.packages.L+f.packages.Mn+f.packages.Mc+f.packages.Nd+f.packages.Pc+"\\$_]*\\b",l="\\\\(?:x[0-9a-fA-F]{2}|u[0-9a-fA-F]{4}|[0-2][0-7]{0,2}|3[0-6][0-7]?|37[0-7]?|[4-7][0-7]?|.)";this.$rules={start:[{token:"comment",regex:/\/\/.*$/},(new g).getStartRule("doc-start"),{token:"comment",merge:!0,regex:/\/\*/,next:"comment"},{token:"string",regex:"'",next:"qstring"},{token:"string",regex:'"',next:"qqstring"},{token:"constant.numeric",regex:/0[xX][0-9a-fA-F]+\b/},{token:"constant.numeric",regex:/[+-]?\d+(?:(?:\.\d*)?(?:[eE][+-]?\d+)?)?\b/},{token:["storage.type","punctuation.operator","support.function","punctuation.operator","entity.name.function","text","keyword.operator","text","storage.type","text","paren.lparen","variable.parameter","paren.rparen"],regex:"("+k+")(\\.)(prototype)(\\.)("+k+")(\\s*)(=)(\\s*)(function)(\\s*)(\\()(.*?)(\\))"},{token:["storage.type","punctuation.operator","support.function","punctuation.operator","entity.name.function","text","keyword.operator","text"],regex:"("+k+")(\\.)(prototype)(\\.)("+k+")(\\s*)(=)(\\s*)"},{token:["storage.type","punctuation.operator","entity.name.function","text","keyword.operator","text","storage.type","text","paren.lparen","variable.parameter","paren.rparen"],regex:"("+k+")(\\.)("+k+")(\\s*)(=)(\\s*)(function)(\\s*)(\\()(.*?)(\\))"},{token:["entity.name.function","text","keyword.operator","text","storage.type","text","paren.lparen","variable.parameter","paren.rparen"],regex:"("+k+")(\\s*)(=)(\\s*)(function)(\\s*)(\\()(.*?)(\\))"},{token:["storage.type","text","entity.name.function","text","paren.lparen","variable.parameter","paren.rparen"],regex:"(function)(\\s+)("+k+")(\\s*)(\\()(.*?)(\\))"},{token:["entity.name.function","text","punctuation.operator","text","storage.type","text","paren.lparen","variable.parameter","paren.rparen"],regex:"("+k+")(\\s*)(:)(\\s*)(function)(\\s*)(\\()(.*?)(\\))"},{token:["text","text","storage.type","text","paren.lparen","variable.parameter","paren.rparen"],regex:"(:)(\\s*)(function)?(\\s*)(\\()([^)]*)(\\))"},{token:"constant.language.boolean",regex:/(?:true|false)\b/},{token:"keyword",regex:"(?:"+c+")\\b",next:"regex_allowed"},{token:["punctuation.operator","support.function"],regex:/(\.)(s(?:h(?:ift|ow(?:Mod(?:elessDialog|alDialog)|Help))|croll(?:X|By(?:Pages|Lines)?|Y|To)?|t(?:opzzzz|rike)|i(?:n|zeToContent|debar|gnText)|ort|u(?:p|b(?:str(?:ing)?)?)|pli(?:ce|t)|e(?:nd|t(?:Re(?:sizable|questHeader)|M(?:i(?:nutes|lliseconds)|onth)|Seconds|Ho(?:tKeys|urs)|Year|Cursor|Time(?:out)?|Interval|ZOptions|Date|UTC(?:M(?:i(?:nutes|lliseconds)|onth)|Seconds|Hours|Date|FullYear)|FullYear|Active)|arch)|qrt|lice|avePreferences|mall)|h(?:ome|andleEvent)|navigate|c(?:har(?:CodeAt|At)|o(?:s|n(?:cat|textual|firm)|mpile)|eil|lear(?:Timeout|Interval)?|a(?:ptureEvents|ll)|reate(?:StyleSheet|Popup|EventObject))|t(?:o(?:GMTString|S(?:tring|ource)|U(?:TCString|pperCase)|Lo(?:caleString|werCase))|est|a(?:n|int(?:Enabled)?))|i(?:s(?:NaN|Finite)|ndexOf|talics)|d(?:isableExternalCapture|ump|etachEvent)|u(?:n(?:shift|taint|escape|watch)|pdateCommands)|j(?:oin|avaEnabled)|p(?:o(?:p|w)|ush|lugins.refresh|a(?:ddings|rse(?:Int|Float)?)|r(?:int|ompt|eference))|e(?:scape|nableExternalCapture|val|lementFromPoint|x(?:p|ec(?:Script|Command)?))|valueOf|UTC|queryCommand(?:State|Indeterm|Enabled|Value)|f(?:i(?:nd|le(?:ModifiedDate|Size|CreatedDate|UpdatedDate)|xed)|o(?:nt(?:size|color)|rward)|loor|romCharCode)|watch|l(?:ink|o(?:ad|g)|astIndexOf)|a(?:sin|nchor|cos|t(?:tachEvent|ob|an(?:2)?)|pply|lert|b(?:s|ort))|r(?:ou(?:nd|teEvents)|e(?:size(?:By|To)|calc|turnValue|place|verse|l(?:oad|ease(?:Capture|Events)))|andom)|g(?:o|et(?:ResponseHeader|M(?:i(?:nutes|lliseconds)|onth)|Se(?:conds|lection)|Hours|Year|Time(?:zoneOffset)?|Da(?:y|te)|UTC(?:M(?:i(?:nutes|lliseconds)|onth)|Seconds|Hours|Da(?:y|te)|FullYear)|FullYear|A(?:ttention|llResponseHeaders)))|m(?:in|ove(?:B(?:y|elow)|To(?:Absolute)?|Above)|ergeAttributes|a(?:tch|rgins|x))|b(?:toa|ig|o(?:ld|rderWidths)|link|ack))\b(?=\()/},{token:["punctuation.operator","support.function.dom"],regex:/(\.)(s(?:ub(?:stringData|mit)|plitText|e(?:t(?:NamedItem|Attribute(?:Node)?)|lect))|has(?:ChildNodes|Feature)|namedItem|c(?:l(?:ick|o(?:se|neNode))|reate(?:C(?:omment|DATASection|aption)|T(?:Head|extNode|Foot)|DocumentFragment|ProcessingInstruction|E(?:ntityReference|lement)|Attribute))|tabIndex|i(?:nsert(?:Row|Before|Cell|Data)|tem)|open|delete(?:Row|C(?:ell|aption)|T(?:Head|Foot)|Data)|focus|write(?:ln)?|a(?:dd|ppend(?:Child|Data))|re(?:set|place(?:Child|Data)|move(?:NamedItem|Child|Attribute(?:Node)?)?)|get(?:NamedItem|Element(?:sBy(?:Name|TagName)|ById)|Attribute(?:Node)?)|blur)\b(?=\()/},{token:["punctuation.operator","support.constant"],regex:/(\.)(s(?:ystemLanguage|cr(?:ipts|ollbars|een(?:X|Y|Top|Left))|t(?:yle(?:Sheets)?|atus(?:Text|bar)?)|ibling(?:Below|Above)|ource|uffixes|e(?:curity(?:Policy)?|l(?:ection|f)))|h(?:istory|ost(?:name)?|as(?:h|Focus))|y|X(?:MLDocument|SLDocument)|n(?:ext|ame(?:space(?:s|URI)|Prop))|M(?:IN_VALUE|AX_VALUE)|c(?:haracterSet|o(?:n(?:structor|trollers)|okieEnabled|lorDepth|mp(?:onents|lete))|urrent|puClass|l(?:i(?:p(?:boardData)?|entInformation)|osed|asses)|alle(?:e|r)|rypto)|t(?:o(?:olbar|p)|ext(?:Transform|Indent|Decoration|Align)|ags)|SQRT(?:1_2|2)|i(?:n(?:ner(?:Height|Width)|put)|ds|gnoreCase)|zIndex|o(?:scpu|n(?:readystatechange|Line)|uter(?:Height|Width)|p(?:sProfile|ener)|ffscreenBuffering)|NEGATIVE_INFINITY|d(?:i(?:splay|alog(?:Height|Top|Width|Left|Arguments)|rectories)|e(?:scription|fault(?:Status|Ch(?:ecked|arset)|View)))|u(?:ser(?:Profile|Language|Agent)|n(?:iqueID|defined)|pdateInterval)|_content|p(?:ixelDepth|ort|ersonalbar|kcs11|l(?:ugins|atform)|a(?:thname|dding(?:Right|Bottom|Top|Left)|rent(?:Window|Layer)?|ge(?:X(?:Offset)?|Y(?:Offset)?))|r(?:o(?:to(?:col|type)|duct(?:Sub)?|mpter)|e(?:vious|fix)))|e(?:n(?:coding|abledPlugin)|x(?:ternal|pando)|mbeds)|v(?:isibility|endor(?:Sub)?|Linkcolor)|URLUnencoded|P(?:I|OSITIVE_INFINITY)|f(?:ilename|o(?:nt(?:Size|Family|Weight)|rmName)|rame(?:s|Element)|gColor)|E|whiteSpace|l(?:i(?:stStyleType|n(?:eHeight|kColor))|o(?:ca(?:tion(?:bar)?|lName)|wsrc)|e(?:ngth|ft(?:Context)?)|a(?:st(?:M(?:odified|atch)|Index|Paren)|yer(?:s|X)|nguage))|a(?:pp(?:MinorVersion|Name|Co(?:deName|re)|Version)|vail(?:Height|Top|Width|Left)|ll|r(?:ity|guments)|Linkcolor|bove)|r(?:ight(?:Context)?|e(?:sponse(?:XML|Text)|adyState))|global|x|m(?:imeTypes|ultiline|enubar|argin(?:Right|Bottom|Top|Left))|L(?:N(?:10|2)|OG(?:10E|2E))|b(?:o(?:ttom|rder(?:Width|RightWidth|BottomWidth|Style|Color|TopWidth|LeftWidth))|ufferDepth|elow|ackground(?:Color|Image)))\b/},{token:["storage.type","punctuation.operator","support.function.firebug"],regex:/(console)(\.)(warn|info|log|error|time|timeEnd|assert)\b/},{token:function(c){return a.hasOwnProperty(c)?"variable.language":d.hasOwnProperty(c)?"invalid.deprecated":h.hasOwnProperty(c)?"storage.type":b.hasOwnProperty(c)?"keyword":i.hasOwnProperty(c)?"constant.language":j.hasOwnProperty(c)?"invalid.illegal":c=="debugger"?"invalid.deprecated":"identifier"},regex:k},{token:"keyword.operator",regex:/!|\$|%|&|\*|\-\-|\-|\+\+|\+|~|===|==|=|!=|!==|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\|\||\?\:|\*=|%=|\+=|\-=|&=|\^=|\b(?:in|instanceof|new|delete|typeof|void)/,next:"regex_allowed"},{token:"punctuation.operator",regex:/\?|\:|\,|\;|\./,next:"regex_allowed"},{token:"paren.lparen",regex:/[\[({]/,next:"regex_allowed"},{token:"paren.rparen",regex:/[\])}]/},{token:"keyword.operator",regex:/\/=?/,next:"regex_allowed"},{token:"comment",regex:/^#!.*$/},{token:"text",regex:/\s+/}],regex_allowed:[{token:"comment",merge:!0,regex:"\\/\\*",next:"comment_regex_allowed"},{token:"comment",regex:"\\/\\/.*$"},{token:"string.regexp",regex:"\\/",next:"regex",merge:!0},{token:"text",regex:"\\s+"},{token:"empty",regex:"",next:"start"}],regex:[{token:"regexp.keyword.operator",regex:"\\\\(?:u[\\da-fA-F]{4}|x[\\da-fA-F]{2}|.)",next:"regex"},{token:"string.regexp",regex:"/\\w*",next:"start",merge:!0},{token:"string.regexp",regex:"[^\\\\/\\[]+",next:"regex",merge:!0},{token:"string.regexp.charachterclass",regex:"\\[",next:"regex_character_class",merge:!0},{token:"empty",regex:"",next:"start"}],regex_character_class:[{token:"regexp.keyword.operator",regex:"\\\\(?:u[\\da-fA-F]{4}|x[\\da-fA-F]{2}|.)",next:"regex_character_class"},{token:"string.regexp.charachterclass",regex:"]",next:"regex",merge:!0},{token:"string.regexp.charachterclass",regex:"[^\\\\\\]]+",next:"regex_character_class",merge:!0},{token:"empty",regex:"",next:"start"}],comment_regex_allowed:[{token:"comment",regex:".*?\\*\\/",merge:!0,next:"regex_allowed"},{token:"comment",merge:!0,regex:".+"}],comment:[{token:"comment",regex:".*?\\*\\/",merge:!0,next:"start"},{token:"comment",merge:!0,regex:".+"}],qqstring:[{token:"constant.language.escape",regex:l},{token:"string",regex:'[^"\\\\]+'},{token:"string",regex:'"',next:"start"}],qstring:[{token:"constant.language.escape",regex:l},{token:"string",regex:"[^'\\\\]+"},{token:"string",regex:"'",next:"start"}]},this.embedRules(g,"doc-",[(new g).getEndRule("start")])};d.inherits(i,h),b.JavaScriptHighlightRules=i}),define("ace/mode/doc_comment_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("./text_highlight_rules").TextHighlightRules,f=function(){this.$rules={start:[{token:"comment.doc.tag",regex:"@[\\w\\d_]+"},{token:"comment.doc",merge:!0,regex:"\\s+"},{token:"comment.doc",merge:!0,regex:"TODO"},{token:"comment.doc",merge:!0,regex:"[^@\\*]+"},{token:"comment.doc",merge:!0,regex:"."}]}};d.inherits(f,e),function(){this.getStartRule=function(a){return{token:"comment.doc",merge:!0,regex:"\\/\\*(?=\\*)",next:a}},this.getEndRule=function(a){return{token:"comment.doc",merge:!0,regex:"\\*\\/",next:a}}}.call(f.prototype),b.DocCommentHighlightRules=f}),define("ace/mode/matching_brace_outdent",["require","exports","module","ace/range"],function(a,b,c){"use strict";var d=a("../range").Range,e=function(){};(function(){this.checkOutdent=function(a,b){return/^\s+$/.test(a)?/^\s*\}/.test(b):!1},this.autoOutdent=function(a,b){var c=a.getLine(b),e=c.match(/^(\s*\})/);if(!e)return 0;var f=e[1].length,g=a.findMatchingBracket({row:b,column:f});if(!g||g.row==b)return 0;var h=this.$getIndent(a.getLine(g.row));a.replace(new d(b,0,b,f-1),h)},this.$getIndent=function(a){var b=a.match(/^(\s+)/);return b?b[1]:""}}).call(e.prototype),b.MatchingBraceOutdent=e}),define("ace/mode/behaviour/cstyle",["require","exports","module","ace/lib/oop","ace/mode/behaviour"],function(a,b,c){"use strict";var d=a("../../lib/oop"),e=a("../behaviour").Behaviour,f=function(){this.add("braces","insertion",function(a,b,c,d,e){if(e=="{"){var f=c.getSelectionRange(),g=d.doc.getTextRange(f);return g!==""?{text:"{"+g+"}",selection:!1}:{text:"{}",selection:[1,1]}}if(e=="}"){var h=c.getCursorPosition(),i=d.doc.getLine(h.row),j=i.substring(h.column,h.column+1);if(j=="}"){var k=d.$findOpeningBracket("}",{column:h.column+1,row:h.row});if(k!==null)return{text:"",selection:[1,1]}}}else if(e=="\n"){var h=c.getCursorPosition(),i=d.doc.getLine(h.row),j=i.substring(h.column,h.column+1);if(j=="}"){var l=d.findMatchingBracket({row:h.row,column:h.column+1});if(!l)return null;var m=this.getNextLineIndent(a,i.substring(0,i.length-1),d.getTabString()),n=this.$getIndent(d.doc.getLine(l.row));return{text:"\n"+m+"\n"+n,selection:[1,m.length,1,m.length]}}}}),this.add("braces","deletion",function(a,b,c,d,e){var f=d.doc.getTextRange(e);if(!e.isMultiLine()&&f=="{"){var g=d.doc.getLine(e.start.row),h=g.substring(e.end.column,e.end.column+1);if(h=="}")return e.end.column++,e}}),this.add("parens","insertion",function(a,b,c,d,e){if(e=="("){var f=c.getSelectionRange(),g=d.doc.getTextRange(f);return g!==""?{text:"("+g+")",selection:!1}:{text:"()",selection:[1,1]}}if(e==")"){var h=c.getCursorPosition(),i=d.doc.getLine(h.row),j=i.substring(h.column,h.column+1);if(j==")"){var k=d.$findOpeningBracket(")",{column:h.column+1,row:h.row});if(k!==null)return{text:"",selection:[1,1]}}}}),this.add("parens","deletion",function(a,b,c,d,e){var f=d.doc.getTextRange(e);if(!e.isMultiLine()&&f=="("){var g=d.doc.getLine(e.start.row),h=g.substring(e.start.column+1,e.start.column+2);if(h==")")return e.end.column++,e}}),this.add("string_dquotes","insertion",function(a,b,c,d,e){if(e=='"'||e=="'"){var f=e,g=c.getSelectionRange(),h=d.doc.getTextRange(g);if(h!=="")return{text:f+h+f,selection:!1};var i=c.getCursorPosition(),j=d.doc.getLine(i.row),k=j.substring(i.column-1,i.column);if(k=="\\")return null;var l=d.getTokens(g.start.row,g.start.row)[0].tokens,m=0,n,o=-1;for(var p=0;p<l.length;p++){n=l[p],n.type=="string"?o=-1:o<0&&(o=n.value.indexOf(f));if(n.value.length+m>g.start.column)break;m+=l[p].value.length}if(!n||o<0&&n.type!=="comment"&&(n.type!=="string"||g.start.column!==n.value.length+m-1&&n.value.lastIndexOf(f)===n.value.length-1))return{text:f+f,selection:[1,1]};if(n&&n.type==="string"){var q=j.substring(i.column,i.column+1);if(q==f)return{text:"",selection:[1,1]}}}}),this.add("string_dquotes","deletion",function(a,b,c,d,e){var f=d.doc.getTextRange(e);if(!e.isMultiLine()&&(f=='"'||f=="'")){var g=d.doc.getLine(e.start.row),h=g.substring(e.start.column+1,e.start.column+2);if(h=='"')return e.end.column++,e}})};d.inherits(f,e),b.CstyleBehaviour=f}),define("ace/mode/folding/cstyle",["require","exports","module","ace/lib/oop","ace/range","ace/mode/folding/fold_mode"],function(a,b,c){"use strict";var d=a("../../lib/oop"),e=a("../../range").Range,f=a("./fold_mode").FoldMode,g=b.FoldMode=function(){};d.inherits(g,f),function(){this.foldingStartMarker=/(\{|\[)[^\}\]]*$|^\s*(\/\*)/,this.foldingStopMarker=/^[^\[\{]*(\}|\])|^[\s\*]*(\*\/)/,this.getFoldWidgetRange=function(a,b,c){var d=a.getLine(c),f=d.match(this.foldingStartMarker);if(f){var g=f.index;if(f[1])return this.openingBracketBlock(a,f[1],c,g);var h=a.getCommentFoldRange(c,g+f[0].length);return h.end.column-=2,h}if(b!=="markbeginend")return;var f=d.match(this.foldingStopMarker);if(f){var g=f.index+f[0].length;if(f[2]){var h=a.getCommentFoldRange(c,g);return h.end.column-=2,h}var i={row:c,column:g},j=a.$findOpeningBracket(f[1],i);if(!j)return;return j.column++,i.column--,e.fromPoints(j,i)}}}.call(g.prototype)}),define("ace/mode/folding/fold_mode",["require","exports","module","ace/range"],function(a,b,c){"use strict";var d=a("../../range").Range,e=b.FoldMode=function(){};(function(){this.foldingStartMarker=null,this.foldingStopMarker=null,this.getFoldWidget=function(a,b,c){var d=a.getLine(c);return this.foldingStartMarker.test(d)?"start":b=="markbeginend"&&this.foldingStopMarker&&this.foldingStopMarker.test(d)?"end":""},this.getFoldWidgetRange=function(a,b,c){return null},this.indentationBlock=function(a,b,c){var e=/^\s*/,f=b,g=b,h=a.getLine(b),i=c||h.length,j=h.match(e)[0].length,k=a.getLength();while(++b<k){h=a.getLine(b);var l=h.match(e)[0].length;if(l==h.length)continue;if(l<=j)break;g=b}if(g>f){var m=a.getLine(g).length;return new d(f,i,g,m)}},this.openingBracketBlock=function(a,b,c,e){var f={row:c,column:e+1},g=a.$findClosingBracket(b,f);if(!g)return;var h=a.foldWidgets[g.row];return h==null&&(h=this.getFoldWidget(a,g.row)),h=="start"&&(g.row--,g.column=a.getLine(g.row).length),d.fromPoints(f,g)}}).call(e.prototype)})
\ No newline at end of file
diff --git a/apps/files_texteditor/js/aceeditor/mode-json-uncompressed.js b/apps/files_texteditor/js/aceeditor/mode-json-uncompressed.js
old mode 100755
new mode 100644
index 19dc612ab3e9327c1fee96e2bb7c7ad0b8b9aa7b..22399889f3e2bda2dad2c7a768de2e69808acdbb
--- a/apps/files_texteditor/js/aceeditor/mode-json-uncompressed.js
+++ b/apps/files_texteditor/js/aceeditor/mode-json-uncompressed.js
@@ -35,7 +35,7 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
-define('ace/mode/json', ['require', 'exports', 'module' , 'ace/lib/oop', 'ace/mode/text', 'ace/tokenizer', 'ace/mode/json_highlight_rules', 'ace/mode/matching_brace_outdent', 'ace/mode/behaviour/cstyle', 'ace/mode/folding/cstyle'], function(require, exports, module) {
+define('ace/mode/json', ['require', 'exports', 'module' , 'ace/lib/oop', 'ace/mode/text', 'ace/tokenizer', 'ace/mode/json_highlight_rules', 'ace/mode/matching_brace_outdent', 'ace/mode/behaviour/cstyle', 'ace/mode/folding/cstyle', 'ace/worker/worker_client'], function(require, exports, module) {
 "use strict";
 
 var oop = require("../lib/oop");
@@ -45,6 +45,7 @@ var HighlightRules = require("./json_highlight_rules").JsonHighlightRules;
 var MatchingBraceOutdent = require("./matching_brace_outdent").MatchingBraceOutdent;
 var CstyleBehaviour = require("./behaviour/cstyle").CstyleBehaviour;
 var CStyleFoldMode = require("./folding/cstyle").FoldMode;
+var WorkerClient = require("../worker/worker_client").WorkerClient;
 
 var Mode = function() {
     this.$tokenizer = new Tokenizer(new HighlightRules().getRules());
@@ -76,7 +77,23 @@ oop.inherits(Mode, TextMode);
     this.autoOutdent = function(state, doc, row) {
         this.$outdent.autoOutdent(doc, row);
     };
-    
+
+    this.createWorker = function(session) {
+        var worker = new WorkerClient(["ace"], "worker-json.js", "ace/mode/json_worker", "JsonWorker");
+        worker.attachToDocument(session.getDocument());
+
+        worker.on("error", function(e) {
+            session.setAnnotations([e.data]);
+        });
+
+        worker.on("ok", function() {
+            session.clearAnnotations();
+        });
+
+        return worker;
+    };
+
+
 }).call(Mode.prototype);
 
 exports.Mode = Mode;
@@ -302,12 +319,12 @@ var CstyleBehaviour = function () {
                 return {
                     text: '{' + selected + '}',
                     selection: false
-                }
+                };
             } else {
                 return {
                     text: '{}',
                     selection: [1, 1]
-                }
+                };
             }
         } else if (text == '}') {
             var cursor = editor.getCursorPosition();
@@ -319,7 +336,7 @@ var CstyleBehaviour = function () {
                     return {
                         text: '',
                         selection: [1, 1]
-                    }
+                    };
                 }
             }
         } else if (text == "\n") {
@@ -337,7 +354,7 @@ var CstyleBehaviour = function () {
                 return {
                     text: '\n' + indent + '\n' + next_indent,
                     selection: [1, indent.length, 1, indent.length]
-                }
+                };
             }
         }
     });
@@ -362,12 +379,12 @@ var CstyleBehaviour = function () {
                 return {
                     text: '(' + selected + ')',
                     selection: false
-                }
+                };
             } else {
                 return {
                     text: '()',
                     selection: [1, 1]
-                }
+                };
             }
         } else if (text == ')') {
             var cursor = editor.getCursorPosition();
@@ -379,7 +396,7 @@ var CstyleBehaviour = function () {
                     return {
                         text: '',
                         selection: [1, 1]
-                    }
+                    };
                 }
             }
         }
@@ -398,14 +415,15 @@ var CstyleBehaviour = function () {
     });
 
     this.add("string_dquotes", "insertion", function (state, action, editor, session, text) {
-        if (text == '"') {
+        if (text == '"' || text == "'") {
+            var quote = text;
             var selection = editor.getSelectionRange();
             var selected = session.doc.getTextRange(selection);
             if (selected !== "") {
                 return {
-                    text: '"' + selected + '"',
+                    text: quote + selected + quote,
                     selection: false
-                }
+                };
             } else {
                 var cursor = editor.getCursorPosition();
                 var line = session.doc.getLine(cursor.row);
@@ -426,7 +444,7 @@ var CstyleBehaviour = function () {
                     if (token.type == "string") {
                       quotepos = -1;
                     } else if (quotepos < 0) {
-                      quotepos = token.value.indexOf('"');
+                      quotepos = token.value.indexOf(quote);
                     }
                     if ((token.value.length + col) > selection.start.column) {
                         break;
@@ -435,19 +453,19 @@ var CstyleBehaviour = function () {
                 }
 
                 // Try and be smart about when we auto insert.
-                if (!token || (quotepos < 0 && token.type !== "comment" && (token.type !== "string" || ((selection.start.column !== token.value.length+col-1) && token.value.lastIndexOf('"') === token.value.length-1)))) {
+                if (!token || (quotepos < 0 && token.type !== "comment" && (token.type !== "string" || ((selection.start.column !== token.value.length+col-1) && token.value.lastIndexOf(quote) === token.value.length-1)))) {
                     return {
-                        text: '""',
+                        text: quote + quote,
                         selection: [1,1]
-                    }
+                    };
                 } else if (token && token.type === "string") {
                     // Ignore input and move right one if we're typing over the closing quote.
                     var rightChar = line.substring(cursor.column, cursor.column + 1);
-                    if (rightChar == '"') {
+                    if (rightChar == quote) {
                         return {
                             text: '',
                             selection: [1, 1]
-                        }
+                        };
                     }
                 }
             }
@@ -456,7 +474,7 @@ var CstyleBehaviour = function () {
 
     this.add("string_dquotes", "deletion", function (state, action, editor, session, range) {
         var selected = session.doc.getTextRange(range);
-        if (!range.isMultiLine() && selected == '"') {
+        if (!range.isMultiLine() && (selected == '"' || selected == "'")) {
             var line = session.doc.getLine(range.start.row);
             var rightChar = line.substring(range.start.column + 1, range.start.column + 2);
             if (rightChar == '"') {
@@ -466,7 +484,8 @@ var CstyleBehaviour = function () {
         }
     });
 
-}
+};
+
 oop.inherits(CstyleBehaviour, Behaviour);
 
 exports.CstyleBehaviour = CstyleBehaviour;
@@ -677,13 +696,3 @@ var FoldMode = exports.FoldMode = function() {};
 }).call(FoldMode.prototype);
 
 });
-;
-            (function() {
-                window.require(["ace/ace"], function(a) {
-                    if (!window.ace)
-                        window.ace = {};
-                    for (var key in a) if (a.hasOwnProperty(key))
-                        ace[key] = a[key];
-                });
-            })();
-        
\ No newline at end of file
diff --git a/apps/files_texteditor/js/aceeditor/mode-json.js b/apps/files_texteditor/js/aceeditor/mode-json.js
index d0dd59fec3e5096c56d61dde59cb1481a7cd659d..05729db5e66538e028e6b4390a895d8f6d554bba 100644
--- a/apps/files_texteditor/js/aceeditor/mode-json.js
+++ b/apps/files_texteditor/js/aceeditor/mode-json.js
@@ -1 +1 @@
-define("ace/mode/json",["require","exports","module","ace/lib/oop","ace/mode/text","ace/tokenizer","ace/mode/json_highlight_rules","ace/mode/matching_brace_outdent","ace/mode/behaviour/cstyle","ace/mode/folding/cstyle"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("./text").Mode,f=a("../tokenizer").Tokenizer,g=a("./json_highlight_rules").JsonHighlightRules,h=a("./matching_brace_outdent").MatchingBraceOutdent,i=a("./behaviour/cstyle").CstyleBehaviour,j=a("./folding/cstyle").FoldMode,k=function(){this.$tokenizer=new f((new g).getRules()),this.$outdent=new h,this.$behaviour=new i,this.foldingRules=new j};d.inherits(k,e),function(){this.getNextLineIndent=function(a,b,c){var d=this.$getIndent(b);if(a=="start"){var e=b.match(/^.*[\{\(\[]\s*$/);e&&(d+=c)}return d},this.checkOutdent=function(a,b,c){return this.$outdent.checkOutdent(b,c)},this.autoOutdent=function(a,b,c){this.$outdent.autoOutdent(b,c)}}.call(k.prototype),b.Mode=k}),define("ace/mode/json_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("./text_highlight_rules").TextHighlightRules,f=function(){this.$rules={start:[{token:"string",regex:'["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'},{token:"constant.numeric",regex:"0[xX][0-9a-fA-F]+\\b"},{token:"constant.numeric",regex:"[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"},{token:"constant.language.boolean",regex:"(?:true|false)\\b"},{token:"invalid.illegal",regex:"['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"},{token:"invalid.illegal",regex:"\\/\\/.*$"},{token:"paren.lparen",regex:"[[({]"},{token:"paren.rparen",regex:"[\\])}]"},{token:"text",regex:"\\s+"}]}};d.inherits(f,e),b.JsonHighlightRules=f}),define("ace/mode/matching_brace_outdent",["require","exports","module","ace/range"],function(a,b,c){"use strict";var d=a("../range").Range,e=function(){};((function(){this.checkOutdent=function(a,b){return/^\s+$/.test(a)?/^\s*\}/.test(b):!1},this.autoOutdent=function(a,b){var c=a.getLine(b),e=c.match(/^(\s*\})/);if(!e)return 0;var f=e[1].length,g=a.findMatchingBracket({row:b,column:f});if(!g||g.row==b)return 0;var h=this.$getIndent(a.getLine(g.row));a.replace(new d(b,0,b,f-1),h)},this.$getIndent=function(a){var b=a.match(/^(\s+)/);return b?b[1]:""}})).call(e.prototype),b.MatchingBraceOutdent=e}),define("ace/mode/behaviour/cstyle",["require","exports","module","ace/lib/oop","ace/mode/behaviour"],function(a,b,c){"use strict";var d=a("../../lib/oop"),e=a("../behaviour").Behaviour,f=function(){this.add("braces","insertion",function(a,b,c,d,e){if(e=="{"){var f=c.getSelectionRange(),g=d.doc.getTextRange(f);return g!==""?{text:"{"+g+"}",selection:!1}:{text:"{}",selection:[1,1]}}if(e=="}"){var h=c.getCursorPosition(),i=d.doc.getLine(h.row),j=i.substring(h.column,h.column+1);if(j=="}"){var k=d.$findOpeningBracket("}",{column:h.column+1,row:h.row});if(k!==null)return{text:"",selection:[1,1]}}}else if(e=="\n"){var h=c.getCursorPosition(),i=d.doc.getLine(h.row),j=i.substring(h.column,h.column+1);if(j=="}"){var l=d.findMatchingBracket({row:h.row,column:h.column+1});if(!l)return null;var m=this.getNextLineIndent(a,i.substring(0,i.length-1),d.getTabString()),n=this.$getIndent(d.doc.getLine(l.row));return{text:"\n"+m+"\n"+n,selection:[1,m.length,1,m.length]}}}}),this.add("braces","deletion",function(a,b,c,d,e){var f=d.doc.getTextRange(e);if(!e.isMultiLine()&&f=="{"){var g=d.doc.getLine(e.start.row),h=g.substring(e.end.column,e.end.column+1);if(h=="}")return e.end.column++,e}}),this.add("parens","insertion",function(a,b,c,d,e){if(e=="("){var f=c.getSelectionRange(),g=d.doc.getTextRange(f);return g!==""?{text:"("+g+")",selection:!1}:{text:"()",selection:[1,1]}}if(e==")"){var h=c.getCursorPosition(),i=d.doc.getLine(h.row),j=i.substring(h.column,h.column+1);if(j==")"){var k=d.$findOpeningBracket(")",{column:h.column+1,row:h.row});if(k!==null)return{text:"",selection:[1,1]}}}}),this.add("parens","deletion",function(a,b,c,d,e){var f=d.doc.getTextRange(e);if(!e.isMultiLine()&&f=="("){var g=d.doc.getLine(e.start.row),h=g.substring(e.start.column+1,e.start.column+2);if(h==")")return e.end.column++,e}}),this.add("string_dquotes","insertion",function(a,b,c,d,e){if(e=='"'){var f=c.getSelectionRange(),g=d.doc.getTextRange(f);if(g!=="")return{text:'"'+g+'"',selection:!1};var h=c.getCursorPosition(),i=d.doc.getLine(h.row),j=i.substring(h.column-1,h.column);if(j=="\\")return null;var k=d.getTokens(f.start.row,f.start.row)[0].tokens,l=0,m,n=-1;for(var o=0;o<k.length;o++){m=k[o],m.type=="string"?n=-1:n<0&&(n=m.value.indexOf('"'));if(m.value.length+l>f.start.column)break;l+=k[o].value.length}if(!m||n<0&&m.type!=="comment"&&(m.type!=="string"||f.start.column!==m.value.length+l-1&&m.value.lastIndexOf('"')===m.value.length-1))return{text:'""',selection:[1,1]};if(m&&m.type==="string"){var p=i.substring(h.column,h.column+1);if(p=='"')return{text:"",selection:[1,1]}}}}),this.add("string_dquotes","deletion",function(a,b,c,d,e){var f=d.doc.getTextRange(e);if(!e.isMultiLine()&&f=='"'){var g=d.doc.getLine(e.start.row),h=g.substring(e.start.column+1,e.start.column+2);if(h=='"')return e.end.column++,e}})};d.inherits(f,e),b.CstyleBehaviour=f}),define("ace/mode/folding/cstyle",["require","exports","module","ace/lib/oop","ace/range","ace/mode/folding/fold_mode"],function(a,b,c){"use strict";var d=a("../../lib/oop"),e=a("../../range").Range,f=a("./fold_mode").FoldMode,g=b.FoldMode=function(){};d.inherits(g,f),function(){this.foldingStartMarker=/(\{|\[)[^\}\]]*$|^\s*(\/\*)/,this.foldingStopMarker=/^[^\[\{]*(\}|\])|^[\s\*]*(\*\/)/,this.getFoldWidgetRange=function(a,b,c){var d=a.getLine(c),f=d.match(this.foldingStartMarker);if(f){var g=f.index;if(f[1])return this.openingBracketBlock(a,f[1],c,g);var h=a.getCommentFoldRange(c,g+f[0].length);return h.end.column-=2,h}if(b!=="markbeginend")return;var f=d.match(this.foldingStopMarker);if(f){var g=f.index+f[0].length;if(f[2]){var h=a.getCommentFoldRange(c,g);return h.end.column-=2,h}var i={row:c,column:g},j=a.$findOpeningBracket(f[1],i);if(!j)return;return j.column++,i.column--,e.fromPoints(j,i)}}}.call(g.prototype)}),define("ace/mode/folding/fold_mode",["require","exports","module","ace/range"],function(a,b,c){"use strict";var d=a("../../range").Range,e=b.FoldMode=function(){};((function(){this.foldingStartMarker=null,this.foldingStopMarker=null,this.getFoldWidget=function(a,b,c){var d=a.getLine(c);return this.foldingStartMarker.test(d)?"start":b=="markbeginend"&&this.foldingStopMarker&&this.foldingStopMarker.test(d)?"end":""},this.getFoldWidgetRange=function(a,b,c){return null},this.indentationBlock=function(a,b,c){var e=/^\s*/,f=b,g=b,h=a.getLine(b),i=c||h.length,j=h.match(e)[0].length,k=a.getLength();while(++b<k){h=a.getLine(b);var l=h.match(e)[0].length;if(l==h.length)continue;if(l<=j)break;g=b}if(g>f){var m=a.getLine(g).length;return new d(f,i,g,m)}},this.openingBracketBlock=function(a,b,c,e){var f={row:c,column:e+1},g=a.$findClosingBracket(b,f);if(!g)return;var h=a.foldWidgets[g.row];return h==null&&(h=this.getFoldWidget(a,g.row)),h=="start"&&(g.row--,g.column=a.getLine(g.row).length),d.fromPoints(f,g)}})).call(e.prototype)}),function(){window.require(["ace/ace"],function(a){window.ace||(window.ace={});for(var b in a)a.hasOwnProperty(b)&&(ace[b]=a[b])})}()
\ No newline at end of file
+define("ace/mode/json",["require","exports","module","ace/lib/oop","ace/mode/text","ace/tokenizer","ace/mode/json_highlight_rules","ace/mode/matching_brace_outdent","ace/mode/behaviour/cstyle","ace/mode/folding/cstyle","ace/worker/worker_client"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("./text").Mode,f=a("../tokenizer").Tokenizer,g=a("./json_highlight_rules").JsonHighlightRules,h=a("./matching_brace_outdent").MatchingBraceOutdent,i=a("./behaviour/cstyle").CstyleBehaviour,j=a("./folding/cstyle").FoldMode,k=a("../worker/worker_client").WorkerClient,l=function(){this.$tokenizer=new f((new g).getRules()),this.$outdent=new h,this.$behaviour=new i,this.foldingRules=new j};d.inherits(l,e),function(){this.getNextLineIndent=function(a,b,c){var d=this.$getIndent(b);if(a=="start"){var e=b.match(/^.*[\{\(\[]\s*$/);e&&(d+=c)}return d},this.checkOutdent=function(a,b,c){return this.$outdent.checkOutdent(b,c)},this.autoOutdent=function(a,b,c){this.$outdent.autoOutdent(b,c)},this.createWorker=function(a){var b=new k(["ace"],"worker-json.js","ace/mode/json_worker","JsonWorker");return b.attachToDocument(a.getDocument()),b.on("error",function(b){a.setAnnotations([b.data])}),b.on("ok",function(){a.clearAnnotations()}),b}}.call(l.prototype),b.Mode=l}),define("ace/mode/json_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("./text_highlight_rules").TextHighlightRules,f=function(){this.$rules={start:[{token:"string",regex:'["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'},{token:"constant.numeric",regex:"0[xX][0-9a-fA-F]+\\b"},{token:"constant.numeric",regex:"[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"},{token:"constant.language.boolean",regex:"(?:true|false)\\b"},{token:"invalid.illegal",regex:"['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"},{token:"invalid.illegal",regex:"\\/\\/.*$"},{token:"paren.lparen",regex:"[[({]"},{token:"paren.rparen",regex:"[\\])}]"},{token:"text",regex:"\\s+"}]}};d.inherits(f,e),b.JsonHighlightRules=f}),define("ace/mode/matching_brace_outdent",["require","exports","module","ace/range"],function(a,b,c){"use strict";var d=a("../range").Range,e=function(){};(function(){this.checkOutdent=function(a,b){return/^\s+$/.test(a)?/^\s*\}/.test(b):!1},this.autoOutdent=function(a,b){var c=a.getLine(b),e=c.match(/^(\s*\})/);if(!e)return 0;var f=e[1].length,g=a.findMatchingBracket({row:b,column:f});if(!g||g.row==b)return 0;var h=this.$getIndent(a.getLine(g.row));a.replace(new d(b,0,b,f-1),h)},this.$getIndent=function(a){var b=a.match(/^(\s+)/);return b?b[1]:""}}).call(e.prototype),b.MatchingBraceOutdent=e}),define("ace/mode/behaviour/cstyle",["require","exports","module","ace/lib/oop","ace/mode/behaviour"],function(a,b,c){"use strict";var d=a("../../lib/oop"),e=a("../behaviour").Behaviour,f=function(){this.add("braces","insertion",function(a,b,c,d,e){if(e=="{"){var f=c.getSelectionRange(),g=d.doc.getTextRange(f);return g!==""?{text:"{"+g+"}",selection:!1}:{text:"{}",selection:[1,1]}}if(e=="}"){var h=c.getCursorPosition(),i=d.doc.getLine(h.row),j=i.substring(h.column,h.column+1);if(j=="}"){var k=d.$findOpeningBracket("}",{column:h.column+1,row:h.row});if(k!==null)return{text:"",selection:[1,1]}}}else if(e=="\n"){var h=c.getCursorPosition(),i=d.doc.getLine(h.row),j=i.substring(h.column,h.column+1);if(j=="}"){var l=d.findMatchingBracket({row:h.row,column:h.column+1});if(!l)return null;var m=this.getNextLineIndent(a,i.substring(0,i.length-1),d.getTabString()),n=this.$getIndent(d.doc.getLine(l.row));return{text:"\n"+m+"\n"+n,selection:[1,m.length,1,m.length]}}}}),this.add("braces","deletion",function(a,b,c,d,e){var f=d.doc.getTextRange(e);if(!e.isMultiLine()&&f=="{"){var g=d.doc.getLine(e.start.row),h=g.substring(e.end.column,e.end.column+1);if(h=="}")return e.end.column++,e}}),this.add("parens","insertion",function(a,b,c,d,e){if(e=="("){var f=c.getSelectionRange(),g=d.doc.getTextRange(f);return g!==""?{text:"("+g+")",selection:!1}:{text:"()",selection:[1,1]}}if(e==")"){var h=c.getCursorPosition(),i=d.doc.getLine(h.row),j=i.substring(h.column,h.column+1);if(j==")"){var k=d.$findOpeningBracket(")",{column:h.column+1,row:h.row});if(k!==null)return{text:"",selection:[1,1]}}}}),this.add("parens","deletion",function(a,b,c,d,e){var f=d.doc.getTextRange(e);if(!e.isMultiLine()&&f=="("){var g=d.doc.getLine(e.start.row),h=g.substring(e.start.column+1,e.start.column+2);if(h==")")return e.end.column++,e}}),this.add("string_dquotes","insertion",function(a,b,c,d,e){if(e=='"'||e=="'"){var f=e,g=c.getSelectionRange(),h=d.doc.getTextRange(g);if(h!=="")return{text:f+h+f,selection:!1};var i=c.getCursorPosition(),j=d.doc.getLine(i.row),k=j.substring(i.column-1,i.column);if(k=="\\")return null;var l=d.getTokens(g.start.row,g.start.row)[0].tokens,m=0,n,o=-1;for(var p=0;p<l.length;p++){n=l[p],n.type=="string"?o=-1:o<0&&(o=n.value.indexOf(f));if(n.value.length+m>g.start.column)break;m+=l[p].value.length}if(!n||o<0&&n.type!=="comment"&&(n.type!=="string"||g.start.column!==n.value.length+m-1&&n.value.lastIndexOf(f)===n.value.length-1))return{text:f+f,selection:[1,1]};if(n&&n.type==="string"){var q=j.substring(i.column,i.column+1);if(q==f)return{text:"",selection:[1,1]}}}}),this.add("string_dquotes","deletion",function(a,b,c,d,e){var f=d.doc.getTextRange(e);if(!e.isMultiLine()&&(f=='"'||f=="'")){var g=d.doc.getLine(e.start.row),h=g.substring(e.start.column+1,e.start.column+2);if(h=='"')return e.end.column++,e}})};d.inherits(f,e),b.CstyleBehaviour=f}),define("ace/mode/folding/cstyle",["require","exports","module","ace/lib/oop","ace/range","ace/mode/folding/fold_mode"],function(a,b,c){"use strict";var d=a("../../lib/oop"),e=a("../../range").Range,f=a("./fold_mode").FoldMode,g=b.FoldMode=function(){};d.inherits(g,f),function(){this.foldingStartMarker=/(\{|\[)[^\}\]]*$|^\s*(\/\*)/,this.foldingStopMarker=/^[^\[\{]*(\}|\])|^[\s\*]*(\*\/)/,this.getFoldWidgetRange=function(a,b,c){var d=a.getLine(c),f=d.match(this.foldingStartMarker);if(f){var g=f.index;if(f[1])return this.openingBracketBlock(a,f[1],c,g);var h=a.getCommentFoldRange(c,g+f[0].length);return h.end.column-=2,h}if(b!=="markbeginend")return;var f=d.match(this.foldingStopMarker);if(f){var g=f.index+f[0].length;if(f[2]){var h=a.getCommentFoldRange(c,g);return h.end.column-=2,h}var i={row:c,column:g},j=a.$findOpeningBracket(f[1],i);if(!j)return;return j.column++,i.column--,e.fromPoints(j,i)}}}.call(g.prototype)}),define("ace/mode/folding/fold_mode",["require","exports","module","ace/range"],function(a,b,c){"use strict";var d=a("../../range").Range,e=b.FoldMode=function(){};(function(){this.foldingStartMarker=null,this.foldingStopMarker=null,this.getFoldWidget=function(a,b,c){var d=a.getLine(c);return this.foldingStartMarker.test(d)?"start":b=="markbeginend"&&this.foldingStopMarker&&this.foldingStopMarker.test(d)?"end":""},this.getFoldWidgetRange=function(a,b,c){return null},this.indentationBlock=function(a,b,c){var e=/^\s*/,f=b,g=b,h=a.getLine(b),i=c||h.length,j=h.match(e)[0].length,k=a.getLength();while(++b<k){h=a.getLine(b);var l=h.match(e)[0].length;if(l==h.length)continue;if(l<=j)break;g=b}if(g>f){var m=a.getLine(g).length;return new d(f,i,g,m)}},this.openingBracketBlock=function(a,b,c,e){var f={row:c,column:e+1},g=a.$findClosingBracket(b,f);if(!g)return;var h=a.foldWidgets[g.row];return h==null&&(h=this.getFoldWidget(a,g.row)),h=="start"&&(g.row--,g.column=a.getLine(g.row).length),d.fromPoints(f,g)}}).call(e.prototype)})
\ No newline at end of file
diff --git a/apps/files_texteditor/js/aceeditor/mode-latex-uncompressed.js b/apps/files_texteditor/js/aceeditor/mode-latex-uncompressed.js
old mode 100755
new mode 100644
index 864f28d96a9fd7f1bf65577af7931fb0d9614bdd..77c42ab3f9efe7f9b46d4bbaa87d3c9031a2c231
--- a/apps/files_texteditor/js/aceeditor/mode-latex-uncompressed.js
+++ b/apps/files_texteditor/js/aceeditor/mode-latex-uncompressed.js
@@ -93,13 +93,3 @@ oop.inherits(LatexHighlightRules, TextHighlightRules);
 exports.LatexHighlightRules = LatexHighlightRules;
 
 });
-;
-            (function() {
-                window.require(["ace/ace"], function(a) {
-                    if (!window.ace)
-                        window.ace = {};
-                    for (var key in a) if (a.hasOwnProperty(key))
-                        ace[key] = a[key];
-                });
-            })();
-        
\ No newline at end of file
diff --git a/apps/files_texteditor/js/aceeditor/mode-latex.js b/apps/files_texteditor/js/aceeditor/mode-latex.js
old mode 100755
new mode 100644
index 3498213a6441341d72bc903f3a68864cdc8f4e70..e6cfb7cc2f9b0851e70e0492ea53a2f9bae7d58c
--- a/apps/files_texteditor/js/aceeditor/mode-latex.js
+++ b/apps/files_texteditor/js/aceeditor/mode-latex.js
@@ -1 +1 @@
-define("ace/mode/latex",["require","exports","module","ace/lib/oop","ace/mode/text","ace/tokenizer","ace/mode/latex_highlight_rules","ace/range"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("./text").Mode,f=a("../tokenizer").Tokenizer,g=a("./latex_highlight_rules").LatexHighlightRules,h=a("../range").Range,i=function(){this.$tokenizer=new f((new g).getRules())};d.inherits(i,e),function(){this.toggleCommentLines=function(a,b,c,d){var e=!0,f=/^(\s*)\%/;for(var g=c;g<=d;g++)if(!f.test(b.getLine(g))){e=!1;break}if(e){var i=new h(0,0,0,0);for(var g=c;g<=d;g++){var j=b.getLine(g),k=j.match(f);i.start.row=g,i.end.row=g,i.end.column=k[0].length,b.replace(i,k[1])}}else b.indentRows(c,d,"%")},this.getNextLineIndent=function(a,b,c){return this.$getIndent(b)}}.call(i.prototype),b.Mode=i}),define("ace/mode/latex_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("./text_highlight_rules").TextHighlightRules,f=function(){this.$rules={start:[{token:"keyword",regex:"\\\\(?:[^a-zA-Z]|[a-zA-Z]+)"},{token:"lparen",regex:"[[({]"},{token:"rparen",regex:"[\\])}]"},{token:"string",regex:"\\$(?:(?:\\\\.)|(?:[^\\$\\\\]))*?\\$"},{token:"comment",regex:"%.*$"}]}};d.inherits(f,e),b.LatexHighlightRules=f}),function(){window.require(["ace/ace"],function(a){window.ace||(window.ace={});for(var b in a)a.hasOwnProperty(b)&&(ace[b]=a[b])})}()
\ No newline at end of file
+define("ace/mode/latex",["require","exports","module","ace/lib/oop","ace/mode/text","ace/tokenizer","ace/mode/latex_highlight_rules","ace/range"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("./text").Mode,f=a("../tokenizer").Tokenizer,g=a("./latex_highlight_rules").LatexHighlightRules,h=a("../range").Range,i=function(){this.$tokenizer=new f((new g).getRules())};d.inherits(i,e),function(){this.toggleCommentLines=function(a,b,c,d){var e=!0,f=/^(\s*)\%/;for(var g=c;g<=d;g++)if(!f.test(b.getLine(g))){e=!1;break}if(e){var i=new h(0,0,0,0);for(var g=c;g<=d;g++){var j=b.getLine(g),k=j.match(f);i.start.row=g,i.end.row=g,i.end.column=k[0].length,b.replace(i,k[1])}}else b.indentRows(c,d,"%")},this.getNextLineIndent=function(a,b,c){return this.$getIndent(b)}}.call(i.prototype),b.Mode=i}),define("ace/mode/latex_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("./text_highlight_rules").TextHighlightRules,f=function(){this.$rules={start:[{token:"keyword",regex:"\\\\(?:[^a-zA-Z]|[a-zA-Z]+)"},{token:"lparen",regex:"[[({]"},{token:"rparen",regex:"[\\])}]"},{token:"string",regex:"\\$(?:(?:\\\\.)|(?:[^\\$\\\\]))*?\\$"},{token:"comment",regex:"%.*$"}]}};d.inherits(f,e),b.LatexHighlightRules=f})
\ No newline at end of file
diff --git a/apps/files_texteditor/js/aceeditor/mode-less-uncompressed.js b/apps/files_texteditor/js/aceeditor/mode-less-uncompressed.js
new file mode 100644
index 0000000000000000000000000000000000000000..b59684dd2848c413cc95a67e4265141718f48b40
--- /dev/null
+++ b/apps/files_texteditor/js/aceeditor/mode-less-uncompressed.js
@@ -0,0 +1,654 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Ajax.org Code Editor (ACE).
+ *
+ * The Initial Developer of the Original Code is
+ * Ajax.org B.V.
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *      Fabian Jakobs <fabian AT ajax DOT org>
+ *      John Roepke <john AT justjohn DOT us>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+define('ace/mode/less', ['require', 'exports', 'module' , 'ace/lib/oop', 'ace/mode/text', 'ace/tokenizer', 'ace/mode/less_highlight_rules', 'ace/mode/matching_brace_outdent', 'ace/mode/folding/cstyle'], function(require, exports, module) {
+"use strict";
+
+var oop = require("../lib/oop");
+var TextMode = require("./text").Mode;
+var Tokenizer = require("../tokenizer").Tokenizer;
+var LessHighlightRules = require("./less_highlight_rules").LessHighlightRules;
+var MatchingBraceOutdent = require("./matching_brace_outdent").MatchingBraceOutdent;
+var CStyleFoldMode = require("./folding/cstyle").FoldMode;
+
+var Mode = function() {
+    this.$tokenizer = new Tokenizer(new LessHighlightRules().getRules(), "i");
+    this.$outdent = new MatchingBraceOutdent();
+    this.foldingRules = new CStyleFoldMode();
+};
+oop.inherits(Mode, TextMode);
+
+(function() {
+    
+    this.getNextLineIndent = function(state, line, tab) {
+        var indent = this.$getIndent(line);
+
+        // ignore braces in comments
+        var tokens = this.$tokenizer.getLineTokens(line, state).tokens;
+        if (tokens.length && tokens[tokens.length-1].type == "comment") {
+            return indent;
+        }
+
+        var match = line.match(/^.*\{\s*$/);
+        if (match) {
+            indent += tab;
+        }
+
+        return indent;
+    };
+
+    this.checkOutdent = function(state, line, input) {
+        return this.$outdent.checkOutdent(line, input);
+    };
+
+    this.autoOutdent = function(state, doc, row) {
+        this.$outdent.autoOutdent(doc, row);
+    };
+
+}).call(Mode.prototype);
+
+exports.Mode = Mode;
+
+});
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Ajax.org Code Editor (ACE).
+ *
+ * The Initial Developer of the Original Code is
+ * Ajax.org B.V.
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *      Fabian Jakobs <fabian AT ajax DOT org>
+ *      John Roepke <john AT justjohn DOT us>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+define('ace/mode/less_highlight_rules', ['require', 'exports', 'module' , 'ace/lib/oop', 'ace/lib/lang', 'ace/mode/text_highlight_rules'], function(require, exports, module) {
+"use strict";
+
+var oop = require("../lib/oop");
+var lang = require("../lib/lang");
+var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
+
+var LessHighlightRules = function() {
+    
+    var properties = lang.arrayToMap( (function () {
+
+        var browserPrefix = ("-webkit-|-moz-|-o-|-ms-|-svg-|-pie-|-khtml-").split("|");
+        
+        var prefixProperties = ("appearance|background-clip|background-inline-policy|background-origin|" + 
+             "background-size|binding|border-bottom-colors|border-left-colors|" + 
+             "border-right-colors|border-top-colors|border-end|border-end-color|" + 
+             "border-end-style|border-end-width|border-image|border-start|" + 
+             "border-start-color|border-start-style|border-start-width|box-align|" + 
+             "box-direction|box-flex|box-flexgroup|box-ordinal-group|box-orient|" + 
+             "box-pack|box-sizing|column-count|column-gap|column-width|column-rule|" + 
+             "column-rule-width|column-rule-style|column-rule-color|float-edge|" + 
+             "font-feature-settings|font-language-override|force-broken-image-icon|" + 
+             "image-region|margin-end|margin-start|opacity|outline|outline-color|" + 
+             "outline-offset|outline-radius|outline-radius-bottomleft|" + 
+             "outline-radius-bottomright|outline-radius-topleft|outline-radius-topright|" + 
+             "outline-style|outline-width|padding-end|padding-start|stack-sizing|" + 
+             "tab-size|text-blink|text-decoration-color|text-decoration-line|" + 
+             "text-decoration-style|transform|transform-origin|transition|" + 
+             "transition-delay|transition-duration|transition-property|" + 
+             "transition-timing-function|user-focus|user-input|user-modify|user-select|" +
+             "window-shadow|border-radius").split("|");
+        
+        var properties = ("azimuth|background-attachment|background-color|background-image|" +
+            "background-position|background-repeat|background|border-bottom-color|" +
+            "border-bottom-style|border-bottom-width|border-bottom|border-collapse|" +
+            "border-color|border-left-color|border-left-style|border-left-width|" +
+            "border-left|border-right-color|border-right-style|border-right-width|" +
+            "border-right|border-spacing|border-style|border-top-color|" +
+            "border-top-style|border-top-width|border-top|border-width|border|" +
+            "bottom|box-sizing|caption-side|clear|clip|color|content|counter-increment|" +
+            "counter-reset|cue-after|cue-before|cue|cursor|direction|display|" +
+            "elevation|empty-cells|float|font-family|font-size-adjust|font-size|" +
+            "font-stretch|font-style|font-variant|font-weight|font|height|left|" +
+            "letter-spacing|line-height|list-style-image|list-style-position|" +
+            "list-style-type|list-style|margin-bottom|margin-left|margin-right|" +
+            "margin-top|marker-offset|margin|marks|max-height|max-width|min-height|" +
+            "min-width|opacity|orphans|outline-color|" +
+            "outline-style|outline-width|outline|overflow|overflow-x|overflow-y|padding-bottom|" +
+            "padding-left|padding-right|padding-top|padding|page-break-after|" +
+            "page-break-before|page-break-inside|page|pause-after|pause-before|" +
+            "pause|pitch-range|pitch|play-during|position|quotes|richness|right|" +
+            "size|speak-header|speak-numeral|speak-punctuation|speech-rate|speak|" +
+            "stress|table-layout|text-align|text-decoration|text-indent|" +
+            "text-shadow|text-transform|top|unicode-bidi|vertical-align|" +
+            "visibility|voice-family|volume|white-space|widows|width|word-spacing|" +
+            "z-index").split("|");
+          
+        //The return array     
+        var ret = [];
+        
+        //All prefixProperties will get the browserPrefix in
+        //the begning by join the prefixProperties array with the value of browserPrefix
+        for (var i=0, ln=browserPrefix.length; i<ln; i++) {
+            Array.prototype.push.apply(
+                ret,
+                (( browserPrefix[i] + prefixProperties.join("|" + browserPrefix[i]) ).split("|"))
+            );
+        }
+        
+        //Add also prefixProperties and properties without any browser prefix
+        Array.prototype.push.apply(ret, prefixProperties);
+        Array.prototype.push.apply(ret, properties);
+        
+        return ret;
+        
+    })() );
+    
+
+
+    var functions = lang.arrayToMap(
+        ("hsl|hsla|rgb|rgba|url|attr|counter|counters|lighten|darken|saturate|" +
+        "desaturate|fadein|fadeout|fade|spin|mix|hue|saturation|lightness|" +
+        "alpha|round|ceil|floor|percentage|color|iscolor|isnumber|isstring|" +
+        "iskeyword|isurl|ispixel|ispercentage|isem").split("|")
+    );
+
+    var constants = lang.arrayToMap(
+        ("absolute|all-scroll|always|armenian|auto|baseline|below|bidi-override|" +
+        "block|bold|bolder|border-box|both|bottom|break-all|break-word|capitalize|center|" +
+        "char|circle|cjk-ideographic|col-resize|collapse|content-box|crosshair|dashed|" +
+        "decimal-leading-zero|decimal|default|disabled|disc|" +
+        "distribute-all-lines|distribute-letter|distribute-space|" +
+        "distribute|dotted|double|e-resize|ellipsis|fixed|georgian|groove|" +
+        "hand|hebrew|help|hidden|hiragana-iroha|hiragana|horizontal|" +
+        "ideograph-alpha|ideograph-numeric|ideograph-parenthesis|" +
+        "ideograph-space|inactive|inherit|inline-block|inline|inset|inside|" +
+        "inter-ideograph|inter-word|italic|justify|katakana-iroha|katakana|" +
+        "keep-all|left|lighter|line-edge|line-through|line|list-item|loose|" +
+        "lower-alpha|lower-greek|lower-latin|lower-roman|lowercase|lr-tb|ltr|" +
+        "medium|middle|move|n-resize|ne-resize|newspaper|no-drop|no-repeat|" +
+        "nw-resize|none|normal|not-allowed|nowrap|oblique|outset|outside|" +
+        "overline|pointer|progress|relative|repeat-x|repeat-y|repeat|right|" +
+        "ridge|row-resize|rtl|s-resize|scroll|se-resize|separate|small-caps|" +
+        "solid|square|static|strict|super|sw-resize|table-footer-group|" +
+        "table-header-group|tb-rl|text-bottom|text-top|text|thick|thin|top|" +
+        "transparent|underline|upper-alpha|upper-latin|upper-roman|uppercase|" +
+        "vertical-ideographic|vertical-text|visible|w-resize|wait|whitespace|" +
+        "zero").split("|")
+    );
+
+    var colors = lang.arrayToMap(
+        ("aqua|black|blue|fuchsia|gray|green|lime|maroon|navy|olive|orange|" +
+        "purple|red|silver|teal|white|yellow").split("|")
+    );
+    
+    var keywords = lang.arrayToMap(
+        ("@mixin|@extend|@include|@import|@media|@debug|@warn|@if|@for|@each|" +
+        "@while|@else|@font-face|@-webkit-keyframes|if|and|!default|module|" +
+        "def|end|declare|when|not|and").split("|")
+    );
+    
+    var tags = lang.arrayToMap(
+        ("a|abbr|acronym|address|applet|area|article|aside|audio|b|base|basefont|bdo|" + 
+         "big|blockquote|body|br|button|canvas|caption|center|cite|code|col|colgroup|" + 
+         "command|datalist|dd|del|details|dfn|dir|div|dl|dt|em|embed|fieldset|" + 
+         "figcaption|figure|font|footer|form|frame|frameset|h1|h2|h3|h4|h5|h6|head|" + 
+         "header|hgroup|hr|html|i|iframe|img|input|ins|keygen|kbd|label|legend|li|" + 
+         "link|map|mark|menu|meta|meter|nav|noframes|noscript|object|ol|optgroup|" + 
+         "option|output|p|param|pre|progress|q|rp|rt|ruby|s|samp|script|section|select|" + 
+         "small|source|span|strike|strong|style|sub|summary|sup|table|tbody|td|" + 
+         "textarea|tfoot|th|thead|time|title|tr|tt|u|ul|var|video|wbr|xmp").split("|")
+    );
+
+    // regexp must not have capturing parentheses. Use (?:) instead.
+    // regexps are ordered -> the first match is used
+
+    var numRe = "\\-?(?:(?:[0-9]+)|(?:[0-9]*\\.[0-9]+))";
+
+    // regexp must not have capturing parentheses. Use (?:) instead.
+    // regexps are ordered -> the first match is used
+
+    this.$rules = {
+        "start" : [
+            {
+                token : "comment",
+                regex : "\\/\\/.*$"
+            },
+            {
+                token : "comment", // multi line comment
+                merge : true,
+                regex : "\\/\\*",
+                next : "comment"
+            }, {
+                token : "string", // single line
+                regex : '["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'
+            }, {
+                token : "string", // single line
+                regex : "['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"
+            }, {
+                token : "constant.numeric",
+                regex : numRe + "(?:em|ex|px|cm|mm|in|pt|pc|deg|rad|grad|ms|s|hz|khz|%)"
+            }, {
+                token : "constant.numeric", // hex6 color
+                regex : "#[a-f0-9]{6}"
+            }, {
+                token : "constant.numeric", // hex3 color
+                regex : "#[a-f0-9]{3}"
+            }, {
+                token : "constant.numeric",
+                regex : numRe
+            }, {
+                token : function(value) {
+                    if (keywords.hasOwnProperty(value))
+                        return "keyword";
+                    else
+                        return "variable";
+                },
+                regex : "@[a-z0-9_\\-@]*\\b"
+            }, {
+                token : function(value) {
+                    if (properties.hasOwnProperty(value.toLowerCase()))
+                        return "support.type";
+                    else if (keywords.hasOwnProperty(value))
+                        return "keyword";
+                    else if (constants.hasOwnProperty(value))
+                        return "constant.language";
+                    else if (functions.hasOwnProperty(value))
+                        return "support.function";
+                    else if (colors.hasOwnProperty(value.toLowerCase()))
+                        return "support.constant.color";
+                    else if (tags.hasOwnProperty(value.toLowerCase()))
+                        return "variable.language";
+                    else
+                        return "text";
+                },
+                regex : "\\-?[@a-z_][@a-z0-9_\\-]*"
+            }, {
+                token: "variable.language",
+                regex: "#[a-z0-9-_]+"
+            }, {
+                token: "variable.language",
+                regex: "\\.[a-z0-9-_]+"
+            }, {
+                token: "variable.language",
+                regex: ":[a-z0-9-_]+"
+            }, {
+                token: "constant",
+                regex: "[a-z0-9-_]+"
+            }, {
+                token : "keyword.operator",
+                regex : "<|>|<=|>=|==|!=|-|%|#|\\+|\\$|\\+|\\*"
+            }, {
+                token : "paren.lparen",
+                regex : "[[({]"
+            }, {
+                token : "paren.rparen",
+                regex : "[\\])}]"
+            }, {
+                token : "text",
+                regex : "\\s+"
+            }
+        ],
+        "comment" : [
+            {
+                token : "comment", // closing comment
+                regex : ".*?\\*\\/",
+                next : "start"
+            }, {
+                token : "comment", // comment spanning whole line
+                merge : true,
+                regex : ".+"
+            }
+        ]
+    };
+};
+
+oop.inherits(LessHighlightRules, TextHighlightRules);
+
+exports.LessHighlightRules = LessHighlightRules;
+
+});
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Ajax.org Code Editor (ACE).
+ *
+ * The Initial Developer of the Original Code is
+ * Ajax.org B.V.
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *      Fabian Jakobs <fabian AT ajax DOT org>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+define('ace/mode/matching_brace_outdent', ['require', 'exports', 'module' , 'ace/range'], function(require, exports, module) {
+"use strict";
+
+var Range = require("../range").Range;
+
+var MatchingBraceOutdent = function() {};
+
+(function() {
+
+    this.checkOutdent = function(line, input) {
+        if (! /^\s+$/.test(line))
+            return false;
+
+        return /^\s*\}/.test(input);
+    };
+
+    this.autoOutdent = function(doc, row) {
+        var line = doc.getLine(row);
+        var match = line.match(/^(\s*\})/);
+
+        if (!match) return 0;
+
+        var column = match[1].length;
+        var openBracePos = doc.findMatchingBracket({row: row, column: column});
+
+        if (!openBracePos || openBracePos.row == row) return 0;
+
+        var indent = this.$getIndent(doc.getLine(openBracePos.row));
+        doc.replace(new Range(row, 0, row, column-1), indent);
+    };
+
+    this.$getIndent = function(line) {
+        var match = line.match(/^(\s+)/);
+        if (match) {
+            return match[1];
+        }
+
+        return "";
+    };
+
+}).call(MatchingBraceOutdent.prototype);
+
+exports.MatchingBraceOutdent = MatchingBraceOutdent;
+});
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Ajax.org Code Editor (ACE).
+ *
+ * The Initial Developer of the Original Code is
+ * Ajax.org B.V.
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *      Fabian Jakobs <fabian AT ajax DOT org>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+define('ace/mode/folding/cstyle', ['require', 'exports', 'module' , 'ace/lib/oop', 'ace/range', 'ace/mode/folding/fold_mode'], function(require, exports, module) {
+"use strict";
+
+var oop = require("../../lib/oop");
+var Range = require("../../range").Range;
+var BaseFoldMode = require("./fold_mode").FoldMode;
+
+var FoldMode = exports.FoldMode = function() {};
+oop.inherits(FoldMode, BaseFoldMode);
+
+(function() {
+
+    this.foldingStartMarker = /(\{|\[)[^\}\]]*$|^\s*(\/\*)/;
+    this.foldingStopMarker = /^[^\[\{]*(\}|\])|^[\s\*]*(\*\/)/;
+    
+    this.getFoldWidgetRange = function(session, foldStyle, row) {
+        var line = session.getLine(row);
+        var match = line.match(this.foldingStartMarker);
+        if (match) {
+            var i = match.index;
+
+            if (match[1])
+                return this.openingBracketBlock(session, match[1], row, i);
+
+            var range = session.getCommentFoldRange(row, i + match[0].length);
+            range.end.column -= 2;
+            return range;
+        }
+
+        if (foldStyle !== "markbeginend")
+            return;
+            
+        var match = line.match(this.foldingStopMarker);
+        if (match) {
+            var i = match.index + match[0].length;
+
+            if (match[2]) {
+                var range = session.getCommentFoldRange(row, i);
+                range.end.column -= 2;
+                return range;
+            }
+
+            var end = {row: row, column: i};
+            var start = session.$findOpeningBracket(match[1], end);
+            
+            if (!start)
+                return;
+
+            start.column++;
+            end.column--;
+
+            return  Range.fromPoints(start, end);
+        }
+    };
+    
+}).call(FoldMode.prototype);
+
+});/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Ajax.org Code Editor (ACE).
+ *
+ * The Initial Developer of the Original Code is
+ * Ajax.org B.V.
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *      Fabian Jakobs <fabian AT ajax DOT org>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+define('ace/mode/folding/fold_mode', ['require', 'exports', 'module' , 'ace/range'], function(require, exports, module) {
+"use strict";
+
+var Range = require("../../range").Range;
+
+var FoldMode = exports.FoldMode = function() {};
+
+(function() {
+
+    this.foldingStartMarker = null;
+    this.foldingStopMarker = null;
+
+    // must return "" if there's no fold, to enable caching
+    this.getFoldWidget = function(session, foldStyle, row) {
+        var line = session.getLine(row);
+        if (this.foldingStartMarker.test(line))
+            return "start";
+        if (foldStyle == "markbeginend"
+                && this.foldingStopMarker
+                && this.foldingStopMarker.test(line))
+            return "end";
+        return "";
+    };
+    
+    this.getFoldWidgetRange = function(session, foldStyle, row) {
+        return null;
+    };
+
+    this.indentationBlock = function(session, row, column) {
+        var re = /^\s*/;
+        var startRow = row;
+        var endRow = row;
+        var line = session.getLine(row);
+        var startColumn = column || line.length;
+        var startLevel = line.match(re)[0].length;
+        var maxRow = session.getLength()
+        
+        while (++row < maxRow) {
+            line = session.getLine(row);
+            var level = line.match(re)[0].length;
+
+            if (level == line.length)
+                continue;
+
+            if (level <= startLevel)
+                break;
+
+            endRow = row;
+        }
+
+        if (endRow > startRow) {
+            var endColumn = session.getLine(endRow).length;
+            return new Range(startRow, startColumn, endRow, endColumn);
+        }
+    };
+
+    this.openingBracketBlock = function(session, bracket, row, column) {
+        var start = {row: row, column: column + 1};
+        var end = session.$findClosingBracket(bracket, start);
+        if (!end)
+            return;
+
+        var fw = session.foldWidgets[end.row];
+        if (fw == null)
+            fw = this.getFoldWidget(session, end.row);
+
+        if (fw == "start") {
+            end.row --;
+            end.column = session.getLine(end.row).length;
+        }
+        return Range.fromPoints(start, end);
+    };
+
+}).call(FoldMode.prototype);
+
+});
diff --git a/apps/files_texteditor/js/aceeditor/mode-less.js b/apps/files_texteditor/js/aceeditor/mode-less.js
new file mode 100644
index 0000000000000000000000000000000000000000..8ecd9aad97bc4ef095dc807bbe7778a67ba9eb03
--- /dev/null
+++ b/apps/files_texteditor/js/aceeditor/mode-less.js
@@ -0,0 +1 @@
+define("ace/mode/less",["require","exports","module","ace/lib/oop","ace/mode/text","ace/tokenizer","ace/mode/less_highlight_rules","ace/mode/matching_brace_outdent","ace/mode/folding/cstyle"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("./text").Mode,f=a("../tokenizer").Tokenizer,g=a("./less_highlight_rules").LessHighlightRules,h=a("./matching_brace_outdent").MatchingBraceOutdent,i=a("./folding/cstyle").FoldMode,j=function(){this.$tokenizer=new f((new g).getRules(),"i"),this.$outdent=new h,this.foldingRules=new i};d.inherits(j,e),function(){this.getNextLineIndent=function(a,b,c){var d=this.$getIndent(b),e=this.$tokenizer.getLineTokens(b,a).tokens;if(e.length&&e[e.length-1].type=="comment")return d;var f=b.match(/^.*\{\s*$/);return f&&(d+=c),d},this.checkOutdent=function(a,b,c){return this.$outdent.checkOutdent(b,c)},this.autoOutdent=function(a,b,c){this.$outdent.autoOutdent(b,c)}}.call(j.prototype),b.Mode=j}),define("ace/mode/less_highlight_rules",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/mode/text_highlight_rules"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("../lib/lang"),f=a("./text_highlight_rules").TextHighlightRules,g=function(){var a=e.arrayToMap(function(){var a="-webkit-|-moz-|-o-|-ms-|-svg-|-pie-|-khtml-".split("|"),b="appearance|background-clip|background-inline-policy|background-origin|background-size|binding|border-bottom-colors|border-left-colors|border-right-colors|border-top-colors|border-end|border-end-color|border-end-style|border-end-width|border-image|border-start|border-start-color|border-start-style|border-start-width|box-align|box-direction|box-flex|box-flexgroup|box-ordinal-group|box-orient|box-pack|box-sizing|column-count|column-gap|column-width|column-rule|column-rule-width|column-rule-style|column-rule-color|float-edge|font-feature-settings|font-language-override|force-broken-image-icon|image-region|margin-end|margin-start|opacity|outline|outline-color|outline-offset|outline-radius|outline-radius-bottomleft|outline-radius-bottomright|outline-radius-topleft|outline-radius-topright|outline-style|outline-width|padding-end|padding-start|stack-sizing|tab-size|text-blink|text-decoration-color|text-decoration-line|text-decoration-style|transform|transform-origin|transition|transition-delay|transition-duration|transition-property|transition-timing-function|user-focus|user-input|user-modify|user-select|window-shadow|border-radius".split("|"),c="azimuth|background-attachment|background-color|background-image|background-position|background-repeat|background|border-bottom-color|border-bottom-style|border-bottom-width|border-bottom|border-collapse|border-color|border-left-color|border-left-style|border-left-width|border-left|border-right-color|border-right-style|border-right-width|border-right|border-spacing|border-style|border-top-color|border-top-style|border-top-width|border-top|border-width|border|bottom|box-sizing|caption-side|clear|clip|color|content|counter-increment|counter-reset|cue-after|cue-before|cue|cursor|direction|display|elevation|empty-cells|float|font-family|font-size-adjust|font-size|font-stretch|font-style|font-variant|font-weight|font|height|left|letter-spacing|line-height|list-style-image|list-style-position|list-style-type|list-style|margin-bottom|margin-left|margin-right|margin-top|marker-offset|margin|marks|max-height|max-width|min-height|min-width|opacity|orphans|outline-color|outline-style|outline-width|outline|overflow|overflow-x|overflow-y|padding-bottom|padding-left|padding-right|padding-top|padding|page-break-after|page-break-before|page-break-inside|page|pause-after|pause-before|pause|pitch-range|pitch|play-during|position|quotes|richness|right|size|speak-header|speak-numeral|speak-punctuation|speech-rate|speak|stress|table-layout|text-align|text-decoration|text-indent|text-shadow|text-transform|top|unicode-bidi|vertical-align|visibility|voice-family|volume|white-space|widows|width|word-spacing|z-index".split("|"),d=[];for(var e=0,f=a.length;e<f;e++)Array.prototype.push.apply(d,(a[e]+b.join("|"+a[e])).split("|"));return Array.prototype.push.apply(d,b),Array.prototype.push.apply(d,c),d}()),b=e.arrayToMap("hsl|hsla|rgb|rgba|url|attr|counter|counters|lighten|darken|saturate|desaturate|fadein|fadeout|fade|spin|mix|hue|saturation|lightness|alpha|round|ceil|floor|percentage|color|iscolor|isnumber|isstring|iskeyword|isurl|ispixel|ispercentage|isem".split("|")),c=e.arrayToMap("absolute|all-scroll|always|armenian|auto|baseline|below|bidi-override|block|bold|bolder|border-box|both|bottom|break-all|break-word|capitalize|center|char|circle|cjk-ideographic|col-resize|collapse|content-box|crosshair|dashed|decimal-leading-zero|decimal|default|disabled|disc|distribute-all-lines|distribute-letter|distribute-space|distribute|dotted|double|e-resize|ellipsis|fixed|georgian|groove|hand|hebrew|help|hidden|hiragana-iroha|hiragana|horizontal|ideograph-alpha|ideograph-numeric|ideograph-parenthesis|ideograph-space|inactive|inherit|inline-block|inline|inset|inside|inter-ideograph|inter-word|italic|justify|katakana-iroha|katakana|keep-all|left|lighter|line-edge|line-through|line|list-item|loose|lower-alpha|lower-greek|lower-latin|lower-roman|lowercase|lr-tb|ltr|medium|middle|move|n-resize|ne-resize|newspaper|no-drop|no-repeat|nw-resize|none|normal|not-allowed|nowrap|oblique|outset|outside|overline|pointer|progress|relative|repeat-x|repeat-y|repeat|right|ridge|row-resize|rtl|s-resize|scroll|se-resize|separate|small-caps|solid|square|static|strict|super|sw-resize|table-footer-group|table-header-group|tb-rl|text-bottom|text-top|text|thick|thin|top|transparent|underline|upper-alpha|upper-latin|upper-roman|uppercase|vertical-ideographic|vertical-text|visible|w-resize|wait|whitespace|zero".split("|")),d=e.arrayToMap("aqua|black|blue|fuchsia|gray|green|lime|maroon|navy|olive|orange|purple|red|silver|teal|white|yellow".split("|")),f=e.arrayToMap("@mixin|@extend|@include|@import|@media|@debug|@warn|@if|@for|@each|@while|@else|@font-face|@-webkit-keyframes|if|and|!default|module|def|end|declare|when|not|and".split("|")),g=e.arrayToMap("a|abbr|acronym|address|applet|area|article|aside|audio|b|base|basefont|bdo|big|blockquote|body|br|button|canvas|caption|center|cite|code|col|colgroup|command|datalist|dd|del|details|dfn|dir|div|dl|dt|em|embed|fieldset|figcaption|figure|font|footer|form|frame|frameset|h1|h2|h3|h4|h5|h6|head|header|hgroup|hr|html|i|iframe|img|input|ins|keygen|kbd|label|legend|li|link|map|mark|menu|meta|meter|nav|noframes|noscript|object|ol|optgroup|option|output|p|param|pre|progress|q|rp|rt|ruby|s|samp|script|section|select|small|source|span|strike|strong|style|sub|summary|sup|table|tbody|td|textarea|tfoot|th|thead|time|title|tr|tt|u|ul|var|video|wbr|xmp".split("|")),h="\\-?(?:(?:[0-9]+)|(?:[0-9]*\\.[0-9]+))";this.$rules={start:[{token:"comment",regex:"\\/\\/.*$"},{token:"comment",merge:!0,regex:"\\/\\*",next:"comment"},{token:"string",regex:'["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'},{token:"string",regex:"['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"},{token:"constant.numeric",regex:h+"(?:em|ex|px|cm|mm|in|pt|pc|deg|rad|grad|ms|s|hz|khz|%)"},{token:"constant.numeric",regex:"#[a-f0-9]{6}"},{token:"constant.numeric",regex:"#[a-f0-9]{3}"},{token:"constant.numeric",regex:h},{token:function(a){return f.hasOwnProperty(a)?"keyword":"variable"},regex:"@[a-z0-9_\\-@]*\\b"},{token:function(e){return a.hasOwnProperty(e.toLowerCase())?"support.type":f.hasOwnProperty(e)?"keyword":c.hasOwnProperty(e)?"constant.language":b.hasOwnProperty(e)?"support.function":d.hasOwnProperty(e.toLowerCase())?"support.constant.color":g.hasOwnProperty(e.toLowerCase())?"variable.language":"text"},regex:"\\-?[@a-z_][@a-z0-9_\\-]*"},{token:"variable.language",regex:"#[a-z0-9-_]+"},{token:"variable.language",regex:"\\.[a-z0-9-_]+"},{token:"variable.language",regex:":[a-z0-9-_]+"},{token:"constant",regex:"[a-z0-9-_]+"},{token:"keyword.operator",regex:"<|>|<=|>=|==|!=|-|%|#|\\+|\\$|\\+|\\*"},{token:"paren.lparen",regex:"[[({]"},{token:"paren.rparen",regex:"[\\])}]"},{token:"text",regex:"\\s+"}],comment:[{token:"comment",regex:".*?\\*\\/",next:"start"},{token:"comment",merge:!0,regex:".+"}]}};d.inherits(g,f),b.LessHighlightRules=g}),define("ace/mode/matching_brace_outdent",["require","exports","module","ace/range"],function(a,b,c){"use strict";var d=a("../range").Range,e=function(){};(function(){this.checkOutdent=function(a,b){return/^\s+$/.test(a)?/^\s*\}/.test(b):!1},this.autoOutdent=function(a,b){var c=a.getLine(b),e=c.match(/^(\s*\})/);if(!e)return 0;var f=e[1].length,g=a.findMatchingBracket({row:b,column:f});if(!g||g.row==b)return 0;var h=this.$getIndent(a.getLine(g.row));a.replace(new d(b,0,b,f-1),h)},this.$getIndent=function(a){var b=a.match(/^(\s+)/);return b?b[1]:""}}).call(e.prototype),b.MatchingBraceOutdent=e}),define("ace/mode/folding/cstyle",["require","exports","module","ace/lib/oop","ace/range","ace/mode/folding/fold_mode"],function(a,b,c){"use strict";var d=a("../../lib/oop"),e=a("../../range").Range,f=a("./fold_mode").FoldMode,g=b.FoldMode=function(){};d.inherits(g,f),function(){this.foldingStartMarker=/(\{|\[)[^\}\]]*$|^\s*(\/\*)/,this.foldingStopMarker=/^[^\[\{]*(\}|\])|^[\s\*]*(\*\/)/,this.getFoldWidgetRange=function(a,b,c){var d=a.getLine(c),f=d.match(this.foldingStartMarker);if(f){var g=f.index;if(f[1])return this.openingBracketBlock(a,f[1],c,g);var h=a.getCommentFoldRange(c,g+f[0].length);return h.end.column-=2,h}if(b!=="markbeginend")return;var f=d.match(this.foldingStopMarker);if(f){var g=f.index+f[0].length;if(f[2]){var h=a.getCommentFoldRange(c,g);return h.end.column-=2,h}var i={row:c,column:g},j=a.$findOpeningBracket(f[1],i);if(!j)return;return j.column++,i.column--,e.fromPoints(j,i)}}}.call(g.prototype)}),define("ace/mode/folding/fold_mode",["require","exports","module","ace/range"],function(a,b,c){"use strict";var d=a("../../range").Range,e=b.FoldMode=function(){};(function(){this.foldingStartMarker=null,this.foldingStopMarker=null,this.getFoldWidget=function(a,b,c){var d=a.getLine(c);return this.foldingStartMarker.test(d)?"start":b=="markbeginend"&&this.foldingStopMarker&&this.foldingStopMarker.test(d)?"end":""},this.getFoldWidgetRange=function(a,b,c){return null},this.indentationBlock=function(a,b,c){var e=/^\s*/,f=b,g=b,h=a.getLine(b),i=c||h.length,j=h.match(e)[0].length,k=a.getLength();while(++b<k){h=a.getLine(b);var l=h.match(e)[0].length;if(l==h.length)continue;if(l<=j)break;g=b}if(g>f){var m=a.getLine(g).length;return new d(f,i,g,m)}},this.openingBracketBlock=function(a,b,c,e){var f={row:c,column:e+1},g=a.$findClosingBracket(b,f);if(!g)return;var h=a.foldWidgets[g.row];return h==null&&(h=this.getFoldWidget(a,g.row)),h=="start"&&(g.row--,g.column=a.getLine(g.row).length),d.fromPoints(f,g)}}).call(e.prototype)})
\ No newline at end of file
diff --git a/apps/files_texteditor/js/aceeditor/mode-liquid-uncompressed.js b/apps/files_texteditor/js/aceeditor/mode-liquid-uncompressed.js
new file mode 100644
index 0000000000000000000000000000000000000000..6e9b689e85c751c0123701bbfce2d336bd224409
--- /dev/null
+++ b/apps/files_texteditor/js/aceeditor/mode-liquid-uncompressed.js
@@ -0,0 +1,1332 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Ajax.org Code Editor (ACE).
+ *
+ * The Initial Developer of the Original Code is
+ * Ajax.org B.V.
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *      Fabian Jakobs <fabian AT ajax DOT org>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+define('ace/mode/liquid', ['require', 'exports', 'module' , 'ace/lib/oop', 'ace/mode/text', 'ace/tokenizer', 'ace/mode/liquid_highlight_rules', 'ace/mode/matching_brace_outdent', 'ace/range'], function(require, exports, module) {
+
+var oop = require("../lib/oop");
+var TextMode = require("./text").Mode;
+var Tokenizer = require("../tokenizer").Tokenizer;
+var LiquidHighlightRules = require("./liquid_highlight_rules").LiquidHighlightRules;
+var MatchingBraceOutdent = require("./matching_brace_outdent").MatchingBraceOutdent;
+var Range = require("../range").Range;
+
+var Mode = function() {
+    this.$tokenizer = new Tokenizer(new LiquidHighlightRules().getRules());
+    this.$outdent = new MatchingBraceOutdent();
+};
+oop.inherits(Mode, TextMode);
+
+(function() {
+
+    this.toggleCommentLines = function(state, doc, startRow, endRow) {
+        var outdent = true;
+        var outentedRows = [];
+        var re = /^(\s*)#/;
+
+        for (var i=startRow; i<= endRow; i++) {
+            if (!re.test(doc.getLine(i))) {
+                outdent = false;
+                break;
+            }
+        }
+
+        if (outdent) {
+            var deleteRange = new Range(0, 0, 0, 0);
+            for (var i=startRow; i<= endRow; i++)
+            {
+                var line = doc.getLine(i);
+                var m = line.match(re);
+                deleteRange.start.row = i;
+                deleteRange.end.row = i;
+                deleteRange.end.column = m[0].length;
+                doc.replace(deleteRange, m[1]);
+            }
+        }
+        else {
+            doc.indentRows(startRow, endRow, "#");
+        }
+    };
+
+    this.getNextLineIndent = function(state, line, tab) {
+        var indent = this.$getIndent(line);
+
+        var tokenizedLine = this.$tokenizer.getLineTokens(line, state);
+        var tokens = tokenizedLine.tokens;
+        var endState = tokenizedLine.state;
+
+        if (tokens.length && tokens[tokens.length-1].type == "comment") {
+            return indent;
+        }
+
+        if (state == "start") {
+            var match = line.match(/^.*[\{\(\[]\s*$/);
+            if (match) {
+                indent += tab;
+            }
+        }
+
+        return indent;
+    };
+
+    this.checkOutdent = function(state, line, input) {
+        return this.$outdent.checkOutdent(line, input);
+    };
+
+    this.autoOutdent = function(state, doc, row) {
+        this.$outdent.autoOutdent(doc, row);
+    };
+
+}).call(Mode.prototype);
+
+exports.Mode = Mode;
+});
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Ajax.org Code Editor (ACE).
+ *
+ * The Initial Developer of the Original Code is
+ * Ajax.org B.V.
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *      Fabian Jakobs <fabian AT ajax DOT org>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+define('ace/mode/liquid_highlight_rules', ['require', 'exports', 'module' , 'ace/lib/oop', 'ace/mode/css_highlight_rules', 'ace/mode/javascript_highlight_rules', 'ace/lib/lang', 'ace/mode/xml_util', 'ace/mode/text_highlight_rules'], function(require, exports, module) {
+"use strict";
+
+var oop = require("../lib/oop");
+var CssHighlightRules = require("./css_highlight_rules").CssHighlightRules;
+var JavaScriptHighlightRules = require("./javascript_highlight_rules").JavaScriptHighlightRules;
+var lang = require("../lib/lang");
+var xmlUtil = require("./xml_util");
+var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
+
+var LiquidHighlightRules = function() {
+
+    // see: https://developer.mozilla.org/en/Liquid/Reference/Global_Objects
+    var functions = lang.arrayToMap(
+      // Standard Filters
+        ("date|capitalize|downcase|upcase|first|last|join|sort|map|size|escape|" +
+         "escape_once|strip_html|strip_newlines|newline_to_br|replace|replace_first|" +
+         "truncate|truncatewords|prepend|append|minus|plus|times|divided_by|split"
+      ).split("|")
+    );
+
+    var keywords = lang.arrayToMap(
+      // Standard Tags
+        ("capture|endcapture|case|endcase|when|comment|endcomment|" +
+        "cycle|for|endfor|in|reversed|if|endif|else|elsif|include|endinclude|unless|endunless|" +
+     // Commonly used tags
+        "style|text|image|widget|plugin|marker|endmarker|tablerow|endtablerow").split("|")
+    );
+
+    var builtinVariables = lang.arrayToMap(
+        ['forloop']
+        // ("forloop\\.(length|index|index0|rindex|rindex0|first|last)|limit|offset|range" +
+        // "tablerowloop\\.(length|index|index0|rindex|rindex0|first|last|col|col0|"+
+        // "col_first|col_last)").split("|")
+    );
+
+    var definitions = lang.arrayToMap(("assign").split("|"));
+
+    // regexp must not have capturing parentheses. Use (?:) instead.
+    // regexps are ordered -> the first match is used
+
+    this.$rules = {
+            start : [{
+                token : "variable",
+                regex : "{%",
+                next : "liquid_start"
+            }, {
+                token : "variable",
+                regex : "{{",
+                next : "liquid_start"
+            }, {
+                token : "meta.tag",
+                merge : true,
+                regex : "<\\!\\[CDATA\\[",
+                next : "cdata"
+            }, {
+                token : "xml_pe",
+                regex : "<\\?.*?\\?>"
+            }, {
+                token : "comment",
+                merge : true,
+                regex : "<\\!--",
+                next : "comment"
+            }, {
+                token : "meta.tag",
+                regex : "<(?=\\s*script\\b)",
+                next : "script"
+            }, {
+                token : "meta.tag",
+                regex : "<(?=\\s*style\\b)",
+                next : "style"
+            }, {
+                token : "meta.tag", // opening tag
+                regex : "<\\/?",
+                next : "tag"
+            }, {
+                token : "text",
+                regex : "\\s+"
+            }, {
+                token : "text",
+                regex : "[^<]+"
+            } ],
+
+            cdata : [ {
+                token : "text",
+                regex : "\\]\\]>",
+                next : "start"
+            }, {
+                token : "text",
+                merge : true,
+                regex : "\\s+"
+            }, {
+                token : "text",
+                merge : true,
+                regex : ".+"
+            } ],
+
+            comment : [ {
+                token : "comment",
+                regex : ".*?-->",
+                next : "start"
+            }, {
+                token : "comment",
+                merge : true,
+                regex : ".+"
+            } ] ,
+
+            liquid_start : [{
+                token: "variable",
+                regex: "}}",
+                next: "start"
+            }, {
+                token: "variable",
+                regex: "%}",
+                next: "start"
+            }, {
+                token : "string", // single line
+                regex : '["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'
+            }, {
+                token : "string", // single line
+                regex : "['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"
+            }, {
+                token : "constant.numeric", // hex
+                regex : "0[xX][0-9a-fA-F]+\\b"
+            }, {
+                token : "constant.numeric", // float
+                regex : "[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"
+            }, {
+                token : "constant.language.boolean",
+                regex : "(?:true|false)\\b"
+            }, {
+                token : function(value) {
+                    if (functions.hasOwnProperty(value))
+                        return "support.function";
+                    else if (keywords.hasOwnProperty(value))
+                        return "keyword";
+                    else if (builtinVariables.hasOwnProperty(value))
+                        return "variable.language";
+                    else if (definitions.hasOwnProperty(value))
+                        return "keyword.definition";
+                    else
+                        return "identifier";
+                },
+                regex : "[a-zA-Z_$][a-zA-Z0-9_$]*\\b"
+            }, {
+                token : "keyword.operator",
+                regex : "\/|\\*|\\-|\\+|=|!=|\\?\\:"
+            }, {
+                token : "paren.lparen",
+                regex : /[\[\({]/
+            }, {
+                token : "paren.rparen",
+                regex : /[\])}]/
+            }, {
+                token : "text",
+                regex : "\\s+"
+            }]
+    };
+
+    xmlUtil.tag(this.$rules, "tag", "start");
+    xmlUtil.tag(this.$rules, "style", "css-start");
+    xmlUtil.tag(this.$rules, "script", "js-start");
+
+    this.embedRules(JavaScriptHighlightRules, "js-", [{
+        token: "comment",
+        regex: "\\/\\/.*(?=<\\/script>)",
+        next: "tag"
+    }, {
+        token: "meta.tag",
+        regex: "<\\/(?=script)",
+        next: "tag"
+    }]);
+
+    this.embedRules(CssHighlightRules, "css-", [{
+        token: "meta.tag",
+        regex: "<\\/(?=style)",
+        next: "tag"
+    }]);
+};
+oop.inherits(LiquidHighlightRules, TextHighlightRules);
+
+exports.LiquidHighlightRules = LiquidHighlightRules;
+});
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Ajax.org Code Editor (ACE).
+ *
+ * The Initial Developer of the Original Code is
+ * Ajax.org B.V.
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *      Fabian Jakobs <fabian AT ajax DOT org>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+define('ace/mode/css_highlight_rules', ['require', 'exports', 'module' , 'ace/lib/oop', 'ace/lib/lang', 'ace/mode/text_highlight_rules'], function(require, exports, module) {
+"use strict";
+
+var oop = require("../lib/oop");
+var lang = require("../lib/lang");
+var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
+
+var CssHighlightRules = function() {
+
+    var properties = lang.arrayToMap(
+        ("animation-fill-mode|alignment-adjust|alignment-baseline|animation-delay|animation-direction|animation-duration|animation-iteration-count|animation-name|animation-play-state|animation-timing-function|animation|appearance|azimuth|backface-visibility|background-attachment|background-break|background-clip|background-color|background-image|background-origin|background-position|background-repeat|background-size|background|baseline-shift|binding|bleed|bookmark-label|bookmark-level|bookmark-state|bookmark-target|border-bottom|border-bottom-color|border-bottom-left-radius|border-bottom-right-radius|border-bottom-style|border-bottom-width|border-collapse|border-color|border-image|border-image-outset|border-image-repeat|border-image-slice|border-image-source|border-image-width|border-left|border-left-color|border-left-style|border-left-width|border-radius|border-right|border-right-color|border-right-style|border-right-width|border-spacing|border-style|border-top|border-top-color|border-top-left-radius|border-top-right-radius|border-top-style|border-top-width|border-width|border|bottom|box-align|box-decoration-break|box-direction|box-flex-group|box-flex|box-lines|box-ordinal-group|box-orient|box-pack|box-shadow|box-sizing|break-after|break-before|break-inside|caption-side|clear|clip|color-profile|color|column-count|column-fill|column-gap|column-rule|column-rule-color|column-rule-style|column-rule-width|column-span|column-width|columns|content|counter-increment|counter-reset|crop|cue-after|cue-before|cue|cursor|direction|display|dominant-baseline|drop-initial-after-adjust|drop-initial-after-align|drop-initial-before-adjust|drop-initial-before-align|drop-initial-size|drop-initial-value|elevation|empty-cells|fit|fit-position|float-offset|float|font-family|font-size|font-size-adjust|font-stretch|font-style|font-variant|font-weight|font|grid-columns|grid-rows|hanging-punctuation|height|hyphenate-after|hyphenate-before|hyphenate-character|hyphenate-lines|hyphenate-resource|hyphens|icon|image-orientation|image-rendering|image-resolution|inline-box-align|left|letter-spacing|line-height|line-stacking-ruby|line-stacking-shift|line-stacking-strategy|line-stacking|list-style-image|list-style-position|list-style-type|list-style|margin-bottom|margin-left|margin-right|margin-top|margin|mark-after|mark-before|mark|marks|marquee-direction|marquee-play-count|marquee-speed|marquee-style|max-height|max-width|min-height|min-width|move-to|nav-down|nav-index|nav-left|nav-right|nav-up|opacity|orphans|outline-color|outline-offset|outline-style|outline-width|outline|overflow-style|overflow-x|overflow-y|overflow|padding-bottom|padding-left|padding-right|padding-top|padding|page-break-after|page-break-before|page-break-inside|page-policy|page|pause-after|pause-before|pause|perspective-origin|perspective|phonemes|pitch-range|pitch|play-during|position|presentation-level|punctuation-trim|quotes|rendering-intent|resize|rest-after|rest-before|rest|richness|right|rotation-point|rotation|ruby-align|ruby-overhang|ruby-position|ruby-span|size|speak-header|speak-numeral|speak-punctuation|speak|speech-rate|stress|string-set|table-layout|target-name|target-new|target-position|target|text-align-last|text-align|text-decoration|text-emphasis|text-height|text-indent|text-justify|text-outline|text-shadow|text-transform|text-wrap|top|transform-origin|transform-style|transform|transition-delay|transition-duration|transition-property|transition-timing-function|transition|unicode-bidi|vertical-align|visibility|voice-balance|voice-duration|voice-family|voice-pitch-range|voice-pitch|voice-rate|voice-stress|voice-volume|volume|white-space-collapse|white-space|widows|width|word-break|word-spacing|word-wrap|z-index").split("|")
+    );
+
+    var functions = lang.arrayToMap(
+        ("rgb|rgba|url|attr|counter|counters").split("|")
+    );
+
+    var constants = lang.arrayToMap(
+        ("absolute|after-edge|after|all-scroll|all|alphabetic|always|antialiased|armenian|auto|avoid-column|avoid-page|avoid|balance|baseline|before-edge|before|below|bidi-override|block-line-height|block|bold|bolder|border-box|both|bottom|box|break-all|break-word|capitalize|caps-height|caption|center|central|char|circle|cjk-ideographic|clone|close-quote|col-resize|collapse|column|consider-shifts|contain|content-box|cover|crosshair|cubic-bezier|dashed|decimal-leading-zero|decimal|default|disabled|disc|disregard-shifts|distribute-all-lines|distribute-letter|distribute-space|distribute|dotted|double|e-resize|ease-in|ease-in-out|ease-out|ease|ellipsis|end|exclude-ruby|fill|fixed|font-size|font|georgian|glyphs|grid-height|groove|hand|hanging|hebrew|help|hidden|hiragana-iroha|hiragana|horizontal|icon|ideograph-alpha|ideograph-numeric|ideograph-parenthesis|ideograph-space|ideographic|inactive|include-ruby|inherit|initial|inline-block|inline-box|inline-line-height|inline-table|inline|inset|inside|inter-ideograph|inter-word|invert|italic|justify|katakana-iroha|katakana|keep-all|last|left|lighter|line-edge|line-through|line|linear|list-item|local|loose|lower-alpha|lower-greek|lower-latin|lower-roman|lowercase|lr-tb|ltr|mathematical|max-height|max-size|medium|menu|message-box|middle|move|n-resize|ne-resize|newspaper|no-change|no-close-quote|no-drop|no-open-quote|no-repeat|none|normal|not-allowed|nowrap|nw-resize|oblique|open-quote|outset|outside|overline|padding-box|page|pointer|pre-line|pre-wrap|pre|preserve-3d|progress|relative|repeat-x|repeat-y|repeat|replaced|reset-size|ridge|right|round|row-resize|rtl|s-resize|scroll|se-resize|separate|slice|small-caps|small-caption|solid|space|square|start|static|status-bar|step-end|step-start|steps|stretch|strict|sub|super|sw-resize|table-caption|table-cell|table-column-group|table-column|table-footer-group|table-header-group|table-row-group|table-row|table|tb-rl|text-after-edge|text-before-edge|text-bottom|text-size|text-top|text|thick|thin|top|transparent|underline|upper-alpha|upper-latin|upper-roman|uppercase|use-script|vertical-ideographic|vertical-text|visible|w-resize|wait|whitespace|z-index|zero").split("|")
+    );
+
+    var colors = lang.arrayToMap(
+        ("aqua|black|blue|fuchsia|gray|green|lime|maroon|navy|olive|orange|" +
+        "purple|red|silver|teal|white|yellow").split("|")
+    );
+
+    var fonts = lang.arrayToMap(
+        ("arial|century|comic|courier|garamond|georgia|helvetica|impact|lucida|" +
+        "symbol|system|tahoma|times|trebuchet|utopia|verdana|webdings|sans-serif|" +
+        "serif|monospace").split("|")
+    );
+    
+    // regexp must not have capturing parentheses. Use (?:) instead.
+    // regexps are ordered -> the first match is used
+
+    var numRe = "\\-?(?:(?:[0-9]+)|(?:[0-9]*\\.[0-9]+))";
+    var pseudoElements = "(\\:+)\\b(after|before|first-letter|first-line|moz-selection|selection)\\b";
+    var pseudoClasses = "(:)\\b(active|checked|disabled|empty|enabled|first-child|first-of-type|focus|hover|indeterminate|invalid|last-child|last-of-type|link|not|nth-child|nth-last-child|nth-last-of-type|nth-of-type|only-child|only-of-type|required|root|target|valid|visited)\\b";
+    
+    var base_ruleset = [
+        {
+            token : "comment", // multi line comment
+            merge : true,
+            regex : "\\/\\*",
+            next : "ruleset_comment"
+        }, {
+            token : "string", // single line
+            regex : '["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'
+        }, {
+            token : "string", // single line
+            regex : "['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"
+        }, {
+            token : ["constant.numeric", "keyword"],
+            regex : "(" + numRe + ")(ch|cm|deg|em|ex|fr|gd|grad|Hz|in|kHz|mm|ms|pc|pt|px|rad|rem|s|turn|vh|vm|vw|%)"
+        }, {
+            token : ["constant.numeric"],
+            regex : "([0-9]+)"
+        }, {
+            token : "constant.numeric",  // hex6 color
+            regex : "#[a-f0-9]{6}"
+        }, {
+            token : "constant.numeric", // hex3 color
+            regex : "#[a-f0-9]{3}"
+        }, {
+            token : ["punctuation", "entity.other.attribute-name.pseudo-element.css"], 
+            regex : pseudoElements
+        }, {
+            token : ["punctuation", "entity.other.attribute-name.pseudo-class.css"], 
+            regex : pseudoClasses
+        }, {
+            token : function(value) {
+                if (properties.hasOwnProperty(value.toLowerCase())) {
+                    return "support.type";
+                }
+                else if (functions.hasOwnProperty(value.toLowerCase())) {
+                    return "support.function";
+                }
+                else if (constants.hasOwnProperty(value.toLowerCase())) {
+                    return "support.constant";
+                }
+                else if (colors.hasOwnProperty(value.toLowerCase())) {
+                    return "support.constant.color";
+                }
+                else if (fonts.hasOwnProperty(value.toLowerCase())) {
+                    return "support.constant.fonts";
+                }
+                else {
+                    return "text";
+                }
+            },
+            regex : "\\-?[a-zA-Z_][a-zA-Z0-9_\\-]*"
+        } 
+      ];
+
+    var ruleset = lang.copyArray(base_ruleset);
+    ruleset.unshift({
+        token : "paren.rparen",
+        regex : "\\}",
+        next:   "start"
+    });
+
+    var media_ruleset = lang.copyArray( base_ruleset );
+    media_ruleset.unshift({
+        token : "paren.rparen",
+        regex : "\\}",
+        next:   "media"
+    });
+
+    var base_comment = [{
+          token : "comment", // comment spanning whole line
+          merge : true,
+          regex : ".+"
+    }];
+
+    var comment = lang.copyArray(base_comment);
+    comment.unshift({
+          token : "comment", // closing comment
+          regex : ".*?\\*\\/",
+          next : "start"
+    });
+
+    var media_comment = lang.copyArray(base_comment);
+    media_comment.unshift({
+          token : "comment", // closing comment
+          regex : ".*?\\*\\/",
+          next : "media"
+    });
+
+    var ruleset_comment = lang.copyArray(base_comment);
+    ruleset_comment.unshift({
+          token : "comment", // closing comment
+          regex : ".*?\\*\\/",
+          next : "ruleset"
+    });
+
+    this.$rules = {
+        "start" : [{
+            token : "comment", // multi line comment
+            merge : true,
+            regex : "\\/\\*",
+            next : "comment"
+        }, {
+            token: "paren.lparen",
+            regex: "\\{",
+            next:  "ruleset"
+        }, {
+            token: "string",
+            regex: "@.*?{",
+            next:  "media"
+        },{
+            token: "keyword",
+            regex: "#[a-z0-9-_]+"
+        },{
+            token: "variable",
+            regex: "\\.[a-z0-9-_]+"
+        },{
+            token: "string",
+            regex: ":[a-z0-9-_]+"
+        },{
+            token: "constant",
+            regex: "[a-z0-9-_]+"
+        }],
+
+        "media" : [ {
+            token : "comment", // multi line comment
+            merge : true,
+            regex : "\\/\\*",
+            next : "media_comment"
+        }, {
+            token: "paren.lparen",
+            regex: "\\{",
+            next:  "media_ruleset"
+        },{
+            token: "string",
+            regex: "\\}",
+            next:  "start"
+        },{
+            token: "keyword",
+            regex: "#[a-z0-9-_]+"
+        },{
+            token: "variable",
+            regex: "\\.[a-z0-9-_]+"
+        },{
+            token: "string",
+            regex: ":[a-z0-9-_]+"
+        },{
+            token: "constant",
+            regex: "[a-z0-9-_]+"
+        }],
+
+        "comment" : comment,
+
+        "ruleset" : ruleset,
+        "ruleset_comment" : ruleset_comment,
+
+        "media_ruleset" : media_ruleset,
+        "media_comment" : media_comment
+    };
+};
+
+oop.inherits(CssHighlightRules, TextHighlightRules);
+
+exports.CssHighlightRules = CssHighlightRules;
+
+});
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Ajax.org Code Editor (ACE).
+ *
+ * The Initial Developer of the Original Code is
+ * Ajax.org B.V.
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *      Fabian Jakobs <fabian AT ajax DOT org>
+ *      Mihai Sucan <mihai DOT sucan AT gmail DOT com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+define('ace/mode/javascript_highlight_rules', ['require', 'exports', 'module' , 'ace/lib/oop', 'ace/lib/lang', 'ace/unicode', 'ace/mode/doc_comment_highlight_rules', 'ace/mode/text_highlight_rules'], function(require, exports, module) {
+"use strict";
+
+var oop = require("../lib/oop");
+var lang = require("../lib/lang");
+var unicode = require("../unicode");
+var DocCommentHighlightRules = require("./doc_comment_highlight_rules").DocCommentHighlightRules;
+var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
+
+var JavaScriptHighlightRules = function() {
+
+    // see: https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects
+    var globals = lang.arrayToMap(
+      // Constructors
+        ("Array|Boolean|Date|Function|Iterator|Number|Object|RegExp|String|Proxy|" +
+      // E4X
+         "Namespace|QName|XML|XMLList|" +
+         "ArrayBuffer|Float32Array|Float64Array|Int16Array|Int32Array|Int8Array|" +
+         "Uint16Array|Uint32Array|Uint8Array|Uint8ClampedArray|" +
+      // Errors
+        "Error|EvalError|InternalError|RangeError|ReferenceError|StopIteration|" +
+        "SyntaxError|TypeError|URIError|" +
+      //  Non-constructor functions
+        "decodeURI|decodeURIComponent|encodeURI|encodeURIComponent|eval|isFinite|" +
+        "isNaN|parseFloat|parseInt|" +
+      // Other
+        "JSON|Math|" +
+      // Pseudo
+        "this|arguments|prototype|window|document"
+      ).split("|")
+    );
+
+    var keywords = lang.arrayToMap(
+        ("break|case|catch|continue|default|delete|do|else|finally|for|function|" +
+        "if|in|instanceof|new|return|switch|throw|try|typeof|let|var|while|with|" +
+        "const|yield|import|get|set").split("|")
+    );
+
+    // keywords which can be followed by regular expressions
+    var kwBeforeRe = "case|do|else|finally|in|instanceof|return|throw|try|typeof|yield";
+
+    var deprecated = lang.arrayToMap(
+        ("__parent__|__count__|escape|unescape|with|__proto__").split("|")
+    );
+
+    var definitions = lang.arrayToMap(("const|let|var|function").split("|"));
+
+    var buildinConstants = lang.arrayToMap(
+        ("null|Infinity|NaN|undefined").split("|")
+    );
+
+    var futureReserved = lang.arrayToMap(
+        ("class|enum|extends|super|export|implements|private|" +
+        "public|interface|package|protected|static").split("|")
+    );
+
+    // TODO: Unicode escape sequences
+    var identifierRe = "[" + unicode.packages.L + "\\$_]["
+        + unicode.packages.L
+        + unicode.packages.Mn + unicode.packages.Mc
+        + unicode.packages.Nd
+        + unicode.packages.Pc + "\\$_]*\\b";
+
+    var escapedRe = "\\\\(?:x[0-9a-fA-F]{2}|" + // hex
+        "u[0-9a-fA-F]{4}|" + // unicode
+        "[0-2][0-7]{0,2}|" + // oct
+        "3[0-6][0-7]?|" + // oct
+        "37[0-7]?|" + // oct
+        "[4-7][0-7]?|" + //oct
+        ".)";
+
+    // regexp must not have capturing parentheses. Use (?:) instead.
+    // regexps are ordered -> the first match is used
+
+    this.$rules = {
+        "start" : [
+            {
+                token : "comment",
+                regex : /\/\/.*$/
+            },
+            new DocCommentHighlightRules().getStartRule("doc-start"),
+            {
+                token : "comment", // multi line comment
+                merge : true,
+                regex : /\/\*/,
+                next : "comment"
+            }, {
+                token : "string",
+                regex : "'",
+                next  : "qstring"
+            }, {
+                token : "string",
+                regex : '"',
+                next  : "qqstring"
+            }, {
+                token : "constant.numeric", // hex
+                regex : /0[xX][0-9a-fA-F]+\b/
+            }, {
+                token : "constant.numeric", // float
+                regex : /[+-]?\d+(?:(?:\.\d*)?(?:[eE][+-]?\d+)?)?\b/
+            }, { // match stuff like: Sound.prototype.play = function() { }
+                token : [
+                    "storage.type",
+                    "punctuation.operator",
+                    "support.function",
+                    "punctuation.operator",
+                    "entity.name.function",
+                    "text",
+                    "keyword.operator",
+                    "text",
+                    "storage.type",
+                    "text",
+                    "paren.lparen",
+                    "variable.parameter",
+                    "paren.rparen"
+                ],
+                regex : "(" + identifierRe + ")(\\.)(prototype)(\\.)(" + identifierRe +")(\\s*)(=)(\\s*)(function)(\\s*)(\\()(.*?)(\\))"
+            }, { // match stuff like: Sound.prototype.play = myfunc
+                token : [
+                    "storage.type",
+                    "punctuation.operator",
+                    "support.function",
+                    "punctuation.operator",
+                    "entity.name.function",
+                    "text",
+                    "keyword.operator",
+                    "text"
+                ],
+                regex : "(" + identifierRe + ")(\\.)(prototype)(\\.)(" + identifierRe +")(\\s*)(=)(\\s*)"
+            }, { // match stuff like: Sound.play = function() {  }
+                token : [
+                    "storage.type",
+                    "punctuation.operator",
+                    "entity.name.function",
+                    "text",
+                    "keyword.operator",
+                    "text",
+                    "storage.type",
+                    "text",
+                    "paren.lparen",
+                    "variable.parameter",
+                    "paren.rparen"
+                ],
+                regex : "(" + identifierRe + ")(\\.)(" + identifierRe +")(\\s*)(=)(\\s*)(function)(\\s*)(\\()(.*?)(\\))"
+            }, { // match stuff like: play = function() {  }
+                token : [
+                    "entity.name.function",
+                    "text",
+                    "keyword.operator",
+                    "text",
+                    "storage.type",
+                    "text",
+                    "paren.lparen",
+                    "variable.parameter",
+                    "paren.rparen"
+                ],
+                regex : "(" + identifierRe +")(\\s*)(=)(\\s*)(function)(\\s*)(\\()(.*?)(\\))"
+            }, { // match regular function like: function myFunc(arg) { }
+                token : [
+                    "storage.type",
+                    "text",
+                    "entity.name.function",
+                    "text",
+                    "paren.lparen",
+                    "variable.parameter",
+                    "paren.rparen"
+                ],
+                regex : "(function)(\\s+)(" + identifierRe + ")(\\s*)(\\()(.*?)(\\))"
+            }, { // match stuff like: foobar: function() { }
+                token : [
+                    "entity.name.function",
+                    "text",
+                    "punctuation.operator",
+                    "text",
+                    "storage.type",
+                    "text",
+                    "paren.lparen",
+                    "variable.parameter",
+                    "paren.rparen"
+                ],
+                regex : "(" + identifierRe + ")(\\s*)(:)(\\s*)(function)(\\s*)(\\()(.*?)(\\))"
+            }, { // Attempt to match : function() { } (this is for issues with 'foo': function() { })
+                token : [
+                    "text",
+                    "text",
+                    "storage.type",
+                    "text",
+                    "paren.lparen",
+                    "variable.parameter",
+                    "paren.rparen"
+                ],
+                regex : "(:)(\\s*)(function)?(\\s*)(\\()([^)]*)(\\))"
+            }, {
+                token : "constant.language.boolean",
+                regex : /(?:true|false)\b/
+            }, {
+                token : "keyword",
+                regex : "(?:" + kwBeforeRe + ")\\b",
+                next : "regex_allowed"
+            }, {
+                token : ["punctuation.operator", "support.function"],
+                regex : /(\.)(s(?:h(?:ift|ow(?:Mod(?:elessDialog|alDialog)|Help))|croll(?:X|By(?:Pages|Lines)?|Y|To)?|t(?:opzzzz|rike)|i(?:n|zeToContent|debar|gnText)|ort|u(?:p|b(?:str(?:ing)?)?)|pli(?:ce|t)|e(?:nd|t(?:Re(?:sizable|questHeader)|M(?:i(?:nutes|lliseconds)|onth)|Seconds|Ho(?:tKeys|urs)|Year|Cursor|Time(?:out)?|Interval|ZOptions|Date|UTC(?:M(?:i(?:nutes|lliseconds)|onth)|Seconds|Hours|Date|FullYear)|FullYear|Active)|arch)|qrt|lice|avePreferences|mall)|h(?:ome|andleEvent)|navigate|c(?:har(?:CodeAt|At)|o(?:s|n(?:cat|textual|firm)|mpile)|eil|lear(?:Timeout|Interval)?|a(?:ptureEvents|ll)|reate(?:StyleSheet|Popup|EventObject))|t(?:o(?:GMTString|S(?:tring|ource)|U(?:TCString|pperCase)|Lo(?:caleString|werCase))|est|a(?:n|int(?:Enabled)?))|i(?:s(?:NaN|Finite)|ndexOf|talics)|d(?:isableExternalCapture|ump|etachEvent)|u(?:n(?:shift|taint|escape|watch)|pdateCommands)|j(?:oin|avaEnabled)|p(?:o(?:p|w)|ush|lugins.refresh|a(?:ddings|rse(?:Int|Float)?)|r(?:int|ompt|eference))|e(?:scape|nableExternalCapture|val|lementFromPoint|x(?:p|ec(?:Script|Command)?))|valueOf|UTC|queryCommand(?:State|Indeterm|Enabled|Value)|f(?:i(?:nd|le(?:ModifiedDate|Size|CreatedDate|UpdatedDate)|xed)|o(?:nt(?:size|color)|rward)|loor|romCharCode)|watch|l(?:ink|o(?:ad|g)|astIndexOf)|a(?:sin|nchor|cos|t(?:tachEvent|ob|an(?:2)?)|pply|lert|b(?:s|ort))|r(?:ou(?:nd|teEvents)|e(?:size(?:By|To)|calc|turnValue|place|verse|l(?:oad|ease(?:Capture|Events)))|andom)|g(?:o|et(?:ResponseHeader|M(?:i(?:nutes|lliseconds)|onth)|Se(?:conds|lection)|Hours|Year|Time(?:zoneOffset)?|Da(?:y|te)|UTC(?:M(?:i(?:nutes|lliseconds)|onth)|Seconds|Hours|Da(?:y|te)|FullYear)|FullYear|A(?:ttention|llResponseHeaders)))|m(?:in|ove(?:B(?:y|elow)|To(?:Absolute)?|Above)|ergeAttributes|a(?:tch|rgins|x))|b(?:toa|ig|o(?:ld|rderWidths)|link|ack))\b(?=\()/
+            }, {
+                token : ["punctuation.operator", "support.function.dom"],
+                regex : /(\.)(s(?:ub(?:stringData|mit)|plitText|e(?:t(?:NamedItem|Attribute(?:Node)?)|lect))|has(?:ChildNodes|Feature)|namedItem|c(?:l(?:ick|o(?:se|neNode))|reate(?:C(?:omment|DATASection|aption)|T(?:Head|extNode|Foot)|DocumentFragment|ProcessingInstruction|E(?:ntityReference|lement)|Attribute))|tabIndex|i(?:nsert(?:Row|Before|Cell|Data)|tem)|open|delete(?:Row|C(?:ell|aption)|T(?:Head|Foot)|Data)|focus|write(?:ln)?|a(?:dd|ppend(?:Child|Data))|re(?:set|place(?:Child|Data)|move(?:NamedItem|Child|Attribute(?:Node)?)?)|get(?:NamedItem|Element(?:sBy(?:Name|TagName)|ById)|Attribute(?:Node)?)|blur)\b(?=\()/
+            }, {
+                token : ["punctuation.operator", "support.constant"],
+                regex : /(\.)(s(?:ystemLanguage|cr(?:ipts|ollbars|een(?:X|Y|Top|Left))|t(?:yle(?:Sheets)?|atus(?:Text|bar)?)|ibling(?:Below|Above)|ource|uffixes|e(?:curity(?:Policy)?|l(?:ection|f)))|h(?:istory|ost(?:name)?|as(?:h|Focus))|y|X(?:MLDocument|SLDocument)|n(?:ext|ame(?:space(?:s|URI)|Prop))|M(?:IN_VALUE|AX_VALUE)|c(?:haracterSet|o(?:n(?:structor|trollers)|okieEnabled|lorDepth|mp(?:onents|lete))|urrent|puClass|l(?:i(?:p(?:boardData)?|entInformation)|osed|asses)|alle(?:e|r)|rypto)|t(?:o(?:olbar|p)|ext(?:Transform|Indent|Decoration|Align)|ags)|SQRT(?:1_2|2)|i(?:n(?:ner(?:Height|Width)|put)|ds|gnoreCase)|zIndex|o(?:scpu|n(?:readystatechange|Line)|uter(?:Height|Width)|p(?:sProfile|ener)|ffscreenBuffering)|NEGATIVE_INFINITY|d(?:i(?:splay|alog(?:Height|Top|Width|Left|Arguments)|rectories)|e(?:scription|fault(?:Status|Ch(?:ecked|arset)|View)))|u(?:ser(?:Profile|Language|Agent)|n(?:iqueID|defined)|pdateInterval)|_content|p(?:ixelDepth|ort|ersonalbar|kcs11|l(?:ugins|atform)|a(?:thname|dding(?:Right|Bottom|Top|Left)|rent(?:Window|Layer)?|ge(?:X(?:Offset)?|Y(?:Offset)?))|r(?:o(?:to(?:col|type)|duct(?:Sub)?|mpter)|e(?:vious|fix)))|e(?:n(?:coding|abledPlugin)|x(?:ternal|pando)|mbeds)|v(?:isibility|endor(?:Sub)?|Linkcolor)|URLUnencoded|P(?:I|OSITIVE_INFINITY)|f(?:ilename|o(?:nt(?:Size|Family|Weight)|rmName)|rame(?:s|Element)|gColor)|E|whiteSpace|l(?:i(?:stStyleType|n(?:eHeight|kColor))|o(?:ca(?:tion(?:bar)?|lName)|wsrc)|e(?:ngth|ft(?:Context)?)|a(?:st(?:M(?:odified|atch)|Index|Paren)|yer(?:s|X)|nguage))|a(?:pp(?:MinorVersion|Name|Co(?:deName|re)|Version)|vail(?:Height|Top|Width|Left)|ll|r(?:ity|guments)|Linkcolor|bove)|r(?:ight(?:Context)?|e(?:sponse(?:XML|Text)|adyState))|global|x|m(?:imeTypes|ultiline|enubar|argin(?:Right|Bottom|Top|Left))|L(?:N(?:10|2)|OG(?:10E|2E))|b(?:o(?:ttom|rder(?:Width|RightWidth|BottomWidth|Style|Color|TopWidth|LeftWidth))|ufferDepth|elow|ackground(?:Color|Image)))\b/
+            }, {
+                token : ["storage.type", "punctuation.operator", "support.function.firebug"],
+                regex : /(console)(\.)(warn|info|log|error|time|timeEnd|assert)\b/
+            }, {
+                token : function(value) {
+                    if (globals.hasOwnProperty(value))
+                        return "variable.language";
+                    else if (deprecated.hasOwnProperty(value))
+                        return "invalid.deprecated";
+                    else if (definitions.hasOwnProperty(value))
+                        return "storage.type";
+                    else if (keywords.hasOwnProperty(value))
+                        return "keyword";
+                    else if (buildinConstants.hasOwnProperty(value))
+                        return "constant.language";
+                    else if (futureReserved.hasOwnProperty(value))
+                        return "invalid.illegal";
+                    else if (value == "debugger")
+                        return "invalid.deprecated";
+                    else
+                        return "identifier";
+                },
+                regex : identifierRe
+            }, {
+                token : "keyword.operator",
+                regex : /!|\$|%|&|\*|\-\-|\-|\+\+|\+|~|===|==|=|!=|!==|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\|\||\?\:|\*=|%=|\+=|\-=|&=|\^=|\b(?:in|instanceof|new|delete|typeof|void)/,
+                next  : "regex_allowed"
+            }, {
+                token : "punctuation.operator",
+                regex : /\?|\:|\,|\;|\./,
+                next  : "regex_allowed"
+            }, {
+                token : "paren.lparen",
+                regex : /[\[({]/,
+                next  : "regex_allowed"
+            }, {
+                token : "paren.rparen",
+                regex : /[\])}]/
+            }, {
+                token : "keyword.operator",
+                regex : /\/=?/,
+                next  : "regex_allowed"
+            }, {
+                token: "comment",
+                regex: /^#!.*$/
+            }, {
+                token : "text",
+                regex : /\s+/
+            }
+        ],
+        // regular expressions are only allowed after certain tokens. This
+        // makes sure we don't mix up regexps with the divison operator
+        "regex_allowed": [
+            {
+                token : "comment", // multi line comment
+                merge : true,
+                regex : "\\/\\*",
+                next : "comment_regex_allowed"
+            }, {
+                token : "comment",
+                regex : "\\/\\/.*$"
+            }, {
+                token: "string.regexp",
+                regex: "\\/",
+                next: "regex",
+                merge: true
+            }, {
+                token : "text",
+                regex : "\\s+"
+            }, {
+                // immediately return to the start mode without matching
+                // anything
+                token: "empty",
+                regex: "",
+                next: "start"
+            }
+        ],
+        "regex": [
+            {
+                token: "regexp.keyword.operator",
+                regex: "\\\\(?:u[\\da-fA-F]{4}|x[\\da-fA-F]{2}|.)",
+                next: "regex"
+            }, {
+				// flag
+                token: "string.regexp",
+                regex: "/\\w*",
+                next: "start",
+                merge: true
+            }, {
+                token: "string.regexp",
+                regex: "[^\\\\/\\[]+",
+                next: "regex",
+                merge: true
+            }, {
+                token: "string.regexp.charachterclass",
+                regex: "\\[",
+                next: "regex_character_class",
+                merge: true
+            }, {
+                token: "empty",
+                regex: "",
+                next: "start"
+            }
+        ],
+        "regex_character_class": [
+            {
+                token: "regexp.keyword.operator",
+                regex: "\\\\(?:u[\\da-fA-F]{4}|x[\\da-fA-F]{2}|.)",
+                next: "regex_character_class"
+            }, {
+                token: "string.regexp.charachterclass",
+                regex: "]",
+                next: "regex",
+                merge: true
+            }, {
+                token: "string.regexp.charachterclass",
+                regex: "[^\\\\\\]]+",
+                next: "regex_character_class",
+                merge: true
+            }, {
+                token: "empty",
+                regex: "",
+                next: "start"
+            }
+        ],
+        "comment_regex_allowed" : [
+            {
+                token : "comment", // closing comment
+                regex : ".*?\\*\\/",
+                merge : true,
+                next : "regex_allowed"
+            }, {
+                token : "comment", // comment spanning whole line
+                merge : true,
+                regex : ".+"
+            }
+        ],
+        "comment" : [
+            {
+                token : "comment", // closing comment
+                regex : ".*?\\*\\/",
+                merge : true,
+                next : "start"
+            }, {
+                token : "comment", // comment spanning whole line
+                merge : true,
+                regex : ".+"
+            }
+        ],
+        "qqstring" : [
+            {
+                token : "constant.language.escape",
+                regex : escapedRe
+            }, {
+                token : "string",
+                regex : '[^"\\\\]+'
+            }, {
+                token : "string",
+                regex : '"',
+                next  : "start"
+            }
+        ],
+        "qstring" : [
+            {
+                token : "constant.language.escape",
+                regex : escapedRe
+            }, {
+                token : "string",
+                regex : "[^'\\\\]+"
+            }, {
+                token : "string",
+                regex : "'",
+                next  : "start"
+            }
+        ]
+    };
+
+    this.embedRules(DocCommentHighlightRules, "doc-",
+        [ new DocCommentHighlightRules().getEndRule("start") ]);
+};
+
+oop.inherits(JavaScriptHighlightRules, TextHighlightRules);
+
+exports.JavaScriptHighlightRules = JavaScriptHighlightRules;
+});
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Ajax.org Code Editor (ACE).
+ *
+ * The Initial Developer of the Original Code is
+ * Ajax.org B.V.
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *      Fabian Jakobs <fabian AT ajax DOT org>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+define('ace/mode/doc_comment_highlight_rules', ['require', 'exports', 'module' , 'ace/lib/oop', 'ace/mode/text_highlight_rules'], function(require, exports, module) {
+"use strict";
+
+var oop = require("../lib/oop");
+var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
+
+var DocCommentHighlightRules = function() {
+
+    this.$rules = {
+        "start" : [ {
+            token : "comment.doc.tag",
+            regex : "@[\\w\\d_]+" // TODO: fix email addresses
+        }, {
+            token : "comment.doc",
+            merge : true,
+            regex : "\\s+"
+        }, {
+            token : "comment.doc",
+            merge : true,
+            regex : "TODO"
+        }, {
+            token : "comment.doc",
+            merge : true,
+            regex : "[^@\\*]+"
+        }, {
+            token : "comment.doc",
+            merge : true,
+            regex : "."
+        }]
+    };
+};
+
+oop.inherits(DocCommentHighlightRules, TextHighlightRules);
+
+(function() {
+
+    this.getStartRule = function(start) {
+        return {
+            token : "comment.doc", // doc comment
+            merge : true,
+            regex : "\\/\\*(?=\\*)",
+            next  : start
+        };
+    };
+    
+    this.getEndRule = function (start) {
+        return {
+            token : "comment.doc", // closing comment
+            merge : true,
+            regex : "\\*\\/",
+            next  : start
+        };
+    };
+
+}).call(DocCommentHighlightRules.prototype);
+
+exports.DocCommentHighlightRules = DocCommentHighlightRules;
+
+});
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Ajax.org Code Editor (ACE).
+ *
+ * The Initial Developer of the Original Code is
+ * Ajax.org B.V.
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *      Fabian Jakobs <fabian AT ajax DOT org>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+define('ace/mode/xml_util', ['require', 'exports', 'module' , 'ace/lib/lang'], function(require, exports, module) {
+"use strict";
+
+var lang = require("../lib/lang");
+
+var formTags = lang.arrayToMap(
+    ("button|form|input|label|select|textarea").split("|")
+);
+
+var tableTags = lang.arrayToMap(
+    ("table|tbody|td|tfoot|th|tr").split("|")
+);
+
+function string(state) {
+    return [{
+        token : "string",
+        regex : '".*?"'
+    }, {
+        token : "string", // multi line string start
+        merge : true,
+        regex : '["].*',
+        next : state + "_qqstring"
+    }, {
+        token : "string",
+        regex : "'.*?'"
+    }, {
+        token : "string", // multi line string start
+        merge : true,
+        regex : "['].*",
+        next : state + "_qstring"
+    }];
+}
+
+function multiLineString(quote, state) {
+    return [{
+        token : "string",
+        merge : true,
+        regex : ".*?" + quote,
+        next : state
+    }, {
+        token : "string",
+        merge : true,
+        regex : '.+'
+    }];
+}
+
+exports.tag = function(states, name, nextState) {
+    states[name] = [{
+        token : "text",
+        regex : "\\s+"
+    }, {
+        //token : "meta.tag",
+        
+    token : function(value) {
+            if ( value==='a' ) {
+                return "meta.tag.anchor";
+            }
+            else if ( value==='img' ) {
+                return "meta.tag.image";
+            }
+            else if ( value==='script' ) {
+                return "meta.tag.script";
+            }
+            else if ( value==='style' ) {
+                return "meta.tag.style";
+            }
+            else if (formTags.hasOwnProperty(value.toLowerCase())) {
+                return "meta.tag.form";
+            }
+            else if (tableTags.hasOwnProperty(value.toLowerCase())) {
+                return "meta.tag.table";
+            }
+            else {
+                return "meta.tag";
+            }
+        },        
+        merge : true,
+        regex : "[-_a-zA-Z0-9:]+",
+        next : name + "_embed_attribute_list" 
+    }, {
+        token: "empty",
+        regex: "",
+        next : name + "_embed_attribute_list"
+    }];
+
+    states[name + "_qstring"] = multiLineString("'", name + "_embed_attribute_list");
+    states[name + "_qqstring"] = multiLineString("\"", name + "_embed_attribute_list");
+    
+    states[name + "_embed_attribute_list"] = [{
+        token : "meta.tag",
+        merge : true,
+        regex : "\/?>",
+        next : nextState
+    }, {
+        token : "keyword.operator",
+        regex : "="
+    }, {
+        token : "entity.other.attribute-name",
+        regex : "[-_a-zA-Z0-9:]+"
+    }, {
+        token : "constant.numeric", // float
+        regex : "[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"
+    }, {
+        token : "text",
+        regex : "\\s+"
+    }].concat(string(name));
+};
+
+});
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Ajax.org Code Editor (ACE).
+ *
+ * The Initial Developer of the Original Code is
+ * Ajax.org B.V.
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *      Fabian Jakobs <fabian AT ajax DOT org>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+define('ace/mode/matching_brace_outdent', ['require', 'exports', 'module' , 'ace/range'], function(require, exports, module) {
+"use strict";
+
+var Range = require("../range").Range;
+
+var MatchingBraceOutdent = function() {};
+
+(function() {
+
+    this.checkOutdent = function(line, input) {
+        if (! /^\s+$/.test(line))
+            return false;
+
+        return /^\s*\}/.test(input);
+    };
+
+    this.autoOutdent = function(doc, row) {
+        var line = doc.getLine(row);
+        var match = line.match(/^(\s*\})/);
+
+        if (!match) return 0;
+
+        var column = match[1].length;
+        var openBracePos = doc.findMatchingBracket({row: row, column: column});
+
+        if (!openBracePos || openBracePos.row == row) return 0;
+
+        var indent = this.$getIndent(doc.getLine(openBracePos.row));
+        doc.replace(new Range(row, 0, row, column-1), indent);
+    };
+
+    this.$getIndent = function(line) {
+        var match = line.match(/^(\s+)/);
+        if (match) {
+            return match[1];
+        }
+
+        return "";
+    };
+
+}).call(MatchingBraceOutdent.prototype);
+
+exports.MatchingBraceOutdent = MatchingBraceOutdent;
+});
diff --git a/apps/files_texteditor/js/aceeditor/mode-liquid.js b/apps/files_texteditor/js/aceeditor/mode-liquid.js
new file mode 100644
index 0000000000000000000000000000000000000000..1a23cc53ab52224d907259206c2c6785b5e54703
--- /dev/null
+++ b/apps/files_texteditor/js/aceeditor/mode-liquid.js
@@ -0,0 +1 @@
+define("ace/mode/liquid",["require","exports","module","ace/lib/oop","ace/mode/text","ace/tokenizer","ace/mode/liquid_highlight_rules","ace/mode/matching_brace_outdent","ace/range"],function(a,b,c){var d=a("../lib/oop"),e=a("./text").Mode,f=a("../tokenizer").Tokenizer,g=a("./liquid_highlight_rules").LiquidHighlightRules,h=a("./matching_brace_outdent").MatchingBraceOutdent,i=a("../range").Range,j=function(){this.$tokenizer=new f((new g).getRules()),this.$outdent=new h};d.inherits(j,e),function(){this.toggleCommentLines=function(a,b,c,d){var e=!0,f=[],g=/^(\s*)#/;for(var h=c;h<=d;h++)if(!g.test(b.getLine(h))){e=!1;break}if(e){var j=new i(0,0,0,0);for(var h=c;h<=d;h++){var k=b.getLine(h),l=k.match(g);j.start.row=h,j.end.row=h,j.end.column=l[0].length,b.replace(j,l[1])}}else b.indentRows(c,d,"#")},this.getNextLineIndent=function(a,b,c){var d=this.$getIndent(b),e=this.$tokenizer.getLineTokens(b,a),f=e.tokens,g=e.state;if(f.length&&f[f.length-1].type=="comment")return d;if(a=="start"){var h=b.match(/^.*[\{\(\[]\s*$/);h&&(d+=c)}return d},this.checkOutdent=function(a,b,c){return this.$outdent.checkOutdent(b,c)},this.autoOutdent=function(a,b,c){this.$outdent.autoOutdent(b,c)}}.call(j.prototype),b.Mode=j}),define("ace/mode/liquid_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/css_highlight_rules","ace/mode/javascript_highlight_rules","ace/lib/lang","ace/mode/xml_util","ace/mode/text_highlight_rules"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("./css_highlight_rules").CssHighlightRules,f=a("./javascript_highlight_rules").JavaScriptHighlightRules,g=a("../lib/lang"),h=a("./xml_util"),i=a("./text_highlight_rules").TextHighlightRules,j=function(){var a=g.arrayToMap("date|capitalize|downcase|upcase|first|last|join|sort|map|size|escape|escape_once|strip_html|strip_newlines|newline_to_br|replace|replace_first|truncate|truncatewords|prepend|append|minus|plus|times|divided_by|split".split("|")),b=g.arrayToMap("capture|endcapture|case|endcase|when|comment|endcomment|cycle|for|endfor|in|reversed|if|endif|else|elsif|include|endinclude|unless|endunless|style|text|image|widget|plugin|marker|endmarker|tablerow|endtablerow".split("|")),c=g.arrayToMap(["forloop"]),d=g.arrayToMap("assign".split("|"));this.$rules={start:[{token:"variable",regex:"{%",next:"liquid_start"},{token:"variable",regex:"{{",next:"liquid_start"},{token:"meta.tag",merge:!0,regex:"<\\!\\[CDATA\\[",next:"cdata"},{token:"xml_pe",regex:"<\\?.*?\\?>"},{token:"comment",merge:!0,regex:"<\\!--",next:"comment"},{token:"meta.tag",regex:"<(?=\\s*script\\b)",next:"script"},{token:"meta.tag",regex:"<(?=\\s*style\\b)",next:"style"},{token:"meta.tag",regex:"<\\/?",next:"tag"},{token:"text",regex:"\\s+"},{token:"text",regex:"[^<]+"}],cdata:[{token:"text",regex:"\\]\\]>",next:"start"},{token:"text",merge:!0,regex:"\\s+"},{token:"text",merge:!0,regex:".+"}],comment:[{token:"comment",regex:".*?-->",next:"start"},{token:"comment",merge:!0,regex:".+"}],liquid_start:[{token:"variable",regex:"}}",next:"start"},{token:"variable",regex:"%}",next:"start"},{token:"string",regex:'["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'},{token:"string",regex:"['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"},{token:"constant.numeric",regex:"0[xX][0-9a-fA-F]+\\b"},{token:"constant.numeric",regex:"[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"},{token:"constant.language.boolean",regex:"(?:true|false)\\b"},{token:function(e){return a.hasOwnProperty(e)?"support.function":b.hasOwnProperty(e)?"keyword":c.hasOwnProperty(e)?"variable.language":d.hasOwnProperty(e)?"keyword.definition":"identifier"},regex:"[a-zA-Z_$][a-zA-Z0-9_$]*\\b"},{token:"keyword.operator",regex:"/|\\*|\\-|\\+|=|!=|\\?\\:"},{token:"paren.lparen",regex:/[\[\({]/},{token:"paren.rparen",regex:/[\])}]/},{token:"text",regex:"\\s+"}]},h.tag(this.$rules,"tag","start"),h.tag(this.$rules,"style","css-start"),h.tag(this.$rules,"script","js-start"),this.embedRules(f,"js-",[{token:"comment",regex:"\\/\\/.*(?=<\\/script>)",next:"tag"},{token:"meta.tag",regex:"<\\/(?=script)",next:"tag"}]),this.embedRules(e,"css-",[{token:"meta.tag",regex:"<\\/(?=style)",next:"tag"}])};d.inherits(j,i),b.LiquidHighlightRules=j}),define("ace/mode/css_highlight_rules",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/mode/text_highlight_rules"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("../lib/lang"),f=a("./text_highlight_rules").TextHighlightRules,g=function(){var a=e.arrayToMap("animation-fill-mode|alignment-adjust|alignment-baseline|animation-delay|animation-direction|animation-duration|animation-iteration-count|animation-name|animation-play-state|animation-timing-function|animation|appearance|azimuth|backface-visibility|background-attachment|background-break|background-clip|background-color|background-image|background-origin|background-position|background-repeat|background-size|background|baseline-shift|binding|bleed|bookmark-label|bookmark-level|bookmark-state|bookmark-target|border-bottom|border-bottom-color|border-bottom-left-radius|border-bottom-right-radius|border-bottom-style|border-bottom-width|border-collapse|border-color|border-image|border-image-outset|border-image-repeat|border-image-slice|border-image-source|border-image-width|border-left|border-left-color|border-left-style|border-left-width|border-radius|border-right|border-right-color|border-right-style|border-right-width|border-spacing|border-style|border-top|border-top-color|border-top-left-radius|border-top-right-radius|border-top-style|border-top-width|border-width|border|bottom|box-align|box-decoration-break|box-direction|box-flex-group|box-flex|box-lines|box-ordinal-group|box-orient|box-pack|box-shadow|box-sizing|break-after|break-before|break-inside|caption-side|clear|clip|color-profile|color|column-count|column-fill|column-gap|column-rule|column-rule-color|column-rule-style|column-rule-width|column-span|column-width|columns|content|counter-increment|counter-reset|crop|cue-after|cue-before|cue|cursor|direction|display|dominant-baseline|drop-initial-after-adjust|drop-initial-after-align|drop-initial-before-adjust|drop-initial-before-align|drop-initial-size|drop-initial-value|elevation|empty-cells|fit|fit-position|float-offset|float|font-family|font-size|font-size-adjust|font-stretch|font-style|font-variant|font-weight|font|grid-columns|grid-rows|hanging-punctuation|height|hyphenate-after|hyphenate-before|hyphenate-character|hyphenate-lines|hyphenate-resource|hyphens|icon|image-orientation|image-rendering|image-resolution|inline-box-align|left|letter-spacing|line-height|line-stacking-ruby|line-stacking-shift|line-stacking-strategy|line-stacking|list-style-image|list-style-position|list-style-type|list-style|margin-bottom|margin-left|margin-right|margin-top|margin|mark-after|mark-before|mark|marks|marquee-direction|marquee-play-count|marquee-speed|marquee-style|max-height|max-width|min-height|min-width|move-to|nav-down|nav-index|nav-left|nav-right|nav-up|opacity|orphans|outline-color|outline-offset|outline-style|outline-width|outline|overflow-style|overflow-x|overflow-y|overflow|padding-bottom|padding-left|padding-right|padding-top|padding|page-break-after|page-break-before|page-break-inside|page-policy|page|pause-after|pause-before|pause|perspective-origin|perspective|phonemes|pitch-range|pitch|play-during|position|presentation-level|punctuation-trim|quotes|rendering-intent|resize|rest-after|rest-before|rest|richness|right|rotation-point|rotation|ruby-align|ruby-overhang|ruby-position|ruby-span|size|speak-header|speak-numeral|speak-punctuation|speak|speech-rate|stress|string-set|table-layout|target-name|target-new|target-position|target|text-align-last|text-align|text-decoration|text-emphasis|text-height|text-indent|text-justify|text-outline|text-shadow|text-transform|text-wrap|top|transform-origin|transform-style|transform|transition-delay|transition-duration|transition-property|transition-timing-function|transition|unicode-bidi|vertical-align|visibility|voice-balance|voice-duration|voice-family|voice-pitch-range|voice-pitch|voice-rate|voice-stress|voice-volume|volume|white-space-collapse|white-space|widows|width|word-break|word-spacing|word-wrap|z-index".split("|")),b=e.arrayToMap("rgb|rgba|url|attr|counter|counters".split("|")),c=e.arrayToMap("absolute|after-edge|after|all-scroll|all|alphabetic|always|antialiased|armenian|auto|avoid-column|avoid-page|avoid|balance|baseline|before-edge|before|below|bidi-override|block-line-height|block|bold|bolder|border-box|both|bottom|box|break-all|break-word|capitalize|caps-height|caption|center|central|char|circle|cjk-ideographic|clone|close-quote|col-resize|collapse|column|consider-shifts|contain|content-box|cover|crosshair|cubic-bezier|dashed|decimal-leading-zero|decimal|default|disabled|disc|disregard-shifts|distribute-all-lines|distribute-letter|distribute-space|distribute|dotted|double|e-resize|ease-in|ease-in-out|ease-out|ease|ellipsis|end|exclude-ruby|fill|fixed|font-size|font|georgian|glyphs|grid-height|groove|hand|hanging|hebrew|help|hidden|hiragana-iroha|hiragana|horizontal|icon|ideograph-alpha|ideograph-numeric|ideograph-parenthesis|ideograph-space|ideographic|inactive|include-ruby|inherit|initial|inline-block|inline-box|inline-line-height|inline-table|inline|inset|inside|inter-ideograph|inter-word|invert|italic|justify|katakana-iroha|katakana|keep-all|last|left|lighter|line-edge|line-through|line|linear|list-item|local|loose|lower-alpha|lower-greek|lower-latin|lower-roman|lowercase|lr-tb|ltr|mathematical|max-height|max-size|medium|menu|message-box|middle|move|n-resize|ne-resize|newspaper|no-change|no-close-quote|no-drop|no-open-quote|no-repeat|none|normal|not-allowed|nowrap|nw-resize|oblique|open-quote|outset|outside|overline|padding-box|page|pointer|pre-line|pre-wrap|pre|preserve-3d|progress|relative|repeat-x|repeat-y|repeat|replaced|reset-size|ridge|right|round|row-resize|rtl|s-resize|scroll|se-resize|separate|slice|small-caps|small-caption|solid|space|square|start|static|status-bar|step-end|step-start|steps|stretch|strict|sub|super|sw-resize|table-caption|table-cell|table-column-group|table-column|table-footer-group|table-header-group|table-row-group|table-row|table|tb-rl|text-after-edge|text-before-edge|text-bottom|text-size|text-top|text|thick|thin|top|transparent|underline|upper-alpha|upper-latin|upper-roman|uppercase|use-script|vertical-ideographic|vertical-text|visible|w-resize|wait|whitespace|z-index|zero".split("|")),d=e.arrayToMap("aqua|black|blue|fuchsia|gray|green|lime|maroon|navy|olive|orange|purple|red|silver|teal|white|yellow".split("|")),f=e.arrayToMap("arial|century|comic|courier|garamond|georgia|helvetica|impact|lucida|symbol|system|tahoma|times|trebuchet|utopia|verdana|webdings|sans-serif|serif|monospace".split("|")),g="\\-?(?:(?:[0-9]+)|(?:[0-9]*\\.[0-9]+))",h="(\\:+)\\b(after|before|first-letter|first-line|moz-selection|selection)\\b",i="(:)\\b(active|checked|disabled|empty|enabled|first-child|first-of-type|focus|hover|indeterminate|invalid|last-child|last-of-type|link|not|nth-child|nth-last-child|nth-last-of-type|nth-of-type|only-child|only-of-type|required|root|target|valid|visited)\\b",j=[{token:"comment",merge:!0,regex:"\\/\\*",next:"ruleset_comment"},{token:"string",regex:'["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'},{token:"string",regex:"['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"},{token:["constant.numeric","keyword"],regex:"("+g+")(ch|cm|deg|em|ex|fr|gd|grad|Hz|in|kHz|mm|ms|pc|pt|px|rad|rem|s|turn|vh|vm|vw|%)"},{token:["constant.numeric"],regex:"([0-9]+)"},{token:"constant.numeric",regex:"#[a-f0-9]{6}"},{token:"constant.numeric",regex:"#[a-f0-9]{3}"},{token:["punctuation","entity.other.attribute-name.pseudo-element.css"],regex:h},{token:["punctuation","entity.other.attribute-name.pseudo-class.css"],regex:i},{token:function(e){return a.hasOwnProperty(e.toLowerCase())?"support.type":b.hasOwnProperty(e.toLowerCase())?"support.function":c.hasOwnProperty(e.toLowerCase())?"support.constant":d.hasOwnProperty(e.toLowerCase())?"support.constant.color":f.hasOwnProperty(e.toLowerCase())?"support.constant.fonts":"text"},regex:"\\-?[a-zA-Z_][a-zA-Z0-9_\\-]*"}],k=e.copyArray(j);k.unshift({token:"paren.rparen",regex:"\\}",next:"start"});var l=e.copyArray(j);l.unshift({token:"paren.rparen",regex:"\\}",next:"media"});var m=[{token:"comment",merge:!0,regex:".+"}],n=e.copyArray(m);n.unshift({token:"comment",regex:".*?\\*\\/",next:"start"});var o=e.copyArray(m);o.unshift({token:"comment",regex:".*?\\*\\/",next:"media"});var p=e.copyArray(m);p.unshift({token:"comment",regex:".*?\\*\\/",next:"ruleset"}),this.$rules={start:[{token:"comment",merge:!0,regex:"\\/\\*",next:"comment"},{token:"paren.lparen",regex:"\\{",next:"ruleset"},{token:"string",regex:"@.*?{",next:"media"},{token:"keyword",regex:"#[a-z0-9-_]+"},{token:"variable",regex:"\\.[a-z0-9-_]+"},{token:"string",regex:":[a-z0-9-_]+"},{token:"constant",regex:"[a-z0-9-_]+"}],media:[{token:"comment",merge:!0,regex:"\\/\\*",next:"media_comment"},{token:"paren.lparen",regex:"\\{",next:"media_ruleset"},{token:"string",regex:"\\}",next:"start"},{token:"keyword",regex:"#[a-z0-9-_]+"},{token:"variable",regex:"\\.[a-z0-9-_]+"},{token:"string",regex:":[a-z0-9-_]+"},{token:"constant",regex:"[a-z0-9-_]+"}],comment:n,ruleset:k,ruleset_comment:p,media_ruleset:l,media_comment:o}};d.inherits(g,f),b.CssHighlightRules=g}),define("ace/mode/javascript_highlight_rules",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/unicode","ace/mode/doc_comment_highlight_rules","ace/mode/text_highlight_rules"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("../lib/lang"),f=a("../unicode"),g=a("./doc_comment_highlight_rules").DocCommentHighlightRules,h=a("./text_highlight_rules").TextHighlightRules,i=function(){var a=e.arrayToMap("Array|Boolean|Date|Function|Iterator|Number|Object|RegExp|String|Proxy|Namespace|QName|XML|XMLList|ArrayBuffer|Float32Array|Float64Array|Int16Array|Int32Array|Int8Array|Uint16Array|Uint32Array|Uint8Array|Uint8ClampedArray|Error|EvalError|InternalError|RangeError|ReferenceError|StopIteration|SyntaxError|TypeError|URIError|decodeURI|decodeURIComponent|encodeURI|encodeURIComponent|eval|isFinite|isNaN|parseFloat|parseInt|JSON|Math|this|arguments|prototype|window|document".split("|")),b=e.arrayToMap("break|case|catch|continue|default|delete|do|else|finally|for|function|if|in|instanceof|new|return|switch|throw|try|typeof|let|var|while|with|const|yield|import|get|set".split("|")),c="case|do|else|finally|in|instanceof|return|throw|try|typeof|yield",d=e.arrayToMap("__parent__|__count__|escape|unescape|with|__proto__".split("|")),h=e.arrayToMap("const|let|var|function".split("|")),i=e.arrayToMap("null|Infinity|NaN|undefined".split("|")),j=e.arrayToMap("class|enum|extends|super|export|implements|private|public|interface|package|protected|static".split("|")),k="["+f.packages.L+"\\$_]["+f.packages.L+f.packages.Mn+f.packages.Mc+f.packages.Nd+f.packages.Pc+"\\$_]*\\b",l="\\\\(?:x[0-9a-fA-F]{2}|u[0-9a-fA-F]{4}|[0-2][0-7]{0,2}|3[0-6][0-7]?|37[0-7]?|[4-7][0-7]?|.)";this.$rules={start:[{token:"comment",regex:/\/\/.*$/},(new g).getStartRule("doc-start"),{token:"comment",merge:!0,regex:/\/\*/,next:"comment"},{token:"string",regex:"'",next:"qstring"},{token:"string",regex:'"',next:"qqstring"},{token:"constant.numeric",regex:/0[xX][0-9a-fA-F]+\b/},{token:"constant.numeric",regex:/[+-]?\d+(?:(?:\.\d*)?(?:[eE][+-]?\d+)?)?\b/},{token:["storage.type","punctuation.operator","support.function","punctuation.operator","entity.name.function","text","keyword.operator","text","storage.type","text","paren.lparen","variable.parameter","paren.rparen"],regex:"("+k+")(\\.)(prototype)(\\.)("+k+")(\\s*)(=)(\\s*)(function)(\\s*)(\\()(.*?)(\\))"},{token:["storage.type","punctuation.operator","support.function","punctuation.operator","entity.name.function","text","keyword.operator","text"],regex:"("+k+")(\\.)(prototype)(\\.)("+k+")(\\s*)(=)(\\s*)"},{token:["storage.type","punctuation.operator","entity.name.function","text","keyword.operator","text","storage.type","text","paren.lparen","variable.parameter","paren.rparen"],regex:"("+k+")(\\.)("+k+")(\\s*)(=)(\\s*)(function)(\\s*)(\\()(.*?)(\\))"},{token:["entity.name.function","text","keyword.operator","text","storage.type","text","paren.lparen","variable.parameter","paren.rparen"],regex:"("+k+")(\\s*)(=)(\\s*)(function)(\\s*)(\\()(.*?)(\\))"},{token:["storage.type","text","entity.name.function","text","paren.lparen","variable.parameter","paren.rparen"],regex:"(function)(\\s+)("+k+")(\\s*)(\\()(.*?)(\\))"},{token:["entity.name.function","text","punctuation.operator","text","storage.type","text","paren.lparen","variable.parameter","paren.rparen"],regex:"("+k+")(\\s*)(:)(\\s*)(function)(\\s*)(\\()(.*?)(\\))"},{token:["text","text","storage.type","text","paren.lparen","variable.parameter","paren.rparen"],regex:"(:)(\\s*)(function)?(\\s*)(\\()([^)]*)(\\))"},{token:"constant.language.boolean",regex:/(?:true|false)\b/},{token:"keyword",regex:"(?:"+c+")\\b",next:"regex_allowed"},{token:["punctuation.operator","support.function"],regex:/(\.)(s(?:h(?:ift|ow(?:Mod(?:elessDialog|alDialog)|Help))|croll(?:X|By(?:Pages|Lines)?|Y|To)?|t(?:opzzzz|rike)|i(?:n|zeToContent|debar|gnText)|ort|u(?:p|b(?:str(?:ing)?)?)|pli(?:ce|t)|e(?:nd|t(?:Re(?:sizable|questHeader)|M(?:i(?:nutes|lliseconds)|onth)|Seconds|Ho(?:tKeys|urs)|Year|Cursor|Time(?:out)?|Interval|ZOptions|Date|UTC(?:M(?:i(?:nutes|lliseconds)|onth)|Seconds|Hours|Date|FullYear)|FullYear|Active)|arch)|qrt|lice|avePreferences|mall)|h(?:ome|andleEvent)|navigate|c(?:har(?:CodeAt|At)|o(?:s|n(?:cat|textual|firm)|mpile)|eil|lear(?:Timeout|Interval)?|a(?:ptureEvents|ll)|reate(?:StyleSheet|Popup|EventObject))|t(?:o(?:GMTString|S(?:tring|ource)|U(?:TCString|pperCase)|Lo(?:caleString|werCase))|est|a(?:n|int(?:Enabled)?))|i(?:s(?:NaN|Finite)|ndexOf|talics)|d(?:isableExternalCapture|ump|etachEvent)|u(?:n(?:shift|taint|escape|watch)|pdateCommands)|j(?:oin|avaEnabled)|p(?:o(?:p|w)|ush|lugins.refresh|a(?:ddings|rse(?:Int|Float)?)|r(?:int|ompt|eference))|e(?:scape|nableExternalCapture|val|lementFromPoint|x(?:p|ec(?:Script|Command)?))|valueOf|UTC|queryCommand(?:State|Indeterm|Enabled|Value)|f(?:i(?:nd|le(?:ModifiedDate|Size|CreatedDate|UpdatedDate)|xed)|o(?:nt(?:size|color)|rward)|loor|romCharCode)|watch|l(?:ink|o(?:ad|g)|astIndexOf)|a(?:sin|nchor|cos|t(?:tachEvent|ob|an(?:2)?)|pply|lert|b(?:s|ort))|r(?:ou(?:nd|teEvents)|e(?:size(?:By|To)|calc|turnValue|place|verse|l(?:oad|ease(?:Capture|Events)))|andom)|g(?:o|et(?:ResponseHeader|M(?:i(?:nutes|lliseconds)|onth)|Se(?:conds|lection)|Hours|Year|Time(?:zoneOffset)?|Da(?:y|te)|UTC(?:M(?:i(?:nutes|lliseconds)|onth)|Seconds|Hours|Da(?:y|te)|FullYear)|FullYear|A(?:ttention|llResponseHeaders)))|m(?:in|ove(?:B(?:y|elow)|To(?:Absolute)?|Above)|ergeAttributes|a(?:tch|rgins|x))|b(?:toa|ig|o(?:ld|rderWidths)|link|ack))\b(?=\()/},{token:["punctuation.operator","support.function.dom"],regex:/(\.)(s(?:ub(?:stringData|mit)|plitText|e(?:t(?:NamedItem|Attribute(?:Node)?)|lect))|has(?:ChildNodes|Feature)|namedItem|c(?:l(?:ick|o(?:se|neNode))|reate(?:C(?:omment|DATASection|aption)|T(?:Head|extNode|Foot)|DocumentFragment|ProcessingInstruction|E(?:ntityReference|lement)|Attribute))|tabIndex|i(?:nsert(?:Row|Before|Cell|Data)|tem)|open|delete(?:Row|C(?:ell|aption)|T(?:Head|Foot)|Data)|focus|write(?:ln)?|a(?:dd|ppend(?:Child|Data))|re(?:set|place(?:Child|Data)|move(?:NamedItem|Child|Attribute(?:Node)?)?)|get(?:NamedItem|Element(?:sBy(?:Name|TagName)|ById)|Attribute(?:Node)?)|blur)\b(?=\()/},{token:["punctuation.operator","support.constant"],regex:/(\.)(s(?:ystemLanguage|cr(?:ipts|ollbars|een(?:X|Y|Top|Left))|t(?:yle(?:Sheets)?|atus(?:Text|bar)?)|ibling(?:Below|Above)|ource|uffixes|e(?:curity(?:Policy)?|l(?:ection|f)))|h(?:istory|ost(?:name)?|as(?:h|Focus))|y|X(?:MLDocument|SLDocument)|n(?:ext|ame(?:space(?:s|URI)|Prop))|M(?:IN_VALUE|AX_VALUE)|c(?:haracterSet|o(?:n(?:structor|trollers)|okieEnabled|lorDepth|mp(?:onents|lete))|urrent|puClass|l(?:i(?:p(?:boardData)?|entInformation)|osed|asses)|alle(?:e|r)|rypto)|t(?:o(?:olbar|p)|ext(?:Transform|Indent|Decoration|Align)|ags)|SQRT(?:1_2|2)|i(?:n(?:ner(?:Height|Width)|put)|ds|gnoreCase)|zIndex|o(?:scpu|n(?:readystatechange|Line)|uter(?:Height|Width)|p(?:sProfile|ener)|ffscreenBuffering)|NEGATIVE_INFINITY|d(?:i(?:splay|alog(?:Height|Top|Width|Left|Arguments)|rectories)|e(?:scription|fault(?:Status|Ch(?:ecked|arset)|View)))|u(?:ser(?:Profile|Language|Agent)|n(?:iqueID|defined)|pdateInterval)|_content|p(?:ixelDepth|ort|ersonalbar|kcs11|l(?:ugins|atform)|a(?:thname|dding(?:Right|Bottom|Top|Left)|rent(?:Window|Layer)?|ge(?:X(?:Offset)?|Y(?:Offset)?))|r(?:o(?:to(?:col|type)|duct(?:Sub)?|mpter)|e(?:vious|fix)))|e(?:n(?:coding|abledPlugin)|x(?:ternal|pando)|mbeds)|v(?:isibility|endor(?:Sub)?|Linkcolor)|URLUnencoded|P(?:I|OSITIVE_INFINITY)|f(?:ilename|o(?:nt(?:Size|Family|Weight)|rmName)|rame(?:s|Element)|gColor)|E|whiteSpace|l(?:i(?:stStyleType|n(?:eHeight|kColor))|o(?:ca(?:tion(?:bar)?|lName)|wsrc)|e(?:ngth|ft(?:Context)?)|a(?:st(?:M(?:odified|atch)|Index|Paren)|yer(?:s|X)|nguage))|a(?:pp(?:MinorVersion|Name|Co(?:deName|re)|Version)|vail(?:Height|Top|Width|Left)|ll|r(?:ity|guments)|Linkcolor|bove)|r(?:ight(?:Context)?|e(?:sponse(?:XML|Text)|adyState))|global|x|m(?:imeTypes|ultiline|enubar|argin(?:Right|Bottom|Top|Left))|L(?:N(?:10|2)|OG(?:10E|2E))|b(?:o(?:ttom|rder(?:Width|RightWidth|BottomWidth|Style|Color|TopWidth|LeftWidth))|ufferDepth|elow|ackground(?:Color|Image)))\b/},{token:["storage.type","punctuation.operator","support.function.firebug"],regex:/(console)(\.)(warn|info|log|error|time|timeEnd|assert)\b/},{token:function(c){return a.hasOwnProperty(c)?"variable.language":d.hasOwnProperty(c)?"invalid.deprecated":h.hasOwnProperty(c)?"storage.type":b.hasOwnProperty(c)?"keyword":i.hasOwnProperty(c)?"constant.language":j.hasOwnProperty(c)?"invalid.illegal":c=="debugger"?"invalid.deprecated":"identifier"},regex:k},{token:"keyword.operator",regex:/!|\$|%|&|\*|\-\-|\-|\+\+|\+|~|===|==|=|!=|!==|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\|\||\?\:|\*=|%=|\+=|\-=|&=|\^=|\b(?:in|instanceof|new|delete|typeof|void)/,next:"regex_allowed"},{token:"punctuation.operator",regex:/\?|\:|\,|\;|\./,next:"regex_allowed"},{token:"paren.lparen",regex:/[\[({]/,next:"regex_allowed"},{token:"paren.rparen",regex:/[\])}]/},{token:"keyword.operator",regex:/\/=?/,next:"regex_allowed"},{token:"comment",regex:/^#!.*$/},{token:"text",regex:/\s+/}],regex_allowed:[{token:"comment",merge:!0,regex:"\\/\\*",next:"comment_regex_allowed"},{token:"comment",regex:"\\/\\/.*$"},{token:"string.regexp",regex:"\\/",next:"regex",merge:!0},{token:"text",regex:"\\s+"},{token:"empty",regex:"",next:"start"}],regex:[{token:"regexp.keyword.operator",regex:"\\\\(?:u[\\da-fA-F]{4}|x[\\da-fA-F]{2}|.)",next:"regex"},{token:"string.regexp",regex:"/\\w*",next:"start",merge:!0},{token:"string.regexp",regex:"[^\\\\/\\[]+",next:"regex",merge:!0},{token:"string.regexp.charachterclass",regex:"\\[",next:"regex_character_class",merge:!0},{token:"empty",regex:"",next:"start"}],regex_character_class:[{token:"regexp.keyword.operator",regex:"\\\\(?:u[\\da-fA-F]{4}|x[\\da-fA-F]{2}|.)",next:"regex_character_class"},{token:"string.regexp.charachterclass",regex:"]",next:"regex",merge:!0},{token:"string.regexp.charachterclass",regex:"[^\\\\\\]]+",next:"regex_character_class",merge:!0},{token:"empty",regex:"",next:"start"}],comment_regex_allowed:[{token:"comment",regex:".*?\\*\\/",merge:!0,next:"regex_allowed"},{token:"comment",merge:!0,regex:".+"}],comment:[{token:"comment",regex:".*?\\*\\/",merge:!0,next:"start"},{token:"comment",merge:!0,regex:".+"}],qqstring:[{token:"constant.language.escape",regex:l},{token:"string",regex:'[^"\\\\]+'},{token:"string",regex:'"',next:"start"}],qstring:[{token:"constant.language.escape",regex:l},{token:"string",regex:"[^'\\\\]+"},{token:"string",regex:"'",next:"start"}]},this.embedRules(g,"doc-",[(new g).getEndRule("start")])};d.inherits(i,h),b.JavaScriptHighlightRules=i}),define("ace/mode/doc_comment_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("./text_highlight_rules").TextHighlightRules,f=function(){this.$rules={start:[{token:"comment.doc.tag",regex:"@[\\w\\d_]+"},{token:"comment.doc",merge:!0,regex:"\\s+"},{token:"comment.doc",merge:!0,regex:"TODO"},{token:"comment.doc",merge:!0,regex:"[^@\\*]+"},{token:"comment.doc",merge:!0,regex:"."}]}};d.inherits(f,e),function(){this.getStartRule=function(a){return{token:"comment.doc",merge:!0,regex:"\\/\\*(?=\\*)",next:a}},this.getEndRule=function(a){return{token:"comment.doc",merge:!0,regex:"\\*\\/",next:a}}}.call(f.prototype),b.DocCommentHighlightRules=f}),define("ace/mode/xml_util",["require","exports","module","ace/lib/lang"],function(a,b,c){function g(a){return[{token:"string",regex:'".*?"'},{token:"string",merge:!0,regex:'["].*',next:a+"_qqstring"},{token:"string",regex:"'.*?'"},{token:"string",merge:!0,regex:"['].*",next:a+"_qstring"}]}function h(a,b){return[{token:"string",merge:!0,regex:".*?"+a,next:b},{token:"string",merge:!0,regex:".+"}]}"use strict";var d=a("../lib/lang"),e=d.arrayToMap("button|form|input|label|select|textarea".split("|")),f=d.arrayToMap("table|tbody|td|tfoot|th|tr".split("|"));b.tag=function(a,b,c){a[b]=[{token:"text",regex:"\\s+"},{token:function(a){return a==="a"?"meta.tag.anchor":a==="img"?"meta.tag.image":a==="script"?"meta.tag.script":a==="style"?"meta.tag.style":e.hasOwnProperty(a.toLowerCase())?"meta.tag.form":f.hasOwnProperty(a.toLowerCase())?"meta.tag.table":"meta.tag"},merge:!0,regex:"[-_a-zA-Z0-9:]+",next:b+"_embed_attribute_list"},{token:"empty",regex:"",next:b+"_embed_attribute_list"}],a[b+"_qstring"]=h("'",b+"_embed_attribute_list"),a[b+"_qqstring"]=h('"',b+"_embed_attribute_list"),a[b+"_embed_attribute_list"]=[{token:"meta.tag",merge:!0,regex:"/?>",next:c},{token:"keyword.operator",regex:"="},{token:"entity.other.attribute-name",regex:"[-_a-zA-Z0-9:]+"},{token:"constant.numeric",regex:"[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"},{token:"text",regex:"\\s+"}].concat(g(b))}}),define("ace/mode/matching_brace_outdent",["require","exports","module","ace/range"],function(a,b,c){"use strict";var d=a("../range").Range,e=function(){};(function(){this.checkOutdent=function(a,b){return/^\s+$/.test(a)?/^\s*\}/.test(b):!1},this.autoOutdent=function(a,b){var c=a.getLine(b),e=c.match(/^(\s*\})/);if(!e)return 0;var f=e[1].length,g=a.findMatchingBracket({row:b,column:f});if(!g||g.row==b)return 0;var h=this.$getIndent(a.getLine(g.row));a.replace(new d(b,0,b,f-1),h)},this.$getIndent=function(a){var b=a.match(/^(\s+)/);return b?b[1]:""}}).call(e.prototype),b.MatchingBraceOutdent=e})
\ No newline at end of file
diff --git a/apps/files_texteditor/js/aceeditor/mode-lua-uncompressed.js b/apps/files_texteditor/js/aceeditor/mode-lua-uncompressed.js
old mode 100755
new mode 100644
index 454108c6d44cbb436009ca040ee9fb024ed3ab18..c3f875475e9b31628e4cd97b9e0fb5c61269da65
--- a/apps/files_texteditor/js/aceeditor/mode-lua-uncompressed.js
+++ b/apps/files_texteditor/js/aceeditor/mode-lua-uncompressed.js
@@ -521,13 +521,3 @@ oop.inherits(LuaHighlightRules, TextHighlightRules);
 
 exports.LuaHighlightRules = LuaHighlightRules;
 });
-;
-            (function() {
-                window.require(["ace/ace"], function(a) {
-                    if (!window.ace)
-                        window.ace = {};
-                    for (var key in a) if (a.hasOwnProperty(key))
-                        ace[key] = a[key];
-                });
-            })();
-        
\ No newline at end of file
diff --git a/apps/files_texteditor/js/aceeditor/mode-lua.js b/apps/files_texteditor/js/aceeditor/mode-lua.js
old mode 100755
new mode 100644
index 63b812c6bd7d0b8b8c12a5cd8bce800aee4be1cd..8f7471e7bf20093a4613fc5ce299bd6e3ca0bee0
--- a/apps/files_texteditor/js/aceeditor/mode-lua.js
+++ b/apps/files_texteditor/js/aceeditor/mode-lua.js
@@ -1 +1 @@
-define("ace/mode/lua",["require","exports","module","ace/lib/oop","ace/mode/text","ace/tokenizer","ace/mode/lua_highlight_rules"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("./text").Mode,f=a("../tokenizer").Tokenizer,g=a("./lua_highlight_rules").LuaHighlightRules,h=function(){this.$tokenizer=new f((new g).getRules())};d.inherits(h,e),function(){this.getNextLineIndent=function(a,b,c){var d=this.$getIndent(b),e=this.$tokenizer.getLineTokens(b,a),f=e.tokens,g=["function","then","do","repeat"];if(a=="start"){var h=b.match(/^.*[\{\(\[]\s*$/);if(h)d+=c;else for(var i in f){var j=f[i];if(j.type!="keyword")continue;var k=g.indexOf(j.value);if(k!=-1){d+=c;break}}}return d}}.call(h.prototype),b.Mode=h}),define("ace/mode/lua_highlight_rules",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/mode/text_highlight_rules"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("../lib/lang"),f=a("./text_highlight_rules").TextHighlightRules,g=function(){var a=e.arrayToMap("break|do|else|elseif|end|for|function|if|in|local|repeat|return|then|until|while|or|and|not".split("|")),b=e.arrayToMap("true|false|nil|_G|_VERSION".split("|")),c=e.arrayToMap("string|xpcall|package|tostring|print|os|unpack|require|getfenv|setmetatable|next|assert|tonumber|io|rawequal|collectgarbage|getmetatable|module|rawset|math|debug|pcall|table|newproxy|type|coroutine|_G|select|gcinfo|pairs|rawget|loadstring|ipairs|_VERSION|dofile|setfenv|load|error|loadfile|sub|upper|len|gfind|rep|find|match|char|dump|gmatch|reverse|byte|format|gsub|lower|preload|loadlib|loaded|loaders|cpath|config|path|seeall|exit|setlocale|date|getenv|difftime|remove|time|clock|tmpname|rename|execute|lines|write|close|flush|open|output|type|read|stderr|stdin|input|stdout|popen|tmpfile|log|max|acos|huge|ldexp|pi|cos|tanh|pow|deg|tan|cosh|sinh|random|randomseed|frexp|ceil|floor|rad|abs|sqrt|modf|asin|min|mod|fmod|log10|atan2|exp|sin|atan|getupvalue|debug|sethook|getmetatable|gethook|setmetatable|setlocal|traceback|setfenv|getinfo|setupvalue|getlocal|getregistry|getfenv|setn|insert|getn|foreachi|maxn|foreach|concat|sort|remove|resume|yield|status|wrap|create|running".split("|")),d=e.arrayToMap("string|package|os|io|math|debug|table|coroutine".split("|")),f=e.arrayToMap("__add|__sub|__mod|__unm|__concat|__lt|__index|__call|__gc|__metatable|__mul|__div|__pow|__len|__eq|__le|__newindex|__tostring|__mode|__tonumber".split("|")),g=e.arrayToMap("".split("|")),h=e.arrayToMap("setn|foreach|foreachi|gcinfo|log10|maxn".split("|")),i="",j="(?:(?:[1-9]\\d*)|(?:0))",k="(?:0[xX][\\dA-Fa-f]+)",l="(?:"+j+"|"+k+")",m="(?:\\.\\d+)",n="(?:\\d+)",o="(?:(?:"+n+"?"+m+")|(?:"+n+"\\.))",p="(?:"+o+")",q=[];this.$rules={start:[{token:"comment",regex:i+"\\-\\-\\[\\[.*\\]\\]"},{token:"comment",regex:i+"\\-\\-\\[\\=\\[.*\\]\\=\\]"},{token:"comment",regex:i+"\\-\\-\\[\\={2}\\[.*\\]\\={2}\\]"},{token:"comment",regex:i+"\\-\\-\\[\\={3}\\[.*\\]\\={3}\\]"},{token:"comment",regex:i+"\\-\\-\\[\\={4}\\[.*\\]\\={4}\\]"},{token:"comment",regex:i+"\\-\\-\\[\\={5}\\=*\\[.*\\]\\={5}\\=*\\]"},{token:"comment",regex:i+"\\-\\-\\[\\[.*$",merge:!0,next:"qcomment"},{token:"comment",regex:i+"\\-\\-\\[\\=\\[.*$",merge:!0,next:"qcomment1"},{token:"comment",regex:i+"\\-\\-\\[\\={2}\\[.*$",merge:!0,next:"qcomment2"},{token:"comment",regex:i+"\\-\\-\\[\\={3}\\[.*$",merge:!0,next:"qcomment3"},{token:"comment",regex:i+"\\-\\-\\[\\={4}\\[.*$",merge:!0,next:"qcomment4"},{token:function(a){var b=/\-\-\[(\=+)\[/,c;return(c=b.exec(a))!=null&&(c=c[1])!=undefined&&q.push(c.length),"comment"},regex:i+"\\-\\-\\[\\={5}\\=*\\[.*$",merge:!0,next:"qcomment5"},{token:"comment",regex:"\\-\\-.*$"},{token:"string",regex:i+"\\[\\[.*\\]\\]"},{token:"string",regex:i+"\\[\\=\\[.*\\]\\=\\]"},{token:"string",regex:i+"\\[\\={2}\\[.*\\]\\={2}\\]"},{token:"string",regex:i+"\\[\\={3}\\[.*\\]\\={3}\\]"},{token:"string",regex:i+"\\[\\={4}\\[.*\\]\\={4}\\]"},{token:"string",regex:i+"\\[\\={5}\\=*\\[.*\\]\\={5}\\=*\\]"},{token:"string",regex:i+"\\[\\[.*$",merge:!0,next:"qstring"},{token:"string",regex:i+"\\[\\=\\[.*$",merge:!0,next:"qstring1"},{token:"string",regex:i+"\\[\\={2}\\[.*$",merge:!0,next:"qstring2"},{token:"string",regex:i+"\\[\\={3}\\[.*$",merge:!0,next:"qstring3"},{token:"string",regex:i+"\\[\\={4}\\[.*$",merge:!0,next:"qstring4"},{token:function(a){var b=/\[(\=+)\[/,c;return(c=b.exec(a))!=null&&(c=c[1])!=undefined&&q.push(c.length),"string"},regex:i+"\\[\\={5}\\=*\\[.*$",merge:!0,next:"qstring5"},{token:"string",regex:i+'"(?:[^\\\\]|\\\\.)*?"'},{token:"string",regex:i+"'(?:[^\\\\]|\\\\.)*?'"},{token:"constant.numeric",regex:p},{token:"constant.numeric",regex:l+"\\b"},{token:function(e){return a.hasOwnProperty(e)?"keyword":b.hasOwnProperty(e)?"constant.language":g.hasOwnProperty(e)?"invalid.illegal":d.hasOwnProperty(e)?"constant.library":h.hasOwnProperty(e)?"invalid.deprecated":c.hasOwnProperty(e)?"support.function":f.hasOwnProperty(e)?"support.function":"identifier"},regex:"[a-zA-Z_$][a-zA-Z0-9_$]*\\b"},{token:"keyword.operator",regex:"\\+|\\-|\\*|\\/|%|\\#|\\^|~|<|>|<=|=>|==|~=|=|\\:|\\.\\.\\.|\\.\\."},{token:"paren.lparen",regex:"[\\[\\(\\{]"},{token:"paren.rparen",regex:"[\\]\\)\\}]"},{token:"text",regex:"\\s+"}],qcomment:[{token:"comment",regex:"(?:[^\\\\]|\\\\.)*?\\]\\]",next:"start"},{token:"comment",merge:!0,regex:".+"}],qcomment1:[{token:"comment",regex:"(?:[^\\\\]|\\\\.)*?\\]\\=\\]",next:"start"},{token:"comment",merge:!0,regex:".+"}],qcomment2:[{token:"comment",regex:"(?:[^\\\\]|\\\\.)*?\\]\\={2}\\]",next:"start"},{token:"comment",merge:!0,regex:".+"}],qcomment3:[{token:"comment",regex:"(?:[^\\\\]|\\\\.)*?\\]\\={3}\\]",next:"start"},{token:"comment",merge:!0,regex:".+"}],qcomment4:[{token:"comment",regex:"(?:[^\\\\]|\\\\.)*?\\]\\={4}\\]",next:"start"},{token:"comment",merge:!0,regex:".+"}],qcomment5:[{token:function(a){var b=/\](\=+)\]/,c=this.rules.qcomment5[0],d;c.next="start";if((d=b.exec(a))!=null&&(d=d[1])!=undefined){var e=d.length,f;(f=q.pop())!=e&&(q.push(f),c.next="qcomment5")}return"comment"},regex:"(?:[^\\\\]|\\\\.)*?\\]\\={5}\\=*\\]",next:"start"},{token:"comment",merge:!0,regex:".+"}],qstring:[{token:"string",regex:"(?:[^\\\\]|\\\\.)*?\\]\\]",next:"start"},{token:"string",merge:!0,regex:".+"}],qstring1:[{token:"string",regex:"(?:[^\\\\]|\\\\.)*?\\]\\=\\]",next:"start"},{token:"string",merge:!0,regex:".+"}],qstring2:[{token:"string",regex:"(?:[^\\\\]|\\\\.)*?\\]\\={2}\\]",next:"start"},{token:"string",merge:!0,regex:".+"}],qstring3:[{token:"string",regex:"(?:[^\\\\]|\\\\.)*?\\]\\={3}\\]",next:"start"},{token:"string",merge:!0,regex:".+"}],qstring4:[{token:"string",regex:"(?:[^\\\\]|\\\\.)*?\\]\\={4}\\]",next:"start"},{token:"string",merge:!0,regex:".+"}],qstring5:[{token:function(a){var b=/\](\=+)\]/,c=this.rules.qstring5[0],d;c.next="start";if((d=b.exec(a))!=null&&(d=d[1])!=undefined){var e=d.length,f;(f=q.pop())!=e&&(q.push(f),c.next="qstring5")}return"string"},regex:"(?:[^\\\\]|\\\\.)*?\\]\\={5}\\=*\\]",next:"start"},{token:"string",merge:!0,regex:".+"}]}};d.inherits(g,f),b.LuaHighlightRules=g}),function(){window.require(["ace/ace"],function(a){window.ace||(window.ace={});for(var b in a)a.hasOwnProperty(b)&&(ace[b]=a[b])})}()
\ No newline at end of file
+define("ace/mode/lua",["require","exports","module","ace/lib/oop","ace/mode/text","ace/tokenizer","ace/mode/lua_highlight_rules"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("./text").Mode,f=a("../tokenizer").Tokenizer,g=a("./lua_highlight_rules").LuaHighlightRules,h=function(){this.$tokenizer=new f((new g).getRules())};d.inherits(h,e),function(){this.getNextLineIndent=function(a,b,c){var d=this.$getIndent(b),e=this.$tokenizer.getLineTokens(b,a),f=e.tokens,g=["function","then","do","repeat"];if(a=="start"){var h=b.match(/^.*[\{\(\[]\s*$/);if(h)d+=c;else for(var i in f){var j=f[i];if(j.type!="keyword")continue;var k=g.indexOf(j.value);if(k!=-1){d+=c;break}}}return d}}.call(h.prototype),b.Mode=h}),define("ace/mode/lua_highlight_rules",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/mode/text_highlight_rules"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("../lib/lang"),f=a("./text_highlight_rules").TextHighlightRules,g=function(){var a=e.arrayToMap("break|do|else|elseif|end|for|function|if|in|local|repeat|return|then|until|while|or|and|not".split("|")),b=e.arrayToMap("true|false|nil|_G|_VERSION".split("|")),c=e.arrayToMap("string|xpcall|package|tostring|print|os|unpack|require|getfenv|setmetatable|next|assert|tonumber|io|rawequal|collectgarbage|getmetatable|module|rawset|math|debug|pcall|table|newproxy|type|coroutine|_G|select|gcinfo|pairs|rawget|loadstring|ipairs|_VERSION|dofile|setfenv|load|error|loadfile|sub|upper|len|gfind|rep|find|match|char|dump|gmatch|reverse|byte|format|gsub|lower|preload|loadlib|loaded|loaders|cpath|config|path|seeall|exit|setlocale|date|getenv|difftime|remove|time|clock|tmpname|rename|execute|lines|write|close|flush|open|output|type|read|stderr|stdin|input|stdout|popen|tmpfile|log|max|acos|huge|ldexp|pi|cos|tanh|pow|deg|tan|cosh|sinh|random|randomseed|frexp|ceil|floor|rad|abs|sqrt|modf|asin|min|mod|fmod|log10|atan2|exp|sin|atan|getupvalue|debug|sethook|getmetatable|gethook|setmetatable|setlocal|traceback|setfenv|getinfo|setupvalue|getlocal|getregistry|getfenv|setn|insert|getn|foreachi|maxn|foreach|concat|sort|remove|resume|yield|status|wrap|create|running".split("|")),d=e.arrayToMap("string|package|os|io|math|debug|table|coroutine".split("|")),f=e.arrayToMap("__add|__sub|__mod|__unm|__concat|__lt|__index|__call|__gc|__metatable|__mul|__div|__pow|__len|__eq|__le|__newindex|__tostring|__mode|__tonumber".split("|")),g=e.arrayToMap("".split("|")),h=e.arrayToMap("setn|foreach|foreachi|gcinfo|log10|maxn".split("|")),i="",j="(?:(?:[1-9]\\d*)|(?:0))",k="(?:0[xX][\\dA-Fa-f]+)",l="(?:"+j+"|"+k+")",m="(?:\\.\\d+)",n="(?:\\d+)",o="(?:(?:"+n+"?"+m+")|(?:"+n+"\\.))",p="(?:"+o+")",q=[];this.$rules={start:[{token:"comment",regex:i+"\\-\\-\\[\\[.*\\]\\]"},{token:"comment",regex:i+"\\-\\-\\[\\=\\[.*\\]\\=\\]"},{token:"comment",regex:i+"\\-\\-\\[\\={2}\\[.*\\]\\={2}\\]"},{token:"comment",regex:i+"\\-\\-\\[\\={3}\\[.*\\]\\={3}\\]"},{token:"comment",regex:i+"\\-\\-\\[\\={4}\\[.*\\]\\={4}\\]"},{token:"comment",regex:i+"\\-\\-\\[\\={5}\\=*\\[.*\\]\\={5}\\=*\\]"},{token:"comment",regex:i+"\\-\\-\\[\\[.*$",merge:!0,next:"qcomment"},{token:"comment",regex:i+"\\-\\-\\[\\=\\[.*$",merge:!0,next:"qcomment1"},{token:"comment",regex:i+"\\-\\-\\[\\={2}\\[.*$",merge:!0,next:"qcomment2"},{token:"comment",regex:i+"\\-\\-\\[\\={3}\\[.*$",merge:!0,next:"qcomment3"},{token:"comment",regex:i+"\\-\\-\\[\\={4}\\[.*$",merge:!0,next:"qcomment4"},{token:function(a){var b=/\-\-\[(\=+)\[/,c;return(c=b.exec(a))!=null&&(c=c[1])!=undefined&&q.push(c.length),"comment"},regex:i+"\\-\\-\\[\\={5}\\=*\\[.*$",merge:!0,next:"qcomment5"},{token:"comment",regex:"\\-\\-.*$"},{token:"string",regex:i+"\\[\\[.*\\]\\]"},{token:"string",regex:i+"\\[\\=\\[.*\\]\\=\\]"},{token:"string",regex:i+"\\[\\={2}\\[.*\\]\\={2}\\]"},{token:"string",regex:i+"\\[\\={3}\\[.*\\]\\={3}\\]"},{token:"string",regex:i+"\\[\\={4}\\[.*\\]\\={4}\\]"},{token:"string",regex:i+"\\[\\={5}\\=*\\[.*\\]\\={5}\\=*\\]"},{token:"string",regex:i+"\\[\\[.*$",merge:!0,next:"qstring"},{token:"string",regex:i+"\\[\\=\\[.*$",merge:!0,next:"qstring1"},{token:"string",regex:i+"\\[\\={2}\\[.*$",merge:!0,next:"qstring2"},{token:"string",regex:i+"\\[\\={3}\\[.*$",merge:!0,next:"qstring3"},{token:"string",regex:i+"\\[\\={4}\\[.*$",merge:!0,next:"qstring4"},{token:function(a){var b=/\[(\=+)\[/,c;return(c=b.exec(a))!=null&&(c=c[1])!=undefined&&q.push(c.length),"string"},regex:i+"\\[\\={5}\\=*\\[.*$",merge:!0,next:"qstring5"},{token:"string",regex:i+'"(?:[^\\\\]|\\\\.)*?"'},{token:"string",regex:i+"'(?:[^\\\\]|\\\\.)*?'"},{token:"constant.numeric",regex:p},{token:"constant.numeric",regex:l+"\\b"},{token:function(e){return a.hasOwnProperty(e)?"keyword":b.hasOwnProperty(e)?"constant.language":g.hasOwnProperty(e)?"invalid.illegal":d.hasOwnProperty(e)?"constant.library":h.hasOwnProperty(e)?"invalid.deprecated":c.hasOwnProperty(e)?"support.function":f.hasOwnProperty(e)?"support.function":"identifier"},regex:"[a-zA-Z_$][a-zA-Z0-9_$]*\\b"},{token:"keyword.operator",regex:"\\+|\\-|\\*|\\/|%|\\#|\\^|~|<|>|<=|=>|==|~=|=|\\:|\\.\\.\\.|\\.\\."},{token:"paren.lparen",regex:"[\\[\\(\\{]"},{token:"paren.rparen",regex:"[\\]\\)\\}]"},{token:"text",regex:"\\s+"}],qcomment:[{token:"comment",regex:"(?:[^\\\\]|\\\\.)*?\\]\\]",next:"start"},{token:"comment",merge:!0,regex:".+"}],qcomment1:[{token:"comment",regex:"(?:[^\\\\]|\\\\.)*?\\]\\=\\]",next:"start"},{token:"comment",merge:!0,regex:".+"}],qcomment2:[{token:"comment",regex:"(?:[^\\\\]|\\\\.)*?\\]\\={2}\\]",next:"start"},{token:"comment",merge:!0,regex:".+"}],qcomment3:[{token:"comment",regex:"(?:[^\\\\]|\\\\.)*?\\]\\={3}\\]",next:"start"},{token:"comment",merge:!0,regex:".+"}],qcomment4:[{token:"comment",regex:"(?:[^\\\\]|\\\\.)*?\\]\\={4}\\]",next:"start"},{token:"comment",merge:!0,regex:".+"}],qcomment5:[{token:function(a){var b=/\](\=+)\]/,c=this.rules.qcomment5[0],d;c.next="start";if((d=b.exec(a))!=null&&(d=d[1])!=undefined){var e=d.length,f;(f=q.pop())!=e&&(q.push(f),c.next="qcomment5")}return"comment"},regex:"(?:[^\\\\]|\\\\.)*?\\]\\={5}\\=*\\]",next:"start"},{token:"comment",merge:!0,regex:".+"}],qstring:[{token:"string",regex:"(?:[^\\\\]|\\\\.)*?\\]\\]",next:"start"},{token:"string",merge:!0,regex:".+"}],qstring1:[{token:"string",regex:"(?:[^\\\\]|\\\\.)*?\\]\\=\\]",next:"start"},{token:"string",merge:!0,regex:".+"}],qstring2:[{token:"string",regex:"(?:[^\\\\]|\\\\.)*?\\]\\={2}\\]",next:"start"},{token:"string",merge:!0,regex:".+"}],qstring3:[{token:"string",regex:"(?:[^\\\\]|\\\\.)*?\\]\\={3}\\]",next:"start"},{token:"string",merge:!0,regex:".+"}],qstring4:[{token:"string",regex:"(?:[^\\\\]|\\\\.)*?\\]\\={4}\\]",next:"start"},{token:"string",merge:!0,regex:".+"}],qstring5:[{token:function(a){var b=/\](\=+)\]/,c=this.rules.qstring5[0],d;c.next="start";if((d=b.exec(a))!=null&&(d=d[1])!=undefined){var e=d.length,f;(f=q.pop())!=e&&(q.push(f),c.next="qstring5")}return"string"},regex:"(?:[^\\\\]|\\\\.)*?\\]\\={5}\\=*\\]",next:"start"},{token:"string",merge:!0,regex:".+"}]}};d.inherits(g,f),b.LuaHighlightRules=g})
\ No newline at end of file
diff --git a/apps/files_texteditor/js/aceeditor/mode-markdown-uncompressed.js b/apps/files_texteditor/js/aceeditor/mode-markdown-uncompressed.js
old mode 100755
new mode 100644
index 0ddb789736c2c8663a4fab388f18c0044263037e..a8edaafeef82f7c6a70d8ffbcb475e9d557297ae
--- a/apps/files_texteditor/js/aceeditor/mode-markdown-uncompressed.js
+++ b/apps/files_texteditor/js/aceeditor/mode-markdown-uncompressed.js
@@ -337,12 +337,20 @@ var JavaScriptHighlightRules = function() {
     );
 
     // TODO: Unicode escape sequences
-    var identifierRe = "[" + unicode.packages.L + "\\$_][" 
+    var identifierRe = "[" + unicode.packages.L + "\\$_]["
         + unicode.packages.L
         + unicode.packages.Mn + unicode.packages.Mc
         + unicode.packages.Nd
         + unicode.packages.Pc + "\\$_]*\\b";
-        
+
+    var escapedRe = "\\\\(?:x[0-9a-fA-F]{2}|" + // hex
+        "u[0-9a-fA-F]{4}|" + // unicode
+        "[0-2][0-7]{0,2}|" + // oct
+        "3[0-6][0-7]?|" + // oct
+        "37[0-7]?|" + // oct
+        "[4-7][0-7]?|" + //oct
+        ".)";
+
     // regexp must not have capturing parentheses. Use (?:) instead.
     // regexps are ordered -> the first match is used
 
@@ -350,46 +358,139 @@ var JavaScriptHighlightRules = function() {
         "start" : [
             {
                 token : "comment",
-                regex : "\\/\\/.*$"
+                regex : /\/\/.*$/
             },
             new DocCommentHighlightRules().getStartRule("doc-start"),
             {
                 token : "comment", // multi line comment
                 merge : true,
-                regex : "\\/\\*",
+                regex : /\/\*/,
                 next : "comment"
             }, {
-                token : "string", // single line
-                regex : '["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'
-            }, {
-                token : "string", // multi line string start
-                merge : true,
-                regex : '["].*\\\\$',
-                next : "qqstring"
-            }, {
-                token : "string", // single line
-                regex : "['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"
+                token : "string",
+                regex : "'",
+                next  : "qstring"
             }, {
-                token : "string", // multi line string start
-                merge : true,
-                regex : "['].*\\\\$",
-                next : "qstring"
+                token : "string",
+                regex : '"',
+                next  : "qqstring"
             }, {
                 token : "constant.numeric", // hex
-                regex : "0[xX][0-9a-fA-F]+\\b"
+                regex : /0[xX][0-9a-fA-F]+\b/
             }, {
                 token : "constant.numeric", // float
-                regex : "[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"
-            }, {
-                token : ["keyword.definition", "text", "entity.name.function"],
-                regex : "(function)(\\s+)(" + identifierRe + ")"
+                regex : /[+-]?\d+(?:(?:\.\d*)?(?:[eE][+-]?\d+)?)?\b/
+            }, { // match stuff like: Sound.prototype.play = function() { }
+                token : [
+                    "storage.type",
+                    "punctuation.operator",
+                    "support.function",
+                    "punctuation.operator",
+                    "entity.name.function",
+                    "text",
+                    "keyword.operator",
+                    "text",
+                    "storage.type",
+                    "text",
+                    "paren.lparen",
+                    "variable.parameter",
+                    "paren.rparen"
+                ],
+                regex : "(" + identifierRe + ")(\\.)(prototype)(\\.)(" + identifierRe +")(\\s*)(=)(\\s*)(function)(\\s*)(\\()(.*?)(\\))"
+            }, { // match stuff like: Sound.prototype.play = myfunc
+                token : [
+                    "storage.type",
+                    "punctuation.operator",
+                    "support.function",
+                    "punctuation.operator",
+                    "entity.name.function",
+                    "text",
+                    "keyword.operator",
+                    "text"
+                ],
+                regex : "(" + identifierRe + ")(\\.)(prototype)(\\.)(" + identifierRe +")(\\s*)(=)(\\s*)"
+            }, { // match stuff like: Sound.play = function() {  }
+                token : [
+                    "storage.type",
+                    "punctuation.operator",
+                    "entity.name.function",
+                    "text",
+                    "keyword.operator",
+                    "text",
+                    "storage.type",
+                    "text",
+                    "paren.lparen",
+                    "variable.parameter",
+                    "paren.rparen"
+                ],
+                regex : "(" + identifierRe + ")(\\.)(" + identifierRe +")(\\s*)(=)(\\s*)(function)(\\s*)(\\()(.*?)(\\))"
+            }, { // match stuff like: play = function() {  }
+                token : [
+                    "entity.name.function",
+                    "text",
+                    "keyword.operator",
+                    "text",
+                    "storage.type",
+                    "text",
+                    "paren.lparen",
+                    "variable.parameter",
+                    "paren.rparen"
+                ],
+                regex : "(" + identifierRe +")(\\s*)(=)(\\s*)(function)(\\s*)(\\()(.*?)(\\))"
+            }, { // match regular function like: function myFunc(arg) { }
+                token : [
+                    "storage.type",
+                    "text",
+                    "entity.name.function",
+                    "text",
+                    "paren.lparen",
+                    "variable.parameter",
+                    "paren.rparen"
+                ],
+                regex : "(function)(\\s+)(" + identifierRe + ")(\\s*)(\\()(.*?)(\\))"
+            }, { // match stuff like: foobar: function() { }
+                token : [
+                    "entity.name.function",
+                    "text",
+                    "punctuation.operator",
+                    "text",
+                    "storage.type",
+                    "text",
+                    "paren.lparen",
+                    "variable.parameter",
+                    "paren.rparen"
+                ],
+                regex : "(" + identifierRe + ")(\\s*)(:)(\\s*)(function)(\\s*)(\\()(.*?)(\\))"
+            }, { // Attempt to match : function() { } (this is for issues with 'foo': function() { })
+                token : [
+                    "text",
+                    "text",
+                    "storage.type",
+                    "text",
+                    "paren.lparen",
+                    "variable.parameter",
+                    "paren.rparen"
+                ],
+                regex : "(:)(\\s*)(function)?(\\s*)(\\()([^)]*)(\\))"
             }, {
                 token : "constant.language.boolean",
-                regex : "(?:true|false)\\b"
+                regex : /(?:true|false)\b/
             }, {
                 token : "keyword",
                 regex : "(?:" + kwBeforeRe + ")\\b",
                 next : "regex_allowed"
+            }, {
+                token : ["punctuation.operator", "support.function"],
+                regex : /(\.)(s(?:h(?:ift|ow(?:Mod(?:elessDialog|alDialog)|Help))|croll(?:X|By(?:Pages|Lines)?|Y|To)?|t(?:opzzzz|rike)|i(?:n|zeToContent|debar|gnText)|ort|u(?:p|b(?:str(?:ing)?)?)|pli(?:ce|t)|e(?:nd|t(?:Re(?:sizable|questHeader)|M(?:i(?:nutes|lliseconds)|onth)|Seconds|Ho(?:tKeys|urs)|Year|Cursor|Time(?:out)?|Interval|ZOptions|Date|UTC(?:M(?:i(?:nutes|lliseconds)|onth)|Seconds|Hours|Date|FullYear)|FullYear|Active)|arch)|qrt|lice|avePreferences|mall)|h(?:ome|andleEvent)|navigate|c(?:har(?:CodeAt|At)|o(?:s|n(?:cat|textual|firm)|mpile)|eil|lear(?:Timeout|Interval)?|a(?:ptureEvents|ll)|reate(?:StyleSheet|Popup|EventObject))|t(?:o(?:GMTString|S(?:tring|ource)|U(?:TCString|pperCase)|Lo(?:caleString|werCase))|est|a(?:n|int(?:Enabled)?))|i(?:s(?:NaN|Finite)|ndexOf|talics)|d(?:isableExternalCapture|ump|etachEvent)|u(?:n(?:shift|taint|escape|watch)|pdateCommands)|j(?:oin|avaEnabled)|p(?:o(?:p|w)|ush|lugins.refresh|a(?:ddings|rse(?:Int|Float)?)|r(?:int|ompt|eference))|e(?:scape|nableExternalCapture|val|lementFromPoint|x(?:p|ec(?:Script|Command)?))|valueOf|UTC|queryCommand(?:State|Indeterm|Enabled|Value)|f(?:i(?:nd|le(?:ModifiedDate|Size|CreatedDate|UpdatedDate)|xed)|o(?:nt(?:size|color)|rward)|loor|romCharCode)|watch|l(?:ink|o(?:ad|g)|astIndexOf)|a(?:sin|nchor|cos|t(?:tachEvent|ob|an(?:2)?)|pply|lert|b(?:s|ort))|r(?:ou(?:nd|teEvents)|e(?:size(?:By|To)|calc|turnValue|place|verse|l(?:oad|ease(?:Capture|Events)))|andom)|g(?:o|et(?:ResponseHeader|M(?:i(?:nutes|lliseconds)|onth)|Se(?:conds|lection)|Hours|Year|Time(?:zoneOffset)?|Da(?:y|te)|UTC(?:M(?:i(?:nutes|lliseconds)|onth)|Seconds|Hours|Da(?:y|te)|FullYear)|FullYear|A(?:ttention|llResponseHeaders)))|m(?:in|ove(?:B(?:y|elow)|To(?:Absolute)?|Above)|ergeAttributes|a(?:tch|rgins|x))|b(?:toa|ig|o(?:ld|rderWidths)|link|ack))\b(?=\()/
+            }, {
+                token : ["punctuation.operator", "support.function.dom"],
+                regex : /(\.)(s(?:ub(?:stringData|mit)|plitText|e(?:t(?:NamedItem|Attribute(?:Node)?)|lect))|has(?:ChildNodes|Feature)|namedItem|c(?:l(?:ick|o(?:se|neNode))|reate(?:C(?:omment|DATASection|aption)|T(?:Head|extNode|Foot)|DocumentFragment|ProcessingInstruction|E(?:ntityReference|lement)|Attribute))|tabIndex|i(?:nsert(?:Row|Before|Cell|Data)|tem)|open|delete(?:Row|C(?:ell|aption)|T(?:Head|Foot)|Data)|focus|write(?:ln)?|a(?:dd|ppend(?:Child|Data))|re(?:set|place(?:Child|Data)|move(?:NamedItem|Child|Attribute(?:Node)?)?)|get(?:NamedItem|Element(?:sBy(?:Name|TagName)|ById)|Attribute(?:Node)?)|blur)\b(?=\()/
+            }, {
+                token : ["punctuation.operator", "support.constant"],
+                regex : /(\.)(s(?:ystemLanguage|cr(?:ipts|ollbars|een(?:X|Y|Top|Left))|t(?:yle(?:Sheets)?|atus(?:Text|bar)?)|ibling(?:Below|Above)|ource|uffixes|e(?:curity(?:Policy)?|l(?:ection|f)))|h(?:istory|ost(?:name)?|as(?:h|Focus))|y|X(?:MLDocument|SLDocument)|n(?:ext|ame(?:space(?:s|URI)|Prop))|M(?:IN_VALUE|AX_VALUE)|c(?:haracterSet|o(?:n(?:structor|trollers)|okieEnabled|lorDepth|mp(?:onents|lete))|urrent|puClass|l(?:i(?:p(?:boardData)?|entInformation)|osed|asses)|alle(?:e|r)|rypto)|t(?:o(?:olbar|p)|ext(?:Transform|Indent|Decoration|Align)|ags)|SQRT(?:1_2|2)|i(?:n(?:ner(?:Height|Width)|put)|ds|gnoreCase)|zIndex|o(?:scpu|n(?:readystatechange|Line)|uter(?:Height|Width)|p(?:sProfile|ener)|ffscreenBuffering)|NEGATIVE_INFINITY|d(?:i(?:splay|alog(?:Height|Top|Width|Left|Arguments)|rectories)|e(?:scription|fault(?:Status|Ch(?:ecked|arset)|View)))|u(?:ser(?:Profile|Language|Agent)|n(?:iqueID|defined)|pdateInterval)|_content|p(?:ixelDepth|ort|ersonalbar|kcs11|l(?:ugins|atform)|a(?:thname|dding(?:Right|Bottom|Top|Left)|rent(?:Window|Layer)?|ge(?:X(?:Offset)?|Y(?:Offset)?))|r(?:o(?:to(?:col|type)|duct(?:Sub)?|mpter)|e(?:vious|fix)))|e(?:n(?:coding|abledPlugin)|x(?:ternal|pando)|mbeds)|v(?:isibility|endor(?:Sub)?|Linkcolor)|URLUnencoded|P(?:I|OSITIVE_INFINITY)|f(?:ilename|o(?:nt(?:Size|Family|Weight)|rmName)|rame(?:s|Element)|gColor)|E|whiteSpace|l(?:i(?:stStyleType|n(?:eHeight|kColor))|o(?:ca(?:tion(?:bar)?|lName)|wsrc)|e(?:ngth|ft(?:Context)?)|a(?:st(?:M(?:odified|atch)|Index|Paren)|yer(?:s|X)|nguage))|a(?:pp(?:MinorVersion|Name|Co(?:deName|re)|Version)|vail(?:Height|Top|Width|Left)|ll|r(?:ity|guments)|Linkcolor|bove)|r(?:ight(?:Context)?|e(?:sponse(?:XML|Text)|adyState))|global|x|m(?:imeTypes|ultiline|enubar|argin(?:Right|Bottom|Top|Left))|L(?:N(?:10|2)|OG(?:10E|2E))|b(?:o(?:ttom|rder(?:Width|RightWidth|BottomWidth|Style|Color|TopWidth|LeftWidth))|ufferDepth|elow|ackground(?:Color|Image)))\b/
+            }, {
+                token : ["storage.type", "punctuation.operator", "support.function.firebug"],
+                regex : /(console)(\.)(warn|info|log|error|time|timeEnd|assert)\b/
             }, {
                 token : function(value) {
                     if (globals.hasOwnProperty(value))
@@ -397,7 +498,7 @@ var JavaScriptHighlightRules = function() {
                     else if (deprecated.hasOwnProperty(value))
                         return "invalid.deprecated";
                     else if (definitions.hasOwnProperty(value))
-                        return "keyword.definition";
+                        return "storage.type";
                     else if (keywords.hasOwnProperty(value))
                         return "keyword";
                     else if (buildinConstants.hasOwnProperty(value))
@@ -412,29 +513,29 @@ var JavaScriptHighlightRules = function() {
                 regex : identifierRe
             }, {
                 token : "keyword.operator",
-                regex : "!|\\$|%|&|\\*|\\-\\-|\\-|\\+\\+|\\+|~|===|==|=|!=|!==|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\\|\\||\\?\\:|\\*=|%=|\\+=|\\-=|&=|\\^=|\\b(?:in|instanceof|new|delete|typeof|void)",
+                regex : /!|\$|%|&|\*|\-\-|\-|\+\+|\+|~|===|==|=|!=|!==|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\|\||\?\:|\*=|%=|\+=|\-=|&=|\^=|\b(?:in|instanceof|new|delete|typeof|void)/,
                 next  : "regex_allowed"
             }, {
                 token : "punctuation.operator",
-                regex : "\\?|\\:|\\,|\\;|\\.",
+                regex : /\?|\:|\,|\;|\./,
                 next  : "regex_allowed"
             }, {
                 token : "paren.lparen",
-                regex : "[[({]",
+                regex : /[\[({]/,
                 next  : "regex_allowed"
             }, {
                 token : "paren.rparen",
-                regex : "[\\])}]"
+                regex : /[\])}]/
             }, {
                 token : "keyword.operator",
-                regex : "\\/=?",
+                regex : /\/=?/,
                 next  : "regex_allowed"
             }, {
                 token: "comment",
-                regex: "^#!.*$" 
+                regex: /^#!.*$/
             }, {
                 token : "text",
-                regex : "\\s+"
+                regex : /\s+/
             }
         ],
         // regular expressions are only allowed after certain tokens. This
@@ -459,7 +560,7 @@ var JavaScriptHighlightRules = function() {
             }, {
                 // immediately return to the start mode without matching
                 // anything
-                token: "empty", 
+                token: "empty",
                 regex: "",
                 next: "start"
             }
@@ -471,10 +572,10 @@ var JavaScriptHighlightRules = function() {
                 next: "regex"
             }, {
 				// flag
-                token: "string.regexp", 
+                token: "string.regexp",
                 regex: "/\\w*",
                 next: "start",
-                merge: true 
+                merge: true
             }, {
                 token: "string.regexp",
                 regex: "[^\\\\/\\[]+",
@@ -486,9 +587,9 @@ var JavaScriptHighlightRules = function() {
                 next: "regex_character_class",
                 merge: true
             }, {
-                token: "empty", 
+                token: "empty",
                 regex: "",
-                next: "start" 
+                next: "start"
             }
         ],
         "regex_character_class": [
@@ -507,9 +608,9 @@ var JavaScriptHighlightRules = function() {
                 next: "regex_character_class",
                 merge: true
             }, {
-                token: "empty", 
+                token: "empty",
                 regex: "",
-                next: "start" 
+                next: "start"
             }
         ],
         "comment_regex_allowed" : [
@@ -538,28 +639,32 @@ var JavaScriptHighlightRules = function() {
         ],
         "qqstring" : [
             {
+                token : "constant.language.escape",
+                regex : escapedRe
+            }, {
                 token : "string",
-                regex : '(?:(?:\\\\.)|(?:[^"\\\\]))*?"',
-                next : "start"
+                regex : '[^"\\\\]+'
             }, {
                 token : "string",
-                merge : true,
-                regex : '.+'
+                regex : '"',
+                next  : "start"
             }
         ],
         "qstring" : [
             {
+                token : "constant.language.escape",
+                regex : escapedRe
+            }, {
                 token : "string",
-                regex : "(?:(?:\\\\.)|(?:[^'\\\\]))*?'",
-                next : "start"
+                regex : "[^'\\\\]+"
             }, {
                 token : "string",
-                merge : true,
-                regex : '.+'
+                regex : "'",
+                next  : "start"
             }
         ]
     };
-    
+
     this.embedRules(DocCommentHighlightRules, "doc-",
         [ new DocCommentHighlightRules().getEndRule("start") ]);
 };
@@ -744,195 +849,6 @@ var MatchingBraceOutdent = function() {};
 }).call(MatchingBraceOutdent.prototype);
 
 exports.MatchingBraceOutdent = MatchingBraceOutdent;
-});
-/* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is Ajax.org Code Editor (ACE).
- *
- * The Initial Developer of the Original Code is
- * Ajax.org B.V.
- * Portions created by the Initial Developer are Copyright (C) 2010
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *      Fabian Jakobs <fabian AT ajax DOT org>
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-define('ace/worker/worker_client', ['require', 'exports', 'module' , 'ace/lib/oop', 'ace/lib/event_emitter'], function(require, exports, module) {
-"use strict";
-
-var oop = require("../lib/oop");
-var EventEmitter = require("../lib/event_emitter").EventEmitter;
-
-var WorkerClient = function(topLevelNamespaces, packagedJs, mod, classname) {
-
-    this.changeListener = this.changeListener.bind(this);
-
-    if (module.packaged) {
-        var base = this.$guessBasePath();
-        this.$worker = new Worker(base + packagedJs);
-    }
-    else {
-        var workerUrl = this.$normalizePath(require.nameToUrl("ace/worker/worker", null, "_"));
-        this.$worker = new Worker(workerUrl);
-
-        var tlns = {};
-        for (var i=0; i<topLevelNamespaces.length; i++) {
-            var ns = topLevelNamespaces[i];
-            var path = this.$normalizePath(require.nameToUrl(ns, null, "_").replace(/.js$/, ""));
-
-            tlns[ns] = path;
-        }
-    }
-
-    this.$worker.postMessage({
-        init : true,
-        tlns: tlns,
-        module: mod,
-        classname: classname
-    });
-
-    this.callbackId = 1;
-    this.callbacks = {};
-
-    var _self = this;
-    this.$worker.onerror = function(e) {
-        window.console && console.log && console.log(e);
-        throw e;
-    };
-    this.$worker.onmessage = function(e) {
-        var msg = e.data;
-        switch(msg.type) {
-            case "log":
-                window.console && console.log && console.log(msg.data);
-                break;
-
-            case "event":
-                _self._emit(msg.name, {data: msg.data});
-                break;
-
-            case "call":
-                var callback = _self.callbacks[msg.id];
-                if (callback) {
-                    callback(msg.data);
-                    delete _self.callbacks[msg.id];
-                }
-                break;
-        }
-    };
-};
-
-(function(){
-
-    oop.implement(this, EventEmitter);
-
-    this.$normalizePath = function(path) {
-        path = path.replace(/^[a-z]+:\/\/[^\/]+\//, ""); // Remove domain name and rebuild it
-        path = location.protocol + "//" + location.host
-            // paths starting with a slash are relative to the root (host)
-            + (path.charAt(0) == "/" ? "" : location.pathname.replace(/\/[^\/]*$/, ""))
-            + "/" + path.replace(/^[\/]+/, "");
-        return path;
-    };
-
-    this.$guessBasePath = function() {
-        if (require.aceBaseUrl)
-            return require.aceBaseUrl;
-
-        var scripts = document.getElementsByTagName("script");
-        for (var i=0; i<scripts.length; i++) {
-            var script = scripts[i];
-
-            var base = script.getAttribute("data-ace-base");
-            if (base)
-                return base.replace(/\/*$/, "/");
-
-            var src = script.src || script.getAttribute("src");
-            if (!src) {
-                continue;
-            }
-            var m = src.match(/^(?:(.*\/)ace\.js|(.*\/)ace(-uncompressed)?(-noconflict)?\.js)(?:\?|$)/);
-            if (m)
-                return m[1] || m[2];
-        }
-        return "";
-    };
-
-    this.terminate = function() {
-        this._emit("terminate", {});
-        this.$worker.terminate();
-        this.$worker = null;
-        this.$doc.removeEventListener("change", this.changeListener);
-        this.$doc = null;
-    };
-
-    this.send = function(cmd, args) {
-        this.$worker.postMessage({command: cmd, args: args});
-    };
-
-    this.call = function(cmd, args, callback) {
-        if (callback) {
-            var id = this.callbackId++;
-            this.callbacks[id] = callback;
-            args.push(id);
-        }
-        this.send(cmd, args);
-    };
-
-    this.emit = function(event, data) {
-        try {
-            // firefox refuses to clone objects which have function properties
-            // TODO: cleanup event
-            this.$worker.postMessage({event: event, data: {data: data.data}});
-        }
-        catch(ex) {}
-    };
-
-    this.attachToDocument = function(doc) {
-        if(this.$doc)
-            this.terminate();
-
-        this.$doc = doc;
-        this.call("setValue", [doc.getValue()]);
-        doc.on("change", this.changeListener);
-    };
-
-    this.changeListener = function(e) {
-        e.range = {
-            start: e.data.range.start,
-            end: e.data.range.end
-        };
-        this.emit("change", e);
-    };
-
-}).call(WorkerClient.prototype);
-
-exports.WorkerClient = WorkerClient;
-
 });
 /* vim:ts=4:sts=4:sw=4:
  * ***** BEGIN LICENSE BLOCK *****
@@ -988,12 +904,12 @@ var CstyleBehaviour = function () {
                 return {
                     text: '{' + selected + '}',
                     selection: false
-                }
+                };
             } else {
                 return {
                     text: '{}',
                     selection: [1, 1]
-                }
+                };
             }
         } else if (text == '}') {
             var cursor = editor.getCursorPosition();
@@ -1005,7 +921,7 @@ var CstyleBehaviour = function () {
                     return {
                         text: '',
                         selection: [1, 1]
-                    }
+                    };
                 }
             }
         } else if (text == "\n") {
@@ -1023,7 +939,7 @@ var CstyleBehaviour = function () {
                 return {
                     text: '\n' + indent + '\n' + next_indent,
                     selection: [1, indent.length, 1, indent.length]
-                }
+                };
             }
         }
     });
@@ -1048,12 +964,12 @@ var CstyleBehaviour = function () {
                 return {
                     text: '(' + selected + ')',
                     selection: false
-                }
+                };
             } else {
                 return {
                     text: '()',
                     selection: [1, 1]
-                }
+                };
             }
         } else if (text == ')') {
             var cursor = editor.getCursorPosition();
@@ -1065,7 +981,7 @@ var CstyleBehaviour = function () {
                     return {
                         text: '',
                         selection: [1, 1]
-                    }
+                    };
                 }
             }
         }
@@ -1084,14 +1000,15 @@ var CstyleBehaviour = function () {
     });
 
     this.add("string_dquotes", "insertion", function (state, action, editor, session, text) {
-        if (text == '"') {
+        if (text == '"' || text == "'") {
+            var quote = text;
             var selection = editor.getSelectionRange();
             var selected = session.doc.getTextRange(selection);
             if (selected !== "") {
                 return {
-                    text: '"' + selected + '"',
+                    text: quote + selected + quote,
                     selection: false
-                }
+                };
             } else {
                 var cursor = editor.getCursorPosition();
                 var line = session.doc.getLine(cursor.row);
@@ -1112,7 +1029,7 @@ var CstyleBehaviour = function () {
                     if (token.type == "string") {
                       quotepos = -1;
                     } else if (quotepos < 0) {
-                      quotepos = token.value.indexOf('"');
+                      quotepos = token.value.indexOf(quote);
                     }
                     if ((token.value.length + col) > selection.start.column) {
                         break;
@@ -1121,19 +1038,19 @@ var CstyleBehaviour = function () {
                 }
 
                 // Try and be smart about when we auto insert.
-                if (!token || (quotepos < 0 && token.type !== "comment" && (token.type !== "string" || ((selection.start.column !== token.value.length+col-1) && token.value.lastIndexOf('"') === token.value.length-1)))) {
+                if (!token || (quotepos < 0 && token.type !== "comment" && (token.type !== "string" || ((selection.start.column !== token.value.length+col-1) && token.value.lastIndexOf(quote) === token.value.length-1)))) {
                     return {
-                        text: '""',
+                        text: quote + quote,
                         selection: [1,1]
-                    }
+                    };
                 } else if (token && token.type === "string") {
                     // Ignore input and move right one if we're typing over the closing quote.
                     var rightChar = line.substring(cursor.column, cursor.column + 1);
-                    if (rightChar == '"') {
+                    if (rightChar == quote) {
                         return {
                             text: '',
                             selection: [1, 1]
-                        }
+                        };
                     }
                 }
             }
@@ -1142,7 +1059,7 @@ var CstyleBehaviour = function () {
 
     this.add("string_dquotes", "deletion", function (state, action, editor, session, range) {
         var selected = session.doc.getTextRange(range);
-        if (!range.isMultiLine() && selected == '"') {
+        if (!range.isMultiLine() && (selected == '"' || selected == "'")) {
             var line = session.doc.getLine(range.start.row);
             var rightChar = line.substring(range.start.column + 1, range.start.column + 2);
             if (rightChar == '"') {
@@ -1152,7 +1069,8 @@ var CstyleBehaviour = function () {
         }
     });
 
-}
+};
+
 oop.inherits(CstyleBehaviour, Behaviour);
 
 exports.CstyleBehaviour = CstyleBehaviour;
@@ -1489,6 +1407,9 @@ var XmlHighlightRules = function() {
             merge : true,
             regex : "<\\!--",
             next : "comment"
+        }, {
+            token : "xml_pe",
+            regex : "<\\!.*?>"
         }, {
             token : "meta.tag", // opening tag
             regex : "<\\/?",
@@ -1496,6 +1417,9 @@ var XmlHighlightRules = function() {
         }, {
             token : "text",
             regex : "\\s+"
+        }, {
+            token : "constant.character.entity",
+            regex : "(?:&#[0-9]+;)|(?:&#x[0-9a-fA-F]+;)|(?:&[a-zA-Z0-9_:\\.-]+;)"
         }, {
             token : "text",
             regex : "[^<]+"
@@ -1589,7 +1513,7 @@ function string(state) {
         token : "string", // multi line string start
         merge : true,
         regex : '["].*',
-        next : state + "-qqstring"
+        next : state + "_qqstring"
     }, {
         token : "string",
         regex : "'.*?'"
@@ -1597,7 +1521,7 @@ function string(state) {
         token : "string", // multi line string start
         merge : true,
         regex : "['].*",
-        next : state + "-qstring"
+        next : state + "_qstring"
     }];
 }
 
@@ -1645,18 +1569,18 @@ exports.tag = function(states, name, nextState) {
             }
         },        
         merge : true,
-        regex : "[-_a-zA-Z0-9:!]+",
-        next : name + "embed-attribute-list" 
+        regex : "[-_a-zA-Z0-9:]+",
+        next : name + "_embed_attribute_list" 
     }, {
         token: "empty",
         regex: "",
-        next : name + "embed-attribute-list"
+        next : name + "_embed_attribute_list"
     }];
 
-    states[name + "-qstring"] = multiLineString("'", name + "embed-attribute-list");
-    states[name + "-qqstring"] = multiLineString("\"", name + "embed-attribute-list");
+    states[name + "_qstring"] = multiLineString("'", name + "_embed_attribute_list");
+    states[name + "_qqstring"] = multiLineString("\"", name + "_embed_attribute_list");
     
-    states[name + "embed-attribute-list"] = [{
+    states[name + "_embed_attribute_list"] = [{
         token : "meta.tag",
         merge : true,
         regex : "\/?>",
@@ -2269,31 +2193,7 @@ var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
 var CssHighlightRules = function() {
 
     var properties = lang.arrayToMap(
-        ("-moz-appearance|-moz-box-sizing|-webkit-box-sizing|-moz-outline-radius|-moz-transform|-webkit-transform|" +
-        "appearance|azimuth|background-attachment|background-color|background-image|" +
-        "background-origin|background-position|background-repeat|background|border-bottom-color|" +
-        "border-bottom-style|border-bottom-width|border-bottom|border-collapse|" +
-        "border-color|border-left-color|border-left-style|border-left-width|" +
-        "border-left|border-right-color|border-right-style|border-right-width|" +
-        "border-right|border-spacing|border-style|border-top-color|" +
-        "border-top-style|border-top-width|border-top|border-width|border|" +
-        "bottom|box-sizing|caption-side|clear|clip|color|content|counter-increment|" +
-        "counter-reset|cue-after|cue-before|cue|cursor|direction|display|" +
-        "elevation|empty-cells|float|font-family|font-size-adjust|font-size|" +
-        "font-stretch|font-style|font-variant|font-weight|font|height|left|" +
-        "letter-spacing|line-height|list-style-image|list-style-position|" +
-        "list-style-type|list-style|margin-bottom|margin-left|margin-right|" +
-        "margin-top|marker-offset|margin|marks|max-height|max-width|min-height|" +
-        "min-width|-moz-border-radius|opacity|orphans|outline-color|outline-offset|outline-radius|" +
-        "outline-style|outline-width|outline|overflow|overflow-x|overflow-y|padding-bottom|" +
-        "padding-left|padding-right|padding-top|padding|page-break-after|" +
-        "page-break-before|page-break-inside|page|pause-after|pause-before|" +
-        "pause|pitch-range|pitch|play-during|pointer-events|position|quotes|resize|richness|right|" +
-        "size|speak-header|speak-numeral|speak-punctuation|speech-rate|speak|" +
-        "stress|table-layout|text-align|text-decoration|text-indent|" +
-        "text-shadow|text-transform|top|transform|unicode-bidi|vertical-align|" +
-        "visibility|voice-family|volume|white-space|widows|width|word-spacing|" +
-        "z-index").split("|")
+        ("animation-fill-mode|alignment-adjust|alignment-baseline|animation-delay|animation-direction|animation-duration|animation-iteration-count|animation-name|animation-play-state|animation-timing-function|animation|appearance|azimuth|backface-visibility|background-attachment|background-break|background-clip|background-color|background-image|background-origin|background-position|background-repeat|background-size|background|baseline-shift|binding|bleed|bookmark-label|bookmark-level|bookmark-state|bookmark-target|border-bottom|border-bottom-color|border-bottom-left-radius|border-bottom-right-radius|border-bottom-style|border-bottom-width|border-collapse|border-color|border-image|border-image-outset|border-image-repeat|border-image-slice|border-image-source|border-image-width|border-left|border-left-color|border-left-style|border-left-width|border-radius|border-right|border-right-color|border-right-style|border-right-width|border-spacing|border-style|border-top|border-top-color|border-top-left-radius|border-top-right-radius|border-top-style|border-top-width|border-width|border|bottom|box-align|box-decoration-break|box-direction|box-flex-group|box-flex|box-lines|box-ordinal-group|box-orient|box-pack|box-shadow|box-sizing|break-after|break-before|break-inside|caption-side|clear|clip|color-profile|color|column-count|column-fill|column-gap|column-rule|column-rule-color|column-rule-style|column-rule-width|column-span|column-width|columns|content|counter-increment|counter-reset|crop|cue-after|cue-before|cue|cursor|direction|display|dominant-baseline|drop-initial-after-adjust|drop-initial-after-align|drop-initial-before-adjust|drop-initial-before-align|drop-initial-size|drop-initial-value|elevation|empty-cells|fit|fit-position|float-offset|float|font-family|font-size|font-size-adjust|font-stretch|font-style|font-variant|font-weight|font|grid-columns|grid-rows|hanging-punctuation|height|hyphenate-after|hyphenate-before|hyphenate-character|hyphenate-lines|hyphenate-resource|hyphens|icon|image-orientation|image-rendering|image-resolution|inline-box-align|left|letter-spacing|line-height|line-stacking-ruby|line-stacking-shift|line-stacking-strategy|line-stacking|list-style-image|list-style-position|list-style-type|list-style|margin-bottom|margin-left|margin-right|margin-top|margin|mark-after|mark-before|mark|marks|marquee-direction|marquee-play-count|marquee-speed|marquee-style|max-height|max-width|min-height|min-width|move-to|nav-down|nav-index|nav-left|nav-right|nav-up|opacity|orphans|outline-color|outline-offset|outline-style|outline-width|outline|overflow-style|overflow-x|overflow-y|overflow|padding-bottom|padding-left|padding-right|padding-top|padding|page-break-after|page-break-before|page-break-inside|page-policy|page|pause-after|pause-before|pause|perspective-origin|perspective|phonemes|pitch-range|pitch|play-during|position|presentation-level|punctuation-trim|quotes|rendering-intent|resize|rest-after|rest-before|rest|richness|right|rotation-point|rotation|ruby-align|ruby-overhang|ruby-position|ruby-span|size|speak-header|speak-numeral|speak-punctuation|speak|speech-rate|stress|string-set|table-layout|target-name|target-new|target-position|target|text-align-last|text-align|text-decoration|text-emphasis|text-height|text-indent|text-justify|text-outline|text-shadow|text-transform|text-wrap|top|transform-origin|transform-style|transform|transition-delay|transition-duration|transition-property|transition-timing-function|transition|unicode-bidi|vertical-align|visibility|voice-balance|voice-duration|voice-family|voice-pitch-range|voice-pitch|voice-rate|voice-stress|voice-volume|volume|white-space-collapse|white-space|widows|width|word-break|word-spacing|word-wrap|z-index").split("|")
     );
 
     var functions = lang.arrayToMap(
@@ -2301,27 +2201,7 @@ var CssHighlightRules = function() {
     );
 
     var constants = lang.arrayToMap(
-        ("absolute|all-scroll|always|armenian|auto|baseline|below|bidi-override|" +
-        "block|bold|bolder|border-box|both|bottom|break-all|break-word|capitalize|center|" +
-        "char|circle|cjk-ideographic|col-resize|collapse|content-box|crosshair|dashed|" +
-        "decimal-leading-zero|decimal|default|disabled|disc|" +
-        "distribute-all-lines|distribute-letter|distribute-space|" +
-        "distribute|dotted|double|e-resize|ellipsis|fixed|georgian|groove|" +
-        "hand|hebrew|help|hidden|hiragana-iroha|hiragana|horizontal|" +
-        "ideograph-alpha|ideograph-numeric|ideograph-parenthesis|" +
-        "ideograph-space|inactive|inherit|inline-block|inline|inset|inside|" +
-        "inter-ideograph|inter-word|italic|justify|katakana-iroha|katakana|" +
-        "keep-all|left|lighter|line-edge|line-through|line|list-item|loose|" +
-        "lower-alpha|lower-greek|lower-latin|lower-roman|lowercase|lr-tb|ltr|" +
-        "medium|middle|move|n-resize|ne-resize|newspaper|no-drop|no-repeat|" +
-        "nw-resize|none|normal|not-allowed|nowrap|oblique|outset|outside|" +
-        "overline|pointer|progress|relative|repeat-x|repeat-y|repeat|right|" +
-        "ridge|row-resize|rtl|s-resize|scroll|se-resize|separate|small-caps|" +
-        "solid|square|static|strict|super|sw-resize|table-footer-group|" +
-        "table-header-group|tb-rl|text-bottom|text-top|text|thick|thin|top|" +
-        "transparent|underline|upper-alpha|upper-latin|upper-roman|uppercase|" +
-        "vertical-ideographic|vertical-text|visible|w-resize|wait|whitespace|" +
-        "zero").split("|")
+        ("absolute|after-edge|after|all-scroll|all|alphabetic|always|antialiased|armenian|auto|avoid-column|avoid-page|avoid|balance|baseline|before-edge|before|below|bidi-override|block-line-height|block|bold|bolder|border-box|both|bottom|box|break-all|break-word|capitalize|caps-height|caption|center|central|char|circle|cjk-ideographic|clone|close-quote|col-resize|collapse|column|consider-shifts|contain|content-box|cover|crosshair|cubic-bezier|dashed|decimal-leading-zero|decimal|default|disabled|disc|disregard-shifts|distribute-all-lines|distribute-letter|distribute-space|distribute|dotted|double|e-resize|ease-in|ease-in-out|ease-out|ease|ellipsis|end|exclude-ruby|fill|fixed|font-size|font|georgian|glyphs|grid-height|groove|hand|hanging|hebrew|help|hidden|hiragana-iroha|hiragana|horizontal|icon|ideograph-alpha|ideograph-numeric|ideograph-parenthesis|ideograph-space|ideographic|inactive|include-ruby|inherit|initial|inline-block|inline-box|inline-line-height|inline-table|inline|inset|inside|inter-ideograph|inter-word|invert|italic|justify|katakana-iroha|katakana|keep-all|last|left|lighter|line-edge|line-through|line|linear|list-item|local|loose|lower-alpha|lower-greek|lower-latin|lower-roman|lowercase|lr-tb|ltr|mathematical|max-height|max-size|medium|menu|message-box|middle|move|n-resize|ne-resize|newspaper|no-change|no-close-quote|no-drop|no-open-quote|no-repeat|none|normal|not-allowed|nowrap|nw-resize|oblique|open-quote|outset|outside|overline|padding-box|page|pointer|pre-line|pre-wrap|pre|preserve-3d|progress|relative|repeat-x|repeat-y|repeat|replaced|reset-size|ridge|right|round|row-resize|rtl|s-resize|scroll|se-resize|separate|slice|small-caps|small-caption|solid|space|square|start|static|status-bar|step-end|step-start|steps|stretch|strict|sub|super|sw-resize|table-caption|table-cell|table-column-group|table-column|table-footer-group|table-header-group|table-row-group|table-row|table|tb-rl|text-after-edge|text-before-edge|text-bottom|text-size|text-top|text|thick|thin|top|transparent|underline|upper-alpha|upper-latin|upper-roman|uppercase|use-script|vertical-ideographic|vertical-text|visible|w-resize|wait|whitespace|z-index|zero").split("|")
     );
 
     var colors = lang.arrayToMap(
@@ -2329,32 +2209,49 @@ var CssHighlightRules = function() {
         "purple|red|silver|teal|white|yellow").split("|")
     );
 
+    var fonts = lang.arrayToMap(
+        ("arial|century|comic|courier|garamond|georgia|helvetica|impact|lucida|" +
+        "symbol|system|tahoma|times|trebuchet|utopia|verdana|webdings|sans-serif|" +
+        "serif|monospace").split("|")
+    );
+    
     // regexp must not have capturing parentheses. Use (?:) instead.
     // regexps are ordered -> the first match is used
 
     var numRe = "\\-?(?:(?:[0-9]+)|(?:[0-9]*\\.[0-9]+))";
-
+    var pseudoElements = "(\\:+)\\b(after|before|first-letter|first-line|moz-selection|selection)\\b";
+    var pseudoClasses = "(:)\\b(active|checked|disabled|empty|enabled|first-child|first-of-type|focus|hover|indeterminate|invalid|last-child|last-of-type|link|not|nth-child|nth-last-child|nth-last-of-type|nth-of-type|only-child|only-of-type|required|root|target|valid|visited)\\b";
+    
     var base_ruleset = [
         {
             token : "comment", // multi line comment
             merge : true,
             regex : "\\/\\*",
             next : "ruleset_comment"
-        },{
+        }, {
             token : "string", // single line
             regex : '["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'
         }, {
             token : "string", // single line
             regex : "['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"
         }, {
-            token : "constant.numeric",
-            regex : numRe + "(?:em|ex|px|cm|mm|in|pt|pc|deg|rad|grad|ms|s|hz|khz|%)"
+            token : ["constant.numeric", "keyword"],
+            regex : "(" + numRe + ")(ch|cm|deg|em|ex|fr|gd|grad|Hz|in|kHz|mm|ms|pc|pt|px|rad|rem|s|turn|vh|vm|vw|%)"
+        }, {
+            token : ["constant.numeric"],
+            regex : "([0-9]+)"
         }, {
             token : "constant.numeric",  // hex6 color
             regex : "#[a-f0-9]{6}"
         }, {
             token : "constant.numeric", // hex3 color
             regex : "#[a-f0-9]{3}"
+        }, {
+            token : ["punctuation", "entity.other.attribute-name.pseudo-element.css"], 
+            regex : pseudoElements
+        }, {
+            token : ["punctuation", "entity.other.attribute-name.pseudo-class.css"], 
+            regex : pseudoClasses
         }, {
             token : function(value) {
                 if (properties.hasOwnProperty(value.toLowerCase())) {
@@ -2369,12 +2266,15 @@ var CssHighlightRules = function() {
                 else if (colors.hasOwnProperty(value.toLowerCase())) {
                     return "support.constant.color";
                 }
+                else if (fonts.hasOwnProperty(value.toLowerCase())) {
+                    return "support.constant.fonts";
+                }
                 else {
                     return "text";
                 }
             },
             regex : "\\-?[a-zA-Z_][a-zA-Z0-9_\\-]*"
-        }
+        } 
       ];
 
     var ruleset = lang.copyArray(base_ruleset);
@@ -2552,6 +2452,9 @@ var HtmlHighlightRules = function() {
             merge : true,
             regex : "<\\!--",
             next : "comment"
+        }, {
+            token : "xml_pe",
+            regex : "<\\!.*?>"
         }, {
             token : "meta.tag",
             regex : "<(?=\s*script\\b)",
@@ -2559,7 +2462,7 @@ var HtmlHighlightRules = function() {
         }, {
             token : "meta.tag",
             regex : "<(?=\s*style\\b)",
-            next : "css"
+            next : "style"
         }, {
             token : "meta.tag", // opening tag
             regex : "<\\/?",
@@ -2567,6 +2470,9 @@ var HtmlHighlightRules = function() {
         }, {
             token : "text",
             regex : "\\s+"
+        }, {
+            token : "constant.character.entity",
+            regex : "(?:&#[0-9]+;)|(?:&#x[0-9a-fA-F]+;)|(?:&[a-zA-Z0-9_:\\.-]+;)"
         }, {
             token : "text",
             regex : "[^<]+"
@@ -2598,7 +2504,7 @@ var HtmlHighlightRules = function() {
     };
     
     xmlUtil.tag(this.$rules, "tag", "start");
-    xmlUtil.tag(this.$rules, "css", "css-start");
+    xmlUtil.tag(this.$rules, "style", "css-start");
     xmlUtil.tag(this.$rules, "script", "js-start");
     
     this.embedRules(JavaScriptHighlightRules, "js-", [{
@@ -2860,7 +2766,7 @@ var MarkdownHighlightRules = function() {
             token : "empty_line",
             regex : '^$'
         }, { // code span `
-            token : "support.function",
+            token : ["support.function", "support.function", "support.function"],
             regex : "(`+)([^\\r]*?[^`])(\\1)"
         }, { // code block
             token : "support.function",
@@ -2890,7 +2796,7 @@ var MarkdownHighlightRules = function() {
             next  : "blockquote"
         }, { // reference
             token : ["text", "constant", "text", "url", "string", "text"],
-            regex : "^([ ]{0,3}\\[)([^\\]]+)(\\]:\\s*)([^ ]+)(\\s*(?:[\"][^\"]+[\"])?\\s*)$"
+            regex : "^([ ]{0,3}\\[)([^\\]]+)(\\]:\\s*)([^ ]+)(\\s*(?:[\"][^\"]+[\"])?(\\s*))$"
         }, { // link by reference
             token : ["text", "string", "text", "constant", "text"],
             regex : "(\\[)((?:[[^\\]]*\\]|[^\\[\\]])*)(\\][ ]?(?:\\n[ ]*)?\\[)(.*?)(\\])"
@@ -2916,10 +2822,10 @@ var MarkdownHighlightRules = function() {
             regex : "^\\s{0,3}(?:[*+-]|\\d+\\.)\\s+",
             next  : "listblock"
         }, { // strong ** __
-            token : "string",
+            token : ["string", "string", "string"],
             regex : "([*]{2}|[_]{2}(?=\\S))([^\\r]*?\\S[*_]*)(\\1)"
         }, { // emphasis * _
-            token : "string",
+            token : ["string", "string", "string"],
             regex : "([*]|[_](?=\\S))([^\\r]*?\\S[*_]*)(\\1)"
         }, { // 
             token : ["text", "url", "text"],
@@ -2988,13 +2894,4 @@ var MarkdownHighlightRules = function() {
 oop.inherits(MarkdownHighlightRules, TextHighlightRules);
 
 exports.MarkdownHighlightRules = MarkdownHighlightRules;
-});;
-            (function() {
-                window.require(["ace/ace"], function(a) {
-                    if (!window.ace)
-                        window.ace = {};
-                    for (var key in a) if (a.hasOwnProperty(key))
-                        ace[key] = a[key];
-                });
-            })();
-        
\ No newline at end of file
+});
\ No newline at end of file
diff --git a/apps/files_texteditor/js/aceeditor/mode-markdown.js b/apps/files_texteditor/js/aceeditor/mode-markdown.js
old mode 100755
new mode 100644
index 4cf7a4a82b456c660c3efc45b38a2da191b5a3c6..a45debe0443c38503e15affb0297cbec0efeaa6f
--- a/apps/files_texteditor/js/aceeditor/mode-markdown.js
+++ b/apps/files_texteditor/js/aceeditor/mode-markdown.js
@@ -1 +1 @@
-define("ace/mode/markdown",["require","exports","module","ace/lib/oop","ace/mode/text","ace/mode/javascript","ace/mode/xml","ace/mode/html","ace/tokenizer","ace/mode/markdown_highlight_rules"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("./text").Mode,f=a("./javascript").Mode,g=a("./xml").Mode,h=a("./html").Mode,i=a("../tokenizer").Tokenizer,j=a("./markdown_highlight_rules").MarkdownHighlightRules,k=function(){var a=new j;this.$tokenizer=new i(a.getRules()),this.$embeds=a.getEmbeds(),this.createModeDelegates({"js-":f,"xml-":g,"html-":h})};d.inherits(k,e),function(){this.getNextLineIndent=function(a,b,c){if(a=="listblock"){var d=/^((?:.+)?)([-+*][ ]+)/.exec(b);return d?(new Array(d[1].length+1)).join(" ")+d[2]:""}return this.$getIndent(b)}}.call(k.prototype),b.Mode=k}),define("ace/mode/javascript",["require","exports","module","ace/lib/oop","ace/mode/text","ace/tokenizer","ace/mode/javascript_highlight_rules","ace/mode/matching_brace_outdent","ace/range","ace/worker/worker_client","ace/mode/behaviour/cstyle","ace/mode/folding/cstyle"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("./text").Mode,f=a("../tokenizer").Tokenizer,g=a("./javascript_highlight_rules").JavaScriptHighlightRules,h=a("./matching_brace_outdent").MatchingBraceOutdent,i=a("../range").Range,j=a("../worker/worker_client").WorkerClient,k=a("./behaviour/cstyle").CstyleBehaviour,l=a("./folding/cstyle").FoldMode,m=function(){this.$tokenizer=new f((new g).getRules()),this.$outdent=new h,this.$behaviour=new k,this.foldingRules=new l};d.inherits(m,e),function(){this.toggleCommentLines=function(a,b,c,d){var e=!0,f=/^(\s*)\/\//;for(var g=c;g<=d;g++)if(!f.test(b.getLine(g))){e=!1;break}if(e){var h=new i(0,0,0,0);for(var g=c;g<=d;g++){var j=b.getLine(g),k=j.match(f);h.start.row=g,h.end.row=g,h.end.column=k[0].length,b.replace(h,k[1])}}else b.indentRows(c,d,"//")},this.getNextLineIndent=function(a,b,c){var d=this.$getIndent(b),e=this.$tokenizer.getLineTokens(b,a),f=e.tokens,g=e.state;if(f.length&&f[f.length-1].type=="comment")return d;if(a=="start"||a=="regex_allowed"){var h=b.match(/^.*(?:\bcase\b.*\:|[\{\(\[])\s*$/);h&&(d+=c)}else if(a=="doc-start"){if(g=="start"||a=="regex_allowed")return"";var h=b.match(/^\s*(\/?)\*/);h&&(h[1]&&(d+=" "),d+="* ")}return d},this.checkOutdent=function(a,b,c){return this.$outdent.checkOutdent(b,c)},this.autoOutdent=function(a,b,c){this.$outdent.autoOutdent(b,c)},this.createWorker=function(a){var b=new j(["ace"],"worker-javascript.js","ace/mode/javascript_worker","JavaScriptWorker");return b.attachToDocument(a.getDocument()),b.on("jslint",function(b){var c=[];for(var d=0;d<b.data.length;d++){var e=b.data[d];e&&c.push({row:e.line-1,column:e.character-1,text:e.reason,type:"warning",lint:e})}a.setAnnotations(c)}),b.on("narcissus",function(b){a.setAnnotations([b.data])}),b.on("terminate",function(){a.clearAnnotations()}),b}}.call(m.prototype),b.Mode=m}),define("ace/mode/javascript_highlight_rules",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/unicode","ace/mode/doc_comment_highlight_rules","ace/mode/text_highlight_rules"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("../lib/lang"),f=a("../unicode"),g=a("./doc_comment_highlight_rules").DocCommentHighlightRules,h=a("./text_highlight_rules").TextHighlightRules,i=function(){var a=e.arrayToMap("Array|Boolean|Date|Function|Iterator|Number|Object|RegExp|String|Proxy|Namespace|QName|XML|XMLList|ArrayBuffer|Float32Array|Float64Array|Int16Array|Int32Array|Int8Array|Uint16Array|Uint32Array|Uint8Array|Uint8ClampedArray|Error|EvalError|InternalError|RangeError|ReferenceError|StopIteration|SyntaxError|TypeError|URIError|decodeURI|decodeURIComponent|encodeURI|encodeURIComponent|eval|isFinite|isNaN|parseFloat|parseInt|JSON|Math|this|arguments|prototype|window|document".split("|")),b=e.arrayToMap("break|case|catch|continue|default|delete|do|else|finally|for|function|if|in|instanceof|new|return|switch|throw|try|typeof|let|var|while|with|const|yield|import|get|set".split("|")),c="case|do|else|finally|in|instanceof|return|throw|try|typeof|yield",d=e.arrayToMap("__parent__|__count__|escape|unescape|with|__proto__".split("|")),h=e.arrayToMap("const|let|var|function".split("|")),i=e.arrayToMap("null|Infinity|NaN|undefined".split("|")),j=e.arrayToMap("class|enum|extends|super|export|implements|private|public|interface|package|protected|static".split("|")),k="["+f.packages.L+"\\$_]["+f.packages.L+f.packages.Mn+f.packages.Mc+f.packages.Nd+f.packages.Pc+"\\$_]*\\b";this.$rules={start:[{token:"comment",regex:"\\/\\/.*$"},(new g).getStartRule("doc-start"),{token:"comment",merge:!0,regex:"\\/\\*",next:"comment"},{token:"string",regex:'["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'},{token:"string",merge:!0,regex:'["].*\\\\$',next:"qqstring"},{token:"string",regex:"['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"},{token:"string",merge:!0,regex:"['].*\\\\$",next:"qstring"},{token:"constant.numeric",regex:"0[xX][0-9a-fA-F]+\\b"},{token:"constant.numeric",regex:"[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"},{token:["keyword.definition","text","entity.name.function"],regex:"(function)(\\s+)("+k+")"},{token:"constant.language.boolean",regex:"(?:true|false)\\b"},{token:"keyword",regex:"(?:"+c+")\\b",next:"regex_allowed"},{token:function(c){return a.hasOwnProperty(c)?"variable.language":d.hasOwnProperty(c)?"invalid.deprecated":h.hasOwnProperty(c)?"keyword.definition":b.hasOwnProperty(c)?"keyword":i.hasOwnProperty(c)?"constant.language":j.hasOwnProperty(c)?"invalid.illegal":c=="debugger"?"invalid.deprecated":"identifier"},regex:k},{token:"keyword.operator",regex:"!|\\$|%|&|\\*|\\-\\-|\\-|\\+\\+|\\+|~|===|==|=|!=|!==|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\\|\\||\\?\\:|\\*=|%=|\\+=|\\-=|&=|\\^=|\\b(?:in|instanceof|new|delete|typeof|void)",next:"regex_allowed"},{token:"punctuation.operator",regex:"\\?|\\:|\\,|\\;|\\.",next:"regex_allowed"},{token:"paren.lparen",regex:"[[({]",next:"regex_allowed"},{token:"paren.rparen",regex:"[\\])}]"},{token:"keyword.operator",regex:"\\/=?",next:"regex_allowed"},{token:"comment",regex:"^#!.*$"},{token:"text",regex:"\\s+"}],regex_allowed:[{token:"comment",merge:!0,regex:"\\/\\*",next:"comment_regex_allowed"},{token:"comment",regex:"\\/\\/.*$"},{token:"string.regexp",regex:"\\/",next:"regex",merge:!0},{token:"text",regex:"\\s+"},{token:"empty",regex:"",next:"start"}],regex:[{token:"regexp.keyword.operator",regex:"\\\\(?:u[\\da-fA-F]{4}|x[\\da-fA-F]{2}|.)",next:"regex"},{token:"string.regexp",regex:"/\\w*",next:"start",merge:!0},{token:"string.regexp",regex:"[^\\\\/\\[]+",next:"regex",merge:!0},{token:"string.regexp.charachterclass",regex:"\\[",next:"regex_character_class",merge:!0},{token:"empty",regex:"",next:"start"}],regex_character_class:[{token:"regexp.keyword.operator",regex:"\\\\(?:u[\\da-fA-F]{4}|x[\\da-fA-F]{2}|.)",next:"regex_character_class"},{token:"string.regexp.charachterclass",regex:"]",next:"regex",merge:!0},{token:"string.regexp.charachterclass",regex:"[^\\\\\\]]+",next:"regex_character_class",merge:!0},{token:"empty",regex:"",next:"start"}],comment_regex_allowed:[{token:"comment",regex:".*?\\*\\/",merge:!0,next:"regex_allowed"},{token:"comment",merge:!0,regex:".+"}],comment:[{token:"comment",regex:".*?\\*\\/",merge:!0,next:"start"},{token:"comment",merge:!0,regex:".+"}],qqstring:[{token:"string",regex:'(?:(?:\\\\.)|(?:[^"\\\\]))*?"',next:"start"},{token:"string",merge:!0,regex:".+"}],qstring:[{token:"string",regex:"(?:(?:\\\\.)|(?:[^'\\\\]))*?'",next:"start"},{token:"string",merge:!0,regex:".+"}]},this.embedRules(g,"doc-",[(new g).getEndRule("start")])};d.inherits(i,h),b.JavaScriptHighlightRules=i}),define("ace/mode/doc_comment_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("./text_highlight_rules").TextHighlightRules,f=function(){this.$rules={start:[{token:"comment.doc.tag",regex:"@[\\w\\d_]+"},{token:"comment.doc",merge:!0,regex:"\\s+"},{token:"comment.doc",merge:!0,regex:"TODO"},{token:"comment.doc",merge:!0,regex:"[^@\\*]+"},{token:"comment.doc",merge:!0,regex:"."}]}};d.inherits(f,e),function(){this.getStartRule=function(a){return{token:"comment.doc",merge:!0,regex:"\\/\\*(?=\\*)",next:a}},this.getEndRule=function(a){return{token:"comment.doc",merge:!0,regex:"\\*\\/",next:a}}}.call(f.prototype),b.DocCommentHighlightRules=f}),define("ace/mode/matching_brace_outdent",["require","exports","module","ace/range"],function(a,b,c){"use strict";var d=a("../range").Range,e=function(){};((function(){this.checkOutdent=function(a,b){return/^\s+$/.test(a)?/^\s*\}/.test(b):!1},this.autoOutdent=function(a,b){var c=a.getLine(b),e=c.match(/^(\s*\})/);if(!e)return 0;var f=e[1].length,g=a.findMatchingBracket({row:b,column:f});if(!g||g.row==b)return 0;var h=this.$getIndent(a.getLine(g.row));a.replace(new d(b,0,b,f-1),h)},this.$getIndent=function(a){var b=a.match(/^(\s+)/);return b?b[1]:""}})).call(e.prototype),b.MatchingBraceOutdent=e}),define("ace/worker/worker_client",["require","exports","module","ace/lib/oop","ace/lib/event_emitter"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("../lib/event_emitter").EventEmitter,f=function(b,d,e,f){this.changeListener=this.changeListener.bind(this);if(c.packaged){var g=this.$guessBasePath();this.$worker=new Worker(g+d)}else{var h=this.$normalizePath(a.nameToUrl("ace/worker/worker",null,"_"));this.$worker=new Worker(h);var i={};for(var j=0;j<b.length;j++){var k=b[j],l=this.$normalizePath(a.nameToUrl(k,null,"_").replace(/.js$/,""));i[k]=l}}this.$worker.postMessage({init:!0,tlns:i,module:e,classname:f}),this.callbackId=1,this.callbacks={};var m=this;this.$worker.onerror=function(a){throw window.console&&console.log&&console.log(a),a},this.$worker.onmessage=function(a){var b=a.data;switch(b.type){case"log":window.console&&console.log&&console.log(b.data);break;case"event":m._emit(b.name,{data:b.data});break;case"call":var c=m.callbacks[b.id];c&&(c(b.data),delete m.callbacks[b.id])}}};((function(){d.implement(this,e),this.$normalizePath=function(a){return a=a.replace(/^[a-z]+:\/\/[^\/]+\//,""),a=location.protocol+"//"+location.host+(a.charAt(0)=="/"?"":location.pathname.replace(/\/[^\/]*$/,""))+"/"+a.replace(/^[\/]+/,""),a},this.$guessBasePath=function(){if(a.aceBaseUrl)return a.aceBaseUrl;var b=document.getElementsByTagName("script");for(var c=0;c<b.length;c++){var d=b[c],e=d.getAttribute("data-ace-base");if(e)return e.replace(/\/*$/,"/");var f=d.src||d.getAttribute("src");if(!f)continue;var g=f.match(/^(?:(.*\/)ace\.js|(.*\/)ace(-uncompressed)?(-noconflict)?\.js)(?:\?|$)/);if(g)return g[1]||g[2]}return""},this.terminate=function(){this._emit("terminate",{}),this.$worker.terminate(),this.$worker=null,this.$doc.removeEventListener("change",this.changeListener),this.$doc=null},this.send=function(a,b){this.$worker.postMessage({command:a,args:b})},this.call=function(a,b,c){if(c){var d=this.callbackId++;this.callbacks[d]=c,b.push(d)}this.send(a,b)},this.emit=function(a,b){try{this.$worker.postMessage({event:a,data:{data:b.data}})}catch(c){}},this.attachToDocument=function(a){this.$doc&&this.terminate(),this.$doc=a,this.call("setValue",[a.getValue()]),a.on("change",this.changeListener)},this.changeListener=function(a){a.range={start:a.data.range.start,end:a.data.range.end},this.emit("change",a)}})).call(f.prototype),b.WorkerClient=f}),define("ace/mode/behaviour/cstyle",["require","exports","module","ace/lib/oop","ace/mode/behaviour"],function(a,b,c){"use strict";var d=a("../../lib/oop"),e=a("../behaviour").Behaviour,f=function(){this.add("braces","insertion",function(a,b,c,d,e){if(e=="{"){var f=c.getSelectionRange(),g=d.doc.getTextRange(f);return g!==""?{text:"{"+g+"}",selection:!1}:{text:"{}",selection:[1,1]}}if(e=="}"){var h=c.getCursorPosition(),i=d.doc.getLine(h.row),j=i.substring(h.column,h.column+1);if(j=="}"){var k=d.$findOpeningBracket("}",{column:h.column+1,row:h.row});if(k!==null)return{text:"",selection:[1,1]}}}else if(e=="\n"){var h=c.getCursorPosition(),i=d.doc.getLine(h.row),j=i.substring(h.column,h.column+1);if(j=="}"){var l=d.findMatchingBracket({row:h.row,column:h.column+1});if(!l)return null;var m=this.getNextLineIndent(a,i.substring(0,i.length-1),d.getTabString()),n=this.$getIndent(d.doc.getLine(l.row));return{text:"\n"+m+"\n"+n,selection:[1,m.length,1,m.length]}}}}),this.add("braces","deletion",function(a,b,c,d,e){var f=d.doc.getTextRange(e);if(!e.isMultiLine()&&f=="{"){var g=d.doc.getLine(e.start.row),h=g.substring(e.end.column,e.end.column+1);if(h=="}")return e.end.column++,e}}),this.add("parens","insertion",function(a,b,c,d,e){if(e=="("){var f=c.getSelectionRange(),g=d.doc.getTextRange(f);return g!==""?{text:"("+g+")",selection:!1}:{text:"()",selection:[1,1]}}if(e==")"){var h=c.getCursorPosition(),i=d.doc.getLine(h.row),j=i.substring(h.column,h.column+1);if(j==")"){var k=d.$findOpeningBracket(")",{column:h.column+1,row:h.row});if(k!==null)return{text:"",selection:[1,1]}}}}),this.add("parens","deletion",function(a,b,c,d,e){var f=d.doc.getTextRange(e);if(!e.isMultiLine()&&f=="("){var g=d.doc.getLine(e.start.row),h=g.substring(e.start.column+1,e.start.column+2);if(h==")")return e.end.column++,e}}),this.add("string_dquotes","insertion",function(a,b,c,d,e){if(e=='"'){var f=c.getSelectionRange(),g=d.doc.getTextRange(f);if(g!=="")return{text:'"'+g+'"',selection:!1};var h=c.getCursorPosition(),i=d.doc.getLine(h.row),j=i.substring(h.column-1,h.column);if(j=="\\")return null;var k=d.getTokens(f.start.row,f.start.row)[0].tokens,l=0,m,n=-1;for(var o=0;o<k.length;o++){m=k[o],m.type=="string"?n=-1:n<0&&(n=m.value.indexOf('"'));if(m.value.length+l>f.start.column)break;l+=k[o].value.length}if(!m||n<0&&m.type!=="comment"&&(m.type!=="string"||f.start.column!==m.value.length+l-1&&m.value.lastIndexOf('"')===m.value.length-1))return{text:'""',selection:[1,1]};if(m&&m.type==="string"){var p=i.substring(h.column,h.column+1);if(p=='"')return{text:"",selection:[1,1]}}}}),this.add("string_dquotes","deletion",function(a,b,c,d,e){var f=d.doc.getTextRange(e);if(!e.isMultiLine()&&f=='"'){var g=d.doc.getLine(e.start.row),h=g.substring(e.start.column+1,e.start.column+2);if(h=='"')return e.end.column++,e}})};d.inherits(f,e),b.CstyleBehaviour=f}),define("ace/mode/folding/cstyle",["require","exports","module","ace/lib/oop","ace/range","ace/mode/folding/fold_mode"],function(a,b,c){"use strict";var d=a("../../lib/oop"),e=a("../../range").Range,f=a("./fold_mode").FoldMode,g=b.FoldMode=function(){};d.inherits(g,f),function(){this.foldingStartMarker=/(\{|\[)[^\}\]]*$|^\s*(\/\*)/,this.foldingStopMarker=/^[^\[\{]*(\}|\])|^[\s\*]*(\*\/)/,this.getFoldWidgetRange=function(a,b,c){var d=a.getLine(c),f=d.match(this.foldingStartMarker);if(f){var g=f.index;if(f[1])return this.openingBracketBlock(a,f[1],c,g);var h=a.getCommentFoldRange(c,g+f[0].length);return h.end.column-=2,h}if(b!=="markbeginend")return;var f=d.match(this.foldingStopMarker);if(f){var g=f.index+f[0].length;if(f[2]){var h=a.getCommentFoldRange(c,g);return h.end.column-=2,h}var i={row:c,column:g},j=a.$findOpeningBracket(f[1],i);if(!j)return;return j.column++,i.column--,e.fromPoints(j,i)}}}.call(g.prototype)}),define("ace/mode/folding/fold_mode",["require","exports","module","ace/range"],function(a,b,c){"use strict";var d=a("../../range").Range,e=b.FoldMode=function(){};((function(){this.foldingStartMarker=null,this.foldingStopMarker=null,this.getFoldWidget=function(a,b,c){var d=a.getLine(c);return this.foldingStartMarker.test(d)?"start":b=="markbeginend"&&this.foldingStopMarker&&this.foldingStopMarker.test(d)?"end":""},this.getFoldWidgetRange=function(a,b,c){return null},this.indentationBlock=function(a,b,c){var e=/^\s*/,f=b,g=b,h=a.getLine(b),i=c||h.length,j=h.match(e)[0].length,k=a.getLength();while(++b<k){h=a.getLine(b);var l=h.match(e)[0].length;if(l==h.length)continue;if(l<=j)break;g=b}if(g>f){var m=a.getLine(g).length;return new d(f,i,g,m)}},this.openingBracketBlock=function(a,b,c,e){var f={row:c,column:e+1},g=a.$findClosingBracket(b,f);if(!g)return;var h=a.foldWidgets[g.row];return h==null&&(h=this.getFoldWidget(a,g.row)),h=="start"&&(g.row--,g.column=a.getLine(g.row).length),d.fromPoints(f,g)}})).call(e.prototype)}),define("ace/mode/xml",["require","exports","module","ace/lib/oop","ace/mode/text","ace/tokenizer","ace/mode/xml_highlight_rules","ace/mode/behaviour/xml","ace/mode/folding/xml"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("./text").Mode,f=a("../tokenizer").Tokenizer,g=a("./xml_highlight_rules").XmlHighlightRules,h=a("./behaviour/xml").XmlBehaviour,i=a("./folding/xml").FoldMode,j=function(){this.$tokenizer=new f((new g).getRules()),this.$behaviour=new h,this.foldingRules=new i};d.inherits(j,e),function(){this.getNextLineIndent=function(a,b,c){return this.$getIndent(b)}}.call(j.prototype),b.Mode=j}),define("ace/mode/xml_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/xml_util","ace/mode/text_highlight_rules"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("./xml_util"),f=a("./text_highlight_rules").TextHighlightRules,g=function(){this.$rules={start:[{token:"text",regex:"<\\!\\[CDATA\\[",next:"cdata"},{token:"xml_pe",regex:"<\\?.*?\\?>"},{token:"comment",merge:!0,regex:"<\\!--",next:"comment"},{token:"meta.tag",regex:"<\\/?",next:"tag"},{token:"text",regex:"\\s+"},{token:"text",regex:"[^<]+"}],cdata:[{token:"text",regex:"\\]\\]>",next:"start"},{token:"text",regex:"\\s+"},{token:"text",regex:"(?:[^\\]]|\\](?!\\]>))+"}],comment:[{token:"comment",regex:".*?-->",next:"start"},{token:"comment",merge:!0,regex:".+"}]},e.tag(this.$rules,"tag","start")};d.inherits(g,f),b.XmlHighlightRules=g}),define("ace/mode/xml_util",["require","exports","module","ace/lib/lang"],function(a,b,c){function g(a){return[{token:"string",regex:'".*?"'},{token:"string",merge:!0,regex:'["].*',next:a+"-qqstring"},{token:"string",regex:"'.*?'"},{token:"string",merge:!0,regex:"['].*",next:a+"-qstring"}]}function h(a,b){return[{token:"string",merge:!0,regex:".*?"+a,next:b},{token:"string",merge:!0,regex:".+"}]}"use strict";var d=a("../lib/lang"),e=d.arrayToMap("button|form|input|label|select|textarea".split("|")),f=d.arrayToMap("table|tbody|td|tfoot|th|tr".split("|"));b.tag=function(a,b,c){a[b]=[{token:"text",regex:"\\s+"},{token:function(a){return a==="a"?"meta.tag.anchor":a==="img"?"meta.tag.image":a==="script"?"meta.tag.script":a==="style"?"meta.tag.style":e.hasOwnProperty(a.toLowerCase())?"meta.tag.form":f.hasOwnProperty(a.toLowerCase())?"meta.tag.table":"meta.tag"},merge:!0,regex:"[-_a-zA-Z0-9:!]+",next:b+"embed-attribute-list"},{token:"empty",regex:"",next:b+"embed-attribute-list"}],a[b+"-qstring"]=h("'",b+"embed-attribute-list"),a[b+"-qqstring"]=h('"',b+"embed-attribute-list"),a[b+"embed-attribute-list"]=[{token:"meta.tag",merge:!0,regex:"/?>",next:c},{token:"keyword.operator",regex:"="},{token:"entity.other.attribute-name",regex:"[-_a-zA-Z0-9:]+"},{token:"constant.numeric",regex:"[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"},{token:"text",regex:"\\s+"}].concat(g(b))}}),define("ace/mode/behaviour/xml",["require","exports","module","ace/lib/oop","ace/mode/behaviour","ace/mode/behaviour/cstyle"],function(a,b,c){"use strict";var d=a("../../lib/oop"),e=a("../behaviour").Behaviour,f=a("./cstyle").CstyleBehaviour,g=function(){this.inherit(f,["string_dquotes"]),this.add("brackets","insertion",function(a,b,c,d,e){if(e=="<"){var f=c.getSelectionRange(),g=d.doc.getTextRange(f);return g!==""?!1:{text:"<>",selection:[1,1]}}if(e==">"){var h=c.getCursorPosition(),i=d.doc.getLine(h.row),j=i.substring(h.column,h.column+1);if(j==">")return{text:"",selection:[1,1]}}else if(e=="\n"){var h=c.getCursorPosition(),i=d.doc.getLine(h.row),k=i.substring(h.column,h.column+2);if(k=="</"){var l=this.$getIndent(d.doc.getLine(h.row))+d.getTabString(),m=this.$getIndent(d.doc.getLine(h.row));return{text:"\n"+l+"\n"+m,selection:[1,l.length,1,l.length]}}}})};d.inherits(g,e),b.XmlBehaviour=g}),define("ace/mode/folding/xml",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/range","ace/mode/folding/fold_mode","ace/token_iterator"],function(a,b,c){"use strict";var d=a("../../lib/oop"),e=a("../../lib/lang"),f=a("../../range").Range,g=a("./fold_mode").FoldMode,h=a("../../token_iterator").TokenIterator,i=b.FoldMode=function(a){g.call(this),this.voidElements=a||{}};d.inherits(i,g),function(){this.getFoldWidget=function(a,b,c){var d=this._getFirstTagInLine(a,c);return d.closing?b=="markbeginend"?"end":"":!d.tagName||this.voidElements[d.tagName.toLowerCase()]?"":d.selfClosing?"":d.value.indexOf("/"+d.tagName)!==-1?"":"start"},this._getFirstTagInLine=function(a,b){var c=a.getTokens(b,b)[0].tokens,d="";for(var f=0;f<c.length;f++){var g=c[f];g.type.indexOf("meta.tag")===0?d+=g.value:d+=e.stringRepeat(" ",g.value.length)}return this._parseTag(d)},this.tagRe=/^(\s*)(<?(\/?)([-_a-zA-Z0-9:!]*)\s*(\/?)>?)/,this._parseTag=function(a){var b=this.tagRe.exec(a),c=this.tagRe.lastIndex||0;return this.tagRe.lastIndex=0,{value:a,match:b?b[2]:"",closing:b?!!b[3]:!1,selfClosing:b?!!b[5]||b[2]=="/>":!1,tagName:b?b[4]:"",column:b[1]?c+b[1].length:c}},this._readTagForward=function(a){var b=a.getCurrentToken();if(!b)return null;var c="",d;do if(b.type.indexOf("meta.tag")===0){if(!d)var d={row:a.getCurrentTokenRow(),column:a.getCurrentTokenColumn()};c+=b.value;if(c.indexOf(">")!==-1){var e=this._parseTag(c);return e.start=d,e.end={row:a.getCurrentTokenRow(),column:a.getCurrentTokenColumn()+b.value.length},a.stepForward(),e}}while(b=a.stepForward());return null},this._readTagBackward=function(a){var b=a.getCurrentToken();if(!b)return null;var c="",d;do if(b.type.indexOf("meta.tag")===0){d||(d={row:a.getCurrentTokenRow(),column:a.getCurrentTokenColumn()+b.value.length}),c=b.value+c;if(c.indexOf("<")!==-1){var e=this._parseTag(c);return e.end=d,e.start={row:a.getCurrentTokenRow(),column:a.getCurrentTokenColumn()},a.stepBackward(),e}}while(b=a.stepBackward());return null},this._pop=function(a,b){while(a.length){var c=a[a.length-1];if(!b||c.tagName==b.tagName)return a.pop();if(this.voidElements[b.tagName])return;if(this.voidElements[c.tagName]){a.pop();continue}return null}},this.getFoldWidgetRange=function(a,b,c){var d=this._getFirstTagInLine(a,c);if(!d.match)return null;var e=d.closing||d.selfClosing,g=[],i;if(!e){var j=new h(a,c,d.column),k={row:c,column:d.column+d.tagName.length+2};while(i=this._readTagForward(j)){if(i.selfClosing){if(!g.length)return i.start.column+=i.tagName.length+2,i.end.column-=2,f.fromPoints(i.start,i.end);continue}if(i.closing){this._pop(g,i);if(g.length==0)return f.fromPoints(k,i.start)}else g.push(i)}}else{var j=new h(a,c,d.column+d.match.length),l={row:c,column:d.column};while(i=this._readTagBackward(j)){if(i.selfClosing){if(!g.length)return i.start.column+=i.tagName.length+2,i.end.column-=2,f.fromPoints(i.start,i.end);continue}if(!i.closing){this._pop(g,i);if(g.length==0)return i.start.column+=i.tagName.length+2,f.fromPoints(i.start,l)}else g.push(i)}}}}.call(i.prototype)}),define("ace/mode/html",["require","exports","module","ace/lib/oop","ace/mode/text","ace/mode/javascript","ace/mode/css","ace/tokenizer","ace/mode/html_highlight_rules","ace/mode/behaviour/xml","ace/mode/folding/html"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("./text").Mode,f=a("./javascript").Mode,g=a("./css").Mode,h=a("../tokenizer").Tokenizer,i=a("./html_highlight_rules").HtmlHighlightRules,j=a("./behaviour/xml").XmlBehaviour,k=a("./folding/html").FoldMode,l=function(){var a=new i;this.$tokenizer=new h(a.getRules()),this.$behaviour=new j,this.$embeds=a.getEmbeds(),this.createModeDelegates({"js-":f,"css-":g}),this.foldingRules=new k};d.inherits(l,e),function(){this.toggleCommentLines=function(a,b,c,d){return 0},this.getNextLineIndent=function(a,b,c){return this.$getIndent(b)},this.checkOutdent=function(a,b,c){return!1}}.call(l.prototype),b.Mode=l}),define("ace/mode/css",["require","exports","module","ace/lib/oop","ace/mode/text","ace/tokenizer","ace/mode/css_highlight_rules","ace/mode/matching_brace_outdent","ace/worker/worker_client","ace/mode/folding/cstyle"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("./text").Mode,f=a("../tokenizer").Tokenizer,g=a("./css_highlight_rules").CssHighlightRules,h=a("./matching_brace_outdent").MatchingBraceOutdent,i=a("../worker/worker_client").WorkerClient,j=a("./folding/cstyle").FoldMode,k=function(){this.$tokenizer=new f((new g).getRules(),"i"),this.$outdent=new h,this.foldingRules=new j};d.inherits(k,e),function(){this.foldingRules="cStyle",this.getNextLineIndent=function(a,b,c){var d=this.$getIndent(b),e=this.$tokenizer.getLineTokens(b,a).tokens;if(e.length&&e[e.length-1].type=="comment")return d;var f=b.match(/^.*\{\s*$/);return f&&(d+=c),d},this.checkOutdent=function(a,b,c){return this.$outdent.checkOutdent(b,c)},this.autoOutdent=function(a,b,c){this.$outdent.autoOutdent(b,c)},this.createWorker=function(a){var b=new i(["ace"],"worker-css.js","ace/mode/css_worker","Worker");return b.attachToDocument(a.getDocument()),b.on("csslint",function(b){var c=[];b.data.forEach(function(a){c.push({row:a.line-1,column:a.col-1,text:a.message,type:a.type,lint:a})}),a.setAnnotations(c)}),b}}.call(k.prototype),b.Mode=k}),define("ace/mode/css_highlight_rules",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/mode/text_highlight_rules"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("../lib/lang"),f=a("./text_highlight_rules").TextHighlightRules,g=function(){var a=e.arrayToMap("-moz-appearance|-moz-box-sizing|-webkit-box-sizing|-moz-outline-radius|-moz-transform|-webkit-transform|appearance|azimuth|background-attachment|background-color|background-image|background-origin|background-position|background-repeat|background|border-bottom-color|border-bottom-style|border-bottom-width|border-bottom|border-collapse|border-color|border-left-color|border-left-style|border-left-width|border-left|border-right-color|border-right-style|border-right-width|border-right|border-spacing|border-style|border-top-color|border-top-style|border-top-width|border-top|border-width|border|bottom|box-sizing|caption-side|clear|clip|color|content|counter-increment|counter-reset|cue-after|cue-before|cue|cursor|direction|display|elevation|empty-cells|float|font-family|font-size-adjust|font-size|font-stretch|font-style|font-variant|font-weight|font|height|left|letter-spacing|line-height|list-style-image|list-style-position|list-style-type|list-style|margin-bottom|margin-left|margin-right|margin-top|marker-offset|margin|marks|max-height|max-width|min-height|min-width|-moz-border-radius|opacity|orphans|outline-color|outline-offset|outline-radius|outline-style|outline-width|outline|overflow|overflow-x|overflow-y|padding-bottom|padding-left|padding-right|padding-top|padding|page-break-after|page-break-before|page-break-inside|page|pause-after|pause-before|pause|pitch-range|pitch|play-during|pointer-events|position|quotes|resize|richness|right|size|speak-header|speak-numeral|speak-punctuation|speech-rate|speak|stress|table-layout|text-align|text-decoration|text-indent|text-shadow|text-transform|top|transform|unicode-bidi|vertical-align|visibility|voice-family|volume|white-space|widows|width|word-spacing|z-index".split("|")),b=e.arrayToMap("rgb|rgba|url|attr|counter|counters".split("|")),c=e.arrayToMap("absolute|all-scroll|always|armenian|auto|baseline|below|bidi-override|block|bold|bolder|border-box|both|bottom|break-all|break-word|capitalize|center|char|circle|cjk-ideographic|col-resize|collapse|content-box|crosshair|dashed|decimal-leading-zero|decimal|default|disabled|disc|distribute-all-lines|distribute-letter|distribute-space|distribute|dotted|double|e-resize|ellipsis|fixed|georgian|groove|hand|hebrew|help|hidden|hiragana-iroha|hiragana|horizontal|ideograph-alpha|ideograph-numeric|ideograph-parenthesis|ideograph-space|inactive|inherit|inline-block|inline|inset|inside|inter-ideograph|inter-word|italic|justify|katakana-iroha|katakana|keep-all|left|lighter|line-edge|line-through|line|list-item|loose|lower-alpha|lower-greek|lower-latin|lower-roman|lowercase|lr-tb|ltr|medium|middle|move|n-resize|ne-resize|newspaper|no-drop|no-repeat|nw-resize|none|normal|not-allowed|nowrap|oblique|outset|outside|overline|pointer|progress|relative|repeat-x|repeat-y|repeat|right|ridge|row-resize|rtl|s-resize|scroll|se-resize|separate|small-caps|solid|square|static|strict|super|sw-resize|table-footer-group|table-header-group|tb-rl|text-bottom|text-top|text|thick|thin|top|transparent|underline|upper-alpha|upper-latin|upper-roman|uppercase|vertical-ideographic|vertical-text|visible|w-resize|wait|whitespace|zero".split("|")),d=e.arrayToMap("aqua|black|blue|fuchsia|gray|green|lime|maroon|navy|olive|orange|purple|red|silver|teal|white|yellow".split("|")),f="\\-?(?:(?:[0-9]+)|(?:[0-9]*\\.[0-9]+))",g=[{token:"comment",merge:!0,regex:"\\/\\*",next:"ruleset_comment"},{token:"string",regex:'["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'},{token:"string",regex:"['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"},{token:"constant.numeric",regex:f+"(?:em|ex|px|cm|mm|in|pt|pc|deg|rad|grad|ms|s|hz|khz|%)"},{token:"constant.numeric",regex:"#[a-f0-9]{6}"},{token:"constant.numeric",regex:"#[a-f0-9]{3}"},{token:function(e){return a.hasOwnProperty(e.toLowerCase())?"support.type":b.hasOwnProperty(e.toLowerCase())?"support.function":c.hasOwnProperty(e.toLowerCase())?"support.constant":d.hasOwnProperty(e.toLowerCase())?"support.constant.color":"text"},regex:"\\-?[a-zA-Z_][a-zA-Z0-9_\\-]*"}],h=e.copyArray(g);h.unshift({token:"paren.rparen",regex:"\\}",next:"start"});var i=e.copyArray(g);i.unshift({token:"paren.rparen",regex:"\\}",next:"media"});var j=[{token:"comment",merge:!0,regex:".+"}],k=e.copyArray(j);k.unshift({token:"comment",regex:".*?\\*\\/",next:"start"});var l=e.copyArray(j);l.unshift({token:"comment",regex:".*?\\*\\/",next:"media"});var m=e.copyArray(j);m.unshift({token:"comment",regex:".*?\\*\\/",next:"ruleset"}),this.$rules={start:[{token:"comment",merge:!0,regex:"\\/\\*",next:"comment"},{token:"paren.lparen",regex:"\\{",next:"ruleset"},{token:"string",regex:"@.*?{",next:"media"},{token:"keyword",regex:"#[a-z0-9-_]+"},{token:"variable",regex:"\\.[a-z0-9-_]+"},{token:"string",regex:":[a-z0-9-_]+"},{token:"constant",regex:"[a-z0-9-_]+"}],media:[{token:"comment",merge:!0,regex:"\\/\\*",next:"media_comment"},{token:"paren.lparen",regex:"\\{",next:"media_ruleset"},{token:"string",regex:"\\}",next:"start"},{token:"keyword",regex:"#[a-z0-9-_]+"},{token:"variable",regex:"\\.[a-z0-9-_]+"},{token:"string",regex:":[a-z0-9-_]+"},{token:"constant",regex:"[a-z0-9-_]+"}],comment:k,ruleset:h,ruleset_comment:m,media_ruleset:i,media_comment:l}};d.inherits(g,f),b.CssHighlightRules=g}),define("ace/mode/html_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/css_highlight_rules","ace/mode/javascript_highlight_rules","ace/mode/xml_util","ace/mode/text_highlight_rules"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("./css_highlight_rules").CssHighlightRules,f=a("./javascript_highlight_rules").JavaScriptHighlightRules,g=a("./xml_util"),h=a("./text_highlight_rules").TextHighlightRules,i=function(){this.$rules={start:[{token:"text",merge:!0,regex:"<\\!\\[CDATA\\[",next:"cdata"},{token:"xml_pe",regex:"<\\?.*?\\?>"},{token:"comment",merge:!0,regex:"<\\!--",next:"comment"},{token:"meta.tag",regex:"<(?=s*script\\b)",next:"script"},{token:"meta.tag",regex:"<(?=s*style\\b)",next:"css"},{token:"meta.tag",regex:"<\\/?",next:"tag"},{token:"text",regex:"\\s+"},{token:"text",regex:"[^<]+"}],cdata:[{token:"text",regex:"\\]\\]>",next:"start"},{token:"text",merge:!0,regex:"\\s+"},{token:"text",merge:!0,regex:".+"}],comment:[{token:"comment",regex:".*?-->",next:"start"},{token:"comment",merge:!0,regex:".+"}]},g.tag(this.$rules,"tag","start"),g.tag(this.$rules,"css","css-start"),g.tag(this.$rules,"script","js-start"),this.embedRules(f,"js-",[{token:"comment",regex:"\\/\\/.*(?=<\\/script>)",next:"tag"},{token:"meta.tag",regex:"<\\/(?=script)",next:"tag"}]),this.embedRules(e,"css-",[{token:"meta.tag",regex:"<\\/(?=style)",next:"tag"}])};d.inherits(i,h),b.HtmlHighlightRules=i}),define("ace/mode/folding/html",["require","exports","module","ace/lib/oop","ace/mode/folding/mixed","ace/mode/folding/xml","ace/mode/folding/cstyle"],function(a,b,c){"use strict";var d=a("../../lib/oop"),e=a("./mixed").FoldMode,f=a("./xml").FoldMode,g=a("./cstyle").FoldMode,h=b.FoldMode=function(){e.call(this,new f({area:1,base:1,br:1,col:1,command:1,embed:1,hr:1,img:1,input:1,keygen:1,link:1,meta:1,param:1,source:1,track:1,wbr:1,li:1,dt:1,dd:1,p:1,rt:1,rp:1,optgroup:1,option:1,colgroup:1,td:1,th:1}),{"js-":new g,"css-":new g})};d.inherits(h,e)}),define("ace/mode/folding/mixed",["require","exports","module","ace/lib/oop","ace/mode/folding/fold_mode"],function(a,b,c){"use strict";var d=a("../../lib/oop"),e=a("./fold_mode").FoldMode,f=b.FoldMode=function(a,b){this.defaultMode=a,this.subModes=b};d.inherits(f,e),function(){this.$getMode=function(a){for(var b in this.subModes)if(a.indexOf(b)===0)return this.subModes[b];return null},this.$tryMode=function(a,b,c,d){var e=this.$getMode(a);return e?e.getFoldWidget(b,c,d):""},this.getFoldWidget=function(a,b,c){return this.$tryMode(a.getState(c-1),a,b,c)||this.$tryMode(a.getState(c),a,b,c)||this.defaultMode.getFoldWidget(a,b,c)},this.getFoldWidgetRange=function(a,b,c){var d=this.$getMode(a.getState(c-1));if(!d||!d.getFoldWidget(a,b,c))d=this.$getMode(a.getState(c));if(!d||!d.getFoldWidget(a,b,c))d=this.defaultMode;return d.getFoldWidgetRange(a,b,c)}}.call(f.prototype)}),define("ace/mode/markdown_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules","ace/mode/javascript_highlight_rules","ace/mode/xml_highlight_rules","ace/mode/html_highlight_rules","ace/mode/css_highlight_rules"],function(a,b,c){function j(a,b){return{token:"support.function",regex:"^```"+a+"\\s*$",next:b+"start"}}"use strict";var d=a("../lib/oop"),e=a("./text_highlight_rules").TextHighlightRules,f=a("./javascript_highlight_rules").JavaScriptHighlightRules,g=a("./xml_highlight_rules").XmlHighlightRules,h=a("./html_highlight_rules").HtmlHighlightRules,i=a("./css_highlight_rules").CssHighlightRules,k=function(){this.$rules={start:[{token:"empty_line",regex:"^$"},{token:"support.function",regex:"(`+)([^\\r]*?[^`])(\\1)"},{token:"support.function",regex:"^[ ]{4}.+"},{token:"markup.heading.1",regex:"^=+(?=\\s*$)"},{token:"markup.heading.1",regex:"^\\-+(?=\\s*$)"},{token:function(a){return"markup.heading."+a.length},regex:"^#{1,6}"},j("javascript","js-"),j("xml","xml-"),j("html","html-"),j("css","css-"),{token:"support.function",regex:"^```[a-zA-Z]+\\s*$",next:"githubblock"},{token:"string",regex:"^>[ ].+$",next:"blockquote"},{token:["text","constant","text","url","string","text"],regex:'^([ ]{0,3}\\[)([^\\]]+)(\\]:\\s*)([^ ]+)(\\s*(?:["][^"]+["])?\\s*)$'},{token:["text","string","text","constant","text"],regex:"(\\[)((?:[[^\\]]*\\]|[^\\[\\]])*)(\\][ ]?(?:\\n[ ]*)?\\[)(.*?)(\\])"},{token:["text","string","text","markup.underline","string","text"],regex:'(\\[)(\\[[^\\]]*\\]|[^\\[\\]]*)(\\]\\([ \\t]*)(<?(?:(?:[^\\(]*?\\([^\\)]*?\\)\\S*?)|(?:.*?))>?)((?:[ \t]*"(?:.*?)"[ \\t]*)?)(\\))'},{token:"constant",regex:"^[ ]{0,2}(?:[ ]?\\*[ ]?){3,}\\s*$"},{token:"constant",regex:"^[ ]{0,2}(?:[ ]?\\-[ ]?){3,}\\s*$"},{token:"constant",regex:"^[ ]{0,2}(?:[ ]?\\_[ ]?){3,}\\s*$"},{token:"markup.list",regex:"^\\s{0,3}(?:[*+-]|\\d+\\.)\\s+",next:"listblock"},{token:"string",regex:"([*]{2}|[_]{2}(?=\\S))([^\\r]*?\\S[*_]*)(\\1)"},{token:"string",regex:"([*]|[_](?=\\S))([^\\r]*?\\S[*_]*)(\\1)"},{token:["text","url","text"],regex:"(<)((?:https?|ftp|dict):[^'\">\\s]+|(?:mailto:)?[-.\\w]+\\@[-a-z0-9]+(?:\\.[-a-z0-9]+)*\\.[a-z]+)(>)"},{token:"text",regex:"[^\\*_%$`\\[#<>]+"}],listblock:[{token:"empty_line",regex:"^$",next:"start"},{token:"markup.list",regex:".+"}],blockquote:[{token:"empty_line",regex:"^\\s*$",next:"start"},{token:"string",regex:".+"}],githubblock:[{token:"support.function",regex:"^```",next:"start"},{token:"support.function",regex:".+"}]},this.embedRules(f,"js-",[{token:"support.function",regex:"^```",next:"start"}]),this.embedRules(h,"html-",[{token:"support.function",regex:"^```",next:"start"}]),this.embedRules(i,"css-",[{token:"support.function",regex:"^```",next:"start"}]),this.embedRules(g,"xml-",[{token:"support.function",regex:"^```",next:"start"}])};d.inherits(k,e),b.MarkdownHighlightRules=k}),function(){window.require(["ace/ace"],function(a){window.ace||(window.ace={});for(var b in a)a.hasOwnProperty(b)&&(ace[b]=a[b])})}()
\ No newline at end of file
+define("ace/mode/markdown",["require","exports","module","ace/lib/oop","ace/mode/text","ace/mode/javascript","ace/mode/xml","ace/mode/html","ace/tokenizer","ace/mode/markdown_highlight_rules"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("./text").Mode,f=a("./javascript").Mode,g=a("./xml").Mode,h=a("./html").Mode,i=a("../tokenizer").Tokenizer,j=a("./markdown_highlight_rules").MarkdownHighlightRules,k=function(){var a=new j;this.$tokenizer=new i(a.getRules()),this.$embeds=a.getEmbeds(),this.createModeDelegates({"js-":f,"xml-":g,"html-":h})};d.inherits(k,e),function(){this.getNextLineIndent=function(a,b,c){if(a=="listblock"){var d=/^((?:.+)?)([-+*][ ]+)/.exec(b);return d?(new Array(d[1].length+1)).join(" ")+d[2]:""}return this.$getIndent(b)}}.call(k.prototype),b.Mode=k}),define("ace/mode/javascript",["require","exports","module","ace/lib/oop","ace/mode/text","ace/tokenizer","ace/mode/javascript_highlight_rules","ace/mode/matching_brace_outdent","ace/range","ace/worker/worker_client","ace/mode/behaviour/cstyle","ace/mode/folding/cstyle"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("./text").Mode,f=a("../tokenizer").Tokenizer,g=a("./javascript_highlight_rules").JavaScriptHighlightRules,h=a("./matching_brace_outdent").MatchingBraceOutdent,i=a("../range").Range,j=a("../worker/worker_client").WorkerClient,k=a("./behaviour/cstyle").CstyleBehaviour,l=a("./folding/cstyle").FoldMode,m=function(){this.$tokenizer=new f((new g).getRules()),this.$outdent=new h,this.$behaviour=new k,this.foldingRules=new l};d.inherits(m,e),function(){this.toggleCommentLines=function(a,b,c,d){var e=!0,f=/^(\s*)\/\//;for(var g=c;g<=d;g++)if(!f.test(b.getLine(g))){e=!1;break}if(e){var h=new i(0,0,0,0);for(var g=c;g<=d;g++){var j=b.getLine(g),k=j.match(f);h.start.row=g,h.end.row=g,h.end.column=k[0].length,b.replace(h,k[1])}}else b.indentRows(c,d,"//")},this.getNextLineIndent=function(a,b,c){var d=this.$getIndent(b),e=this.$tokenizer.getLineTokens(b,a),f=e.tokens,g=e.state;if(f.length&&f[f.length-1].type=="comment")return d;if(a=="start"||a=="regex_allowed"){var h=b.match(/^.*(?:\bcase\b.*\:|[\{\(\[])\s*$/);h&&(d+=c)}else if(a=="doc-start"){if(g=="start"||a=="regex_allowed")return"";var h=b.match(/^\s*(\/?)\*/);h&&(h[1]&&(d+=" "),d+="* ")}return d},this.checkOutdent=function(a,b,c){return this.$outdent.checkOutdent(b,c)},this.autoOutdent=function(a,b,c){this.$outdent.autoOutdent(b,c)},this.createWorker=function(a){var b=new j(["ace"],"worker-javascript.js","ace/mode/javascript_worker","JavaScriptWorker");return b.attachToDocument(a.getDocument()),b.on("jslint",function(b){var c=[];for(var d=0;d<b.data.length;d++){var e=b.data[d];e&&c.push({row:e.line-1,column:e.character-1,text:e.reason,type:"warning",lint:e})}a.setAnnotations(c)}),b.on("narcissus",function(b){a.setAnnotations([b.data])}),b.on("terminate",function(){a.clearAnnotations()}),b}}.call(m.prototype),b.Mode=m}),define("ace/mode/javascript_highlight_rules",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/unicode","ace/mode/doc_comment_highlight_rules","ace/mode/text_highlight_rules"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("../lib/lang"),f=a("../unicode"),g=a("./doc_comment_highlight_rules").DocCommentHighlightRules,h=a("./text_highlight_rules").TextHighlightRules,i=function(){var a=e.arrayToMap("Array|Boolean|Date|Function|Iterator|Number|Object|RegExp|String|Proxy|Namespace|QName|XML|XMLList|ArrayBuffer|Float32Array|Float64Array|Int16Array|Int32Array|Int8Array|Uint16Array|Uint32Array|Uint8Array|Uint8ClampedArray|Error|EvalError|InternalError|RangeError|ReferenceError|StopIteration|SyntaxError|TypeError|URIError|decodeURI|decodeURIComponent|encodeURI|encodeURIComponent|eval|isFinite|isNaN|parseFloat|parseInt|JSON|Math|this|arguments|prototype|window|document".split("|")),b=e.arrayToMap("break|case|catch|continue|default|delete|do|else|finally|for|function|if|in|instanceof|new|return|switch|throw|try|typeof|let|var|while|with|const|yield|import|get|set".split("|")),c="case|do|else|finally|in|instanceof|return|throw|try|typeof|yield",d=e.arrayToMap("__parent__|__count__|escape|unescape|with|__proto__".split("|")),h=e.arrayToMap("const|let|var|function".split("|")),i=e.arrayToMap("null|Infinity|NaN|undefined".split("|")),j=e.arrayToMap("class|enum|extends|super|export|implements|private|public|interface|package|protected|static".split("|")),k="["+f.packages.L+"\\$_]["+f.packages.L+f.packages.Mn+f.packages.Mc+f.packages.Nd+f.packages.Pc+"\\$_]*\\b",l="\\\\(?:x[0-9a-fA-F]{2}|u[0-9a-fA-F]{4}|[0-2][0-7]{0,2}|3[0-6][0-7]?|37[0-7]?|[4-7][0-7]?|.)";this.$rules={start:[{token:"comment",regex:/\/\/.*$/},(new g).getStartRule("doc-start"),{token:"comment",merge:!0,regex:/\/\*/,next:"comment"},{token:"string",regex:"'",next:"qstring"},{token:"string",regex:'"',next:"qqstring"},{token:"constant.numeric",regex:/0[xX][0-9a-fA-F]+\b/},{token:"constant.numeric",regex:/[+-]?\d+(?:(?:\.\d*)?(?:[eE][+-]?\d+)?)?\b/},{token:["storage.type","punctuation.operator","support.function","punctuation.operator","entity.name.function","text","keyword.operator","text","storage.type","text","paren.lparen","variable.parameter","paren.rparen"],regex:"("+k+")(\\.)(prototype)(\\.)("+k+")(\\s*)(=)(\\s*)(function)(\\s*)(\\()(.*?)(\\))"},{token:["storage.type","punctuation.operator","support.function","punctuation.operator","entity.name.function","text","keyword.operator","text"],regex:"("+k+")(\\.)(prototype)(\\.)("+k+")(\\s*)(=)(\\s*)"},{token:["storage.type","punctuation.operator","entity.name.function","text","keyword.operator","text","storage.type","text","paren.lparen","variable.parameter","paren.rparen"],regex:"("+k+")(\\.)("+k+")(\\s*)(=)(\\s*)(function)(\\s*)(\\()(.*?)(\\))"},{token:["entity.name.function","text","keyword.operator","text","storage.type","text","paren.lparen","variable.parameter","paren.rparen"],regex:"("+k+")(\\s*)(=)(\\s*)(function)(\\s*)(\\()(.*?)(\\))"},{token:["storage.type","text","entity.name.function","text","paren.lparen","variable.parameter","paren.rparen"],regex:"(function)(\\s+)("+k+")(\\s*)(\\()(.*?)(\\))"},{token:["entity.name.function","text","punctuation.operator","text","storage.type","text","paren.lparen","variable.parameter","paren.rparen"],regex:"("+k+")(\\s*)(:)(\\s*)(function)(\\s*)(\\()(.*?)(\\))"},{token:["text","text","storage.type","text","paren.lparen","variable.parameter","paren.rparen"],regex:"(:)(\\s*)(function)?(\\s*)(\\()([^)]*)(\\))"},{token:"constant.language.boolean",regex:/(?:true|false)\b/},{token:"keyword",regex:"(?:"+c+")\\b",next:"regex_allowed"},{token:["punctuation.operator","support.function"],regex:/(\.)(s(?:h(?:ift|ow(?:Mod(?:elessDialog|alDialog)|Help))|croll(?:X|By(?:Pages|Lines)?|Y|To)?|t(?:opzzzz|rike)|i(?:n|zeToContent|debar|gnText)|ort|u(?:p|b(?:str(?:ing)?)?)|pli(?:ce|t)|e(?:nd|t(?:Re(?:sizable|questHeader)|M(?:i(?:nutes|lliseconds)|onth)|Seconds|Ho(?:tKeys|urs)|Year|Cursor|Time(?:out)?|Interval|ZOptions|Date|UTC(?:M(?:i(?:nutes|lliseconds)|onth)|Seconds|Hours|Date|FullYear)|FullYear|Active)|arch)|qrt|lice|avePreferences|mall)|h(?:ome|andleEvent)|navigate|c(?:har(?:CodeAt|At)|o(?:s|n(?:cat|textual|firm)|mpile)|eil|lear(?:Timeout|Interval)?|a(?:ptureEvents|ll)|reate(?:StyleSheet|Popup|EventObject))|t(?:o(?:GMTString|S(?:tring|ource)|U(?:TCString|pperCase)|Lo(?:caleString|werCase))|est|a(?:n|int(?:Enabled)?))|i(?:s(?:NaN|Finite)|ndexOf|talics)|d(?:isableExternalCapture|ump|etachEvent)|u(?:n(?:shift|taint|escape|watch)|pdateCommands)|j(?:oin|avaEnabled)|p(?:o(?:p|w)|ush|lugins.refresh|a(?:ddings|rse(?:Int|Float)?)|r(?:int|ompt|eference))|e(?:scape|nableExternalCapture|val|lementFromPoint|x(?:p|ec(?:Script|Command)?))|valueOf|UTC|queryCommand(?:State|Indeterm|Enabled|Value)|f(?:i(?:nd|le(?:ModifiedDate|Size|CreatedDate|UpdatedDate)|xed)|o(?:nt(?:size|color)|rward)|loor|romCharCode)|watch|l(?:ink|o(?:ad|g)|astIndexOf)|a(?:sin|nchor|cos|t(?:tachEvent|ob|an(?:2)?)|pply|lert|b(?:s|ort))|r(?:ou(?:nd|teEvents)|e(?:size(?:By|To)|calc|turnValue|place|verse|l(?:oad|ease(?:Capture|Events)))|andom)|g(?:o|et(?:ResponseHeader|M(?:i(?:nutes|lliseconds)|onth)|Se(?:conds|lection)|Hours|Year|Time(?:zoneOffset)?|Da(?:y|te)|UTC(?:M(?:i(?:nutes|lliseconds)|onth)|Seconds|Hours|Da(?:y|te)|FullYear)|FullYear|A(?:ttention|llResponseHeaders)))|m(?:in|ove(?:B(?:y|elow)|To(?:Absolute)?|Above)|ergeAttributes|a(?:tch|rgins|x))|b(?:toa|ig|o(?:ld|rderWidths)|link|ack))\b(?=\()/},{token:["punctuation.operator","support.function.dom"],regex:/(\.)(s(?:ub(?:stringData|mit)|plitText|e(?:t(?:NamedItem|Attribute(?:Node)?)|lect))|has(?:ChildNodes|Feature)|namedItem|c(?:l(?:ick|o(?:se|neNode))|reate(?:C(?:omment|DATASection|aption)|T(?:Head|extNode|Foot)|DocumentFragment|ProcessingInstruction|E(?:ntityReference|lement)|Attribute))|tabIndex|i(?:nsert(?:Row|Before|Cell|Data)|tem)|open|delete(?:Row|C(?:ell|aption)|T(?:Head|Foot)|Data)|focus|write(?:ln)?|a(?:dd|ppend(?:Child|Data))|re(?:set|place(?:Child|Data)|move(?:NamedItem|Child|Attribute(?:Node)?)?)|get(?:NamedItem|Element(?:sBy(?:Name|TagName)|ById)|Attribute(?:Node)?)|blur)\b(?=\()/},{token:["punctuation.operator","support.constant"],regex:/(\.)(s(?:ystemLanguage|cr(?:ipts|ollbars|een(?:X|Y|Top|Left))|t(?:yle(?:Sheets)?|atus(?:Text|bar)?)|ibling(?:Below|Above)|ource|uffixes|e(?:curity(?:Policy)?|l(?:ection|f)))|h(?:istory|ost(?:name)?|as(?:h|Focus))|y|X(?:MLDocument|SLDocument)|n(?:ext|ame(?:space(?:s|URI)|Prop))|M(?:IN_VALUE|AX_VALUE)|c(?:haracterSet|o(?:n(?:structor|trollers)|okieEnabled|lorDepth|mp(?:onents|lete))|urrent|puClass|l(?:i(?:p(?:boardData)?|entInformation)|osed|asses)|alle(?:e|r)|rypto)|t(?:o(?:olbar|p)|ext(?:Transform|Indent|Decoration|Align)|ags)|SQRT(?:1_2|2)|i(?:n(?:ner(?:Height|Width)|put)|ds|gnoreCase)|zIndex|o(?:scpu|n(?:readystatechange|Line)|uter(?:Height|Width)|p(?:sProfile|ener)|ffscreenBuffering)|NEGATIVE_INFINITY|d(?:i(?:splay|alog(?:Height|Top|Width|Left|Arguments)|rectories)|e(?:scription|fault(?:Status|Ch(?:ecked|arset)|View)))|u(?:ser(?:Profile|Language|Agent)|n(?:iqueID|defined)|pdateInterval)|_content|p(?:ixelDepth|ort|ersonalbar|kcs11|l(?:ugins|atform)|a(?:thname|dding(?:Right|Bottom|Top|Left)|rent(?:Window|Layer)?|ge(?:X(?:Offset)?|Y(?:Offset)?))|r(?:o(?:to(?:col|type)|duct(?:Sub)?|mpter)|e(?:vious|fix)))|e(?:n(?:coding|abledPlugin)|x(?:ternal|pando)|mbeds)|v(?:isibility|endor(?:Sub)?|Linkcolor)|URLUnencoded|P(?:I|OSITIVE_INFINITY)|f(?:ilename|o(?:nt(?:Size|Family|Weight)|rmName)|rame(?:s|Element)|gColor)|E|whiteSpace|l(?:i(?:stStyleType|n(?:eHeight|kColor))|o(?:ca(?:tion(?:bar)?|lName)|wsrc)|e(?:ngth|ft(?:Context)?)|a(?:st(?:M(?:odified|atch)|Index|Paren)|yer(?:s|X)|nguage))|a(?:pp(?:MinorVersion|Name|Co(?:deName|re)|Version)|vail(?:Height|Top|Width|Left)|ll|r(?:ity|guments)|Linkcolor|bove)|r(?:ight(?:Context)?|e(?:sponse(?:XML|Text)|adyState))|global|x|m(?:imeTypes|ultiline|enubar|argin(?:Right|Bottom|Top|Left))|L(?:N(?:10|2)|OG(?:10E|2E))|b(?:o(?:ttom|rder(?:Width|RightWidth|BottomWidth|Style|Color|TopWidth|LeftWidth))|ufferDepth|elow|ackground(?:Color|Image)))\b/},{token:["storage.type","punctuation.operator","support.function.firebug"],regex:/(console)(\.)(warn|info|log|error|time|timeEnd|assert)\b/},{token:function(c){return a.hasOwnProperty(c)?"variable.language":d.hasOwnProperty(c)?"invalid.deprecated":h.hasOwnProperty(c)?"storage.type":b.hasOwnProperty(c)?"keyword":i.hasOwnProperty(c)?"constant.language":j.hasOwnProperty(c)?"invalid.illegal":c=="debugger"?"invalid.deprecated":"identifier"},regex:k},{token:"keyword.operator",regex:/!|\$|%|&|\*|\-\-|\-|\+\+|\+|~|===|==|=|!=|!==|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\|\||\?\:|\*=|%=|\+=|\-=|&=|\^=|\b(?:in|instanceof|new|delete|typeof|void)/,next:"regex_allowed"},{token:"punctuation.operator",regex:/\?|\:|\,|\;|\./,next:"regex_allowed"},{token:"paren.lparen",regex:/[\[({]/,next:"regex_allowed"},{token:"paren.rparen",regex:/[\])}]/},{token:"keyword.operator",regex:/\/=?/,next:"regex_allowed"},{token:"comment",regex:/^#!.*$/},{token:"text",regex:/\s+/}],regex_allowed:[{token:"comment",merge:!0,regex:"\\/\\*",next:"comment_regex_allowed"},{token:"comment",regex:"\\/\\/.*$"},{token:"string.regexp",regex:"\\/",next:"regex",merge:!0},{token:"text",regex:"\\s+"},{token:"empty",regex:"",next:"start"}],regex:[{token:"regexp.keyword.operator",regex:"\\\\(?:u[\\da-fA-F]{4}|x[\\da-fA-F]{2}|.)",next:"regex"},{token:"string.regexp",regex:"/\\w*",next:"start",merge:!0},{token:"string.regexp",regex:"[^\\\\/\\[]+",next:"regex",merge:!0},{token:"string.regexp.charachterclass",regex:"\\[",next:"regex_character_class",merge:!0},{token:"empty",regex:"",next:"start"}],regex_character_class:[{token:"regexp.keyword.operator",regex:"\\\\(?:u[\\da-fA-F]{4}|x[\\da-fA-F]{2}|.)",next:"regex_character_class"},{token:"string.regexp.charachterclass",regex:"]",next:"regex",merge:!0},{token:"string.regexp.charachterclass",regex:"[^\\\\\\]]+",next:"regex_character_class",merge:!0},{token:"empty",regex:"",next:"start"}],comment_regex_allowed:[{token:"comment",regex:".*?\\*\\/",merge:!0,next:"regex_allowed"},{token:"comment",merge:!0,regex:".+"}],comment:[{token:"comment",regex:".*?\\*\\/",merge:!0,next:"start"},{token:"comment",merge:!0,regex:".+"}],qqstring:[{token:"constant.language.escape",regex:l},{token:"string",regex:'[^"\\\\]+'},{token:"string",regex:'"',next:"start"}],qstring:[{token:"constant.language.escape",regex:l},{token:"string",regex:"[^'\\\\]+"},{token:"string",regex:"'",next:"start"}]},this.embedRules(g,"doc-",[(new g).getEndRule("start")])};d.inherits(i,h),b.JavaScriptHighlightRules=i}),define("ace/mode/doc_comment_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("./text_highlight_rules").TextHighlightRules,f=function(){this.$rules={start:[{token:"comment.doc.tag",regex:"@[\\w\\d_]+"},{token:"comment.doc",merge:!0,regex:"\\s+"},{token:"comment.doc",merge:!0,regex:"TODO"},{token:"comment.doc",merge:!0,regex:"[^@\\*]+"},{token:"comment.doc",merge:!0,regex:"."}]}};d.inherits(f,e),function(){this.getStartRule=function(a){return{token:"comment.doc",merge:!0,regex:"\\/\\*(?=\\*)",next:a}},this.getEndRule=function(a){return{token:"comment.doc",merge:!0,regex:"\\*\\/",next:a}}}.call(f.prototype),b.DocCommentHighlightRules=f}),define("ace/mode/matching_brace_outdent",["require","exports","module","ace/range"],function(a,b,c){"use strict";var d=a("../range").Range,e=function(){};(function(){this.checkOutdent=function(a,b){return/^\s+$/.test(a)?/^\s*\}/.test(b):!1},this.autoOutdent=function(a,b){var c=a.getLine(b),e=c.match(/^(\s*\})/);if(!e)return 0;var f=e[1].length,g=a.findMatchingBracket({row:b,column:f});if(!g||g.row==b)return 0;var h=this.$getIndent(a.getLine(g.row));a.replace(new d(b,0,b,f-1),h)},this.$getIndent=function(a){var b=a.match(/^(\s+)/);return b?b[1]:""}}).call(e.prototype),b.MatchingBraceOutdent=e}),define("ace/mode/behaviour/cstyle",["require","exports","module","ace/lib/oop","ace/mode/behaviour"],function(a,b,c){"use strict";var d=a("../../lib/oop"),e=a("../behaviour").Behaviour,f=function(){this.add("braces","insertion",function(a,b,c,d,e){if(e=="{"){var f=c.getSelectionRange(),g=d.doc.getTextRange(f);return g!==""?{text:"{"+g+"}",selection:!1}:{text:"{}",selection:[1,1]}}if(e=="}"){var h=c.getCursorPosition(),i=d.doc.getLine(h.row),j=i.substring(h.column,h.column+1);if(j=="}"){var k=d.$findOpeningBracket("}",{column:h.column+1,row:h.row});if(k!==null)return{text:"",selection:[1,1]}}}else if(e=="\n"){var h=c.getCursorPosition(),i=d.doc.getLine(h.row),j=i.substring(h.column,h.column+1);if(j=="}"){var l=d.findMatchingBracket({row:h.row,column:h.column+1});if(!l)return null;var m=this.getNextLineIndent(a,i.substring(0,i.length-1),d.getTabString()),n=this.$getIndent(d.doc.getLine(l.row));return{text:"\n"+m+"\n"+n,selection:[1,m.length,1,m.length]}}}}),this.add("braces","deletion",function(a,b,c,d,e){var f=d.doc.getTextRange(e);if(!e.isMultiLine()&&f=="{"){var g=d.doc.getLine(e.start.row),h=g.substring(e.end.column,e.end.column+1);if(h=="}")return e.end.column++,e}}),this.add("parens","insertion",function(a,b,c,d,e){if(e=="("){var f=c.getSelectionRange(),g=d.doc.getTextRange(f);return g!==""?{text:"("+g+")",selection:!1}:{text:"()",selection:[1,1]}}if(e==")"){var h=c.getCursorPosition(),i=d.doc.getLine(h.row),j=i.substring(h.column,h.column+1);if(j==")"){var k=d.$findOpeningBracket(")",{column:h.column+1,row:h.row});if(k!==null)return{text:"",selection:[1,1]}}}}),this.add("parens","deletion",function(a,b,c,d,e){var f=d.doc.getTextRange(e);if(!e.isMultiLine()&&f=="("){var g=d.doc.getLine(e.start.row),h=g.substring(e.start.column+1,e.start.column+2);if(h==")")return e.end.column++,e}}),this.add("string_dquotes","insertion",function(a,b,c,d,e){if(e=='"'||e=="'"){var f=e,g=c.getSelectionRange(),h=d.doc.getTextRange(g);if(h!=="")return{text:f+h+f,selection:!1};var i=c.getCursorPosition(),j=d.doc.getLine(i.row),k=j.substring(i.column-1,i.column);if(k=="\\")return null;var l=d.getTokens(g.start.row,g.start.row)[0].tokens,m=0,n,o=-1;for(var p=0;p<l.length;p++){n=l[p],n.type=="string"?o=-1:o<0&&(o=n.value.indexOf(f));if(n.value.length+m>g.start.column)break;m+=l[p].value.length}if(!n||o<0&&n.type!=="comment"&&(n.type!=="string"||g.start.column!==n.value.length+m-1&&n.value.lastIndexOf(f)===n.value.length-1))return{text:f+f,selection:[1,1]};if(n&&n.type==="string"){var q=j.substring(i.column,i.column+1);if(q==f)return{text:"",selection:[1,1]}}}}),this.add("string_dquotes","deletion",function(a,b,c,d,e){var f=d.doc.getTextRange(e);if(!e.isMultiLine()&&(f=='"'||f=="'")){var g=d.doc.getLine(e.start.row),h=g.substring(e.start.column+1,e.start.column+2);if(h=='"')return e.end.column++,e}})};d.inherits(f,e),b.CstyleBehaviour=f}),define("ace/mode/folding/cstyle",["require","exports","module","ace/lib/oop","ace/range","ace/mode/folding/fold_mode"],function(a,b,c){"use strict";var d=a("../../lib/oop"),e=a("../../range").Range,f=a("./fold_mode").FoldMode,g=b.FoldMode=function(){};d.inherits(g,f),function(){this.foldingStartMarker=/(\{|\[)[^\}\]]*$|^\s*(\/\*)/,this.foldingStopMarker=/^[^\[\{]*(\}|\])|^[\s\*]*(\*\/)/,this.getFoldWidgetRange=function(a,b,c){var d=a.getLine(c),f=d.match(this.foldingStartMarker);if(f){var g=f.index;if(f[1])return this.openingBracketBlock(a,f[1],c,g);var h=a.getCommentFoldRange(c,g+f[0].length);return h.end.column-=2,h}if(b!=="markbeginend")return;var f=d.match(this.foldingStopMarker);if(f){var g=f.index+f[0].length;if(f[2]){var h=a.getCommentFoldRange(c,g);return h.end.column-=2,h}var i={row:c,column:g},j=a.$findOpeningBracket(f[1],i);if(!j)return;return j.column++,i.column--,e.fromPoints(j,i)}}}.call(g.prototype)}),define("ace/mode/folding/fold_mode",["require","exports","module","ace/range"],function(a,b,c){"use strict";var d=a("../../range").Range,e=b.FoldMode=function(){};(function(){this.foldingStartMarker=null,this.foldingStopMarker=null,this.getFoldWidget=function(a,b,c){var d=a.getLine(c);return this.foldingStartMarker.test(d)?"start":b=="markbeginend"&&this.foldingStopMarker&&this.foldingStopMarker.test(d)?"end":""},this.getFoldWidgetRange=function(a,b,c){return null},this.indentationBlock=function(a,b,c){var e=/^\s*/,f=b,g=b,h=a.getLine(b),i=c||h.length,j=h.match(e)[0].length,k=a.getLength();while(++b<k){h=a.getLine(b);var l=h.match(e)[0].length;if(l==h.length)continue;if(l<=j)break;g=b}if(g>f){var m=a.getLine(g).length;return new d(f,i,g,m)}},this.openingBracketBlock=function(a,b,c,e){var f={row:c,column:e+1},g=a.$findClosingBracket(b,f);if(!g)return;var h=a.foldWidgets[g.row];return h==null&&(h=this.getFoldWidget(a,g.row)),h=="start"&&(g.row--,g.column=a.getLine(g.row).length),d.fromPoints(f,g)}}).call(e.prototype)}),define("ace/mode/xml",["require","exports","module","ace/lib/oop","ace/mode/text","ace/tokenizer","ace/mode/xml_highlight_rules","ace/mode/behaviour/xml","ace/mode/folding/xml"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("./text").Mode,f=a("../tokenizer").Tokenizer,g=a("./xml_highlight_rules").XmlHighlightRules,h=a("./behaviour/xml").XmlBehaviour,i=a("./folding/xml").FoldMode,j=function(){this.$tokenizer=new f((new g).getRules()),this.$behaviour=new h,this.foldingRules=new i};d.inherits(j,e),function(){this.getNextLineIndent=function(a,b,c){return this.$getIndent(b)}}.call(j.prototype),b.Mode=j}),define("ace/mode/xml_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/xml_util","ace/mode/text_highlight_rules"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("./xml_util"),f=a("./text_highlight_rules").TextHighlightRules,g=function(){this.$rules={start:[{token:"text",regex:"<\\!\\[CDATA\\[",next:"cdata"},{token:"xml_pe",regex:"<\\?.*?\\?>"},{token:"comment",merge:!0,regex:"<\\!--",next:"comment"},{token:"xml_pe",regex:"<\\!.*?>"},{token:"meta.tag",regex:"<\\/?",next:"tag"},{token:"text",regex:"\\s+"},{token:"constant.character.entity",regex:"(?:&#[0-9]+;)|(?:&#x[0-9a-fA-F]+;)|(?:&[a-zA-Z0-9_:\\.-]+;)"},{token:"text",regex:"[^<]+"}],cdata:[{token:"text",regex:"\\]\\]>",next:"start"},{token:"text",regex:"\\s+"},{token:"text",regex:"(?:[^\\]]|\\](?!\\]>))+"}],comment:[{token:"comment",regex:".*?-->",next:"start"},{token:"comment",merge:!0,regex:".+"}]},e.tag(this.$rules,"tag","start")};d.inherits(g,f),b.XmlHighlightRules=g}),define("ace/mode/xml_util",["require","exports","module","ace/lib/lang"],function(a,b,c){function g(a){return[{token:"string",regex:'".*?"'},{token:"string",merge:!0,regex:'["].*',next:a+"_qqstring"},{token:"string",regex:"'.*?'"},{token:"string",merge:!0,regex:"['].*",next:a+"_qstring"}]}function h(a,b){return[{token:"string",merge:!0,regex:".*?"+a,next:b},{token:"string",merge:!0,regex:".+"}]}"use strict";var d=a("../lib/lang"),e=d.arrayToMap("button|form|input|label|select|textarea".split("|")),f=d.arrayToMap("table|tbody|td|tfoot|th|tr".split("|"));b.tag=function(a,b,c){a[b]=[{token:"text",regex:"\\s+"},{token:function(a){return a==="a"?"meta.tag.anchor":a==="img"?"meta.tag.image":a==="script"?"meta.tag.script":a==="style"?"meta.tag.style":e.hasOwnProperty(a.toLowerCase())?"meta.tag.form":f.hasOwnProperty(a.toLowerCase())?"meta.tag.table":"meta.tag"},merge:!0,regex:"[-_a-zA-Z0-9:]+",next:b+"_embed_attribute_list"},{token:"empty",regex:"",next:b+"_embed_attribute_list"}],a[b+"_qstring"]=h("'",b+"_embed_attribute_list"),a[b+"_qqstring"]=h('"',b+"_embed_attribute_list"),a[b+"_embed_attribute_list"]=[{token:"meta.tag",merge:!0,regex:"/?>",next:c},{token:"keyword.operator",regex:"="},{token:"entity.other.attribute-name",regex:"[-_a-zA-Z0-9:]+"},{token:"constant.numeric",regex:"[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"},{token:"text",regex:"\\s+"}].concat(g(b))}}),define("ace/mode/behaviour/xml",["require","exports","module","ace/lib/oop","ace/mode/behaviour","ace/mode/behaviour/cstyle"],function(a,b,c){"use strict";var d=a("../../lib/oop"),e=a("../behaviour").Behaviour,f=a("./cstyle").CstyleBehaviour,g=function(){this.inherit(f,["string_dquotes"]),this.add("brackets","insertion",function(a,b,c,d,e){if(e=="<"){var f=c.getSelectionRange(),g=d.doc.getTextRange(f);return g!==""?!1:{text:"<>",selection:[1,1]}}if(e==">"){var h=c.getCursorPosition(),i=d.doc.getLine(h.row),j=i.substring(h.column,h.column+1);if(j==">")return{text:"",selection:[1,1]}}else if(e=="\n"){var h=c.getCursorPosition(),i=d.doc.getLine(h.row),k=i.substring(h.column,h.column+2);if(k=="</"){var l=this.$getIndent(d.doc.getLine(h.row))+d.getTabString(),m=this.$getIndent(d.doc.getLine(h.row));return{text:"\n"+l+"\n"+m,selection:[1,l.length,1,l.length]}}}})};d.inherits(g,e),b.XmlBehaviour=g}),define("ace/mode/folding/xml",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/range","ace/mode/folding/fold_mode","ace/token_iterator"],function(a,b,c){"use strict";var d=a("../../lib/oop"),e=a("../../lib/lang"),f=a("../../range").Range,g=a("./fold_mode").FoldMode,h=a("../../token_iterator").TokenIterator,i=b.FoldMode=function(a){g.call(this),this.voidElements=a||{}};d.inherits(i,g),function(){this.getFoldWidget=function(a,b,c){var d=this._getFirstTagInLine(a,c);return d.closing?b=="markbeginend"?"end":"":!d.tagName||this.voidElements[d.tagName.toLowerCase()]?"":d.selfClosing?"":d.value.indexOf("/"+d.tagName)!==-1?"":"start"},this._getFirstTagInLine=function(a,b){var c=a.getTokens(b,b)[0].tokens,d="";for(var f=0;f<c.length;f++){var g=c[f];g.type.indexOf("meta.tag")===0?d+=g.value:d+=e.stringRepeat(" ",g.value.length)}return this._parseTag(d)},this.tagRe=/^(\s*)(<?(\/?)([-_a-zA-Z0-9:!]*)\s*(\/?)>?)/,this._parseTag=function(a){var b=this.tagRe.exec(a),c=this.tagRe.lastIndex||0;return this.tagRe.lastIndex=0,{value:a,match:b?b[2]:"",closing:b?!!b[3]:!1,selfClosing:b?!!b[5]||b[2]=="/>":!1,tagName:b?b[4]:"",column:b[1]?c+b[1].length:c}},this._readTagForward=function(a){var b=a.getCurrentToken();if(!b)return null;var c="",d;do if(b.type.indexOf("meta.tag")===0){if(!d)var d={row:a.getCurrentTokenRow(),column:a.getCurrentTokenColumn()};c+=b.value;if(c.indexOf(">")!==-1){var e=this._parseTag(c);return e.start=d,e.end={row:a.getCurrentTokenRow(),column:a.getCurrentTokenColumn()+b.value.length},a.stepForward(),e}}while(b=a.stepForward());return null},this._readTagBackward=function(a){var b=a.getCurrentToken();if(!b)return null;var c="",d;do if(b.type.indexOf("meta.tag")===0){d||(d={row:a.getCurrentTokenRow(),column:a.getCurrentTokenColumn()+b.value.length}),c=b.value+c;if(c.indexOf("<")!==-1){var e=this._parseTag(c);return e.end=d,e.start={row:a.getCurrentTokenRow(),column:a.getCurrentTokenColumn()},a.stepBackward(),e}}while(b=a.stepBackward());return null},this._pop=function(a,b){while(a.length){var c=a[a.length-1];if(!b||c.tagName==b.tagName)return a.pop();if(this.voidElements[b.tagName])return;if(this.voidElements[c.tagName]){a.pop();continue}return null}},this.getFoldWidgetRange=function(a,b,c){var d=this._getFirstTagInLine(a,c);if(!d.match)return null;var e=d.closing||d.selfClosing,g=[],i;if(!e){var j=new h(a,c,d.column),k={row:c,column:d.column+d.tagName.length+2};while(i=this._readTagForward(j)){if(i.selfClosing){if(!g.length)return i.start.column+=i.tagName.length+2,i.end.column-=2,f.fromPoints(i.start,i.end);continue}if(i.closing){this._pop(g,i);if(g.length==0)return f.fromPoints(k,i.start)}else g.push(i)}}else{var j=new h(a,c,d.column+d.match.length),l={row:c,column:d.column};while(i=this._readTagBackward(j)){if(i.selfClosing){if(!g.length)return i.start.column+=i.tagName.length+2,i.end.column-=2,f.fromPoints(i.start,i.end);continue}if(!i.closing){this._pop(g,i);if(g.length==0)return i.start.column+=i.tagName.length+2,f.fromPoints(i.start,l)}else g.push(i)}}}}.call(i.prototype)}),define("ace/mode/html",["require","exports","module","ace/lib/oop","ace/mode/text","ace/mode/javascript","ace/mode/css","ace/tokenizer","ace/mode/html_highlight_rules","ace/mode/behaviour/xml","ace/mode/folding/html"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("./text").Mode,f=a("./javascript").Mode,g=a("./css").Mode,h=a("../tokenizer").Tokenizer,i=a("./html_highlight_rules").HtmlHighlightRules,j=a("./behaviour/xml").XmlBehaviour,k=a("./folding/html").FoldMode,l=function(){var a=new i;this.$tokenizer=new h(a.getRules()),this.$behaviour=new j,this.$embeds=a.getEmbeds(),this.createModeDelegates({"js-":f,"css-":g}),this.foldingRules=new k};d.inherits(l,e),function(){this.toggleCommentLines=function(a,b,c,d){return 0},this.getNextLineIndent=function(a,b,c){return this.$getIndent(b)},this.checkOutdent=function(a,b,c){return!1}}.call(l.prototype),b.Mode=l}),define("ace/mode/css",["require","exports","module","ace/lib/oop","ace/mode/text","ace/tokenizer","ace/mode/css_highlight_rules","ace/mode/matching_brace_outdent","ace/worker/worker_client","ace/mode/folding/cstyle"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("./text").Mode,f=a("../tokenizer").Tokenizer,g=a("./css_highlight_rules").CssHighlightRules,h=a("./matching_brace_outdent").MatchingBraceOutdent,i=a("../worker/worker_client").WorkerClient,j=a("./folding/cstyle").FoldMode,k=function(){this.$tokenizer=new f((new g).getRules(),"i"),this.$outdent=new h,this.foldingRules=new j};d.inherits(k,e),function(){this.foldingRules="cStyle",this.getNextLineIndent=function(a,b,c){var d=this.$getIndent(b),e=this.$tokenizer.getLineTokens(b,a).tokens;if(e.length&&e[e.length-1].type=="comment")return d;var f=b.match(/^.*\{\s*$/);return f&&(d+=c),d},this.checkOutdent=function(a,b,c){return this.$outdent.checkOutdent(b,c)},this.autoOutdent=function(a,b,c){this.$outdent.autoOutdent(b,c)},this.createWorker=function(a){var b=new i(["ace"],"worker-css.js","ace/mode/css_worker","Worker");return b.attachToDocument(a.getDocument()),b.on("csslint",function(b){var c=[];b.data.forEach(function(a){c.push({row:a.line-1,column:a.col-1,text:a.message,type:a.type,lint:a})}),a.setAnnotations(c)}),b}}.call(k.prototype),b.Mode=k}),define("ace/mode/css_highlight_rules",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/mode/text_highlight_rules"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("../lib/lang"),f=a("./text_highlight_rules").TextHighlightRules,g=function(){var a=e.arrayToMap("animation-fill-mode|alignment-adjust|alignment-baseline|animation-delay|animation-direction|animation-duration|animation-iteration-count|animation-name|animation-play-state|animation-timing-function|animation|appearance|azimuth|backface-visibility|background-attachment|background-break|background-clip|background-color|background-image|background-origin|background-position|background-repeat|background-size|background|baseline-shift|binding|bleed|bookmark-label|bookmark-level|bookmark-state|bookmark-target|border-bottom|border-bottom-color|border-bottom-left-radius|border-bottom-right-radius|border-bottom-style|border-bottom-width|border-collapse|border-color|border-image|border-image-outset|border-image-repeat|border-image-slice|border-image-source|border-image-width|border-left|border-left-color|border-left-style|border-left-width|border-radius|border-right|border-right-color|border-right-style|border-right-width|border-spacing|border-style|border-top|border-top-color|border-top-left-radius|border-top-right-radius|border-top-style|border-top-width|border-width|border|bottom|box-align|box-decoration-break|box-direction|box-flex-group|box-flex|box-lines|box-ordinal-group|box-orient|box-pack|box-shadow|box-sizing|break-after|break-before|break-inside|caption-side|clear|clip|color-profile|color|column-count|column-fill|column-gap|column-rule|column-rule-color|column-rule-style|column-rule-width|column-span|column-width|columns|content|counter-increment|counter-reset|crop|cue-after|cue-before|cue|cursor|direction|display|dominant-baseline|drop-initial-after-adjust|drop-initial-after-align|drop-initial-before-adjust|drop-initial-before-align|drop-initial-size|drop-initial-value|elevation|empty-cells|fit|fit-position|float-offset|float|font-family|font-size|font-size-adjust|font-stretch|font-style|font-variant|font-weight|font|grid-columns|grid-rows|hanging-punctuation|height|hyphenate-after|hyphenate-before|hyphenate-character|hyphenate-lines|hyphenate-resource|hyphens|icon|image-orientation|image-rendering|image-resolution|inline-box-align|left|letter-spacing|line-height|line-stacking-ruby|line-stacking-shift|line-stacking-strategy|line-stacking|list-style-image|list-style-position|list-style-type|list-style|margin-bottom|margin-left|margin-right|margin-top|margin|mark-after|mark-before|mark|marks|marquee-direction|marquee-play-count|marquee-speed|marquee-style|max-height|max-width|min-height|min-width|move-to|nav-down|nav-index|nav-left|nav-right|nav-up|opacity|orphans|outline-color|outline-offset|outline-style|outline-width|outline|overflow-style|overflow-x|overflow-y|overflow|padding-bottom|padding-left|padding-right|padding-top|padding|page-break-after|page-break-before|page-break-inside|page-policy|page|pause-after|pause-before|pause|perspective-origin|perspective|phonemes|pitch-range|pitch|play-during|position|presentation-level|punctuation-trim|quotes|rendering-intent|resize|rest-after|rest-before|rest|richness|right|rotation-point|rotation|ruby-align|ruby-overhang|ruby-position|ruby-span|size|speak-header|speak-numeral|speak-punctuation|speak|speech-rate|stress|string-set|table-layout|target-name|target-new|target-position|target|text-align-last|text-align|text-decoration|text-emphasis|text-height|text-indent|text-justify|text-outline|text-shadow|text-transform|text-wrap|top|transform-origin|transform-style|transform|transition-delay|transition-duration|transition-property|transition-timing-function|transition|unicode-bidi|vertical-align|visibility|voice-balance|voice-duration|voice-family|voice-pitch-range|voice-pitch|voice-rate|voice-stress|voice-volume|volume|white-space-collapse|white-space|widows|width|word-break|word-spacing|word-wrap|z-index".split("|")),b=e.arrayToMap("rgb|rgba|url|attr|counter|counters".split("|")),c=e.arrayToMap("absolute|after-edge|after|all-scroll|all|alphabetic|always|antialiased|armenian|auto|avoid-column|avoid-page|avoid|balance|baseline|before-edge|before|below|bidi-override|block-line-height|block|bold|bolder|border-box|both|bottom|box|break-all|break-word|capitalize|caps-height|caption|center|central|char|circle|cjk-ideographic|clone|close-quote|col-resize|collapse|column|consider-shifts|contain|content-box|cover|crosshair|cubic-bezier|dashed|decimal-leading-zero|decimal|default|disabled|disc|disregard-shifts|distribute-all-lines|distribute-letter|distribute-space|distribute|dotted|double|e-resize|ease-in|ease-in-out|ease-out|ease|ellipsis|end|exclude-ruby|fill|fixed|font-size|font|georgian|glyphs|grid-height|groove|hand|hanging|hebrew|help|hidden|hiragana-iroha|hiragana|horizontal|icon|ideograph-alpha|ideograph-numeric|ideograph-parenthesis|ideograph-space|ideographic|inactive|include-ruby|inherit|initial|inline-block|inline-box|inline-line-height|inline-table|inline|inset|inside|inter-ideograph|inter-word|invert|italic|justify|katakana-iroha|katakana|keep-all|last|left|lighter|line-edge|line-through|line|linear|list-item|local|loose|lower-alpha|lower-greek|lower-latin|lower-roman|lowercase|lr-tb|ltr|mathematical|max-height|max-size|medium|menu|message-box|middle|move|n-resize|ne-resize|newspaper|no-change|no-close-quote|no-drop|no-open-quote|no-repeat|none|normal|not-allowed|nowrap|nw-resize|oblique|open-quote|outset|outside|overline|padding-box|page|pointer|pre-line|pre-wrap|pre|preserve-3d|progress|relative|repeat-x|repeat-y|repeat|replaced|reset-size|ridge|right|round|row-resize|rtl|s-resize|scroll|se-resize|separate|slice|small-caps|small-caption|solid|space|square|start|static|status-bar|step-end|step-start|steps|stretch|strict|sub|super|sw-resize|table-caption|table-cell|table-column-group|table-column|table-footer-group|table-header-group|table-row-group|table-row|table|tb-rl|text-after-edge|text-before-edge|text-bottom|text-size|text-top|text|thick|thin|top|transparent|underline|upper-alpha|upper-latin|upper-roman|uppercase|use-script|vertical-ideographic|vertical-text|visible|w-resize|wait|whitespace|z-index|zero".split("|")),d=e.arrayToMap("aqua|black|blue|fuchsia|gray|green|lime|maroon|navy|olive|orange|purple|red|silver|teal|white|yellow".split("|")),f=e.arrayToMap("arial|century|comic|courier|garamond|georgia|helvetica|impact|lucida|symbol|system|tahoma|times|trebuchet|utopia|verdana|webdings|sans-serif|serif|monospace".split("|")),g="\\-?(?:(?:[0-9]+)|(?:[0-9]*\\.[0-9]+))",h="(\\:+)\\b(after|before|first-letter|first-line|moz-selection|selection)\\b",i="(:)\\b(active|checked|disabled|empty|enabled|first-child|first-of-type|focus|hover|indeterminate|invalid|last-child|last-of-type|link|not|nth-child|nth-last-child|nth-last-of-type|nth-of-type|only-child|only-of-type|required|root|target|valid|visited)\\b",j=[{token:"comment",merge:!0,regex:"\\/\\*",next:"ruleset_comment"},{token:"string",regex:'["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'},{token:"string",regex:"['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"},{token:["constant.numeric","keyword"],regex:"("+g+")(ch|cm|deg|em|ex|fr|gd|grad|Hz|in|kHz|mm|ms|pc|pt|px|rad|rem|s|turn|vh|vm|vw|%)"},{token:["constant.numeric"],regex:"([0-9]+)"},{token:"constant.numeric",regex:"#[a-f0-9]{6}"},{token:"constant.numeric",regex:"#[a-f0-9]{3}"},{token:["punctuation","entity.other.attribute-name.pseudo-element.css"],regex:h},{token:["punctuation","entity.other.attribute-name.pseudo-class.css"],regex:i},{token:function(e){return a.hasOwnProperty(e.toLowerCase())?"support.type":b.hasOwnProperty(e.toLowerCase())?"support.function":c.hasOwnProperty(e.toLowerCase())?"support.constant":d.hasOwnProperty(e.toLowerCase())?"support.constant.color":f.hasOwnProperty(e.toLowerCase())?"support.constant.fonts":"text"},regex:"\\-?[a-zA-Z_][a-zA-Z0-9_\\-]*"}],k=e.copyArray(j);k.unshift({token:"paren.rparen",regex:"\\}",next:"start"});var l=e.copyArray(j);l.unshift({token:"paren.rparen",regex:"\\}",next:"media"});var m=[{token:"comment",merge:!0,regex:".+"}],n=e.copyArray(m);n.unshift({token:"comment",regex:".*?\\*\\/",next:"start"});var o=e.copyArray(m);o.unshift({token:"comment",regex:".*?\\*\\/",next:"media"});var p=e.copyArray(m);p.unshift({token:"comment",regex:".*?\\*\\/",next:"ruleset"}),this.$rules={start:[{token:"comment",merge:!0,regex:"\\/\\*",next:"comment"},{token:"paren.lparen",regex:"\\{",next:"ruleset"},{token:"string",regex:"@.*?{",next:"media"},{token:"keyword",regex:"#[a-z0-9-_]+"},{token:"variable",regex:"\\.[a-z0-9-_]+"},{token:"string",regex:":[a-z0-9-_]+"},{token:"constant",regex:"[a-z0-9-_]+"}],media:[{token:"comment",merge:!0,regex:"\\/\\*",next:"media_comment"},{token:"paren.lparen",regex:"\\{",next:"media_ruleset"},{token:"string",regex:"\\}",next:"start"},{token:"keyword",regex:"#[a-z0-9-_]+"},{token:"variable",regex:"\\.[a-z0-9-_]+"},{token:"string",regex:":[a-z0-9-_]+"},{token:"constant",regex:"[a-z0-9-_]+"}],comment:n,ruleset:k,ruleset_comment:p,media_ruleset:l,media_comment:o}};d.inherits(g,f),b.CssHighlightRules=g}),define("ace/mode/html_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/css_highlight_rules","ace/mode/javascript_highlight_rules","ace/mode/xml_util","ace/mode/text_highlight_rules"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("./css_highlight_rules").CssHighlightRules,f=a("./javascript_highlight_rules").JavaScriptHighlightRules,g=a("./xml_util"),h=a("./text_highlight_rules").TextHighlightRules,i=function(){this.$rules={start:[{token:"text",merge:!0,regex:"<\\!\\[CDATA\\[",next:"cdata"},{token:"xml_pe",regex:"<\\?.*?\\?>"},{token:"comment",merge:!0,regex:"<\\!--",next:"comment"},{token:"xml_pe",regex:"<\\!.*?>"},{token:"meta.tag",regex:"<(?=s*script\\b)",next:"script"},{token:"meta.tag",regex:"<(?=s*style\\b)",next:"style"},{token:"meta.tag",regex:"<\\/?",next:"tag"},{token:"text",regex:"\\s+"},{token:"constant.character.entity",regex:"(?:&#[0-9]+;)|(?:&#x[0-9a-fA-F]+;)|(?:&[a-zA-Z0-9_:\\.-]+;)"},{token:"text",regex:"[^<]+"}],cdata:[{token:"text",regex:"\\]\\]>",next:"start"},{token:"text",merge:!0,regex:"\\s+"},{token:"text",merge:!0,regex:".+"}],comment:[{token:"comment",regex:".*?-->",next:"start"},{token:"comment",merge:!0,regex:".+"}]},g.tag(this.$rules,"tag","start"),g.tag(this.$rules,"style","css-start"),g.tag(this.$rules,"script","js-start"),this.embedRules(f,"js-",[{token:"comment",regex:"\\/\\/.*(?=<\\/script>)",next:"tag"},{token:"meta.tag",regex:"<\\/(?=script)",next:"tag"}]),this.embedRules(e,"css-",[{token:"meta.tag",regex:"<\\/(?=style)",next:"tag"}])};d.inherits(i,h),b.HtmlHighlightRules=i}),define("ace/mode/folding/html",["require","exports","module","ace/lib/oop","ace/mode/folding/mixed","ace/mode/folding/xml","ace/mode/folding/cstyle"],function(a,b,c){"use strict";var d=a("../../lib/oop"),e=a("./mixed").FoldMode,f=a("./xml").FoldMode,g=a("./cstyle").FoldMode,h=b.FoldMode=function(){e.call(this,new f({area:1,base:1,br:1,col:1,command:1,embed:1,hr:1,img:1,input:1,keygen:1,link:1,meta:1,param:1,source:1,track:1,wbr:1,li:1,dt:1,dd:1,p:1,rt:1,rp:1,optgroup:1,option:1,colgroup:1,td:1,th:1}),{"js-":new g,"css-":new g})};d.inherits(h,e)}),define("ace/mode/folding/mixed",["require","exports","module","ace/lib/oop","ace/mode/folding/fold_mode"],function(a,b,c){"use strict";var d=a("../../lib/oop"),e=a("./fold_mode").FoldMode,f=b.FoldMode=function(a,b){this.defaultMode=a,this.subModes=b};d.inherits(f,e),function(){this.$getMode=function(a){for(var b in this.subModes)if(a.indexOf(b)===0)return this.subModes[b];return null},this.$tryMode=function(a,b,c,d){var e=this.$getMode(a);return e?e.getFoldWidget(b,c,d):""},this.getFoldWidget=function(a,b,c){return this.$tryMode(a.getState(c-1),a,b,c)||this.$tryMode(a.getState(c),a,b,c)||this.defaultMode.getFoldWidget(a,b,c)},this.getFoldWidgetRange=function(a,b,c){var d=this.$getMode(a.getState(c-1));if(!d||!d.getFoldWidget(a,b,c))d=this.$getMode(a.getState(c));if(!d||!d.getFoldWidget(a,b,c))d=this.defaultMode;return d.getFoldWidgetRange(a,b,c)}}.call(f.prototype)}),define("ace/mode/markdown_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules","ace/mode/javascript_highlight_rules","ace/mode/xml_highlight_rules","ace/mode/html_highlight_rules","ace/mode/css_highlight_rules"],function(a,b,c){function j(a,b){return{token:"support.function",regex:"^```"+a+"\\s*$",next:b+"start"}}"use strict";var d=a("../lib/oop"),e=a("./text_highlight_rules").TextHighlightRules,f=a("./javascript_highlight_rules").JavaScriptHighlightRules,g=a("./xml_highlight_rules").XmlHighlightRules,h=a("./html_highlight_rules").HtmlHighlightRules,i=a("./css_highlight_rules").CssHighlightRules,k=function(){this.$rules={start:[{token:"empty_line",regex:"^$"},{token:["support.function","support.function","support.function"],regex:"(`+)([^\\r]*?[^`])(\\1)"},{token:"support.function",regex:"^[ ]{4}.+"},{token:"markup.heading.1",regex:"^=+(?=\\s*$)"},{token:"markup.heading.1",regex:"^\\-+(?=\\s*$)"},{token:function(a){return"markup.heading."+a.length},regex:"^#{1,6}"},j("javascript","js-"),j("xml","xml-"),j("html","html-"),j("css","css-"),{token:"support.function",regex:"^```[a-zA-Z]+\\s*$",next:"githubblock"},{token:"string",regex:"^>[ ].+$",next:"blockquote"},{token:["text","constant","text","url","string","text"],regex:'^([ ]{0,3}\\[)([^\\]]+)(\\]:\\s*)([^ ]+)(\\s*(?:["][^"]+["])?(\\s*))$'},{token:["text","string","text","constant","text"],regex:"(\\[)((?:[[^\\]]*\\]|[^\\[\\]])*)(\\][ ]?(?:\\n[ ]*)?\\[)(.*?)(\\])"},{token:["text","string","text","markup.underline","string","text"],regex:'(\\[)(\\[[^\\]]*\\]|[^\\[\\]]*)(\\]\\([ \\t]*)(<?(?:(?:[^\\(]*?\\([^\\)]*?\\)\\S*?)|(?:.*?))>?)((?:[ 	]*"(?:.*?)"[ \\t]*)?)(\\))'},{token:"constant",regex:"^[ ]{0,2}(?:[ ]?\\*[ ]?){3,}\\s*$"},{token:"constant",regex:"^[ ]{0,2}(?:[ ]?\\-[ ]?){3,}\\s*$"},{token:"constant",regex:"^[ ]{0,2}(?:[ ]?\\_[ ]?){3,}\\s*$"},{token:"markup.list",regex:"^\\s{0,3}(?:[*+-]|\\d+\\.)\\s+",next:"listblock"},{token:["string","string","string"],regex:"([*]{2}|[_]{2}(?=\\S))([^\\r]*?\\S[*_]*)(\\1)"},{token:["string","string","string"],regex:"([*]|[_](?=\\S))([^\\r]*?\\S[*_]*)(\\1)"},{token:["text","url","text"],regex:"(<)((?:https?|ftp|dict):[^'\">\\s]+|(?:mailto:)?[-.\\w]+\\@[-a-z0-9]+(?:\\.[-a-z0-9]+)*\\.[a-z]+)(>)"},{token:"text",regex:"[^\\*_%$`\\[#<>]+"}],listblock:[{token:"empty_line",regex:"^$",next:"start"},{token:"markup.list",regex:".+"}],blockquote:[{token:"empty_line",regex:"^\\s*$",next:"start"},{token:"string",regex:".+"}],githubblock:[{token:"support.function",regex:"^```",next:"start"},{token:"support.function",regex:".+"}]},this.embedRules(f,"js-",[{token:"support.function",regex:"^```",next:"start"}]),this.embedRules(h,"html-",[{token:"support.function",regex:"^```",next:"start"}]),this.embedRules(i,"css-",[{token:"support.function",regex:"^```",next:"start"}]),this.embedRules(g,"xml-",[{token:"support.function",regex:"^```",next:"start"}])};d.inherits(k,e),b.MarkdownHighlightRules=k})
\ No newline at end of file
diff --git a/apps/files_texteditor/js/aceeditor/mode-ocaml-uncompressed.js b/apps/files_texteditor/js/aceeditor/mode-ocaml-uncompressed.js
old mode 100755
new mode 100644
index b91107dea600941b07f7fd54098acd7e43cae71e..c268a4f8caeb2310c22a9d9a700502ce685ae37e
--- a/apps/files_texteditor/js/aceeditor/mode-ocaml-uncompressed.js
+++ b/apps/files_texteditor/js/aceeditor/mode-ocaml-uncompressed.js
@@ -537,13 +537,3 @@ var MatchingBraceOutdent = function() {};
 
 exports.MatchingBraceOutdent = MatchingBraceOutdent;
 });
-;
-            (function() {
-                window.require(["ace/ace"], function(a) {
-                    if (!window.ace)
-                        window.ace = {};
-                    for (var key in a) if (a.hasOwnProperty(key))
-                        ace[key] = a[key];
-                });
-            })();
-        
\ No newline at end of file
diff --git a/apps/files_texteditor/js/aceeditor/mode-ocaml.js b/apps/files_texteditor/js/aceeditor/mode-ocaml.js
index 0e3e15f225cc8c653848e1d1ea3dbc361b06ff85..622f817e30908da9aa032b1dd15c1bf14283dcce 100644
--- a/apps/files_texteditor/js/aceeditor/mode-ocaml.js
+++ b/apps/files_texteditor/js/aceeditor/mode-ocaml.js
@@ -1 +1 @@
-define("ace/mode/ocaml",["require","exports","module","ace/lib/oop","ace/mode/text","ace/tokenizer","ace/mode/ocaml_highlight_rules","ace/mode/matching_brace_outdent","ace/range"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("./text").Mode,f=a("../tokenizer").Tokenizer,g=a("./ocaml_highlight_rules").OcamlHighlightRules,h=a("./matching_brace_outdent").MatchingBraceOutdent,i=a("../range").Range,j=function(){this.$tokenizer=new f((new g).getRules()),this.$outdent=new h};d.inherits(j,e);var k=/(?:[({[=:]|[-=]>|\b(?:else|try|with))\s*$/;((function(){this.toggleCommentLines=function(a,b,c,d){var e,f,g=!0,h=/^\s*\(\*(.*)\*\)/;for(e=c;e<=d;e++)if(!h.test(b.getLine(e))){g=!1;break}var j=new i(0,0,0,0);for(e=c;e<=d;e++)f=b.getLine(e),j.start.row=e,j.end.row=e,j.end.column=f.length,b.replace(j,g?f.match(h)[1]:"(*"+f+"*)")},this.getNextLineIndent=function(a,b,c){var d=this.$getIndent(b),e=this.$tokenizer.getLineTokens(b,a).tokens;return(!e.length||e[e.length-1].type!=="comment")&&a==="start"&&k.test(b)&&(d+=c),d},this.checkOutdent=function(a,b,c){return this.$outdent.checkOutdent(b,c)},this.autoOutdent=function(a,b,c){this.$outdent.autoOutdent(b,c)}})).call(j.prototype),b.Mode=j}),define("ace/mode/ocaml_highlight_rules",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/mode/text_highlight_rules"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("../lib/lang"),f=a("./text_highlight_rules").TextHighlightRules,g=function(){var a=e.arrayToMap("and|as|assert|begin|class|constraint|do|done|downto|else|end|exception|external|for|fun|function|functor|if|in|include|inherit|initializer|lazy|let|match|method|module|mutable|new|object|of|open|or|private|rec|sig|struct|then|to|try|type|val|virtual|when|while|with".split("|")),b=e.arrayToMap("true|false".split("|")),c=e.arrayToMap("abs|abs_big_int|abs_float|abs_num|abstract_tag|accept|access|acos|add|add_available_units|add_big_int|add_buffer|add_channel|add_char|add_initializer|add_int_big_int|add_interfaces|add_num|add_string|add_substitute|add_substring|alarm|allocated_bytes|allow_only|allow_unsafe_modules|always|append|appname_get|appname_set|approx_num_exp|approx_num_fix|arg|argv|arith_status|array|array1_of_genarray|array2_of_genarray|array3_of_genarray|asin|asr|assoc|assq|at_exit|atan|atan2|auto_synchronize|background|basename|beginning_of_input|big_int_of_int|big_int_of_num|big_int_of_string|bind|bind_class|bind_tag|bits|bits_of_float|black|blit|blit_image|blue|bool|bool_of_string|bounded_full_split|bounded_split|bounded_split_delim|bprintf|break|broadcast|bscanf|button_down|c_layout|capitalize|cardinal|cardinal|catch|catch_break|ceil|ceiling_num|channel|char|char_of_int|chdir|check|check_suffix|chmod|choose|chop_extension|chop_suffix|chown|chown|chr|chroot|classify_float|clear|clear_available_units|clear_close_on_exec|clear_graph|clear_nonblock|clear_parser|close|close|closeTk|close_box|close_graph|close_in|close_in_noerr|close_out|close_out_noerr|close_process|close_process|close_process_full|close_process_in|close_process_out|close_subwindow|close_tag|close_tbox|closedir|closedir|closure_tag|code|combine|combine|combine|command|compact|compare|compare_big_int|compare_num|complex32|complex64|concat|conj|connect|contains|contains_from|contents|copy|cos|cosh|count|count|counters|create|create_alarm|create_image|create_matrix|create_matrix|create_matrix|create_object|create_object_and_run_initializers|create_object_opt|create_process|create_process|create_process_env|create_process_env|create_table|current|current_dir_name|current_point|current_x|current_y|curveto|custom_tag|cyan|data_size|decr|decr_num|default_available_units|delay|delete_alarm|descr_of_in_channel|descr_of_out_channel|destroy|diff|dim|dim1|dim2|dim3|dims|dirname|display_mode|div|div_big_int|div_num|double_array_tag|double_tag|draw_arc|draw_char|draw_circle|draw_ellipse|draw_image|draw_poly|draw_poly_line|draw_rect|draw_segments|draw_string|dummy_pos|dummy_table|dump_image|dup|dup2|elements|empty|end_of_input|environment|eprintf|epsilon_float|eq_big_int|eq_num|equal|err_formatter|error_message|escaped|establish_server|executable_name|execv|execve|execvp|execvpe|exists|exists2|exit|exp|failwith|fast_sort|fchmod|fchown|field|file|file_exists|fill|fill_arc|fill_circle|fill_ellipse|fill_poly|fill_rect|filter|final_tag|finalise|find|find_all|first_chars|firstkey|flatten|float|float32|float64|float_of_big_int|float_of_bits|float_of_int|float_of_num|float_of_string|floor|floor_num|flush|flush_all|flush_input|flush_str_formatter|fold|fold_left|fold_left2|fold_right|fold_right2|for_all|for_all2|force|force_newline|force_val|foreground|fork|format_of_string|formatter_of_buffer|formatter_of_out_channel|fortran_layout|forward_tag|fprintf|frexp|from|from_channel|from_file|from_file_bin|from_function|from_string|fscanf|fst|fstat|ftruncate|full_init|full_major|full_split|gcd_big_int|ge_big_int|ge_num|genarray_of_array1|genarray_of_array2|genarray_of_array3|get|get_all_formatter_output_functions|get_approx_printing|get_copy|get_ellipsis_text|get_error_when_null_denominator|get_floating_precision|get_formatter_output_functions|get_formatter_tag_functions|get_image|get_margin|get_mark_tags|get_max_boxes|get_max_indent|get_method|get_method_label|get_normalize_ratio|get_normalize_ratio_when_printing|get_print_tags|get_state|get_variable|getcwd|getegid|getegid|getenv|getenv|getenv|geteuid|geteuid|getgid|getgid|getgrgid|getgrgid|getgrnam|getgrnam|getgroups|gethostbyaddr|gethostbyname|gethostname|getitimer|getlogin|getpeername|getpid|getppid|getprotobyname|getprotobynumber|getpwnam|getpwuid|getservbyname|getservbyport|getsockname|getsockopt|getsockopt_float|getsockopt_int|getsockopt_optint|gettimeofday|getuid|global_replace|global_substitute|gmtime|green|grid|group_beginning|group_end|gt_big_int|gt_num|guard|handle_unix_error|hash|hash_param|hd|header_size|i|id|ignore|in_channel_length|in_channel_of_descr|incr|incr_num|index|index_from|inet_addr_any|inet_addr_of_string|infinity|infix_tag|init|init_class|input|input_binary_int|input_byte|input_char|input_line|input_value|int|int16_signed|int16_unsigned|int32|int64|int8_signed|int8_unsigned|int_of_big_int|int_of_char|int_of_float|int_of_num|int_of_string|integer_num|inter|interactive|inv|invalid_arg|is_block|is_empty|is_implicit|is_int|is_int_big_int|is_integer_num|is_relative|iter|iter2|iteri|join|junk|key_pressed|kill|kind|kprintf|kscanf|land|last_chars|layout|lazy_from_fun|lazy_from_val|lazy_is_val|lazy_tag|ldexp|le_big_int|le_num|length|lexeme|lexeme_char|lexeme_end|lexeme_end_p|lexeme_start|lexeme_start_p|lineto|link|list|listen|lnot|loadfile|loadfile_private|localtime|lock|lockf|log|log10|logand|lognot|logor|logxor|lor|lower_window|lowercase|lseek|lsl|lsr|lstat|lt_big_int|lt_num|lxor|magenta|magic|mainLoop|major|major_slice|make|make_formatter|make_image|make_lexer|make_matrix|make_self_init|map|map2|map_file|mapi|marshal|match_beginning|match_end|matched_group|matched_string|max|max_array_length|max_big_int|max_elt|max_float|max_int|max_num|max_string_length|mem|mem_assoc|mem_assq|memq|merge|min|min_big_int|min_elt|min_float|min_int|min_num|minor|minus_big_int|minus_num|minus_one|mkdir|mkfifo|mktime|mod|mod_big_int|mod_float|mod_num|modf|mouse_pos|moveto|mul|mult_big_int|mult_int_big_int|mult_num|nan|narrow|nat_of_num|nativeint|neg|neg_infinity|new_block|new_channel|new_method|new_variable|next|nextkey|nice|nice|no_scan_tag|norm|norm2|not|npeek|nth|nth_dim|num_digits_big_int|num_dims|num_of_big_int|num_of_int|num_of_nat|num_of_ratio|num_of_string|O|obj|object_tag|ocaml_version|of_array|of_channel|of_float|of_int|of_int32|of_list|of_nativeint|of_string|one|openTk|open_box|open_connection|open_graph|open_hbox|open_hovbox|open_hvbox|open_in|open_in_bin|open_in_gen|open_out|open_out_bin|open_out_gen|open_process|open_process_full|open_process_in|open_process_out|open_subwindow|open_tag|open_tbox|open_temp_file|open_vbox|opendbm|opendir|openfile|or|os_type|out_channel_length|out_channel_of_descr|output|output_binary_int|output_buffer|output_byte|output_char|output_string|output_value|over_max_boxes|pack|params|parent_dir_name|parse|parse_argv|partition|pause|peek|pipe|pixels|place|plot|plots|point_color|polar|poll|pop|pos_in|pos_out|pow|power_big_int_positive_big_int|power_big_int_positive_int|power_int_positive_big_int|power_int_positive_int|power_num|pp_close_box|pp_close_tag|pp_close_tbox|pp_force_newline|pp_get_all_formatter_output_functions|pp_get_ellipsis_text|pp_get_formatter_output_functions|pp_get_formatter_tag_functions|pp_get_margin|pp_get_mark_tags|pp_get_max_boxes|pp_get_max_indent|pp_get_print_tags|pp_open_box|pp_open_hbox|pp_open_hovbox|pp_open_hvbox|pp_open_tag|pp_open_tbox|pp_open_vbox|pp_over_max_boxes|pp_print_as|pp_print_bool|pp_print_break|pp_print_char|pp_print_cut|pp_print_float|pp_print_flush|pp_print_if_newline|pp_print_int|pp_print_newline|pp_print_space|pp_print_string|pp_print_tab|pp_print_tbreak|pp_set_all_formatter_output_functions|pp_set_ellipsis_text|pp_set_formatter_out_channel|pp_set_formatter_output_functions|pp_set_formatter_tag_functions|pp_set_margin|pp_set_mark_tags|pp_set_max_boxes|pp_set_max_indent|pp_set_print_tags|pp_set_tab|pp_set_tags|pred|pred_big_int|pred_num|prerr_char|prerr_endline|prerr_float|prerr_int|prerr_newline|prerr_string|print|print_as|print_bool|print_break|print_char|print_cut|print_endline|print_float|print_flush|print_if_newline|print_int|print_newline|print_space|print_stat|print_string|print_tab|print_tbreak|printf|prohibit|public_method_label|push|putenv|quo_num|quomod_big_int|quote|raise|raise_window|ratio_of_num|rcontains_from|read|read_float|read_int|read_key|read_line|readdir|readdir|readlink|really_input|receive|recv|recvfrom|red|ref|regexp|regexp_case_fold|regexp_string|regexp_string_case_fold|register|register_exception|rem|remember_mode|remove|remove_assoc|remove_assq|rename|replace|replace_first|replace_matched|repr|reset|reshape|reshape_1|reshape_2|reshape_3|rev|rev_append|rev_map|rev_map2|rewinddir|rgb|rhs_end|rhs_end_pos|rhs_start|rhs_start_pos|rindex|rindex_from|rlineto|rmdir|rmoveto|round_num|run_initializers|run_initializers_opt|scanf|search_backward|search_forward|seek_in|seek_out|select|self|self_init|send|sendto|set|set_all_formatter_output_functions|set_approx_printing|set_binary_mode_in|set_binary_mode_out|set_close_on_exec|set_close_on_exec|set_color|set_ellipsis_text|set_error_when_null_denominator|set_field|set_floating_precision|set_font|set_formatter_out_channel|set_formatter_output_functions|set_formatter_tag_functions|set_line_width|set_margin|set_mark_tags|set_max_boxes|set_max_indent|set_method|set_nonblock|set_nonblock|set_normalize_ratio|set_normalize_ratio_when_printing|set_print_tags|set_signal|set_state|set_tab|set_tag|set_tags|set_text_size|set_window_title|setgid|setgid|setitimer|setitimer|setsid|setsid|setsockopt|setsockopt|setsockopt_float|setsockopt_float|setsockopt_int|setsockopt_int|setsockopt_optint|setsockopt_optint|setuid|setuid|shift_left|shift_left|shift_left|shift_right|shift_right|shift_right|shift_right_logical|shift_right_logical|shift_right_logical|show_buckets|shutdown|shutdown|shutdown_connection|shutdown_connection|sigabrt|sigalrm|sigchld|sigcont|sigfpe|sighup|sigill|sigint|sigkill|sign_big_int|sign_num|signal|signal|sigpending|sigpending|sigpipe|sigprocmask|sigprocmask|sigprof|sigquit|sigsegv|sigstop|sigsuspend|sigsuspend|sigterm|sigtstp|sigttin|sigttou|sigusr1|sigusr2|sigvtalrm|sin|singleton|sinh|size|size|size_x|size_y|sleep|sleep|sleep|slice_left|slice_left|slice_left_1|slice_left_2|slice_right|slice_right|slice_right_1|slice_right_2|snd|socket|socket|socket|socketpair|socketpair|sort|sound|split|split_delim|sprintf|sprintf|sqrt|sqrt|sqrt_big_int|square_big_int|square_num|sscanf|stable_sort|stable_sort|stable_sort|stable_sort|stable_sort|stable_sort|stat|stat|stat|stat|stat|stats|stats|std_formatter|stdbuf|stderr|stderr|stderr|stdib|stdin|stdin|stdin|stdout|stdout|stdout|str_formatter|string|string_after|string_before|string_match|string_of_big_int|string_of_bool|string_of_float|string_of_format|string_of_inet_addr|string_of_inet_addr|string_of_int|string_of_num|string_partial_match|string_tag|sub|sub|sub_big_int|sub_left|sub_num|sub_right|subset|subset|substitute_first|substring|succ|succ|succ|succ|succ_big_int|succ_num|symbol_end|symbol_end_pos|symbol_start|symbol_start_pos|symlink|symlink|sync|synchronize|system|system|system|tag|take|tan|tanh|tcdrain|tcdrain|tcflow|tcflow|tcflush|tcflush|tcgetattr|tcgetattr|tcsendbreak|tcsendbreak|tcsetattr|tcsetattr|temp_file|text_size|time|time|time|timed_read|timed_write|times|times|tl|tl|tl|to_buffer|to_channel|to_float|to_hex|to_int|to_int32|to_list|to_list|to_list|to_nativeint|to_string|to_string|to_string|to_string|to_string|top|top|total_size|transfer|transp|truncate|truncate|truncate|truncate|truncate|truncate|try_lock|umask|umask|uncapitalize|uncapitalize|uncapitalize|union|union|unit_big_int|unlink|unlink|unlock|unmarshal|unsafe_blit|unsafe_fill|unsafe_get|unsafe_get|unsafe_set|unsafe_set|update|uppercase|uppercase|uppercase|uppercase|usage|utimes|utimes|wait|wait|wait|wait|wait_next_event|wait_pid|wait_read|wait_signal|wait_timed_read|wait_timed_write|wait_write|waitpid|white|widen|window_id|word_size|wrap|wrap_abort|write|yellow|yield|zero|zero_big_int|Arg|Arith_status|Array|Array1|Array2|Array3|ArrayLabels|Big_int|Bigarray|Buffer|Callback|CamlinternalOO|Char|Complex|Condition|Dbm|Digest|Dynlink|Event|Filename|Format|Gc|Genarray|Genlex|Graphics|GraphicsX11|Hashtbl|Int32|Int64|LargeFile|Lazy|Lexing|List|ListLabels|Make|Map|Marshal|MoreLabels|Mutex|Nativeint|Num|Obj|Oo|Parsing|Pervasives|Printexc|Printf|Queue|Random|Scanf|Scanning|Set|Sort|Stack|State|StdLabels|Str|Stream|String|StringLabels|Sys|Thread|ThreadUnix|Tk|Unix|UnixLabels|Weak".split("|")),d="(?:(?:[1-9]\\d*)|(?:0))",f="(?:0[oO]?[0-7]+)",g="(?:0[xX][\\dA-Fa-f]+)",h="(?:0[bB][01]+)",i="(?:"+d+"|"+f+"|"+g+"|"+h+")",j="(?:[eE][+-]?\\d+)",k="(?:\\.\\d+)",l="(?:\\d+)",m="(?:(?:"+l+"?"+k+")|(?:"+l+"\\.))",n="(?:(?:"+m+"|"+l+")"+j+")",o="(?:"+n+"|"+m+")";this.$rules={start:[{token:"comment",regex:"\\(\\*.*?\\*\\)\\s*?$"},{token:"comment",merge:!0,regex:"\\(\\*.*",next:"comment"},{token:"string",regex:'["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'},{token:"string",regex:"'.'"},{token:"string",merge:!0,regex:'"',next:"qstring"},{token:"constant.numeric",regex:"(?:"+o+"|\\d+)[jJ]\\b"},{token:"constant.numeric",regex:o},{token:"constant.numeric",regex:i+"\\b"},{token:function(d){return a.hasOwnProperty(d)?"keyword":b.hasOwnProperty(d)?"constant.language":c.hasOwnProperty(d)?"support.function":"identifier"},regex:"[a-zA-Z_$][a-zA-Z0-9_$]*\\b"},{token:"keyword.operator",regex:"\\+\\.|\\-\\.|\\*\\.|\\/\\.|#|;;|\\+|\\-|\\*|\\*\\*\\/|\\/\\/|%|<<|>>|&|\\||\\^|~|<|>|<=|=>|==|!=|<>|<-|="},{token:"paren.lparen",regex:"[[({]"},{token:"paren.rparen",regex:"[\\])}]"},{token:"text",regex:"\\s+"}],comment:[{token:"comment",regex:".*?\\*\\)",next:"start"},{token:"comment",merge:!0,regex:".+"}],qstring:[{token:"string",regex:'"',next:"start"},{token:"string",merge:!0,regex:".+"}]}};d.inherits(g,f),b.OcamlHighlightRules=g}),define("ace/mode/matching_brace_outdent",["require","exports","module","ace/range"],function(a,b,c){"use strict";var d=a("../range").Range,e=function(){};((function(){this.checkOutdent=function(a,b){return/^\s+$/.test(a)?/^\s*\}/.test(b):!1},this.autoOutdent=function(a,b){var c=a.getLine(b),e=c.match(/^(\s*\})/);if(!e)return 0;var f=e[1].length,g=a.findMatchingBracket({row:b,column:f});if(!g||g.row==b)return 0;var h=this.$getIndent(a.getLine(g.row));a.replace(new d(b,0,b,f-1),h)},this.$getIndent=function(a){var b=a.match(/^(\s+)/);return b?b[1]:""}})).call(e.prototype),b.MatchingBraceOutdent=e}),function(){window.require(["ace/ace"],function(a){window.ace||(window.ace={});for(var b in a)a.hasOwnProperty(b)&&(ace[b]=a[b])})}()
\ No newline at end of file
+define("ace/mode/ocaml",["require","exports","module","ace/lib/oop","ace/mode/text","ace/tokenizer","ace/mode/ocaml_highlight_rules","ace/mode/matching_brace_outdent","ace/range"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("./text").Mode,f=a("../tokenizer").Tokenizer,g=a("./ocaml_highlight_rules").OcamlHighlightRules,h=a("./matching_brace_outdent").MatchingBraceOutdent,i=a("../range").Range,j=function(){this.$tokenizer=new f((new g).getRules()),this.$outdent=new h};d.inherits(j,e);var k=/(?:[({[=:]|[-=]>|\b(?:else|try|with))\s*$/;(function(){this.toggleCommentLines=function(a,b,c,d){var e,f,g=!0,h=/^\s*\(\*(.*)\*\)/;for(e=c;e<=d;e++)if(!h.test(b.getLine(e))){g=!1;break}var j=new i(0,0,0,0);for(e=c;e<=d;e++)f=b.getLine(e),j.start.row=e,j.end.row=e,j.end.column=f.length,b.replace(j,g?f.match(h)[1]:"(*"+f+"*)")},this.getNextLineIndent=function(a,b,c){var d=this.$getIndent(b),e=this.$tokenizer.getLineTokens(b,a).tokens;return(!e.length||e[e.length-1].type!=="comment")&&a==="start"&&k.test(b)&&(d+=c),d},this.checkOutdent=function(a,b,c){return this.$outdent.checkOutdent(b,c)},this.autoOutdent=function(a,b,c){this.$outdent.autoOutdent(b,c)}}).call(j.prototype),b.Mode=j}),define("ace/mode/ocaml_highlight_rules",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/mode/text_highlight_rules"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("../lib/lang"),f=a("./text_highlight_rules").TextHighlightRules,g=function(){var a=e.arrayToMap("and|as|assert|begin|class|constraint|do|done|downto|else|end|exception|external|for|fun|function|functor|if|in|include|inherit|initializer|lazy|let|match|method|module|mutable|new|object|of|open|or|private|rec|sig|struct|then|to|try|type|val|virtual|when|while|with".split("|")),b=e.arrayToMap("true|false".split("|")),c=e.arrayToMap("abs|abs_big_int|abs_float|abs_num|abstract_tag|accept|access|acos|add|add_available_units|add_big_int|add_buffer|add_channel|add_char|add_initializer|add_int_big_int|add_interfaces|add_num|add_string|add_substitute|add_substring|alarm|allocated_bytes|allow_only|allow_unsafe_modules|always|append|appname_get|appname_set|approx_num_exp|approx_num_fix|arg|argv|arith_status|array|array1_of_genarray|array2_of_genarray|array3_of_genarray|asin|asr|assoc|assq|at_exit|atan|atan2|auto_synchronize|background|basename|beginning_of_input|big_int_of_int|big_int_of_num|big_int_of_string|bind|bind_class|bind_tag|bits|bits_of_float|black|blit|blit_image|blue|bool|bool_of_string|bounded_full_split|bounded_split|bounded_split_delim|bprintf|break|broadcast|bscanf|button_down|c_layout|capitalize|cardinal|cardinal|catch|catch_break|ceil|ceiling_num|channel|char|char_of_int|chdir|check|check_suffix|chmod|choose|chop_extension|chop_suffix|chown|chown|chr|chroot|classify_float|clear|clear_available_units|clear_close_on_exec|clear_graph|clear_nonblock|clear_parser|close|close|closeTk|close_box|close_graph|close_in|close_in_noerr|close_out|close_out_noerr|close_process|close_process|close_process_full|close_process_in|close_process_out|close_subwindow|close_tag|close_tbox|closedir|closedir|closure_tag|code|combine|combine|combine|command|compact|compare|compare_big_int|compare_num|complex32|complex64|concat|conj|connect|contains|contains_from|contents|copy|cos|cosh|count|count|counters|create|create_alarm|create_image|create_matrix|create_matrix|create_matrix|create_object|create_object_and_run_initializers|create_object_opt|create_process|create_process|create_process_env|create_process_env|create_table|current|current_dir_name|current_point|current_x|current_y|curveto|custom_tag|cyan|data_size|decr|decr_num|default_available_units|delay|delete_alarm|descr_of_in_channel|descr_of_out_channel|destroy|diff|dim|dim1|dim2|dim3|dims|dirname|display_mode|div|div_big_int|div_num|double_array_tag|double_tag|draw_arc|draw_char|draw_circle|draw_ellipse|draw_image|draw_poly|draw_poly_line|draw_rect|draw_segments|draw_string|dummy_pos|dummy_table|dump_image|dup|dup2|elements|empty|end_of_input|environment|eprintf|epsilon_float|eq_big_int|eq_num|equal|err_formatter|error_message|escaped|establish_server|executable_name|execv|execve|execvp|execvpe|exists|exists2|exit|exp|failwith|fast_sort|fchmod|fchown|field|file|file_exists|fill|fill_arc|fill_circle|fill_ellipse|fill_poly|fill_rect|filter|final_tag|finalise|find|find_all|first_chars|firstkey|flatten|float|float32|float64|float_of_big_int|float_of_bits|float_of_int|float_of_num|float_of_string|floor|floor_num|flush|flush_all|flush_input|flush_str_formatter|fold|fold_left|fold_left2|fold_right|fold_right2|for_all|for_all2|force|force_newline|force_val|foreground|fork|format_of_string|formatter_of_buffer|formatter_of_out_channel|fortran_layout|forward_tag|fprintf|frexp|from|from_channel|from_file|from_file_bin|from_function|from_string|fscanf|fst|fstat|ftruncate|full_init|full_major|full_split|gcd_big_int|ge_big_int|ge_num|genarray_of_array1|genarray_of_array2|genarray_of_array3|get|get_all_formatter_output_functions|get_approx_printing|get_copy|get_ellipsis_text|get_error_when_null_denominator|get_floating_precision|get_formatter_output_functions|get_formatter_tag_functions|get_image|get_margin|get_mark_tags|get_max_boxes|get_max_indent|get_method|get_method_label|get_normalize_ratio|get_normalize_ratio_when_printing|get_print_tags|get_state|get_variable|getcwd|getegid|getegid|getenv|getenv|getenv|geteuid|geteuid|getgid|getgid|getgrgid|getgrgid|getgrnam|getgrnam|getgroups|gethostbyaddr|gethostbyname|gethostname|getitimer|getlogin|getpeername|getpid|getppid|getprotobyname|getprotobynumber|getpwnam|getpwuid|getservbyname|getservbyport|getsockname|getsockopt|getsockopt_float|getsockopt_int|getsockopt_optint|gettimeofday|getuid|global_replace|global_substitute|gmtime|green|grid|group_beginning|group_end|gt_big_int|gt_num|guard|handle_unix_error|hash|hash_param|hd|header_size|i|id|ignore|in_channel_length|in_channel_of_descr|incr|incr_num|index|index_from|inet_addr_any|inet_addr_of_string|infinity|infix_tag|init|init_class|input|input_binary_int|input_byte|input_char|input_line|input_value|int|int16_signed|int16_unsigned|int32|int64|int8_signed|int8_unsigned|int_of_big_int|int_of_char|int_of_float|int_of_num|int_of_string|integer_num|inter|interactive|inv|invalid_arg|is_block|is_empty|is_implicit|is_int|is_int_big_int|is_integer_num|is_relative|iter|iter2|iteri|join|junk|key_pressed|kill|kind|kprintf|kscanf|land|last_chars|layout|lazy_from_fun|lazy_from_val|lazy_is_val|lazy_tag|ldexp|le_big_int|le_num|length|lexeme|lexeme_char|lexeme_end|lexeme_end_p|lexeme_start|lexeme_start_p|lineto|link|list|listen|lnot|loadfile|loadfile_private|localtime|lock|lockf|log|log10|logand|lognot|logor|logxor|lor|lower_window|lowercase|lseek|lsl|lsr|lstat|lt_big_int|lt_num|lxor|magenta|magic|mainLoop|major|major_slice|make|make_formatter|make_image|make_lexer|make_matrix|make_self_init|map|map2|map_file|mapi|marshal|match_beginning|match_end|matched_group|matched_string|max|max_array_length|max_big_int|max_elt|max_float|max_int|max_num|max_string_length|mem|mem_assoc|mem_assq|memq|merge|min|min_big_int|min_elt|min_float|min_int|min_num|minor|minus_big_int|minus_num|minus_one|mkdir|mkfifo|mktime|mod|mod_big_int|mod_float|mod_num|modf|mouse_pos|moveto|mul|mult_big_int|mult_int_big_int|mult_num|nan|narrow|nat_of_num|nativeint|neg|neg_infinity|new_block|new_channel|new_method|new_variable|next|nextkey|nice|nice|no_scan_tag|norm|norm2|not|npeek|nth|nth_dim|num_digits_big_int|num_dims|num_of_big_int|num_of_int|num_of_nat|num_of_ratio|num_of_string|O|obj|object_tag|ocaml_version|of_array|of_channel|of_float|of_int|of_int32|of_list|of_nativeint|of_string|one|openTk|open_box|open_connection|open_graph|open_hbox|open_hovbox|open_hvbox|open_in|open_in_bin|open_in_gen|open_out|open_out_bin|open_out_gen|open_process|open_process_full|open_process_in|open_process_out|open_subwindow|open_tag|open_tbox|open_temp_file|open_vbox|opendbm|opendir|openfile|or|os_type|out_channel_length|out_channel_of_descr|output|output_binary_int|output_buffer|output_byte|output_char|output_string|output_value|over_max_boxes|pack|params|parent_dir_name|parse|parse_argv|partition|pause|peek|pipe|pixels|place|plot|plots|point_color|polar|poll|pop|pos_in|pos_out|pow|power_big_int_positive_big_int|power_big_int_positive_int|power_int_positive_big_int|power_int_positive_int|power_num|pp_close_box|pp_close_tag|pp_close_tbox|pp_force_newline|pp_get_all_formatter_output_functions|pp_get_ellipsis_text|pp_get_formatter_output_functions|pp_get_formatter_tag_functions|pp_get_margin|pp_get_mark_tags|pp_get_max_boxes|pp_get_max_indent|pp_get_print_tags|pp_open_box|pp_open_hbox|pp_open_hovbox|pp_open_hvbox|pp_open_tag|pp_open_tbox|pp_open_vbox|pp_over_max_boxes|pp_print_as|pp_print_bool|pp_print_break|pp_print_char|pp_print_cut|pp_print_float|pp_print_flush|pp_print_if_newline|pp_print_int|pp_print_newline|pp_print_space|pp_print_string|pp_print_tab|pp_print_tbreak|pp_set_all_formatter_output_functions|pp_set_ellipsis_text|pp_set_formatter_out_channel|pp_set_formatter_output_functions|pp_set_formatter_tag_functions|pp_set_margin|pp_set_mark_tags|pp_set_max_boxes|pp_set_max_indent|pp_set_print_tags|pp_set_tab|pp_set_tags|pred|pred_big_int|pred_num|prerr_char|prerr_endline|prerr_float|prerr_int|prerr_newline|prerr_string|print|print_as|print_bool|print_break|print_char|print_cut|print_endline|print_float|print_flush|print_if_newline|print_int|print_newline|print_space|print_stat|print_string|print_tab|print_tbreak|printf|prohibit|public_method_label|push|putenv|quo_num|quomod_big_int|quote|raise|raise_window|ratio_of_num|rcontains_from|read|read_float|read_int|read_key|read_line|readdir|readdir|readlink|really_input|receive|recv|recvfrom|red|ref|regexp|regexp_case_fold|regexp_string|regexp_string_case_fold|register|register_exception|rem|remember_mode|remove|remove_assoc|remove_assq|rename|replace|replace_first|replace_matched|repr|reset|reshape|reshape_1|reshape_2|reshape_3|rev|rev_append|rev_map|rev_map2|rewinddir|rgb|rhs_end|rhs_end_pos|rhs_start|rhs_start_pos|rindex|rindex_from|rlineto|rmdir|rmoveto|round_num|run_initializers|run_initializers_opt|scanf|search_backward|search_forward|seek_in|seek_out|select|self|self_init|send|sendto|set|set_all_formatter_output_functions|set_approx_printing|set_binary_mode_in|set_binary_mode_out|set_close_on_exec|set_close_on_exec|set_color|set_ellipsis_text|set_error_when_null_denominator|set_field|set_floating_precision|set_font|set_formatter_out_channel|set_formatter_output_functions|set_formatter_tag_functions|set_line_width|set_margin|set_mark_tags|set_max_boxes|set_max_indent|set_method|set_nonblock|set_nonblock|set_normalize_ratio|set_normalize_ratio_when_printing|set_print_tags|set_signal|set_state|set_tab|set_tag|set_tags|set_text_size|set_window_title|setgid|setgid|setitimer|setitimer|setsid|setsid|setsockopt|setsockopt|setsockopt_float|setsockopt_float|setsockopt_int|setsockopt_int|setsockopt_optint|setsockopt_optint|setuid|setuid|shift_left|shift_left|shift_left|shift_right|shift_right|shift_right|shift_right_logical|shift_right_logical|shift_right_logical|show_buckets|shutdown|shutdown|shutdown_connection|shutdown_connection|sigabrt|sigalrm|sigchld|sigcont|sigfpe|sighup|sigill|sigint|sigkill|sign_big_int|sign_num|signal|signal|sigpending|sigpending|sigpipe|sigprocmask|sigprocmask|sigprof|sigquit|sigsegv|sigstop|sigsuspend|sigsuspend|sigterm|sigtstp|sigttin|sigttou|sigusr1|sigusr2|sigvtalrm|sin|singleton|sinh|size|size|size_x|size_y|sleep|sleep|sleep|slice_left|slice_left|slice_left_1|slice_left_2|slice_right|slice_right|slice_right_1|slice_right_2|snd|socket|socket|socket|socketpair|socketpair|sort|sound|split|split_delim|sprintf|sprintf|sqrt|sqrt|sqrt_big_int|square_big_int|square_num|sscanf|stable_sort|stable_sort|stable_sort|stable_sort|stable_sort|stable_sort|stat|stat|stat|stat|stat|stats|stats|std_formatter|stdbuf|stderr|stderr|stderr|stdib|stdin|stdin|stdin|stdout|stdout|stdout|str_formatter|string|string_after|string_before|string_match|string_of_big_int|string_of_bool|string_of_float|string_of_format|string_of_inet_addr|string_of_inet_addr|string_of_int|string_of_num|string_partial_match|string_tag|sub|sub|sub_big_int|sub_left|sub_num|sub_right|subset|subset|substitute_first|substring|succ|succ|succ|succ|succ_big_int|succ_num|symbol_end|symbol_end_pos|symbol_start|symbol_start_pos|symlink|symlink|sync|synchronize|system|system|system|tag|take|tan|tanh|tcdrain|tcdrain|tcflow|tcflow|tcflush|tcflush|tcgetattr|tcgetattr|tcsendbreak|tcsendbreak|tcsetattr|tcsetattr|temp_file|text_size|time|time|time|timed_read|timed_write|times|times|tl|tl|tl|to_buffer|to_channel|to_float|to_hex|to_int|to_int32|to_list|to_list|to_list|to_nativeint|to_string|to_string|to_string|to_string|to_string|top|top|total_size|transfer|transp|truncate|truncate|truncate|truncate|truncate|truncate|try_lock|umask|umask|uncapitalize|uncapitalize|uncapitalize|union|union|unit_big_int|unlink|unlink|unlock|unmarshal|unsafe_blit|unsafe_fill|unsafe_get|unsafe_get|unsafe_set|unsafe_set|update|uppercase|uppercase|uppercase|uppercase|usage|utimes|utimes|wait|wait|wait|wait|wait_next_event|wait_pid|wait_read|wait_signal|wait_timed_read|wait_timed_write|wait_write|waitpid|white|widen|window_id|word_size|wrap|wrap_abort|write|yellow|yield|zero|zero_big_int|Arg|Arith_status|Array|Array1|Array2|Array3|ArrayLabels|Big_int|Bigarray|Buffer|Callback|CamlinternalOO|Char|Complex|Condition|Dbm|Digest|Dynlink|Event|Filename|Format|Gc|Genarray|Genlex|Graphics|GraphicsX11|Hashtbl|Int32|Int64|LargeFile|Lazy|Lexing|List|ListLabels|Make|Map|Marshal|MoreLabels|Mutex|Nativeint|Num|Obj|Oo|Parsing|Pervasives|Printexc|Printf|Queue|Random|Scanf|Scanning|Set|Sort|Stack|State|StdLabels|Str|Stream|String|StringLabels|Sys|Thread|ThreadUnix|Tk|Unix|UnixLabels|Weak".split("|")),d="(?:(?:[1-9]\\d*)|(?:0))",f="(?:0[oO]?[0-7]+)",g="(?:0[xX][\\dA-Fa-f]+)",h="(?:0[bB][01]+)",i="(?:"+d+"|"+f+"|"+g+"|"+h+")",j="(?:[eE][+-]?\\d+)",k="(?:\\.\\d+)",l="(?:\\d+)",m="(?:(?:"+l+"?"+k+")|(?:"+l+"\\.))",n="(?:(?:"+m+"|"+l+")"+j+")",o="(?:"+n+"|"+m+")";this.$rules={start:[{token:"comment",regex:"\\(\\*.*?\\*\\)\\s*?$"},{token:"comment",merge:!0,regex:"\\(\\*.*",next:"comment"},{token:"string",regex:'["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'},{token:"string",regex:"'.'"},{token:"string",merge:!0,regex:'"',next:"qstring"},{token:"constant.numeric",regex:"(?:"+o+"|\\d+)[jJ]\\b"},{token:"constant.numeric",regex:o},{token:"constant.numeric",regex:i+"\\b"},{token:function(d){return a.hasOwnProperty(d)?"keyword":b.hasOwnProperty(d)?"constant.language":c.hasOwnProperty(d)?"support.function":"identifier"},regex:"[a-zA-Z_$][a-zA-Z0-9_$]*\\b"},{token:"keyword.operator",regex:"\\+\\.|\\-\\.|\\*\\.|\\/\\.|#|;;|\\+|\\-|\\*|\\*\\*\\/|\\/\\/|%|<<|>>|&|\\||\\^|~|<|>|<=|=>|==|!=|<>|<-|="},{token:"paren.lparen",regex:"[[({]"},{token:"paren.rparen",regex:"[\\])}]"},{token:"text",regex:"\\s+"}],comment:[{token:"comment",regex:".*?\\*\\)",next:"start"},{token:"comment",merge:!0,regex:".+"}],qstring:[{token:"string",regex:'"',next:"start"},{token:"string",merge:!0,regex:".+"}]}};d.inherits(g,f),b.OcamlHighlightRules=g}),define("ace/mode/matching_brace_outdent",["require","exports","module","ace/range"],function(a,b,c){"use strict";var d=a("../range").Range,e=function(){};(function(){this.checkOutdent=function(a,b){return/^\s+$/.test(a)?/^\s*\}/.test(b):!1},this.autoOutdent=function(a,b){var c=a.getLine(b),e=c.match(/^(\s*\})/);if(!e)return 0;var f=e[1].length,g=a.findMatchingBracket({row:b,column:f});if(!g||g.row==b)return 0;var h=this.$getIndent(a.getLine(g.row));a.replace(new d(b,0,b,f-1),h)},this.$getIndent=function(a){var b=a.match(/^(\s+)/);return b?b[1]:""}}).call(e.prototype),b.MatchingBraceOutdent=e})
\ No newline at end of file
diff --git a/apps/files_texteditor/js/aceeditor/mode-perl-uncompressed.js b/apps/files_texteditor/js/aceeditor/mode-perl-uncompressed.js
old mode 100755
new mode 100644
index c8bf4c47eb56beed716d8a79d395014bce64ce89..04796f61aed82e2675072fe4badd35c30a340db8
--- a/apps/files_texteditor/js/aceeditor/mode-perl-uncompressed.js
+++ b/apps/files_texteditor/js/aceeditor/mode-perl-uncompressed.js
@@ -571,13 +571,3 @@ var FoldMode = exports.FoldMode = function() {};
 }).call(FoldMode.prototype);
 
 });
-;
-            (function() {
-                window.require(["ace/ace"], function(a) {
-                    if (!window.ace)
-                        window.ace = {};
-                    for (var key in a) if (a.hasOwnProperty(key))
-                        ace[key] = a[key];
-                });
-            })();
-        
\ No newline at end of file
diff --git a/apps/files_texteditor/js/aceeditor/mode-perl.js b/apps/files_texteditor/js/aceeditor/mode-perl.js
index 706bb9362c3abd87a301ae2f9b6eb94ced2b224b..909781418b3d41db795bda4389822cefd3d02576 100644
--- a/apps/files_texteditor/js/aceeditor/mode-perl.js
+++ b/apps/files_texteditor/js/aceeditor/mode-perl.js
@@ -1 +1 @@
-define("ace/mode/perl",["require","exports","module","ace/lib/oop","ace/mode/text","ace/tokenizer","ace/mode/perl_highlight_rules","ace/mode/matching_brace_outdent","ace/range","ace/mode/folding/cstyle"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("./text").Mode,f=a("../tokenizer").Tokenizer,g=a("./perl_highlight_rules").PerlHighlightRules,h=a("./matching_brace_outdent").MatchingBraceOutdent,i=a("../range").Range,j=a("./folding/cstyle").FoldMode,k=function(){this.$tokenizer=new f((new g).getRules()),this.$outdent=new h,this.foldingRules=new j};d.inherits(k,e),function(){this.toggleCommentLines=function(a,b,c,d){var e=!0,f=/^(\s*)#/;for(var g=c;g<=d;g++)if(!f.test(b.getLine(g))){e=!1;break}if(e){var h=new i(0,0,0,0);for(var g=c;g<=d;g++){var j=b.getLine(g),k=j.match(f);h.start.row=g,h.end.row=g,h.end.column=k[0].length,b.replace(h,k[1])}}else b.indentRows(c,d,"#")},this.getNextLineIndent=function(a,b,c){var d=this.$getIndent(b),e=this.$tokenizer.getLineTokens(b,a),f=e.tokens;if(f.length&&f[f.length-1].type=="comment")return d;if(a=="start"){var g=b.match(/^.*[\{\(\[\:]\s*$/);g&&(d+=c)}return d},this.checkOutdent=function(a,b,c){return this.$outdent.checkOutdent(b,c)},this.autoOutdent=function(a,b,c){this.$outdent.autoOutdent(b,c)}}.call(k.prototype),b.Mode=k}),define("ace/mode/perl_highlight_rules",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/mode/text_highlight_rules"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("../lib/lang"),f=a("./text_highlight_rules").TextHighlightRules,g=function(){var a=e.arrayToMap("base|constant|continue|else|elsif|for|foreach|format|goto|if|last|local|my|next|no|package|parent|redo|require|scalar|sub|unless|until|while|use|vars".split("|")),b=e.arrayToMap("ARGV|ENV|INC|SIG".split("|")),c=e.arrayToMap("getprotobynumber|getprotobyname|getservbyname|gethostbyaddr|gethostbyname|getservbyport|getnetbyaddr|getnetbyname|getsockname|getpeername|setpriority|getprotoent|setprotoent|getpriority|endprotoent|getservent|setservent|endservent|sethostent|socketpair|getsockopt|gethostent|endhostent|setsockopt|setnetent|quotemeta|localtime|prototype|getnetent|endnetent|rewinddir|wantarray|getpwuid|closedir|getlogin|readlink|endgrent|getgrgid|getgrnam|shmwrite|shutdown|readline|endpwent|setgrent|readpipe|formline|truncate|dbmclose|syswrite|setpwent|getpwnam|getgrent|getpwent|ucfirst|sysread|setpgrp|shmread|sysseek|sysopen|telldir|defined|opendir|connect|lcfirst|getppid|binmode|syscall|sprintf|getpgrp|readdir|seekdir|waitpid|reverse|unshift|symlink|dbmopen|semget|msgrcv|rename|listen|chroot|msgsnd|shmctl|accept|unpack|exists|fileno|shmget|system|unlink|printf|gmtime|msgctl|semctl|values|rindex|substr|splice|length|msgget|select|socket|return|caller|delete|alarm|ioctl|index|undef|lstat|times|srand|chown|fcntl|close|write|umask|rmdir|study|sleep|chomp|untie|print|utime|mkdir|atan2|split|crypt|flock|chmod|BEGIN|bless|chdir|semop|shift|reset|link|stat|chop|grep|fork|dump|join|open|tell|pipe|exit|glob|warn|each|bind|sort|pack|eval|push|keys|getc|kill|seek|sqrt|send|wait|rand|tied|read|time|exec|recv|eof|chr|int|ord|exp|pos|pop|sin|log|abs|oct|hex|tie|cos|vec|END|ref|map|die|uc|lc|do".split("|"));this.$rules={start:[{token:"comment",regex:"#.*$"},{token:"string.regexp",regex:"[/](?:(?:\\[(?:\\\\]|[^\\]])+\\])|(?:\\\\/|[^\\]/]))*[/]\\w*\\s*(?=[).,;]|$)"},{token:"string",regex:'["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'},{token:"string",merge:!0,regex:'["].*\\\\$',next:"qqstring"},{token:"string",regex:"['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"},{token:"string",merge:!0,regex:"['].*\\\\$",next:"qstring"},{token:"constant.numeric",regex:"0x[0-9a-fA-F]+\\b"},{token:"constant.numeric",regex:"[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"},{token:function(d){return a.hasOwnProperty(d)?"keyword":b.hasOwnProperty(d)?"constant.language":c.hasOwnProperty(d)?"support.function":"identifier"},regex:"[a-zA-Z_$][a-zA-Z0-9_$]*\\b"},{token:"keyword.operator",regex:"\\.\\.\\.|\\|\\|=|>>=|<<=|<=>|&&=|=>|!~|\\^=|&=|\\|=|\\.=|x=|%=|\\/=|\\*=|\\-=|\\+=|=~|\\*\\*|\\-\\-|\\.\\.|\\|\\||&&|\\+\\+|\\->|!=|==|>=|<=|>>|<<|,|=|\\?\\:|\\^|\\||x|%|\\/|\\*|<|&|\\\\|~|!|>|\\.|\\-|\\+|\\-C|\\-b|\\-S|\\-u|\\-t|\\-p|\\-l|\\-d|\\-f|\\-g|\\-s|\\-z|\\-k|\\-e|\\-O|\\-T|\\-B|\\-M|\\-A|\\-X|\\-W|\\-c|\\-R|\\-o|\\-x|\\-w|\\-r|\\b(?:and|cmp|eq|ge|gt|le|lt|ne|not|or|xor)"},{token:"lparen",regex:"[[({]"},{token:"rparen",regex:"[\\])}]"},{token:"text",regex:"\\s+"}],qqstring:[{token:"string",regex:'(?:(?:\\\\.)|(?:[^"\\\\]))*?"',next:"start"},{token:"string",merge:!0,regex:".+"}],qstring:[{token:"string",regex:"(?:(?:\\\\.)|(?:[^'\\\\]))*?'",next:"start"},{token:"string",merge:!0,regex:".+"}]}};d.inherits(g,f),b.PerlHighlightRules=g}),define("ace/mode/matching_brace_outdent",["require","exports","module","ace/range"],function(a,b,c){"use strict";var d=a("../range").Range,e=function(){};((function(){this.checkOutdent=function(a,b){return/^\s+$/.test(a)?/^\s*\}/.test(b):!1},this.autoOutdent=function(a,b){var c=a.getLine(b),e=c.match(/^(\s*\})/);if(!e)return 0;var f=e[1].length,g=a.findMatchingBracket({row:b,column:f});if(!g||g.row==b)return 0;var h=this.$getIndent(a.getLine(g.row));a.replace(new d(b,0,b,f-1),h)},this.$getIndent=function(a){var b=a.match(/^(\s+)/);return b?b[1]:""}})).call(e.prototype),b.MatchingBraceOutdent=e}),define("ace/mode/folding/cstyle",["require","exports","module","ace/lib/oop","ace/range","ace/mode/folding/fold_mode"],function(a,b,c){"use strict";var d=a("../../lib/oop"),e=a("../../range").Range,f=a("./fold_mode").FoldMode,g=b.FoldMode=function(){};d.inherits(g,f),function(){this.foldingStartMarker=/(\{|\[)[^\}\]]*$|^\s*(\/\*)/,this.foldingStopMarker=/^[^\[\{]*(\}|\])|^[\s\*]*(\*\/)/,this.getFoldWidgetRange=function(a,b,c){var d=a.getLine(c),f=d.match(this.foldingStartMarker);if(f){var g=f.index;if(f[1])return this.openingBracketBlock(a,f[1],c,g);var h=a.getCommentFoldRange(c,g+f[0].length);return h.end.column-=2,h}if(b!=="markbeginend")return;var f=d.match(this.foldingStopMarker);if(f){var g=f.index+f[0].length;if(f[2]){var h=a.getCommentFoldRange(c,g);return h.end.column-=2,h}var i={row:c,column:g},j=a.$findOpeningBracket(f[1],i);if(!j)return;return j.column++,i.column--,e.fromPoints(j,i)}}}.call(g.prototype)}),define("ace/mode/folding/fold_mode",["require","exports","module","ace/range"],function(a,b,c){"use strict";var d=a("../../range").Range,e=b.FoldMode=function(){};((function(){this.foldingStartMarker=null,this.foldingStopMarker=null,this.getFoldWidget=function(a,b,c){var d=a.getLine(c);return this.foldingStartMarker.test(d)?"start":b=="markbeginend"&&this.foldingStopMarker&&this.foldingStopMarker.test(d)?"end":""},this.getFoldWidgetRange=function(a,b,c){return null},this.indentationBlock=function(a,b,c){var e=/^\s*/,f=b,g=b,h=a.getLine(b),i=c||h.length,j=h.match(e)[0].length,k=a.getLength();while(++b<k){h=a.getLine(b);var l=h.match(e)[0].length;if(l==h.length)continue;if(l<=j)break;g=b}if(g>f){var m=a.getLine(g).length;return new d(f,i,g,m)}},this.openingBracketBlock=function(a,b,c,e){var f={row:c,column:e+1},g=a.$findClosingBracket(b,f);if(!g)return;var h=a.foldWidgets[g.row];return h==null&&(h=this.getFoldWidget(a,g.row)),h=="start"&&(g.row--,g.column=a.getLine(g.row).length),d.fromPoints(f,g)}})).call(e.prototype)}),function(){window.require(["ace/ace"],function(a){window.ace||(window.ace={});for(var b in a)a.hasOwnProperty(b)&&(ace[b]=a[b])})}()
\ No newline at end of file
+define("ace/mode/perl",["require","exports","module","ace/lib/oop","ace/mode/text","ace/tokenizer","ace/mode/perl_highlight_rules","ace/mode/matching_brace_outdent","ace/range","ace/mode/folding/cstyle"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("./text").Mode,f=a("../tokenizer").Tokenizer,g=a("./perl_highlight_rules").PerlHighlightRules,h=a("./matching_brace_outdent").MatchingBraceOutdent,i=a("../range").Range,j=a("./folding/cstyle").FoldMode,k=function(){this.$tokenizer=new f((new g).getRules()),this.$outdent=new h,this.foldingRules=new j};d.inherits(k,e),function(){this.toggleCommentLines=function(a,b,c,d){var e=!0,f=/^(\s*)#/;for(var g=c;g<=d;g++)if(!f.test(b.getLine(g))){e=!1;break}if(e){var h=new i(0,0,0,0);for(var g=c;g<=d;g++){var j=b.getLine(g),k=j.match(f);h.start.row=g,h.end.row=g,h.end.column=k[0].length,b.replace(h,k[1])}}else b.indentRows(c,d,"#")},this.getNextLineIndent=function(a,b,c){var d=this.$getIndent(b),e=this.$tokenizer.getLineTokens(b,a),f=e.tokens;if(f.length&&f[f.length-1].type=="comment")return d;if(a=="start"){var g=b.match(/^.*[\{\(\[\:]\s*$/);g&&(d+=c)}return d},this.checkOutdent=function(a,b,c){return this.$outdent.checkOutdent(b,c)},this.autoOutdent=function(a,b,c){this.$outdent.autoOutdent(b,c)}}.call(k.prototype),b.Mode=k}),define("ace/mode/perl_highlight_rules",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/mode/text_highlight_rules"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("../lib/lang"),f=a("./text_highlight_rules").TextHighlightRules,g=function(){var a=e.arrayToMap("base|constant|continue|else|elsif|for|foreach|format|goto|if|last|local|my|next|no|package|parent|redo|require|scalar|sub|unless|until|while|use|vars".split("|")),b=e.arrayToMap("ARGV|ENV|INC|SIG".split("|")),c=e.arrayToMap("getprotobynumber|getprotobyname|getservbyname|gethostbyaddr|gethostbyname|getservbyport|getnetbyaddr|getnetbyname|getsockname|getpeername|setpriority|getprotoent|setprotoent|getpriority|endprotoent|getservent|setservent|endservent|sethostent|socketpair|getsockopt|gethostent|endhostent|setsockopt|setnetent|quotemeta|localtime|prototype|getnetent|endnetent|rewinddir|wantarray|getpwuid|closedir|getlogin|readlink|endgrent|getgrgid|getgrnam|shmwrite|shutdown|readline|endpwent|setgrent|readpipe|formline|truncate|dbmclose|syswrite|setpwent|getpwnam|getgrent|getpwent|ucfirst|sysread|setpgrp|shmread|sysseek|sysopen|telldir|defined|opendir|connect|lcfirst|getppid|binmode|syscall|sprintf|getpgrp|readdir|seekdir|waitpid|reverse|unshift|symlink|dbmopen|semget|msgrcv|rename|listen|chroot|msgsnd|shmctl|accept|unpack|exists|fileno|shmget|system|unlink|printf|gmtime|msgctl|semctl|values|rindex|substr|splice|length|msgget|select|socket|return|caller|delete|alarm|ioctl|index|undef|lstat|times|srand|chown|fcntl|close|write|umask|rmdir|study|sleep|chomp|untie|print|utime|mkdir|atan2|split|crypt|flock|chmod|BEGIN|bless|chdir|semop|shift|reset|link|stat|chop|grep|fork|dump|join|open|tell|pipe|exit|glob|warn|each|bind|sort|pack|eval|push|keys|getc|kill|seek|sqrt|send|wait|rand|tied|read|time|exec|recv|eof|chr|int|ord|exp|pos|pop|sin|log|abs|oct|hex|tie|cos|vec|END|ref|map|die|uc|lc|do".split("|"));this.$rules={start:[{token:"comment",regex:"#.*$"},{token:"string.regexp",regex:"[/](?:(?:\\[(?:\\\\]|[^\\]])+\\])|(?:\\\\/|[^\\]/]))*[/]\\w*\\s*(?=[).,;]|$)"},{token:"string",regex:'["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'},{token:"string",merge:!0,regex:'["].*\\\\$',next:"qqstring"},{token:"string",regex:"['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"},{token:"string",merge:!0,regex:"['].*\\\\$",next:"qstring"},{token:"constant.numeric",regex:"0x[0-9a-fA-F]+\\b"},{token:"constant.numeric",regex:"[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"},{token:function(d){return a.hasOwnProperty(d)?"keyword":b.hasOwnProperty(d)?"constant.language":c.hasOwnProperty(d)?"support.function":"identifier"},regex:"[a-zA-Z_$][a-zA-Z0-9_$]*\\b"},{token:"keyword.operator",regex:"\\.\\.\\.|\\|\\|=|>>=|<<=|<=>|&&=|=>|!~|\\^=|&=|\\|=|\\.=|x=|%=|\\/=|\\*=|\\-=|\\+=|=~|\\*\\*|\\-\\-|\\.\\.|\\|\\||&&|\\+\\+|\\->|!=|==|>=|<=|>>|<<|,|=|\\?\\:|\\^|\\||x|%|\\/|\\*|<|&|\\\\|~|!|>|\\.|\\-|\\+|\\-C|\\-b|\\-S|\\-u|\\-t|\\-p|\\-l|\\-d|\\-f|\\-g|\\-s|\\-z|\\-k|\\-e|\\-O|\\-T|\\-B|\\-M|\\-A|\\-X|\\-W|\\-c|\\-R|\\-o|\\-x|\\-w|\\-r|\\b(?:and|cmp|eq|ge|gt|le|lt|ne|not|or|xor)"},{token:"lparen",regex:"[[({]"},{token:"rparen",regex:"[\\])}]"},{token:"text",regex:"\\s+"}],qqstring:[{token:"string",regex:'(?:(?:\\\\.)|(?:[^"\\\\]))*?"',next:"start"},{token:"string",merge:!0,regex:".+"}],qstring:[{token:"string",regex:"(?:(?:\\\\.)|(?:[^'\\\\]))*?'",next:"start"},{token:"string",merge:!0,regex:".+"}]}};d.inherits(g,f),b.PerlHighlightRules=g}),define("ace/mode/matching_brace_outdent",["require","exports","module","ace/range"],function(a,b,c){"use strict";var d=a("../range").Range,e=function(){};(function(){this.checkOutdent=function(a,b){return/^\s+$/.test(a)?/^\s*\}/.test(b):!1},this.autoOutdent=function(a,b){var c=a.getLine(b),e=c.match(/^(\s*\})/);if(!e)return 0;var f=e[1].length,g=a.findMatchingBracket({row:b,column:f});if(!g||g.row==b)return 0;var h=this.$getIndent(a.getLine(g.row));a.replace(new d(b,0,b,f-1),h)},this.$getIndent=function(a){var b=a.match(/^(\s+)/);return b?b[1]:""}}).call(e.prototype),b.MatchingBraceOutdent=e}),define("ace/mode/folding/cstyle",["require","exports","module","ace/lib/oop","ace/range","ace/mode/folding/fold_mode"],function(a,b,c){"use strict";var d=a("../../lib/oop"),e=a("../../range").Range,f=a("./fold_mode").FoldMode,g=b.FoldMode=function(){};d.inherits(g,f),function(){this.foldingStartMarker=/(\{|\[)[^\}\]]*$|^\s*(\/\*)/,this.foldingStopMarker=/^[^\[\{]*(\}|\])|^[\s\*]*(\*\/)/,this.getFoldWidgetRange=function(a,b,c){var d=a.getLine(c),f=d.match(this.foldingStartMarker);if(f){var g=f.index;if(f[1])return this.openingBracketBlock(a,f[1],c,g);var h=a.getCommentFoldRange(c,g+f[0].length);return h.end.column-=2,h}if(b!=="markbeginend")return;var f=d.match(this.foldingStopMarker);if(f){var g=f.index+f[0].length;if(f[2]){var h=a.getCommentFoldRange(c,g);return h.end.column-=2,h}var i={row:c,column:g},j=a.$findOpeningBracket(f[1],i);if(!j)return;return j.column++,i.column--,e.fromPoints(j,i)}}}.call(g.prototype)}),define("ace/mode/folding/fold_mode",["require","exports","module","ace/range"],function(a,b,c){"use strict";var d=a("../../range").Range,e=b.FoldMode=function(){};(function(){this.foldingStartMarker=null,this.foldingStopMarker=null,this.getFoldWidget=function(a,b,c){var d=a.getLine(c);return this.foldingStartMarker.test(d)?"start":b=="markbeginend"&&this.foldingStopMarker&&this.foldingStopMarker.test(d)?"end":""},this.getFoldWidgetRange=function(a,b,c){return null},this.indentationBlock=function(a,b,c){var e=/^\s*/,f=b,g=b,h=a.getLine(b),i=c||h.length,j=h.match(e)[0].length,k=a.getLength();while(++b<k){h=a.getLine(b);var l=h.match(e)[0].length;if(l==h.length)continue;if(l<=j)break;g=b}if(g>f){var m=a.getLine(g).length;return new d(f,i,g,m)}},this.openingBracketBlock=function(a,b,c,e){var f={row:c,column:e+1},g=a.$findClosingBracket(b,f);if(!g)return;var h=a.foldWidgets[g.row];return h==null&&(h=this.getFoldWidget(a,g.row)),h=="start"&&(g.row--,g.column=a.getLine(g.row).length),d.fromPoints(f,g)}}).call(e.prototype)})
\ No newline at end of file
diff --git a/apps/files_texteditor/js/aceeditor/mode-pgsql-uncompressed.js b/apps/files_texteditor/js/aceeditor/mode-pgsql-uncompressed.js
new file mode 100644
index 0000000000000000000000000000000000000000..344647c792fd1ba4b82d37ffc46934b65c3b2002
--- /dev/null
+++ b/apps/files_texteditor/js/aceeditor/mode-pgsql-uncompressed.js
@@ -0,0 +1,1107 @@
+/* ***** BEGIN LICENSE BLOCK *****
+* The Original Code is Ajax.org Code Editor (ACE).
+*
+* Contributor(s):
+*      Jonathan Camile <jonathan.camile AT gmail DOT com>
+*
+* Alternatively, the contents of this file may be used under the terms of
+* either the GNU General Public License Version 2 or later (the "GPL"), or
+* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+* in which case the provisions of the GPL or the LGPL are applicable instead
+* of those above. If you wish to allow use of your version of this file only
+* under the terms of either the GPL or the LGPL, and not to allow others to
+* use your version of this file under the terms of the MPL, indicate your
+* decision by deleting the provisions above and replace them with the notice
+* and other provisions required by the GPL or the LGPL. If you do not delete
+* the provisions above, a recipient may use your version of this file under
+* the terms of any one of the MPL, the GPL or the LGPL.
+*
+* ***** END LICENSE BLOCK ***** */
+
+define('ace/mode/pgsql', ['require', 'exports', 'module' , 'ace/lib/oop', 'ace/mode/text', 'ace/tokenizer', 'ace/mode/pgsql_highlight_rules', 'ace/range'], function(require, exports, module) {
+
+    var oop = require("ace/lib/oop");
+    var TextMode = require("ace/mode/text").Mode;
+    var Tokenizer = require("ace/tokenizer").Tokenizer;
+    var PgsqlHighlightRules = require("ace/mode/pgsql_highlight_rules").PgsqlHighlightRules;
+    var Range = require("ace/range").Range;
+    // var EditSession = require("ace/edit_session").EditSession;
+
+    var Mode = function() {
+        this.$tokenizer = new Tokenizer(new PgsqlHighlightRules().getRules());
+    };
+    oop.inherits(Mode, TextMode);
+
+    (function() {
+
+        this.toggleCommentLines = function(state, doc, startRow, endRow) {
+            var outdent = true;
+            // var outentedRows = [];
+            var re = /^(\s*)--/;
+
+            for (var i=startRow; i<= endRow; i++) {
+                if (!re.test(doc.getLine(i))) {
+                    outdent = false;
+                    break;
+                }
+            }
+
+            if (outdent) {
+                var deleteRange = new Range(0, 0, 0, 0);
+                for (var i=startRow; i<= endRow; i++)
+                {
+                    var line = doc.getLine(i);
+                    var m = line.match(re);
+                    deleteRange.start.row = i;
+                    deleteRange.end.row = i;
+                    deleteRange.end.column = m[0].length;
+                    doc.replace(deleteRange, m[1]);
+                }
+            }
+            else {
+                doc.indentRows(startRow, endRow, "--");
+            }
+        };
+
+
+        this.getNextLineIndent = function(state, line, tab) { 
+            if (state == "start" || state == "keyword.statementEnd") {
+                return "";
+            } else {
+                return this.$getIndent(line); // Keep whatever indent the previous line has
+            }
+        }
+
+    }).call(Mode.prototype);
+
+    exports.Mode = Mode;
+});
+/* ***** BEGIN LICENSE BLOCK *****
+ * The Original Code is Ajax.org Code Editor (ACE).
+ *
+ * Contributor(s):
+ *      John DeSoi, Ph.D. <desoi AT pgedit DOT com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK *****
+ *
+ */
+
+
+define('ace/mode/pgsql_highlight_rules', ['require', 'exports', 'module' , 'ace/lib/oop', 'ace/lib/lang', 'ace/mode/doc_comment_highlight_rules', 'ace/mode/text_highlight_rules', 'ace/mode/perl_highlight_rules', 'ace/mode/python_highlight_rules'], function(require, exports, module) {
+
+var oop = require("ace/lib/oop");
+var lang = require("ace/lib/lang");
+var DocCommentHighlightRules = require("./doc_comment_highlight_rules").DocCommentHighlightRules;
+var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
+// Supporting perl and python for now -- both in pg core and ace
+var PerlHighlightRules = require("./perl_highlight_rules").PerlHighlightRules;
+var PythonHighlightRules = require("./python_highlight_rules").PythonHighlightRules;
+
+var PgsqlHighlightRules = function() {
+    
+    // Keywords, functions, operators last updated for pg 9.1.
+    var keywords = lang.arrayToMap(
+        ("abort|absolute|abstime|access|aclitem|action|add|admin|after|aggregate|all|also|alter|always|" +
+        "analyse|analyze|and|any|anyarray|anyelement|anyenum|anynonarray|array|as|asc|assertion|" +
+        "assignment|asymmetric|at|attribute|authorization|backward|before|begin|between|bigint|" +
+        "binary|bit|bool|boolean|both|box|bpchar|by|bytea|cache|called|cascade|cascaded|case|cast|" +
+        "catalog|chain|char|character|characteristics|check|checkpoint|cid|cidr|circle|class|close|" +
+        "cluster|coalesce|collate|collation|column|comment|comments|commit|committed|concurrently|" +
+        "configuration|connection|constraint|constraints|content|continue|conversion|copy|cost|" +
+        "create|cross|cstring|csv|current|current_catalog|current_date|current_role|" +
+        "current_schema|current_time|current_timestamp|current_user|cursor|cycle|data|database|" +
+        "date|day|deallocate|dec|decimal|declare|default|defaults|deferrable|deferred|definer|delete|" +
+        "delimiter|delimiters|desc|dictionary|disable|discard|distinct|do|document|domain|double|" +
+        "drop|each|else|enable|encoding|encrypted|end|enum|escape|except|exclude|excluding|exclusive|" +
+        "execute|exists|explain|extension|external|extract|false|family|fdw_handler|fetch|first|" +
+        "float|float4|float8|following|for|force|foreign|forward|freeze|from|full|function|functions|" +
+        "global|grant|granted|greatest|group|gtsvector|handler|having|header|hold|hour|identity|if|" +
+        "ilike|immediate|immutable|implicit|in|including|increment|index|indexes|inet|inherit|" +
+        "inherits|initially|inline|inner|inout|input|insensitive|insert|instead|int|int2|int2vector|" +
+        "int4|int8|integer|internal|intersect|interval|into|invoker|is|isnull|isolation|join|key|label|" +
+        "language|language_handler|large|last|lc_collate|lc_ctype|leading|least|left|level|like|" +
+        "limit|line|listen|load|local|localtime|localtimestamp|location|lock|lseg|macaddr|mapping|" +
+        "match|maxvalue|minute|minvalue|mode|money|month|move|name|names|national|natural|nchar|next|no|" +
+        "none|not|nothing|notify|notnull|nowait|null|nullif|nulls|numeric|object|of|off|offset|oid|oids|" +
+        "oidvector|on|only|opaque|operator|option|options|or|order|out|outer|over|overlaps|overlay|" +
+        "owned|owner|parser|partial|partition|passing|password|path|pg_attribute|pg_auth_members|" +
+        "pg_authid|pg_class|pg_database|pg_node_tree|pg_proc|pg_type|placing|plans|point|polygon|" +
+        "position|preceding|precision|prepare|prepared|preserve|primary|prior|privileges|" +
+        "procedural|procedure|quote|range|read|real|reassign|recheck|record|recursive|ref|refcursor|" +
+        "references|regclass|regconfig|regdictionary|regoper|regoperator|regproc|regprocedure|" +
+        "regtype|reindex|relative|release|reltime|rename|repeatable|replace|replica|reset|restart|" +
+        "restrict|returning|returns|revoke|right|role|rollback|row|rows|rule|savepoint|schema|scroll|" +
+        "search|second|security|select|sequence|sequences|serializable|server|session|session_user|" +
+        "set|setof|share|show|similar|simple|smallint|smgr|some|stable|standalone|start|statement|" +
+        "statistics|stdin|stdout|storage|strict|strip|substring|symmetric|sysid|system|table|tables|" +
+        "tablespace|temp|template|temporary|text|then|tid|time|timestamp|timestamptz|timetz|" +
+        "tinterval|to|trailing|transaction|treat|trigger|trim|true|truncate|trusted|tsquery|tsvector|" +
+        "txid_snapshot|type|unbounded|uncommitted|unencrypted|union|unique|unknown|unlisten|" +
+        "unlogged|until|update|user|using|uuid|vacuum|valid|validate|validator|value|values|varbit|" +
+        "varchar|variadic|varying|verbose|version|view|void|volatile|when|where|whitespace|window|" +
+        "with|without|work|wrapper|write|xid|xml|xmlattributes|xmlconcat|xmlelement|xmlexists|" +
+        "xmlforest|xmlparse|xmlpi|xmlroot|xmlserialize|year|yes|zone").split("|")
+    );
+    
+    
+    var builtinFunctions = lang.arrayToMap(
+        ("RI_FKey_cascade_del|RI_FKey_cascade_upd|RI_FKey_check_ins|RI_FKey_check_upd|" +
+        "RI_FKey_noaction_del|RI_FKey_noaction_upd|RI_FKey_restrict_del|RI_FKey_restrict_upd|" +
+        "RI_FKey_setdefault_del|RI_FKey_setdefault_upd|RI_FKey_setnull_del|" +
+        "RI_FKey_setnull_upd|abbrev|abs|abstime|abstimeeq|abstimege|abstimegt|abstimein|abstimele|" +
+        "abstimelt|abstimene|abstimeout|abstimerecv|abstimesend|aclcontains|aclexplode|aclinsert|" +
+        "aclitemeq|aclitemin|aclitemout|aclremove|acos|age|any_in|any_out|anyarray_in|anyarray_out|" +
+        "anyarray_recv|anyarray_send|anyelement_in|anyelement_out|anyenum_in|anyenum_out|" +
+        "anynonarray_in|anynonarray_out|anytextcat|area|areajoinsel|areasel|array_agg|" +
+        "array_agg_finalfn|array_agg_transfn|array_append|array_cat|array_dims|array_eq|" +
+        "array_fill|array_ge|array_gt|array_in|array_larger|array_le|array_length|array_lower|" +
+        "array_lt|array_ndims|array_ne|array_out|array_prepend|array_recv|array_send|" +
+        "array_smaller|array_to_string|array_upper|arraycontained|arraycontains|arrayoverlap|" +
+        "ascii|ascii_to_mic|ascii_to_utf8|asin|atan|atan2|avg|big5_to_euc_tw|big5_to_mic|" +
+        "big5_to_utf8|bit_and|bit_in|bit_length|bit_or|bit_out|bit_recv|bit_send|bitand|bitcat|" +
+        "bitcmp|biteq|bitge|bitgt|bitle|bitlt|bitne|bitnot|bitor|bitshiftleft|bitshiftright|" +
+        "bittypmodin|bittypmodout|bitxor|bool|bool_and|bool_or|booland_statefunc|booleq|boolge|" +
+        "boolgt|boolin|boolle|boollt|boolne|boolor_statefunc|boolout|boolrecv|boolsend|box|" +
+        "box_above|box_above_eq|box_add|box_below|box_below_eq|box_center|box_contain|" +
+        "box_contain_pt|box_contained|box_distance|box_div|box_eq|box_ge|box_gt|box_in|" +
+        "box_intersect|box_le|box_left|box_lt|box_mul|box_out|box_overabove|box_overbelow|" +
+        "box_overlap|box_overleft|box_overright|box_recv|box_right|box_same|box_send|box_sub|" +
+        "bpchar_larger|bpchar_pattern_ge|bpchar_pattern_gt|bpchar_pattern_le|" +
+        "bpchar_pattern_lt|bpchar_smaller|bpcharcmp|bpchareq|bpcharge|bpchargt|bpchariclike|" +
+        "bpcharicnlike|bpcharicregexeq|bpcharicregexne|bpcharin|bpcharle|bpcharlike|bpcharlt|" +
+        "bpcharne|bpcharnlike|bpcharout|bpcharrecv|bpcharregexeq|bpcharregexne|bpcharsend|" +
+        "bpchartypmodin|bpchartypmodout|broadcast|btabstimecmp|btarraycmp|btbeginscan|btboolcmp|" +
+        "btbpchar_pattern_cmp|btbuild|btbuildempty|btbulkdelete|btcharcmp|btcostestimate|" +
+        "btendscan|btfloat48cmp|btfloat4cmp|btfloat84cmp|btfloat8cmp|btgetbitmap|btgettuple|" +
+        "btinsert|btint24cmp|btint28cmp|btint2cmp|btint42cmp|btint48cmp|btint4cmp|btint82cmp|" +
+        "btint84cmp|btint8cmp|btmarkpos|btnamecmp|btoidcmp|btoidvectorcmp|btoptions|btrecordcmp|" +
+        "btreltimecmp|btrescan|btrestrpos|btrim|bttext_pattern_cmp|bttextcmp|bttidcmp|" +
+        "bttintervalcmp|btvacuumcleanup|byteacat|byteacmp|byteaeq|byteage|byteagt|byteain|byteale|" +
+        "bytealike|bytealt|byteane|byteanlike|byteaout|bytearecv|byteasend|cash_cmp|cash_div_cash|" +
+        "cash_div_flt4|cash_div_flt8|cash_div_int2|cash_div_int4|cash_eq|cash_ge|cash_gt|cash_in|" +
+        "cash_le|cash_lt|cash_mi|cash_mul_flt4|cash_mul_flt8|cash_mul_int2|cash_mul_int4|cash_ne|" +
+        "cash_out|cash_pl|cash_recv|cash_send|cash_words|cashlarger|cashsmaller|cbrt|ceil|ceiling|" +
+        "center|char|char_length|character_length|chareq|charge|chargt|charin|charle|charlt|charne|" +
+        "charout|charrecv|charsend|chr|cideq|cidin|cidout|cidr|cidr_in|cidr_out|cidr_recv|cidr_send|" +
+        "cidrecv|cidsend|circle|circle_above|circle_add_pt|circle_below|circle_center|" +
+        "circle_contain|circle_contain_pt|circle_contained|circle_distance|circle_div_pt|" +
+        "circle_eq|circle_ge|circle_gt|circle_in|circle_le|circle_left|circle_lt|circle_mul_pt|" +
+        "circle_ne|circle_out|circle_overabove|circle_overbelow|circle_overlap|circle_overleft|" +
+        "circle_overright|circle_recv|circle_right|circle_same|circle_send|circle_sub_pt|" +
+        "clock_timestamp|close_lb|close_ls|close_lseg|close_pb|close_pl|close_ps|close_sb|" +
+        "close_sl|col_description|concat|concat_ws|contjoinsel|contsel|convert|convert_from|" +
+        "convert_to|corr|cos|cot|count|covar_pop|covar_samp|cstring_in|cstring_out|cstring_recv|" +
+        "cstring_send|cume_dist|current_database|current_query|current_schema|current_schemas|" +
+        "current_setting|current_user|currtid|currtid2|currval|cursor_to_xml|" +
+        "cursor_to_xmlschema|database_to_xml|database_to_xml_and_xmlschema|" +
+        "database_to_xmlschema|date|date_cmp|date_cmp_timestamp|date_cmp_timestamptz|date_eq|" +
+        "date_eq_timestamp|date_eq_timestamptz|date_ge|date_ge_timestamp|date_ge_timestamptz|" +
+        "date_gt|date_gt_timestamp|date_gt_timestamptz|date_in|date_larger|date_le|" +
+        "date_le_timestamp|date_le_timestamptz|date_lt|date_lt_timestamp|date_lt_timestamptz|" +
+        "date_mi|date_mi_interval|date_mii|date_ne|date_ne_timestamp|date_ne_timestamptz|" +
+        "date_out|date_part|date_pl_interval|date_pli|date_recv|date_send|date_smaller|" +
+        "date_trunc|datetime_pl|datetimetz_pl|dcbrt|decode|degrees|dense_rank|dexp|diagonal|" +
+        "diameter|dispell_init|dispell_lexize|dist_cpoly|dist_lb|dist_pb|dist_pc|dist_pl|" +
+        "dist_ppath|dist_ps|dist_sb|dist_sl|div|dlog1|dlog10|domain_in|domain_recv|dpow|dround|" +
+        "dsimple_init|dsimple_lexize|dsnowball_init|dsnowball_lexize|dsqrt|dsynonym_init|" +
+        "dsynonym_lexize|dtrunc|encode|enum_cmp|enum_eq|enum_first|enum_ge|enum_gt|enum_in|" +
+        "enum_larger|enum_last|enum_le|enum_lt|enum_ne|enum_out|enum_range|enum_recv|enum_send|" +
+        "enum_smaller|eqjoinsel|eqsel|euc_cn_to_mic|euc_cn_to_utf8|" +
+        "euc_jis_2004_to_shift_jis_2004|euc_jis_2004_to_utf8|euc_jp_to_mic|euc_jp_to_sjis|" +
+        "euc_jp_to_utf8|euc_kr_to_mic|euc_kr_to_utf8|euc_tw_to_big5|euc_tw_to_mic|" +
+        "euc_tw_to_utf8|every|exp|factorial|family|fdw_handler_in|fdw_handler_out|first_value|" +
+        "float4|float48div|float48eq|float48ge|float48gt|float48le|float48lt|float48mi|float48mul|" +
+        "float48ne|float48pl|float4_accum|float4abs|float4div|float4eq|float4ge|float4gt|float4in|" +
+        "float4larger|float4le|float4lt|float4mi|float4mul|float4ne|float4out|float4pl|float4recv|" +
+        "float4send|float4smaller|float4um|float4up|float8|float84div|float84eq|float84ge|" +
+        "float84gt|float84le|float84lt|float84mi|float84mul|float84ne|float84pl|float8_accum|" +
+        "float8_avg|float8_corr|float8_covar_pop|float8_covar_samp|float8_regr_accum|" +
+        "float8_regr_avgx|float8_regr_avgy|float8_regr_intercept|float8_regr_r2|" +
+        "float8_regr_slope|float8_regr_sxx|float8_regr_sxy|float8_regr_syy|float8_stddev_pop|" +
+        "float8_stddev_samp|float8_var_pop|float8_var_samp|float8abs|float8div|float8eq|" +
+        "float8ge|float8gt|float8in|float8larger|float8le|float8lt|float8mi|float8mul|float8ne|" +
+        "float8out|float8pl|float8recv|float8send|float8smaller|float8um|float8up|floor|" +
+        "flt4_mul_cash|flt8_mul_cash|fmgr_c_validator|fmgr_internal_validator|" +
+        "fmgr_sql_validator|format|format_type|gb18030_to_utf8|gbk_to_utf8|generate_series|" +
+        "generate_subscripts|get_bit|get_byte|get_current_ts_config|getdatabaseencoding|" +
+        "getpgusername|gin_cmp_prefix|gin_cmp_tslexeme|gin_extract_tsquery|" +
+        "gin_extract_tsvector|gin_tsquery_consistent|ginarrayconsistent|ginarrayextract|" +
+        "ginbeginscan|ginbuild|ginbuildempty|ginbulkdelete|gincostestimate|ginendscan|" +
+        "gingetbitmap|gininsert|ginmarkpos|ginoptions|ginqueryarrayextract|ginrescan|" +
+        "ginrestrpos|ginvacuumcleanup|gist_box_compress|gist_box_consistent|" +
+        "gist_box_decompress|gist_box_penalty|gist_box_picksplit|gist_box_same|gist_box_union|" +
+        "gist_circle_compress|gist_circle_consistent|gist_point_compress|" +
+        "gist_point_consistent|gist_point_distance|gist_poly_compress|gist_poly_consistent|" +
+        "gistbeginscan|gistbuild|gistbuildempty|gistbulkdelete|gistcostestimate|gistendscan|" +
+        "gistgetbitmap|gistgettuple|gistinsert|gistmarkpos|gistoptions|gistrescan|gistrestrpos|" +
+        "gistvacuumcleanup|gtsquery_compress|gtsquery_consistent|gtsquery_decompress|" +
+        "gtsquery_penalty|gtsquery_picksplit|gtsquery_same|gtsquery_union|gtsvector_compress|" +
+        "gtsvector_consistent|gtsvector_decompress|gtsvector_penalty|gtsvector_picksplit|" +
+        "gtsvector_same|gtsvector_union|gtsvectorin|gtsvectorout|has_any_column_privilege|" +
+        "has_column_privilege|has_database_privilege|has_foreign_data_wrapper_privilege|" +
+        "has_function_privilege|has_language_privilege|has_schema_privilege|" +
+        "has_sequence_privilege|has_server_privilege|has_table_privilege|" +
+        "has_tablespace_privilege|hash_aclitem|hash_array|hash_numeric|hashbeginscan|" +
+        "hashbpchar|hashbuild|hashbuildempty|hashbulkdelete|hashchar|hashcostestimate|" +
+        "hashendscan|hashenum|hashfloat4|hashfloat8|hashgetbitmap|hashgettuple|hashinet|" +
+        "hashinsert|hashint2|hashint2vector|hashint4|hashint8|hashmacaddr|hashmarkpos|hashname|" +
+        "hashoid|hashoidvector|hashoptions|hashrescan|hashrestrpos|hashtext|hashvacuumcleanup|" +
+        "hashvarlena|height|host|hostmask|iclikejoinsel|iclikesel|icnlikejoinsel|icnlikesel|" +
+        "icregexeqjoinsel|icregexeqsel|icregexnejoinsel|icregexnesel|inet_client_addr|" +
+        "inet_client_port|inet_in|inet_out|inet_recv|inet_send|inet_server_addr|" +
+        "inet_server_port|inetand|inetmi|inetmi_int8|inetnot|inetor|inetpl|initcap|int2|int24div|" +
+        "int24eq|int24ge|int24gt|int24le|int24lt|int24mi|int24mul|int24ne|int24pl|int28div|int28eq|" +
+        "int28ge|int28gt|int28le|int28lt|int28mi|int28mul|int28ne|int28pl|int2_accum|" +
+        "int2_avg_accum|int2_mul_cash|int2_sum|int2abs|int2and|int2div|int2eq|int2ge|int2gt|int2in|" +
+        "int2larger|int2le|int2lt|int2mi|int2mod|int2mul|int2ne|int2not|int2or|int2out|int2pl|" +
+        "int2recv|int2send|int2shl|int2shr|int2smaller|int2um|int2up|int2vectoreq|int2vectorin|" +
+        "int2vectorout|int2vectorrecv|int2vectorsend|int2xor|int4|int42div|int42eq|int42ge|" +
+        "int42gt|int42le|int42lt|int42mi|int42mul|int42ne|int42pl|int48div|int48eq|int48ge|int48gt|" +
+        "int48le|int48lt|int48mi|int48mul|int48ne|int48pl|int4_accum|int4_avg_accum|int4_mul_cash|" +
+        "int4_sum|int4abs|int4and|int4div|int4eq|int4ge|int4gt|int4in|int4inc|int4larger|int4le|" +
+        "int4lt|int4mi|int4mod|int4mul|int4ne|int4not|int4or|int4out|int4pl|int4recv|int4send|" +
+        "int4shl|int4shr|int4smaller|int4um|int4up|int4xor|int8|int82div|int82eq|int82ge|int82gt|" +
+        "int82le|int82lt|int82mi|int82mul|int82ne|int82pl|int84div|int84eq|int84ge|int84gt|int84le|" +
+        "int84lt|int84mi|int84mul|int84ne|int84pl|int8_accum|int8_avg|int8_avg_accum|int8_sum|" +
+        "int8abs|int8and|int8div|int8eq|int8ge|int8gt|int8in|int8inc|int8inc_any|" +
+        "int8inc_float8_float8|int8larger|int8le|int8lt|int8mi|int8mod|int8mul|int8ne|int8not|" +
+        "int8or|int8out|int8pl|int8pl_inet|int8recv|int8send|int8shl|int8shr|int8smaller|int8um|" +
+        "int8up|int8xor|integer_pl_date|inter_lb|inter_sb|inter_sl|internal_in|internal_out|" +
+        "interval_accum|interval_avg|interval_cmp|interval_div|interval_eq|interval_ge|" +
+        "interval_gt|interval_hash|interval_in|interval_larger|interval_le|interval_lt|" +
+        "interval_mi|interval_mul|interval_ne|interval_out|interval_pl|interval_pl_date|" +
+        "interval_pl_time|interval_pl_timestamp|interval_pl_timestamptz|interval_pl_timetz|" +
+        "interval_recv|interval_send|interval_smaller|interval_um|intervaltypmodin|" +
+        "intervaltypmodout|intinterval|isclosed|isfinite|ishorizontal|iso8859_1_to_utf8|" +
+        "iso8859_to_utf8|iso_to_koi8r|iso_to_mic|iso_to_win1251|iso_to_win866|isopen|isparallel|" +
+        "isperp|isvertical|johab_to_utf8|justify_days|justify_hours|justify_interval|" +
+        "koi8r_to_iso|koi8r_to_mic|koi8r_to_utf8|koi8r_to_win1251|koi8r_to_win866|" +
+        "koi8u_to_utf8|lag|language_handler_in|language_handler_out|last_value|lastval|" +
+        "latin1_to_mic|latin2_to_mic|latin2_to_win1250|latin3_to_mic|latin4_to_mic|lead|left|" +
+        "length|like|like_escape|likejoinsel|likesel|line|line_distance|line_eq|line_horizontal|" +
+        "line_in|line_interpt|line_intersect|line_out|line_parallel|line_perp|line_recv|" +
+        "line_send|line_vertical|ln|lo_close|lo_creat|lo_create|lo_export|lo_import|lo_lseek|" +
+        "lo_open|lo_tell|lo_truncate|lo_unlink|log|loread|lower|lowrite|lpad|lseg|lseg_center|" +
+        "lseg_distance|lseg_eq|lseg_ge|lseg_gt|lseg_horizontal|lseg_in|lseg_interpt|" +
+        "lseg_intersect|lseg_le|lseg_length|lseg_lt|lseg_ne|lseg_out|lseg_parallel|lseg_perp|" +
+        "lseg_recv|lseg_send|lseg_vertical|ltrim|macaddr_cmp|macaddr_eq|macaddr_ge|macaddr_gt|" +
+        "macaddr_in|macaddr_le|macaddr_lt|macaddr_ne|macaddr_out|macaddr_recv|macaddr_send|" +
+        "makeaclitem|masklen|max|md5|mic_to_ascii|mic_to_big5|mic_to_euc_cn|mic_to_euc_jp|" +
+        "mic_to_euc_kr|mic_to_euc_tw|mic_to_iso|mic_to_koi8r|mic_to_latin1|mic_to_latin2|" +
+        "mic_to_latin3|mic_to_latin4|mic_to_sjis|mic_to_win1250|mic_to_win1251|mic_to_win866|" +
+        "min|mktinterval|mod|money|mul_d_interval|name|nameeq|namege|namegt|nameiclike|nameicnlike|" +
+        "nameicregexeq|nameicregexne|namein|namele|namelike|namelt|namene|namenlike|nameout|" +
+        "namerecv|nameregexeq|nameregexne|namesend|neqjoinsel|neqsel|netmask|network|network_cmp|" +
+        "network_eq|network_ge|network_gt|network_le|network_lt|network_ne|network_sub|" +
+        "network_subeq|network_sup|network_supeq|nextval|nlikejoinsel|nlikesel|notlike|now|" +
+        "npoints|nth_value|ntile|numeric_abs|numeric_accum|numeric_add|numeric_avg|" +
+        "numeric_avg_accum|numeric_cmp|numeric_div|numeric_div_trunc|numeric_eq|numeric_exp|" +
+        "numeric_fac|numeric_ge|numeric_gt|numeric_in|numeric_inc|numeric_larger|numeric_le|" +
+        "numeric_ln|numeric_log|numeric_lt|numeric_mod|numeric_mul|numeric_ne|numeric_out|" +
+        "numeric_power|numeric_recv|numeric_send|numeric_smaller|numeric_sqrt|" +
+        "numeric_stddev_pop|numeric_stddev_samp|numeric_sub|numeric_uminus|numeric_uplus|" +
+        "numeric_var_pop|numeric_var_samp|numerictypmodin|numerictypmodout|numnode|" +
+        "obj_description|octet_length|oid|oideq|oidge|oidgt|oidin|oidlarger|oidle|oidlt|oidne|oidout|" +
+        "oidrecv|oidsend|oidsmaller|oidvectoreq|oidvectorge|oidvectorgt|oidvectorin|oidvectorle|" +
+        "oidvectorlt|oidvectorne|oidvectorout|oidvectorrecv|oidvectorsend|oidvectortypes|on_pb|" +
+        "on_pl|on_ppath|on_ps|on_sb|on_sl|opaque_in|opaque_out|overlaps|overlay|path|path_add|" +
+        "path_add_pt|path_center|path_contain_pt|path_distance|path_div_pt|path_in|path_inter|" +
+        "path_length|path_mul_pt|path_n_eq|path_n_ge|path_n_gt|path_n_le|path_n_lt|path_npoints|" +
+        "path_out|path_recv|path_send|path_sub_pt|pclose|percent_rank|pg_advisory_lock|" +
+        "pg_advisory_lock_shared|pg_advisory_unlock|pg_advisory_unlock_all|" +
+        "pg_advisory_unlock_shared|pg_advisory_xact_lock|pg_advisory_xact_lock_shared|" +
+        "pg_available_extension_versions|pg_available_extensions|pg_backend_pid|" +
+        "pg_cancel_backend|pg_char_to_encoding|pg_client_encoding|pg_collation_is_visible|" +
+        "pg_column_size|pg_conf_load_time|pg_conversion_is_visible|pg_create_restore_point|" +
+        "pg_current_xlog_insert_location|pg_current_xlog_location|pg_cursor|pg_database_size|" +
+        "pg_describe_object|pg_encoding_max_length|pg_encoding_to_char|" +
+        "pg_extension_config_dump|pg_extension_update_paths|pg_function_is_visible|" +
+        "pg_get_constraintdef|pg_get_expr|pg_get_function_arguments|" +
+        "pg_get_function_identity_arguments|pg_get_function_result|pg_get_functiondef|" +
+        "pg_get_indexdef|pg_get_keywords|pg_get_ruledef|pg_get_serial_sequence|" +
+        "pg_get_triggerdef|pg_get_userbyid|pg_get_viewdef|pg_has_role|pg_indexes_size|" +
+        "pg_is_in_recovery|pg_is_other_temp_schema|pg_is_xlog_replay_paused|" +
+        "pg_last_xact_replay_timestamp|pg_last_xlog_receive_location|" +
+        "pg_last_xlog_replay_location|pg_listening_channels|pg_lock_status|pg_ls_dir|" +
+        "pg_my_temp_schema|pg_node_tree_in|pg_node_tree_out|pg_node_tree_recv|" +
+        "pg_node_tree_send|pg_notify|pg_opclass_is_visible|pg_operator_is_visible|" +
+        "pg_options_to_table|pg_postmaster_start_time|pg_prepared_statement|pg_prepared_xact|" +
+        "pg_read_binary_file|pg_read_file|pg_relation_filenode|pg_relation_filepath|" +
+        "pg_relation_size|pg_reload_conf|pg_rotate_logfile|pg_sequence_parameters|" +
+        "pg_show_all_settings|pg_size_pretty|pg_sleep|pg_start_backup|pg_stat_clear_snapshot|" +
+        "pg_stat_file|pg_stat_get_activity|pg_stat_get_analyze_count|" +
+        "pg_stat_get_autoanalyze_count|pg_stat_get_autovacuum_count|" +
+        "pg_stat_get_backend_activity|pg_stat_get_backend_activity_start|" +
+        "pg_stat_get_backend_client_addr|pg_stat_get_backend_client_port|" +
+        "pg_stat_get_backend_dbid|pg_stat_get_backend_idset|pg_stat_get_backend_pid|" +
+        "pg_stat_get_backend_start|pg_stat_get_backend_userid|pg_stat_get_backend_waiting|" +
+        "pg_stat_get_backend_xact_start|pg_stat_get_bgwriter_buf_written_checkpoints|" +
+        "pg_stat_get_bgwriter_buf_written_clean|pg_stat_get_bgwriter_maxwritten_clean|" +
+        "pg_stat_get_bgwriter_requested_checkpoints|pg_stat_get_bgwriter_stat_reset_time|" +
+        "pg_stat_get_bgwriter_timed_checkpoints|pg_stat_get_blocks_fetched|" +
+        "pg_stat_get_blocks_hit|pg_stat_get_buf_alloc|pg_stat_get_buf_fsync_backend|" +
+        "pg_stat_get_buf_written_backend|pg_stat_get_db_blocks_fetched|" +
+        "pg_stat_get_db_blocks_hit|pg_stat_get_db_conflict_all|" +
+        "pg_stat_get_db_conflict_bufferpin|pg_stat_get_db_conflict_lock|" +
+        "pg_stat_get_db_conflict_snapshot|pg_stat_get_db_conflict_startup_deadlock|" +
+        "pg_stat_get_db_conflict_tablespace|pg_stat_get_db_numbackends|" +
+        "pg_stat_get_db_stat_reset_time|pg_stat_get_db_tuples_deleted|" +
+        "pg_stat_get_db_tuples_fetched|pg_stat_get_db_tuples_inserted|" +
+        "pg_stat_get_db_tuples_returned|pg_stat_get_db_tuples_updated|" +
+        "pg_stat_get_db_xact_commit|pg_stat_get_db_xact_rollback|pg_stat_get_dead_tuples|" +
+        "pg_stat_get_function_calls|pg_stat_get_function_self_time|" +
+        "pg_stat_get_function_time|pg_stat_get_last_analyze_time|" +
+        "pg_stat_get_last_autoanalyze_time|pg_stat_get_last_autovacuum_time|" +
+        "pg_stat_get_last_vacuum_time|pg_stat_get_live_tuples|pg_stat_get_numscans|" +
+        "pg_stat_get_tuples_deleted|pg_stat_get_tuples_fetched|" +
+        "pg_stat_get_tuples_hot_updated|pg_stat_get_tuples_inserted|" +
+        "pg_stat_get_tuples_returned|pg_stat_get_tuples_updated|pg_stat_get_vacuum_count|" +
+        "pg_stat_get_wal_senders|pg_stat_get_xact_blocks_fetched|" +
+        "pg_stat_get_xact_blocks_hit|pg_stat_get_xact_function_calls|" +
+        "pg_stat_get_xact_function_self_time|pg_stat_get_xact_function_time|" +
+        "pg_stat_get_xact_numscans|pg_stat_get_xact_tuples_deleted|" +
+        "pg_stat_get_xact_tuples_fetched|pg_stat_get_xact_tuples_hot_updated|" +
+        "pg_stat_get_xact_tuples_inserted|pg_stat_get_xact_tuples_returned|" +
+        "pg_stat_get_xact_tuples_updated|pg_stat_reset|pg_stat_reset_shared|" +
+        "pg_stat_reset_single_function_counters|pg_stat_reset_single_table_counters|" +
+        "pg_stop_backup|pg_switch_xlog|pg_table_is_visible|pg_table_size|" +
+        "pg_tablespace_databases|pg_tablespace_size|pg_terminate_backend|pg_timezone_abbrevs|" +
+        "pg_timezone_names|pg_total_relation_size|pg_try_advisory_lock|" +
+        "pg_try_advisory_lock_shared|pg_try_advisory_xact_lock|" +
+        "pg_try_advisory_xact_lock_shared|pg_ts_config_is_visible|pg_ts_dict_is_visible|" +
+        "pg_ts_parser_is_visible|pg_ts_template_is_visible|pg_type_is_visible|pg_typeof|" +
+        "pg_xlog_replay_pause|pg_xlog_replay_resume|pg_xlogfile_name|pg_xlogfile_name_offset|" +
+        "pi|plainto_tsquery|plpgsql_call_handler|plpgsql_inline_handler|plpgsql_validator|" +
+        "point|point_above|point_add|point_below|point_distance|point_div|point_eq|point_horiz|" +
+        "point_in|point_left|point_mul|point_ne|point_out|point_recv|point_right|point_send|" +
+        "point_sub|point_vert|poly_above|poly_below|poly_center|poly_contain|poly_contain_pt|" +
+        "poly_contained|poly_distance|poly_in|poly_left|poly_npoints|poly_out|poly_overabove|" +
+        "poly_overbelow|poly_overlap|poly_overleft|poly_overright|poly_recv|poly_right|" +
+        "poly_same|poly_send|polygon|popen|position|positionjoinsel|positionsel|" +
+        "postgresql_fdw_validator|pow|power|prsd_end|prsd_headline|prsd_lextype|prsd_nexttoken|" +
+        "prsd_start|pt_contained_circle|pt_contained_poly|query_to_xml|" +
+        "query_to_xml_and_xmlschema|query_to_xmlschema|querytree|quote_ident|quote_literal|" +
+        "quote_nullable|radians|radius|random|rank|record_eq|record_ge|record_gt|record_in|" +
+        "record_le|record_lt|record_ne|record_out|record_recv|record_send|regclass|regclassin|" +
+        "regclassout|regclassrecv|regclasssend|regconfigin|regconfigout|regconfigrecv|" +
+        "regconfigsend|regdictionaryin|regdictionaryout|regdictionaryrecv|regdictionarysend|" +
+        "regexeqjoinsel|regexeqsel|regexnejoinsel|regexnesel|regexp_matches|regexp_replace|" +
+        "regexp_split_to_array|regexp_split_to_table|regoperatorin|regoperatorout|" +
+        "regoperatorrecv|regoperatorsend|regoperin|regoperout|regoperrecv|regopersend|" +
+        "regprocedurein|regprocedureout|regprocedurerecv|regproceduresend|regprocin|regprocout|" +
+        "regprocrecv|regprocsend|regr_avgx|regr_avgy|regr_count|regr_intercept|regr_r2|" +
+        "regr_slope|regr_sxx|regr_sxy|regr_syy|regtypein|regtypeout|regtyperecv|regtypesend|" +
+        "reltime|reltimeeq|reltimege|reltimegt|reltimein|reltimele|reltimelt|reltimene|reltimeout|" +
+        "reltimerecv|reltimesend|repeat|replace|reverse|right|round|row_number|rpad|rtrim|" +
+        "scalargtjoinsel|scalargtsel|scalarltjoinsel|scalarltsel|schema_to_xml|" +
+        "schema_to_xml_and_xmlschema|schema_to_xmlschema|session_user|set_bit|set_byte|" +
+        "set_config|set_masklen|setseed|setval|setweight|shell_in|shell_out|" +
+        "shift_jis_2004_to_euc_jis_2004|shift_jis_2004_to_utf8|shobj_description|sign|" +
+        "similar_escape|sin|sjis_to_euc_jp|sjis_to_mic|sjis_to_utf8|slope|smgreq|smgrin|smgrne|" +
+        "smgrout|split_part|sqrt|statement_timestamp|stddev|stddev_pop|stddev_samp|string_agg|" +
+        "string_agg_finalfn|string_agg_transfn|string_to_array|strip|strpos|substr|substring|sum|" +
+        "suppress_redundant_updates_trigger|table_to_xml|table_to_xml_and_xmlschema|" +
+        "table_to_xmlschema|tan|text|text_ge|text_gt|text_larger|text_le|text_lt|text_pattern_ge|" +
+        "text_pattern_gt|text_pattern_le|text_pattern_lt|text_smaller|textanycat|textcat|texteq|" +
+        "texticlike|texticnlike|texticregexeq|texticregexne|textin|textlen|textlike|textne|" +
+        "textnlike|textout|textrecv|textregexeq|textregexne|textsend|thesaurus_init|" +
+        "thesaurus_lexize|tideq|tidge|tidgt|tidin|tidlarger|tidle|tidlt|tidne|tidout|tidrecv|tidsend|" +
+        "tidsmaller|time_cmp|time_eq|time_ge|time_gt|time_hash|time_in|time_larger|time_le|time_lt|" +
+        "time_mi_interval|time_mi_time|time_ne|time_out|time_pl_interval|time_recv|time_send|" +
+        "time_smaller|timedate_pl|timemi|timenow|timeofday|timepl|timestamp_cmp|" +
+        "timestamp_cmp_date|timestamp_cmp_timestamptz|timestamp_eq|timestamp_eq_date|" +
+        "timestamp_eq_timestamptz|timestamp_ge|timestamp_ge_date|timestamp_ge_timestamptz|" +
+        "timestamp_gt|timestamp_gt_date|timestamp_gt_timestamptz|timestamp_hash|timestamp_in|" +
+        "timestamp_larger|timestamp_le|timestamp_le_date|timestamp_le_timestamptz|" +
+        "timestamp_lt|timestamp_lt_date|timestamp_lt_timestamptz|timestamp_mi|" +
+        "timestamp_mi_interval|timestamp_ne|timestamp_ne_date|timestamp_ne_timestamptz|" +
+        "timestamp_out|timestamp_pl_interval|timestamp_recv|timestamp_send|timestamp_smaller|" +
+        "timestamptypmodin|timestamptypmodout|timestamptz_cmp|timestamptz_cmp_date|" +
+        "timestamptz_cmp_timestamp|timestamptz_eq|timestamptz_eq_date|" +
+        "timestamptz_eq_timestamp|timestamptz_ge|timestamptz_ge_date|" +
+        "timestamptz_ge_timestamp|timestamptz_gt|timestamptz_gt_date|" +
+        "timestamptz_gt_timestamp|timestamptz_in|timestamptz_larger|timestamptz_le|" +
+        "timestamptz_le_date|timestamptz_le_timestamp|timestamptz_lt|timestamptz_lt_date|" +
+        "timestamptz_lt_timestamp|timestamptz_mi|timestamptz_mi_interval|timestamptz_ne|" +
+        "timestamptz_ne_date|timestamptz_ne_timestamp|timestamptz_out|" +
+        "timestamptz_pl_interval|timestamptz_recv|timestamptz_send|timestamptz_smaller|" +
+        "timestamptztypmodin|timestamptztypmodout|timetypmodin|timetypmodout|timetz_cmp|" +
+        "timetz_eq|timetz_ge|timetz_gt|timetz_hash|timetz_in|timetz_larger|timetz_le|timetz_lt|" +
+        "timetz_mi_interval|timetz_ne|timetz_out|timetz_pl_interval|timetz_recv|timetz_send|" +
+        "timetz_smaller|timetzdate_pl|timetztypmodin|timetztypmodout|timezone|tinterval|" +
+        "tintervalct|tintervalend|tintervaleq|tintervalge|tintervalgt|tintervalin|tintervalle|" +
+        "tintervalleneq|tintervallenge|tintervallengt|tintervallenle|tintervallenlt|" +
+        "tintervallenne|tintervallt|tintervalne|tintervalout|tintervalov|tintervalrecv|" +
+        "tintervalrel|tintervalsame|tintervalsend|tintervalstart|to_ascii|to_char|to_date|to_hex|" +
+        "to_number|to_timestamp|to_tsquery|to_tsvector|transaction_timestamp|translate|" +
+        "trigger_in|trigger_out|trunc|ts_debug|ts_headline|ts_lexize|ts_match_qv|ts_match_tq|" +
+        "ts_match_tt|ts_match_vq|ts_parse|ts_rank|ts_rank_cd|ts_rewrite|ts_stat|ts_token_type|" +
+        "ts_typanalyze|tsmatchjoinsel|tsmatchsel|tsq_mcontained|tsq_mcontains|tsquery_and|" +
+        "tsquery_cmp|tsquery_eq|tsquery_ge|tsquery_gt|tsquery_le|tsquery_lt|tsquery_ne|" +
+        "tsquery_not|tsquery_or|tsqueryin|tsqueryout|tsqueryrecv|tsquerysend|tsvector_cmp|" +
+        "tsvector_concat|tsvector_eq|tsvector_ge|tsvector_gt|tsvector_le|tsvector_lt|" +
+        "tsvector_ne|tsvector_update_trigger|tsvector_update_trigger_column|tsvectorin|" +
+        "tsvectorout|tsvectorrecv|tsvectorsend|txid_current|txid_current_snapshot|" +
+        "txid_snapshot_in|txid_snapshot_out|txid_snapshot_recv|txid_snapshot_send|" +
+        "txid_snapshot_xip|txid_snapshot_xmax|txid_snapshot_xmin|txid_visible_in_snapshot|" +
+        "uhc_to_utf8|unique_key_recheck|unknownin|unknownout|unknownrecv|unknownsend|unnest|" +
+        "upper|utf8_to_ascii|utf8_to_big5|utf8_to_euc_cn|utf8_to_euc_jis_2004|utf8_to_euc_jp|" +
+        "utf8_to_euc_kr|utf8_to_euc_tw|utf8_to_gb18030|utf8_to_gbk|utf8_to_iso8859|" +
+        "utf8_to_iso8859_1|utf8_to_johab|utf8_to_koi8r|utf8_to_koi8u|utf8_to_shift_jis_2004|" +
+        "utf8_to_sjis|utf8_to_uhc|utf8_to_win|uuid_cmp|uuid_eq|uuid_ge|uuid_gt|uuid_hash|uuid_in|" +
+        "uuid_le|uuid_lt|uuid_ne|uuid_out|uuid_recv|uuid_send|var_pop|var_samp|varbit_in|" +
+        "varbit_out|varbit_recv|varbit_send|varbitcmp|varbiteq|varbitge|varbitgt|varbitle|" +
+        "varbitlt|varbitne|varbittypmodin|varbittypmodout|varcharin|varcharout|varcharrecv|" +
+        "varcharsend|varchartypmodin|varchartypmodout|variance|version|void_in|void_out|" +
+        "void_recv|void_send|width|width_bucket|win1250_to_latin2|win1250_to_mic|win1251_to_iso|" +
+        "win1251_to_koi8r|win1251_to_mic|win1251_to_win866|win866_to_iso|win866_to_koi8r|" +
+        "win866_to_mic|win866_to_win1251|win_to_utf8|xideq|xideqint4|xidin|xidout|xidrecv|xidsend|" +
+        "xml|xml_in|xml_is_well_formed|xml_is_well_formed_content|xml_is_well_formed_document|" +
+        "xml_out|xml_recv|xml_send|xmlagg|xmlcomment|xmlconcat2|xmlexists|xmlvalidate|xpath|" +
+        "xpath_exists").split("|")
+    );
+    
+    var sqlRules = [
+        {
+            token : "string", // single line string -- assume dollar strings if multi-line for now
+            regex : "['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"
+        }, {
+            token : "variable.language", // pg identifier
+            regex : '".*?"'
+        }, {
+            token : "constant.numeric", // float
+            regex : "[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"
+        }, {
+            token : function(value) {
+                value = value.toLowerCase();
+                if (keywords.hasOwnProperty(value)) {
+                    return "keyword";
+                } else if (builtinFunctions.hasOwnProperty(value)) {
+                    return "support.function";
+                } else {
+                    return "identifier";
+                }
+              },
+              regex : "[a-zA-Z_][a-zA-Z0-9_$]*\\b" // TODO - Unicode in identifiers
+          }, {
+              token : "keyword.operator",
+              regex : "!|!!|!~|!~\\*|!~~|!~~\\*|#|##|#<|#<=|#<>|#=|#>|#>=|%|\\&|\\&\\&|\\&<|\\&<\\||\\&>|\\*|\\+|" +
+                      "\\-|/|<|<#>|<\\->|<<|<<=|<<\\||<=|<>|<\\?>|<@|<\\^|=|>|>=|>>|>>=|>\\^|\\?#|\\?\\-|\\?\\-\\||" +
+                      "\\?\\||\\?\\|\\||@|@\\-@|@>|@@|@@@|\\^|\\||\\|\\&>|\\|/|\\|>>|\\|\\||\\|\\|/|~|~\\*|~<=~|~<~|" +
+                      "~=|~>=~|~>~|~~|~~\\*"
+          }, {
+              token : "lparen.paren",
+              regex : "[\\(]"
+          }, {
+              token : "paren.rparen",
+              regex : "[\\)]"
+          }, {
+              token : "text",
+              regex : "\\s+"
+          }
+    ];
+           
+
+    this.$rules = {
+        "start" : [
+            {
+                token : "comment",
+                regex : "--.*$"
+            }, 
+            new DocCommentHighlightRules().getStartRule("doc-start"),
+            {
+                token : "comment", // multi-line comment
+                merge : true,
+                regex : "\\/\\*",
+                next : "comment"
+            },{
+                token : "keyword.statementBegin",
+                regex : "^[a-zA-Z]+", // Could enumerate starting keywords but this allows things to work when new statements are added.
+                next : "statement"
+            },{
+                token : "support.buildin", // psql directive
+                regex : "^\\\\[\\S]+.*$"
+            }
+        ],
+        
+        "statement" : [
+            {
+                token : "comment",
+                regex : "--.*$"
+            }, {
+                token : "comment", // multi-line comment
+                merge : true,
+                regex : "\\/\\*",
+                next : "commentStatement"
+            }, {
+                token : "statementEnd",
+                regex : ";",
+                next : "start"
+            }, {
+                token : "string", // perl, python, tcl are in the pg default dist (no tcl highlighter)
+                regex : "\\$perl\\$",
+                next : "perl-start"
+            }, {
+                token : "string",
+                regex : "\\$python\\$",
+                next : "python-start"
+            },{
+                token : "string",
+                regex : "\\$[\\w_0-9]*\\$$", // dollar quote at the end of a line
+                next : "dollarSql"
+            }, {
+                token : "string",
+                regex : "\\$[\\w_0-9]*\\$",
+                next : "dollarStatementString"
+            }
+        ].concat(sqlRules),
+        
+        "dollarSql" : [
+            {
+                token : "comment",
+                regex : "--.*$"
+            }, {
+                token : "comment", // multi-line comment
+                merge : true,
+                regex : "\\/\\*",
+                next : "commentDollarSql"
+            }, {
+                token : "string", // end quoting with dollar at the start of a line
+                regex : "^\\$[\\w_0-9]*\\$",
+                next : "statement"
+            }, {
+                token : "string",
+                regex : "\\$[\\w_0-9]*\\$",
+                next : "dollarSqlString"
+            }
+        ].concat(sqlRules),
+        
+        "comment" : [
+            {
+                token : "comment", // closing comment
+                regex : ".*?\\*\\/",
+                next : "start"
+            }, {
+                token : "comment", // comment spanning whole line
+                merge : true,
+                regex : ".+"
+            }
+        ],
+        
+        "commentStatement" : [
+            {
+                token : "comment", // closing comment
+                regex : ".*?\\*\\/",
+                next : "statement"
+            }, {
+                token : "comment", // comment spanning whole line
+                merge : true,
+                regex : ".+"
+            }
+        ],
+        
+        "commentDollarSql" : [
+            {
+                token : "comment", // closing comment
+                regex : ".*?\\*\\/",
+                next : "dollarSql"
+            }, {
+                token : "comment", // comment spanning whole line
+                merge : true,
+                regex : ".+"
+            }
+        ],
+        
+        "dollarStatementString" : [
+            {
+                token : "string", // closing dollarstring
+                regex : ".*?\\$[\\w_0-9]*\\$",
+                next : "statement"
+            }, {
+                token : "string", // dollarstring spanning whole line
+                merge : true,
+                regex : ".+"
+            }
+        ],
+        
+        "dollarSqlString" : [
+            {
+                token : "string", // closing dollarstring
+                regex : ".*?\\$[\\w_0-9]*\\$",
+                next : "dollarSql"
+            }, {
+                token : "string", // dollarstring spanning whole line
+                merge : true,
+                regex : ".+"
+            }
+        ]
+    };
+    
+    this.embedRules(DocCommentHighlightRules, "doc-", [ new DocCommentHighlightRules().getEndRule("start") ]);
+    this.embedRules(PerlHighlightRules, "perl-", [{token : "string", regex : "\\$perl\\$", next : "statement"}]);
+    this.embedRules(PythonHighlightRules, "python-", [{token : "string", regex : "\\$python\\$", next : "statement"}]);
+};
+
+oop.inherits(PgsqlHighlightRules, TextHighlightRules);
+
+exports.PgsqlHighlightRules = PgsqlHighlightRules;
+});
+
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Ajax.org Code Editor (ACE).
+ *
+ * The Initial Developer of the Original Code is
+ * Ajax.org B.V.
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *      Fabian Jakobs <fabian AT ajax DOT org>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+define('ace/mode/doc_comment_highlight_rules', ['require', 'exports', 'module' , 'ace/lib/oop', 'ace/mode/text_highlight_rules'], function(require, exports, module) {
+"use strict";
+
+var oop = require("../lib/oop");
+var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
+
+var DocCommentHighlightRules = function() {
+
+    this.$rules = {
+        "start" : [ {
+            token : "comment.doc.tag",
+            regex : "@[\\w\\d_]+" // TODO: fix email addresses
+        }, {
+            token : "comment.doc",
+            merge : true,
+            regex : "\\s+"
+        }, {
+            token : "comment.doc",
+            merge : true,
+            regex : "TODO"
+        }, {
+            token : "comment.doc",
+            merge : true,
+            regex : "[^@\\*]+"
+        }, {
+            token : "comment.doc",
+            merge : true,
+            regex : "."
+        }]
+    };
+};
+
+oop.inherits(DocCommentHighlightRules, TextHighlightRules);
+
+(function() {
+
+    this.getStartRule = function(start) {
+        return {
+            token : "comment.doc", // doc comment
+            merge : true,
+            regex : "\\/\\*(?=\\*)",
+            next  : start
+        };
+    };
+    
+    this.getEndRule = function (start) {
+        return {
+            token : "comment.doc", // closing comment
+            merge : true,
+            regex : "\\*\\/",
+            next  : start
+        };
+    };
+
+}).call(DocCommentHighlightRules.prototype);
+
+exports.DocCommentHighlightRules = DocCommentHighlightRules;
+
+});
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Ajax.org Code Editor (ACE).
+ *
+ * The Initial Developer of the Original Code is
+ * Ajax.org B.V.
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *      Panagiotis Astithas <pastith AT gmail DOT com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+define('ace/mode/perl_highlight_rules', ['require', 'exports', 'module' , 'ace/lib/oop', 'ace/lib/lang', 'ace/mode/text_highlight_rules'], function(require, exports, module) {
+"use strict";
+
+var oop = require("../lib/oop");
+var lang = require("../lib/lang");
+var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
+
+var PerlHighlightRules = function() {
+
+    var keywords = lang.arrayToMap(
+        ("base|constant|continue|else|elsif|for|foreach|format|goto|if|last|local|my|next|" +
+         "no|package|parent|redo|require|scalar|sub|unless|until|while|use|vars").split("|")
+    );
+
+    var buildinConstants = lang.arrayToMap(
+        ("ARGV|ENV|INC|SIG").split("|")
+    );
+
+    var builtinFunctions = lang.arrayToMap(
+        ("getprotobynumber|getprotobyname|getservbyname|gethostbyaddr|" +
+         "gethostbyname|getservbyport|getnetbyaddr|getnetbyname|getsockname|" +
+         "getpeername|setpriority|getprotoent|setprotoent|getpriority|" +
+         "endprotoent|getservent|setservent|endservent|sethostent|socketpair|" +
+         "getsockopt|gethostent|endhostent|setsockopt|setnetent|quotemeta|" +
+         "localtime|prototype|getnetent|endnetent|rewinddir|wantarray|getpwuid|" +
+         "closedir|getlogin|readlink|endgrent|getgrgid|getgrnam|shmwrite|" +
+         "shutdown|readline|endpwent|setgrent|readpipe|formline|truncate|" +
+         "dbmclose|syswrite|setpwent|getpwnam|getgrent|getpwent|ucfirst|sysread|" +
+         "setpgrp|shmread|sysseek|sysopen|telldir|defined|opendir|connect|" +
+         "lcfirst|getppid|binmode|syscall|sprintf|getpgrp|readdir|seekdir|" +
+         "waitpid|reverse|unshift|symlink|dbmopen|semget|msgrcv|rename|listen|" +
+         "chroot|msgsnd|shmctl|accept|unpack|exists|fileno|shmget|system|" +
+         "unlink|printf|gmtime|msgctl|semctl|values|rindex|substr|splice|" +
+         "length|msgget|select|socket|return|caller|delete|alarm|ioctl|index|" +
+         "undef|lstat|times|srand|chown|fcntl|close|write|umask|rmdir|study|" +
+         "sleep|chomp|untie|print|utime|mkdir|atan2|split|crypt|flock|chmod|" +
+         "BEGIN|bless|chdir|semop|shift|reset|link|stat|chop|grep|fork|dump|" +
+         "join|open|tell|pipe|exit|glob|warn|each|bind|sort|pack|eval|push|" +
+         "keys|getc|kill|seek|sqrt|send|wait|rand|tied|read|time|exec|recv|" +
+         "eof|chr|int|ord|exp|pos|pop|sin|log|abs|oct|hex|tie|cos|vec|END|ref|" +
+         "map|die|uc|lc|do").split("|")
+    );
+
+    // regexp must not have capturing parentheses. Use (?:) instead.
+    // regexps are ordered -> the first match is used
+
+    this.$rules = {
+        "start" : [
+            {
+                token : "comment",
+                regex : "#.*$"
+            }, {
+                token : "string.regexp",
+                regex : "[/](?:(?:\\[(?:\\\\]|[^\\]])+\\])|(?:\\\\/|[^\\]/]))*[/]\\w*\\s*(?=[).,;]|$)"
+            }, {
+                token : "string", // single line
+                regex : '["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'
+            }, {
+                token : "string", // multi line string start
+                merge : true,
+                regex : '["].*\\\\$',
+                next : "qqstring"
+            }, {
+                token : "string", // single line
+                regex : "['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"
+            }, {
+                token : "string", // multi line string start
+                merge : true,
+                regex : "['].*\\\\$",
+                next : "qstring"
+            }, {
+                token : "constant.numeric", // hex
+                regex : "0x[0-9a-fA-F]+\\b"
+            }, {
+                token : "constant.numeric", // float
+                regex : "[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"
+            }, {
+                token : function(value) {
+                    if (keywords.hasOwnProperty(value))
+                        return "keyword";
+                    else if (buildinConstants.hasOwnProperty(value))
+                        return "constant.language";
+                    else if (builtinFunctions.hasOwnProperty(value))
+                        return "support.function";
+                    else
+                        return "identifier";
+                },
+                regex : "[a-zA-Z_$][a-zA-Z0-9_$]*\\b"
+            }, {
+                token : "keyword.operator",
+                regex : "\\.\\.\\.|\\|\\|=|>>=|<<=|<=>|&&=|=>|!~|\\^=|&=|\\|=|\\.=|x=|%=|\\/=|\\*=|\\-=|\\+=|=~|\\*\\*|\\-\\-|\\.\\.|\\|\\||&&|\\+\\+|\\->|!=|==|>=|<=|>>|<<|,|=|\\?\\:|\\^|\\||x|%|\\/|\\*|<|&|\\\\|~|!|>|\\.|\\-|\\+|\\-C|\\-b|\\-S|\\-u|\\-t|\\-p|\\-l|\\-d|\\-f|\\-g|\\-s|\\-z|\\-k|\\-e|\\-O|\\-T|\\-B|\\-M|\\-A|\\-X|\\-W|\\-c|\\-R|\\-o|\\-x|\\-w|\\-r|\\b(?:and|cmp|eq|ge|gt|le|lt|ne|not|or|xor)"
+            }, {
+                token : "lparen",
+                regex : "[[({]"
+            }, {
+                token : "rparen",
+                regex : "[\\])}]"
+            }, {
+                token : "text",
+                regex : "\\s+"
+            }
+        ],
+        "qqstring" : [
+            {
+                token : "string",
+                regex : '(?:(?:\\\\.)|(?:[^"\\\\]))*?"',
+                next : "start"
+            }, {
+                token : "string",
+                merge : true,
+                regex : '.+'
+            }
+        ],
+        "qstring" : [
+            {
+                token : "string",
+                regex : "(?:(?:\\\\.)|(?:[^'\\\\]))*?'",
+                next : "start"
+            }, {
+                token : "string",
+                merge : true,
+                regex : '.+'
+            }
+        ]
+    };
+};
+
+oop.inherits(PerlHighlightRules, TextHighlightRules);
+
+exports.PerlHighlightRules = PerlHighlightRules;
+});
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Ajax.org Code Editor (ACE).
+ *
+ * The Initial Developer of the Original Code is
+ * Ajax.org B.V.
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *      Fabian Jakobs <fabian AT ajax DOT org>
+ *      Colin Gourlay <colin DOT j DOT gourlay AT gmail DOT com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK *****
+ *
+ * TODO: python delimiters
+ */
+
+define('ace/mode/python_highlight_rules', ['require', 'exports', 'module' , 'ace/lib/oop', 'ace/lib/lang', 'ace/mode/text_highlight_rules'], function(require, exports, module) {
+"use strict";
+
+var oop = require("../lib/oop");
+var lang = require("../lib/lang");
+var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
+
+var PythonHighlightRules = function() {
+
+    var keywords = lang.arrayToMap(
+        ("and|as|assert|break|class|continue|def|del|elif|else|except|exec|" +
+        "finally|for|from|global|if|import|in|is|lambda|not|or|pass|print|" +
+        "raise|return|try|while|with|yield").split("|")
+    );
+
+    var builtinConstants = lang.arrayToMap(
+        ("True|False|None|NotImplemented|Ellipsis|__debug__").split("|")
+    );
+
+    var builtinFunctions = lang.arrayToMap(
+        ("abs|divmod|input|open|staticmethod|all|enumerate|int|ord|str|any|" +
+        "eval|isinstance|pow|sum|basestring|execfile|issubclass|print|super|" +
+        "binfile|iter|property|tuple|bool|filter|len|range|type|bytearray|" +
+        "float|list|raw_input|unichr|callable|format|locals|reduce|unicode|" +
+        "chr|frozenset|long|reload|vars|classmethod|getattr|map|repr|xrange|" +
+        "cmp|globals|max|reversed|zip|compile|hasattr|memoryview|round|" +
+        "__import__|complex|hash|min|set|apply|delattr|help|next|setattr|" +
+        "buffer|dict|hex|object|slice|coerce|dir|id|oct|sorted|intern").split("|")
+    );
+
+    var futureReserved = lang.arrayToMap(
+        ("").split("|")
+    );
+
+    var strPre = "(?:r|u|ur|R|U|UR|Ur|uR)?";
+
+    var decimalInteger = "(?:(?:[1-9]\\d*)|(?:0))";
+    var octInteger = "(?:0[oO]?[0-7]+)";
+    var hexInteger = "(?:0[xX][\\dA-Fa-f]+)";
+    var binInteger = "(?:0[bB][01]+)";
+    var integer = "(?:" + decimalInteger + "|" + octInteger + "|" + hexInteger + "|" + binInteger + ")";
+
+    var exponent = "(?:[eE][+-]?\\d+)";
+    var fraction = "(?:\\.\\d+)";
+    var intPart = "(?:\\d+)";
+    var pointFloat = "(?:(?:" + intPart + "?" + fraction + ")|(?:" + intPart + "\\.))";
+    var exponentFloat = "(?:(?:" + pointFloat + "|" +  intPart + ")" + exponent + ")";
+    var floatNumber = "(?:" + exponentFloat + "|" + pointFloat + ")";
+
+    this.$rules = {
+        "start" : [ {
+            token : "comment",
+            regex : "#.*$"
+        }, {
+            token : "string",           // """ string
+            regex : strPre + '"{3}(?:[^\\\\]|\\\\.)*?"{3}'
+        }, {
+            token : "string",           // multi line """ string start
+            merge : true,
+            regex : strPre + '"{3}.*$',
+            next : "qqstring"
+        }, {
+            token : "string",           // " string
+            regex : strPre + '"(?:[^\\\\]|\\\\.)*?"'
+        }, {
+            token : "string",           // ''' string
+            regex : strPre + "'{3}(?:[^\\\\]|\\\\.)*?'{3}"
+        }, {
+            token : "string",           // multi line ''' string start
+            merge : true,
+            regex : strPre + "'{3}.*$",
+            next : "qstring"
+        }, {
+            token : "string",           // ' string
+            regex : strPre + "'(?:[^\\\\]|\\\\.)*?'"
+        }, {
+            token : "constant.numeric", // imaginary
+            regex : "(?:" + floatNumber + "|\\d+)[jJ]\\b"
+        }, {
+            token : "constant.numeric", // float
+            regex : floatNumber
+        }, {
+            token : "constant.numeric", // long integer
+            regex : integer + "[lL]\\b"
+        }, {
+            token : "constant.numeric", // integer
+            regex : integer + "\\b"
+        }, {
+            token : function(value) {
+                if (keywords.hasOwnProperty(value))
+                    return "keyword";
+                else if (builtinConstants.hasOwnProperty(value))
+                    return "constant.language";
+                else if (futureReserved.hasOwnProperty(value))
+                    return "invalid.illegal";
+                else if (builtinFunctions.hasOwnProperty(value))
+                    return "support.function";
+                else if (value == "debugger")
+                    return "invalid.deprecated";
+                else
+                    return "identifier";
+            },
+            regex : "[a-zA-Z_$][a-zA-Z0-9_$]*\\b"
+        }, {
+            token : "keyword.operator",
+            regex : "\\+|\\-|\\*|\\*\\*|\\/|\\/\\/|%|<<|>>|&|\\||\\^|~|<|>|<=|=>|==|!=|<>|="
+        }, {
+            token : "lparen.paren",
+            regex : "[\\[\\(\\{]"
+        }, {
+            token : "paren.rparen",
+            regex : "[\\]\\)\\}]"
+        }, {
+            token : "text",
+            regex : "\\s+"
+        } ],
+        "qqstring" : [ {
+            token : "string", // multi line """ string end
+            regex : '(?:[^\\\\]|\\\\.)*?"{3}',
+            next : "start"
+        }, {
+            token : "string",
+            merge : true,
+            regex : '.+'
+        } ],
+        "qstring" : [ {
+            token : "string",  // multi line ''' string end
+            regex : "(?:[^\\\\]|\\\\.)*?'{3}",
+            next : "start"
+        }, {
+            token : "string",
+            merge : true,
+            regex : '.+'
+        } ]
+    };
+};
+
+oop.inherits(PythonHighlightRules, TextHighlightRules);
+
+exports.PythonHighlightRules = PythonHighlightRules;
+});
diff --git a/apps/files_texteditor/js/aceeditor/mode-pgsql.js b/apps/files_texteditor/js/aceeditor/mode-pgsql.js
new file mode 100644
index 0000000000000000000000000000000000000000..12a02277af757c4fe4eca449e1b5bb9adea76d78
--- /dev/null
+++ b/apps/files_texteditor/js/aceeditor/mode-pgsql.js
@@ -0,0 +1 @@
+define("ace/mode/pgsql",["require","exports","module","ace/lib/oop","ace/mode/text","ace/tokenizer","ace/mode/pgsql_highlight_rules","ace/range"],function(a,b,c){var d=a("ace/lib/oop"),e=a("ace/mode/text").Mode,f=a("ace/tokenizer").Tokenizer,g=a("ace/mode/pgsql_highlight_rules").PgsqlHighlightRules,h=a("ace/range").Range,i=function(){this.$tokenizer=new f((new g).getRules())};d.inherits(i,e),function(){this.toggleCommentLines=function(a,b,c,d){var e=!0,f=/^(\s*)--/;for(var g=c;g<=d;g++)if(!f.test(b.getLine(g))){e=!1;break}if(e){var i=new h(0,0,0,0);for(var g=c;g<=d;g++){var j=b.getLine(g),k=j.match(f);i.start.row=g,i.end.row=g,i.end.column=k[0].length,b.replace(i,k[1])}}else b.indentRows(c,d,"--")},this.getNextLineIndent=function(a,b,c){return a=="start"||a=="keyword.statementEnd"?"":this.$getIndent(b)}}.call(i.prototype),b.Mode=i}),define("ace/mode/pgsql_highlight_rules",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/mode/doc_comment_highlight_rules","ace/mode/text_highlight_rules","ace/mode/perl_highlight_rules","ace/mode/python_highlight_rules"],function(a,b,c){var d=a("ace/lib/oop"),e=a("ace/lib/lang"),f=a("./doc_comment_highlight_rules").DocCommentHighlightRules,g=a("./text_highlight_rules").TextHighlightRules,h=a("./perl_highlight_rules").PerlHighlightRules,i=a("./python_highlight_rules").PythonHighlightRules,j=function(){var a=e.arrayToMap("abort|absolute|abstime|access|aclitem|action|add|admin|after|aggregate|all|also|alter|always|analyse|analyze|and|any|anyarray|anyelement|anyenum|anynonarray|array|as|asc|assertion|assignment|asymmetric|at|attribute|authorization|backward|before|begin|between|bigint|binary|bit|bool|boolean|both|box|bpchar|by|bytea|cache|called|cascade|cascaded|case|cast|catalog|chain|char|character|characteristics|check|checkpoint|cid|cidr|circle|class|close|cluster|coalesce|collate|collation|column|comment|comments|commit|committed|concurrently|configuration|connection|constraint|constraints|content|continue|conversion|copy|cost|create|cross|cstring|csv|current|current_catalog|current_date|current_role|current_schema|current_time|current_timestamp|current_user|cursor|cycle|data|database|date|day|deallocate|dec|decimal|declare|default|defaults|deferrable|deferred|definer|delete|delimiter|delimiters|desc|dictionary|disable|discard|distinct|do|document|domain|double|drop|each|else|enable|encoding|encrypted|end|enum|escape|except|exclude|excluding|exclusive|execute|exists|explain|extension|external|extract|false|family|fdw_handler|fetch|first|float|float4|float8|following|for|force|foreign|forward|freeze|from|full|function|functions|global|grant|granted|greatest|group|gtsvector|handler|having|header|hold|hour|identity|if|ilike|immediate|immutable|implicit|in|including|increment|index|indexes|inet|inherit|inherits|initially|inline|inner|inout|input|insensitive|insert|instead|int|int2|int2vector|int4|int8|integer|internal|intersect|interval|into|invoker|is|isnull|isolation|join|key|label|language|language_handler|large|last|lc_collate|lc_ctype|leading|least|left|level|like|limit|line|listen|load|local|localtime|localtimestamp|location|lock|lseg|macaddr|mapping|match|maxvalue|minute|minvalue|mode|money|month|move|name|names|national|natural|nchar|next|no|none|not|nothing|notify|notnull|nowait|null|nullif|nulls|numeric|object|of|off|offset|oid|oids|oidvector|on|only|opaque|operator|option|options|or|order|out|outer|over|overlaps|overlay|owned|owner|parser|partial|partition|passing|password|path|pg_attribute|pg_auth_members|pg_authid|pg_class|pg_database|pg_node_tree|pg_proc|pg_type|placing|plans|point|polygon|position|preceding|precision|prepare|prepared|preserve|primary|prior|privileges|procedural|procedure|quote|range|read|real|reassign|recheck|record|recursive|ref|refcursor|references|regclass|regconfig|regdictionary|regoper|regoperator|regproc|regprocedure|regtype|reindex|relative|release|reltime|rename|repeatable|replace|replica|reset|restart|restrict|returning|returns|revoke|right|role|rollback|row|rows|rule|savepoint|schema|scroll|search|second|security|select|sequence|sequences|serializable|server|session|session_user|set|setof|share|show|similar|simple|smallint|smgr|some|stable|standalone|start|statement|statistics|stdin|stdout|storage|strict|strip|substring|symmetric|sysid|system|table|tables|tablespace|temp|template|temporary|text|then|tid|time|timestamp|timestamptz|timetz|tinterval|to|trailing|transaction|treat|trigger|trim|true|truncate|trusted|tsquery|tsvector|txid_snapshot|type|unbounded|uncommitted|unencrypted|union|unique|unknown|unlisten|unlogged|until|update|user|using|uuid|vacuum|valid|validate|validator|value|values|varbit|varchar|variadic|varying|verbose|version|view|void|volatile|when|where|whitespace|window|with|without|work|wrapper|write|xid|xml|xmlattributes|xmlconcat|xmlelement|xmlexists|xmlforest|xmlparse|xmlpi|xmlroot|xmlserialize|year|yes|zone".split("|")),b=e.arrayToMap("RI_FKey_cascade_del|RI_FKey_cascade_upd|RI_FKey_check_ins|RI_FKey_check_upd|RI_FKey_noaction_del|RI_FKey_noaction_upd|RI_FKey_restrict_del|RI_FKey_restrict_upd|RI_FKey_setdefault_del|RI_FKey_setdefault_upd|RI_FKey_setnull_del|RI_FKey_setnull_upd|abbrev|abs|abstime|abstimeeq|abstimege|abstimegt|abstimein|abstimele|abstimelt|abstimene|abstimeout|abstimerecv|abstimesend|aclcontains|aclexplode|aclinsert|aclitemeq|aclitemin|aclitemout|aclremove|acos|age|any_in|any_out|anyarray_in|anyarray_out|anyarray_recv|anyarray_send|anyelement_in|anyelement_out|anyenum_in|anyenum_out|anynonarray_in|anynonarray_out|anytextcat|area|areajoinsel|areasel|array_agg|array_agg_finalfn|array_agg_transfn|array_append|array_cat|array_dims|array_eq|array_fill|array_ge|array_gt|array_in|array_larger|array_le|array_length|array_lower|array_lt|array_ndims|array_ne|array_out|array_prepend|array_recv|array_send|array_smaller|array_to_string|array_upper|arraycontained|arraycontains|arrayoverlap|ascii|ascii_to_mic|ascii_to_utf8|asin|atan|atan2|avg|big5_to_euc_tw|big5_to_mic|big5_to_utf8|bit_and|bit_in|bit_length|bit_or|bit_out|bit_recv|bit_send|bitand|bitcat|bitcmp|biteq|bitge|bitgt|bitle|bitlt|bitne|bitnot|bitor|bitshiftleft|bitshiftright|bittypmodin|bittypmodout|bitxor|bool|bool_and|bool_or|booland_statefunc|booleq|boolge|boolgt|boolin|boolle|boollt|boolne|boolor_statefunc|boolout|boolrecv|boolsend|box|box_above|box_above_eq|box_add|box_below|box_below_eq|box_center|box_contain|box_contain_pt|box_contained|box_distance|box_div|box_eq|box_ge|box_gt|box_in|box_intersect|box_le|box_left|box_lt|box_mul|box_out|box_overabove|box_overbelow|box_overlap|box_overleft|box_overright|box_recv|box_right|box_same|box_send|box_sub|bpchar_larger|bpchar_pattern_ge|bpchar_pattern_gt|bpchar_pattern_le|bpchar_pattern_lt|bpchar_smaller|bpcharcmp|bpchareq|bpcharge|bpchargt|bpchariclike|bpcharicnlike|bpcharicregexeq|bpcharicregexne|bpcharin|bpcharle|bpcharlike|bpcharlt|bpcharne|bpcharnlike|bpcharout|bpcharrecv|bpcharregexeq|bpcharregexne|bpcharsend|bpchartypmodin|bpchartypmodout|broadcast|btabstimecmp|btarraycmp|btbeginscan|btboolcmp|btbpchar_pattern_cmp|btbuild|btbuildempty|btbulkdelete|btcharcmp|btcostestimate|btendscan|btfloat48cmp|btfloat4cmp|btfloat84cmp|btfloat8cmp|btgetbitmap|btgettuple|btinsert|btint24cmp|btint28cmp|btint2cmp|btint42cmp|btint48cmp|btint4cmp|btint82cmp|btint84cmp|btint8cmp|btmarkpos|btnamecmp|btoidcmp|btoidvectorcmp|btoptions|btrecordcmp|btreltimecmp|btrescan|btrestrpos|btrim|bttext_pattern_cmp|bttextcmp|bttidcmp|bttintervalcmp|btvacuumcleanup|byteacat|byteacmp|byteaeq|byteage|byteagt|byteain|byteale|bytealike|bytealt|byteane|byteanlike|byteaout|bytearecv|byteasend|cash_cmp|cash_div_cash|cash_div_flt4|cash_div_flt8|cash_div_int2|cash_div_int4|cash_eq|cash_ge|cash_gt|cash_in|cash_le|cash_lt|cash_mi|cash_mul_flt4|cash_mul_flt8|cash_mul_int2|cash_mul_int4|cash_ne|cash_out|cash_pl|cash_recv|cash_send|cash_words|cashlarger|cashsmaller|cbrt|ceil|ceiling|center|char|char_length|character_length|chareq|charge|chargt|charin|charle|charlt|charne|charout|charrecv|charsend|chr|cideq|cidin|cidout|cidr|cidr_in|cidr_out|cidr_recv|cidr_send|cidrecv|cidsend|circle|circle_above|circle_add_pt|circle_below|circle_center|circle_contain|circle_contain_pt|circle_contained|circle_distance|circle_div_pt|circle_eq|circle_ge|circle_gt|circle_in|circle_le|circle_left|circle_lt|circle_mul_pt|circle_ne|circle_out|circle_overabove|circle_overbelow|circle_overlap|circle_overleft|circle_overright|circle_recv|circle_right|circle_same|circle_send|circle_sub_pt|clock_timestamp|close_lb|close_ls|close_lseg|close_pb|close_pl|close_ps|close_sb|close_sl|col_description|concat|concat_ws|contjoinsel|contsel|convert|convert_from|convert_to|corr|cos|cot|count|covar_pop|covar_samp|cstring_in|cstring_out|cstring_recv|cstring_send|cume_dist|current_database|current_query|current_schema|current_schemas|current_setting|current_user|currtid|currtid2|currval|cursor_to_xml|cursor_to_xmlschema|database_to_xml|database_to_xml_and_xmlschema|database_to_xmlschema|date|date_cmp|date_cmp_timestamp|date_cmp_timestamptz|date_eq|date_eq_timestamp|date_eq_timestamptz|date_ge|date_ge_timestamp|date_ge_timestamptz|date_gt|date_gt_timestamp|date_gt_timestamptz|date_in|date_larger|date_le|date_le_timestamp|date_le_timestamptz|date_lt|date_lt_timestamp|date_lt_timestamptz|date_mi|date_mi_interval|date_mii|date_ne|date_ne_timestamp|date_ne_timestamptz|date_out|date_part|date_pl_interval|date_pli|date_recv|date_send|date_smaller|date_trunc|datetime_pl|datetimetz_pl|dcbrt|decode|degrees|dense_rank|dexp|diagonal|diameter|dispell_init|dispell_lexize|dist_cpoly|dist_lb|dist_pb|dist_pc|dist_pl|dist_ppath|dist_ps|dist_sb|dist_sl|div|dlog1|dlog10|domain_in|domain_recv|dpow|dround|dsimple_init|dsimple_lexize|dsnowball_init|dsnowball_lexize|dsqrt|dsynonym_init|dsynonym_lexize|dtrunc|encode|enum_cmp|enum_eq|enum_first|enum_ge|enum_gt|enum_in|enum_larger|enum_last|enum_le|enum_lt|enum_ne|enum_out|enum_range|enum_recv|enum_send|enum_smaller|eqjoinsel|eqsel|euc_cn_to_mic|euc_cn_to_utf8|euc_jis_2004_to_shift_jis_2004|euc_jis_2004_to_utf8|euc_jp_to_mic|euc_jp_to_sjis|euc_jp_to_utf8|euc_kr_to_mic|euc_kr_to_utf8|euc_tw_to_big5|euc_tw_to_mic|euc_tw_to_utf8|every|exp|factorial|family|fdw_handler_in|fdw_handler_out|first_value|float4|float48div|float48eq|float48ge|float48gt|float48le|float48lt|float48mi|float48mul|float48ne|float48pl|float4_accum|float4abs|float4div|float4eq|float4ge|float4gt|float4in|float4larger|float4le|float4lt|float4mi|float4mul|float4ne|float4out|float4pl|float4recv|float4send|float4smaller|float4um|float4up|float8|float84div|float84eq|float84ge|float84gt|float84le|float84lt|float84mi|float84mul|float84ne|float84pl|float8_accum|float8_avg|float8_corr|float8_covar_pop|float8_covar_samp|float8_regr_accum|float8_regr_avgx|float8_regr_avgy|float8_regr_intercept|float8_regr_r2|float8_regr_slope|float8_regr_sxx|float8_regr_sxy|float8_regr_syy|float8_stddev_pop|float8_stddev_samp|float8_var_pop|float8_var_samp|float8abs|float8div|float8eq|float8ge|float8gt|float8in|float8larger|float8le|float8lt|float8mi|float8mul|float8ne|float8out|float8pl|float8recv|float8send|float8smaller|float8um|float8up|floor|flt4_mul_cash|flt8_mul_cash|fmgr_c_validator|fmgr_internal_validator|fmgr_sql_validator|format|format_type|gb18030_to_utf8|gbk_to_utf8|generate_series|generate_subscripts|get_bit|get_byte|get_current_ts_config|getdatabaseencoding|getpgusername|gin_cmp_prefix|gin_cmp_tslexeme|gin_extract_tsquery|gin_extract_tsvector|gin_tsquery_consistent|ginarrayconsistent|ginarrayextract|ginbeginscan|ginbuild|ginbuildempty|ginbulkdelete|gincostestimate|ginendscan|gingetbitmap|gininsert|ginmarkpos|ginoptions|ginqueryarrayextract|ginrescan|ginrestrpos|ginvacuumcleanup|gist_box_compress|gist_box_consistent|gist_box_decompress|gist_box_penalty|gist_box_picksplit|gist_box_same|gist_box_union|gist_circle_compress|gist_circle_consistent|gist_point_compress|gist_point_consistent|gist_point_distance|gist_poly_compress|gist_poly_consistent|gistbeginscan|gistbuild|gistbuildempty|gistbulkdelete|gistcostestimate|gistendscan|gistgetbitmap|gistgettuple|gistinsert|gistmarkpos|gistoptions|gistrescan|gistrestrpos|gistvacuumcleanup|gtsquery_compress|gtsquery_consistent|gtsquery_decompress|gtsquery_penalty|gtsquery_picksplit|gtsquery_same|gtsquery_union|gtsvector_compress|gtsvector_consistent|gtsvector_decompress|gtsvector_penalty|gtsvector_picksplit|gtsvector_same|gtsvector_union|gtsvectorin|gtsvectorout|has_any_column_privilege|has_column_privilege|has_database_privilege|has_foreign_data_wrapper_privilege|has_function_privilege|has_language_privilege|has_schema_privilege|has_sequence_privilege|has_server_privilege|has_table_privilege|has_tablespace_privilege|hash_aclitem|hash_array|hash_numeric|hashbeginscan|hashbpchar|hashbuild|hashbuildempty|hashbulkdelete|hashchar|hashcostestimate|hashendscan|hashenum|hashfloat4|hashfloat8|hashgetbitmap|hashgettuple|hashinet|hashinsert|hashint2|hashint2vector|hashint4|hashint8|hashmacaddr|hashmarkpos|hashname|hashoid|hashoidvector|hashoptions|hashrescan|hashrestrpos|hashtext|hashvacuumcleanup|hashvarlena|height|host|hostmask|iclikejoinsel|iclikesel|icnlikejoinsel|icnlikesel|icregexeqjoinsel|icregexeqsel|icregexnejoinsel|icregexnesel|inet_client_addr|inet_client_port|inet_in|inet_out|inet_recv|inet_send|inet_server_addr|inet_server_port|inetand|inetmi|inetmi_int8|inetnot|inetor|inetpl|initcap|int2|int24div|int24eq|int24ge|int24gt|int24le|int24lt|int24mi|int24mul|int24ne|int24pl|int28div|int28eq|int28ge|int28gt|int28le|int28lt|int28mi|int28mul|int28ne|int28pl|int2_accum|int2_avg_accum|int2_mul_cash|int2_sum|int2abs|int2and|int2div|int2eq|int2ge|int2gt|int2in|int2larger|int2le|int2lt|int2mi|int2mod|int2mul|int2ne|int2not|int2or|int2out|int2pl|int2recv|int2send|int2shl|int2shr|int2smaller|int2um|int2up|int2vectoreq|int2vectorin|int2vectorout|int2vectorrecv|int2vectorsend|int2xor|int4|int42div|int42eq|int42ge|int42gt|int42le|int42lt|int42mi|int42mul|int42ne|int42pl|int48div|int48eq|int48ge|int48gt|int48le|int48lt|int48mi|int48mul|int48ne|int48pl|int4_accum|int4_avg_accum|int4_mul_cash|int4_sum|int4abs|int4and|int4div|int4eq|int4ge|int4gt|int4in|int4inc|int4larger|int4le|int4lt|int4mi|int4mod|int4mul|int4ne|int4not|int4or|int4out|int4pl|int4recv|int4send|int4shl|int4shr|int4smaller|int4um|int4up|int4xor|int8|int82div|int82eq|int82ge|int82gt|int82le|int82lt|int82mi|int82mul|int82ne|int82pl|int84div|int84eq|int84ge|int84gt|int84le|int84lt|int84mi|int84mul|int84ne|int84pl|int8_accum|int8_avg|int8_avg_accum|int8_sum|int8abs|int8and|int8div|int8eq|int8ge|int8gt|int8in|int8inc|int8inc_any|int8inc_float8_float8|int8larger|int8le|int8lt|int8mi|int8mod|int8mul|int8ne|int8not|int8or|int8out|int8pl|int8pl_inet|int8recv|int8send|int8shl|int8shr|int8smaller|int8um|int8up|int8xor|integer_pl_date|inter_lb|inter_sb|inter_sl|internal_in|internal_out|interval_accum|interval_avg|interval_cmp|interval_div|interval_eq|interval_ge|interval_gt|interval_hash|interval_in|interval_larger|interval_le|interval_lt|interval_mi|interval_mul|interval_ne|interval_out|interval_pl|interval_pl_date|interval_pl_time|interval_pl_timestamp|interval_pl_timestamptz|interval_pl_timetz|interval_recv|interval_send|interval_smaller|interval_um|intervaltypmodin|intervaltypmodout|intinterval|isclosed|isfinite|ishorizontal|iso8859_1_to_utf8|iso8859_to_utf8|iso_to_koi8r|iso_to_mic|iso_to_win1251|iso_to_win866|isopen|isparallel|isperp|isvertical|johab_to_utf8|justify_days|justify_hours|justify_interval|koi8r_to_iso|koi8r_to_mic|koi8r_to_utf8|koi8r_to_win1251|koi8r_to_win866|koi8u_to_utf8|lag|language_handler_in|language_handler_out|last_value|lastval|latin1_to_mic|latin2_to_mic|latin2_to_win1250|latin3_to_mic|latin4_to_mic|lead|left|length|like|like_escape|likejoinsel|likesel|line|line_distance|line_eq|line_horizontal|line_in|line_interpt|line_intersect|line_out|line_parallel|line_perp|line_recv|line_send|line_vertical|ln|lo_close|lo_creat|lo_create|lo_export|lo_import|lo_lseek|lo_open|lo_tell|lo_truncate|lo_unlink|log|loread|lower|lowrite|lpad|lseg|lseg_center|lseg_distance|lseg_eq|lseg_ge|lseg_gt|lseg_horizontal|lseg_in|lseg_interpt|lseg_intersect|lseg_le|lseg_length|lseg_lt|lseg_ne|lseg_out|lseg_parallel|lseg_perp|lseg_recv|lseg_send|lseg_vertical|ltrim|macaddr_cmp|macaddr_eq|macaddr_ge|macaddr_gt|macaddr_in|macaddr_le|macaddr_lt|macaddr_ne|macaddr_out|macaddr_recv|macaddr_send|makeaclitem|masklen|max|md5|mic_to_ascii|mic_to_big5|mic_to_euc_cn|mic_to_euc_jp|mic_to_euc_kr|mic_to_euc_tw|mic_to_iso|mic_to_koi8r|mic_to_latin1|mic_to_latin2|mic_to_latin3|mic_to_latin4|mic_to_sjis|mic_to_win1250|mic_to_win1251|mic_to_win866|min|mktinterval|mod|money|mul_d_interval|name|nameeq|namege|namegt|nameiclike|nameicnlike|nameicregexeq|nameicregexne|namein|namele|namelike|namelt|namene|namenlike|nameout|namerecv|nameregexeq|nameregexne|namesend|neqjoinsel|neqsel|netmask|network|network_cmp|network_eq|network_ge|network_gt|network_le|network_lt|network_ne|network_sub|network_subeq|network_sup|network_supeq|nextval|nlikejoinsel|nlikesel|notlike|now|npoints|nth_value|ntile|numeric_abs|numeric_accum|numeric_add|numeric_avg|numeric_avg_accum|numeric_cmp|numeric_div|numeric_div_trunc|numeric_eq|numeric_exp|numeric_fac|numeric_ge|numeric_gt|numeric_in|numeric_inc|numeric_larger|numeric_le|numeric_ln|numeric_log|numeric_lt|numeric_mod|numeric_mul|numeric_ne|numeric_out|numeric_power|numeric_recv|numeric_send|numeric_smaller|numeric_sqrt|numeric_stddev_pop|numeric_stddev_samp|numeric_sub|numeric_uminus|numeric_uplus|numeric_var_pop|numeric_var_samp|numerictypmodin|numerictypmodout|numnode|obj_description|octet_length|oid|oideq|oidge|oidgt|oidin|oidlarger|oidle|oidlt|oidne|oidout|oidrecv|oidsend|oidsmaller|oidvectoreq|oidvectorge|oidvectorgt|oidvectorin|oidvectorle|oidvectorlt|oidvectorne|oidvectorout|oidvectorrecv|oidvectorsend|oidvectortypes|on_pb|on_pl|on_ppath|on_ps|on_sb|on_sl|opaque_in|opaque_out|overlaps|overlay|path|path_add|path_add_pt|path_center|path_contain_pt|path_distance|path_div_pt|path_in|path_inter|path_length|path_mul_pt|path_n_eq|path_n_ge|path_n_gt|path_n_le|path_n_lt|path_npoints|path_out|path_recv|path_send|path_sub_pt|pclose|percent_rank|pg_advisory_lock|pg_advisory_lock_shared|pg_advisory_unlock|pg_advisory_unlock_all|pg_advisory_unlock_shared|pg_advisory_xact_lock|pg_advisory_xact_lock_shared|pg_available_extension_versions|pg_available_extensions|pg_backend_pid|pg_cancel_backend|pg_char_to_encoding|pg_client_encoding|pg_collation_is_visible|pg_column_size|pg_conf_load_time|pg_conversion_is_visible|pg_create_restore_point|pg_current_xlog_insert_location|pg_current_xlog_location|pg_cursor|pg_database_size|pg_describe_object|pg_encoding_max_length|pg_encoding_to_char|pg_extension_config_dump|pg_extension_update_paths|pg_function_is_visible|pg_get_constraintdef|pg_get_expr|pg_get_function_arguments|pg_get_function_identity_arguments|pg_get_function_result|pg_get_functiondef|pg_get_indexdef|pg_get_keywords|pg_get_ruledef|pg_get_serial_sequence|pg_get_triggerdef|pg_get_userbyid|pg_get_viewdef|pg_has_role|pg_indexes_size|pg_is_in_recovery|pg_is_other_temp_schema|pg_is_xlog_replay_paused|pg_last_xact_replay_timestamp|pg_last_xlog_receive_location|pg_last_xlog_replay_location|pg_listening_channels|pg_lock_status|pg_ls_dir|pg_my_temp_schema|pg_node_tree_in|pg_node_tree_out|pg_node_tree_recv|pg_node_tree_send|pg_notify|pg_opclass_is_visible|pg_operator_is_visible|pg_options_to_table|pg_postmaster_start_time|pg_prepared_statement|pg_prepared_xact|pg_read_binary_file|pg_read_file|pg_relation_filenode|pg_relation_filepath|pg_relation_size|pg_reload_conf|pg_rotate_logfile|pg_sequence_parameters|pg_show_all_settings|pg_size_pretty|pg_sleep|pg_start_backup|pg_stat_clear_snapshot|pg_stat_file|pg_stat_get_activity|pg_stat_get_analyze_count|pg_stat_get_autoanalyze_count|pg_stat_get_autovacuum_count|pg_stat_get_backend_activity|pg_stat_get_backend_activity_start|pg_stat_get_backend_client_addr|pg_stat_get_backend_client_port|pg_stat_get_backend_dbid|pg_stat_get_backend_idset|pg_stat_get_backend_pid|pg_stat_get_backend_start|pg_stat_get_backend_userid|pg_stat_get_backend_waiting|pg_stat_get_backend_xact_start|pg_stat_get_bgwriter_buf_written_checkpoints|pg_stat_get_bgwriter_buf_written_clean|pg_stat_get_bgwriter_maxwritten_clean|pg_stat_get_bgwriter_requested_checkpoints|pg_stat_get_bgwriter_stat_reset_time|pg_stat_get_bgwriter_timed_checkpoints|pg_stat_get_blocks_fetched|pg_stat_get_blocks_hit|pg_stat_get_buf_alloc|pg_stat_get_buf_fsync_backend|pg_stat_get_buf_written_backend|pg_stat_get_db_blocks_fetched|pg_stat_get_db_blocks_hit|pg_stat_get_db_conflict_all|pg_stat_get_db_conflict_bufferpin|pg_stat_get_db_conflict_lock|pg_stat_get_db_conflict_snapshot|pg_stat_get_db_conflict_startup_deadlock|pg_stat_get_db_conflict_tablespace|pg_stat_get_db_numbackends|pg_stat_get_db_stat_reset_time|pg_stat_get_db_tuples_deleted|pg_stat_get_db_tuples_fetched|pg_stat_get_db_tuples_inserted|pg_stat_get_db_tuples_returned|pg_stat_get_db_tuples_updated|pg_stat_get_db_xact_commit|pg_stat_get_db_xact_rollback|pg_stat_get_dead_tuples|pg_stat_get_function_calls|pg_stat_get_function_self_time|pg_stat_get_function_time|pg_stat_get_last_analyze_time|pg_stat_get_last_autoanalyze_time|pg_stat_get_last_autovacuum_time|pg_stat_get_last_vacuum_time|pg_stat_get_live_tuples|pg_stat_get_numscans|pg_stat_get_tuples_deleted|pg_stat_get_tuples_fetched|pg_stat_get_tuples_hot_updated|pg_stat_get_tuples_inserted|pg_stat_get_tuples_returned|pg_stat_get_tuples_updated|pg_stat_get_vacuum_count|pg_stat_get_wal_senders|pg_stat_get_xact_blocks_fetched|pg_stat_get_xact_blocks_hit|pg_stat_get_xact_function_calls|pg_stat_get_xact_function_self_time|pg_stat_get_xact_function_time|pg_stat_get_xact_numscans|pg_stat_get_xact_tuples_deleted|pg_stat_get_xact_tuples_fetched|pg_stat_get_xact_tuples_hot_updated|pg_stat_get_xact_tuples_inserted|pg_stat_get_xact_tuples_returned|pg_stat_get_xact_tuples_updated|pg_stat_reset|pg_stat_reset_shared|pg_stat_reset_single_function_counters|pg_stat_reset_single_table_counters|pg_stop_backup|pg_switch_xlog|pg_table_is_visible|pg_table_size|pg_tablespace_databases|pg_tablespace_size|pg_terminate_backend|pg_timezone_abbrevs|pg_timezone_names|pg_total_relation_size|pg_try_advisory_lock|pg_try_advisory_lock_shared|pg_try_advisory_xact_lock|pg_try_advisory_xact_lock_shared|pg_ts_config_is_visible|pg_ts_dict_is_visible|pg_ts_parser_is_visible|pg_ts_template_is_visible|pg_type_is_visible|pg_typeof|pg_xlog_replay_pause|pg_xlog_replay_resume|pg_xlogfile_name|pg_xlogfile_name_offset|pi|plainto_tsquery|plpgsql_call_handler|plpgsql_inline_handler|plpgsql_validator|point|point_above|point_add|point_below|point_distance|point_div|point_eq|point_horiz|point_in|point_left|point_mul|point_ne|point_out|point_recv|point_right|point_send|point_sub|point_vert|poly_above|poly_below|poly_center|poly_contain|poly_contain_pt|poly_contained|poly_distance|poly_in|poly_left|poly_npoints|poly_out|poly_overabove|poly_overbelow|poly_overlap|poly_overleft|poly_overright|poly_recv|poly_right|poly_same|poly_send|polygon|popen|position|positionjoinsel|positionsel|postgresql_fdw_validator|pow|power|prsd_end|prsd_headline|prsd_lextype|prsd_nexttoken|prsd_start|pt_contained_circle|pt_contained_poly|query_to_xml|query_to_xml_and_xmlschema|query_to_xmlschema|querytree|quote_ident|quote_literal|quote_nullable|radians|radius|random|rank|record_eq|record_ge|record_gt|record_in|record_le|record_lt|record_ne|record_out|record_recv|record_send|regclass|regclassin|regclassout|regclassrecv|regclasssend|regconfigin|regconfigout|regconfigrecv|regconfigsend|regdictionaryin|regdictionaryout|regdictionaryrecv|regdictionarysend|regexeqjoinsel|regexeqsel|regexnejoinsel|regexnesel|regexp_matches|regexp_replace|regexp_split_to_array|regexp_split_to_table|regoperatorin|regoperatorout|regoperatorrecv|regoperatorsend|regoperin|regoperout|regoperrecv|regopersend|regprocedurein|regprocedureout|regprocedurerecv|regproceduresend|regprocin|regprocout|regprocrecv|regprocsend|regr_avgx|regr_avgy|regr_count|regr_intercept|regr_r2|regr_slope|regr_sxx|regr_sxy|regr_syy|regtypein|regtypeout|regtyperecv|regtypesend|reltime|reltimeeq|reltimege|reltimegt|reltimein|reltimele|reltimelt|reltimene|reltimeout|reltimerecv|reltimesend|repeat|replace|reverse|right|round|row_number|rpad|rtrim|scalargtjoinsel|scalargtsel|scalarltjoinsel|scalarltsel|schema_to_xml|schema_to_xml_and_xmlschema|schema_to_xmlschema|session_user|set_bit|set_byte|set_config|set_masklen|setseed|setval|setweight|shell_in|shell_out|shift_jis_2004_to_euc_jis_2004|shift_jis_2004_to_utf8|shobj_description|sign|similar_escape|sin|sjis_to_euc_jp|sjis_to_mic|sjis_to_utf8|slope|smgreq|smgrin|smgrne|smgrout|split_part|sqrt|statement_timestamp|stddev|stddev_pop|stddev_samp|string_agg|string_agg_finalfn|string_agg_transfn|string_to_array|strip|strpos|substr|substring|sum|suppress_redundant_updates_trigger|table_to_xml|table_to_xml_and_xmlschema|table_to_xmlschema|tan|text|text_ge|text_gt|text_larger|text_le|text_lt|text_pattern_ge|text_pattern_gt|text_pattern_le|text_pattern_lt|text_smaller|textanycat|textcat|texteq|texticlike|texticnlike|texticregexeq|texticregexne|textin|textlen|textlike|textne|textnlike|textout|textrecv|textregexeq|textregexne|textsend|thesaurus_init|thesaurus_lexize|tideq|tidge|tidgt|tidin|tidlarger|tidle|tidlt|tidne|tidout|tidrecv|tidsend|tidsmaller|time_cmp|time_eq|time_ge|time_gt|time_hash|time_in|time_larger|time_le|time_lt|time_mi_interval|time_mi_time|time_ne|time_out|time_pl_interval|time_recv|time_send|time_smaller|timedate_pl|timemi|timenow|timeofday|timepl|timestamp_cmp|timestamp_cmp_date|timestamp_cmp_timestamptz|timestamp_eq|timestamp_eq_date|timestamp_eq_timestamptz|timestamp_ge|timestamp_ge_date|timestamp_ge_timestamptz|timestamp_gt|timestamp_gt_date|timestamp_gt_timestamptz|timestamp_hash|timestamp_in|timestamp_larger|timestamp_le|timestamp_le_date|timestamp_le_timestamptz|timestamp_lt|timestamp_lt_date|timestamp_lt_timestamptz|timestamp_mi|timestamp_mi_interval|timestamp_ne|timestamp_ne_date|timestamp_ne_timestamptz|timestamp_out|timestamp_pl_interval|timestamp_recv|timestamp_send|timestamp_smaller|timestamptypmodin|timestamptypmodout|timestamptz_cmp|timestamptz_cmp_date|timestamptz_cmp_timestamp|timestamptz_eq|timestamptz_eq_date|timestamptz_eq_timestamp|timestamptz_ge|timestamptz_ge_date|timestamptz_ge_timestamp|timestamptz_gt|timestamptz_gt_date|timestamptz_gt_timestamp|timestamptz_in|timestamptz_larger|timestamptz_le|timestamptz_le_date|timestamptz_le_timestamp|timestamptz_lt|timestamptz_lt_date|timestamptz_lt_timestamp|timestamptz_mi|timestamptz_mi_interval|timestamptz_ne|timestamptz_ne_date|timestamptz_ne_timestamp|timestamptz_out|timestamptz_pl_interval|timestamptz_recv|timestamptz_send|timestamptz_smaller|timestamptztypmodin|timestamptztypmodout|timetypmodin|timetypmodout|timetz_cmp|timetz_eq|timetz_ge|timetz_gt|timetz_hash|timetz_in|timetz_larger|timetz_le|timetz_lt|timetz_mi_interval|timetz_ne|timetz_out|timetz_pl_interval|timetz_recv|timetz_send|timetz_smaller|timetzdate_pl|timetztypmodin|timetztypmodout|timezone|tinterval|tintervalct|tintervalend|tintervaleq|tintervalge|tintervalgt|tintervalin|tintervalle|tintervalleneq|tintervallenge|tintervallengt|tintervallenle|tintervallenlt|tintervallenne|tintervallt|tintervalne|tintervalout|tintervalov|tintervalrecv|tintervalrel|tintervalsame|tintervalsend|tintervalstart|to_ascii|to_char|to_date|to_hex|to_number|to_timestamp|to_tsquery|to_tsvector|transaction_timestamp|translate|trigger_in|trigger_out|trunc|ts_debug|ts_headline|ts_lexize|ts_match_qv|ts_match_tq|ts_match_tt|ts_match_vq|ts_parse|ts_rank|ts_rank_cd|ts_rewrite|ts_stat|ts_token_type|ts_typanalyze|tsmatchjoinsel|tsmatchsel|tsq_mcontained|tsq_mcontains|tsquery_and|tsquery_cmp|tsquery_eq|tsquery_ge|tsquery_gt|tsquery_le|tsquery_lt|tsquery_ne|tsquery_not|tsquery_or|tsqueryin|tsqueryout|tsqueryrecv|tsquerysend|tsvector_cmp|tsvector_concat|tsvector_eq|tsvector_ge|tsvector_gt|tsvector_le|tsvector_lt|tsvector_ne|tsvector_update_trigger|tsvector_update_trigger_column|tsvectorin|tsvectorout|tsvectorrecv|tsvectorsend|txid_current|txid_current_snapshot|txid_snapshot_in|txid_snapshot_out|txid_snapshot_recv|txid_snapshot_send|txid_snapshot_xip|txid_snapshot_xmax|txid_snapshot_xmin|txid_visible_in_snapshot|uhc_to_utf8|unique_key_recheck|unknownin|unknownout|unknownrecv|unknownsend|unnest|upper|utf8_to_ascii|utf8_to_big5|utf8_to_euc_cn|utf8_to_euc_jis_2004|utf8_to_euc_jp|utf8_to_euc_kr|utf8_to_euc_tw|utf8_to_gb18030|utf8_to_gbk|utf8_to_iso8859|utf8_to_iso8859_1|utf8_to_johab|utf8_to_koi8r|utf8_to_koi8u|utf8_to_shift_jis_2004|utf8_to_sjis|utf8_to_uhc|utf8_to_win|uuid_cmp|uuid_eq|uuid_ge|uuid_gt|uuid_hash|uuid_in|uuid_le|uuid_lt|uuid_ne|uuid_out|uuid_recv|uuid_send|var_pop|var_samp|varbit_in|varbit_out|varbit_recv|varbit_send|varbitcmp|varbiteq|varbitge|varbitgt|varbitle|varbitlt|varbitne|varbittypmodin|varbittypmodout|varcharin|varcharout|varcharrecv|varcharsend|varchartypmodin|varchartypmodout|variance|version|void_in|void_out|void_recv|void_send|width|width_bucket|win1250_to_latin2|win1250_to_mic|win1251_to_iso|win1251_to_koi8r|win1251_to_mic|win1251_to_win866|win866_to_iso|win866_to_koi8r|win866_to_mic|win866_to_win1251|win_to_utf8|xideq|xideqint4|xidin|xidout|xidrecv|xidsend|xml|xml_in|xml_is_well_formed|xml_is_well_formed_content|xml_is_well_formed_document|xml_out|xml_recv|xml_send|xmlagg|xmlcomment|xmlconcat2|xmlexists|xmlvalidate|xpath|xpath_exists".split("|")),c=[{token:"string",regex:"['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"},{token:"variable.language",regex:'".*?"'},{token:"constant.numeric",regex:"[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"},{token:function(c){return c=c.toLowerCase(),a.hasOwnProperty(c)?"keyword":b.hasOwnProperty(c)?"support.function":"identifier"},regex:"[a-zA-Z_][a-zA-Z0-9_$]*\\b"},{token:"keyword.operator",regex:"!|!!|!~|!~\\*|!~~|!~~\\*|#|##|#<|#<=|#<>|#=|#>|#>=|%|\\&|\\&\\&|\\&<|\\&<\\||\\&>|\\*|\\+|\\-|/|<|<#>|<\\->|<<|<<=|<<\\||<=|<>|<\\?>|<@|<\\^|=|>|>=|>>|>>=|>\\^|\\?#|\\?\\-|\\?\\-\\||\\?\\||\\?\\|\\||@|@\\-@|@>|@@|@@@|\\^|\\||\\|\\&>|\\|/|\\|>>|\\|\\||\\|\\|/|~|~\\*|~<=~|~<~|~=|~>=~|~>~|~~|~~\\*"},{token:"lparen.paren",regex:"[\\(]"},{token:"paren.rparen",regex:"[\\)]"},{token:"text",regex:"\\s+"}];this.$rules={start:[{token:"comment",regex:"--.*$"},(new f).getStartRule("doc-start"),{token:"comment",merge:!0,regex:"\\/\\*",next:"comment"},{token:"keyword.statementBegin",regex:"^[a-zA-Z]+",next:"statement"},{token:"support.buildin",regex:"^\\\\[\\S]+.*$"}],statement:[{token:"comment",regex:"--.*$"},{token:"comment",merge:!0,regex:"\\/\\*",next:"commentStatement"},{token:"statementEnd",regex:";",next:"start"},{token:"string",regex:"\\$perl\\$",next:"perl-start"},{token:"string",regex:"\\$python\\$",next:"python-start"},{token:"string",regex:"\\$[\\w_0-9]*\\$$",next:"dollarSql"},{token:"string",regex:"\\$[\\w_0-9]*\\$",next:"dollarStatementString"}].concat(c),dollarSql:[{token:"comment",regex:"--.*$"},{token:"comment",merge:!0,regex:"\\/\\*",next:"commentDollarSql"},{token:"string",regex:"^\\$[\\w_0-9]*\\$",next:"statement"},{token:"string",regex:"\\$[\\w_0-9]*\\$",next:"dollarSqlString"}].concat(c),comment:[{token:"comment",regex:".*?\\*\\/",next:"start"},{token:"comment",merge:!0,regex:".+"}],commentStatement:[{token:"comment",regex:".*?\\*\\/",next:"statement"},{token:"comment",merge:!0,regex:".+"}],commentDollarSql:[{token:"comment",regex:".*?\\*\\/",next:"dollarSql"},{token:"comment",merge:!0,regex:".+"}],dollarStatementString:[{token:"string",regex:".*?\\$[\\w_0-9]*\\$",next:"statement"},{token:"string",merge:!0,regex:".+"}],dollarSqlString:[{token:"string",regex:".*?\\$[\\w_0-9]*\\$",next:"dollarSql"},{token:"string",merge:!0,regex:".+"}]},this.embedRules(f,"doc-",[(new f).getEndRule("start")]),this.embedRules(h,"perl-",[{token:"string",regex:"\\$perl\\$",next:"statement"}]),this.embedRules(i,"python-",[{token:"string",regex:"\\$python\\$",next:"statement"}])};d.inherits(j,g),b.PgsqlHighlightRules=j}),define("ace/mode/doc_comment_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("./text_highlight_rules").TextHighlightRules,f=function(){this.$rules={start:[{token:"comment.doc.tag",regex:"@[\\w\\d_]+"},{token:"comment.doc",merge:!0,regex:"\\s+"},{token:"comment.doc",merge:!0,regex:"TODO"},{token:"comment.doc",merge:!0,regex:"[^@\\*]+"},{token:"comment.doc",merge:!0,regex:"."}]}};d.inherits(f,e),function(){this.getStartRule=function(a){return{token:"comment.doc",merge:!0,regex:"\\/\\*(?=\\*)",next:a}},this.getEndRule=function(a){return{token:"comment.doc",merge:!0,regex:"\\*\\/",next:a}}}.call(f.prototype),b.DocCommentHighlightRules=f}),define("ace/mode/perl_highlight_rules",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/mode/text_highlight_rules"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("../lib/lang"),f=a("./text_highlight_rules").TextHighlightRules,g=function(){var a=e.arrayToMap("base|constant|continue|else|elsif|for|foreach|format|goto|if|last|local|my|next|no|package|parent|redo|require|scalar|sub|unless|until|while|use|vars".split("|")),b=e.arrayToMap("ARGV|ENV|INC|SIG".split("|")),c=e.arrayToMap("getprotobynumber|getprotobyname|getservbyname|gethostbyaddr|gethostbyname|getservbyport|getnetbyaddr|getnetbyname|getsockname|getpeername|setpriority|getprotoent|setprotoent|getpriority|endprotoent|getservent|setservent|endservent|sethostent|socketpair|getsockopt|gethostent|endhostent|setsockopt|setnetent|quotemeta|localtime|prototype|getnetent|endnetent|rewinddir|wantarray|getpwuid|closedir|getlogin|readlink|endgrent|getgrgid|getgrnam|shmwrite|shutdown|readline|endpwent|setgrent|readpipe|formline|truncate|dbmclose|syswrite|setpwent|getpwnam|getgrent|getpwent|ucfirst|sysread|setpgrp|shmread|sysseek|sysopen|telldir|defined|opendir|connect|lcfirst|getppid|binmode|syscall|sprintf|getpgrp|readdir|seekdir|waitpid|reverse|unshift|symlink|dbmopen|semget|msgrcv|rename|listen|chroot|msgsnd|shmctl|accept|unpack|exists|fileno|shmget|system|unlink|printf|gmtime|msgctl|semctl|values|rindex|substr|splice|length|msgget|select|socket|return|caller|delete|alarm|ioctl|index|undef|lstat|times|srand|chown|fcntl|close|write|umask|rmdir|study|sleep|chomp|untie|print|utime|mkdir|atan2|split|crypt|flock|chmod|BEGIN|bless|chdir|semop|shift|reset|link|stat|chop|grep|fork|dump|join|open|tell|pipe|exit|glob|warn|each|bind|sort|pack|eval|push|keys|getc|kill|seek|sqrt|send|wait|rand|tied|read|time|exec|recv|eof|chr|int|ord|exp|pos|pop|sin|log|abs|oct|hex|tie|cos|vec|END|ref|map|die|uc|lc|do".split("|"));this.$rules={start:[{token:"comment",regex:"#.*$"},{token:"string.regexp",regex:"[/](?:(?:\\[(?:\\\\]|[^\\]])+\\])|(?:\\\\/|[^\\]/]))*[/]\\w*\\s*(?=[).,;]|$)"},{token:"string",regex:'["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'},{token:"string",merge:!0,regex:'["].*\\\\$',next:"qqstring"},{token:"string",regex:"['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"},{token:"string",merge:!0,regex:"['].*\\\\$",next:"qstring"},{token:"constant.numeric",regex:"0x[0-9a-fA-F]+\\b"},{token:"constant.numeric",regex:"[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"},{token:function(d){return a.hasOwnProperty(d)?"keyword":b.hasOwnProperty(d)?"constant.language":c.hasOwnProperty(d)?"support.function":"identifier"},regex:"[a-zA-Z_$][a-zA-Z0-9_$]*\\b"},{token:"keyword.operator",regex:"\\.\\.\\.|\\|\\|=|>>=|<<=|<=>|&&=|=>|!~|\\^=|&=|\\|=|\\.=|x=|%=|\\/=|\\*=|\\-=|\\+=|=~|\\*\\*|\\-\\-|\\.\\.|\\|\\||&&|\\+\\+|\\->|!=|==|>=|<=|>>|<<|,|=|\\?\\:|\\^|\\||x|%|\\/|\\*|<|&|\\\\|~|!|>|\\.|\\-|\\+|\\-C|\\-b|\\-S|\\-u|\\-t|\\-p|\\-l|\\-d|\\-f|\\-g|\\-s|\\-z|\\-k|\\-e|\\-O|\\-T|\\-B|\\-M|\\-A|\\-X|\\-W|\\-c|\\-R|\\-o|\\-x|\\-w|\\-r|\\b(?:and|cmp|eq|ge|gt|le|lt|ne|not|or|xor)"},{token:"lparen",regex:"[[({]"},{token:"rparen",regex:"[\\])}]"},{token:"text",regex:"\\s+"}],qqstring:[{token:"string",regex:'(?:(?:\\\\.)|(?:[^"\\\\]))*?"',next:"start"},{token:"string",merge:!0,regex:".+"}],qstring:[{token:"string",regex:"(?:(?:\\\\.)|(?:[^'\\\\]))*?'",next:"start"},{token:"string",merge:!0,regex:".+"}]}};d.inherits(g,f),b.PerlHighlightRules=g}),define("ace/mode/python_highlight_rules",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/mode/text_highlight_rules"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("../lib/lang"),f=a("./text_highlight_rules").TextHighlightRules,g=function(){var a=e.arrayToMap("and|as|assert|break|class|continue|def|del|elif|else|except|exec|finally|for|from|global|if|import|in|is|lambda|not|or|pass|print|raise|return|try|while|with|yield".split("|")),b=e.arrayToMap("True|False|None|NotImplemented|Ellipsis|__debug__".split("|")),c=e.arrayToMap("abs|divmod|input|open|staticmethod|all|enumerate|int|ord|str|any|eval|isinstance|pow|sum|basestring|execfile|issubclass|print|super|binfile|iter|property|tuple|bool|filter|len|range|type|bytearray|float|list|raw_input|unichr|callable|format|locals|reduce|unicode|chr|frozenset|long|reload|vars|classmethod|getattr|map|repr|xrange|cmp|globals|max|reversed|zip|compile|hasattr|memoryview|round|__import__|complex|hash|min|set|apply|delattr|help|next|setattr|buffer|dict|hex|object|slice|coerce|dir|id|oct|sorted|intern".split("|")),d=e.arrayToMap("".split("|")),f="(?:r|u|ur|R|U|UR|Ur|uR)?",g="(?:(?:[1-9]\\d*)|(?:0))",h="(?:0[oO]?[0-7]+)",i="(?:0[xX][\\dA-Fa-f]+)",j="(?:0[bB][01]+)",k="(?:"+g+"|"+h+"|"+i+"|"+j+")",l="(?:[eE][+-]?\\d+)",m="(?:\\.\\d+)",n="(?:\\d+)",o="(?:(?:"+n+"?"+m+")|(?:"+n+"\\.))",p="(?:(?:"+o+"|"+n+")"+l+")",q="(?:"+p+"|"+o+")";this.$rules={start:[{token:"comment",regex:"#.*$"},{token:"string",regex:f+'"{3}(?:[^\\\\]|\\\\.)*?"{3}'},{token:"string",merge:!0,regex:f+'"{3}.*$',next:"qqstring"},{token:"string",regex:f+'"(?:[^\\\\]|\\\\.)*?"'},{token:"string",regex:f+"'{3}(?:[^\\\\]|\\\\.)*?'{3}"},{token:"string",merge:!0,regex:f+"'{3}.*$",next:"qstring"},{token:"string",regex:f+"'(?:[^\\\\]|\\\\.)*?'"},{token:"constant.numeric",regex:"(?:"+q+"|\\d+)[jJ]\\b"},{token:"constant.numeric",regex:q},{token:"constant.numeric",regex:k+"[lL]\\b"},{token:"constant.numeric",regex:k+"\\b"},{token:function(e){return a.hasOwnProperty(e)?"keyword":b.hasOwnProperty(e)?"constant.language":d.hasOwnProperty(e)?"invalid.illegal":c.hasOwnProperty(e)?"support.function":e=="debugger"?"invalid.deprecated":"identifier"},regex:"[a-zA-Z_$][a-zA-Z0-9_$]*\\b"},{token:"keyword.operator",regex:"\\+|\\-|\\*|\\*\\*|\\/|\\/\\/|%|<<|>>|&|\\||\\^|~|<|>|<=|=>|==|!=|<>|="},{token:"lparen.paren",regex:"[\\[\\(\\{]"},{token:"paren.rparen",regex:"[\\]\\)\\}]"},{token:"text",regex:"\\s+"}],qqstring:[{token:"string",regex:'(?:[^\\\\]|\\\\.)*?"{3}',next:"start"},{token:"string",merge:!0,regex:".+"}],qstring:[{token:"string",regex:"(?:[^\\\\]|\\\\.)*?'{3}",next:"start"},{token:"string",merge:!0,regex:".+"}]}};d.inherits(g,f),b.PythonHighlightRules=g})
\ No newline at end of file
diff --git a/apps/files_texteditor/js/aceeditor/mode-php-uncompressed.js b/apps/files_texteditor/js/aceeditor/mode-php-uncompressed.js
old mode 100755
new mode 100644
index 58c9255623dcfc988581221317ea7bfae9ac7282..3b0c2f8de10498c434b861f7b549af20725b86b5
--- a/apps/files_texteditor/js/aceeditor/mode-php-uncompressed.js
+++ b/apps/files_texteditor/js/aceeditor/mode-php-uncompressed.js
@@ -1071,14 +1071,14 @@ var PhpHighlightRules = function() {
                 regex : '["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'
             }, {
                 token : "string", // multi line string start
-                regex : '["].*\\\\$',
+                regex : '["][\\s\\S]*',
                 next : "qqstring"
             }, {
                 token : "string", // single line
                 regex : "['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"
             }, {
                 token : "string", // multi line string start
-                regex : "['].*\\\\$",
+                regex : "['][\\s\\S]+",
                 next : "qstring"
             }, {
                 token : "constant.numeric", // hex
@@ -1160,21 +1160,21 @@ var PhpHighlightRules = function() {
         "qqstring" : [
             {
                 token : "string",
-                regex : '(?:(?:\\\\.)|(?:[^"\\\\]))*?"',
+                regex : '"',
                 next : "start"
             }, {
                 token : "string",
-                regex : '.+'
+                regex : '[^"]+'
             }
         ],
         "qstring" : [
             {
                 token : "string",
-                regex : "(?:(?:\\\\.)|(?:[^'\\\\]))*?'",
+                regex : "'",
                 next : "start"
             }, {
                 token : "string",
-                regex : '.+'
+                regex : "[^']+"
             }
         ],
         "htmlcomment" : [
@@ -1213,7 +1213,7 @@ var PhpHighlightRules = function() {
                  next : "htmltag"
              }, {
                  token : "meta.tag",
-                 regex : ">",
+                 regex : ">"
              }, {
                  token : 'text',
                  regex : "(?:media|type|href)"
@@ -1223,7 +1223,7 @@ var PhpHighlightRules = function() {
              }, {
                  token : "paren.lparen",
                  regex : "\{",
-                 next : "cssdeclaration",
+                 next : "cssdeclaration"
              }, {
                  token : "keyword",
                  regex : "#[A-Za-z0-9\-\_\.]+"
@@ -1265,7 +1265,7 @@ var PhpHighlightRules = function() {
                    regex : ";",
                    next : "cssdeclaration"
                }
-         ],
+         ]
     };
 
     this.embedRules(DocCommentHighlightRules, "doc-",
@@ -1507,12 +1507,12 @@ var CstyleBehaviour = function () {
                 return {
                     text: '{' + selected + '}',
                     selection: false
-                }
+                };
             } else {
                 return {
                     text: '{}',
                     selection: [1, 1]
-                }
+                };
             }
         } else if (text == '}') {
             var cursor = editor.getCursorPosition();
@@ -1524,7 +1524,7 @@ var CstyleBehaviour = function () {
                     return {
                         text: '',
                         selection: [1, 1]
-                    }
+                    };
                 }
             }
         } else if (text == "\n") {
@@ -1542,7 +1542,7 @@ var CstyleBehaviour = function () {
                 return {
                     text: '\n' + indent + '\n' + next_indent,
                     selection: [1, indent.length, 1, indent.length]
-                }
+                };
             }
         }
     });
@@ -1567,12 +1567,12 @@ var CstyleBehaviour = function () {
                 return {
                     text: '(' + selected + ')',
                     selection: false
-                }
+                };
             } else {
                 return {
                     text: '()',
                     selection: [1, 1]
-                }
+                };
             }
         } else if (text == ')') {
             var cursor = editor.getCursorPosition();
@@ -1584,7 +1584,7 @@ var CstyleBehaviour = function () {
                     return {
                         text: '',
                         selection: [1, 1]
-                    }
+                    };
                 }
             }
         }
@@ -1603,14 +1603,15 @@ var CstyleBehaviour = function () {
     });
 
     this.add("string_dquotes", "insertion", function (state, action, editor, session, text) {
-        if (text == '"') {
+        if (text == '"' || text == "'") {
+            var quote = text;
             var selection = editor.getSelectionRange();
             var selected = session.doc.getTextRange(selection);
             if (selected !== "") {
                 return {
-                    text: '"' + selected + '"',
+                    text: quote + selected + quote,
                     selection: false
-                }
+                };
             } else {
                 var cursor = editor.getCursorPosition();
                 var line = session.doc.getLine(cursor.row);
@@ -1631,7 +1632,7 @@ var CstyleBehaviour = function () {
                     if (token.type == "string") {
                       quotepos = -1;
                     } else if (quotepos < 0) {
-                      quotepos = token.value.indexOf('"');
+                      quotepos = token.value.indexOf(quote);
                     }
                     if ((token.value.length + col) > selection.start.column) {
                         break;
@@ -1640,19 +1641,19 @@ var CstyleBehaviour = function () {
                 }
 
                 // Try and be smart about when we auto insert.
-                if (!token || (quotepos < 0 && token.type !== "comment" && (token.type !== "string" || ((selection.start.column !== token.value.length+col-1) && token.value.lastIndexOf('"') === token.value.length-1)))) {
+                if (!token || (quotepos < 0 && token.type !== "comment" && (token.type !== "string" || ((selection.start.column !== token.value.length+col-1) && token.value.lastIndexOf(quote) === token.value.length-1)))) {
                     return {
-                        text: '""',
+                        text: quote + quote,
                         selection: [1,1]
-                    }
+                    };
                 } else if (token && token.type === "string") {
                     // Ignore input and move right one if we're typing over the closing quote.
                     var rightChar = line.substring(cursor.column, cursor.column + 1);
-                    if (rightChar == '"') {
+                    if (rightChar == quote) {
                         return {
                             text: '',
                             selection: [1, 1]
-                        }
+                        };
                     }
                 }
             }
@@ -1661,7 +1662,7 @@ var CstyleBehaviour = function () {
 
     this.add("string_dquotes", "deletion", function (state, action, editor, session, range) {
         var selected = session.doc.getTextRange(range);
-        if (!range.isMultiLine() && selected == '"') {
+        if (!range.isMultiLine() && (selected == '"' || selected == "'")) {
             var line = session.doc.getLine(range.start.row);
             var rightChar = line.substring(range.start.column + 1, range.start.column + 2);
             if (rightChar == '"') {
@@ -1671,7 +1672,8 @@ var CstyleBehaviour = function () {
         }
     });
 
-}
+};
+
 oop.inherits(CstyleBehaviour, Behaviour);
 
 exports.CstyleBehaviour = CstyleBehaviour;
@@ -1882,13 +1884,3 @@ var FoldMode = exports.FoldMode = function() {};
 }).call(FoldMode.prototype);
 
 });
-;
-            (function() {
-                window.require(["ace/ace"], function(a) {
-                    if (!window.ace)
-                        window.ace = {};
-                    for (var key in a) if (a.hasOwnProperty(key))
-                        ace[key] = a[key];
-                });
-            })();
-        
\ No newline at end of file
diff --git a/apps/files_texteditor/js/aceeditor/mode-php.js b/apps/files_texteditor/js/aceeditor/mode-php.js
index a60c8df726943f44a717614d5947d651c5ff5277..8b156ab98bc13fc0f42056e5bcd5f3e701f6bd5f 100644
--- a/apps/files_texteditor/js/aceeditor/mode-php.js
+++ b/apps/files_texteditor/js/aceeditor/mode-php.js
@@ -1 +1 @@
-define("ace/mode/php",["require","exports","module","ace/lib/oop","ace/mode/text","ace/tokenizer","ace/mode/php_highlight_rules","ace/mode/matching_brace_outdent","ace/range","ace/mode/behaviour/cstyle","ace/mode/folding/cstyle"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("./text").Mode,f=a("../tokenizer").Tokenizer,g=a("./php_highlight_rules").PhpHighlightRules,h=a("./matching_brace_outdent").MatchingBraceOutdent,i=a("../range").Range,j=a("./behaviour/cstyle").CstyleBehaviour,k=a("./folding/cstyle").FoldMode,l=function(){this.$tokenizer=new f((new g).getRules()),this.$outdent=new h,this.$behaviour=new j,this.foldingRules=new k};d.inherits(l,e),function(){this.toggleCommentLines=function(a,b,c,d){var e=!0,f=/^(\s*)#/;for(var g=c;g<=d;g++)if(!f.test(b.getLine(g))){e=!1;break}if(e){var h=new i(0,0,0,0);for(var g=c;g<=d;g++){var j=b.getLine(g),k=j.match(f);h.start.row=g,h.end.row=g,h.end.column=k[0].length,b.replace(h,k[1])}}else b.indentRows(c,d,"#")},this.getNextLineIndent=function(a,b,c){var d=this.$getIndent(b),e=this.$tokenizer.getLineTokens(b,a),f=e.tokens;if(f.length&&f[f.length-1].type=="comment")return d;if(a=="start"){var g=b.match(/^.*[\{\(\[\:]\s*$/);g&&(d+=c)}return d},this.checkOutdent=function(a,b,c){return this.$outdent.checkOutdent(b,c)},this.autoOutdent=function(a,b,c){this.$outdent.autoOutdent(b,c)}}.call(l.prototype),b.Mode=l}),define("ace/mode/php_highlight_rules",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/mode/doc_comment_highlight_rules","ace/mode/text_highlight_rules"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("../lib/lang"),f=a("./doc_comment_highlight_rules").DocCommentHighlightRules,g=a("./text_highlight_rules").TextHighlightRules,h=function(){var a=new f,b=e.arrayToMap("abs|acos|acosh|addcslashes|addslashes|aggregate|aggregate_info|aggregate_methods|aggregate_methods_by_list|aggregate_methods_by_regexp|aggregate_properties|aggregate_properties_by_list|aggregate_properties_by_regexp|aggregation_info|amqpconnection|amqpexchange|amqpqueue|apache_child_terminate|apache_get_modules|apache_get_version|apache_getenv|apache_lookup_uri|apache_note|apache_request_headers|apache_reset_timeout|apache_response_headers|apache_setenv|apc_add|apc_bin_dump|apc_bin_dumpfile|apc_bin_load|apc_bin_loadfile|apc_cache_info|apc_cas|apc_clear_cache|apc_compile_file|apc_dec|apc_define_constants|apc_delete|apc_delete_file|apc_exists|apc_fetch|apc_inc|apc_load_constants|apc_sma_info|apc_store|apciterator|apd_breakpoint|apd_callstack|apd_clunk|apd_continue|apd_croak|apd_dump_function_table|apd_dump_persistent_resources|apd_dump_regular_resources|apd_echo|apd_get_active_symbols|apd_set_pprof_trace|apd_set_session|apd_set_session_trace|apd_set_session_trace_socket|appenditerator|array|array_change_key_case|array_chunk|array_combine|array_count_values|array_diff|array_diff_assoc|array_diff_key|array_diff_uassoc|array_diff_ukey|array_fill|array_fill_keys|array_filter|array_flip|array_intersect|array_intersect_assoc|array_intersect_key|array_intersect_uassoc|array_intersect_ukey|array_key_exists|array_keys|array_map|array_merge|array_merge_recursive|array_multisort|array_pad|array_pop|array_product|array_push|array_rand|array_reduce|array_replace|array_replace_recursive|array_reverse|array_search|array_shift|array_slice|array_splice|array_sum|array_udiff|array_udiff_assoc|array_udiff_uassoc|array_uintersect|array_uintersect_assoc|array_uintersect_uassoc|array_unique|array_unshift|array_values|array_walk|array_walk_recursive|arrayaccess|arrayiterator|arrayobject|arsort|asin|asinh|asort|assert|assert_options|atan|atan2|atanh|audioproperties|badfunctioncallexception|badmethodcallexception|base64_decode|base64_encode|base_convert|basename|bbcode_add_element|bbcode_add_smiley|bbcode_create|bbcode_destroy|bbcode_parse|bbcode_set_arg_parser|bbcode_set_flags|bcadd|bccomp|bcdiv|bcmod|bcmul|bcompiler_load|bcompiler_load_exe|bcompiler_parse_class|bcompiler_read|bcompiler_write_class|bcompiler_write_constant|bcompiler_write_exe_footer|bcompiler_write_file|bcompiler_write_footer|bcompiler_write_function|bcompiler_write_functions_from_file|bcompiler_write_header|bcompiler_write_included_filename|bcpow|bcpowmod|bcscale|bcsqrt|bcsub|bin2hex|bind_textdomain_codeset|bindec|bindtextdomain|bson_decode|bson_encode|bumpValue|bzclose|bzcompress|bzdecompress|bzerrno|bzerror|bzerrstr|bzflush|bzopen|bzread|bzwrite|cachingiterator|cairo|cairo_create|cairo_font_face_get_type|cairo_font_face_status|cairo_font_options_create|cairo_font_options_equal|cairo_font_options_get_antialias|cairo_font_options_get_hint_metrics|cairo_font_options_get_hint_style|cairo_font_options_get_subpixel_order|cairo_font_options_hash|cairo_font_options_merge|cairo_font_options_set_antialias|cairo_font_options_set_hint_metrics|cairo_font_options_set_hint_style|cairo_font_options_set_subpixel_order|cairo_font_options_status|cairo_format_stride_for_width|cairo_image_surface_create|cairo_image_surface_create_for_data|cairo_image_surface_create_from_png|cairo_image_surface_get_data|cairo_image_surface_get_format|cairo_image_surface_get_height|cairo_image_surface_get_stride|cairo_image_surface_get_width|cairo_matrix_create_scale|cairo_matrix_create_translate|cairo_matrix_invert|cairo_matrix_multiply|cairo_matrix_rotate|cairo_matrix_transform_distance|cairo_matrix_transform_point|cairo_matrix_translate|cairo_pattern_add_color_stop_rgb|cairo_pattern_add_color_stop_rgba|cairo_pattern_create_for_surface|cairo_pattern_create_linear|cairo_pattern_create_radial|cairo_pattern_create_rgb|cairo_pattern_create_rgba|cairo_pattern_get_color_stop_count|cairo_pattern_get_color_stop_rgba|cairo_pattern_get_extend|cairo_pattern_get_filter|cairo_pattern_get_linear_points|cairo_pattern_get_matrix|cairo_pattern_get_radial_circles|cairo_pattern_get_rgba|cairo_pattern_get_surface|cairo_pattern_get_type|cairo_pattern_set_extend|cairo_pattern_set_filter|cairo_pattern_set_matrix|cairo_pattern_status|cairo_pdf_surface_create|cairo_pdf_surface_set_size|cairo_ps_get_levels|cairo_ps_level_to_string|cairo_ps_surface_create|cairo_ps_surface_dsc_begin_page_setup|cairo_ps_surface_dsc_begin_setup|cairo_ps_surface_dsc_comment|cairo_ps_surface_get_eps|cairo_ps_surface_restrict_to_level|cairo_ps_surface_set_eps|cairo_ps_surface_set_size|cairo_scaled_font_create|cairo_scaled_font_extents|cairo_scaled_font_get_ctm|cairo_scaled_font_get_font_face|cairo_scaled_font_get_font_matrix|cairo_scaled_font_get_font_options|cairo_scaled_font_get_scale_matrix|cairo_scaled_font_get_type|cairo_scaled_font_glyph_extents|cairo_scaled_font_status|cairo_scaled_font_text_extents|cairo_surface_copy_page|cairo_surface_create_similar|cairo_surface_finish|cairo_surface_flush|cairo_surface_get_content|cairo_surface_get_device_offset|cairo_surface_get_font_options|cairo_surface_get_type|cairo_surface_mark_dirty|cairo_surface_mark_dirty_rectangle|cairo_surface_set_device_offset|cairo_surface_set_fallback_resolution|cairo_surface_show_page|cairo_surface_status|cairo_surface_write_to_png|cairo_svg_surface_create|cairo_svg_surface_restrict_to_version|cairo_svg_version_to_string|cairoantialias|cairocontent|cairocontext|cairoexception|cairoextend|cairofillrule|cairofilter|cairofontface|cairofontoptions|cairofontslant|cairofonttype|cairofontweight|cairoformat|cairogradientpattern|cairohintmetrics|cairohintstyle|cairoimagesurface|cairolineargradient|cairolinecap|cairolinejoin|cairomatrix|cairooperator|cairopath|cairopattern|cairopatterntype|cairopdfsurface|cairopslevel|cairopssurface|cairoradialgradient|cairoscaledfont|cairosolidpattern|cairostatus|cairosubpixelorder|cairosurface|cairosurfacepattern|cairosurfacetype|cairosvgsurface|cairosvgversion|cairotoyfontface|cal_days_in_month|cal_from_jd|cal_info|cal_to_jd|calcul_hmac|calculhmac|call_user_func|call_user_func_array|call_user_method|call_user_method_array|callbackfilteriterator|ceil|chdb|chdb_create|chdir|checkdate|checkdnsrr|chgrp|chmod|chop|chown|chr|chroot|chunk_split|class_alias|class_exists|class_implements|class_parents|classkit_import|classkit_method_add|classkit_method_copy|classkit_method_redefine|classkit_method_remove|classkit_method_rename|clearstatcache|clone|closedir|closelog|collator|com|com_addref|com_create_guid|com_event_sink|com_get|com_get_active_object|com_invoke|com_isenum|com_load|com_load_typelib|com_message_pump|com_print_typeinfo|com_propget|com_propput|com_propset|com_release|com_set|compact|connection_aborted|connection_status|connection_timeout|constant|construct|construct|construct|convert_cyr_string|convert_uudecode|convert_uuencode|copy|cos|cosh|count|count_chars|countable|counter_bump|counter_bump_value|counter_create|counter_get|counter_get_meta|counter_get_named|counter_get_value|counter_reset|counter_reset_value|crack_check|crack_closedict|crack_getlastmessage|crack_opendict|crc32|create_function|crypt|ctype_alnum|ctype_alpha|ctype_cntrl|ctype_digit|ctype_graph|ctype_lower|ctype_print|ctype_punct|ctype_space|ctype_upper|ctype_xdigit|cubrid_affected_rows|cubrid_bind|cubrid_client_encoding|cubrid_close|cubrid_close_prepare|cubrid_close_request|cubrid_col_get|cubrid_col_size|cubrid_column_names|cubrid_column_types|cubrid_commit|cubrid_connect|cubrid_connect_with_url|cubrid_current_oid|cubrid_data_seek|cubrid_db_name|cubrid_disconnect|cubrid_drop|cubrid_errno|cubrid_error|cubrid_error_code|cubrid_error_code_facility|cubrid_error_msg|cubrid_execute|cubrid_fetch|cubrid_fetch_array|cubrid_fetch_assoc|cubrid_fetch_field|cubrid_fetch_lengths|cubrid_fetch_object|cubrid_fetch_row|cubrid_field_flags|cubrid_field_len|cubrid_field_name|cubrid_field_seek|cubrid_field_table|cubrid_field_type|cubrid_free_result|cubrid_get|cubrid_get_autocommit|cubrid_get_charset|cubrid_get_class_name|cubrid_get_client_info|cubrid_get_db_parameter|cubrid_get_server_info|cubrid_insert_id|cubrid_is_instance|cubrid_list_dbs|cubrid_load_from_glo|cubrid_lob_close|cubrid_lob_export|cubrid_lob_get|cubrid_lob_send|cubrid_lob_size|cubrid_lock_read|cubrid_lock_write|cubrid_move_cursor|cubrid_new_glo|cubrid_next_result|cubrid_num_cols|cubrid_num_fields|cubrid_num_rows|cubrid_ping|cubrid_prepare|cubrid_put|cubrid_query|cubrid_real_escape_string|cubrid_result|cubrid_rollback|cubrid_save_to_glo|cubrid_schema|cubrid_send_glo|cubrid_seq_drop|cubrid_seq_insert|cubrid_seq_put|cubrid_set_add|cubrid_set_autocommit|cubrid_set_db_parameter|cubrid_set_drop|cubrid_unbuffered_query|cubrid_version|curl_close|curl_copy_handle|curl_errno|curl_error|curl_exec|curl_getinfo|curl_init|curl_multi_add_handle|curl_multi_close|curl_multi_exec|curl_multi_getcontent|curl_multi_info_read|curl_multi_init|curl_multi_remove_handle|curl_multi_select|curl_setopt|curl_setopt_array|curl_version|current|cyrus_authenticate|cyrus_bind|cyrus_close|cyrus_connect|cyrus_query|cyrus_unbind|date|date_add|date_create|date_create_from_format|date_date_set|date_default_timezone_get|date_default_timezone_set|date_diff|date_format|date_get_last_errors|date_interval_create_from_date_string|date_interval_format|date_isodate_set|date_modify|date_offset_get|date_parse|date_parse_from_format|date_sub|date_sun_info|date_sunrise|date_sunset|date_time_set|date_timestamp_get|date_timestamp_set|date_timezone_get|date_timezone_set|dateinterval|dateperiod|datetime|datetimezone|db2_autocommit|db2_bind_param|db2_client_info|db2_close|db2_column_privileges|db2_columns|db2_commit|db2_conn_error|db2_conn_errormsg|db2_connect|db2_cursor_type|db2_escape_string|db2_exec|db2_execute|db2_fetch_array|db2_fetch_assoc|db2_fetch_both|db2_fetch_object|db2_fetch_row|db2_field_display_size|db2_field_name|db2_field_num|db2_field_precision|db2_field_scale|db2_field_type|db2_field_width|db2_foreign_keys|db2_free_result|db2_free_stmt|db2_get_option|db2_last_insert_id|db2_lob_read|db2_next_result|db2_num_fields|db2_num_rows|db2_pclose|db2_pconnect|db2_prepare|db2_primary_keys|db2_procedure_columns|db2_procedures|db2_result|db2_rollback|db2_server_info|db2_set_option|db2_special_columns|db2_statistics|db2_stmt_error|db2_stmt_errormsg|db2_table_privileges|db2_tables|dba_close|dba_delete|dba_exists|dba_fetch|dba_firstkey|dba_handlers|dba_insert|dba_key_split|dba_list|dba_nextkey|dba_open|dba_optimize|dba_popen|dba_replace|dba_sync|dbase_add_record|dbase_close|dbase_create|dbase_delete_record|dbase_get_header_info|dbase_get_record|dbase_get_record_with_names|dbase_numfields|dbase_numrecords|dbase_open|dbase_pack|dbase_replace_record|dbplus_add|dbplus_aql|dbplus_chdir|dbplus_close|dbplus_curr|dbplus_errcode|dbplus_errno|dbplus_find|dbplus_first|dbplus_flush|dbplus_freealllocks|dbplus_freelock|dbplus_freerlocks|dbplus_getlock|dbplus_getunique|dbplus_info|dbplus_last|dbplus_lockrel|dbplus_next|dbplus_open|dbplus_prev|dbplus_rchperm|dbplus_rcreate|dbplus_rcrtexact|dbplus_rcrtlike|dbplus_resolve|dbplus_restorepos|dbplus_rkeys|dbplus_ropen|dbplus_rquery|dbplus_rrename|dbplus_rsecindex|dbplus_runlink|dbplus_rzap|dbplus_savepos|dbplus_setindex|dbplus_setindexbynumber|dbplus_sql|dbplus_tcl|dbplus_tremove|dbplus_undo|dbplus_undoprepare|dbplus_unlockrel|dbplus_unselect|dbplus_update|dbplus_xlockrel|dbplus_xunlockrel|dbx_close|dbx_compare|dbx_connect|dbx_error|dbx_escape_string|dbx_fetch_row|dbx_query|dbx_sort|dcgettext|dcngettext|deaggregate|debug_backtrace|debug_print_backtrace|debug_zval_dump|decbin|dechex|decoct|define|define_syslog_variables|defined|deg2rad|delete|dgettext|die|dio_close|dio_fcntl|dio_open|dio_read|dio_seek|dio_stat|dio_tcsetattr|dio_truncate|dio_write|dir|directoryiterator|dirname|disk_free_space|disk_total_space|diskfreespace|dl|dngettext|dns_check_record|dns_get_mx|dns_get_record|dom_import_simplexml|domainexception|domattr|domattribute_name|domattribute_set_value|domattribute_specified|domattribute_value|domcharacterdata|domcomment|domdocument|domdocument_add_root|domdocument_create_attribute|domdocument_create_cdata_section|domdocument_create_comment|domdocument_create_element|domdocument_create_element_ns|domdocument_create_entity_reference|domdocument_create_processing_instruction|domdocument_create_text_node|domdocument_doctype|domdocument_document_element|domdocument_dump_file|domdocument_dump_mem|domdocument_get_element_by_id|domdocument_get_elements_by_tagname|domdocument_html_dump_mem|domdocument_xinclude|domdocumentfragment|domdocumenttype|domdocumenttype_entities|domdocumenttype_internal_subset|domdocumenttype_name|domdocumenttype_notations|domdocumenttype_public_id|domdocumenttype_system_id|domelement|domelement_get_attribute|domelement_get_attribute_node|domelement_get_elements_by_tagname|domelement_has_attribute|domelement_remove_attribute|domelement_set_attribute|domelement_set_attribute_node|domelement_tagname|domentity|domentityreference|domexception|domimplementation|domnamednodemap|domnode|domnode_add_namespace|domnode_append_child|domnode_append_sibling|domnode_attributes|domnode_child_nodes|domnode_clone_node|domnode_dump_node|domnode_first_child|domnode_get_content|domnode_has_attributes|domnode_has_child_nodes|domnode_insert_before|domnode_is_blank_node|domnode_last_child|domnode_next_sibling|domnode_node_name|domnode_node_type|domnode_node_value|domnode_owner_document|domnode_parent_node|domnode_prefix|domnode_previous_sibling|domnode_remove_child|domnode_replace_child|domnode_replace_node|domnode_set_content|domnode_set_name|domnode_set_namespace|domnode_unlink_node|domnodelist|domnotation|domprocessinginstruction|domprocessinginstruction_data|domprocessinginstruction_target|domtext|domxml_new_doc|domxml_open_file|domxml_open_mem|domxml_version|domxml_xmltree|domxml_xslt_stylesheet|domxml_xslt_stylesheet_doc|domxml_xslt_stylesheet_file|domxml_xslt_version|domxpath|domxsltstylesheet_process|domxsltstylesheet_result_dump_file|domxsltstylesheet_result_dump_mem|dotnet|dotnet_load|doubleval|each|easter_date|easter_days|echo|empty|emptyiterator|enchant_broker_describe|enchant_broker_dict_exists|enchant_broker_free|enchant_broker_free_dict|enchant_broker_get_error|enchant_broker_init|enchant_broker_list_dicts|enchant_broker_request_dict|enchant_broker_request_pwl_dict|enchant_broker_set_ordering|enchant_dict_add_to_personal|enchant_dict_add_to_session|enchant_dict_check|enchant_dict_describe|enchant_dict_get_error|enchant_dict_is_in_session|enchant_dict_quick_check|enchant_dict_store_replacement|enchant_dict_suggest|end|ereg|ereg_replace|eregi|eregi_replace|error_get_last|error_log|error_reporting|errorexception|escapeshellarg|escapeshellcmd|eval|event_add|event_base_free|event_base_loop|event_base_loopbreak|event_base_loopexit|event_base_new|event_base_priority_init|event_base_set|event_buffer_base_set|event_buffer_disable|event_buffer_enable|event_buffer_fd_set|event_buffer_free|event_buffer_new|event_buffer_priority_set|event_buffer_read|event_buffer_set_callback|event_buffer_timeout_set|event_buffer_watermark_set|event_buffer_write|event_del|event_free|event_new|event_set|exception|exec|exif_imagetype|exif_read_data|exif_tagname|exif_thumbnail|exit|exp|expect_expectl|expect_popen|explode|expm1|export|export|extension_loaded|extract|ezmlm_hash|fam_cancel_monitor|fam_close|fam_monitor_collection|fam_monitor_directory|fam_monitor_file|fam_next_event|fam_open|fam_pending|fam_resume_monitor|fam_suspend_monitor|fbsql_affected_rows|fbsql_autocommit|fbsql_blob_size|fbsql_change_user|fbsql_clob_size|fbsql_close|fbsql_commit|fbsql_connect|fbsql_create_blob|fbsql_create_clob|fbsql_create_db|fbsql_data_seek|fbsql_database|fbsql_database_password|fbsql_db_query|fbsql_db_status|fbsql_drop_db|fbsql_errno|fbsql_error|fbsql_fetch_array|fbsql_fetch_assoc|fbsql_fetch_field|fbsql_fetch_lengths|fbsql_fetch_object|fbsql_fetch_row|fbsql_field_flags|fbsql_field_len|fbsql_field_name|fbsql_field_seek|fbsql_field_table|fbsql_field_type|fbsql_free_result|fbsql_get_autostart_info|fbsql_hostname|fbsql_insert_id|fbsql_list_dbs|fbsql_list_fields|fbsql_list_tables|fbsql_next_result|fbsql_num_fields|fbsql_num_rows|fbsql_password|fbsql_pconnect|fbsql_query|fbsql_read_blob|fbsql_read_clob|fbsql_result|fbsql_rollback|fbsql_rows_fetched|fbsql_select_db|fbsql_set_characterset|fbsql_set_lob_mode|fbsql_set_password|fbsql_set_transaction|fbsql_start_db|fbsql_stop_db|fbsql_table_name|fbsql_tablename|fbsql_username|fbsql_warnings|fclose|fdf_add_doc_javascript|fdf_add_template|fdf_close|fdf_create|fdf_enum_values|fdf_errno|fdf_error|fdf_get_ap|fdf_get_attachment|fdf_get_encoding|fdf_get_file|fdf_get_flags|fdf_get_opt|fdf_get_status|fdf_get_value|fdf_get_version|fdf_header|fdf_next_field_name|fdf_open|fdf_open_string|fdf_remove_item|fdf_save|fdf_save_string|fdf_set_ap|fdf_set_encoding|fdf_set_file|fdf_set_flags|fdf_set_javascript_action|fdf_set_on_import_javascript|fdf_set_opt|fdf_set_status|fdf_set_submit_form_action|fdf_set_target_frame|fdf_set_value|fdf_set_version|feof|fflush|fgetc|fgetcsv|fgets|fgetss|file|file_exists|file_get_contents|file_put_contents|fileatime|filectime|filegroup|fileinode|filemtime|fileowner|fileperms|filepro|filepro_fieldcount|filepro_fieldname|filepro_fieldtype|filepro_fieldwidth|filepro_retrieve|filepro_rowcount|filesize|filesystemiterator|filetype|filter_has_var|filter_id|filter_input|filter_input_array|filter_list|filter_var|filter_var_array|filteriterator|finfo_buffer|finfo_close|finfo_file|finfo_open|finfo_set_flags|floatval|flock|floor|flush|fmod|fnmatch|fopen|forward_static_call|forward_static_call_array|fpassthru|fprintf|fputcsv|fputs|fread|frenchtojd|fribidi_log2vis|fscanf|fseek|fsockopen|fstat|ftell|ftok|ftp_alloc|ftp_cdup|ftp_chdir|ftp_chmod|ftp_close|ftp_connect|ftp_delete|ftp_exec|ftp_fget|ftp_fput|ftp_get|ftp_get_option|ftp_login|ftp_mdtm|ftp_mkdir|ftp_nb_continue|ftp_nb_fget|ftp_nb_fput|ftp_nb_get|ftp_nb_put|ftp_nlist|ftp_pasv|ftp_put|ftp_pwd|ftp_quit|ftp_raw|ftp_rawlist|ftp_rename|ftp_rmdir|ftp_set_option|ftp_site|ftp_size|ftp_ssl_connect|ftp_systype|ftruncate|func_get_arg|func_get_args|func_num_args|function_exists|fwrite|gc_collect_cycles|gc_disable|gc_enable|gc_enabled|gd_info|gearmanclient|gearmanjob|gearmantask|gearmanworker|geoip_continent_code_by_name|geoip_country_code3_by_name|geoip_country_code_by_name|geoip_country_name_by_name|geoip_database_info|geoip_db_avail|geoip_db_filename|geoip_db_get_all_info|geoip_id_by_name|geoip_isp_by_name|geoip_org_by_name|geoip_record_by_name|geoip_region_by_name|geoip_region_name_by_code|geoip_time_zone_by_country_and_region|getMeta|getNamed|getValue|get_browser|get_called_class|get_cfg_var|get_class|get_class_methods|get_class_vars|get_current_user|get_declared_classes|get_declared_interfaces|get_defined_constants|get_defined_functions|get_defined_vars|get_extension_funcs|get_headers|get_html_translation_table|get_include_path|get_included_files|get_loaded_extensions|get_magic_quotes_gpc|get_magic_quotes_runtime|get_meta_tags|get_object_vars|get_parent_class|get_required_files|get_resource_type|getallheaders|getconstant|getconstants|getconstructor|getcwd|getdate|getdefaultproperties|getdoccomment|getendline|getenv|getextension|getextensionname|getfilename|gethostbyaddr|gethostbyname|gethostbynamel|gethostname|getimagesize|getinterfacenames|getinterfaces|getlastmod|getmethod|getmethods|getmodifiers|getmxrr|getmygid|getmyinode|getmypid|getmyuid|getname|getnamespacename|getopt|getparentclass|getproperties|getproperty|getprotobyname|getprotobynumber|getrandmax|getrusage|getservbyname|getservbyport|getshortname|getstartline|getstaticproperties|getstaticpropertyvalue|gettext|gettimeofday|gettype|glob|globiterator|gmagick|gmagickdraw|gmagickpixel|gmdate|gmmktime|gmp_abs|gmp_add|gmp_and|gmp_clrbit|gmp_cmp|gmp_com|gmp_div|gmp_div_q|gmp_div_qr|gmp_div_r|gmp_divexact|gmp_fact|gmp_gcd|gmp_gcdext|gmp_hamdist|gmp_init|gmp_intval|gmp_invert|gmp_jacobi|gmp_legendre|gmp_mod|gmp_mul|gmp_neg|gmp_nextprime|gmp_or|gmp_perfect_square|gmp_popcount|gmp_pow|gmp_powm|gmp_prob_prime|gmp_random|gmp_scan0|gmp_scan1|gmp_setbit|gmp_sign|gmp_sqrt|gmp_sqrtrem|gmp_strval|gmp_sub|gmp_testbit|gmp_xor|gmstrftime|gnupg_adddecryptkey|gnupg_addencryptkey|gnupg_addsignkey|gnupg_cleardecryptkeys|gnupg_clearencryptkeys|gnupg_clearsignkeys|gnupg_decrypt|gnupg_decryptverify|gnupg_encrypt|gnupg_encryptsign|gnupg_export|gnupg_geterror|gnupg_getprotocol|gnupg_import|gnupg_init|gnupg_keyinfo|gnupg_setarmor|gnupg_seterrormode|gnupg_setsignmode|gnupg_sign|gnupg_verify|gopher_parsedir|grapheme_extract|grapheme_stripos|grapheme_stristr|grapheme_strlen|grapheme_strpos|grapheme_strripos|grapheme_strrpos|grapheme_strstr|grapheme_substr|gregoriantojd|gupnp_context_get_host_ip|gupnp_context_get_port|gupnp_context_get_subscription_timeout|gupnp_context_host_path|gupnp_context_new|gupnp_context_set_subscription_timeout|gupnp_context_timeout_add|gupnp_context_unhost_path|gupnp_control_point_browse_start|gupnp_control_point_browse_stop|gupnp_control_point_callback_set|gupnp_control_point_new|gupnp_device_action_callback_set|gupnp_device_info_get|gupnp_device_info_get_service|gupnp_root_device_get_available|gupnp_root_device_get_relative_location|gupnp_root_device_new|gupnp_root_device_set_available|gupnp_root_device_start|gupnp_root_device_stop|gupnp_service_action_get|gupnp_service_action_return|gupnp_service_action_return_error|gupnp_service_action_set|gupnp_service_freeze_notify|gupnp_service_info_get|gupnp_service_info_get_introspection|gupnp_service_introspection_get_state_variable|gupnp_service_notify|gupnp_service_proxy_action_get|gupnp_service_proxy_action_set|gupnp_service_proxy_add_notify|gupnp_service_proxy_callback_set|gupnp_service_proxy_get_subscribed|gupnp_service_proxy_remove_notify|gupnp_service_proxy_set_subscribed|gupnp_service_thaw_notify|gzclose|gzcompress|gzdecode|gzdeflate|gzencode|gzeof|gzfile|gzgetc|gzgets|gzgetss|gzinflate|gzopen|gzpassthru|gzputs|gzread|gzrewind|gzseek|gztell|gzuncompress|gzwrite|halt_compiler|haruannotation|haruannotation_setborderstyle|haruannotation_sethighlightmode|haruannotation_seticon|haruannotation_setopened|harudestination|harudestination_setfit|harudestination_setfitb|harudestination_setfitbh|harudestination_setfitbv|harudestination_setfith|harudestination_setfitr|harudestination_setfitv|harudestination_setxyz|harudoc|harudoc_addpage|harudoc_addpagelabel|harudoc_construct|harudoc_createoutline|harudoc_getcurrentencoder|harudoc_getcurrentpage|harudoc_getencoder|harudoc_getfont|harudoc_getinfoattr|harudoc_getpagelayout|harudoc_getpagemode|harudoc_getstreamsize|harudoc_insertpage|harudoc_loadjpeg|harudoc_loadpng|harudoc_loadraw|harudoc_loadttc|harudoc_loadttf|harudoc_loadtype1|harudoc_output|harudoc_readfromstream|harudoc_reseterror|harudoc_resetstream|harudoc_save|harudoc_savetostream|harudoc_setcompressionmode|harudoc_setcurrentencoder|harudoc_setencryptionmode|harudoc_setinfoattr|harudoc_setinfodateattr|harudoc_setopenaction|harudoc_setpagelayout|harudoc_setpagemode|harudoc_setpagesconfiguration|harudoc_setpassword|harudoc_setpermission|harudoc_usecnsencodings|harudoc_usecnsfonts|harudoc_usecntencodings|harudoc_usecntfonts|harudoc_usejpencodings|harudoc_usejpfonts|harudoc_usekrencodings|harudoc_usekrfonts|haruencoder|haruencoder_getbytetype|haruencoder_gettype|haruencoder_getunicode|haruencoder_getwritingmode|haruexception|harufont|harufont_getascent|harufont_getcapheight|harufont_getdescent|harufont_getencodingname|harufont_getfontname|harufont_gettextwidth|harufont_getunicodewidth|harufont_getxheight|harufont_measuretext|haruimage|haruimage_getbitspercomponent|haruimage_getcolorspace|haruimage_getheight|haruimage_getsize|haruimage_getwidth|haruimage_setcolormask|haruimage_setmaskimage|haruoutline|haruoutline_setdestination|haruoutline_setopened|harupage|harupage_arc|harupage_begintext|harupage_circle|harupage_closepath|harupage_concat|harupage_createdestination|harupage_createlinkannotation|harupage_createtextannotation|harupage_createurlannotation|harupage_curveto|harupage_curveto2|harupage_curveto3|harupage_drawimage|harupage_ellipse|harupage_endpath|harupage_endtext|harupage_eofill|harupage_eofillstroke|harupage_fill|harupage_fillstroke|harupage_getcharspace|harupage_getcmykfill|harupage_getcmykstroke|harupage_getcurrentfont|harupage_getcurrentfontsize|harupage_getcurrentpos|harupage_getcurrenttextpos|harupage_getdash|harupage_getfillingcolorspace|harupage_getflatness|harupage_getgmode|harupage_getgrayfill|harupage_getgraystroke|harupage_getheight|harupage_gethorizontalscaling|harupage_getlinecap|harupage_getlinejoin|harupage_getlinewidth|harupage_getmiterlimit|harupage_getrgbfill|harupage_getrgbstroke|harupage_getstrokingcolorspace|harupage_gettextleading|harupage_gettextmatrix|harupage_gettextrenderingmode|harupage_gettextrise|harupage_gettextwidth|harupage_gettransmatrix|harupage_getwidth|harupage_getwordspace|harupage_lineto|harupage_measuretext|harupage_movetextpos|harupage_moveto|harupage_movetonextline|harupage_rectangle|harupage_setcharspace|harupage_setcmykfill|harupage_setcmykstroke|harupage_setdash|harupage_setflatness|harupage_setfontandsize|harupage_setgrayfill|harupage_setgraystroke|harupage_setheight|harupage_sethorizontalscaling|harupage_setlinecap|harupage_setlinejoin|harupage_setlinewidth|harupage_setmiterlimit|harupage_setrgbfill|harupage_setrgbstroke|harupage_setrotate|harupage_setsize|harupage_setslideshow|harupage_settextleading|harupage_settextmatrix|harupage_settextrenderingmode|harupage_settextrise|harupage_setwidth|harupage_setwordspace|harupage_showtext|harupage_showtextnextline|harupage_stroke|harupage_textout|harupage_textrect|hasconstant|hash|hash_algos|hash_copy|hash_file|hash_final|hash_hmac|hash_hmac_file|hash_init|hash_update|hash_update_file|hash_update_stream|hasmethod|hasproperty|header|header_register_callback|header_remove|headers_list|headers_sent|hebrev|hebrevc|hex2bin|hexdec|highlight_file|highlight_string|html_entity_decode|htmlentities|htmlspecialchars|htmlspecialchars_decode|http_build_cookie|http_build_query|http_build_str|http_build_url|http_cache_etag|http_cache_last_modified|http_chunked_decode|http_date|http_deflate|http_get|http_get_request_body|http_get_request_body_stream|http_get_request_headers|http_head|http_inflate|http_match_etag|http_match_modified|http_match_request_header|http_negotiate_charset|http_negotiate_content_type|http_negotiate_language|http_parse_cookie|http_parse_headers|http_parse_message|http_parse_params|http_persistent_handles_clean|http_persistent_handles_count|http_persistent_handles_ident|http_post_data|http_post_fields|http_put_data|http_put_file|http_put_stream|http_redirect|http_request|http_request_body_encode|http_request_method_exists|http_request_method_name|http_request_method_register|http_request_method_unregister|http_response_code|http_send_content_disposition|http_send_content_type|http_send_data|http_send_file|http_send_last_modified|http_send_status|http_send_stream|http_support|http_throttle|httpdeflatestream|httpdeflatestream_construct|httpdeflatestream_factory|httpdeflatestream_finish|httpdeflatestream_flush|httpdeflatestream_update|httpinflatestream|httpinflatestream_construct|httpinflatestream_factory|httpinflatestream_finish|httpinflatestream_flush|httpinflatestream_update|httpmessage|httpmessage_addheaders|httpmessage_construct|httpmessage_detach|httpmessage_factory|httpmessage_fromenv|httpmessage_fromstring|httpmessage_getbody|httpmessage_getheader|httpmessage_getheaders|httpmessage_gethttpversion|httpmessage_getparentmessage|httpmessage_getrequestmethod|httpmessage_getrequesturl|httpmessage_getresponsecode|httpmessage_getresponsestatus|httpmessage_gettype|httpmessage_guesscontenttype|httpmessage_prepend|httpmessage_reverse|httpmessage_send|httpmessage_setbody|httpmessage_setheaders|httpmessage_sethttpversion|httpmessage_setrequestmethod|httpmessage_setrequesturl|httpmessage_setresponsecode|httpmessage_setresponsestatus|httpmessage_settype|httpmessage_tomessagetypeobject|httpmessage_tostring|httpquerystring|httpquerystring_construct|httpquerystring_get|httpquerystring_mod|httpquerystring_set|httpquerystring_singleton|httpquerystring_toarray|httpquerystring_tostring|httpquerystring_xlate|httprequest|httprequest_addcookies|httprequest_addheaders|httprequest_addpostfields|httprequest_addpostfile|httprequest_addputdata|httprequest_addquerydata|httprequest_addrawpostdata|httprequest_addssloptions|httprequest_clearhistory|httprequest_construct|httprequest_enablecookies|httprequest_getcontenttype|httprequest_getcookies|httprequest_getheaders|httprequest_gethistory|httprequest_getmethod|httprequest_getoptions|httprequest_getpostfields|httprequest_getpostfiles|httprequest_getputdata|httprequest_getputfile|httprequest_getquerydata|httprequest_getrawpostdata|httprequest_getrawrequestmessage|httprequest_getrawresponsemessage|httprequest_getrequestmessage|httprequest_getresponsebody|httprequest_getresponsecode|httprequest_getresponsecookies|httprequest_getresponsedata|httprequest_getresponseheader|httprequest_getresponseinfo|httprequest_getresponsemessage|httprequest_getresponsestatus|httprequest_getssloptions|httprequest_geturl|httprequest_resetcookies|httprequest_send|httprequest_setcontenttype|httprequest_setcookies|httprequest_setheaders|httprequest_setmethod|httprequest_setoptions|httprequest_setpostfields|httprequest_setpostfiles|httprequest_setputdata|httprequest_setputfile|httprequest_setquerydata|httprequest_setrawpostdata|httprequest_setssloptions|httprequest_seturl|httprequestpool|httprequestpool_attach|httprequestpool_construct|httprequestpool_destruct|httprequestpool_detach|httprequestpool_getattachedrequests|httprequestpool_getfinishedrequests|httprequestpool_reset|httprequestpool_send|httprequestpool_socketperform|httprequestpool_socketselect|httpresponse|httpresponse_capture|httpresponse_getbuffersize|httpresponse_getcache|httpresponse_getcachecontrol|httpresponse_getcontentdisposition|httpresponse_getcontenttype|httpresponse_getdata|httpresponse_getetag|httpresponse_getfile|httpresponse_getgzip|httpresponse_getheader|httpresponse_getlastmodified|httpresponse_getrequestbody|httpresponse_getrequestbodystream|httpresponse_getrequestheaders|httpresponse_getstream|httpresponse_getthrottledelay|httpresponse_guesscontenttype|httpresponse_redirect|httpresponse_send|httpresponse_setbuffersize|httpresponse_setcache|httpresponse_setcachecontrol|httpresponse_setcontentdisposition|httpresponse_setcontenttype|httpresponse_setdata|httpresponse_setetag|httpresponse_setfile|httpresponse_setgzip|httpresponse_setheader|httpresponse_setlastmodified|httpresponse_setstream|httpresponse_setthrottledelay|httpresponse_status|hw_array2objrec|hw_changeobject|hw_children|hw_childrenobj|hw_close|hw_connect|hw_connection_info|hw_cp|hw_deleteobject|hw_docbyanchor|hw_docbyanchorobj|hw_document_attributes|hw_document_bodytag|hw_document_content|hw_document_setcontent|hw_document_size|hw_dummy|hw_edittext|hw_error|hw_errormsg|hw_free_document|hw_getanchors|hw_getanchorsobj|hw_getandlock|hw_getchildcoll|hw_getchildcollobj|hw_getchilddoccoll|hw_getchilddoccollobj|hw_getobject|hw_getobjectbyquery|hw_getobjectbyquerycoll|hw_getobjectbyquerycollobj|hw_getobjectbyqueryobj|hw_getparents|hw_getparentsobj|hw_getrellink|hw_getremote|hw_getremotechildren|hw_getsrcbydestobj|hw_gettext|hw_getusername|hw_identify|hw_incollections|hw_info|hw_inscoll|hw_insdoc|hw_insertanchors|hw_insertdocument|hw_insertobject|hw_mapid|hw_modifyobject|hw_mv|hw_new_document|hw_objrec2array|hw_output_document|hw_pconnect|hw_pipedocument|hw_root|hw_setlinkroot|hw_stat|hw_unlock|hw_who|hwapi_attribute|hwapi_attribute_key|hwapi_attribute_langdepvalue|hwapi_attribute_value|hwapi_attribute_values|hwapi_checkin|hwapi_checkout|hwapi_children|hwapi_content|hwapi_content_mimetype|hwapi_content_read|hwapi_copy|hwapi_dbstat|hwapi_dcstat|hwapi_dstanchors|hwapi_dstofsrcanchor|hwapi_error_count|hwapi_error_reason|hwapi_find|hwapi_ftstat|hwapi_hgcsp|hwapi_hwstat|hwapi_identify|hwapi_info|hwapi_insert|hwapi_insertanchor|hwapi_insertcollection|hwapi_insertdocument|hwapi_link|hwapi_lock|hwapi_move|hwapi_new_content|hwapi_object|hwapi_object_assign|hwapi_object_attreditable|hwapi_object_count|hwapi_object_insert|hwapi_object_new|hwapi_object_remove|hwapi_object_title|hwapi_object_value|hwapi_objectbyanchor|hwapi_parents|hwapi_reason_description|hwapi_reason_type|hwapi_remove|hwapi_replace|hwapi_setcommittedversion|hwapi_srcanchors|hwapi_srcsofdst|hwapi_unlock|hwapi_user|hwapi_userlist|hypot|ibase_add_user|ibase_affected_rows|ibase_backup|ibase_blob_add|ibase_blob_cancel|ibase_blob_close|ibase_blob_create|ibase_blob_echo|ibase_blob_get|ibase_blob_import|ibase_blob_info|ibase_blob_open|ibase_close|ibase_commit|ibase_commit_ret|ibase_connect|ibase_db_info|ibase_delete_user|ibase_drop_db|ibase_errcode|ibase_errmsg|ibase_execute|ibase_fetch_assoc|ibase_fetch_object|ibase_fetch_row|ibase_field_info|ibase_free_event_handler|ibase_free_query|ibase_free_result|ibase_gen_id|ibase_maintain_db|ibase_modify_user|ibase_name_result|ibase_num_fields|ibase_num_params|ibase_param_info|ibase_pconnect|ibase_prepare|ibase_query|ibase_restore|ibase_rollback|ibase_rollback_ret|ibase_server_info|ibase_service_attach|ibase_service_detach|ibase_set_event_handler|ibase_timefmt|ibase_trans|ibase_wait_event|iconv|iconv_get_encoding|iconv_mime_decode|iconv_mime_decode_headers|iconv_mime_encode|iconv_set_encoding|iconv_strlen|iconv_strpos|iconv_strrpos|iconv_substr|id3_get_frame_long_name|id3_get_frame_short_name|id3_get_genre_id|id3_get_genre_list|id3_get_genre_name|id3_get_tag|id3_get_version|id3_remove_tag|id3_set_tag|id3v2attachedpictureframe|id3v2frame|id3v2tag|idate|idn_to_ascii|idn_to_unicode|idn_to_utf8|ifx_affected_rows|ifx_blobinfile_mode|ifx_byteasvarchar|ifx_close|ifx_connect|ifx_copy_blob|ifx_create_blob|ifx_create_char|ifx_do|ifx_error|ifx_errormsg|ifx_fetch_row|ifx_fieldproperties|ifx_fieldtypes|ifx_free_blob|ifx_free_char|ifx_free_result|ifx_get_blob|ifx_get_char|ifx_getsqlca|ifx_htmltbl_result|ifx_nullformat|ifx_num_fields|ifx_num_rows|ifx_pconnect|ifx_prepare|ifx_query|ifx_textasvarchar|ifx_update_blob|ifx_update_char|ifxus_close_slob|ifxus_create_slob|ifxus_free_slob|ifxus_open_slob|ifxus_read_slob|ifxus_seek_slob|ifxus_tell_slob|ifxus_write_slob|ignore_user_abort|iis_add_server|iis_get_dir_security|iis_get_script_map|iis_get_server_by_comment|iis_get_server_by_path|iis_get_server_rights|iis_get_service_state|iis_remove_server|iis_set_app_settings|iis_set_dir_security|iis_set_script_map|iis_set_server_rights|iis_start_server|iis_start_service|iis_stop_server|iis_stop_service|image2wbmp|image_type_to_extension|image_type_to_mime_type|imagealphablending|imageantialias|imagearc|imagechar|imagecharup|imagecolorallocate|imagecolorallocatealpha|imagecolorat|imagecolorclosest|imagecolorclosestalpha|imagecolorclosesthwb|imagecolordeallocate|imagecolorexact|imagecolorexactalpha|imagecolormatch|imagecolorresolve|imagecolorresolvealpha|imagecolorset|imagecolorsforindex|imagecolorstotal|imagecolortransparent|imageconvolution|imagecopy|imagecopymerge|imagecopymergegray|imagecopyresampled|imagecopyresized|imagecreate|imagecreatefromgd|imagecreatefromgd2|imagecreatefromgd2part|imagecreatefromgif|imagecreatefromjpeg|imagecreatefrompng|imagecreatefromstring|imagecreatefromwbmp|imagecreatefromxbm|imagecreatefromxpm|imagecreatetruecolor|imagedashedline|imagedestroy|imageellipse|imagefill|imagefilledarc|imagefilledellipse|imagefilledpolygon|imagefilledrectangle|imagefilltoborder|imagefilter|imagefontheight|imagefontwidth|imageftbbox|imagefttext|imagegammacorrect|imagegd|imagegd2|imagegif|imagegrabscreen|imagegrabwindow|imageinterlace|imageistruecolor|imagejpeg|imagelayereffect|imageline|imageloadfont|imagepalettecopy|imagepng|imagepolygon|imagepsbbox|imagepsencodefont|imagepsextendfont|imagepsfreefont|imagepsloadfont|imagepsslantfont|imagepstext|imagerectangle|imagerotate|imagesavealpha|imagesetbrush|imagesetpixel|imagesetstyle|imagesetthickness|imagesettile|imagestring|imagestringup|imagesx|imagesy|imagetruecolortopalette|imagettfbbox|imagettftext|imagetypes|imagewbmp|imagexbm|imagick|imagick_adaptiveblurimage|imagick_adaptiveresizeimage|imagick_adaptivesharpenimage|imagick_adaptivethresholdimage|imagick_addimage|imagick_addnoiseimage|imagick_affinetransformimage|imagick_animateimages|imagick_annotateimage|imagick_appendimages|imagick_averageimages|imagick_blackthresholdimage|imagick_blurimage|imagick_borderimage|imagick_charcoalimage|imagick_chopimage|imagick_clear|imagick_clipimage|imagick_clippathimage|imagick_clone|imagick_clutimage|imagick_coalesceimages|imagick_colorfloodfillimage|imagick_colorizeimage|imagick_combineimages|imagick_commentimage|imagick_compareimagechannels|imagick_compareimagelayers|imagick_compareimages|imagick_compositeimage|imagick_construct|imagick_contrastimage|imagick_contraststretchimage|imagick_convolveimage|imagick_cropimage|imagick_cropthumbnailimage|imagick_current|imagick_cyclecolormapimage|imagick_decipherimage|imagick_deconstructimages|imagick_deleteimageartifact|imagick_despeckleimage|imagick_destroy|imagick_displayimage|imagick_displayimages|imagick_distortimage|imagick_drawimage|imagick_edgeimage|imagick_embossimage|imagick_encipherimage|imagick_enhanceimage|imagick_equalizeimage|imagick_evaluateimage|imagick_extentimage|imagick_flattenimages|imagick_flipimage|imagick_floodfillpaintimage|imagick_flopimage|imagick_frameimage|imagick_fximage|imagick_gammaimage|imagick_gaussianblurimage|imagick_getcolorspace|imagick_getcompression|imagick_getcompressionquality|imagick_getcopyright|imagick_getfilename|imagick_getfont|imagick_getformat|imagick_getgravity|imagick_gethomeurl|imagick_getimage|imagick_getimagealphachannel|imagick_getimageartifact|imagick_getimagebackgroundcolor|imagick_getimageblob|imagick_getimageblueprimary|imagick_getimagebordercolor|imagick_getimagechanneldepth|imagick_getimagechanneldistortion|imagick_getimagechanneldistortions|imagick_getimagechannelextrema|imagick_getimagechannelmean|imagick_getimagechannelrange|imagick_getimagechannelstatistics|imagick_getimageclipmask|imagick_getimagecolormapcolor|imagick_getimagecolors|imagick_getimagecolorspace|imagick_getimagecompose|imagick_getimagecompression|imagick_getimagecompressionquality|imagick_getimagedelay|imagick_getimagedepth|imagick_getimagedispose|imagick_getimagedistortion|imagick_getimageextrema|imagick_getimagefilename|imagick_getimageformat|imagick_getimagegamma|imagick_getimagegeometry|imagick_getimagegravity|imagick_getimagegreenprimary|imagick_getimageheight|imagick_getimagehistogram|imagick_getimageindex|imagick_getimageinterlacescheme|imagick_getimageinterpolatemethod|imagick_getimageiterations|imagick_getimagelength|imagick_getimagemagicklicense|imagick_getimagematte|imagick_getimagemattecolor|imagick_getimageorientation|imagick_getimagepage|imagick_getimagepixelcolor|imagick_getimageprofile|imagick_getimageprofiles|imagick_getimageproperties|imagick_getimageproperty|imagick_getimageredprimary|imagick_getimageregion|imagick_getimagerenderingintent|imagick_getimageresolution|imagick_getimagesblob|imagick_getimagescene|imagick_getimagesignature|imagick_getimagesize|imagick_getimagetickspersecond|imagick_getimagetotalinkdensity|imagick_getimagetype|imagick_getimageunits|imagick_getimagevirtualpixelmethod|imagick_getimagewhitepoint|imagick_getimagewidth|imagick_getinterlacescheme|imagick_getiteratorindex|imagick_getnumberimages|imagick_getoption|imagick_getpackagename|imagick_getpage|imagick_getpixeliterator|imagick_getpixelregioniterator|imagick_getpointsize|imagick_getquantumdepth|imagick_getquantumrange|imagick_getreleasedate|imagick_getresource|imagick_getresourcelimit|imagick_getsamplingfactors|imagick_getsize|imagick_getsizeoffset|imagick_getversion|imagick_hasnextimage|imagick_haspreviousimage|imagick_identifyimage|imagick_implodeimage|imagick_labelimage|imagick_levelimage|imagick_linearstretchimage|imagick_liquidrescaleimage|imagick_magnifyimage|imagick_mapimage|imagick_mattefloodfillimage|imagick_medianfilterimage|imagick_mergeimagelayers|imagick_minifyimage|imagick_modulateimage|imagick_montageimage|imagick_morphimages|imagick_mosaicimages|imagick_motionblurimage|imagick_negateimage|imagick_newimage|imagick_newpseudoimage|imagick_nextimage|imagick_normalizeimage|imagick_oilpaintimage|imagick_opaquepaintimage|imagick_optimizeimagelayers|imagick_orderedposterizeimage|imagick_paintfloodfillimage|imagick_paintopaqueimage|imagick_painttransparentimage|imagick_pingimage|imagick_pingimageblob|imagick_pingimagefile|imagick_polaroidimage|imagick_posterizeimage|imagick_previewimages|imagick_previousimage|imagick_profileimage|imagick_quantizeimage|imagick_quantizeimages|imagick_queryfontmetrics|imagick_queryfonts|imagick_queryformats|imagick_radialblurimage|imagick_raiseimage|imagick_randomthresholdimage|imagick_readimage|imagick_readimageblob|imagick_readimagefile|imagick_recolorimage|imagick_reducenoiseimage|imagick_removeimage|imagick_removeimageprofile|imagick_render|imagick_resampleimage|imagick_resetimagepage|imagick_resizeimage|imagick_rollimage|imagick_rotateimage|imagick_roundcorners|imagick_sampleimage|imagick_scaleimage|imagick_separateimagechannel|imagick_sepiatoneimage|imagick_setbackgroundcolor|imagick_setcolorspace|imagick_setcompression|imagick_setcompressionquality|imagick_setfilename|imagick_setfirstiterator|imagick_setfont|imagick_setformat|imagick_setgravity|imagick_setimage|imagick_setimagealphachannel|imagick_setimageartifact|imagick_setimagebackgroundcolor|imagick_setimagebias|imagick_setimageblueprimary|imagick_setimagebordercolor|imagick_setimagechanneldepth|imagick_setimageclipmask|imagick_setimagecolormapcolor|imagick_setimagecolorspace|imagick_setimagecompose|imagick_setimagecompression|imagick_setimagecompressionquality|imagick_setimagedelay|imagick_setimagedepth|imagick_setimagedispose|imagick_setimageextent|imagick_setimagefilename|imagick_setimageformat|imagick_setimagegamma|imagick_setimagegravity|imagick_setimagegreenprimary|imagick_setimageindex|imagick_setimageinterlacescheme|imagick_setimageinterpolatemethod|imagick_setimageiterations|imagick_setimagematte|imagick_setimagemattecolor|imagick_setimageopacity|imagick_setimageorientation|imagick_setimagepage|imagick_setimageprofile|imagick_setimageproperty|imagick_setimageredprimary|imagick_setimagerenderingintent|imagick_setimageresolution|imagick_setimagescene|imagick_setimagetickspersecond|imagick_setimagetype|imagick_setimageunits|imagick_setimagevirtualpixelmethod|imagick_setimagewhitepoint|imagick_setinterlacescheme|imagick_setiteratorindex|imagick_setlastiterator|imagick_setoption|imagick_setpage|imagick_setpointsize|imagick_setresolution|imagick_setresourcelimit|imagick_setsamplingfactors|imagick_setsize|imagick_setsizeoffset|imagick_settype|imagick_shadeimage|imagick_shadowimage|imagick_sharpenimage|imagick_shaveimage|imagick_shearimage|imagick_sigmoidalcontrastimage|imagick_sketchimage|imagick_solarizeimage|imagick_spliceimage|imagick_spreadimage|imagick_steganoimage|imagick_stereoimage|imagick_stripimage|imagick_swirlimage|imagick_textureimage|imagick_thresholdimage|imagick_thumbnailimage|imagick_tintimage|imagick_transformimage|imagick_transparentpaintimage|imagick_transposeimage|imagick_transverseimage|imagick_trimimage|imagick_uniqueimagecolors|imagick_unsharpmaskimage|imagick_valid|imagick_vignetteimage|imagick_waveimage|imagick_whitethresholdimage|imagick_writeimage|imagick_writeimagefile|imagick_writeimages|imagick_writeimagesfile|imagickdraw|imagickdraw_affine|imagickdraw_annotation|imagickdraw_arc|imagickdraw_bezier|imagickdraw_circle|imagickdraw_clear|imagickdraw_clone|imagickdraw_color|imagickdraw_comment|imagickdraw_composite|imagickdraw_construct|imagickdraw_destroy|imagickdraw_ellipse|imagickdraw_getclippath|imagickdraw_getcliprule|imagickdraw_getclipunits|imagickdraw_getfillcolor|imagickdraw_getfillopacity|imagickdraw_getfillrule|imagickdraw_getfont|imagickdraw_getfontfamily|imagickdraw_getfontsize|imagickdraw_getfontstyle|imagickdraw_getfontweight|imagickdraw_getgravity|imagickdraw_getstrokeantialias|imagickdraw_getstrokecolor|imagickdraw_getstrokedasharray|imagickdraw_getstrokedashoffset|imagickdraw_getstrokelinecap|imagickdraw_getstrokelinejoin|imagickdraw_getstrokemiterlimit|imagickdraw_getstrokeopacity|imagickdraw_getstrokewidth|imagickdraw_gettextalignment|imagickdraw_gettextantialias|imagickdraw_gettextdecoration|imagickdraw_gettextencoding|imagickdraw_gettextundercolor|imagickdraw_getvectorgraphics|imagickdraw_line|imagickdraw_matte|imagickdraw_pathclose|imagickdraw_pathcurvetoabsolute|imagickdraw_pathcurvetoquadraticbezierabsolute|imagickdraw_pathcurvetoquadraticbezierrelative|imagickdraw_pathcurvetoquadraticbeziersmoothabsolute|imagickdraw_pathcurvetoquadraticbeziersmoothrelative|imagickdraw_pathcurvetorelative|imagickdraw_pathcurvetosmoothabsolute|imagickdraw_pathcurvetosmoothrelative|imagickdraw_pathellipticarcabsolute|imagickdraw_pathellipticarcrelative|imagickdraw_pathfinish|imagickdraw_pathlinetoabsolute|imagickdraw_pathlinetohorizontalabsolute|imagickdraw_pathlinetohorizontalrelative|imagickdraw_pathlinetorelative|imagickdraw_pathlinetoverticalabsolute|imagickdraw_pathlinetoverticalrelative|imagickdraw_pathmovetoabsolute|imagickdraw_pathmovetorelative|imagickdraw_pathstart|imagickdraw_point|imagickdraw_polygon|imagickdraw_polyline|imagickdraw_pop|imagickdraw_popclippath|imagickdraw_popdefs|imagickdraw_poppattern|imagickdraw_push|imagickdraw_pushclippath|imagickdraw_pushdefs|imagickdraw_pushpattern|imagickdraw_rectangle|imagickdraw_render|imagickdraw_rotate|imagickdraw_roundrectangle|imagickdraw_scale|imagickdraw_setclippath|imagickdraw_setcliprule|imagickdraw_setclipunits|imagickdraw_setfillalpha|imagickdraw_setfillcolor|imagickdraw_setfillopacity|imagickdraw_setfillpatternurl|imagickdraw_setfillrule|imagickdraw_setfont|imagickdraw_setfontfamily|imagickdraw_setfontsize|imagickdraw_setfontstretch|imagickdraw_setfontstyle|imagickdraw_setfontweight|imagickdraw_setgravity|imagickdraw_setstrokealpha|imagickdraw_setstrokeantialias|imagickdraw_setstrokecolor|imagickdraw_setstrokedasharray|imagickdraw_setstrokedashoffset|imagickdraw_setstrokelinecap|imagickdraw_setstrokelinejoin|imagickdraw_setstrokemiterlimit|imagickdraw_setstrokeopacity|imagickdraw_setstrokepatternurl|imagickdraw_setstrokewidth|imagickdraw_settextalignment|imagickdraw_settextantialias|imagickdraw_settextdecoration|imagickdraw_settextencoding|imagickdraw_settextundercolor|imagickdraw_setvectorgraphics|imagickdraw_setviewbox|imagickdraw_skewx|imagickdraw_skewy|imagickdraw_translate|imagickpixel|imagickpixel_clear|imagickpixel_construct|imagickpixel_destroy|imagickpixel_getcolor|imagickpixel_getcolorasstring|imagickpixel_getcolorcount|imagickpixel_getcolorvalue|imagickpixel_gethsl|imagickpixel_issimilar|imagickpixel_setcolor|imagickpixel_setcolorvalue|imagickpixel_sethsl|imagickpixeliterator|imagickpixeliterator_clear|imagickpixeliterator_construct|imagickpixeliterator_destroy|imagickpixeliterator_getcurrentiteratorrow|imagickpixeliterator_getiteratorrow|imagickpixeliterator_getnextiteratorrow|imagickpixeliterator_getpreviousiteratorrow|imagickpixeliterator_newpixeliterator|imagickpixeliterator_newpixelregioniterator|imagickpixeliterator_resetiterator|imagickpixeliterator_setiteratorfirstrow|imagickpixeliterator_setiteratorlastrow|imagickpixeliterator_setiteratorrow|imagickpixeliterator_synciterator|imap_8bit|imap_alerts|imap_append|imap_base64|imap_binary|imap_body|imap_bodystruct|imap_check|imap_clearflag_full|imap_close|imap_create|imap_createmailbox|imap_delete|imap_deletemailbox|imap_errors|imap_expunge|imap_fetch_overview|imap_fetchbody|imap_fetchheader|imap_fetchmime|imap_fetchstructure|imap_fetchtext|imap_gc|imap_get_quota|imap_get_quotaroot|imap_getacl|imap_getmailboxes|imap_getsubscribed|imap_header|imap_headerinfo|imap_headers|imap_last_error|imap_list|imap_listmailbox|imap_listscan|imap_listsubscribed|imap_lsub|imap_mail|imap_mail_compose|imap_mail_copy|imap_mail_move|imap_mailboxmsginfo|imap_mime_header_decode|imap_msgno|imap_num_msg|imap_num_recent|imap_open|imap_ping|imap_qprint|imap_rename|imap_renamemailbox|imap_reopen|imap_rfc822_parse_adrlist|imap_rfc822_parse_headers|imap_rfc822_write_address|imap_savebody|imap_scan|imap_scanmailbox|imap_search|imap_set_quota|imap_setacl|imap_setflag_full|imap_sort|imap_status|imap_subscribe|imap_thread|imap_timeout|imap_uid|imap_undelete|imap_unsubscribe|imap_utf7_decode|imap_utf7_encode|imap_utf8|implementsinterface|implode|import_request_variables|in_array|include|include_once|inclued_get_data|inet_ntop|inet_pton|infiniteiterator|ingres_autocommit|ingres_autocommit_state|ingres_charset|ingres_close|ingres_commit|ingres_connect|ingres_cursor|ingres_errno|ingres_error|ingres_errsqlstate|ingres_escape_string|ingres_execute|ingres_fetch_array|ingres_fetch_assoc|ingres_fetch_object|ingres_fetch_proc_return|ingres_fetch_row|ingres_field_length|ingres_field_name|ingres_field_nullable|ingres_field_precision|ingres_field_scale|ingres_field_type|ingres_free_result|ingres_next_error|ingres_num_fields|ingres_num_rows|ingres_pconnect|ingres_prepare|ingres_query|ingres_result_seek|ingres_rollback|ingres_set_environment|ingres_unbuffered_query|ini_alter|ini_get|ini_get_all|ini_restore|ini_set|innamespace|inotify_add_watch|inotify_init|inotify_queue_len|inotify_read|inotify_rm_watch|interface_exists|intl_error_name|intl_get_error_code|intl_get_error_message|intl_is_failure|intldateformatter|intval|invalidargumentexception|invoke|invokeargs|ip2long|iptcembed|iptcparse|is_a|is_array|is_bool|is_callable|is_dir|is_double|is_executable|is_file|is_finite|is_float|is_infinite|is_int|is_integer|is_link|is_long|is_nan|is_null|is_numeric|is_object|is_readable|is_real|is_resource|is_scalar|is_soap_fault|is_string|is_subclass_of|is_uploaded_file|is_writable|is_writeable|isabstract|iscloneable|isdisabled|isfinal|isinstance|isinstantiable|isinterface|isinternal|isiterateable|isset|issubclassof|isuserdefined|iterator|iterator_apply|iterator_count|iterator_to_array|iteratoraggregate|iteratoriterator|java_last_exception_clear|java_last_exception_get|jddayofweek|jdmonthname|jdtofrench|jdtogregorian|jdtojewish|jdtojulian|jdtounix|jewishtojd|join|jpeg2wbmp|json_decode|json_encode|json_last_error|jsonserializable|judy|judy_type|judy_version|juliantojd|kadm5_chpass_principal|kadm5_create_principal|kadm5_delete_principal|kadm5_destroy|kadm5_flush|kadm5_get_policies|kadm5_get_principal|kadm5_get_principals|kadm5_init_with_password|kadm5_modify_principal|key|krsort|ksort|lcfirst|lcg_value|lchgrp|lchown|ldap_8859_to_t61|ldap_add|ldap_bind|ldap_close|ldap_compare|ldap_connect|ldap_count_entries|ldap_delete|ldap_dn2ufn|ldap_err2str|ldap_errno|ldap_error|ldap_explode_dn|ldap_first_attribute|ldap_first_entry|ldap_first_reference|ldap_free_result|ldap_get_attributes|ldap_get_dn|ldap_get_entries|ldap_get_option|ldap_get_values|ldap_get_values_len|ldap_list|ldap_mod_add|ldap_mod_del|ldap_mod_replace|ldap_modify|ldap_next_attribute|ldap_next_entry|ldap_next_reference|ldap_parse_reference|ldap_parse_result|ldap_read|ldap_rename|ldap_sasl_bind|ldap_search|ldap_set_option|ldap_set_rebind_proc|ldap_sort|ldap_start_tls|ldap_t61_to_8859|ldap_unbind|lengthexception|levenshtein|libxml_clear_errors|libxml_disable_entity_loader|libxml_get_errors|libxml_get_last_error|libxml_set_streams_context|libxml_use_internal_errors|libxmlerror|limititerator|link|linkinfo|list|locale|localeconv|localtime|log|log10|log1p|logicexception|long2ip|lstat|ltrim|lzf_compress|lzf_decompress|lzf_optimized_for|m_checkstatus|m_completeauthorizations|m_connect|m_connectionerror|m_deletetrans|m_destroyconn|m_destroyengine|m_getcell|m_getcellbynum|m_getcommadelimited|m_getheader|m_initconn|m_initengine|m_iscommadelimited|m_maxconntimeout|m_monitor|m_numcolumns|m_numrows|m_parsecommadelimited|m_responsekeys|m_responseparam|m_returnstatus|m_setblocking|m_setdropfile|m_setip|m_setssl|m_setssl_cafile|m_setssl_files|m_settimeout|m_sslcert_gen_hash|m_transactionssent|m_transinqueue|m_transkeyval|m_transnew|m_transsend|m_uwait|m_validateidentifier|m_verifyconnection|m_verifysslcert|magic_quotes_runtime|mail|mailparse_determine_best_xfer_encoding|mailparse_msg_create|mailparse_msg_extract_part|mailparse_msg_extract_part_file|mailparse_msg_extract_whole_part_file|mailparse_msg_free|mailparse_msg_get_part|mailparse_msg_get_part_data|mailparse_msg_get_structure|mailparse_msg_parse|mailparse_msg_parse_file|mailparse_rfc822_parse_addresses|mailparse_stream_encode|mailparse_uudecode_all|main|max|maxdb_affected_rows|maxdb_autocommit|maxdb_bind_param|maxdb_bind_result|maxdb_change_user|maxdb_character_set_name|maxdb_client_encoding|maxdb_close|maxdb_close_long_data|maxdb_commit|maxdb_connect|maxdb_connect_errno|maxdb_connect_error|maxdb_data_seek|maxdb_debug|maxdb_disable_reads_from_master|maxdb_disable_rpl_parse|maxdb_dump_debug_info|maxdb_embedded_connect|maxdb_enable_reads_from_master|maxdb_enable_rpl_parse|maxdb_errno|maxdb_error|maxdb_escape_string|maxdb_execute|maxdb_fetch|maxdb_fetch_array|maxdb_fetch_assoc|maxdb_fetch_field|maxdb_fetch_field_direct|maxdb_fetch_fields|maxdb_fetch_lengths|maxdb_fetch_object|maxdb_fetch_row|maxdb_field_count|maxdb_field_seek|maxdb_field_tell|maxdb_free_result|maxdb_get_client_info|maxdb_get_client_version|maxdb_get_host_info|maxdb_get_metadata|maxdb_get_proto_info|maxdb_get_server_info|maxdb_get_server_version|maxdb_info|maxdb_init|maxdb_insert_id|maxdb_kill|maxdb_master_query|maxdb_more_results|maxdb_multi_query|maxdb_next_result|maxdb_num_fields|maxdb_num_rows|maxdb_options|maxdb_param_count|maxdb_ping|maxdb_prepare|maxdb_query|maxdb_real_connect|maxdb_real_escape_string|maxdb_real_query|maxdb_report|maxdb_rollback|maxdb_rpl_parse_enabled|maxdb_rpl_probe|maxdb_rpl_query_type|maxdb_select_db|maxdb_send_long_data|maxdb_send_query|maxdb_server_end|maxdb_server_init|maxdb_set_opt|maxdb_sqlstate|maxdb_ssl_set|maxdb_stat|maxdb_stmt_affected_rows|maxdb_stmt_bind_param|maxdb_stmt_bind_result|maxdb_stmt_close|maxdb_stmt_close_long_data|maxdb_stmt_data_seek|maxdb_stmt_errno|maxdb_stmt_error|maxdb_stmt_execute|maxdb_stmt_fetch|maxdb_stmt_free_result|maxdb_stmt_init|maxdb_stmt_num_rows|maxdb_stmt_param_count|maxdb_stmt_prepare|maxdb_stmt_reset|maxdb_stmt_result_metadata|maxdb_stmt_send_long_data|maxdb_stmt_sqlstate|maxdb_stmt_store_result|maxdb_store_result|maxdb_thread_id|maxdb_thread_safe|maxdb_use_result|maxdb_warning_count|mb_check_encoding|mb_convert_case|mb_convert_encoding|mb_convert_kana|mb_convert_variables|mb_decode_mimeheader|mb_decode_numericentity|mb_detect_encoding|mb_detect_order|mb_encode_mimeheader|mb_encode_numericentity|mb_encoding_aliases|mb_ereg|mb_ereg_match|mb_ereg_replace|mb_ereg_search|mb_ereg_search_getpos|mb_ereg_search_getregs|mb_ereg_search_init|mb_ereg_search_pos|mb_ereg_search_regs|mb_ereg_search_setpos|mb_eregi|mb_eregi_replace|mb_get_info|mb_http_input|mb_http_output|mb_internal_encoding|mb_language|mb_list_encodings|mb_output_handler|mb_parse_str|mb_preferred_mime_name|mb_regex_encoding|mb_regex_set_options|mb_send_mail|mb_split|mb_strcut|mb_strimwidth|mb_stripos|mb_stristr|mb_strlen|mb_strpos|mb_strrchr|mb_strrichr|mb_strripos|mb_strrpos|mb_strstr|mb_strtolower|mb_strtoupper|mb_strwidth|mb_substitute_character|mb_substr|mb_substr_count|mcrypt_cbc|mcrypt_cfb|mcrypt_create_iv|mcrypt_decrypt|mcrypt_ecb|mcrypt_enc_get_algorithms_name|mcrypt_enc_get_block_size|mcrypt_enc_get_iv_size|mcrypt_enc_get_key_size|mcrypt_enc_get_modes_name|mcrypt_enc_get_supported_key_sizes|mcrypt_enc_is_block_algorithm|mcrypt_enc_is_block_algorithm_mode|mcrypt_enc_is_block_mode|mcrypt_enc_self_test|mcrypt_encrypt|mcrypt_generic|mcrypt_generic_deinit|mcrypt_generic_end|mcrypt_generic_init|mcrypt_get_block_size|mcrypt_get_cipher_name|mcrypt_get_iv_size|mcrypt_get_key_size|mcrypt_list_algorithms|mcrypt_list_modes|mcrypt_module_close|mcrypt_module_get_algo_block_size|mcrypt_module_get_algo_key_size|mcrypt_module_get_supported_key_sizes|mcrypt_module_is_block_algorithm|mcrypt_module_is_block_algorithm_mode|mcrypt_module_is_block_mode|mcrypt_module_open|mcrypt_module_self_test|mcrypt_ofb|md5|md5_file|mdecrypt_generic|memcache|memcache_debug|memcached|memory_get_peak_usage|memory_get_usage|messageformatter|metaphone|method_exists|mhash|mhash_count|mhash_get_block_size|mhash_get_hash_name|mhash_keygen_s2k|microtime|mime_content_type|min|ming_keypress|ming_setcubicthreshold|ming_setscale|ming_setswfcompression|ming_useconstants|ming_useswfversion|mkdir|mktime|money_format|mongo|mongobindata|mongocode|mongocollection|mongoconnectionexception|mongocursor|mongocursorexception|mongocursortimeoutexception|mongodate|mongodb|mongodbref|mongoexception|mongogridfs|mongogridfscursor|mongogridfsexception|mongogridfsfile|mongoid|mongoint32|mongoint64|mongomaxkey|mongominkey|mongoregex|mongotimestamp|move_uploaded_file|mpegfile|mqseries_back|mqseries_begin|mqseries_close|mqseries_cmit|mqseries_conn|mqseries_connx|mqseries_disc|mqseries_get|mqseries_inq|mqseries_open|mqseries_put|mqseries_put1|mqseries_set|mqseries_strerror|msession_connect|msession_count|msession_create|msession_destroy|msession_disconnect|msession_find|msession_get|msession_get_array|msession_get_data|msession_inc|msession_list|msession_listvar|msession_lock|msession_plugin|msession_randstr|msession_set|msession_set_array|msession_set_data|msession_timeout|msession_uniq|msession_unlock|msg_get_queue|msg_queue_exists|msg_receive|msg_remove_queue|msg_send|msg_set_queue|msg_stat_queue|msql|msql_affected_rows|msql_close|msql_connect|msql_create_db|msql_createdb|msql_data_seek|msql_db_query|msql_dbname|msql_drop_db|msql_error|msql_fetch_array|msql_fetch_field|msql_fetch_object|msql_fetch_row|msql_field_flags|msql_field_len|msql_field_name|msql_field_seek|msql_field_table|msql_field_type|msql_fieldflags|msql_fieldlen|msql_fieldname|msql_fieldtable|msql_fieldtype|msql_free_result|msql_list_dbs|msql_list_fields|msql_list_tables|msql_num_fields|msql_num_rows|msql_numfields|msql_numrows|msql_pconnect|msql_query|msql_regcase|msql_result|msql_select_db|msql_tablename|mssql_bind|mssql_close|mssql_connect|mssql_data_seek|mssql_execute|mssql_fetch_array|mssql_fetch_assoc|mssql_fetch_batch|mssql_fetch_field|mssql_fetch_object|mssql_fetch_row|mssql_field_length|mssql_field_name|mssql_field_seek|mssql_field_type|mssql_free_result|mssql_free_statement|mssql_get_last_message|mssql_guid_string|mssql_init|mssql_min_error_severity|mssql_min_message_severity|mssql_next_result|mssql_num_fields|mssql_num_rows|mssql_pconnect|mssql_query|mssql_result|mssql_rows_affected|mssql_select_db|mt_getrandmax|mt_rand|mt_srand|multipleiterator|mysql_affected_rows|mysql_client_encoding|mysql_close|mysql_connect|mysql_create_db|mysql_data_seek|mysql_db_name|mysql_db_query|mysql_drop_db|mysql_errno|mysql_error|mysql_escape_string|mysql_fetch_array|mysql_fetch_assoc|mysql_fetch_field|mysql_fetch_lengths|mysql_fetch_object|mysql_fetch_row|mysql_field_flags|mysql_field_len|mysql_field_name|mysql_field_seek|mysql_field_table|mysql_field_type|mysql_free_result|mysql_get_client_info|mysql_get_host_info|mysql_get_proto_info|mysql_get_server_info|mysql_info|mysql_insert_id|mysql_list_dbs|mysql_list_fields|mysql_list_processes|mysql_list_tables|mysql_num_fields|mysql_num_rows|mysql_pconnect|mysql_ping|mysql_query|mysql_real_escape_string|mysql_result|mysql_select_db|mysql_set_charset|mysql_stat|mysql_tablename|mysql_thread_id|mysql_unbuffered_query|mysqli|mysqli_bind_param|mysqli_bind_result|mysqli_client_encoding|mysqli_connect|mysqli_disable_reads_from_master|mysqli_disable_rpl_parse|mysqli_driver|mysqli_enable_reads_from_master|mysqli_enable_rpl_parse|mysqli_escape_string|mysqli_execute|mysqli_fetch|mysqli_get_metadata|mysqli_master_query|mysqli_param_count|mysqli_report|mysqli_result|mysqli_rpl_parse_enabled|mysqli_rpl_probe|mysqli_rpl_query_type|mysqli_send_long_data|mysqli_send_query|mysqli_set_opt|mysqli_slave_query|mysqli_stmt|mysqli_warning|mysqlnd_ms_get_stats|mysqlnd_ms_query_is_select|mysqlnd_ms_set_user_pick_server|mysqlnd_qc_change_handler|mysqlnd_qc_clear_cache|mysqlnd_qc_get_cache_info|mysqlnd_qc_get_core_stats|mysqlnd_qc_get_handler|mysqlnd_qc_get_query_trace_log|mysqlnd_qc_set_user_handlers|natcasesort|natsort|ncurses_addch|ncurses_addchnstr|ncurses_addchstr|ncurses_addnstr|ncurses_addstr|ncurses_assume_default_colors|ncurses_attroff|ncurses_attron|ncurses_attrset|ncurses_baudrate|ncurses_beep|ncurses_bkgd|ncurses_bkgdset|ncurses_border|ncurses_bottom_panel|ncurses_can_change_color|ncurses_cbreak|ncurses_clear|ncurses_clrtobot|ncurses_clrtoeol|ncurses_color_content|ncurses_color_set|ncurses_curs_set|ncurses_def_prog_mode|ncurses_def_shell_mode|ncurses_define_key|ncurses_del_panel|ncurses_delay_output|ncurses_delch|ncurses_deleteln|ncurses_delwin|ncurses_doupdate|ncurses_echo|ncurses_echochar|ncurses_end|ncurses_erase|ncurses_erasechar|ncurses_filter|ncurses_flash|ncurses_flushinp|ncurses_getch|ncurses_getmaxyx|ncurses_getmouse|ncurses_getyx|ncurses_halfdelay|ncurses_has_colors|ncurses_has_ic|ncurses_has_il|ncurses_has_key|ncurses_hide_panel|ncurses_hline|ncurses_inch|ncurses_init|ncurses_init_color|ncurses_init_pair|ncurses_insch|ncurses_insdelln|ncurses_insertln|ncurses_insstr|ncurses_instr|ncurses_isendwin|ncurses_keyok|ncurses_keypad|ncurses_killchar|ncurses_longname|ncurses_meta|ncurses_mouse_trafo|ncurses_mouseinterval|ncurses_mousemask|ncurses_move|ncurses_move_panel|ncurses_mvaddch|ncurses_mvaddchnstr|ncurses_mvaddchstr|ncurses_mvaddnstr|ncurses_mvaddstr|ncurses_mvcur|ncurses_mvdelch|ncurses_mvgetch|ncurses_mvhline|ncurses_mvinch|ncurses_mvvline|ncurses_mvwaddstr|ncurses_napms|ncurses_new_panel|ncurses_newpad|ncurses_newwin|ncurses_nl|ncurses_nocbreak|ncurses_noecho|ncurses_nonl|ncurses_noqiflush|ncurses_noraw|ncurses_pair_content|ncurses_panel_above|ncurses_panel_below|ncurses_panel_window|ncurses_pnoutrefresh|ncurses_prefresh|ncurses_putp|ncurses_qiflush|ncurses_raw|ncurses_refresh|ncurses_replace_panel|ncurses_reset_prog_mode|ncurses_reset_shell_mode|ncurses_resetty|ncurses_savetty|ncurses_scr_dump|ncurses_scr_init|ncurses_scr_restore|ncurses_scr_set|ncurses_scrl|ncurses_show_panel|ncurses_slk_attr|ncurses_slk_attroff|ncurses_slk_attron|ncurses_slk_attrset|ncurses_slk_clear|ncurses_slk_color|ncurses_slk_init|ncurses_slk_noutrefresh|ncurses_slk_refresh|ncurses_slk_restore|ncurses_slk_set|ncurses_slk_touch|ncurses_standend|ncurses_standout|ncurses_start_color|ncurses_termattrs|ncurses_termname|ncurses_timeout|ncurses_top_panel|ncurses_typeahead|ncurses_ungetch|ncurses_ungetmouse|ncurses_update_panels|ncurses_use_default_colors|ncurses_use_env|ncurses_use_extended_names|ncurses_vidattr|ncurses_vline|ncurses_waddch|ncurses_waddstr|ncurses_wattroff|ncurses_wattron|ncurses_wattrset|ncurses_wborder|ncurses_wclear|ncurses_wcolor_set|ncurses_werase|ncurses_wgetch|ncurses_whline|ncurses_wmouse_trafo|ncurses_wmove|ncurses_wnoutrefresh|ncurses_wrefresh|ncurses_wstandend|ncurses_wstandout|ncurses_wvline|newinstance|newinstanceargs|newt_bell|newt_button|newt_button_bar|newt_centered_window|newt_checkbox|newt_checkbox_get_value|newt_checkbox_set_flags|newt_checkbox_set_value|newt_checkbox_tree|newt_checkbox_tree_add_item|newt_checkbox_tree_find_item|newt_checkbox_tree_get_current|newt_checkbox_tree_get_entry_value|newt_checkbox_tree_get_multi_selection|newt_checkbox_tree_get_selection|newt_checkbox_tree_multi|newt_checkbox_tree_set_current|newt_checkbox_tree_set_entry|newt_checkbox_tree_set_entry_value|newt_checkbox_tree_set_width|newt_clear_key_buffer|newt_cls|newt_compact_button|newt_component_add_callback|newt_component_takes_focus|newt_create_grid|newt_cursor_off|newt_cursor_on|newt_delay|newt_draw_form|newt_draw_root_text|newt_entry|newt_entry_get_value|newt_entry_set|newt_entry_set_filter|newt_entry_set_flags|newt_finished|newt_form|newt_form_add_component|newt_form_add_components|newt_form_add_hot_key|newt_form_destroy|newt_form_get_current|newt_form_run|newt_form_set_background|newt_form_set_height|newt_form_set_size|newt_form_set_timer|newt_form_set_width|newt_form_watch_fd|newt_get_screen_size|newt_grid_add_components_to_form|newt_grid_basic_window|newt_grid_free|newt_grid_get_size|newt_grid_h_close_stacked|newt_grid_h_stacked|newt_grid_place|newt_grid_set_field|newt_grid_simple_window|newt_grid_v_close_stacked|newt_grid_v_stacked|newt_grid_wrapped_window|newt_grid_wrapped_window_at|newt_init|newt_label|newt_label_set_text|newt_listbox|newt_listbox_append_entry|newt_listbox_clear|newt_listbox_clear_selection|newt_listbox_delete_entry|newt_listbox_get_current|newt_listbox_get_selection|newt_listbox_insert_entry|newt_listbox_item_count|newt_listbox_select_item|newt_listbox_set_current|newt_listbox_set_current_by_key|newt_listbox_set_data|newt_listbox_set_entry|newt_listbox_set_width|newt_listitem|newt_listitem_get_data|newt_listitem_set|newt_open_window|newt_pop_help_line|newt_pop_window|newt_push_help_line|newt_radio_get_current|newt_radiobutton|newt_redraw_help_line|newt_reflow_text|newt_refresh|newt_resize_screen|newt_resume|newt_run_form|newt_scale|newt_scale_set|newt_scrollbar_set|newt_set_help_callback|newt_set_suspend_callback|newt_suspend|newt_textbox|newt_textbox_get_num_lines|newt_textbox_reflowed|newt_textbox_set_height|newt_textbox_set_text|newt_vertical_scrollbar|newt_wait_for_key|newt_win_choice|newt_win_entries|newt_win_menu|newt_win_message|newt_win_messagev|newt_win_ternary|next|ngettext|nl2br|nl_langinfo|norewinditerator|normalizer|notes_body|notes_copy_db|notes_create_db|notes_create_note|notes_drop_db|notes_find_note|notes_header_info|notes_list_msgs|notes_mark_read|notes_mark_unread|notes_nav_create|notes_search|notes_unread|notes_version|nsapi_request_headers|nsapi_response_headers|nsapi_virtual|nthmac|number_format|numberformatter|oauth|oauth_get_sbs|oauth_urlencode|oauthexception|oauthprovider|ob_clean|ob_deflatehandler|ob_end_clean|ob_end_flush|ob_etaghandler|ob_flush|ob_get_clean|ob_get_contents|ob_get_flush|ob_get_length|ob_get_level|ob_get_status|ob_gzhandler|ob_iconv_handler|ob_implicit_flush|ob_inflatehandler|ob_list_handlers|ob_start|ob_tidyhandler|oci_bind_array_by_name|oci_bind_by_name|oci_cancel|oci_client_version|oci_close|oci_collection_append|oci_collection_assign|oci_collection_element_assign|oci_collection_element_get|oci_collection_free|oci_collection_max|oci_collection_size|oci_collection_trim|oci_commit|oci_connect|oci_define_by_name|oci_error|oci_execute|oci_fetch|oci_fetch_all|oci_fetch_array|oci_fetch_assoc|oci_fetch_object|oci_fetch_row|oci_field_is_null|oci_field_name|oci_field_precision|oci_field_scale|oci_field_size|oci_field_type|oci_field_type_raw|oci_free_statement|oci_internal_debug|oci_lob_append|oci_lob_close|oci_lob_copy|oci_lob_eof|oci_lob_erase|oci_lob_export|oci_lob_flush|oci_lob_free|oci_lob_getbuffering|oci_lob_import|oci_lob_is_equal|oci_lob_load|oci_lob_read|oci_lob_rewind|oci_lob_save|oci_lob_savefile|oci_lob_seek|oci_lob_setbuffering|oci_lob_size|oci_lob_tell|oci_lob_truncate|oci_lob_write|oci_lob_writetemporary|oci_lob_writetofile|oci_new_collection|oci_new_connect|oci_new_cursor|oci_new_descriptor|oci_num_fields|oci_num_rows|oci_parse|oci_password_change|oci_pconnect|oci_result|oci_rollback|oci_server_version|oci_set_action|oci_set_client_identifier|oci_set_client_info|oci_set_edition|oci_set_module_name|oci_set_prefetch|oci_statement_type|ocibindbyname|ocicancel|ocicloselob|ocicollappend|ocicollassign|ocicollassignelem|ocicollgetelem|ocicollmax|ocicollsize|ocicolltrim|ocicolumnisnull|ocicolumnname|ocicolumnprecision|ocicolumnscale|ocicolumnsize|ocicolumntype|ocicolumntyperaw|ocicommit|ocidefinebyname|ocierror|ociexecute|ocifetch|ocifetchinto|ocifetchstatement|ocifreecollection|ocifreecursor|ocifreedesc|ocifreestatement|ociinternaldebug|ociloadlob|ocilogoff|ocilogon|ocinewcollection|ocinewcursor|ocinewdescriptor|ocinlogon|ocinumcols|ociparse|ociplogon|ociresult|ocirollback|ocirowcount|ocisavelob|ocisavelobfile|ociserverversion|ocisetprefetch|ocistatementtype|ociwritelobtofile|ociwritetemporarylob|octdec|odbc_autocommit|odbc_binmode|odbc_close|odbc_close_all|odbc_columnprivileges|odbc_columns|odbc_commit|odbc_connect|odbc_cursor|odbc_data_source|odbc_do|odbc_error|odbc_errormsg|odbc_exec|odbc_execute|odbc_fetch_array|odbc_fetch_into|odbc_fetch_object|odbc_fetch_row|odbc_field_len|odbc_field_name|odbc_field_num|odbc_field_precision|odbc_field_scale|odbc_field_type|odbc_foreignkeys|odbc_free_result|odbc_gettypeinfo|odbc_longreadlen|odbc_next_result|odbc_num_fields|odbc_num_rows|odbc_pconnect|odbc_prepare|odbc_primarykeys|odbc_procedurecolumns|odbc_procedures|odbc_result|odbc_result_all|odbc_rollback|odbc_setoption|odbc_specialcolumns|odbc_statistics|odbc_tableprivileges|odbc_tables|openal_buffer_create|openal_buffer_data|openal_buffer_destroy|openal_buffer_get|openal_buffer_loadwav|openal_context_create|openal_context_current|openal_context_destroy|openal_context_process|openal_context_suspend|openal_device_close|openal_device_open|openal_listener_get|openal_listener_set|openal_source_create|openal_source_destroy|openal_source_get|openal_source_pause|openal_source_play|openal_source_rewind|openal_source_set|openal_source_stop|openal_stream|opendir|openlog|openssl_cipher_iv_length|openssl_csr_export|openssl_csr_export_to_file|openssl_csr_get_public_key|openssl_csr_get_subject|openssl_csr_new|openssl_csr_sign|openssl_decrypt|openssl_dh_compute_key|openssl_digest|openssl_encrypt|openssl_error_string|openssl_free_key|openssl_get_cipher_methods|openssl_get_md_methods|openssl_get_privatekey|openssl_get_publickey|openssl_open|openssl_pkcs12_export|openssl_pkcs12_export_to_file|openssl_pkcs12_read|openssl_pkcs7_decrypt|openssl_pkcs7_encrypt|openssl_pkcs7_sign|openssl_pkcs7_verify|openssl_pkey_export|openssl_pkey_export_to_file|openssl_pkey_free|openssl_pkey_get_details|openssl_pkey_get_private|openssl_pkey_get_public|openssl_pkey_new|openssl_private_decrypt|openssl_private_encrypt|openssl_public_decrypt|openssl_public_encrypt|openssl_random_pseudo_bytes|openssl_seal|openssl_sign|openssl_verify|openssl_x509_check_private_key|openssl_x509_checkpurpose|openssl_x509_export|openssl_x509_export_to_file|openssl_x509_free|openssl_x509_parse|openssl_x509_read|ord|outeriterator|outofboundsexception|outofrangeexception|output_add_rewrite_var|output_reset_rewrite_vars|overflowexception|overload|override_function|ovrimos_close|ovrimos_commit|ovrimos_connect|ovrimos_cursor|ovrimos_exec|ovrimos_execute|ovrimos_fetch_into|ovrimos_fetch_row|ovrimos_field_len|ovrimos_field_name|ovrimos_field_num|ovrimos_field_type|ovrimos_free_result|ovrimos_longreadlen|ovrimos_num_fields|ovrimos_num_rows|ovrimos_prepare|ovrimos_result|ovrimos_result_all|ovrimos_rollback|pack|parentiterator|parse_ini_file|parse_ini_string|parse_str|parse_url|parsekit_compile_file|parsekit_compile_string|parsekit_func_arginfo|passthru|pathinfo|pclose|pcntl_alarm|pcntl_exec|pcntl_fork|pcntl_getpriority|pcntl_setpriority|pcntl_signal|pcntl_signal_dispatch|pcntl_sigprocmask|pcntl_sigtimedwait|pcntl_sigwaitinfo|pcntl_wait|pcntl_waitpid|pcntl_wexitstatus|pcntl_wifexited|pcntl_wifsignaled|pcntl_wifstopped|pcntl_wstopsig|pcntl_wtermsig|pdf_activate_item|pdf_add_annotation|pdf_add_bookmark|pdf_add_launchlink|pdf_add_locallink|pdf_add_nameddest|pdf_add_note|pdf_add_outline|pdf_add_pdflink|pdf_add_table_cell|pdf_add_textflow|pdf_add_thumbnail|pdf_add_weblink|pdf_arc|pdf_arcn|pdf_attach_file|pdf_begin_document|pdf_begin_font|pdf_begin_glyph|pdf_begin_item|pdf_begin_layer|pdf_begin_page|pdf_begin_page_ext|pdf_begin_pattern|pdf_begin_template|pdf_begin_template_ext|pdf_circle|pdf_clip|pdf_close|pdf_close_image|pdf_close_pdi|pdf_close_pdi_page|pdf_closepath|pdf_closepath_fill_stroke|pdf_closepath_stroke|pdf_concat|pdf_continue_text|pdf_create_3dview|pdf_create_action|pdf_create_annotation|pdf_create_bookmark|pdf_create_field|pdf_create_fieldgroup|pdf_create_gstate|pdf_create_pvf|pdf_create_textflow|pdf_curveto|pdf_define_layer|pdf_delete|pdf_delete_pvf|pdf_delete_table|pdf_delete_textflow|pdf_encoding_set_char|pdf_end_document|pdf_end_font|pdf_end_glyph|pdf_end_item|pdf_end_layer|pdf_end_page|pdf_end_page_ext|pdf_end_pattern|pdf_end_template|pdf_endpath|pdf_fill|pdf_fill_imageblock|pdf_fill_pdfblock|pdf_fill_stroke|pdf_fill_textblock|pdf_findfont|pdf_fit_image|pdf_fit_pdi_page|pdf_fit_table|pdf_fit_textflow|pdf_fit_textline|pdf_get_apiname|pdf_get_buffer|pdf_get_errmsg|pdf_get_errnum|pdf_get_font|pdf_get_fontname|pdf_get_fontsize|pdf_get_image_height|pdf_get_image_width|pdf_get_majorversion|pdf_get_minorversion|pdf_get_parameter|pdf_get_pdi_parameter|pdf_get_pdi_value|pdf_get_value|pdf_info_font|pdf_info_matchbox|pdf_info_table|pdf_info_textflow|pdf_info_textline|pdf_initgraphics|pdf_lineto|pdf_load_3ddata|pdf_load_font|pdf_load_iccprofile|pdf_load_image|pdf_makespotcolor|pdf_moveto|pdf_new|pdf_open_ccitt|pdf_open_file|pdf_open_gif|pdf_open_image|pdf_open_image_file|pdf_open_jpeg|pdf_open_memory_image|pdf_open_pdi|pdf_open_pdi_document|pdf_open_pdi_page|pdf_open_tiff|pdf_pcos_get_number|pdf_pcos_get_stream|pdf_pcos_get_string|pdf_place_image|pdf_place_pdi_page|pdf_process_pdi|pdf_rect|pdf_restore|pdf_resume_page|pdf_rotate|pdf_save|pdf_scale|pdf_set_border_color|pdf_set_border_dash|pdf_set_border_style|pdf_set_char_spacing|pdf_set_duration|pdf_set_gstate|pdf_set_horiz_scaling|pdf_set_info|pdf_set_info_author|pdf_set_info_creator|pdf_set_info_keywords|pdf_set_info_subject|pdf_set_info_title|pdf_set_layer_dependency|pdf_set_leading|pdf_set_parameter|pdf_set_text_matrix|pdf_set_text_pos|pdf_set_text_rendering|pdf_set_text_rise|pdf_set_value|pdf_set_word_spacing|pdf_setcolor|pdf_setdash|pdf_setdashpattern|pdf_setflat|pdf_setfont|pdf_setgray|pdf_setgray_fill|pdf_setgray_stroke|pdf_setlinecap|pdf_setlinejoin|pdf_setlinewidth|pdf_setmatrix|pdf_setmiterlimit|pdf_setpolydash|pdf_setrgbcolor|pdf_setrgbcolor_fill|pdf_setrgbcolor_stroke|pdf_shading|pdf_shading_pattern|pdf_shfill|pdf_show|pdf_show_boxed|pdf_show_xy|pdf_skew|pdf_stringwidth|pdf_stroke|pdf_suspend_page|pdf_translate|pdf_utf16_to_utf8|pdf_utf32_to_utf16|pdf_utf8_to_utf16|pdo|pdo_cubrid_schema|pdo_pgsqllobcreate|pdo_pgsqllobopen|pdo_pgsqllobunlink|pdo_sqlitecreateaggregate|pdo_sqlitecreatefunction|pdoexception|pdostatement|pfsockopen|pg_affected_rows|pg_cancel_query|pg_client_encoding|pg_close|pg_connect|pg_connection_busy|pg_connection_reset|pg_connection_status|pg_convert|pg_copy_from|pg_copy_to|pg_dbname|pg_delete|pg_end_copy|pg_escape_bytea|pg_escape_string|pg_execute|pg_fetch_all|pg_fetch_all_columns|pg_fetch_array|pg_fetch_assoc|pg_fetch_object|pg_fetch_result|pg_fetch_row|pg_field_is_null|pg_field_name|pg_field_num|pg_field_prtlen|pg_field_size|pg_field_table|pg_field_type|pg_field_type_oid|pg_free_result|pg_get_notify|pg_get_pid|pg_get_result|pg_host|pg_insert|pg_last_error|pg_last_notice|pg_last_oid|pg_lo_close|pg_lo_create|pg_lo_export|pg_lo_import|pg_lo_open|pg_lo_read|pg_lo_read_all|pg_lo_seek|pg_lo_tell|pg_lo_unlink|pg_lo_write|pg_meta_data|pg_num_fields|pg_num_rows|pg_options|pg_parameter_status|pg_pconnect|pg_ping|pg_port|pg_prepare|pg_put_line|pg_query|pg_query_params|pg_result_error|pg_result_error_field|pg_result_seek|pg_result_status|pg_select|pg_send_execute|pg_send_prepare|pg_send_query|pg_send_query_params|pg_set_client_encoding|pg_set_error_verbosity|pg_trace|pg_transaction_status|pg_tty|pg_unescape_bytea|pg_untrace|pg_update|pg_version|php_check_syntax|php_ini_loaded_file|php_ini_scanned_files|php_logo_guid|php_sapi_name|php_strip_whitespace|php_uname|phpcredits|phpinfo|phpversion|pi|png2wbmp|popen|pos|posix_access|posix_ctermid|posix_errno|posix_get_last_error|posix_getcwd|posix_getegid|posix_geteuid|posix_getgid|posix_getgrgid|posix_getgrnam|posix_getgroups|posix_getlogin|posix_getpgid|posix_getpgrp|posix_getpid|posix_getppid|posix_getpwnam|posix_getpwuid|posix_getrlimit|posix_getsid|posix_getuid|posix_initgroups|posix_isatty|posix_kill|posix_mkfifo|posix_mknod|posix_setegid|posix_seteuid|posix_setgid|posix_setpgid|posix_setsid|posix_setuid|posix_strerror|posix_times|posix_ttyname|posix_uname|pow|preg_filter|preg_grep|preg_last_error|preg_match|preg_match_all|preg_quote|preg_replace|preg_replace_callback|preg_split|prev|print|print_r|printer_abort|printer_close|printer_create_brush|printer_create_dc|printer_create_font|printer_create_pen|printer_delete_brush|printer_delete_dc|printer_delete_font|printer_delete_pen|printer_draw_bmp|printer_draw_chord|printer_draw_elipse|printer_draw_line|printer_draw_pie|printer_draw_rectangle|printer_draw_roundrect|printer_draw_text|printer_end_doc|printer_end_page|printer_get_option|printer_list|printer_logical_fontheight|printer_open|printer_select_brush|printer_select_font|printer_select_pen|printer_set_option|printer_start_doc|printer_start_page|printer_write|printf|proc_close|proc_get_status|proc_nice|proc_open|proc_terminate|property_exists|ps_add_bookmark|ps_add_launchlink|ps_add_locallink|ps_add_note|ps_add_pdflink|ps_add_weblink|ps_arc|ps_arcn|ps_begin_page|ps_begin_pattern|ps_begin_template|ps_circle|ps_clip|ps_close|ps_close_image|ps_closepath|ps_closepath_stroke|ps_continue_text|ps_curveto|ps_delete|ps_end_page|ps_end_pattern|ps_end_template|ps_fill|ps_fill_stroke|ps_findfont|ps_get_buffer|ps_get_parameter|ps_get_value|ps_hyphenate|ps_include_file|ps_lineto|ps_makespotcolor|ps_moveto|ps_new|ps_open_file|ps_open_image|ps_open_image_file|ps_open_memory_image|ps_place_image|ps_rect|ps_restore|ps_rotate|ps_save|ps_scale|ps_set_border_color|ps_set_border_dash|ps_set_border_style|ps_set_info|ps_set_parameter|ps_set_text_pos|ps_set_value|ps_setcolor|ps_setdash|ps_setflat|ps_setfont|ps_setgray|ps_setlinecap|ps_setlinejoin|ps_setlinewidth|ps_setmiterlimit|ps_setoverprintmode|ps_setpolydash|ps_shading|ps_shading_pattern|ps_shfill|ps_show|ps_show2|ps_show_boxed|ps_show_xy|ps_show_xy2|ps_string_geometry|ps_stringwidth|ps_stroke|ps_symbol|ps_symbol_name|ps_symbol_width|ps_translate|pspell_add_to_personal|pspell_add_to_session|pspell_check|pspell_clear_session|pspell_config_create|pspell_config_data_dir|pspell_config_dict_dir|pspell_config_ignore|pspell_config_mode|pspell_config_personal|pspell_config_repl|pspell_config_runtogether|pspell_config_save_repl|pspell_new|pspell_new_config|pspell_new_personal|pspell_save_wordlist|pspell_store_replacement|pspell_suggest|putenv|px_close|px_create_fp|px_date2string|px_delete|px_delete_record|px_get_field|px_get_info|px_get_parameter|px_get_record|px_get_schema|px_get_value|px_insert_record|px_new|px_numfields|px_numrecords|px_open_fp|px_put_record|px_retrieve_record|px_set_blob_file|px_set_parameter|px_set_tablename|px_set_targetencoding|px_set_value|px_timestamp2string|px_update_record|qdom_error|qdom_tree|quoted_printable_decode|quoted_printable_encode|quotemeta|rad2deg|radius_acct_open|radius_add_server|radius_auth_open|radius_close|radius_config|radius_create_request|radius_cvt_addr|radius_cvt_int|radius_cvt_string|radius_demangle|radius_demangle_mppe_key|radius_get_attr|radius_get_vendor_attr|radius_put_addr|radius_put_attr|radius_put_int|radius_put_string|radius_put_vendor_addr|radius_put_vendor_attr|radius_put_vendor_int|radius_put_vendor_string|radius_request_authenticator|radius_send_request|radius_server_secret|radius_strerror|rand|range|rangeexception|rar_wrapper_cache_stats|rararchive|rarentry|rarexception|rawurldecode|rawurlencode|read_exif_data|readdir|readfile|readgzfile|readline|readline_add_history|readline_callback_handler_install|readline_callback_handler_remove|readline_callback_read_char|readline_clear_history|readline_completion_function|readline_info|readline_list_history|readline_on_new_line|readline_read_history|readline_redisplay|readline_write_history|readlink|realpath|realpath_cache_get|realpath_cache_size|recode|recode_file|recode_string|recursivearrayiterator|recursivecachingiterator|recursivecallbackfilteriterator|recursivedirectoryiterator|recursivefilteriterator|recursiveiterator|recursiveiteratoriterator|recursiveregexiterator|recursivetreeiterator|reflection|reflectionclass|reflectionexception|reflectionextension|reflectionfunction|reflectionfunctionabstract|reflectionmethod|reflectionobject|reflectionparameter|reflectionproperty|reflector|regexiterator|register_shutdown_function|register_tick_function|rename|rename_function|require|require_once|reset|resetValue|resourcebundle|restore_error_handler|restore_exception_handler|restore_include_path|return|rewind|rewinddir|rmdir|round|rpm_close|rpm_get_tag|rpm_is_valid|rpm_open|rpm_version|rrd_create|rrd_error|rrd_fetch|rrd_first|rrd_graph|rrd_info|rrd_last|rrd_lastupdate|rrd_restore|rrd_tune|rrd_update|rrd_xport|rrdcreator|rrdgraph|rrdupdater|rsort|rtrim|runkit_class_adopt|runkit_class_emancipate|runkit_constant_add|runkit_constant_redefine|runkit_constant_remove|runkit_function_add|runkit_function_copy|runkit_function_redefine|runkit_function_remove|runkit_function_rename|runkit_import|runkit_lint|runkit_lint_file|runkit_method_add|runkit_method_copy|runkit_method_redefine|runkit_method_remove|runkit_method_rename|runkit_return_value_used|runkit_sandbox_output_handler|runkit_superglobals|runtimeexception|samconnection_commit|samconnection_connect|samconnection_constructor|samconnection_disconnect|samconnection_errno|samconnection_error|samconnection_isconnected|samconnection_peek|samconnection_peekall|samconnection_receive|samconnection_remove|samconnection_rollback|samconnection_send|samconnection_setDebug|samconnection_subscribe|samconnection_unsubscribe|sammessage_body|sammessage_constructor|sammessage_header|sca_createdataobject|sca_getservice|sca_localproxy_createdataobject|sca_soapproxy_createdataobject|scandir|sdo_das_changesummary_beginlogging|sdo_das_changesummary_endlogging|sdo_das_changesummary_getchangeddataobjects|sdo_das_changesummary_getchangetype|sdo_das_changesummary_getoldcontainer|sdo_das_changesummary_getoldvalues|sdo_das_changesummary_islogging|sdo_das_datafactory_addpropertytotype|sdo_das_datafactory_addtype|sdo_das_datafactory_getdatafactory|sdo_das_dataobject_getchangesummary|sdo_das_relational_applychanges|sdo_das_relational_construct|sdo_das_relational_createrootdataobject|sdo_das_relational_executepreparedquery|sdo_das_relational_executequery|sdo_das_setting_getlistindex|sdo_das_setting_getpropertyindex|sdo_das_setting_getpropertyname|sdo_das_setting_getvalue|sdo_das_setting_isset|sdo_das_xml_addtypes|sdo_das_xml_create|sdo_das_xml_createdataobject|sdo_das_xml_createdocument|sdo_das_xml_document_getrootdataobject|sdo_das_xml_document_getrootelementname|sdo_das_xml_document_getrootelementuri|sdo_das_xml_document_setencoding|sdo_das_xml_document_setxmldeclaration|sdo_das_xml_document_setxmlversion|sdo_das_xml_loadfile|sdo_das_xml_loadstring|sdo_das_xml_savefile|sdo_das_xml_savestring|sdo_datafactory_create|sdo_dataobject_clear|sdo_dataobject_createdataobject|sdo_dataobject_getcontainer|sdo_dataobject_getsequence|sdo_dataobject_gettypename|sdo_dataobject_gettypenamespaceuri|sdo_exception_getcause|sdo_list_insert|sdo_model_property_getcontainingtype|sdo_model_property_getdefault|sdo_model_property_getname|sdo_model_property_gettype|sdo_model_property_iscontainment|sdo_model_property_ismany|sdo_model_reflectiondataobject_construct|sdo_model_reflectiondataobject_export|sdo_model_reflectiondataobject_getcontainmentproperty|sdo_model_reflectiondataobject_getinstanceproperties|sdo_model_reflectiondataobject_gettype|sdo_model_type_getbasetype|sdo_model_type_getname|sdo_model_type_getnamespaceuri|sdo_model_type_getproperties|sdo_model_type_getproperty|sdo_model_type_isabstracttype|sdo_model_type_isdatatype|sdo_model_type_isinstance|sdo_model_type_isopentype|sdo_model_type_issequencedtype|sdo_sequence_getproperty|sdo_sequence_insert|sdo_sequence_move|seekableiterator|sem_acquire|sem_get|sem_release|sem_remove|serializable|serialize|session_cache_expire|session_cache_limiter|session_commit|session_decode|session_destroy|session_encode|session_get_cookie_params|session_id|session_is_registered|session_module_name|session_name|session_pgsql_add_error|session_pgsql_get_error|session_pgsql_get_field|session_pgsql_reset|session_pgsql_set_field|session_pgsql_status|session_regenerate_id|session_register|session_save_path|session_set_cookie_params|session_set_save_handler|session_start|session_unregister|session_unset|session_write_close|setCounterClass|set_error_handler|set_exception_handler|set_file_buffer|set_include_path|set_magic_quotes_runtime|set_socket_blocking|set_time_limit|setcookie|setlocale|setproctitle|setrawcookie|setstaticpropertyvalue|setthreadtitle|settype|sha1|sha1_file|shell_exec|shm_attach|shm_detach|shm_get_var|shm_has_var|shm_put_var|shm_remove|shm_remove_var|shmop_close|shmop_delete|shmop_open|shmop_read|shmop_size|shmop_write|show_source|shuffle|signeurlpaiement|similar_text|simplexml_import_dom|simplexml_load_file|simplexml_load_string|simplexmlelement|simplexmliterator|sin|sinh|sizeof|sleep|snmp|snmp2_get|snmp2_getnext|snmp2_real_walk|snmp2_set|snmp2_walk|snmp3_get|snmp3_getnext|snmp3_real_walk|snmp3_set|snmp3_walk|snmp_get_quick_print|snmp_get_valueretrieval|snmp_read_mib|snmp_set_enum_print|snmp_set_oid_numeric_print|snmp_set_oid_output_format|snmp_set_quick_print|snmp_set_valueretrieval|snmpget|snmpgetnext|snmprealwalk|snmpset|snmpwalk|snmpwalkoid|soapclient|soapfault|soapheader|soapparam|soapserver|soapvar|socket_accept|socket_bind|socket_clear_error|socket_close|socket_connect|socket_create|socket_create_listen|socket_create_pair|socket_get_option|socket_get_status|socket_getpeername|socket_getsockname|socket_last_error|socket_listen|socket_read|socket_recv|socket_recvfrom|socket_select|socket_send|socket_sendto|socket_set_block|socket_set_blocking|socket_set_nonblock|socket_set_option|socket_set_timeout|socket_shutdown|socket_strerror|socket_write|solr_get_version|solrclient|solrclientexception|solrdocument|solrdocumentfield|solrexception|solrgenericresponse|solrillegalargumentexception|solrillegaloperationexception|solrinputdocument|solrmodifiableparams|solrobject|solrparams|solrpingresponse|solrquery|solrqueryresponse|solrresponse|solrupdateresponse|solrutils|sort|soundex|sphinxclient|spl_autoload|spl_autoload_call|spl_autoload_extensions|spl_autoload_functions|spl_autoload_register|spl_autoload_unregister|spl_classes|spl_object_hash|splbool|spldoublylinkedlist|splenum|splfileinfo|splfileobject|splfixedarray|splfloat|splheap|splint|split|spliti|splmaxheap|splminheap|splobjectstorage|splobserver|splpriorityqueue|splqueue|splstack|splstring|splsubject|spltempfileobject|spoofchecker|sprintf|sql_regcase|sqlite3|sqlite3result|sqlite3stmt|sqlite_array_query|sqlite_busy_timeout|sqlite_changes|sqlite_close|sqlite_column|sqlite_create_aggregate|sqlite_create_function|sqlite_current|sqlite_error_string|sqlite_escape_string|sqlite_exec|sqlite_factory|sqlite_fetch_all|sqlite_fetch_array|sqlite_fetch_column_types|sqlite_fetch_object|sqlite_fetch_single|sqlite_fetch_string|sqlite_field_name|sqlite_has_more|sqlite_has_prev|sqlite_key|sqlite_last_error|sqlite_last_insert_rowid|sqlite_libencoding|sqlite_libversion|sqlite_next|sqlite_num_fields|sqlite_num_rows|sqlite_open|sqlite_popen|sqlite_prev|sqlite_query|sqlite_rewind|sqlite_seek|sqlite_single_query|sqlite_udf_decode_binary|sqlite_udf_encode_binary|sqlite_unbuffered_query|sqlite_valid|sqrt|srand|sscanf|ssdeep_fuzzy_compare|ssdeep_fuzzy_hash|ssdeep_fuzzy_hash_filename|ssh2_auth_hostbased_file|ssh2_auth_none|ssh2_auth_password|ssh2_auth_pubkey_file|ssh2_connect|ssh2_exec|ssh2_fetch_stream|ssh2_fingerprint|ssh2_methods_negotiated|ssh2_publickey_add|ssh2_publickey_init|ssh2_publickey_list|ssh2_publickey_remove|ssh2_scp_recv|ssh2_scp_send|ssh2_sftp|ssh2_sftp_lstat|ssh2_sftp_mkdir|ssh2_sftp_readlink|ssh2_sftp_realpath|ssh2_sftp_rename|ssh2_sftp_rmdir|ssh2_sftp_stat|ssh2_sftp_symlink|ssh2_sftp_unlink|ssh2_shell|ssh2_tunnel|stat|stats_absolute_deviation|stats_cdf_beta|stats_cdf_binomial|stats_cdf_cauchy|stats_cdf_chisquare|stats_cdf_exponential|stats_cdf_f|stats_cdf_gamma|stats_cdf_laplace|stats_cdf_logistic|stats_cdf_negative_binomial|stats_cdf_noncentral_chisquare|stats_cdf_noncentral_f|stats_cdf_poisson|stats_cdf_t|stats_cdf_uniform|stats_cdf_weibull|stats_covariance|stats_den_uniform|stats_dens_beta|stats_dens_cauchy|stats_dens_chisquare|stats_dens_exponential|stats_dens_f|stats_dens_gamma|stats_dens_laplace|stats_dens_logistic|stats_dens_negative_binomial|stats_dens_normal|stats_dens_pmf_binomial|stats_dens_pmf_hypergeometric|stats_dens_pmf_poisson|stats_dens_t|stats_dens_weibull|stats_harmonic_mean|stats_kurtosis|stats_rand_gen_beta|stats_rand_gen_chisquare|stats_rand_gen_exponential|stats_rand_gen_f|stats_rand_gen_funiform|stats_rand_gen_gamma|stats_rand_gen_ibinomial|stats_rand_gen_ibinomial_negative|stats_rand_gen_int|stats_rand_gen_ipoisson|stats_rand_gen_iuniform|stats_rand_gen_noncenral_chisquare|stats_rand_gen_noncentral_f|stats_rand_gen_noncentral_t|stats_rand_gen_normal|stats_rand_gen_t|stats_rand_get_seeds|stats_rand_phrase_to_seeds|stats_rand_ranf|stats_rand_setall|stats_skew|stats_standard_deviation|stats_stat_binomial_coef|stats_stat_correlation|stats_stat_gennch|stats_stat_independent_t|stats_stat_innerproduct|stats_stat_noncentral_t|stats_stat_paired_t|stats_stat_percentile|stats_stat_powersum|stats_variance|stomp|stomp_connect_error|stomp_version|stompexception|stompframe|str_getcsv|str_ireplace|str_pad|str_repeat|str_replace|str_rot13|str_shuffle|str_split|str_word_count|strcasecmp|strchr|strcmp|strcoll|strcspn|stream_bucket_append|stream_bucket_make_writeable|stream_bucket_new|stream_bucket_prepend|stream_context_create|stream_context_get_default|stream_context_get_options|stream_context_get_params|stream_context_set_default|stream_context_set_option|stream_context_set_params|stream_copy_to_stream|stream_encoding|stream_filter_append|stream_filter_prepend|stream_filter_register|stream_filter_remove|stream_get_contents|stream_get_filters|stream_get_line|stream_get_meta_data|stream_get_transports|stream_get_wrappers|stream_is_local|stream_notification_callback|stream_register_wrapper|stream_resolve_include_path|stream_select|stream_set_blocking|stream_set_read_buffer|stream_set_timeout|stream_set_write_buffer|stream_socket_accept|stream_socket_client|stream_socket_enable_crypto|stream_socket_get_name|stream_socket_pair|stream_socket_recvfrom|stream_socket_sendto|stream_socket_server|stream_socket_shutdown|stream_supports_lock|stream_wrapper_register|stream_wrapper_restore|stream_wrapper_unregister|streamwrapper|strftime|strip_tags|stripcslashes|stripos|stripslashes|stristr|strlen|strnatcasecmp|strnatcmp|strncasecmp|strncmp|strpbrk|strpos|strptime|strrchr|strrev|strripos|strrpos|strspn|strstr|strtok|strtolower|strtotime|strtoupper|strtr|strval|substr|substr_compare|substr_count|substr_replace|svm|svmmodel|svn_add|svn_auth_get_parameter|svn_auth_set_parameter|svn_blame|svn_cat|svn_checkout|svn_cleanup|svn_client_version|svn_commit|svn_delete|svn_diff|svn_export|svn_fs_abort_txn|svn_fs_apply_text|svn_fs_begin_txn2|svn_fs_change_node_prop|svn_fs_check_path|svn_fs_contents_changed|svn_fs_copy|svn_fs_delete|svn_fs_dir_entries|svn_fs_file_contents|svn_fs_file_length|svn_fs_is_dir|svn_fs_is_file|svn_fs_make_dir|svn_fs_make_file|svn_fs_node_created_rev|svn_fs_node_prop|svn_fs_props_changed|svn_fs_revision_prop|svn_fs_revision_root|svn_fs_txn_root|svn_fs_youngest_rev|svn_import|svn_log|svn_ls|svn_mkdir|svn_repos_create|svn_repos_fs|svn_repos_fs_begin_txn_for_commit|svn_repos_fs_commit_txn|svn_repos_hotcopy|svn_repos_open|svn_repos_recover|svn_revert|svn_status|svn_update|swf_actiongeturl|swf_actiongotoframe|swf_actiongotolabel|swf_actionnextframe|swf_actionplay|swf_actionprevframe|swf_actionsettarget|swf_actionstop|swf_actiontogglequality|swf_actionwaitforframe|swf_addbuttonrecord|swf_addcolor|swf_closefile|swf_definebitmap|swf_definefont|swf_defineline|swf_definepoly|swf_definerect|swf_definetext|swf_endbutton|swf_enddoaction|swf_endshape|swf_endsymbol|swf_fontsize|swf_fontslant|swf_fonttracking|swf_getbitmapinfo|swf_getfontinfo|swf_getframe|swf_labelframe|swf_lookat|swf_modifyobject|swf_mulcolor|swf_nextid|swf_oncondition|swf_openfile|swf_ortho|swf_ortho2|swf_perspective|swf_placeobject|swf_polarview|swf_popmatrix|swf_posround|swf_pushmatrix|swf_removeobject|swf_rotate|swf_scale|swf_setfont|swf_setframe|swf_shapearc|swf_shapecurveto|swf_shapecurveto3|swf_shapefillbitmapclip|swf_shapefillbitmaptile|swf_shapefilloff|swf_shapefillsolid|swf_shapelinesolid|swf_shapelineto|swf_shapemoveto|swf_showframe|swf_startbutton|swf_startdoaction|swf_startshape|swf_startsymbol|swf_textwidth|swf_translate|swf_viewport|swfaction|swfbitmap|swfbutton|swfdisplayitem|swffill|swffont|swffontchar|swfgradient|swfmorph|swfmovie|swfprebuiltclip|swfshape|swfsound|swfsoundinstance|swfsprite|swftext|swftextfield|swfvideostream|swish_construct|swish_getmetalist|swish_getpropertylist|swish_prepare|swish_query|swishresult_getmetalist|swishresult_stem|swishresults_getparsedwords|swishresults_getremovedstopwords|swishresults_nextresult|swishresults_seekresult|swishsearch_execute|swishsearch_resetlimit|swishsearch_setlimit|swishsearch_setphrasedelimiter|swishsearch_setsort|swishsearch_setstructure|sybase_affected_rows|sybase_close|sybase_connect|sybase_data_seek|sybase_deadlock_retry_count|sybase_fetch_array|sybase_fetch_assoc|sybase_fetch_field|sybase_fetch_object|sybase_fetch_row|sybase_field_seek|sybase_free_result|sybase_get_last_message|sybase_min_client_severity|sybase_min_error_severity|sybase_min_message_severity|sybase_min_server_severity|sybase_num_fields|sybase_num_rows|sybase_pconnect|sybase_query|sybase_result|sybase_select_db|sybase_set_message_handler|sybase_unbuffered_query|symlink|sys_get_temp_dir|sys_getloadavg|syslog|system|tag|tan|tanh|tcpwrap_check|tempnam|textdomain|tidy|tidy_access_count|tidy_config_count|tidy_diagnose|tidy_error_count|tidy_get_error_buffer|tidy_get_output|tidy_load_config|tidy_reset_config|tidy_save_config|tidy_set_encoding|tidy_setopt|tidy_warning_count|tidynode|time|time_nanosleep|time_sleep_until|timezone_abbreviations_list|timezone_identifiers_list|timezone_location_get|timezone_name_from_abbr|timezone_name_get|timezone_offset_get|timezone_open|timezone_transitions_get|timezone_version_get|tmpfile|token_get_all|token_name|tokyotyrant|tokyotyrantquery|tokyotyranttable|tostring|tostring|touch|transliterator|traversable|trigger_error|trim|uasort|ucfirst|ucwords|udm_add_search_limit|udm_alloc_agent|udm_alloc_agent_array|udm_api_version|udm_cat_list|udm_cat_path|udm_check_charset|udm_check_stored|udm_clear_search_limits|udm_close_stored|udm_crc32|udm_errno|udm_error|udm_find|udm_free_agent|udm_free_ispell_data|udm_free_res|udm_get_doc_count|udm_get_res_field|udm_get_res_param|udm_hash32|udm_load_ispell_data|udm_open_stored|udm_set_agent_param|uksort|umask|underflowexception|unexpectedvalueexception|uniqid|unixtojd|unlink|unpack|unregister_tick_function|unserialize|unset|urldecode|urlencode|use_soap_error_handler|user_error|usleep|usort|utf8_decode|utf8_encode|v8js|v8jsexception|var_dump|var_export|variant|variant_abs|variant_add|variant_and|variant_cast|variant_cat|variant_cmp|variant_date_from_timestamp|variant_date_to_timestamp|variant_div|variant_eqv|variant_fix|variant_get_type|variant_idiv|variant_imp|variant_int|variant_mod|variant_mul|variant_neg|variant_not|variant_or|variant_pow|variant_round|variant_set|variant_set_type|variant_sub|variant_xor|version_compare|vfprintf|virtual|vpopmail_add_alias_domain|vpopmail_add_alias_domain_ex|vpopmail_add_domain|vpopmail_add_domain_ex|vpopmail_add_user|vpopmail_alias_add|vpopmail_alias_del|vpopmail_alias_del_domain|vpopmail_alias_get|vpopmail_alias_get_all|vpopmail_auth_user|vpopmail_del_domain|vpopmail_del_domain_ex|vpopmail_del_user|vpopmail_error|vpopmail_passwd|vpopmail_set_user_quota|vprintf|vsprintf|w32api_deftype|w32api_init_dtype|w32api_invoke_function|w32api_register_function|w32api_set_call_method|wddx_add_vars|wddx_deserialize|wddx_packet_end|wddx_packet_start|wddx_serialize_value|wddx_serialize_vars|win32_continue_service|win32_create_service|win32_delete_service|win32_get_last_control_message|win32_pause_service|win32_ps_list_procs|win32_ps_stat_mem|win32_ps_stat_proc|win32_query_service_status|win32_set_service_status|win32_start_service|win32_start_service_ctrl_dispatcher|win32_stop_service|wincache_fcache_fileinfo|wincache_fcache_meminfo|wincache_lock|wincache_ocache_fileinfo|wincache_ocache_meminfo|wincache_refresh_if_changed|wincache_rplist_fileinfo|wincache_rplist_meminfo|wincache_scache_info|wincache_scache_meminfo|wincache_ucache_add|wincache_ucache_cas|wincache_ucache_clear|wincache_ucache_dec|wincache_ucache_delete|wincache_ucache_exists|wincache_ucache_get|wincache_ucache_inc|wincache_ucache_info|wincache_ucache_meminfo|wincache_ucache_set|wincache_unlock|wordwrap|xattr_get|xattr_list|xattr_remove|xattr_set|xattr_supported|xdiff_file_bdiff|xdiff_file_bdiff_size|xdiff_file_bpatch|xdiff_file_diff|xdiff_file_diff_binary|xdiff_file_merge3|xdiff_file_patch|xdiff_file_patch_binary|xdiff_file_rabdiff|xdiff_string_bdiff|xdiff_string_bdiff_size|xdiff_string_bpatch|xdiff_string_diff|xdiff_string_diff_binary|xdiff_string_merge3|xdiff_string_patch|xdiff_string_patch_binary|xdiff_string_rabdiff|xhprof_disable|xhprof_enable|xhprof_sample_disable|xhprof_sample_enable|xml_error_string|xml_get_current_byte_index|xml_get_current_column_number|xml_get_current_line_number|xml_get_error_code|xml_parse|xml_parse_into_struct|xml_parser_create|xml_parser_create_ns|xml_parser_free|xml_parser_get_option|xml_parser_set_option|xml_set_character_data_handler|xml_set_default_handler|xml_set_element_handler|xml_set_end_namespace_decl_handler|xml_set_external_entity_ref_handler|xml_set_notation_decl_handler|xml_set_object|xml_set_processing_instruction_handler|xml_set_start_namespace_decl_handler|xml_set_unparsed_entity_decl_handler|xmlreader|xmlrpc_decode|xmlrpc_decode_request|xmlrpc_encode|xmlrpc_encode_request|xmlrpc_get_type|xmlrpc_is_fault|xmlrpc_parse_method_descriptions|xmlrpc_server_add_introspection_data|xmlrpc_server_call_method|xmlrpc_server_create|xmlrpc_server_destroy|xmlrpc_server_register_introspection_callback|xmlrpc_server_register_method|xmlrpc_set_type|xmlwriter_end_attribute|xmlwriter_end_cdata|xmlwriter_end_comment|xmlwriter_end_document|xmlwriter_end_dtd|xmlwriter_end_dtd_attlist|xmlwriter_end_dtd_element|xmlwriter_end_dtd_entity|xmlwriter_end_element|xmlwriter_end_pi|xmlwriter_flush|xmlwriter_full_end_element|xmlwriter_open_memory|xmlwriter_open_uri|xmlwriter_output_memory|xmlwriter_set_indent|xmlwriter_set_indent_string|xmlwriter_start_attribute|xmlwriter_start_attribute_ns|xmlwriter_start_cdata|xmlwriter_start_comment|xmlwriter_start_document|xmlwriter_start_dtd|xmlwriter_start_dtd_attlist|xmlwriter_start_dtd_element|xmlwriter_start_dtd_entity|xmlwriter_start_element|xmlwriter_start_element_ns|xmlwriter_start_pi|xmlwriter_text|xmlwriter_write_attribute|xmlwriter_write_attribute_ns|xmlwriter_write_cdata|xmlwriter_write_comment|xmlwriter_write_dtd|xmlwriter_write_dtd_attlist|xmlwriter_write_dtd_element|xmlwriter_write_dtd_entity|xmlwriter_write_element|xmlwriter_write_element_ns|xmlwriter_write_pi|xmlwriter_write_raw|xpath_eval|xpath_eval_expression|xpath_new_context|xpath_register_ns|xpath_register_ns_auto|xptr_eval|xptr_new_context|xslt_backend_info|xslt_backend_name|xslt_backend_version|xslt_create|xslt_errno|xslt_error|xslt_free|xslt_getopt|xslt_process|xslt_set_base|xslt_set_encoding|xslt_set_error_handler|xslt_set_log|xslt_set_object|xslt_set_sax_handler|xslt_set_sax_handlers|xslt_set_scheme_handler|xslt_set_scheme_handlers|xslt_setopt|xsltprocessor|yaml_emit|yaml_emit_file|yaml_parse|yaml_parse_file|yaml_parse_url|yaz_addinfo|yaz_ccl_conf|yaz_ccl_parse|yaz_close|yaz_connect|yaz_database|yaz_element|yaz_errno|yaz_error|yaz_es|yaz_es_result|yaz_get_option|yaz_hits|yaz_itemorder|yaz_present|yaz_range|yaz_record|yaz_scan|yaz_scan_result|yaz_schema|yaz_search|yaz_set_option|yaz_sort|yaz_syntax|yaz_wait|yp_all|yp_cat|yp_err_string|yp_errno|yp_first|yp_get_default_domain|yp_master|yp_match|yp_next|yp_order|zend_logo_guid|zend_thread_id|zend_version|zip_close|zip_entry_close|zip_entry_compressedsize|zip_entry_compressionmethod|zip_entry_filesize|zip_entry_name|zip_entry_open|zip_entry_read|zip_open|zip_read|ziparchive|ziparchive_addemptydir|ziparchive_addfile|ziparchive_addfromstring|ziparchive_close|ziparchive_deleteindex|ziparchive_deletename|ziparchive_extractto|ziparchive_getarchivecomment|ziparchive_getcommentindex|ziparchive_getcommentname|ziparchive_getfromindex|ziparchive_getfromname|ziparchive_getnameindex|ziparchive_getstatusstring|ziparchive_getstream|ziparchive_locatename|ziparchive_open|ziparchive_renameindex|ziparchive_renamename|ziparchive_setCommentName|ziparchive_setarchivecomment|ziparchive_setcommentindex|ziparchive_statindex|ziparchive_statname|ziparchive_unchangeall|ziparchive_unchangearchive|ziparchive_unchangeindex|ziparchive_unchangename|zlib_get_coding_type".split("|")),c=e.arrayToMap("abstract|and|array|as|break|case|catch|class|clone|const|continue|declare|default|do|else|elseif|enddeclare|endfor|endforeach|endif|endswitch|endwhile|extends|final|for|foreach|function|global|goto|if|implements|interface|instanceof|namespace|new|or|private|protected|public|static|switch|throw|try|use|var|while|xor".split("|")),d=e.arrayToMap("die|echo|empty|exit|eval|include|include_once|isset|list|require|require_once|return|print|unset".split("|")),g=e.arrayToMap("true|false|null|__CLASS__|__DIR__|__FILE__|__LINE__|__METHOD__|__FUNCTION__|__NAMESPACE__".split("|")),h=e.arrayToMap("$GLOBALS|$_SERVER|$_GET|$_POST|$_FILES|$_REQUEST|$_SESSION|$_ENV|$_COOKIE|$php_errormsg|$HTTP_RAW_POST_DATA|$http_response_header|$argc|$argv".split("|")),i=e.arrayToMap("key_exists|cairo_matrix_create_scale|cairo_matrix_create_translate|call_user_method|call_user_method_array|com_addref|com_get|com_invoke|com_isenum|com_load|com_release|com_set|connection_timeout|cubrid_load_from_glo|cubrid_new_glo|cubrid_save_to_glo|cubrid_send_glo|define_syslog_variables|dl|ereg|ereg_replace|eregi|eregi_replace|hw_documentattributes|hw_documentbodytag|hw_documentsize|hw_outputdocument|imagedashedline|maxdb_bind_param|maxdb_bind_result|maxdb_client_encoding|maxdb_close_long_data|maxdb_execute|maxdb_fetch|maxdb_get_metadata|maxdb_param_count|maxdb_send_long_data|mcrypt_ecb|mcrypt_generic_end|mime_content_type|mysql_createdb|mysql_dbname|mysql_db_query|mysql_drop_db|mysql_dropdb|mysql_escape_string|mysql_fieldflags|mysql_fieldflags|mysql_fieldname|mysql_fieldtable|mysql_fieldtype|mysql_freeresult|mysql_listdbs|mysql_list_fields|mysql_listfields|mysql_list_tables|mysql_listtables|mysql_numfields|mysql_numrows|mysql_selectdb|mysql_tablename|mysqli_bind_param|mysqli_bind_result|mysqli_disable_reads_from_master|mysqli_disable_rpl_parse|mysqli_enable_reads_from_master|mysqli_enable_rpl_parse|mysqli_execute|mysqli_fetch|mysqli_get_metadata|mysqli_master_query|mysqli_param_count|mysqli_rpl_parse_enabled|mysqli_rpl_probe|mysqli_rpl_query_type|mysqli_send_long_data|mysqli_send_query|mysqli_slave_query|ocibindbyname|ocicancel|ocicloselob|ocicollappend|ocicollassign|ocicollassignelem|ocicollgetelem|ocicollmax|ocicollsize|ocicolltrim|ocicolumnisnull|ocicolumnname|ocicolumnprecision|ocicolumnscale|ocicolumnsize|ocicolumntype|ocicolumntyperaw|ocicommit|ocidefinebyname|ocierror|ociexecute|ocifetch|ocifetchinto|ocifetchstatement|ocifreecollection|ocifreecursor|ocifreedesc|ocifreestatement|ociinternaldebug|ociloadlob|ocilogoff|ocilogon|ocinewcollection|ocinewcursor|ocinewdescriptor|ocinlogon|ocinumcols|ociparse|ociplogon|ociresult|ocirollback|ocirowcount|ocisavelob|ocisavelobfile|ociserverversion|ocisetprefetch|ocistatementtype|ociwritelobtofile|ociwritetemporarylob|PDF_add_annotation|PDF_add_bookmark|PDF_add_launchlink|PDF_add_locallink|PDF_add_note|PDF_add_outline|PDF_add_pdflink|PDF_add_weblink|PDF_attach_file|PDF_begin_page|PDF_begin_template|PDF_close_pdi|PDF_close|PDF_findfont|PDF_get_font|PDF_get_fontname|PDF_get_fontsize|PDF_get_image_height|PDF_get_image_width|PDF_get_majorversion|PDF_get_minorversion|PDF_get_pdi_parameter|PDF_get_pdi_value|PDF_open_ccitt|PDF_open_file|PDF_open_gif|PDF_open_image_file|PDF_open_image|PDF_open_jpeg|PDF_open_pdi|PDF_open_tiff|PDF_place_image|PDF_place_pdi_page|PDF_set_border_color|PDF_set_border_dash|PDF_set_border_style|PDF_set_char_spacing|PDF_set_duration|PDF_set_horiz_scaling|PDF_set_info_author|PDF_set_info_creator|PDF_set_info_keywords|PDF_set_info_subject|PDF_set_info_title|PDF_set_leading|PDF_set_text_matrix|PDF_set_text_rendering|PDF_set_text_rise|PDF_set_word_spacing|PDF_setgray_fill|PDF_setgray_stroke|PDF_setgray|PDF_setpolydash|PDF_setrgbcolor_fill|PDF_setrgbcolor_stroke|PDF_setrgbcolor|PDF_show_boxed|php_check_syntax|px_set_tablename|px_set_targetencoding|runkit_sandbox_output_handler|session_is_registered|session_register|session_unregisterset_magic_quotes_runtime|magic_quotes_runtime|set_socket_blocking|socket_set_blocking|set_socket_timeout|socket_set_timeout|split|spliti|sql_regcase".split("|")),j=e.arrayToMap("cfunction|old_function".split("|")),k=e.arrayToMap([]);this.$rules={start:[{token:"support.php_tag",regex:"<\\?(?:php|\\=)"},{token:"support.php_tag",regex:"\\?>"},{token:"comment",regex:"<\\!--",next:"htmlcomment"},{token:"meta.tag",regex:"<style",next:"css"},{token:"meta.tag",regex:"<\\/?[-_a-zA-Z0-9:]+",next:"htmltag"},{token:"meta.tag",regex:"<!DOCTYPE.*?>"},{token:"comment",regex:"\\/\\/.*$"},{token:"comment",regex:"#.*$"},a.getStartRule("doc-start"),{token:"comment",regex:"\\/\\*",next:"comment"},{token:"string.regexp",regex:"[/](?:(?:\\[(?:\\\\]|[^\\]])+\\])|(?:\\\\/|[^\\]/]))*[/][gimy]*\\s*(?=[).,;]|$)"},{token:"string",regex:'["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'},{token:"string",regex:'["].*\\\\$',next:"qqstring"},{token:"string",regex:"['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"},{token:"string",regex:"['].*\\\\$",next:"qstring"},{token:"constant.numeric",regex:"0[xX][0-9a-fA-F]+\\b"},{token:"constant.numeric",regex:"[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"},{token:"constant.language",regex:"\\b(?:DEFAULT_INCLUDE_PATH|E_(?:ALL|CO(?:MPILE_(?:ERROR|WARNING)|RE_(?:ERROR|WARNING))|ERROR|NOTICE|PARSE|STRICT|USER_(?:ERROR|NOTICE|WARNING)|WARNING)|P(?:EAR_(?:EXTENSION_DIR|INSTALL_DIR)|HP_(?:BINDIR|CONFIG_FILE_(?:PATH|SCAN_DIR)|DATADIR|E(?:OL|XTENSION_DIR)|INT_(?:MAX|SIZE)|L(?:IBDIR|OCALSTATEDIR)|O(?:S|UTPUT_HANDLER_(?:CONT|END|START))|PREFIX|S(?:API|HLIB_SUFFIX|YSCONFDIR)|VERSION))|__COMPILER_HALT_OFFSET__)\\b"},{token:"constant.language",regex:"\\b(?:A(?:B(?:DAY_(?:1|2|3|4|5|6|7)|MON_(?:1(?:0|1|2|)|2|3|4|5|6|7|8|9))|LT_DIGITS|M_STR|SSERT_(?:ACTIVE|BAIL|CALLBACK|QUIET_EVAL|WARNING))|C(?:ASE_(?:LOWER|UPPER)|HAR_MAX|O(?:DESET|NNECTION_(?:ABORTED|NORMAL|TIMEOUT)|UNT_(?:NORMAL|RECURSIVE))|R(?:EDITS_(?:ALL|DOCS|FULLPAGE|G(?:ENERAL|ROUP)|MODULES|QA|SAPI)|NCYSTR|YPT_(?:BLOWFISH|EXT_DES|MD5|S(?:ALT_LENGTH|TD_DES)))|URRENCY_SYMBOL)|D(?:AY_(?:1|2|3|4|5|6|7)|ECIMAL_POINT|IRECTORY_SEPARATOR|_(?:FMT|T_FMT))|E(?:NT_(?:COMPAT|NOQUOTES|QUOTES)|RA(?:_(?:D_(?:FMT|T_FMT)|T_FMT|YEAR)|)|XTR_(?:IF_EXISTS|OVERWRITE|PREFIX_(?:ALL|I(?:F_EXISTS|NVALID)|SAME)|SKIP))|FRAC_DIGITS|GROUPING|HTML_(?:ENTITIES|SPECIALCHARS)|IN(?:FO_(?:ALL|C(?:ONFIGURATION|REDITS)|ENVIRONMENT|GENERAL|LICENSE|MODULES|VARIABLES)|I_(?:ALL|PERDIR|SYSTEM|USER)|T_(?:CURR_SYMBOL|FRAC_DIGITS))|L(?:C_(?:ALL|C(?:OLLATE|TYPE)|M(?:ESSAGES|ONETARY)|NUMERIC|TIME)|O(?:CK_(?:EX|NB|SH|UN)|G_(?:A(?:LERT|UTH(?:PRIV|))|C(?:ONS|R(?:IT|ON))|D(?:AEMON|EBUG)|E(?:MERG|RR)|INFO|KERN|L(?:OCAL(?:0|1|2|3|4|5|6|7)|PR)|MAIL|N(?:DELAY|EWS|O(?:TICE|WAIT))|ODELAY|P(?:ERROR|ID)|SYSLOG|U(?:SER|UCP)|WARNING)))|M(?:ON_(?:1(?:0|1|2|)|2|3|4|5|6|7|8|9|DECIMAL_POINT|GROUPING|THOUSANDS_SEP)|_(?:1_PI|2_(?:PI|SQRTPI)|E|L(?:N(?:10|2)|OG(?:10E|2E))|PI(?:_(?:2|4)|)|SQRT(?:1_2|2)))|N(?:EGATIVE_SIGN|O(?:EXPR|STR)|_(?:CS_PRECEDES|S(?:EP_BY_SPACE|IGN_POSN)))|P(?:ATH(?:INFO_(?:BASENAME|DIRNAME|EXTENSION)|_SEPARATOR)|M_STR|OSITIVE_SIGN|_(?:CS_PRECEDES|S(?:EP_BY_SPACE|IGN_POSN)))|RADIXCHAR|S(?:EEK_(?:CUR|END|SET)|ORT_(?:ASC|DESC|NUMERIC|REGULAR|STRING)|TR_PAD_(?:BOTH|LEFT|RIGHT))|T(?:HOUS(?:ANDS_SEP|EP)|_FMT(?:_AMPM|))|YES(?:EXPR|STR)|STD(?:IN|OUT|ERR))\\b"},{token:function(a){return c.hasOwnProperty(a)?"keyword":g.hasOwnProperty(a)?"constant.language":h.hasOwnProperty(a)?"variable.language":k.hasOwnProperty(a)?"invalid.illegal":b.hasOwnProperty(a)?"support.function":a=="debugger"?"invalid.deprecated":a.match(/^(\$[a-zA-Z][a-zA-Z0-9_]*|self|parent)$/)?"variable":"identifier"},regex:"[a-zA-Z_$][a-zA-Z0-9_$]*\\b"},{token:"keyword.operator",regex:"!|\\$|%|&|\\*|\\-\\-|\\-|\\+\\+|\\+|~|===|==|=|!=|!==|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\\|\\||\\?\\:|\\*=|%=|\\+=|\\-=|&=|\\^=|\\b(?:in|instanceof|new|delete|typeof|void)"},{token:"lparen",regex:"[[({]"},{token:"rparen",regex:"[\\])}]"},{token:"text",regex:"\\s+"}],comment:[{token:"comment",regex:".*?\\*\\/",next:"start"},{token:"comment",regex:".+"}],qqstring:[{token:"string",regex:'(?:(?:\\\\.)|(?:[^"\\\\]))*?"',next:"start"},{token:"string",regex:".+"}],qstring:[{token:"string",regex:"(?:(?:\\\\.)|(?:[^'\\\\]))*?'",next:"start"},{token:"string",regex:".+"}],htmlcomment:[{token:"comment",regex:".*?-->",next:"start"},{token:"comment",regex:".+"}],htmltag:[{token:"meta.tag",regex:">",next:"start"},{token:"text",regex:"[-_a-zA-Z0-9:]+"},{token:"text",regex:"\\s+"},{token:"string",regex:'".*?"'},{token:"string",regex:"'.*?'"}],css:[{token:"meta.tag",regex:"</style>",next:"htmltag"},{token:"meta.tag",regex:">"},{token:"text",regex:"(?:media|type|href)"},{token:"string",regex:'=".*?"'},{token:"paren.lparen",regex:"{",next:"cssdeclaration"},{token:"keyword",regex:"#[A-Za-z0-9-_.]+"},{token:"variable",regex:"\\.[A-Za-z0-9-_.]+"},{token:"constant",regex:"[A-Za-z0-9]+"}],cssdeclaration:[{token:"support.type",regex:"[-a-zA-Z]+",next:"cssvalue"},{token:"paren.rparen",regex:"}",next:"css"}],cssvalue:[{token:"text",regex:":"},{token:"constant",regex:"#[0-9a-zA-Z]+"},{token:"text",regex:"[-_0-9a-zA-Z\"' ,%]+"},{token:"text",regex:";",next:"cssdeclaration"}]},this.embedRules(f,"doc-",[(new f).getEndRule("start")])};d.inherits(h,g),b.PhpHighlightRules=h}),define("ace/mode/doc_comment_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("./text_highlight_rules").TextHighlightRules,f=function(){this.$rules={start:[{token:"comment.doc.tag",regex:"@[\\w\\d_]+"},{token:"comment.doc",merge:!0,regex:"\\s+"},{token:"comment.doc",merge:!0,regex:"TODO"},{token:"comment.doc",merge:!0,regex:"[^@\\*]+"},{token:"comment.doc",merge:!0,regex:"."}]}};d.inherits(f,e),function(){this.getStartRule=function(a){return{token:"comment.doc",merge:!0,regex:"\\/\\*(?=\\*)",next:a}},this.getEndRule=function(a){return{token:"comment.doc",merge:!0,regex:"\\*\\/",next:a}}}.call(f.prototype),b.DocCommentHighlightRules=f}),define("ace/mode/matching_brace_outdent",["require","exports","module","ace/range"],function(a,b,c){"use strict";var d=a("../range").Range,e=function(){};((function(){this.checkOutdent=function(a,b){return/^\s+$/.test(a)?/^\s*\}/.test(b):!1},this.autoOutdent=function(a,b){var c=a.getLine(b),e=c.match(/^(\s*\})/);if(!e)return 0;var f=e[1].length,g=a.findMatchingBracket({row:b,column:f});if(!g||g.row==b)return 0;var h=this.$getIndent(a.getLine(g.row));a.replace(new d(b,0,b,f-1),h)},this.$getIndent=function(a){var b=a.match(/^(\s+)/);return b?b[1]:""}})).call(e.prototype),b.MatchingBraceOutdent=e}),define("ace/mode/behaviour/cstyle",["require","exports","module","ace/lib/oop","ace/mode/behaviour"],function(a,b,c){"use strict";var d=a("../../lib/oop"),e=a("../behaviour").Behaviour,f=function(){this.add("braces","insertion",function(a,b,c,d,e){if(e=="{"){var f=c.getSelectionRange(),g=d.doc.getTextRange(f);return g!==""?{text:"{"+g+"}",selection:!1}:{text:"{}",selection:[1,1]}}if(e=="}"){var h=c.getCursorPosition(),i=d.doc.getLine(h.row),j=i.substring(h.column,h.column+1);if(j=="}"){var k=d.$findOpeningBracket("}",{column:h.column+1,row:h.row});if(k!==null)return{text:"",selection:[1,1]}}}else if(e=="\n"){var h=c.getCursorPosition(),i=d.doc.getLine(h.row),j=i.substring(h.column,h.column+1);if(j=="}"){var l=d.findMatchingBracket({row:h.row,column:h.column+1});if(!l)return null;var m=this.getNextLineIndent(a,i.substring(0,i.length-1),d.getTabString()),n=this.$getIndent(d.doc.getLine(l.row));return{text:"\n"+m+"\n"+n,selection:[1,m.length,1,m.length]}}}}),this.add("braces","deletion",function(a,b,c,d,e){var f=d.doc.getTextRange(e);if(!e.isMultiLine()&&f=="{"){var g=d.doc.getLine(e.start.row),h=g.substring(e.end.column,e.end.column+1);if(h=="}")return e.end.column++,e}}),this.add("parens","insertion",function(a,b,c,d,e){if(e=="("){var f=c.getSelectionRange(),g=d.doc.getTextRange(f);return g!==""?{text:"("+g+")",selection:!1}:{text:"()",selection:[1,1]}}if(e==")"){var h=c.getCursorPosition(),i=d.doc.getLine(h.row),j=i.substring(h.column,h.column+1);if(j==")"){var k=d.$findOpeningBracket(")",{column:h.column+1,row:h.row});if(k!==null)return{text:"",selection:[1,1]}}}}),this.add("parens","deletion",function(a,b,c,d,e){var f=d.doc.getTextRange(e);if(!e.isMultiLine()&&f=="("){var g=d.doc.getLine(e.start.row),h=g.substring(e.start.column+1,e.start.column+2);if(h==")")return e.end.column++,e}}),this.add("string_dquotes","insertion",function(a,b,c,d,e){if(e=='"'){var f=c.getSelectionRange(),g=d.doc.getTextRange(f);if(g!=="")return{text:'"'+g+'"',selection:!1};var h=c.getCursorPosition(),i=d.doc.getLine(h.row),j=i.substring(h.column-1,h.column);if(j=="\\")return null;var k=d.getTokens(f.start.row,f.start.row)[0].tokens,l=0,m,n=-1;for(var o=0;o<k.length;o++){m=k[o],m.type=="string"?n=-1:n<0&&(n=m.value.indexOf('"'));if(m.value.length+l>f.start.column)break;l+=k[o].value.length}if(!m||n<0&&m.type!=="comment"&&(m.type!=="string"||f.start.column!==m.value.length+l-1&&m.value.lastIndexOf('"')===m.value.length-1))return{text:'""',selection:[1,1]};if(m&&m.type==="string"){var p=i.substring(h.column,h.column+1);if(p=='"')return{text:"",selection:[1,1]}}}}),this.add("string_dquotes","deletion",function(a,b,c,d,e){var f=d.doc.getTextRange(e);if(!e.isMultiLine()&&f=='"'){var g=d.doc.getLine(e.start.row),h=g.substring(e.start.column+1,e.start.column+2);if(h=='"')return e.end.column++,e}})};d.inherits(f,e),b.CstyleBehaviour=f}),define("ace/mode/folding/cstyle",["require","exports","module","ace/lib/oop","ace/range","ace/mode/folding/fold_mode"],function(a,b,c){"use strict";var d=a("../../lib/oop"),e=a("../../range").Range,f=a("./fold_mode").FoldMode,g=b.FoldMode=function(){};d.inherits(g,f),function(){this.foldingStartMarker=/(\{|\[)[^\}\]]*$|^\s*(\/\*)/,this.foldingStopMarker=/^[^\[\{]*(\}|\])|^[\s\*]*(\*\/)/,this.getFoldWidgetRange=function(a,b,c){var d=a.getLine(c),f=d.match(this.foldingStartMarker);if(f){var g=f.index;if(f[1])return this.openingBracketBlock(a,f[1],c,g);var h=a.getCommentFoldRange(c,g+f[0].length);return h.end.column-=2,h}if(b!=="markbeginend")return;var f=d.match(this.foldingStopMarker);if(f){var g=f.index+f[0].length;if(f[2]){var h=a.getCommentFoldRange(c,g);return h.end.column-=2,h}var i={row:c,column:g},j=a.$findOpeningBracket(f[1],i);if(!j)return;return j.column++,i.column--,e.fromPoints(j,i)}}}.call(g.prototype)}),define("ace/mode/folding/fold_mode",["require","exports","module","ace/range"],function(a,b,c){"use strict";var d=a("../../range").Range,e=b.FoldMode=function(){};((function(){this.foldingStartMarker=null,this.foldingStopMarker=null,this.getFoldWidget=function(a,b,c){var d=a.getLine(c);return this.foldingStartMarker.test(d)?"start":b=="markbeginend"&&this.foldingStopMarker&&this.foldingStopMarker.test(d)?"end":""},this.getFoldWidgetRange=function(a,b,c){return null},this.indentationBlock=function(a,b,c){var e=/^\s*/,f=b,g=b,h=a.getLine(b),i=c||h.length,j=h.match(e)[0].length,k=a.getLength();while(++b<k){h=a.getLine(b);var l=h.match(e)[0].length;if(l==h.length)continue;if(l<=j)break;g=b}if(g>f){var m=a.getLine(g).length;return new d(f,i,g,m)}},this.openingBracketBlock=function(a,b,c,e){var f={row:c,column:e+1},g=a.$findClosingBracket(b,f);if(!g)return;var h=a.foldWidgets[g.row];return h==null&&(h=this.getFoldWidget(a,g.row)),h=="start"&&(g.row--,g.column=a.getLine(g.row).length),d.fromPoints(f,g)}})).call(e.prototype)}),function(){window.require(["ace/ace"],function(a){window.ace||(window.ace={});for(var b in a)a.hasOwnProperty(b)&&(ace[b]=a[b])})}()
\ No newline at end of file
+define("ace/mode/php",["require","exports","module","ace/lib/oop","ace/mode/text","ace/tokenizer","ace/mode/php_highlight_rules","ace/mode/matching_brace_outdent","ace/range","ace/mode/behaviour/cstyle","ace/mode/folding/cstyle"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("./text").Mode,f=a("../tokenizer").Tokenizer,g=a("./php_highlight_rules").PhpHighlightRules,h=a("./matching_brace_outdent").MatchingBraceOutdent,i=a("../range").Range,j=a("./behaviour/cstyle").CstyleBehaviour,k=a("./folding/cstyle").FoldMode,l=function(){this.$tokenizer=new f((new g).getRules()),this.$outdent=new h,this.$behaviour=new j,this.foldingRules=new k};d.inherits(l,e),function(){this.toggleCommentLines=function(a,b,c,d){var e=!0,f=/^(\s*)#/;for(var g=c;g<=d;g++)if(!f.test(b.getLine(g))){e=!1;break}if(e){var h=new i(0,0,0,0);for(var g=c;g<=d;g++){var j=b.getLine(g),k=j.match(f);h.start.row=g,h.end.row=g,h.end.column=k[0].length,b.replace(h,k[1])}}else b.indentRows(c,d,"#")},this.getNextLineIndent=function(a,b,c){var d=this.$getIndent(b),e=this.$tokenizer.getLineTokens(b,a),f=e.tokens;if(f.length&&f[f.length-1].type=="comment")return d;if(a=="start"){var g=b.match(/^.*[\{\(\[\:]\s*$/);g&&(d+=c)}return d},this.checkOutdent=function(a,b,c){return this.$outdent.checkOutdent(b,c)},this.autoOutdent=function(a,b,c){this.$outdent.autoOutdent(b,c)}}.call(l.prototype),b.Mode=l}),define("ace/mode/php_highlight_rules",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/mode/doc_comment_highlight_rules","ace/mode/text_highlight_rules"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("../lib/lang"),f=a("./doc_comment_highlight_rules").DocCommentHighlightRules,g=a("./text_highlight_rules").TextHighlightRules,h=function(){var a=new f,b=e.arrayToMap("abs|acos|acosh|addcslashes|addslashes|aggregate|aggregate_info|aggregate_methods|aggregate_methods_by_list|aggregate_methods_by_regexp|aggregate_properties|aggregate_properties_by_list|aggregate_properties_by_regexp|aggregation_info|amqpconnection|amqpexchange|amqpqueue|apache_child_terminate|apache_get_modules|apache_get_version|apache_getenv|apache_lookup_uri|apache_note|apache_request_headers|apache_reset_timeout|apache_response_headers|apache_setenv|apc_add|apc_bin_dump|apc_bin_dumpfile|apc_bin_load|apc_bin_loadfile|apc_cache_info|apc_cas|apc_clear_cache|apc_compile_file|apc_dec|apc_define_constants|apc_delete|apc_delete_file|apc_exists|apc_fetch|apc_inc|apc_load_constants|apc_sma_info|apc_store|apciterator|apd_breakpoint|apd_callstack|apd_clunk|apd_continue|apd_croak|apd_dump_function_table|apd_dump_persistent_resources|apd_dump_regular_resources|apd_echo|apd_get_active_symbols|apd_set_pprof_trace|apd_set_session|apd_set_session_trace|apd_set_session_trace_socket|appenditerator|array|array_change_key_case|array_chunk|array_combine|array_count_values|array_diff|array_diff_assoc|array_diff_key|array_diff_uassoc|array_diff_ukey|array_fill|array_fill_keys|array_filter|array_flip|array_intersect|array_intersect_assoc|array_intersect_key|array_intersect_uassoc|array_intersect_ukey|array_key_exists|array_keys|array_map|array_merge|array_merge_recursive|array_multisort|array_pad|array_pop|array_product|array_push|array_rand|array_reduce|array_replace|array_replace_recursive|array_reverse|array_search|array_shift|array_slice|array_splice|array_sum|array_udiff|array_udiff_assoc|array_udiff_uassoc|array_uintersect|array_uintersect_assoc|array_uintersect_uassoc|array_unique|array_unshift|array_values|array_walk|array_walk_recursive|arrayaccess|arrayiterator|arrayobject|arsort|asin|asinh|asort|assert|assert_options|atan|atan2|atanh|audioproperties|badfunctioncallexception|badmethodcallexception|base64_decode|base64_encode|base_convert|basename|bbcode_add_element|bbcode_add_smiley|bbcode_create|bbcode_destroy|bbcode_parse|bbcode_set_arg_parser|bbcode_set_flags|bcadd|bccomp|bcdiv|bcmod|bcmul|bcompiler_load|bcompiler_load_exe|bcompiler_parse_class|bcompiler_read|bcompiler_write_class|bcompiler_write_constant|bcompiler_write_exe_footer|bcompiler_write_file|bcompiler_write_footer|bcompiler_write_function|bcompiler_write_functions_from_file|bcompiler_write_header|bcompiler_write_included_filename|bcpow|bcpowmod|bcscale|bcsqrt|bcsub|bin2hex|bind_textdomain_codeset|bindec|bindtextdomain|bson_decode|bson_encode|bumpValue|bzclose|bzcompress|bzdecompress|bzerrno|bzerror|bzerrstr|bzflush|bzopen|bzread|bzwrite|cachingiterator|cairo|cairo_create|cairo_font_face_get_type|cairo_font_face_status|cairo_font_options_create|cairo_font_options_equal|cairo_font_options_get_antialias|cairo_font_options_get_hint_metrics|cairo_font_options_get_hint_style|cairo_font_options_get_subpixel_order|cairo_font_options_hash|cairo_font_options_merge|cairo_font_options_set_antialias|cairo_font_options_set_hint_metrics|cairo_font_options_set_hint_style|cairo_font_options_set_subpixel_order|cairo_font_options_status|cairo_format_stride_for_width|cairo_image_surface_create|cairo_image_surface_create_for_data|cairo_image_surface_create_from_png|cairo_image_surface_get_data|cairo_image_surface_get_format|cairo_image_surface_get_height|cairo_image_surface_get_stride|cairo_image_surface_get_width|cairo_matrix_create_scale|cairo_matrix_create_translate|cairo_matrix_invert|cairo_matrix_multiply|cairo_matrix_rotate|cairo_matrix_transform_distance|cairo_matrix_transform_point|cairo_matrix_translate|cairo_pattern_add_color_stop_rgb|cairo_pattern_add_color_stop_rgba|cairo_pattern_create_for_surface|cairo_pattern_create_linear|cairo_pattern_create_radial|cairo_pattern_create_rgb|cairo_pattern_create_rgba|cairo_pattern_get_color_stop_count|cairo_pattern_get_color_stop_rgba|cairo_pattern_get_extend|cairo_pattern_get_filter|cairo_pattern_get_linear_points|cairo_pattern_get_matrix|cairo_pattern_get_radial_circles|cairo_pattern_get_rgba|cairo_pattern_get_surface|cairo_pattern_get_type|cairo_pattern_set_extend|cairo_pattern_set_filter|cairo_pattern_set_matrix|cairo_pattern_status|cairo_pdf_surface_create|cairo_pdf_surface_set_size|cairo_ps_get_levels|cairo_ps_level_to_string|cairo_ps_surface_create|cairo_ps_surface_dsc_begin_page_setup|cairo_ps_surface_dsc_begin_setup|cairo_ps_surface_dsc_comment|cairo_ps_surface_get_eps|cairo_ps_surface_restrict_to_level|cairo_ps_surface_set_eps|cairo_ps_surface_set_size|cairo_scaled_font_create|cairo_scaled_font_extents|cairo_scaled_font_get_ctm|cairo_scaled_font_get_font_face|cairo_scaled_font_get_font_matrix|cairo_scaled_font_get_font_options|cairo_scaled_font_get_scale_matrix|cairo_scaled_font_get_type|cairo_scaled_font_glyph_extents|cairo_scaled_font_status|cairo_scaled_font_text_extents|cairo_surface_copy_page|cairo_surface_create_similar|cairo_surface_finish|cairo_surface_flush|cairo_surface_get_content|cairo_surface_get_device_offset|cairo_surface_get_font_options|cairo_surface_get_type|cairo_surface_mark_dirty|cairo_surface_mark_dirty_rectangle|cairo_surface_set_device_offset|cairo_surface_set_fallback_resolution|cairo_surface_show_page|cairo_surface_status|cairo_surface_write_to_png|cairo_svg_surface_create|cairo_svg_surface_restrict_to_version|cairo_svg_version_to_string|cairoantialias|cairocontent|cairocontext|cairoexception|cairoextend|cairofillrule|cairofilter|cairofontface|cairofontoptions|cairofontslant|cairofonttype|cairofontweight|cairoformat|cairogradientpattern|cairohintmetrics|cairohintstyle|cairoimagesurface|cairolineargradient|cairolinecap|cairolinejoin|cairomatrix|cairooperator|cairopath|cairopattern|cairopatterntype|cairopdfsurface|cairopslevel|cairopssurface|cairoradialgradient|cairoscaledfont|cairosolidpattern|cairostatus|cairosubpixelorder|cairosurface|cairosurfacepattern|cairosurfacetype|cairosvgsurface|cairosvgversion|cairotoyfontface|cal_days_in_month|cal_from_jd|cal_info|cal_to_jd|calcul_hmac|calculhmac|call_user_func|call_user_func_array|call_user_method|call_user_method_array|callbackfilteriterator|ceil|chdb|chdb_create|chdir|checkdate|checkdnsrr|chgrp|chmod|chop|chown|chr|chroot|chunk_split|class_alias|class_exists|class_implements|class_parents|classkit_import|classkit_method_add|classkit_method_copy|classkit_method_redefine|classkit_method_remove|classkit_method_rename|clearstatcache|clone|closedir|closelog|collator|com|com_addref|com_create_guid|com_event_sink|com_get|com_get_active_object|com_invoke|com_isenum|com_load|com_load_typelib|com_message_pump|com_print_typeinfo|com_propget|com_propput|com_propset|com_release|com_set|compact|connection_aborted|connection_status|connection_timeout|constant|construct|construct|construct|convert_cyr_string|convert_uudecode|convert_uuencode|copy|cos|cosh|count|count_chars|countable|counter_bump|counter_bump_value|counter_create|counter_get|counter_get_meta|counter_get_named|counter_get_value|counter_reset|counter_reset_value|crack_check|crack_closedict|crack_getlastmessage|crack_opendict|crc32|create_function|crypt|ctype_alnum|ctype_alpha|ctype_cntrl|ctype_digit|ctype_graph|ctype_lower|ctype_print|ctype_punct|ctype_space|ctype_upper|ctype_xdigit|cubrid_affected_rows|cubrid_bind|cubrid_client_encoding|cubrid_close|cubrid_close_prepare|cubrid_close_request|cubrid_col_get|cubrid_col_size|cubrid_column_names|cubrid_column_types|cubrid_commit|cubrid_connect|cubrid_connect_with_url|cubrid_current_oid|cubrid_data_seek|cubrid_db_name|cubrid_disconnect|cubrid_drop|cubrid_errno|cubrid_error|cubrid_error_code|cubrid_error_code_facility|cubrid_error_msg|cubrid_execute|cubrid_fetch|cubrid_fetch_array|cubrid_fetch_assoc|cubrid_fetch_field|cubrid_fetch_lengths|cubrid_fetch_object|cubrid_fetch_row|cubrid_field_flags|cubrid_field_len|cubrid_field_name|cubrid_field_seek|cubrid_field_table|cubrid_field_type|cubrid_free_result|cubrid_get|cubrid_get_autocommit|cubrid_get_charset|cubrid_get_class_name|cubrid_get_client_info|cubrid_get_db_parameter|cubrid_get_server_info|cubrid_insert_id|cubrid_is_instance|cubrid_list_dbs|cubrid_load_from_glo|cubrid_lob_close|cubrid_lob_export|cubrid_lob_get|cubrid_lob_send|cubrid_lob_size|cubrid_lock_read|cubrid_lock_write|cubrid_move_cursor|cubrid_new_glo|cubrid_next_result|cubrid_num_cols|cubrid_num_fields|cubrid_num_rows|cubrid_ping|cubrid_prepare|cubrid_put|cubrid_query|cubrid_real_escape_string|cubrid_result|cubrid_rollback|cubrid_save_to_glo|cubrid_schema|cubrid_send_glo|cubrid_seq_drop|cubrid_seq_insert|cubrid_seq_put|cubrid_set_add|cubrid_set_autocommit|cubrid_set_db_parameter|cubrid_set_drop|cubrid_unbuffered_query|cubrid_version|curl_close|curl_copy_handle|curl_errno|curl_error|curl_exec|curl_getinfo|curl_init|curl_multi_add_handle|curl_multi_close|curl_multi_exec|curl_multi_getcontent|curl_multi_info_read|curl_multi_init|curl_multi_remove_handle|curl_multi_select|curl_setopt|curl_setopt_array|curl_version|current|cyrus_authenticate|cyrus_bind|cyrus_close|cyrus_connect|cyrus_query|cyrus_unbind|date|date_add|date_create|date_create_from_format|date_date_set|date_default_timezone_get|date_default_timezone_set|date_diff|date_format|date_get_last_errors|date_interval_create_from_date_string|date_interval_format|date_isodate_set|date_modify|date_offset_get|date_parse|date_parse_from_format|date_sub|date_sun_info|date_sunrise|date_sunset|date_time_set|date_timestamp_get|date_timestamp_set|date_timezone_get|date_timezone_set|dateinterval|dateperiod|datetime|datetimezone|db2_autocommit|db2_bind_param|db2_client_info|db2_close|db2_column_privileges|db2_columns|db2_commit|db2_conn_error|db2_conn_errormsg|db2_connect|db2_cursor_type|db2_escape_string|db2_exec|db2_execute|db2_fetch_array|db2_fetch_assoc|db2_fetch_both|db2_fetch_object|db2_fetch_row|db2_field_display_size|db2_field_name|db2_field_num|db2_field_precision|db2_field_scale|db2_field_type|db2_field_width|db2_foreign_keys|db2_free_result|db2_free_stmt|db2_get_option|db2_last_insert_id|db2_lob_read|db2_next_result|db2_num_fields|db2_num_rows|db2_pclose|db2_pconnect|db2_prepare|db2_primary_keys|db2_procedure_columns|db2_procedures|db2_result|db2_rollback|db2_server_info|db2_set_option|db2_special_columns|db2_statistics|db2_stmt_error|db2_stmt_errormsg|db2_table_privileges|db2_tables|dba_close|dba_delete|dba_exists|dba_fetch|dba_firstkey|dba_handlers|dba_insert|dba_key_split|dba_list|dba_nextkey|dba_open|dba_optimize|dba_popen|dba_replace|dba_sync|dbase_add_record|dbase_close|dbase_create|dbase_delete_record|dbase_get_header_info|dbase_get_record|dbase_get_record_with_names|dbase_numfields|dbase_numrecords|dbase_open|dbase_pack|dbase_replace_record|dbplus_add|dbplus_aql|dbplus_chdir|dbplus_close|dbplus_curr|dbplus_errcode|dbplus_errno|dbplus_find|dbplus_first|dbplus_flush|dbplus_freealllocks|dbplus_freelock|dbplus_freerlocks|dbplus_getlock|dbplus_getunique|dbplus_info|dbplus_last|dbplus_lockrel|dbplus_next|dbplus_open|dbplus_prev|dbplus_rchperm|dbplus_rcreate|dbplus_rcrtexact|dbplus_rcrtlike|dbplus_resolve|dbplus_restorepos|dbplus_rkeys|dbplus_ropen|dbplus_rquery|dbplus_rrename|dbplus_rsecindex|dbplus_runlink|dbplus_rzap|dbplus_savepos|dbplus_setindex|dbplus_setindexbynumber|dbplus_sql|dbplus_tcl|dbplus_tremove|dbplus_undo|dbplus_undoprepare|dbplus_unlockrel|dbplus_unselect|dbplus_update|dbplus_xlockrel|dbplus_xunlockrel|dbx_close|dbx_compare|dbx_connect|dbx_error|dbx_escape_string|dbx_fetch_row|dbx_query|dbx_sort|dcgettext|dcngettext|deaggregate|debug_backtrace|debug_print_backtrace|debug_zval_dump|decbin|dechex|decoct|define|define_syslog_variables|defined|deg2rad|delete|dgettext|die|dio_close|dio_fcntl|dio_open|dio_read|dio_seek|dio_stat|dio_tcsetattr|dio_truncate|dio_write|dir|directoryiterator|dirname|disk_free_space|disk_total_space|diskfreespace|dl|dngettext|dns_check_record|dns_get_mx|dns_get_record|dom_import_simplexml|domainexception|domattr|domattribute_name|domattribute_set_value|domattribute_specified|domattribute_value|domcharacterdata|domcomment|domdocument|domdocument_add_root|domdocument_create_attribute|domdocument_create_cdata_section|domdocument_create_comment|domdocument_create_element|domdocument_create_element_ns|domdocument_create_entity_reference|domdocument_create_processing_instruction|domdocument_create_text_node|domdocument_doctype|domdocument_document_element|domdocument_dump_file|domdocument_dump_mem|domdocument_get_element_by_id|domdocument_get_elements_by_tagname|domdocument_html_dump_mem|domdocument_xinclude|domdocumentfragment|domdocumenttype|domdocumenttype_entities|domdocumenttype_internal_subset|domdocumenttype_name|domdocumenttype_notations|domdocumenttype_public_id|domdocumenttype_system_id|domelement|domelement_get_attribute|domelement_get_attribute_node|domelement_get_elements_by_tagname|domelement_has_attribute|domelement_remove_attribute|domelement_set_attribute|domelement_set_attribute_node|domelement_tagname|domentity|domentityreference|domexception|domimplementation|domnamednodemap|domnode|domnode_add_namespace|domnode_append_child|domnode_append_sibling|domnode_attributes|domnode_child_nodes|domnode_clone_node|domnode_dump_node|domnode_first_child|domnode_get_content|domnode_has_attributes|domnode_has_child_nodes|domnode_insert_before|domnode_is_blank_node|domnode_last_child|domnode_next_sibling|domnode_node_name|domnode_node_type|domnode_node_value|domnode_owner_document|domnode_parent_node|domnode_prefix|domnode_previous_sibling|domnode_remove_child|domnode_replace_child|domnode_replace_node|domnode_set_content|domnode_set_name|domnode_set_namespace|domnode_unlink_node|domnodelist|domnotation|domprocessinginstruction|domprocessinginstruction_data|domprocessinginstruction_target|domtext|domxml_new_doc|domxml_open_file|domxml_open_mem|domxml_version|domxml_xmltree|domxml_xslt_stylesheet|domxml_xslt_stylesheet_doc|domxml_xslt_stylesheet_file|domxml_xslt_version|domxpath|domxsltstylesheet_process|domxsltstylesheet_result_dump_file|domxsltstylesheet_result_dump_mem|dotnet|dotnet_load|doubleval|each|easter_date|easter_days|echo|empty|emptyiterator|enchant_broker_describe|enchant_broker_dict_exists|enchant_broker_free|enchant_broker_free_dict|enchant_broker_get_error|enchant_broker_init|enchant_broker_list_dicts|enchant_broker_request_dict|enchant_broker_request_pwl_dict|enchant_broker_set_ordering|enchant_dict_add_to_personal|enchant_dict_add_to_session|enchant_dict_check|enchant_dict_describe|enchant_dict_get_error|enchant_dict_is_in_session|enchant_dict_quick_check|enchant_dict_store_replacement|enchant_dict_suggest|end|ereg|ereg_replace|eregi|eregi_replace|error_get_last|error_log|error_reporting|errorexception|escapeshellarg|escapeshellcmd|eval|event_add|event_base_free|event_base_loop|event_base_loopbreak|event_base_loopexit|event_base_new|event_base_priority_init|event_base_set|event_buffer_base_set|event_buffer_disable|event_buffer_enable|event_buffer_fd_set|event_buffer_free|event_buffer_new|event_buffer_priority_set|event_buffer_read|event_buffer_set_callback|event_buffer_timeout_set|event_buffer_watermark_set|event_buffer_write|event_del|event_free|event_new|event_set|exception|exec|exif_imagetype|exif_read_data|exif_tagname|exif_thumbnail|exit|exp|expect_expectl|expect_popen|explode|expm1|export|export|extension_loaded|extract|ezmlm_hash|fam_cancel_monitor|fam_close|fam_monitor_collection|fam_monitor_directory|fam_monitor_file|fam_next_event|fam_open|fam_pending|fam_resume_monitor|fam_suspend_monitor|fbsql_affected_rows|fbsql_autocommit|fbsql_blob_size|fbsql_change_user|fbsql_clob_size|fbsql_close|fbsql_commit|fbsql_connect|fbsql_create_blob|fbsql_create_clob|fbsql_create_db|fbsql_data_seek|fbsql_database|fbsql_database_password|fbsql_db_query|fbsql_db_status|fbsql_drop_db|fbsql_errno|fbsql_error|fbsql_fetch_array|fbsql_fetch_assoc|fbsql_fetch_field|fbsql_fetch_lengths|fbsql_fetch_object|fbsql_fetch_row|fbsql_field_flags|fbsql_field_len|fbsql_field_name|fbsql_field_seek|fbsql_field_table|fbsql_field_type|fbsql_free_result|fbsql_get_autostart_info|fbsql_hostname|fbsql_insert_id|fbsql_list_dbs|fbsql_list_fields|fbsql_list_tables|fbsql_next_result|fbsql_num_fields|fbsql_num_rows|fbsql_password|fbsql_pconnect|fbsql_query|fbsql_read_blob|fbsql_read_clob|fbsql_result|fbsql_rollback|fbsql_rows_fetched|fbsql_select_db|fbsql_set_characterset|fbsql_set_lob_mode|fbsql_set_password|fbsql_set_transaction|fbsql_start_db|fbsql_stop_db|fbsql_table_name|fbsql_tablename|fbsql_username|fbsql_warnings|fclose|fdf_add_doc_javascript|fdf_add_template|fdf_close|fdf_create|fdf_enum_values|fdf_errno|fdf_error|fdf_get_ap|fdf_get_attachment|fdf_get_encoding|fdf_get_file|fdf_get_flags|fdf_get_opt|fdf_get_status|fdf_get_value|fdf_get_version|fdf_header|fdf_next_field_name|fdf_open|fdf_open_string|fdf_remove_item|fdf_save|fdf_save_string|fdf_set_ap|fdf_set_encoding|fdf_set_file|fdf_set_flags|fdf_set_javascript_action|fdf_set_on_import_javascript|fdf_set_opt|fdf_set_status|fdf_set_submit_form_action|fdf_set_target_frame|fdf_set_value|fdf_set_version|feof|fflush|fgetc|fgetcsv|fgets|fgetss|file|file_exists|file_get_contents|file_put_contents|fileatime|filectime|filegroup|fileinode|filemtime|fileowner|fileperms|filepro|filepro_fieldcount|filepro_fieldname|filepro_fieldtype|filepro_fieldwidth|filepro_retrieve|filepro_rowcount|filesize|filesystemiterator|filetype|filter_has_var|filter_id|filter_input|filter_input_array|filter_list|filter_var|filter_var_array|filteriterator|finfo_buffer|finfo_close|finfo_file|finfo_open|finfo_set_flags|floatval|flock|floor|flush|fmod|fnmatch|fopen|forward_static_call|forward_static_call_array|fpassthru|fprintf|fputcsv|fputs|fread|frenchtojd|fribidi_log2vis|fscanf|fseek|fsockopen|fstat|ftell|ftok|ftp_alloc|ftp_cdup|ftp_chdir|ftp_chmod|ftp_close|ftp_connect|ftp_delete|ftp_exec|ftp_fget|ftp_fput|ftp_get|ftp_get_option|ftp_login|ftp_mdtm|ftp_mkdir|ftp_nb_continue|ftp_nb_fget|ftp_nb_fput|ftp_nb_get|ftp_nb_put|ftp_nlist|ftp_pasv|ftp_put|ftp_pwd|ftp_quit|ftp_raw|ftp_rawlist|ftp_rename|ftp_rmdir|ftp_set_option|ftp_site|ftp_size|ftp_ssl_connect|ftp_systype|ftruncate|func_get_arg|func_get_args|func_num_args|function_exists|fwrite|gc_collect_cycles|gc_disable|gc_enable|gc_enabled|gd_info|gearmanclient|gearmanjob|gearmantask|gearmanworker|geoip_continent_code_by_name|geoip_country_code3_by_name|geoip_country_code_by_name|geoip_country_name_by_name|geoip_database_info|geoip_db_avail|geoip_db_filename|geoip_db_get_all_info|geoip_id_by_name|geoip_isp_by_name|geoip_org_by_name|geoip_record_by_name|geoip_region_by_name|geoip_region_name_by_code|geoip_time_zone_by_country_and_region|getMeta|getNamed|getValue|get_browser|get_called_class|get_cfg_var|get_class|get_class_methods|get_class_vars|get_current_user|get_declared_classes|get_declared_interfaces|get_defined_constants|get_defined_functions|get_defined_vars|get_extension_funcs|get_headers|get_html_translation_table|get_include_path|get_included_files|get_loaded_extensions|get_magic_quotes_gpc|get_magic_quotes_runtime|get_meta_tags|get_object_vars|get_parent_class|get_required_files|get_resource_type|getallheaders|getconstant|getconstants|getconstructor|getcwd|getdate|getdefaultproperties|getdoccomment|getendline|getenv|getextension|getextensionname|getfilename|gethostbyaddr|gethostbyname|gethostbynamel|gethostname|getimagesize|getinterfacenames|getinterfaces|getlastmod|getmethod|getmethods|getmodifiers|getmxrr|getmygid|getmyinode|getmypid|getmyuid|getname|getnamespacename|getopt|getparentclass|getproperties|getproperty|getprotobyname|getprotobynumber|getrandmax|getrusage|getservbyname|getservbyport|getshortname|getstartline|getstaticproperties|getstaticpropertyvalue|gettext|gettimeofday|gettype|glob|globiterator|gmagick|gmagickdraw|gmagickpixel|gmdate|gmmktime|gmp_abs|gmp_add|gmp_and|gmp_clrbit|gmp_cmp|gmp_com|gmp_div|gmp_div_q|gmp_div_qr|gmp_div_r|gmp_divexact|gmp_fact|gmp_gcd|gmp_gcdext|gmp_hamdist|gmp_init|gmp_intval|gmp_invert|gmp_jacobi|gmp_legendre|gmp_mod|gmp_mul|gmp_neg|gmp_nextprime|gmp_or|gmp_perfect_square|gmp_popcount|gmp_pow|gmp_powm|gmp_prob_prime|gmp_random|gmp_scan0|gmp_scan1|gmp_setbit|gmp_sign|gmp_sqrt|gmp_sqrtrem|gmp_strval|gmp_sub|gmp_testbit|gmp_xor|gmstrftime|gnupg_adddecryptkey|gnupg_addencryptkey|gnupg_addsignkey|gnupg_cleardecryptkeys|gnupg_clearencryptkeys|gnupg_clearsignkeys|gnupg_decrypt|gnupg_decryptverify|gnupg_encrypt|gnupg_encryptsign|gnupg_export|gnupg_geterror|gnupg_getprotocol|gnupg_import|gnupg_init|gnupg_keyinfo|gnupg_setarmor|gnupg_seterrormode|gnupg_setsignmode|gnupg_sign|gnupg_verify|gopher_parsedir|grapheme_extract|grapheme_stripos|grapheme_stristr|grapheme_strlen|grapheme_strpos|grapheme_strripos|grapheme_strrpos|grapheme_strstr|grapheme_substr|gregoriantojd|gupnp_context_get_host_ip|gupnp_context_get_port|gupnp_context_get_subscription_timeout|gupnp_context_host_path|gupnp_context_new|gupnp_context_set_subscription_timeout|gupnp_context_timeout_add|gupnp_context_unhost_path|gupnp_control_point_browse_start|gupnp_control_point_browse_stop|gupnp_control_point_callback_set|gupnp_control_point_new|gupnp_device_action_callback_set|gupnp_device_info_get|gupnp_device_info_get_service|gupnp_root_device_get_available|gupnp_root_device_get_relative_location|gupnp_root_device_new|gupnp_root_device_set_available|gupnp_root_device_start|gupnp_root_device_stop|gupnp_service_action_get|gupnp_service_action_return|gupnp_service_action_return_error|gupnp_service_action_set|gupnp_service_freeze_notify|gupnp_service_info_get|gupnp_service_info_get_introspection|gupnp_service_introspection_get_state_variable|gupnp_service_notify|gupnp_service_proxy_action_get|gupnp_service_proxy_action_set|gupnp_service_proxy_add_notify|gupnp_service_proxy_callback_set|gupnp_service_proxy_get_subscribed|gupnp_service_proxy_remove_notify|gupnp_service_proxy_set_subscribed|gupnp_service_thaw_notify|gzclose|gzcompress|gzdecode|gzdeflate|gzencode|gzeof|gzfile|gzgetc|gzgets|gzgetss|gzinflate|gzopen|gzpassthru|gzputs|gzread|gzrewind|gzseek|gztell|gzuncompress|gzwrite|halt_compiler|haruannotation|haruannotation_setborderstyle|haruannotation_sethighlightmode|haruannotation_seticon|haruannotation_setopened|harudestination|harudestination_setfit|harudestination_setfitb|harudestination_setfitbh|harudestination_setfitbv|harudestination_setfith|harudestination_setfitr|harudestination_setfitv|harudestination_setxyz|harudoc|harudoc_addpage|harudoc_addpagelabel|harudoc_construct|harudoc_createoutline|harudoc_getcurrentencoder|harudoc_getcurrentpage|harudoc_getencoder|harudoc_getfont|harudoc_getinfoattr|harudoc_getpagelayout|harudoc_getpagemode|harudoc_getstreamsize|harudoc_insertpage|harudoc_loadjpeg|harudoc_loadpng|harudoc_loadraw|harudoc_loadttc|harudoc_loadttf|harudoc_loadtype1|harudoc_output|harudoc_readfromstream|harudoc_reseterror|harudoc_resetstream|harudoc_save|harudoc_savetostream|harudoc_setcompressionmode|harudoc_setcurrentencoder|harudoc_setencryptionmode|harudoc_setinfoattr|harudoc_setinfodateattr|harudoc_setopenaction|harudoc_setpagelayout|harudoc_setpagemode|harudoc_setpagesconfiguration|harudoc_setpassword|harudoc_setpermission|harudoc_usecnsencodings|harudoc_usecnsfonts|harudoc_usecntencodings|harudoc_usecntfonts|harudoc_usejpencodings|harudoc_usejpfonts|harudoc_usekrencodings|harudoc_usekrfonts|haruencoder|haruencoder_getbytetype|haruencoder_gettype|haruencoder_getunicode|haruencoder_getwritingmode|haruexception|harufont|harufont_getascent|harufont_getcapheight|harufont_getdescent|harufont_getencodingname|harufont_getfontname|harufont_gettextwidth|harufont_getunicodewidth|harufont_getxheight|harufont_measuretext|haruimage|haruimage_getbitspercomponent|haruimage_getcolorspace|haruimage_getheight|haruimage_getsize|haruimage_getwidth|haruimage_setcolormask|haruimage_setmaskimage|haruoutline|haruoutline_setdestination|haruoutline_setopened|harupage|harupage_arc|harupage_begintext|harupage_circle|harupage_closepath|harupage_concat|harupage_createdestination|harupage_createlinkannotation|harupage_createtextannotation|harupage_createurlannotation|harupage_curveto|harupage_curveto2|harupage_curveto3|harupage_drawimage|harupage_ellipse|harupage_endpath|harupage_endtext|harupage_eofill|harupage_eofillstroke|harupage_fill|harupage_fillstroke|harupage_getcharspace|harupage_getcmykfill|harupage_getcmykstroke|harupage_getcurrentfont|harupage_getcurrentfontsize|harupage_getcurrentpos|harupage_getcurrenttextpos|harupage_getdash|harupage_getfillingcolorspace|harupage_getflatness|harupage_getgmode|harupage_getgrayfill|harupage_getgraystroke|harupage_getheight|harupage_gethorizontalscaling|harupage_getlinecap|harupage_getlinejoin|harupage_getlinewidth|harupage_getmiterlimit|harupage_getrgbfill|harupage_getrgbstroke|harupage_getstrokingcolorspace|harupage_gettextleading|harupage_gettextmatrix|harupage_gettextrenderingmode|harupage_gettextrise|harupage_gettextwidth|harupage_gettransmatrix|harupage_getwidth|harupage_getwordspace|harupage_lineto|harupage_measuretext|harupage_movetextpos|harupage_moveto|harupage_movetonextline|harupage_rectangle|harupage_setcharspace|harupage_setcmykfill|harupage_setcmykstroke|harupage_setdash|harupage_setflatness|harupage_setfontandsize|harupage_setgrayfill|harupage_setgraystroke|harupage_setheight|harupage_sethorizontalscaling|harupage_setlinecap|harupage_setlinejoin|harupage_setlinewidth|harupage_setmiterlimit|harupage_setrgbfill|harupage_setrgbstroke|harupage_setrotate|harupage_setsize|harupage_setslideshow|harupage_settextleading|harupage_settextmatrix|harupage_settextrenderingmode|harupage_settextrise|harupage_setwidth|harupage_setwordspace|harupage_showtext|harupage_showtextnextline|harupage_stroke|harupage_textout|harupage_textrect|hasconstant|hash|hash_algos|hash_copy|hash_file|hash_final|hash_hmac|hash_hmac_file|hash_init|hash_update|hash_update_file|hash_update_stream|hasmethod|hasproperty|header|header_register_callback|header_remove|headers_list|headers_sent|hebrev|hebrevc|hex2bin|hexdec|highlight_file|highlight_string|html_entity_decode|htmlentities|htmlspecialchars|htmlspecialchars_decode|http_build_cookie|http_build_query|http_build_str|http_build_url|http_cache_etag|http_cache_last_modified|http_chunked_decode|http_date|http_deflate|http_get|http_get_request_body|http_get_request_body_stream|http_get_request_headers|http_head|http_inflate|http_match_etag|http_match_modified|http_match_request_header|http_negotiate_charset|http_negotiate_content_type|http_negotiate_language|http_parse_cookie|http_parse_headers|http_parse_message|http_parse_params|http_persistent_handles_clean|http_persistent_handles_count|http_persistent_handles_ident|http_post_data|http_post_fields|http_put_data|http_put_file|http_put_stream|http_redirect|http_request|http_request_body_encode|http_request_method_exists|http_request_method_name|http_request_method_register|http_request_method_unregister|http_response_code|http_send_content_disposition|http_send_content_type|http_send_data|http_send_file|http_send_last_modified|http_send_status|http_send_stream|http_support|http_throttle|httpdeflatestream|httpdeflatestream_construct|httpdeflatestream_factory|httpdeflatestream_finish|httpdeflatestream_flush|httpdeflatestream_update|httpinflatestream|httpinflatestream_construct|httpinflatestream_factory|httpinflatestream_finish|httpinflatestream_flush|httpinflatestream_update|httpmessage|httpmessage_addheaders|httpmessage_construct|httpmessage_detach|httpmessage_factory|httpmessage_fromenv|httpmessage_fromstring|httpmessage_getbody|httpmessage_getheader|httpmessage_getheaders|httpmessage_gethttpversion|httpmessage_getparentmessage|httpmessage_getrequestmethod|httpmessage_getrequesturl|httpmessage_getresponsecode|httpmessage_getresponsestatus|httpmessage_gettype|httpmessage_guesscontenttype|httpmessage_prepend|httpmessage_reverse|httpmessage_send|httpmessage_setbody|httpmessage_setheaders|httpmessage_sethttpversion|httpmessage_setrequestmethod|httpmessage_setrequesturl|httpmessage_setresponsecode|httpmessage_setresponsestatus|httpmessage_settype|httpmessage_tomessagetypeobject|httpmessage_tostring|httpquerystring|httpquerystring_construct|httpquerystring_get|httpquerystring_mod|httpquerystring_set|httpquerystring_singleton|httpquerystring_toarray|httpquerystring_tostring|httpquerystring_xlate|httprequest|httprequest_addcookies|httprequest_addheaders|httprequest_addpostfields|httprequest_addpostfile|httprequest_addputdata|httprequest_addquerydata|httprequest_addrawpostdata|httprequest_addssloptions|httprequest_clearhistory|httprequest_construct|httprequest_enablecookies|httprequest_getcontenttype|httprequest_getcookies|httprequest_getheaders|httprequest_gethistory|httprequest_getmethod|httprequest_getoptions|httprequest_getpostfields|httprequest_getpostfiles|httprequest_getputdata|httprequest_getputfile|httprequest_getquerydata|httprequest_getrawpostdata|httprequest_getrawrequestmessage|httprequest_getrawresponsemessage|httprequest_getrequestmessage|httprequest_getresponsebody|httprequest_getresponsecode|httprequest_getresponsecookies|httprequest_getresponsedata|httprequest_getresponseheader|httprequest_getresponseinfo|httprequest_getresponsemessage|httprequest_getresponsestatus|httprequest_getssloptions|httprequest_geturl|httprequest_resetcookies|httprequest_send|httprequest_setcontenttype|httprequest_setcookies|httprequest_setheaders|httprequest_setmethod|httprequest_setoptions|httprequest_setpostfields|httprequest_setpostfiles|httprequest_setputdata|httprequest_setputfile|httprequest_setquerydata|httprequest_setrawpostdata|httprequest_setssloptions|httprequest_seturl|httprequestpool|httprequestpool_attach|httprequestpool_construct|httprequestpool_destruct|httprequestpool_detach|httprequestpool_getattachedrequests|httprequestpool_getfinishedrequests|httprequestpool_reset|httprequestpool_send|httprequestpool_socketperform|httprequestpool_socketselect|httpresponse|httpresponse_capture|httpresponse_getbuffersize|httpresponse_getcache|httpresponse_getcachecontrol|httpresponse_getcontentdisposition|httpresponse_getcontenttype|httpresponse_getdata|httpresponse_getetag|httpresponse_getfile|httpresponse_getgzip|httpresponse_getheader|httpresponse_getlastmodified|httpresponse_getrequestbody|httpresponse_getrequestbodystream|httpresponse_getrequestheaders|httpresponse_getstream|httpresponse_getthrottledelay|httpresponse_guesscontenttype|httpresponse_redirect|httpresponse_send|httpresponse_setbuffersize|httpresponse_setcache|httpresponse_setcachecontrol|httpresponse_setcontentdisposition|httpresponse_setcontenttype|httpresponse_setdata|httpresponse_setetag|httpresponse_setfile|httpresponse_setgzip|httpresponse_setheader|httpresponse_setlastmodified|httpresponse_setstream|httpresponse_setthrottledelay|httpresponse_status|hw_array2objrec|hw_changeobject|hw_children|hw_childrenobj|hw_close|hw_connect|hw_connection_info|hw_cp|hw_deleteobject|hw_docbyanchor|hw_docbyanchorobj|hw_document_attributes|hw_document_bodytag|hw_document_content|hw_document_setcontent|hw_document_size|hw_dummy|hw_edittext|hw_error|hw_errormsg|hw_free_document|hw_getanchors|hw_getanchorsobj|hw_getandlock|hw_getchildcoll|hw_getchildcollobj|hw_getchilddoccoll|hw_getchilddoccollobj|hw_getobject|hw_getobjectbyquery|hw_getobjectbyquerycoll|hw_getobjectbyquerycollobj|hw_getobjectbyqueryobj|hw_getparents|hw_getparentsobj|hw_getrellink|hw_getremote|hw_getremotechildren|hw_getsrcbydestobj|hw_gettext|hw_getusername|hw_identify|hw_incollections|hw_info|hw_inscoll|hw_insdoc|hw_insertanchors|hw_insertdocument|hw_insertobject|hw_mapid|hw_modifyobject|hw_mv|hw_new_document|hw_objrec2array|hw_output_document|hw_pconnect|hw_pipedocument|hw_root|hw_setlinkroot|hw_stat|hw_unlock|hw_who|hwapi_attribute|hwapi_attribute_key|hwapi_attribute_langdepvalue|hwapi_attribute_value|hwapi_attribute_values|hwapi_checkin|hwapi_checkout|hwapi_children|hwapi_content|hwapi_content_mimetype|hwapi_content_read|hwapi_copy|hwapi_dbstat|hwapi_dcstat|hwapi_dstanchors|hwapi_dstofsrcanchor|hwapi_error_count|hwapi_error_reason|hwapi_find|hwapi_ftstat|hwapi_hgcsp|hwapi_hwstat|hwapi_identify|hwapi_info|hwapi_insert|hwapi_insertanchor|hwapi_insertcollection|hwapi_insertdocument|hwapi_link|hwapi_lock|hwapi_move|hwapi_new_content|hwapi_object|hwapi_object_assign|hwapi_object_attreditable|hwapi_object_count|hwapi_object_insert|hwapi_object_new|hwapi_object_remove|hwapi_object_title|hwapi_object_value|hwapi_objectbyanchor|hwapi_parents|hwapi_reason_description|hwapi_reason_type|hwapi_remove|hwapi_replace|hwapi_setcommittedversion|hwapi_srcanchors|hwapi_srcsofdst|hwapi_unlock|hwapi_user|hwapi_userlist|hypot|ibase_add_user|ibase_affected_rows|ibase_backup|ibase_blob_add|ibase_blob_cancel|ibase_blob_close|ibase_blob_create|ibase_blob_echo|ibase_blob_get|ibase_blob_import|ibase_blob_info|ibase_blob_open|ibase_close|ibase_commit|ibase_commit_ret|ibase_connect|ibase_db_info|ibase_delete_user|ibase_drop_db|ibase_errcode|ibase_errmsg|ibase_execute|ibase_fetch_assoc|ibase_fetch_object|ibase_fetch_row|ibase_field_info|ibase_free_event_handler|ibase_free_query|ibase_free_result|ibase_gen_id|ibase_maintain_db|ibase_modify_user|ibase_name_result|ibase_num_fields|ibase_num_params|ibase_param_info|ibase_pconnect|ibase_prepare|ibase_query|ibase_restore|ibase_rollback|ibase_rollback_ret|ibase_server_info|ibase_service_attach|ibase_service_detach|ibase_set_event_handler|ibase_timefmt|ibase_trans|ibase_wait_event|iconv|iconv_get_encoding|iconv_mime_decode|iconv_mime_decode_headers|iconv_mime_encode|iconv_set_encoding|iconv_strlen|iconv_strpos|iconv_strrpos|iconv_substr|id3_get_frame_long_name|id3_get_frame_short_name|id3_get_genre_id|id3_get_genre_list|id3_get_genre_name|id3_get_tag|id3_get_version|id3_remove_tag|id3_set_tag|id3v2attachedpictureframe|id3v2frame|id3v2tag|idate|idn_to_ascii|idn_to_unicode|idn_to_utf8|ifx_affected_rows|ifx_blobinfile_mode|ifx_byteasvarchar|ifx_close|ifx_connect|ifx_copy_blob|ifx_create_blob|ifx_create_char|ifx_do|ifx_error|ifx_errormsg|ifx_fetch_row|ifx_fieldproperties|ifx_fieldtypes|ifx_free_blob|ifx_free_char|ifx_free_result|ifx_get_blob|ifx_get_char|ifx_getsqlca|ifx_htmltbl_result|ifx_nullformat|ifx_num_fields|ifx_num_rows|ifx_pconnect|ifx_prepare|ifx_query|ifx_textasvarchar|ifx_update_blob|ifx_update_char|ifxus_close_slob|ifxus_create_slob|ifxus_free_slob|ifxus_open_slob|ifxus_read_slob|ifxus_seek_slob|ifxus_tell_slob|ifxus_write_slob|ignore_user_abort|iis_add_server|iis_get_dir_security|iis_get_script_map|iis_get_server_by_comment|iis_get_server_by_path|iis_get_server_rights|iis_get_service_state|iis_remove_server|iis_set_app_settings|iis_set_dir_security|iis_set_script_map|iis_set_server_rights|iis_start_server|iis_start_service|iis_stop_server|iis_stop_service|image2wbmp|image_type_to_extension|image_type_to_mime_type|imagealphablending|imageantialias|imagearc|imagechar|imagecharup|imagecolorallocate|imagecolorallocatealpha|imagecolorat|imagecolorclosest|imagecolorclosestalpha|imagecolorclosesthwb|imagecolordeallocate|imagecolorexact|imagecolorexactalpha|imagecolormatch|imagecolorresolve|imagecolorresolvealpha|imagecolorset|imagecolorsforindex|imagecolorstotal|imagecolortransparent|imageconvolution|imagecopy|imagecopymerge|imagecopymergegray|imagecopyresampled|imagecopyresized|imagecreate|imagecreatefromgd|imagecreatefromgd2|imagecreatefromgd2part|imagecreatefromgif|imagecreatefromjpeg|imagecreatefrompng|imagecreatefromstring|imagecreatefromwbmp|imagecreatefromxbm|imagecreatefromxpm|imagecreatetruecolor|imagedashedline|imagedestroy|imageellipse|imagefill|imagefilledarc|imagefilledellipse|imagefilledpolygon|imagefilledrectangle|imagefilltoborder|imagefilter|imagefontheight|imagefontwidth|imageftbbox|imagefttext|imagegammacorrect|imagegd|imagegd2|imagegif|imagegrabscreen|imagegrabwindow|imageinterlace|imageistruecolor|imagejpeg|imagelayereffect|imageline|imageloadfont|imagepalettecopy|imagepng|imagepolygon|imagepsbbox|imagepsencodefont|imagepsextendfont|imagepsfreefont|imagepsloadfont|imagepsslantfont|imagepstext|imagerectangle|imagerotate|imagesavealpha|imagesetbrush|imagesetpixel|imagesetstyle|imagesetthickness|imagesettile|imagestring|imagestringup|imagesx|imagesy|imagetruecolortopalette|imagettfbbox|imagettftext|imagetypes|imagewbmp|imagexbm|imagick|imagick_adaptiveblurimage|imagick_adaptiveresizeimage|imagick_adaptivesharpenimage|imagick_adaptivethresholdimage|imagick_addimage|imagick_addnoiseimage|imagick_affinetransformimage|imagick_animateimages|imagick_annotateimage|imagick_appendimages|imagick_averageimages|imagick_blackthresholdimage|imagick_blurimage|imagick_borderimage|imagick_charcoalimage|imagick_chopimage|imagick_clear|imagick_clipimage|imagick_clippathimage|imagick_clone|imagick_clutimage|imagick_coalesceimages|imagick_colorfloodfillimage|imagick_colorizeimage|imagick_combineimages|imagick_commentimage|imagick_compareimagechannels|imagick_compareimagelayers|imagick_compareimages|imagick_compositeimage|imagick_construct|imagick_contrastimage|imagick_contraststretchimage|imagick_convolveimage|imagick_cropimage|imagick_cropthumbnailimage|imagick_current|imagick_cyclecolormapimage|imagick_decipherimage|imagick_deconstructimages|imagick_deleteimageartifact|imagick_despeckleimage|imagick_destroy|imagick_displayimage|imagick_displayimages|imagick_distortimage|imagick_drawimage|imagick_edgeimage|imagick_embossimage|imagick_encipherimage|imagick_enhanceimage|imagick_equalizeimage|imagick_evaluateimage|imagick_extentimage|imagick_flattenimages|imagick_flipimage|imagick_floodfillpaintimage|imagick_flopimage|imagick_frameimage|imagick_fximage|imagick_gammaimage|imagick_gaussianblurimage|imagick_getcolorspace|imagick_getcompression|imagick_getcompressionquality|imagick_getcopyright|imagick_getfilename|imagick_getfont|imagick_getformat|imagick_getgravity|imagick_gethomeurl|imagick_getimage|imagick_getimagealphachannel|imagick_getimageartifact|imagick_getimagebackgroundcolor|imagick_getimageblob|imagick_getimageblueprimary|imagick_getimagebordercolor|imagick_getimagechanneldepth|imagick_getimagechanneldistortion|imagick_getimagechanneldistortions|imagick_getimagechannelextrema|imagick_getimagechannelmean|imagick_getimagechannelrange|imagick_getimagechannelstatistics|imagick_getimageclipmask|imagick_getimagecolormapcolor|imagick_getimagecolors|imagick_getimagecolorspace|imagick_getimagecompose|imagick_getimagecompression|imagick_getimagecompressionquality|imagick_getimagedelay|imagick_getimagedepth|imagick_getimagedispose|imagick_getimagedistortion|imagick_getimageextrema|imagick_getimagefilename|imagick_getimageformat|imagick_getimagegamma|imagick_getimagegeometry|imagick_getimagegravity|imagick_getimagegreenprimary|imagick_getimageheight|imagick_getimagehistogram|imagick_getimageindex|imagick_getimageinterlacescheme|imagick_getimageinterpolatemethod|imagick_getimageiterations|imagick_getimagelength|imagick_getimagemagicklicense|imagick_getimagematte|imagick_getimagemattecolor|imagick_getimageorientation|imagick_getimagepage|imagick_getimagepixelcolor|imagick_getimageprofile|imagick_getimageprofiles|imagick_getimageproperties|imagick_getimageproperty|imagick_getimageredprimary|imagick_getimageregion|imagick_getimagerenderingintent|imagick_getimageresolution|imagick_getimagesblob|imagick_getimagescene|imagick_getimagesignature|imagick_getimagesize|imagick_getimagetickspersecond|imagick_getimagetotalinkdensity|imagick_getimagetype|imagick_getimageunits|imagick_getimagevirtualpixelmethod|imagick_getimagewhitepoint|imagick_getimagewidth|imagick_getinterlacescheme|imagick_getiteratorindex|imagick_getnumberimages|imagick_getoption|imagick_getpackagename|imagick_getpage|imagick_getpixeliterator|imagick_getpixelregioniterator|imagick_getpointsize|imagick_getquantumdepth|imagick_getquantumrange|imagick_getreleasedate|imagick_getresource|imagick_getresourcelimit|imagick_getsamplingfactors|imagick_getsize|imagick_getsizeoffset|imagick_getversion|imagick_hasnextimage|imagick_haspreviousimage|imagick_identifyimage|imagick_implodeimage|imagick_labelimage|imagick_levelimage|imagick_linearstretchimage|imagick_liquidrescaleimage|imagick_magnifyimage|imagick_mapimage|imagick_mattefloodfillimage|imagick_medianfilterimage|imagick_mergeimagelayers|imagick_minifyimage|imagick_modulateimage|imagick_montageimage|imagick_morphimages|imagick_mosaicimages|imagick_motionblurimage|imagick_negateimage|imagick_newimage|imagick_newpseudoimage|imagick_nextimage|imagick_normalizeimage|imagick_oilpaintimage|imagick_opaquepaintimage|imagick_optimizeimagelayers|imagick_orderedposterizeimage|imagick_paintfloodfillimage|imagick_paintopaqueimage|imagick_painttransparentimage|imagick_pingimage|imagick_pingimageblob|imagick_pingimagefile|imagick_polaroidimage|imagick_posterizeimage|imagick_previewimages|imagick_previousimage|imagick_profileimage|imagick_quantizeimage|imagick_quantizeimages|imagick_queryfontmetrics|imagick_queryfonts|imagick_queryformats|imagick_radialblurimage|imagick_raiseimage|imagick_randomthresholdimage|imagick_readimage|imagick_readimageblob|imagick_readimagefile|imagick_recolorimage|imagick_reducenoiseimage|imagick_removeimage|imagick_removeimageprofile|imagick_render|imagick_resampleimage|imagick_resetimagepage|imagick_resizeimage|imagick_rollimage|imagick_rotateimage|imagick_roundcorners|imagick_sampleimage|imagick_scaleimage|imagick_separateimagechannel|imagick_sepiatoneimage|imagick_setbackgroundcolor|imagick_setcolorspace|imagick_setcompression|imagick_setcompressionquality|imagick_setfilename|imagick_setfirstiterator|imagick_setfont|imagick_setformat|imagick_setgravity|imagick_setimage|imagick_setimagealphachannel|imagick_setimageartifact|imagick_setimagebackgroundcolor|imagick_setimagebias|imagick_setimageblueprimary|imagick_setimagebordercolor|imagick_setimagechanneldepth|imagick_setimageclipmask|imagick_setimagecolormapcolor|imagick_setimagecolorspace|imagick_setimagecompose|imagick_setimagecompression|imagick_setimagecompressionquality|imagick_setimagedelay|imagick_setimagedepth|imagick_setimagedispose|imagick_setimageextent|imagick_setimagefilename|imagick_setimageformat|imagick_setimagegamma|imagick_setimagegravity|imagick_setimagegreenprimary|imagick_setimageindex|imagick_setimageinterlacescheme|imagick_setimageinterpolatemethod|imagick_setimageiterations|imagick_setimagematte|imagick_setimagemattecolor|imagick_setimageopacity|imagick_setimageorientation|imagick_setimagepage|imagick_setimageprofile|imagick_setimageproperty|imagick_setimageredprimary|imagick_setimagerenderingintent|imagick_setimageresolution|imagick_setimagescene|imagick_setimagetickspersecond|imagick_setimagetype|imagick_setimageunits|imagick_setimagevirtualpixelmethod|imagick_setimagewhitepoint|imagick_setinterlacescheme|imagick_setiteratorindex|imagick_setlastiterator|imagick_setoption|imagick_setpage|imagick_setpointsize|imagick_setresolution|imagick_setresourcelimit|imagick_setsamplingfactors|imagick_setsize|imagick_setsizeoffset|imagick_settype|imagick_shadeimage|imagick_shadowimage|imagick_sharpenimage|imagick_shaveimage|imagick_shearimage|imagick_sigmoidalcontrastimage|imagick_sketchimage|imagick_solarizeimage|imagick_spliceimage|imagick_spreadimage|imagick_steganoimage|imagick_stereoimage|imagick_stripimage|imagick_swirlimage|imagick_textureimage|imagick_thresholdimage|imagick_thumbnailimage|imagick_tintimage|imagick_transformimage|imagick_transparentpaintimage|imagick_transposeimage|imagick_transverseimage|imagick_trimimage|imagick_uniqueimagecolors|imagick_unsharpmaskimage|imagick_valid|imagick_vignetteimage|imagick_waveimage|imagick_whitethresholdimage|imagick_writeimage|imagick_writeimagefile|imagick_writeimages|imagick_writeimagesfile|imagickdraw|imagickdraw_affine|imagickdraw_annotation|imagickdraw_arc|imagickdraw_bezier|imagickdraw_circle|imagickdraw_clear|imagickdraw_clone|imagickdraw_color|imagickdraw_comment|imagickdraw_composite|imagickdraw_construct|imagickdraw_destroy|imagickdraw_ellipse|imagickdraw_getclippath|imagickdraw_getcliprule|imagickdraw_getclipunits|imagickdraw_getfillcolor|imagickdraw_getfillopacity|imagickdraw_getfillrule|imagickdraw_getfont|imagickdraw_getfontfamily|imagickdraw_getfontsize|imagickdraw_getfontstyle|imagickdraw_getfontweight|imagickdraw_getgravity|imagickdraw_getstrokeantialias|imagickdraw_getstrokecolor|imagickdraw_getstrokedasharray|imagickdraw_getstrokedashoffset|imagickdraw_getstrokelinecap|imagickdraw_getstrokelinejoin|imagickdraw_getstrokemiterlimit|imagickdraw_getstrokeopacity|imagickdraw_getstrokewidth|imagickdraw_gettextalignment|imagickdraw_gettextantialias|imagickdraw_gettextdecoration|imagickdraw_gettextencoding|imagickdraw_gettextundercolor|imagickdraw_getvectorgraphics|imagickdraw_line|imagickdraw_matte|imagickdraw_pathclose|imagickdraw_pathcurvetoabsolute|imagickdraw_pathcurvetoquadraticbezierabsolute|imagickdraw_pathcurvetoquadraticbezierrelative|imagickdraw_pathcurvetoquadraticbeziersmoothabsolute|imagickdraw_pathcurvetoquadraticbeziersmoothrelative|imagickdraw_pathcurvetorelative|imagickdraw_pathcurvetosmoothabsolute|imagickdraw_pathcurvetosmoothrelative|imagickdraw_pathellipticarcabsolute|imagickdraw_pathellipticarcrelative|imagickdraw_pathfinish|imagickdraw_pathlinetoabsolute|imagickdraw_pathlinetohorizontalabsolute|imagickdraw_pathlinetohorizontalrelative|imagickdraw_pathlinetorelative|imagickdraw_pathlinetoverticalabsolute|imagickdraw_pathlinetoverticalrelative|imagickdraw_pathmovetoabsolute|imagickdraw_pathmovetorelative|imagickdraw_pathstart|imagickdraw_point|imagickdraw_polygon|imagickdraw_polyline|imagickdraw_pop|imagickdraw_popclippath|imagickdraw_popdefs|imagickdraw_poppattern|imagickdraw_push|imagickdraw_pushclippath|imagickdraw_pushdefs|imagickdraw_pushpattern|imagickdraw_rectangle|imagickdraw_render|imagickdraw_rotate|imagickdraw_roundrectangle|imagickdraw_scale|imagickdraw_setclippath|imagickdraw_setcliprule|imagickdraw_setclipunits|imagickdraw_setfillalpha|imagickdraw_setfillcolor|imagickdraw_setfillopacity|imagickdraw_setfillpatternurl|imagickdraw_setfillrule|imagickdraw_setfont|imagickdraw_setfontfamily|imagickdraw_setfontsize|imagickdraw_setfontstretch|imagickdraw_setfontstyle|imagickdraw_setfontweight|imagickdraw_setgravity|imagickdraw_setstrokealpha|imagickdraw_setstrokeantialias|imagickdraw_setstrokecolor|imagickdraw_setstrokedasharray|imagickdraw_setstrokedashoffset|imagickdraw_setstrokelinecap|imagickdraw_setstrokelinejoin|imagickdraw_setstrokemiterlimit|imagickdraw_setstrokeopacity|imagickdraw_setstrokepatternurl|imagickdraw_setstrokewidth|imagickdraw_settextalignment|imagickdraw_settextantialias|imagickdraw_settextdecoration|imagickdraw_settextencoding|imagickdraw_settextundercolor|imagickdraw_setvectorgraphics|imagickdraw_setviewbox|imagickdraw_skewx|imagickdraw_skewy|imagickdraw_translate|imagickpixel|imagickpixel_clear|imagickpixel_construct|imagickpixel_destroy|imagickpixel_getcolor|imagickpixel_getcolorasstring|imagickpixel_getcolorcount|imagickpixel_getcolorvalue|imagickpixel_gethsl|imagickpixel_issimilar|imagickpixel_setcolor|imagickpixel_setcolorvalue|imagickpixel_sethsl|imagickpixeliterator|imagickpixeliterator_clear|imagickpixeliterator_construct|imagickpixeliterator_destroy|imagickpixeliterator_getcurrentiteratorrow|imagickpixeliterator_getiteratorrow|imagickpixeliterator_getnextiteratorrow|imagickpixeliterator_getpreviousiteratorrow|imagickpixeliterator_newpixeliterator|imagickpixeliterator_newpixelregioniterator|imagickpixeliterator_resetiterator|imagickpixeliterator_setiteratorfirstrow|imagickpixeliterator_setiteratorlastrow|imagickpixeliterator_setiteratorrow|imagickpixeliterator_synciterator|imap_8bit|imap_alerts|imap_append|imap_base64|imap_binary|imap_body|imap_bodystruct|imap_check|imap_clearflag_full|imap_close|imap_create|imap_createmailbox|imap_delete|imap_deletemailbox|imap_errors|imap_expunge|imap_fetch_overview|imap_fetchbody|imap_fetchheader|imap_fetchmime|imap_fetchstructure|imap_fetchtext|imap_gc|imap_get_quota|imap_get_quotaroot|imap_getacl|imap_getmailboxes|imap_getsubscribed|imap_header|imap_headerinfo|imap_headers|imap_last_error|imap_list|imap_listmailbox|imap_listscan|imap_listsubscribed|imap_lsub|imap_mail|imap_mail_compose|imap_mail_copy|imap_mail_move|imap_mailboxmsginfo|imap_mime_header_decode|imap_msgno|imap_num_msg|imap_num_recent|imap_open|imap_ping|imap_qprint|imap_rename|imap_renamemailbox|imap_reopen|imap_rfc822_parse_adrlist|imap_rfc822_parse_headers|imap_rfc822_write_address|imap_savebody|imap_scan|imap_scanmailbox|imap_search|imap_set_quota|imap_setacl|imap_setflag_full|imap_sort|imap_status|imap_subscribe|imap_thread|imap_timeout|imap_uid|imap_undelete|imap_unsubscribe|imap_utf7_decode|imap_utf7_encode|imap_utf8|implementsinterface|implode|import_request_variables|in_array|include|include_once|inclued_get_data|inet_ntop|inet_pton|infiniteiterator|ingres_autocommit|ingres_autocommit_state|ingres_charset|ingres_close|ingres_commit|ingres_connect|ingres_cursor|ingres_errno|ingres_error|ingres_errsqlstate|ingres_escape_string|ingres_execute|ingres_fetch_array|ingres_fetch_assoc|ingres_fetch_object|ingres_fetch_proc_return|ingres_fetch_row|ingres_field_length|ingres_field_name|ingres_field_nullable|ingres_field_precision|ingres_field_scale|ingres_field_type|ingres_free_result|ingres_next_error|ingres_num_fields|ingres_num_rows|ingres_pconnect|ingres_prepare|ingres_query|ingres_result_seek|ingres_rollback|ingres_set_environment|ingres_unbuffered_query|ini_alter|ini_get|ini_get_all|ini_restore|ini_set|innamespace|inotify_add_watch|inotify_init|inotify_queue_len|inotify_read|inotify_rm_watch|interface_exists|intl_error_name|intl_get_error_code|intl_get_error_message|intl_is_failure|intldateformatter|intval|invalidargumentexception|invoke|invokeargs|ip2long|iptcembed|iptcparse|is_a|is_array|is_bool|is_callable|is_dir|is_double|is_executable|is_file|is_finite|is_float|is_infinite|is_int|is_integer|is_link|is_long|is_nan|is_null|is_numeric|is_object|is_readable|is_real|is_resource|is_scalar|is_soap_fault|is_string|is_subclass_of|is_uploaded_file|is_writable|is_writeable|isabstract|iscloneable|isdisabled|isfinal|isinstance|isinstantiable|isinterface|isinternal|isiterateable|isset|issubclassof|isuserdefined|iterator|iterator_apply|iterator_count|iterator_to_array|iteratoraggregate|iteratoriterator|java_last_exception_clear|java_last_exception_get|jddayofweek|jdmonthname|jdtofrench|jdtogregorian|jdtojewish|jdtojulian|jdtounix|jewishtojd|join|jpeg2wbmp|json_decode|json_encode|json_last_error|jsonserializable|judy|judy_type|judy_version|juliantojd|kadm5_chpass_principal|kadm5_create_principal|kadm5_delete_principal|kadm5_destroy|kadm5_flush|kadm5_get_policies|kadm5_get_principal|kadm5_get_principals|kadm5_init_with_password|kadm5_modify_principal|key|krsort|ksort|lcfirst|lcg_value|lchgrp|lchown|ldap_8859_to_t61|ldap_add|ldap_bind|ldap_close|ldap_compare|ldap_connect|ldap_count_entries|ldap_delete|ldap_dn2ufn|ldap_err2str|ldap_errno|ldap_error|ldap_explode_dn|ldap_first_attribute|ldap_first_entry|ldap_first_reference|ldap_free_result|ldap_get_attributes|ldap_get_dn|ldap_get_entries|ldap_get_option|ldap_get_values|ldap_get_values_len|ldap_list|ldap_mod_add|ldap_mod_del|ldap_mod_replace|ldap_modify|ldap_next_attribute|ldap_next_entry|ldap_next_reference|ldap_parse_reference|ldap_parse_result|ldap_read|ldap_rename|ldap_sasl_bind|ldap_search|ldap_set_option|ldap_set_rebind_proc|ldap_sort|ldap_start_tls|ldap_t61_to_8859|ldap_unbind|lengthexception|levenshtein|libxml_clear_errors|libxml_disable_entity_loader|libxml_get_errors|libxml_get_last_error|libxml_set_streams_context|libxml_use_internal_errors|libxmlerror|limititerator|link|linkinfo|list|locale|localeconv|localtime|log|log10|log1p|logicexception|long2ip|lstat|ltrim|lzf_compress|lzf_decompress|lzf_optimized_for|m_checkstatus|m_completeauthorizations|m_connect|m_connectionerror|m_deletetrans|m_destroyconn|m_destroyengine|m_getcell|m_getcellbynum|m_getcommadelimited|m_getheader|m_initconn|m_initengine|m_iscommadelimited|m_maxconntimeout|m_monitor|m_numcolumns|m_numrows|m_parsecommadelimited|m_responsekeys|m_responseparam|m_returnstatus|m_setblocking|m_setdropfile|m_setip|m_setssl|m_setssl_cafile|m_setssl_files|m_settimeout|m_sslcert_gen_hash|m_transactionssent|m_transinqueue|m_transkeyval|m_transnew|m_transsend|m_uwait|m_validateidentifier|m_verifyconnection|m_verifysslcert|magic_quotes_runtime|mail|mailparse_determine_best_xfer_encoding|mailparse_msg_create|mailparse_msg_extract_part|mailparse_msg_extract_part_file|mailparse_msg_extract_whole_part_file|mailparse_msg_free|mailparse_msg_get_part|mailparse_msg_get_part_data|mailparse_msg_get_structure|mailparse_msg_parse|mailparse_msg_parse_file|mailparse_rfc822_parse_addresses|mailparse_stream_encode|mailparse_uudecode_all|main|max|maxdb_affected_rows|maxdb_autocommit|maxdb_bind_param|maxdb_bind_result|maxdb_change_user|maxdb_character_set_name|maxdb_client_encoding|maxdb_close|maxdb_close_long_data|maxdb_commit|maxdb_connect|maxdb_connect_errno|maxdb_connect_error|maxdb_data_seek|maxdb_debug|maxdb_disable_reads_from_master|maxdb_disable_rpl_parse|maxdb_dump_debug_info|maxdb_embedded_connect|maxdb_enable_reads_from_master|maxdb_enable_rpl_parse|maxdb_errno|maxdb_error|maxdb_escape_string|maxdb_execute|maxdb_fetch|maxdb_fetch_array|maxdb_fetch_assoc|maxdb_fetch_field|maxdb_fetch_field_direct|maxdb_fetch_fields|maxdb_fetch_lengths|maxdb_fetch_object|maxdb_fetch_row|maxdb_field_count|maxdb_field_seek|maxdb_field_tell|maxdb_free_result|maxdb_get_client_info|maxdb_get_client_version|maxdb_get_host_info|maxdb_get_metadata|maxdb_get_proto_info|maxdb_get_server_info|maxdb_get_server_version|maxdb_info|maxdb_init|maxdb_insert_id|maxdb_kill|maxdb_master_query|maxdb_more_results|maxdb_multi_query|maxdb_next_result|maxdb_num_fields|maxdb_num_rows|maxdb_options|maxdb_param_count|maxdb_ping|maxdb_prepare|maxdb_query|maxdb_real_connect|maxdb_real_escape_string|maxdb_real_query|maxdb_report|maxdb_rollback|maxdb_rpl_parse_enabled|maxdb_rpl_probe|maxdb_rpl_query_type|maxdb_select_db|maxdb_send_long_data|maxdb_send_query|maxdb_server_end|maxdb_server_init|maxdb_set_opt|maxdb_sqlstate|maxdb_ssl_set|maxdb_stat|maxdb_stmt_affected_rows|maxdb_stmt_bind_param|maxdb_stmt_bind_result|maxdb_stmt_close|maxdb_stmt_close_long_data|maxdb_stmt_data_seek|maxdb_stmt_errno|maxdb_stmt_error|maxdb_stmt_execute|maxdb_stmt_fetch|maxdb_stmt_free_result|maxdb_stmt_init|maxdb_stmt_num_rows|maxdb_stmt_param_count|maxdb_stmt_prepare|maxdb_stmt_reset|maxdb_stmt_result_metadata|maxdb_stmt_send_long_data|maxdb_stmt_sqlstate|maxdb_stmt_store_result|maxdb_store_result|maxdb_thread_id|maxdb_thread_safe|maxdb_use_result|maxdb_warning_count|mb_check_encoding|mb_convert_case|mb_convert_encoding|mb_convert_kana|mb_convert_variables|mb_decode_mimeheader|mb_decode_numericentity|mb_detect_encoding|mb_detect_order|mb_encode_mimeheader|mb_encode_numericentity|mb_encoding_aliases|mb_ereg|mb_ereg_match|mb_ereg_replace|mb_ereg_search|mb_ereg_search_getpos|mb_ereg_search_getregs|mb_ereg_search_init|mb_ereg_search_pos|mb_ereg_search_regs|mb_ereg_search_setpos|mb_eregi|mb_eregi_replace|mb_get_info|mb_http_input|mb_http_output|mb_internal_encoding|mb_language|mb_list_encodings|mb_output_handler|mb_parse_str|mb_preferred_mime_name|mb_regex_encoding|mb_regex_set_options|mb_send_mail|mb_split|mb_strcut|mb_strimwidth|mb_stripos|mb_stristr|mb_strlen|mb_strpos|mb_strrchr|mb_strrichr|mb_strripos|mb_strrpos|mb_strstr|mb_strtolower|mb_strtoupper|mb_strwidth|mb_substitute_character|mb_substr|mb_substr_count|mcrypt_cbc|mcrypt_cfb|mcrypt_create_iv|mcrypt_decrypt|mcrypt_ecb|mcrypt_enc_get_algorithms_name|mcrypt_enc_get_block_size|mcrypt_enc_get_iv_size|mcrypt_enc_get_key_size|mcrypt_enc_get_modes_name|mcrypt_enc_get_supported_key_sizes|mcrypt_enc_is_block_algorithm|mcrypt_enc_is_block_algorithm_mode|mcrypt_enc_is_block_mode|mcrypt_enc_self_test|mcrypt_encrypt|mcrypt_generic|mcrypt_generic_deinit|mcrypt_generic_end|mcrypt_generic_init|mcrypt_get_block_size|mcrypt_get_cipher_name|mcrypt_get_iv_size|mcrypt_get_key_size|mcrypt_list_algorithms|mcrypt_list_modes|mcrypt_module_close|mcrypt_module_get_algo_block_size|mcrypt_module_get_algo_key_size|mcrypt_module_get_supported_key_sizes|mcrypt_module_is_block_algorithm|mcrypt_module_is_block_algorithm_mode|mcrypt_module_is_block_mode|mcrypt_module_open|mcrypt_module_self_test|mcrypt_ofb|md5|md5_file|mdecrypt_generic|memcache|memcache_debug|memcached|memory_get_peak_usage|memory_get_usage|messageformatter|metaphone|method_exists|mhash|mhash_count|mhash_get_block_size|mhash_get_hash_name|mhash_keygen_s2k|microtime|mime_content_type|min|ming_keypress|ming_setcubicthreshold|ming_setscale|ming_setswfcompression|ming_useconstants|ming_useswfversion|mkdir|mktime|money_format|mongo|mongobindata|mongocode|mongocollection|mongoconnectionexception|mongocursor|mongocursorexception|mongocursortimeoutexception|mongodate|mongodb|mongodbref|mongoexception|mongogridfs|mongogridfscursor|mongogridfsexception|mongogridfsfile|mongoid|mongoint32|mongoint64|mongomaxkey|mongominkey|mongoregex|mongotimestamp|move_uploaded_file|mpegfile|mqseries_back|mqseries_begin|mqseries_close|mqseries_cmit|mqseries_conn|mqseries_connx|mqseries_disc|mqseries_get|mqseries_inq|mqseries_open|mqseries_put|mqseries_put1|mqseries_set|mqseries_strerror|msession_connect|msession_count|msession_create|msession_destroy|msession_disconnect|msession_find|msession_get|msession_get_array|msession_get_data|msession_inc|msession_list|msession_listvar|msession_lock|msession_plugin|msession_randstr|msession_set|msession_set_array|msession_set_data|msession_timeout|msession_uniq|msession_unlock|msg_get_queue|msg_queue_exists|msg_receive|msg_remove_queue|msg_send|msg_set_queue|msg_stat_queue|msql|msql_affected_rows|msql_close|msql_connect|msql_create_db|msql_createdb|msql_data_seek|msql_db_query|msql_dbname|msql_drop_db|msql_error|msql_fetch_array|msql_fetch_field|msql_fetch_object|msql_fetch_row|msql_field_flags|msql_field_len|msql_field_name|msql_field_seek|msql_field_table|msql_field_type|msql_fieldflags|msql_fieldlen|msql_fieldname|msql_fieldtable|msql_fieldtype|msql_free_result|msql_list_dbs|msql_list_fields|msql_list_tables|msql_num_fields|msql_num_rows|msql_numfields|msql_numrows|msql_pconnect|msql_query|msql_regcase|msql_result|msql_select_db|msql_tablename|mssql_bind|mssql_close|mssql_connect|mssql_data_seek|mssql_execute|mssql_fetch_array|mssql_fetch_assoc|mssql_fetch_batch|mssql_fetch_field|mssql_fetch_object|mssql_fetch_row|mssql_field_length|mssql_field_name|mssql_field_seek|mssql_field_type|mssql_free_result|mssql_free_statement|mssql_get_last_message|mssql_guid_string|mssql_init|mssql_min_error_severity|mssql_min_message_severity|mssql_next_result|mssql_num_fields|mssql_num_rows|mssql_pconnect|mssql_query|mssql_result|mssql_rows_affected|mssql_select_db|mt_getrandmax|mt_rand|mt_srand|multipleiterator|mysql_affected_rows|mysql_client_encoding|mysql_close|mysql_connect|mysql_create_db|mysql_data_seek|mysql_db_name|mysql_db_query|mysql_drop_db|mysql_errno|mysql_error|mysql_escape_string|mysql_fetch_array|mysql_fetch_assoc|mysql_fetch_field|mysql_fetch_lengths|mysql_fetch_object|mysql_fetch_row|mysql_field_flags|mysql_field_len|mysql_field_name|mysql_field_seek|mysql_field_table|mysql_field_type|mysql_free_result|mysql_get_client_info|mysql_get_host_info|mysql_get_proto_info|mysql_get_server_info|mysql_info|mysql_insert_id|mysql_list_dbs|mysql_list_fields|mysql_list_processes|mysql_list_tables|mysql_num_fields|mysql_num_rows|mysql_pconnect|mysql_ping|mysql_query|mysql_real_escape_string|mysql_result|mysql_select_db|mysql_set_charset|mysql_stat|mysql_tablename|mysql_thread_id|mysql_unbuffered_query|mysqli|mysqli_bind_param|mysqli_bind_result|mysqli_client_encoding|mysqli_connect|mysqli_disable_reads_from_master|mysqli_disable_rpl_parse|mysqli_driver|mysqli_enable_reads_from_master|mysqli_enable_rpl_parse|mysqli_escape_string|mysqli_execute|mysqli_fetch|mysqli_get_metadata|mysqli_master_query|mysqli_param_count|mysqli_report|mysqli_result|mysqli_rpl_parse_enabled|mysqli_rpl_probe|mysqli_rpl_query_type|mysqli_send_long_data|mysqli_send_query|mysqli_set_opt|mysqli_slave_query|mysqli_stmt|mysqli_warning|mysqlnd_ms_get_stats|mysqlnd_ms_query_is_select|mysqlnd_ms_set_user_pick_server|mysqlnd_qc_change_handler|mysqlnd_qc_clear_cache|mysqlnd_qc_get_cache_info|mysqlnd_qc_get_core_stats|mysqlnd_qc_get_handler|mysqlnd_qc_get_query_trace_log|mysqlnd_qc_set_user_handlers|natcasesort|natsort|ncurses_addch|ncurses_addchnstr|ncurses_addchstr|ncurses_addnstr|ncurses_addstr|ncurses_assume_default_colors|ncurses_attroff|ncurses_attron|ncurses_attrset|ncurses_baudrate|ncurses_beep|ncurses_bkgd|ncurses_bkgdset|ncurses_border|ncurses_bottom_panel|ncurses_can_change_color|ncurses_cbreak|ncurses_clear|ncurses_clrtobot|ncurses_clrtoeol|ncurses_color_content|ncurses_color_set|ncurses_curs_set|ncurses_def_prog_mode|ncurses_def_shell_mode|ncurses_define_key|ncurses_del_panel|ncurses_delay_output|ncurses_delch|ncurses_deleteln|ncurses_delwin|ncurses_doupdate|ncurses_echo|ncurses_echochar|ncurses_end|ncurses_erase|ncurses_erasechar|ncurses_filter|ncurses_flash|ncurses_flushinp|ncurses_getch|ncurses_getmaxyx|ncurses_getmouse|ncurses_getyx|ncurses_halfdelay|ncurses_has_colors|ncurses_has_ic|ncurses_has_il|ncurses_has_key|ncurses_hide_panel|ncurses_hline|ncurses_inch|ncurses_init|ncurses_init_color|ncurses_init_pair|ncurses_insch|ncurses_insdelln|ncurses_insertln|ncurses_insstr|ncurses_instr|ncurses_isendwin|ncurses_keyok|ncurses_keypad|ncurses_killchar|ncurses_longname|ncurses_meta|ncurses_mouse_trafo|ncurses_mouseinterval|ncurses_mousemask|ncurses_move|ncurses_move_panel|ncurses_mvaddch|ncurses_mvaddchnstr|ncurses_mvaddchstr|ncurses_mvaddnstr|ncurses_mvaddstr|ncurses_mvcur|ncurses_mvdelch|ncurses_mvgetch|ncurses_mvhline|ncurses_mvinch|ncurses_mvvline|ncurses_mvwaddstr|ncurses_napms|ncurses_new_panel|ncurses_newpad|ncurses_newwin|ncurses_nl|ncurses_nocbreak|ncurses_noecho|ncurses_nonl|ncurses_noqiflush|ncurses_noraw|ncurses_pair_content|ncurses_panel_above|ncurses_panel_below|ncurses_panel_window|ncurses_pnoutrefresh|ncurses_prefresh|ncurses_putp|ncurses_qiflush|ncurses_raw|ncurses_refresh|ncurses_replace_panel|ncurses_reset_prog_mode|ncurses_reset_shell_mode|ncurses_resetty|ncurses_savetty|ncurses_scr_dump|ncurses_scr_init|ncurses_scr_restore|ncurses_scr_set|ncurses_scrl|ncurses_show_panel|ncurses_slk_attr|ncurses_slk_attroff|ncurses_slk_attron|ncurses_slk_attrset|ncurses_slk_clear|ncurses_slk_color|ncurses_slk_init|ncurses_slk_noutrefresh|ncurses_slk_refresh|ncurses_slk_restore|ncurses_slk_set|ncurses_slk_touch|ncurses_standend|ncurses_standout|ncurses_start_color|ncurses_termattrs|ncurses_termname|ncurses_timeout|ncurses_top_panel|ncurses_typeahead|ncurses_ungetch|ncurses_ungetmouse|ncurses_update_panels|ncurses_use_default_colors|ncurses_use_env|ncurses_use_extended_names|ncurses_vidattr|ncurses_vline|ncurses_waddch|ncurses_waddstr|ncurses_wattroff|ncurses_wattron|ncurses_wattrset|ncurses_wborder|ncurses_wclear|ncurses_wcolor_set|ncurses_werase|ncurses_wgetch|ncurses_whline|ncurses_wmouse_trafo|ncurses_wmove|ncurses_wnoutrefresh|ncurses_wrefresh|ncurses_wstandend|ncurses_wstandout|ncurses_wvline|newinstance|newinstanceargs|newt_bell|newt_button|newt_button_bar|newt_centered_window|newt_checkbox|newt_checkbox_get_value|newt_checkbox_set_flags|newt_checkbox_set_value|newt_checkbox_tree|newt_checkbox_tree_add_item|newt_checkbox_tree_find_item|newt_checkbox_tree_get_current|newt_checkbox_tree_get_entry_value|newt_checkbox_tree_get_multi_selection|newt_checkbox_tree_get_selection|newt_checkbox_tree_multi|newt_checkbox_tree_set_current|newt_checkbox_tree_set_entry|newt_checkbox_tree_set_entry_value|newt_checkbox_tree_set_width|newt_clear_key_buffer|newt_cls|newt_compact_button|newt_component_add_callback|newt_component_takes_focus|newt_create_grid|newt_cursor_off|newt_cursor_on|newt_delay|newt_draw_form|newt_draw_root_text|newt_entry|newt_entry_get_value|newt_entry_set|newt_entry_set_filter|newt_entry_set_flags|newt_finished|newt_form|newt_form_add_component|newt_form_add_components|newt_form_add_hot_key|newt_form_destroy|newt_form_get_current|newt_form_run|newt_form_set_background|newt_form_set_height|newt_form_set_size|newt_form_set_timer|newt_form_set_width|newt_form_watch_fd|newt_get_screen_size|newt_grid_add_components_to_form|newt_grid_basic_window|newt_grid_free|newt_grid_get_size|newt_grid_h_close_stacked|newt_grid_h_stacked|newt_grid_place|newt_grid_set_field|newt_grid_simple_window|newt_grid_v_close_stacked|newt_grid_v_stacked|newt_grid_wrapped_window|newt_grid_wrapped_window_at|newt_init|newt_label|newt_label_set_text|newt_listbox|newt_listbox_append_entry|newt_listbox_clear|newt_listbox_clear_selection|newt_listbox_delete_entry|newt_listbox_get_current|newt_listbox_get_selection|newt_listbox_insert_entry|newt_listbox_item_count|newt_listbox_select_item|newt_listbox_set_current|newt_listbox_set_current_by_key|newt_listbox_set_data|newt_listbox_set_entry|newt_listbox_set_width|newt_listitem|newt_listitem_get_data|newt_listitem_set|newt_open_window|newt_pop_help_line|newt_pop_window|newt_push_help_line|newt_radio_get_current|newt_radiobutton|newt_redraw_help_line|newt_reflow_text|newt_refresh|newt_resize_screen|newt_resume|newt_run_form|newt_scale|newt_scale_set|newt_scrollbar_set|newt_set_help_callback|newt_set_suspend_callback|newt_suspend|newt_textbox|newt_textbox_get_num_lines|newt_textbox_reflowed|newt_textbox_set_height|newt_textbox_set_text|newt_vertical_scrollbar|newt_wait_for_key|newt_win_choice|newt_win_entries|newt_win_menu|newt_win_message|newt_win_messagev|newt_win_ternary|next|ngettext|nl2br|nl_langinfo|norewinditerator|normalizer|notes_body|notes_copy_db|notes_create_db|notes_create_note|notes_drop_db|notes_find_note|notes_header_info|notes_list_msgs|notes_mark_read|notes_mark_unread|notes_nav_create|notes_search|notes_unread|notes_version|nsapi_request_headers|nsapi_response_headers|nsapi_virtual|nthmac|number_format|numberformatter|oauth|oauth_get_sbs|oauth_urlencode|oauthexception|oauthprovider|ob_clean|ob_deflatehandler|ob_end_clean|ob_end_flush|ob_etaghandler|ob_flush|ob_get_clean|ob_get_contents|ob_get_flush|ob_get_length|ob_get_level|ob_get_status|ob_gzhandler|ob_iconv_handler|ob_implicit_flush|ob_inflatehandler|ob_list_handlers|ob_start|ob_tidyhandler|oci_bind_array_by_name|oci_bind_by_name|oci_cancel|oci_client_version|oci_close|oci_collection_append|oci_collection_assign|oci_collection_element_assign|oci_collection_element_get|oci_collection_free|oci_collection_max|oci_collection_size|oci_collection_trim|oci_commit|oci_connect|oci_define_by_name|oci_error|oci_execute|oci_fetch|oci_fetch_all|oci_fetch_array|oci_fetch_assoc|oci_fetch_object|oci_fetch_row|oci_field_is_null|oci_field_name|oci_field_precision|oci_field_scale|oci_field_size|oci_field_type|oci_field_type_raw|oci_free_statement|oci_internal_debug|oci_lob_append|oci_lob_close|oci_lob_copy|oci_lob_eof|oci_lob_erase|oci_lob_export|oci_lob_flush|oci_lob_free|oci_lob_getbuffering|oci_lob_import|oci_lob_is_equal|oci_lob_load|oci_lob_read|oci_lob_rewind|oci_lob_save|oci_lob_savefile|oci_lob_seek|oci_lob_setbuffering|oci_lob_size|oci_lob_tell|oci_lob_truncate|oci_lob_write|oci_lob_writetemporary|oci_lob_writetofile|oci_new_collection|oci_new_connect|oci_new_cursor|oci_new_descriptor|oci_num_fields|oci_num_rows|oci_parse|oci_password_change|oci_pconnect|oci_result|oci_rollback|oci_server_version|oci_set_action|oci_set_client_identifier|oci_set_client_info|oci_set_edition|oci_set_module_name|oci_set_prefetch|oci_statement_type|ocibindbyname|ocicancel|ocicloselob|ocicollappend|ocicollassign|ocicollassignelem|ocicollgetelem|ocicollmax|ocicollsize|ocicolltrim|ocicolumnisnull|ocicolumnname|ocicolumnprecision|ocicolumnscale|ocicolumnsize|ocicolumntype|ocicolumntyperaw|ocicommit|ocidefinebyname|ocierror|ociexecute|ocifetch|ocifetchinto|ocifetchstatement|ocifreecollection|ocifreecursor|ocifreedesc|ocifreestatement|ociinternaldebug|ociloadlob|ocilogoff|ocilogon|ocinewcollection|ocinewcursor|ocinewdescriptor|ocinlogon|ocinumcols|ociparse|ociplogon|ociresult|ocirollback|ocirowcount|ocisavelob|ocisavelobfile|ociserverversion|ocisetprefetch|ocistatementtype|ociwritelobtofile|ociwritetemporarylob|octdec|odbc_autocommit|odbc_binmode|odbc_close|odbc_close_all|odbc_columnprivileges|odbc_columns|odbc_commit|odbc_connect|odbc_cursor|odbc_data_source|odbc_do|odbc_error|odbc_errormsg|odbc_exec|odbc_execute|odbc_fetch_array|odbc_fetch_into|odbc_fetch_object|odbc_fetch_row|odbc_field_len|odbc_field_name|odbc_field_num|odbc_field_precision|odbc_field_scale|odbc_field_type|odbc_foreignkeys|odbc_free_result|odbc_gettypeinfo|odbc_longreadlen|odbc_next_result|odbc_num_fields|odbc_num_rows|odbc_pconnect|odbc_prepare|odbc_primarykeys|odbc_procedurecolumns|odbc_procedures|odbc_result|odbc_result_all|odbc_rollback|odbc_setoption|odbc_specialcolumns|odbc_statistics|odbc_tableprivileges|odbc_tables|openal_buffer_create|openal_buffer_data|openal_buffer_destroy|openal_buffer_get|openal_buffer_loadwav|openal_context_create|openal_context_current|openal_context_destroy|openal_context_process|openal_context_suspend|openal_device_close|openal_device_open|openal_listener_get|openal_listener_set|openal_source_create|openal_source_destroy|openal_source_get|openal_source_pause|openal_source_play|openal_source_rewind|openal_source_set|openal_source_stop|openal_stream|opendir|openlog|openssl_cipher_iv_length|openssl_csr_export|openssl_csr_export_to_file|openssl_csr_get_public_key|openssl_csr_get_subject|openssl_csr_new|openssl_csr_sign|openssl_decrypt|openssl_dh_compute_key|openssl_digest|openssl_encrypt|openssl_error_string|openssl_free_key|openssl_get_cipher_methods|openssl_get_md_methods|openssl_get_privatekey|openssl_get_publickey|openssl_open|openssl_pkcs12_export|openssl_pkcs12_export_to_file|openssl_pkcs12_read|openssl_pkcs7_decrypt|openssl_pkcs7_encrypt|openssl_pkcs7_sign|openssl_pkcs7_verify|openssl_pkey_export|openssl_pkey_export_to_file|openssl_pkey_free|openssl_pkey_get_details|openssl_pkey_get_private|openssl_pkey_get_public|openssl_pkey_new|openssl_private_decrypt|openssl_private_encrypt|openssl_public_decrypt|openssl_public_encrypt|openssl_random_pseudo_bytes|openssl_seal|openssl_sign|openssl_verify|openssl_x509_check_private_key|openssl_x509_checkpurpose|openssl_x509_export|openssl_x509_export_to_file|openssl_x509_free|openssl_x509_parse|openssl_x509_read|ord|outeriterator|outofboundsexception|outofrangeexception|output_add_rewrite_var|output_reset_rewrite_vars|overflowexception|overload|override_function|ovrimos_close|ovrimos_commit|ovrimos_connect|ovrimos_cursor|ovrimos_exec|ovrimos_execute|ovrimos_fetch_into|ovrimos_fetch_row|ovrimos_field_len|ovrimos_field_name|ovrimos_field_num|ovrimos_field_type|ovrimos_free_result|ovrimos_longreadlen|ovrimos_num_fields|ovrimos_num_rows|ovrimos_prepare|ovrimos_result|ovrimos_result_all|ovrimos_rollback|pack|parentiterator|parse_ini_file|parse_ini_string|parse_str|parse_url|parsekit_compile_file|parsekit_compile_string|parsekit_func_arginfo|passthru|pathinfo|pclose|pcntl_alarm|pcntl_exec|pcntl_fork|pcntl_getpriority|pcntl_setpriority|pcntl_signal|pcntl_signal_dispatch|pcntl_sigprocmask|pcntl_sigtimedwait|pcntl_sigwaitinfo|pcntl_wait|pcntl_waitpid|pcntl_wexitstatus|pcntl_wifexited|pcntl_wifsignaled|pcntl_wifstopped|pcntl_wstopsig|pcntl_wtermsig|pdf_activate_item|pdf_add_annotation|pdf_add_bookmark|pdf_add_launchlink|pdf_add_locallink|pdf_add_nameddest|pdf_add_note|pdf_add_outline|pdf_add_pdflink|pdf_add_table_cell|pdf_add_textflow|pdf_add_thumbnail|pdf_add_weblink|pdf_arc|pdf_arcn|pdf_attach_file|pdf_begin_document|pdf_begin_font|pdf_begin_glyph|pdf_begin_item|pdf_begin_layer|pdf_begin_page|pdf_begin_page_ext|pdf_begin_pattern|pdf_begin_template|pdf_begin_template_ext|pdf_circle|pdf_clip|pdf_close|pdf_close_image|pdf_close_pdi|pdf_close_pdi_page|pdf_closepath|pdf_closepath_fill_stroke|pdf_closepath_stroke|pdf_concat|pdf_continue_text|pdf_create_3dview|pdf_create_action|pdf_create_annotation|pdf_create_bookmark|pdf_create_field|pdf_create_fieldgroup|pdf_create_gstate|pdf_create_pvf|pdf_create_textflow|pdf_curveto|pdf_define_layer|pdf_delete|pdf_delete_pvf|pdf_delete_table|pdf_delete_textflow|pdf_encoding_set_char|pdf_end_document|pdf_end_font|pdf_end_glyph|pdf_end_item|pdf_end_layer|pdf_end_page|pdf_end_page_ext|pdf_end_pattern|pdf_end_template|pdf_endpath|pdf_fill|pdf_fill_imageblock|pdf_fill_pdfblock|pdf_fill_stroke|pdf_fill_textblock|pdf_findfont|pdf_fit_image|pdf_fit_pdi_page|pdf_fit_table|pdf_fit_textflow|pdf_fit_textline|pdf_get_apiname|pdf_get_buffer|pdf_get_errmsg|pdf_get_errnum|pdf_get_font|pdf_get_fontname|pdf_get_fontsize|pdf_get_image_height|pdf_get_image_width|pdf_get_majorversion|pdf_get_minorversion|pdf_get_parameter|pdf_get_pdi_parameter|pdf_get_pdi_value|pdf_get_value|pdf_info_font|pdf_info_matchbox|pdf_info_table|pdf_info_textflow|pdf_info_textline|pdf_initgraphics|pdf_lineto|pdf_load_3ddata|pdf_load_font|pdf_load_iccprofile|pdf_load_image|pdf_makespotcolor|pdf_moveto|pdf_new|pdf_open_ccitt|pdf_open_file|pdf_open_gif|pdf_open_image|pdf_open_image_file|pdf_open_jpeg|pdf_open_memory_image|pdf_open_pdi|pdf_open_pdi_document|pdf_open_pdi_page|pdf_open_tiff|pdf_pcos_get_number|pdf_pcos_get_stream|pdf_pcos_get_string|pdf_place_image|pdf_place_pdi_page|pdf_process_pdi|pdf_rect|pdf_restore|pdf_resume_page|pdf_rotate|pdf_save|pdf_scale|pdf_set_border_color|pdf_set_border_dash|pdf_set_border_style|pdf_set_char_spacing|pdf_set_duration|pdf_set_gstate|pdf_set_horiz_scaling|pdf_set_info|pdf_set_info_author|pdf_set_info_creator|pdf_set_info_keywords|pdf_set_info_subject|pdf_set_info_title|pdf_set_layer_dependency|pdf_set_leading|pdf_set_parameter|pdf_set_text_matrix|pdf_set_text_pos|pdf_set_text_rendering|pdf_set_text_rise|pdf_set_value|pdf_set_word_spacing|pdf_setcolor|pdf_setdash|pdf_setdashpattern|pdf_setflat|pdf_setfont|pdf_setgray|pdf_setgray_fill|pdf_setgray_stroke|pdf_setlinecap|pdf_setlinejoin|pdf_setlinewidth|pdf_setmatrix|pdf_setmiterlimit|pdf_setpolydash|pdf_setrgbcolor|pdf_setrgbcolor_fill|pdf_setrgbcolor_stroke|pdf_shading|pdf_shading_pattern|pdf_shfill|pdf_show|pdf_show_boxed|pdf_show_xy|pdf_skew|pdf_stringwidth|pdf_stroke|pdf_suspend_page|pdf_translate|pdf_utf16_to_utf8|pdf_utf32_to_utf16|pdf_utf8_to_utf16|pdo|pdo_cubrid_schema|pdo_pgsqllobcreate|pdo_pgsqllobopen|pdo_pgsqllobunlink|pdo_sqlitecreateaggregate|pdo_sqlitecreatefunction|pdoexception|pdostatement|pfsockopen|pg_affected_rows|pg_cancel_query|pg_client_encoding|pg_close|pg_connect|pg_connection_busy|pg_connection_reset|pg_connection_status|pg_convert|pg_copy_from|pg_copy_to|pg_dbname|pg_delete|pg_end_copy|pg_escape_bytea|pg_escape_string|pg_execute|pg_fetch_all|pg_fetch_all_columns|pg_fetch_array|pg_fetch_assoc|pg_fetch_object|pg_fetch_result|pg_fetch_row|pg_field_is_null|pg_field_name|pg_field_num|pg_field_prtlen|pg_field_size|pg_field_table|pg_field_type|pg_field_type_oid|pg_free_result|pg_get_notify|pg_get_pid|pg_get_result|pg_host|pg_insert|pg_last_error|pg_last_notice|pg_last_oid|pg_lo_close|pg_lo_create|pg_lo_export|pg_lo_import|pg_lo_open|pg_lo_read|pg_lo_read_all|pg_lo_seek|pg_lo_tell|pg_lo_unlink|pg_lo_write|pg_meta_data|pg_num_fields|pg_num_rows|pg_options|pg_parameter_status|pg_pconnect|pg_ping|pg_port|pg_prepare|pg_put_line|pg_query|pg_query_params|pg_result_error|pg_result_error_field|pg_result_seek|pg_result_status|pg_select|pg_send_execute|pg_send_prepare|pg_send_query|pg_send_query_params|pg_set_client_encoding|pg_set_error_verbosity|pg_trace|pg_transaction_status|pg_tty|pg_unescape_bytea|pg_untrace|pg_update|pg_version|php_check_syntax|php_ini_loaded_file|php_ini_scanned_files|php_logo_guid|php_sapi_name|php_strip_whitespace|php_uname|phpcredits|phpinfo|phpversion|pi|png2wbmp|popen|pos|posix_access|posix_ctermid|posix_errno|posix_get_last_error|posix_getcwd|posix_getegid|posix_geteuid|posix_getgid|posix_getgrgid|posix_getgrnam|posix_getgroups|posix_getlogin|posix_getpgid|posix_getpgrp|posix_getpid|posix_getppid|posix_getpwnam|posix_getpwuid|posix_getrlimit|posix_getsid|posix_getuid|posix_initgroups|posix_isatty|posix_kill|posix_mkfifo|posix_mknod|posix_setegid|posix_seteuid|posix_setgid|posix_setpgid|posix_setsid|posix_setuid|posix_strerror|posix_times|posix_ttyname|posix_uname|pow|preg_filter|preg_grep|preg_last_error|preg_match|preg_match_all|preg_quote|preg_replace|preg_replace_callback|preg_split|prev|print|print_r|printer_abort|printer_close|printer_create_brush|printer_create_dc|printer_create_font|printer_create_pen|printer_delete_brush|printer_delete_dc|printer_delete_font|printer_delete_pen|printer_draw_bmp|printer_draw_chord|printer_draw_elipse|printer_draw_line|printer_draw_pie|printer_draw_rectangle|printer_draw_roundrect|printer_draw_text|printer_end_doc|printer_end_page|printer_get_option|printer_list|printer_logical_fontheight|printer_open|printer_select_brush|printer_select_font|printer_select_pen|printer_set_option|printer_start_doc|printer_start_page|printer_write|printf|proc_close|proc_get_status|proc_nice|proc_open|proc_terminate|property_exists|ps_add_bookmark|ps_add_launchlink|ps_add_locallink|ps_add_note|ps_add_pdflink|ps_add_weblink|ps_arc|ps_arcn|ps_begin_page|ps_begin_pattern|ps_begin_template|ps_circle|ps_clip|ps_close|ps_close_image|ps_closepath|ps_closepath_stroke|ps_continue_text|ps_curveto|ps_delete|ps_end_page|ps_end_pattern|ps_end_template|ps_fill|ps_fill_stroke|ps_findfont|ps_get_buffer|ps_get_parameter|ps_get_value|ps_hyphenate|ps_include_file|ps_lineto|ps_makespotcolor|ps_moveto|ps_new|ps_open_file|ps_open_image|ps_open_image_file|ps_open_memory_image|ps_place_image|ps_rect|ps_restore|ps_rotate|ps_save|ps_scale|ps_set_border_color|ps_set_border_dash|ps_set_border_style|ps_set_info|ps_set_parameter|ps_set_text_pos|ps_set_value|ps_setcolor|ps_setdash|ps_setflat|ps_setfont|ps_setgray|ps_setlinecap|ps_setlinejoin|ps_setlinewidth|ps_setmiterlimit|ps_setoverprintmode|ps_setpolydash|ps_shading|ps_shading_pattern|ps_shfill|ps_show|ps_show2|ps_show_boxed|ps_show_xy|ps_show_xy2|ps_string_geometry|ps_stringwidth|ps_stroke|ps_symbol|ps_symbol_name|ps_symbol_width|ps_translate|pspell_add_to_personal|pspell_add_to_session|pspell_check|pspell_clear_session|pspell_config_create|pspell_config_data_dir|pspell_config_dict_dir|pspell_config_ignore|pspell_config_mode|pspell_config_personal|pspell_config_repl|pspell_config_runtogether|pspell_config_save_repl|pspell_new|pspell_new_config|pspell_new_personal|pspell_save_wordlist|pspell_store_replacement|pspell_suggest|putenv|px_close|px_create_fp|px_date2string|px_delete|px_delete_record|px_get_field|px_get_info|px_get_parameter|px_get_record|px_get_schema|px_get_value|px_insert_record|px_new|px_numfields|px_numrecords|px_open_fp|px_put_record|px_retrieve_record|px_set_blob_file|px_set_parameter|px_set_tablename|px_set_targetencoding|px_set_value|px_timestamp2string|px_update_record|qdom_error|qdom_tree|quoted_printable_decode|quoted_printable_encode|quotemeta|rad2deg|radius_acct_open|radius_add_server|radius_auth_open|radius_close|radius_config|radius_create_request|radius_cvt_addr|radius_cvt_int|radius_cvt_string|radius_demangle|radius_demangle_mppe_key|radius_get_attr|radius_get_vendor_attr|radius_put_addr|radius_put_attr|radius_put_int|radius_put_string|radius_put_vendor_addr|radius_put_vendor_attr|radius_put_vendor_int|radius_put_vendor_string|radius_request_authenticator|radius_send_request|radius_server_secret|radius_strerror|rand|range|rangeexception|rar_wrapper_cache_stats|rararchive|rarentry|rarexception|rawurldecode|rawurlencode|read_exif_data|readdir|readfile|readgzfile|readline|readline_add_history|readline_callback_handler_install|readline_callback_handler_remove|readline_callback_read_char|readline_clear_history|readline_completion_function|readline_info|readline_list_history|readline_on_new_line|readline_read_history|readline_redisplay|readline_write_history|readlink|realpath|realpath_cache_get|realpath_cache_size|recode|recode_file|recode_string|recursivearrayiterator|recursivecachingiterator|recursivecallbackfilteriterator|recursivedirectoryiterator|recursivefilteriterator|recursiveiterator|recursiveiteratoriterator|recursiveregexiterator|recursivetreeiterator|reflection|reflectionclass|reflectionexception|reflectionextension|reflectionfunction|reflectionfunctionabstract|reflectionmethod|reflectionobject|reflectionparameter|reflectionproperty|reflector|regexiterator|register_shutdown_function|register_tick_function|rename|rename_function|require|require_once|reset|resetValue|resourcebundle|restore_error_handler|restore_exception_handler|restore_include_path|return|rewind|rewinddir|rmdir|round|rpm_close|rpm_get_tag|rpm_is_valid|rpm_open|rpm_version|rrd_create|rrd_error|rrd_fetch|rrd_first|rrd_graph|rrd_info|rrd_last|rrd_lastupdate|rrd_restore|rrd_tune|rrd_update|rrd_xport|rrdcreator|rrdgraph|rrdupdater|rsort|rtrim|runkit_class_adopt|runkit_class_emancipate|runkit_constant_add|runkit_constant_redefine|runkit_constant_remove|runkit_function_add|runkit_function_copy|runkit_function_redefine|runkit_function_remove|runkit_function_rename|runkit_import|runkit_lint|runkit_lint_file|runkit_method_add|runkit_method_copy|runkit_method_redefine|runkit_method_remove|runkit_method_rename|runkit_return_value_used|runkit_sandbox_output_handler|runkit_superglobals|runtimeexception|samconnection_commit|samconnection_connect|samconnection_constructor|samconnection_disconnect|samconnection_errno|samconnection_error|samconnection_isconnected|samconnection_peek|samconnection_peekall|samconnection_receive|samconnection_remove|samconnection_rollback|samconnection_send|samconnection_setDebug|samconnection_subscribe|samconnection_unsubscribe|sammessage_body|sammessage_constructor|sammessage_header|sca_createdataobject|sca_getservice|sca_localproxy_createdataobject|sca_soapproxy_createdataobject|scandir|sdo_das_changesummary_beginlogging|sdo_das_changesummary_endlogging|sdo_das_changesummary_getchangeddataobjects|sdo_das_changesummary_getchangetype|sdo_das_changesummary_getoldcontainer|sdo_das_changesummary_getoldvalues|sdo_das_changesummary_islogging|sdo_das_datafactory_addpropertytotype|sdo_das_datafactory_addtype|sdo_das_datafactory_getdatafactory|sdo_das_dataobject_getchangesummary|sdo_das_relational_applychanges|sdo_das_relational_construct|sdo_das_relational_createrootdataobject|sdo_das_relational_executepreparedquery|sdo_das_relational_executequery|sdo_das_setting_getlistindex|sdo_das_setting_getpropertyindex|sdo_das_setting_getpropertyname|sdo_das_setting_getvalue|sdo_das_setting_isset|sdo_das_xml_addtypes|sdo_das_xml_create|sdo_das_xml_createdataobject|sdo_das_xml_createdocument|sdo_das_xml_document_getrootdataobject|sdo_das_xml_document_getrootelementname|sdo_das_xml_document_getrootelementuri|sdo_das_xml_document_setencoding|sdo_das_xml_document_setxmldeclaration|sdo_das_xml_document_setxmlversion|sdo_das_xml_loadfile|sdo_das_xml_loadstring|sdo_das_xml_savefile|sdo_das_xml_savestring|sdo_datafactory_create|sdo_dataobject_clear|sdo_dataobject_createdataobject|sdo_dataobject_getcontainer|sdo_dataobject_getsequence|sdo_dataobject_gettypename|sdo_dataobject_gettypenamespaceuri|sdo_exception_getcause|sdo_list_insert|sdo_model_property_getcontainingtype|sdo_model_property_getdefault|sdo_model_property_getname|sdo_model_property_gettype|sdo_model_property_iscontainment|sdo_model_property_ismany|sdo_model_reflectiondataobject_construct|sdo_model_reflectiondataobject_export|sdo_model_reflectiondataobject_getcontainmentproperty|sdo_model_reflectiondataobject_getinstanceproperties|sdo_model_reflectiondataobject_gettype|sdo_model_type_getbasetype|sdo_model_type_getname|sdo_model_type_getnamespaceuri|sdo_model_type_getproperties|sdo_model_type_getproperty|sdo_model_type_isabstracttype|sdo_model_type_isdatatype|sdo_model_type_isinstance|sdo_model_type_isopentype|sdo_model_type_issequencedtype|sdo_sequence_getproperty|sdo_sequence_insert|sdo_sequence_move|seekableiterator|sem_acquire|sem_get|sem_release|sem_remove|serializable|serialize|session_cache_expire|session_cache_limiter|session_commit|session_decode|session_destroy|session_encode|session_get_cookie_params|session_id|session_is_registered|session_module_name|session_name|session_pgsql_add_error|session_pgsql_get_error|session_pgsql_get_field|session_pgsql_reset|session_pgsql_set_field|session_pgsql_status|session_regenerate_id|session_register|session_save_path|session_set_cookie_params|session_set_save_handler|session_start|session_unregister|session_unset|session_write_close|setCounterClass|set_error_handler|set_exception_handler|set_file_buffer|set_include_path|set_magic_quotes_runtime|set_socket_blocking|set_time_limit|setcookie|setlocale|setproctitle|setrawcookie|setstaticpropertyvalue|setthreadtitle|settype|sha1|sha1_file|shell_exec|shm_attach|shm_detach|shm_get_var|shm_has_var|shm_put_var|shm_remove|shm_remove_var|shmop_close|shmop_delete|shmop_open|shmop_read|shmop_size|shmop_write|show_source|shuffle|signeurlpaiement|similar_text|simplexml_import_dom|simplexml_load_file|simplexml_load_string|simplexmlelement|simplexmliterator|sin|sinh|sizeof|sleep|snmp|snmp2_get|snmp2_getnext|snmp2_real_walk|snmp2_set|snmp2_walk|snmp3_get|snmp3_getnext|snmp3_real_walk|snmp3_set|snmp3_walk|snmp_get_quick_print|snmp_get_valueretrieval|snmp_read_mib|snmp_set_enum_print|snmp_set_oid_numeric_print|snmp_set_oid_output_format|snmp_set_quick_print|snmp_set_valueretrieval|snmpget|snmpgetnext|snmprealwalk|snmpset|snmpwalk|snmpwalkoid|soapclient|soapfault|soapheader|soapparam|soapserver|soapvar|socket_accept|socket_bind|socket_clear_error|socket_close|socket_connect|socket_create|socket_create_listen|socket_create_pair|socket_get_option|socket_get_status|socket_getpeername|socket_getsockname|socket_last_error|socket_listen|socket_read|socket_recv|socket_recvfrom|socket_select|socket_send|socket_sendto|socket_set_block|socket_set_blocking|socket_set_nonblock|socket_set_option|socket_set_timeout|socket_shutdown|socket_strerror|socket_write|solr_get_version|solrclient|solrclientexception|solrdocument|solrdocumentfield|solrexception|solrgenericresponse|solrillegalargumentexception|solrillegaloperationexception|solrinputdocument|solrmodifiableparams|solrobject|solrparams|solrpingresponse|solrquery|solrqueryresponse|solrresponse|solrupdateresponse|solrutils|sort|soundex|sphinxclient|spl_autoload|spl_autoload_call|spl_autoload_extensions|spl_autoload_functions|spl_autoload_register|spl_autoload_unregister|spl_classes|spl_object_hash|splbool|spldoublylinkedlist|splenum|splfileinfo|splfileobject|splfixedarray|splfloat|splheap|splint|split|spliti|splmaxheap|splminheap|splobjectstorage|splobserver|splpriorityqueue|splqueue|splstack|splstring|splsubject|spltempfileobject|spoofchecker|sprintf|sql_regcase|sqlite3|sqlite3result|sqlite3stmt|sqlite_array_query|sqlite_busy_timeout|sqlite_changes|sqlite_close|sqlite_column|sqlite_create_aggregate|sqlite_create_function|sqlite_current|sqlite_error_string|sqlite_escape_string|sqlite_exec|sqlite_factory|sqlite_fetch_all|sqlite_fetch_array|sqlite_fetch_column_types|sqlite_fetch_object|sqlite_fetch_single|sqlite_fetch_string|sqlite_field_name|sqlite_has_more|sqlite_has_prev|sqlite_key|sqlite_last_error|sqlite_last_insert_rowid|sqlite_libencoding|sqlite_libversion|sqlite_next|sqlite_num_fields|sqlite_num_rows|sqlite_open|sqlite_popen|sqlite_prev|sqlite_query|sqlite_rewind|sqlite_seek|sqlite_single_query|sqlite_udf_decode_binary|sqlite_udf_encode_binary|sqlite_unbuffered_query|sqlite_valid|sqrt|srand|sscanf|ssdeep_fuzzy_compare|ssdeep_fuzzy_hash|ssdeep_fuzzy_hash_filename|ssh2_auth_hostbased_file|ssh2_auth_none|ssh2_auth_password|ssh2_auth_pubkey_file|ssh2_connect|ssh2_exec|ssh2_fetch_stream|ssh2_fingerprint|ssh2_methods_negotiated|ssh2_publickey_add|ssh2_publickey_init|ssh2_publickey_list|ssh2_publickey_remove|ssh2_scp_recv|ssh2_scp_send|ssh2_sftp|ssh2_sftp_lstat|ssh2_sftp_mkdir|ssh2_sftp_readlink|ssh2_sftp_realpath|ssh2_sftp_rename|ssh2_sftp_rmdir|ssh2_sftp_stat|ssh2_sftp_symlink|ssh2_sftp_unlink|ssh2_shell|ssh2_tunnel|stat|stats_absolute_deviation|stats_cdf_beta|stats_cdf_binomial|stats_cdf_cauchy|stats_cdf_chisquare|stats_cdf_exponential|stats_cdf_f|stats_cdf_gamma|stats_cdf_laplace|stats_cdf_logistic|stats_cdf_negative_binomial|stats_cdf_noncentral_chisquare|stats_cdf_noncentral_f|stats_cdf_poisson|stats_cdf_t|stats_cdf_uniform|stats_cdf_weibull|stats_covariance|stats_den_uniform|stats_dens_beta|stats_dens_cauchy|stats_dens_chisquare|stats_dens_exponential|stats_dens_f|stats_dens_gamma|stats_dens_laplace|stats_dens_logistic|stats_dens_negative_binomial|stats_dens_normal|stats_dens_pmf_binomial|stats_dens_pmf_hypergeometric|stats_dens_pmf_poisson|stats_dens_t|stats_dens_weibull|stats_harmonic_mean|stats_kurtosis|stats_rand_gen_beta|stats_rand_gen_chisquare|stats_rand_gen_exponential|stats_rand_gen_f|stats_rand_gen_funiform|stats_rand_gen_gamma|stats_rand_gen_ibinomial|stats_rand_gen_ibinomial_negative|stats_rand_gen_int|stats_rand_gen_ipoisson|stats_rand_gen_iuniform|stats_rand_gen_noncenral_chisquare|stats_rand_gen_noncentral_f|stats_rand_gen_noncentral_t|stats_rand_gen_normal|stats_rand_gen_t|stats_rand_get_seeds|stats_rand_phrase_to_seeds|stats_rand_ranf|stats_rand_setall|stats_skew|stats_standard_deviation|stats_stat_binomial_coef|stats_stat_correlation|stats_stat_gennch|stats_stat_independent_t|stats_stat_innerproduct|stats_stat_noncentral_t|stats_stat_paired_t|stats_stat_percentile|stats_stat_powersum|stats_variance|stomp|stomp_connect_error|stomp_version|stompexception|stompframe|str_getcsv|str_ireplace|str_pad|str_repeat|str_replace|str_rot13|str_shuffle|str_split|str_word_count|strcasecmp|strchr|strcmp|strcoll|strcspn|stream_bucket_append|stream_bucket_make_writeable|stream_bucket_new|stream_bucket_prepend|stream_context_create|stream_context_get_default|stream_context_get_options|stream_context_get_params|stream_context_set_default|stream_context_set_option|stream_context_set_params|stream_copy_to_stream|stream_encoding|stream_filter_append|stream_filter_prepend|stream_filter_register|stream_filter_remove|stream_get_contents|stream_get_filters|stream_get_line|stream_get_meta_data|stream_get_transports|stream_get_wrappers|stream_is_local|stream_notification_callback|stream_register_wrapper|stream_resolve_include_path|stream_select|stream_set_blocking|stream_set_read_buffer|stream_set_timeout|stream_set_write_buffer|stream_socket_accept|stream_socket_client|stream_socket_enable_crypto|stream_socket_get_name|stream_socket_pair|stream_socket_recvfrom|stream_socket_sendto|stream_socket_server|stream_socket_shutdown|stream_supports_lock|stream_wrapper_register|stream_wrapper_restore|stream_wrapper_unregister|streamwrapper|strftime|strip_tags|stripcslashes|stripos|stripslashes|stristr|strlen|strnatcasecmp|strnatcmp|strncasecmp|strncmp|strpbrk|strpos|strptime|strrchr|strrev|strripos|strrpos|strspn|strstr|strtok|strtolower|strtotime|strtoupper|strtr|strval|substr|substr_compare|substr_count|substr_replace|svm|svmmodel|svn_add|svn_auth_get_parameter|svn_auth_set_parameter|svn_blame|svn_cat|svn_checkout|svn_cleanup|svn_client_version|svn_commit|svn_delete|svn_diff|svn_export|svn_fs_abort_txn|svn_fs_apply_text|svn_fs_begin_txn2|svn_fs_change_node_prop|svn_fs_check_path|svn_fs_contents_changed|svn_fs_copy|svn_fs_delete|svn_fs_dir_entries|svn_fs_file_contents|svn_fs_file_length|svn_fs_is_dir|svn_fs_is_file|svn_fs_make_dir|svn_fs_make_file|svn_fs_node_created_rev|svn_fs_node_prop|svn_fs_props_changed|svn_fs_revision_prop|svn_fs_revision_root|svn_fs_txn_root|svn_fs_youngest_rev|svn_import|svn_log|svn_ls|svn_mkdir|svn_repos_create|svn_repos_fs|svn_repos_fs_begin_txn_for_commit|svn_repos_fs_commit_txn|svn_repos_hotcopy|svn_repos_open|svn_repos_recover|svn_revert|svn_status|svn_update|swf_actiongeturl|swf_actiongotoframe|swf_actiongotolabel|swf_actionnextframe|swf_actionplay|swf_actionprevframe|swf_actionsettarget|swf_actionstop|swf_actiontogglequality|swf_actionwaitforframe|swf_addbuttonrecord|swf_addcolor|swf_closefile|swf_definebitmap|swf_definefont|swf_defineline|swf_definepoly|swf_definerect|swf_definetext|swf_endbutton|swf_enddoaction|swf_endshape|swf_endsymbol|swf_fontsize|swf_fontslant|swf_fonttracking|swf_getbitmapinfo|swf_getfontinfo|swf_getframe|swf_labelframe|swf_lookat|swf_modifyobject|swf_mulcolor|swf_nextid|swf_oncondition|swf_openfile|swf_ortho|swf_ortho2|swf_perspective|swf_placeobject|swf_polarview|swf_popmatrix|swf_posround|swf_pushmatrix|swf_removeobject|swf_rotate|swf_scale|swf_setfont|swf_setframe|swf_shapearc|swf_shapecurveto|swf_shapecurveto3|swf_shapefillbitmapclip|swf_shapefillbitmaptile|swf_shapefilloff|swf_shapefillsolid|swf_shapelinesolid|swf_shapelineto|swf_shapemoveto|swf_showframe|swf_startbutton|swf_startdoaction|swf_startshape|swf_startsymbol|swf_textwidth|swf_translate|swf_viewport|swfaction|swfbitmap|swfbutton|swfdisplayitem|swffill|swffont|swffontchar|swfgradient|swfmorph|swfmovie|swfprebuiltclip|swfshape|swfsound|swfsoundinstance|swfsprite|swftext|swftextfield|swfvideostream|swish_construct|swish_getmetalist|swish_getpropertylist|swish_prepare|swish_query|swishresult_getmetalist|swishresult_stem|swishresults_getparsedwords|swishresults_getremovedstopwords|swishresults_nextresult|swishresults_seekresult|swishsearch_execute|swishsearch_resetlimit|swishsearch_setlimit|swishsearch_setphrasedelimiter|swishsearch_setsort|swishsearch_setstructure|sybase_affected_rows|sybase_close|sybase_connect|sybase_data_seek|sybase_deadlock_retry_count|sybase_fetch_array|sybase_fetch_assoc|sybase_fetch_field|sybase_fetch_object|sybase_fetch_row|sybase_field_seek|sybase_free_result|sybase_get_last_message|sybase_min_client_severity|sybase_min_error_severity|sybase_min_message_severity|sybase_min_server_severity|sybase_num_fields|sybase_num_rows|sybase_pconnect|sybase_query|sybase_result|sybase_select_db|sybase_set_message_handler|sybase_unbuffered_query|symlink|sys_get_temp_dir|sys_getloadavg|syslog|system|tag|tan|tanh|tcpwrap_check|tempnam|textdomain|tidy|tidy_access_count|tidy_config_count|tidy_diagnose|tidy_error_count|tidy_get_error_buffer|tidy_get_output|tidy_load_config|tidy_reset_config|tidy_save_config|tidy_set_encoding|tidy_setopt|tidy_warning_count|tidynode|time|time_nanosleep|time_sleep_until|timezone_abbreviations_list|timezone_identifiers_list|timezone_location_get|timezone_name_from_abbr|timezone_name_get|timezone_offset_get|timezone_open|timezone_transitions_get|timezone_version_get|tmpfile|token_get_all|token_name|tokyotyrant|tokyotyrantquery|tokyotyranttable|tostring|tostring|touch|transliterator|traversable|trigger_error|trim|uasort|ucfirst|ucwords|udm_add_search_limit|udm_alloc_agent|udm_alloc_agent_array|udm_api_version|udm_cat_list|udm_cat_path|udm_check_charset|udm_check_stored|udm_clear_search_limits|udm_close_stored|udm_crc32|udm_errno|udm_error|udm_find|udm_free_agent|udm_free_ispell_data|udm_free_res|udm_get_doc_count|udm_get_res_field|udm_get_res_param|udm_hash32|udm_load_ispell_data|udm_open_stored|udm_set_agent_param|uksort|umask|underflowexception|unexpectedvalueexception|uniqid|unixtojd|unlink|unpack|unregister_tick_function|unserialize|unset|urldecode|urlencode|use_soap_error_handler|user_error|usleep|usort|utf8_decode|utf8_encode|v8js|v8jsexception|var_dump|var_export|variant|variant_abs|variant_add|variant_and|variant_cast|variant_cat|variant_cmp|variant_date_from_timestamp|variant_date_to_timestamp|variant_div|variant_eqv|variant_fix|variant_get_type|variant_idiv|variant_imp|variant_int|variant_mod|variant_mul|variant_neg|variant_not|variant_or|variant_pow|variant_round|variant_set|variant_set_type|variant_sub|variant_xor|version_compare|vfprintf|virtual|vpopmail_add_alias_domain|vpopmail_add_alias_domain_ex|vpopmail_add_domain|vpopmail_add_domain_ex|vpopmail_add_user|vpopmail_alias_add|vpopmail_alias_del|vpopmail_alias_del_domain|vpopmail_alias_get|vpopmail_alias_get_all|vpopmail_auth_user|vpopmail_del_domain|vpopmail_del_domain_ex|vpopmail_del_user|vpopmail_error|vpopmail_passwd|vpopmail_set_user_quota|vprintf|vsprintf|w32api_deftype|w32api_init_dtype|w32api_invoke_function|w32api_register_function|w32api_set_call_method|wddx_add_vars|wddx_deserialize|wddx_packet_end|wddx_packet_start|wddx_serialize_value|wddx_serialize_vars|win32_continue_service|win32_create_service|win32_delete_service|win32_get_last_control_message|win32_pause_service|win32_ps_list_procs|win32_ps_stat_mem|win32_ps_stat_proc|win32_query_service_status|win32_set_service_status|win32_start_service|win32_start_service_ctrl_dispatcher|win32_stop_service|wincache_fcache_fileinfo|wincache_fcache_meminfo|wincache_lock|wincache_ocache_fileinfo|wincache_ocache_meminfo|wincache_refresh_if_changed|wincache_rplist_fileinfo|wincache_rplist_meminfo|wincache_scache_info|wincache_scache_meminfo|wincache_ucache_add|wincache_ucache_cas|wincache_ucache_clear|wincache_ucache_dec|wincache_ucache_delete|wincache_ucache_exists|wincache_ucache_get|wincache_ucache_inc|wincache_ucache_info|wincache_ucache_meminfo|wincache_ucache_set|wincache_unlock|wordwrap|xattr_get|xattr_list|xattr_remove|xattr_set|xattr_supported|xdiff_file_bdiff|xdiff_file_bdiff_size|xdiff_file_bpatch|xdiff_file_diff|xdiff_file_diff_binary|xdiff_file_merge3|xdiff_file_patch|xdiff_file_patch_binary|xdiff_file_rabdiff|xdiff_string_bdiff|xdiff_string_bdiff_size|xdiff_string_bpatch|xdiff_string_diff|xdiff_string_diff_binary|xdiff_string_merge3|xdiff_string_patch|xdiff_string_patch_binary|xdiff_string_rabdiff|xhprof_disable|xhprof_enable|xhprof_sample_disable|xhprof_sample_enable|xml_error_string|xml_get_current_byte_index|xml_get_current_column_number|xml_get_current_line_number|xml_get_error_code|xml_parse|xml_parse_into_struct|xml_parser_create|xml_parser_create_ns|xml_parser_free|xml_parser_get_option|xml_parser_set_option|xml_set_character_data_handler|xml_set_default_handler|xml_set_element_handler|xml_set_end_namespace_decl_handler|xml_set_external_entity_ref_handler|xml_set_notation_decl_handler|xml_set_object|xml_set_processing_instruction_handler|xml_set_start_namespace_decl_handler|xml_set_unparsed_entity_decl_handler|xmlreader|xmlrpc_decode|xmlrpc_decode_request|xmlrpc_encode|xmlrpc_encode_request|xmlrpc_get_type|xmlrpc_is_fault|xmlrpc_parse_method_descriptions|xmlrpc_server_add_introspection_data|xmlrpc_server_call_method|xmlrpc_server_create|xmlrpc_server_destroy|xmlrpc_server_register_introspection_callback|xmlrpc_server_register_method|xmlrpc_set_type|xmlwriter_end_attribute|xmlwriter_end_cdata|xmlwriter_end_comment|xmlwriter_end_document|xmlwriter_end_dtd|xmlwriter_end_dtd_attlist|xmlwriter_end_dtd_element|xmlwriter_end_dtd_entity|xmlwriter_end_element|xmlwriter_end_pi|xmlwriter_flush|xmlwriter_full_end_element|xmlwriter_open_memory|xmlwriter_open_uri|xmlwriter_output_memory|xmlwriter_set_indent|xmlwriter_set_indent_string|xmlwriter_start_attribute|xmlwriter_start_attribute_ns|xmlwriter_start_cdata|xmlwriter_start_comment|xmlwriter_start_document|xmlwriter_start_dtd|xmlwriter_start_dtd_attlist|xmlwriter_start_dtd_element|xmlwriter_start_dtd_entity|xmlwriter_start_element|xmlwriter_start_element_ns|xmlwriter_start_pi|xmlwriter_text|xmlwriter_write_attribute|xmlwriter_write_attribute_ns|xmlwriter_write_cdata|xmlwriter_write_comment|xmlwriter_write_dtd|xmlwriter_write_dtd_attlist|xmlwriter_write_dtd_element|xmlwriter_write_dtd_entity|xmlwriter_write_element|xmlwriter_write_element_ns|xmlwriter_write_pi|xmlwriter_write_raw|xpath_eval|xpath_eval_expression|xpath_new_context|xpath_register_ns|xpath_register_ns_auto|xptr_eval|xptr_new_context|xslt_backend_info|xslt_backend_name|xslt_backend_version|xslt_create|xslt_errno|xslt_error|xslt_free|xslt_getopt|xslt_process|xslt_set_base|xslt_set_encoding|xslt_set_error_handler|xslt_set_log|xslt_set_object|xslt_set_sax_handler|xslt_set_sax_handlers|xslt_set_scheme_handler|xslt_set_scheme_handlers|xslt_setopt|xsltprocessor|yaml_emit|yaml_emit_file|yaml_parse|yaml_parse_file|yaml_parse_url|yaz_addinfo|yaz_ccl_conf|yaz_ccl_parse|yaz_close|yaz_connect|yaz_database|yaz_element|yaz_errno|yaz_error|yaz_es|yaz_es_result|yaz_get_option|yaz_hits|yaz_itemorder|yaz_present|yaz_range|yaz_record|yaz_scan|yaz_scan_result|yaz_schema|yaz_search|yaz_set_option|yaz_sort|yaz_syntax|yaz_wait|yp_all|yp_cat|yp_err_string|yp_errno|yp_first|yp_get_default_domain|yp_master|yp_match|yp_next|yp_order|zend_logo_guid|zend_thread_id|zend_version|zip_close|zip_entry_close|zip_entry_compressedsize|zip_entry_compressionmethod|zip_entry_filesize|zip_entry_name|zip_entry_open|zip_entry_read|zip_open|zip_read|ziparchive|ziparchive_addemptydir|ziparchive_addfile|ziparchive_addfromstring|ziparchive_close|ziparchive_deleteindex|ziparchive_deletename|ziparchive_extractto|ziparchive_getarchivecomment|ziparchive_getcommentindex|ziparchive_getcommentname|ziparchive_getfromindex|ziparchive_getfromname|ziparchive_getnameindex|ziparchive_getstatusstring|ziparchive_getstream|ziparchive_locatename|ziparchive_open|ziparchive_renameindex|ziparchive_renamename|ziparchive_setCommentName|ziparchive_setarchivecomment|ziparchive_setcommentindex|ziparchive_statindex|ziparchive_statname|ziparchive_unchangeall|ziparchive_unchangearchive|ziparchive_unchangeindex|ziparchive_unchangename|zlib_get_coding_type".split("|")),c=e.arrayToMap("abstract|and|array|as|break|case|catch|class|clone|const|continue|declare|default|do|else|elseif|enddeclare|endfor|endforeach|endif|endswitch|endwhile|extends|final|for|foreach|function|global|goto|if|implements|interface|instanceof|namespace|new|or|private|protected|public|static|switch|throw|try|use|var|while|xor".split("|")),d=e.arrayToMap("die|echo|empty|exit|eval|include|include_once|isset|list|require|require_once|return|print|unset".split("|")),g=e.arrayToMap("true|false|null|__CLASS__|__DIR__|__FILE__|__LINE__|__METHOD__|__FUNCTION__|__NAMESPACE__".split("|")),h=e.arrayToMap("$GLOBALS|$_SERVER|$_GET|$_POST|$_FILES|$_REQUEST|$_SESSION|$_ENV|$_COOKIE|$php_errormsg|$HTTP_RAW_POST_DATA|$http_response_header|$argc|$argv".split("|")),i=e.arrayToMap("key_exists|cairo_matrix_create_scale|cairo_matrix_create_translate|call_user_method|call_user_method_array|com_addref|com_get|com_invoke|com_isenum|com_load|com_release|com_set|connection_timeout|cubrid_load_from_glo|cubrid_new_glo|cubrid_save_to_glo|cubrid_send_glo|define_syslog_variables|dl|ereg|ereg_replace|eregi|eregi_replace|hw_documentattributes|hw_documentbodytag|hw_documentsize|hw_outputdocument|imagedashedline|maxdb_bind_param|maxdb_bind_result|maxdb_client_encoding|maxdb_close_long_data|maxdb_execute|maxdb_fetch|maxdb_get_metadata|maxdb_param_count|maxdb_send_long_data|mcrypt_ecb|mcrypt_generic_end|mime_content_type|mysql_createdb|mysql_dbname|mysql_db_query|mysql_drop_db|mysql_dropdb|mysql_escape_string|mysql_fieldflags|mysql_fieldflags|mysql_fieldname|mysql_fieldtable|mysql_fieldtype|mysql_freeresult|mysql_listdbs|mysql_list_fields|mysql_listfields|mysql_list_tables|mysql_listtables|mysql_numfields|mysql_numrows|mysql_selectdb|mysql_tablename|mysqli_bind_param|mysqli_bind_result|mysqli_disable_reads_from_master|mysqli_disable_rpl_parse|mysqli_enable_reads_from_master|mysqli_enable_rpl_parse|mysqli_execute|mysqli_fetch|mysqli_get_metadata|mysqli_master_query|mysqli_param_count|mysqli_rpl_parse_enabled|mysqli_rpl_probe|mysqli_rpl_query_type|mysqli_send_long_data|mysqli_send_query|mysqli_slave_query|ocibindbyname|ocicancel|ocicloselob|ocicollappend|ocicollassign|ocicollassignelem|ocicollgetelem|ocicollmax|ocicollsize|ocicolltrim|ocicolumnisnull|ocicolumnname|ocicolumnprecision|ocicolumnscale|ocicolumnsize|ocicolumntype|ocicolumntyperaw|ocicommit|ocidefinebyname|ocierror|ociexecute|ocifetch|ocifetchinto|ocifetchstatement|ocifreecollection|ocifreecursor|ocifreedesc|ocifreestatement|ociinternaldebug|ociloadlob|ocilogoff|ocilogon|ocinewcollection|ocinewcursor|ocinewdescriptor|ocinlogon|ocinumcols|ociparse|ociplogon|ociresult|ocirollback|ocirowcount|ocisavelob|ocisavelobfile|ociserverversion|ocisetprefetch|ocistatementtype|ociwritelobtofile|ociwritetemporarylob|PDF_add_annotation|PDF_add_bookmark|PDF_add_launchlink|PDF_add_locallink|PDF_add_note|PDF_add_outline|PDF_add_pdflink|PDF_add_weblink|PDF_attach_file|PDF_begin_page|PDF_begin_template|PDF_close_pdi|PDF_close|PDF_findfont|PDF_get_font|PDF_get_fontname|PDF_get_fontsize|PDF_get_image_height|PDF_get_image_width|PDF_get_majorversion|PDF_get_minorversion|PDF_get_pdi_parameter|PDF_get_pdi_value|PDF_open_ccitt|PDF_open_file|PDF_open_gif|PDF_open_image_file|PDF_open_image|PDF_open_jpeg|PDF_open_pdi|PDF_open_tiff|PDF_place_image|PDF_place_pdi_page|PDF_set_border_color|PDF_set_border_dash|PDF_set_border_style|PDF_set_char_spacing|PDF_set_duration|PDF_set_horiz_scaling|PDF_set_info_author|PDF_set_info_creator|PDF_set_info_keywords|PDF_set_info_subject|PDF_set_info_title|PDF_set_leading|PDF_set_text_matrix|PDF_set_text_rendering|PDF_set_text_rise|PDF_set_word_spacing|PDF_setgray_fill|PDF_setgray_stroke|PDF_setgray|PDF_setpolydash|PDF_setrgbcolor_fill|PDF_setrgbcolor_stroke|PDF_setrgbcolor|PDF_show_boxed|php_check_syntax|px_set_tablename|px_set_targetencoding|runkit_sandbox_output_handler|session_is_registered|session_register|session_unregisterset_magic_quotes_runtime|magic_quotes_runtime|set_socket_blocking|socket_set_blocking|set_socket_timeout|socket_set_timeout|split|spliti|sql_regcase".split("|")),j=e.arrayToMap("cfunction|old_function".split("|")),k=e.arrayToMap([]);this.$rules={start:[{token:"support.php_tag",regex:"<\\?(?:php|\\=)"},{token:"support.php_tag",regex:"\\?>"},{token:"comment",regex:"<\\!--",next:"htmlcomment"},{token:"meta.tag",regex:"<style",next:"css"},{token:"meta.tag",regex:"<\\/?[-_a-zA-Z0-9:]+",next:"htmltag"},{token:"meta.tag",regex:"<!DOCTYPE.*?>"},{token:"comment",regex:"\\/\\/.*$"},{token:"comment",regex:"#.*$"},a.getStartRule("doc-start"),{token:"comment",regex:"\\/\\*",next:"comment"},{token:"string.regexp",regex:"[/](?:(?:\\[(?:\\\\]|[^\\]])+\\])|(?:\\\\/|[^\\]/]))*[/][gimy]*\\s*(?=[).,;]|$)"},{token:"string",regex:'["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'},{token:"string",regex:'["][\\s\\S]*',next:"qqstring"},{token:"string",regex:"['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"},{token:"string",regex:"['][\\s\\S]+",next:"qstring"},{token:"constant.numeric",regex:"0[xX][0-9a-fA-F]+\\b"},{token:"constant.numeric",regex:"[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"},{token:"constant.language",regex:"\\b(?:DEFAULT_INCLUDE_PATH|E_(?:ALL|CO(?:MPILE_(?:ERROR|WARNING)|RE_(?:ERROR|WARNING))|ERROR|NOTICE|PARSE|STRICT|USER_(?:ERROR|NOTICE|WARNING)|WARNING)|P(?:EAR_(?:EXTENSION_DIR|INSTALL_DIR)|HP_(?:BINDIR|CONFIG_FILE_(?:PATH|SCAN_DIR)|DATADIR|E(?:OL|XTENSION_DIR)|INT_(?:MAX|SIZE)|L(?:IBDIR|OCALSTATEDIR)|O(?:S|UTPUT_HANDLER_(?:CONT|END|START))|PREFIX|S(?:API|HLIB_SUFFIX|YSCONFDIR)|VERSION))|__COMPILER_HALT_OFFSET__)\\b"},{token:"constant.language",regex:"\\b(?:A(?:B(?:DAY_(?:1|2|3|4|5|6|7)|MON_(?:1(?:0|1|2|)|2|3|4|5|6|7|8|9))|LT_DIGITS|M_STR|SSERT_(?:ACTIVE|BAIL|CALLBACK|QUIET_EVAL|WARNING))|C(?:ASE_(?:LOWER|UPPER)|HAR_MAX|O(?:DESET|NNECTION_(?:ABORTED|NORMAL|TIMEOUT)|UNT_(?:NORMAL|RECURSIVE))|R(?:EDITS_(?:ALL|DOCS|FULLPAGE|G(?:ENERAL|ROUP)|MODULES|QA|SAPI)|NCYSTR|YPT_(?:BLOWFISH|EXT_DES|MD5|S(?:ALT_LENGTH|TD_DES)))|URRENCY_SYMBOL)|D(?:AY_(?:1|2|3|4|5|6|7)|ECIMAL_POINT|IRECTORY_SEPARATOR|_(?:FMT|T_FMT))|E(?:NT_(?:COMPAT|NOQUOTES|QUOTES)|RA(?:_(?:D_(?:FMT|T_FMT)|T_FMT|YEAR)|)|XTR_(?:IF_EXISTS|OVERWRITE|PREFIX_(?:ALL|I(?:F_EXISTS|NVALID)|SAME)|SKIP))|FRAC_DIGITS|GROUPING|HTML_(?:ENTITIES|SPECIALCHARS)|IN(?:FO_(?:ALL|C(?:ONFIGURATION|REDITS)|ENVIRONMENT|GENERAL|LICENSE|MODULES|VARIABLES)|I_(?:ALL|PERDIR|SYSTEM|USER)|T_(?:CURR_SYMBOL|FRAC_DIGITS))|L(?:C_(?:ALL|C(?:OLLATE|TYPE)|M(?:ESSAGES|ONETARY)|NUMERIC|TIME)|O(?:CK_(?:EX|NB|SH|UN)|G_(?:A(?:LERT|UTH(?:PRIV|))|C(?:ONS|R(?:IT|ON))|D(?:AEMON|EBUG)|E(?:MERG|RR)|INFO|KERN|L(?:OCAL(?:0|1|2|3|4|5|6|7)|PR)|MAIL|N(?:DELAY|EWS|O(?:TICE|WAIT))|ODELAY|P(?:ERROR|ID)|SYSLOG|U(?:SER|UCP)|WARNING)))|M(?:ON_(?:1(?:0|1|2|)|2|3|4|5|6|7|8|9|DECIMAL_POINT|GROUPING|THOUSANDS_SEP)|_(?:1_PI|2_(?:PI|SQRTPI)|E|L(?:N(?:10|2)|OG(?:10E|2E))|PI(?:_(?:2|4)|)|SQRT(?:1_2|2)))|N(?:EGATIVE_SIGN|O(?:EXPR|STR)|_(?:CS_PRECEDES|S(?:EP_BY_SPACE|IGN_POSN)))|P(?:ATH(?:INFO_(?:BASENAME|DIRNAME|EXTENSION)|_SEPARATOR)|M_STR|OSITIVE_SIGN|_(?:CS_PRECEDES|S(?:EP_BY_SPACE|IGN_POSN)))|RADIXCHAR|S(?:EEK_(?:CUR|END|SET)|ORT_(?:ASC|DESC|NUMERIC|REGULAR|STRING)|TR_PAD_(?:BOTH|LEFT|RIGHT))|T(?:HOUS(?:ANDS_SEP|EP)|_FMT(?:_AMPM|))|YES(?:EXPR|STR)|STD(?:IN|OUT|ERR))\\b"},{token:function(a){return c.hasOwnProperty(a)?"keyword":g.hasOwnProperty(a)?"constant.language":h.hasOwnProperty(a)?"variable.language":k.hasOwnProperty(a)?"invalid.illegal":b.hasOwnProperty(a)?"support.function":a=="debugger"?"invalid.deprecated":a.match(/^(\$[a-zA-Z][a-zA-Z0-9_]*|self|parent)$/)?"variable":"identifier"},regex:"[a-zA-Z_$][a-zA-Z0-9_$]*\\b"},{token:"keyword.operator",regex:"!|\\$|%|&|\\*|\\-\\-|\\-|\\+\\+|\\+|~|===|==|=|!=|!==|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\\|\\||\\?\\:|\\*=|%=|\\+=|\\-=|&=|\\^=|\\b(?:in|instanceof|new|delete|typeof|void)"},{token:"lparen",regex:"[[({]"},{token:"rparen",regex:"[\\])}]"},{token:"text",regex:"\\s+"}],comment:[{token:"comment",regex:".*?\\*\\/",next:"start"},{token:"comment",regex:".+"}],qqstring:[{token:"string",regex:'"',next:"start"},{token:"string",regex:'[^"]+'}],qstring:[{token:"string",regex:"'",next:"start"},{token:"string",regex:"[^']+"}],htmlcomment:[{token:"comment",regex:".*?-->",next:"start"},{token:"comment",regex:".+"}],htmltag:[{token:"meta.tag",regex:">",next:"start"},{token:"text",regex:"[-_a-zA-Z0-9:]+"},{token:"text",regex:"\\s+"},{token:"string",regex:'".*?"'},{token:"string",regex:"'.*?'"}],css:[{token:"meta.tag",regex:"</style>",next:"htmltag"},{token:"meta.tag",regex:">"},{token:"text",regex:"(?:media|type|href)"},{token:"string",regex:'=".*?"'},{token:"paren.lparen",regex:"{",next:"cssdeclaration"},{token:"keyword",regex:"#[A-Za-z0-9-_.]+"},{token:"variable",regex:"\\.[A-Za-z0-9-_.]+"},{token:"constant",regex:"[A-Za-z0-9]+"}],cssdeclaration:[{token:"support.type",regex:"[-a-zA-Z]+",next:"cssvalue"},{token:"paren.rparen",regex:"}",next:"css"}],cssvalue:[{token:"text",regex:":"},{token:"constant",regex:"#[0-9a-zA-Z]+"},{token:"text",regex:"[-_0-9a-zA-Z\"' ,%]+"},{token:"text",regex:";",next:"cssdeclaration"}]},this.embedRules(f,"doc-",[(new f).getEndRule("start")])};d.inherits(h,g),b.PhpHighlightRules=h}),define("ace/mode/doc_comment_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("./text_highlight_rules").TextHighlightRules,f=function(){this.$rules={start:[{token:"comment.doc.tag",regex:"@[\\w\\d_]+"},{token:"comment.doc",merge:!0,regex:"\\s+"},{token:"comment.doc",merge:!0,regex:"TODO"},{token:"comment.doc",merge:!0,regex:"[^@\\*]+"},{token:"comment.doc",merge:!0,regex:"."}]}};d.inherits(f,e),function(){this.getStartRule=function(a){return{token:"comment.doc",merge:!0,regex:"\\/\\*(?=\\*)",next:a}},this.getEndRule=function(a){return{token:"comment.doc",merge:!0,regex:"\\*\\/",next:a}}}.call(f.prototype),b.DocCommentHighlightRules=f}),define("ace/mode/matching_brace_outdent",["require","exports","module","ace/range"],function(a,b,c){"use strict";var d=a("../range").Range,e=function(){};(function(){this.checkOutdent=function(a,b){return/^\s+$/.test(a)?/^\s*\}/.test(b):!1},this.autoOutdent=function(a,b){var c=a.getLine(b),e=c.match(/^(\s*\})/);if(!e)return 0;var f=e[1].length,g=a.findMatchingBracket({row:b,column:f});if(!g||g.row==b)return 0;var h=this.$getIndent(a.getLine(g.row));a.replace(new d(b,0,b,f-1),h)},this.$getIndent=function(a){var b=a.match(/^(\s+)/);return b?b[1]:""}}).call(e.prototype),b.MatchingBraceOutdent=e}),define("ace/mode/behaviour/cstyle",["require","exports","module","ace/lib/oop","ace/mode/behaviour"],function(a,b,c){"use strict";var d=a("../../lib/oop"),e=a("../behaviour").Behaviour,f=function(){this.add("braces","insertion",function(a,b,c,d,e){if(e=="{"){var f=c.getSelectionRange(),g=d.doc.getTextRange(f);return g!==""?{text:"{"+g+"}",selection:!1}:{text:"{}",selection:[1,1]}}if(e=="}"){var h=c.getCursorPosition(),i=d.doc.getLine(h.row),j=i.substring(h.column,h.column+1);if(j=="}"){var k=d.$findOpeningBracket("}",{column:h.column+1,row:h.row});if(k!==null)return{text:"",selection:[1,1]}}}else if(e=="\n"){var h=c.getCursorPosition(),i=d.doc.getLine(h.row),j=i.substring(h.column,h.column+1);if(j=="}"){var l=d.findMatchingBracket({row:h.row,column:h.column+1});if(!l)return null;var m=this.getNextLineIndent(a,i.substring(0,i.length-1),d.getTabString()),n=this.$getIndent(d.doc.getLine(l.row));return{text:"\n"+m+"\n"+n,selection:[1,m.length,1,m.length]}}}}),this.add("braces","deletion",function(a,b,c,d,e){var f=d.doc.getTextRange(e);if(!e.isMultiLine()&&f=="{"){var g=d.doc.getLine(e.start.row),h=g.substring(e.end.column,e.end.column+1);if(h=="}")return e.end.column++,e}}),this.add("parens","insertion",function(a,b,c,d,e){if(e=="("){var f=c.getSelectionRange(),g=d.doc.getTextRange(f);return g!==""?{text:"("+g+")",selection:!1}:{text:"()",selection:[1,1]}}if(e==")"){var h=c.getCursorPosition(),i=d.doc.getLine(h.row),j=i.substring(h.column,h.column+1);if(j==")"){var k=d.$findOpeningBracket(")",{column:h.column+1,row:h.row});if(k!==null)return{text:"",selection:[1,1]}}}}),this.add("parens","deletion",function(a,b,c,d,e){var f=d.doc.getTextRange(e);if(!e.isMultiLine()&&f=="("){var g=d.doc.getLine(e.start.row),h=g.substring(e.start.column+1,e.start.column+2);if(h==")")return e.end.column++,e}}),this.add("string_dquotes","insertion",function(a,b,c,d,e){if(e=='"'||e=="'"){var f=e,g=c.getSelectionRange(),h=d.doc.getTextRange(g);if(h!=="")return{text:f+h+f,selection:!1};var i=c.getCursorPosition(),j=d.doc.getLine(i.row),k=j.substring(i.column-1,i.column);if(k=="\\")return null;var l=d.getTokens(g.start.row,g.start.row)[0].tokens,m=0,n,o=-1;for(var p=0;p<l.length;p++){n=l[p],n.type=="string"?o=-1:o<0&&(o=n.value.indexOf(f));if(n.value.length+m>g.start.column)break;m+=l[p].value.length}if(!n||o<0&&n.type!=="comment"&&(n.type!=="string"||g.start.column!==n.value.length+m-1&&n.value.lastIndexOf(f)===n.value.length-1))return{text:f+f,selection:[1,1]};if(n&&n.type==="string"){var q=j.substring(i.column,i.column+1);if(q==f)return{text:"",selection:[1,1]}}}}),this.add("string_dquotes","deletion",function(a,b,c,d,e){var f=d.doc.getTextRange(e);if(!e.isMultiLine()&&(f=='"'||f=="'")){var g=d.doc.getLine(e.start.row),h=g.substring(e.start.column+1,e.start.column+2);if(h=='"')return e.end.column++,e}})};d.inherits(f,e),b.CstyleBehaviour=f}),define("ace/mode/folding/cstyle",["require","exports","module","ace/lib/oop","ace/range","ace/mode/folding/fold_mode"],function(a,b,c){"use strict";var d=a("../../lib/oop"),e=a("../../range").Range,f=a("./fold_mode").FoldMode,g=b.FoldMode=function(){};d.inherits(g,f),function(){this.foldingStartMarker=/(\{|\[)[^\}\]]*$|^\s*(\/\*)/,this.foldingStopMarker=/^[^\[\{]*(\}|\])|^[\s\*]*(\*\/)/,this.getFoldWidgetRange=function(a,b,c){var d=a.getLine(c),f=d.match(this.foldingStartMarker);if(f){var g=f.index;if(f[1])return this.openingBracketBlock(a,f[1],c,g);var h=a.getCommentFoldRange(c,g+f[0].length);return h.end.column-=2,h}if(b!=="markbeginend")return;var f=d.match(this.foldingStopMarker);if(f){var g=f.index+f[0].length;if(f[2]){var h=a.getCommentFoldRange(c,g);return h.end.column-=2,h}var i={row:c,column:g},j=a.$findOpeningBracket(f[1],i);if(!j)return;return j.column++,i.column--,e.fromPoints(j,i)}}}.call(g.prototype)}),define("ace/mode/folding/fold_mode",["require","exports","module","ace/range"],function(a,b,c){"use strict";var d=a("../../range").Range,e=b.FoldMode=function(){};(function(){this.foldingStartMarker=null,this.foldingStopMarker=null,this.getFoldWidget=function(a,b,c){var d=a.getLine(c);return this.foldingStartMarker.test(d)?"start":b=="markbeginend"&&this.foldingStopMarker&&this.foldingStopMarker.test(d)?"end":""},this.getFoldWidgetRange=function(a,b,c){return null},this.indentationBlock=function(a,b,c){var e=/^\s*/,f=b,g=b,h=a.getLine(b),i=c||h.length,j=h.match(e)[0].length,k=a.getLength();while(++b<k){h=a.getLine(b);var l=h.match(e)[0].length;if(l==h.length)continue;if(l<=j)break;g=b}if(g>f){var m=a.getLine(g).length;return new d(f,i,g,m)}},this.openingBracketBlock=function(a,b,c,e){var f={row:c,column:e+1},g=a.$findClosingBracket(b,f);if(!g)return;var h=a.foldWidgets[g.row];return h==null&&(h=this.getFoldWidget(a,g.row)),h=="start"&&(g.row--,g.column=a.getLine(g.row).length),d.fromPoints(f,g)}}).call(e.prototype)})
\ No newline at end of file
diff --git a/apps/files_texteditor/js/aceeditor/mode-powershell-uncompressed.js b/apps/files_texteditor/js/aceeditor/mode-powershell-uncompressed.js
old mode 100755
new mode 100644
index e5877f6237393100b38f1bf41bff32fed95183b9..e6f9deea0140166c395e77e14b39bf9547665f9d
--- a/apps/files_texteditor/js/aceeditor/mode-powershell-uncompressed.js
+++ b/apps/files_texteditor/js/aceeditor/mode-powershell-uncompressed.js
@@ -329,12 +329,12 @@ var CstyleBehaviour = function () {
                 return {
                     text: '{' + selected + '}',
                     selection: false
-                }
+                };
             } else {
                 return {
                     text: '{}',
                     selection: [1, 1]
-                }
+                };
             }
         } else if (text == '}') {
             var cursor = editor.getCursorPosition();
@@ -346,7 +346,7 @@ var CstyleBehaviour = function () {
                     return {
                         text: '',
                         selection: [1, 1]
-                    }
+                    };
                 }
             }
         } else if (text == "\n") {
@@ -364,7 +364,7 @@ var CstyleBehaviour = function () {
                 return {
                     text: '\n' + indent + '\n' + next_indent,
                     selection: [1, indent.length, 1, indent.length]
-                }
+                };
             }
         }
     });
@@ -389,12 +389,12 @@ var CstyleBehaviour = function () {
                 return {
                     text: '(' + selected + ')',
                     selection: false
-                }
+                };
             } else {
                 return {
                     text: '()',
                     selection: [1, 1]
-                }
+                };
             }
         } else if (text == ')') {
             var cursor = editor.getCursorPosition();
@@ -406,7 +406,7 @@ var CstyleBehaviour = function () {
                     return {
                         text: '',
                         selection: [1, 1]
-                    }
+                    };
                 }
             }
         }
@@ -425,14 +425,15 @@ var CstyleBehaviour = function () {
     });
 
     this.add("string_dquotes", "insertion", function (state, action, editor, session, text) {
-        if (text == '"') {
+        if (text == '"' || text == "'") {
+            var quote = text;
             var selection = editor.getSelectionRange();
             var selected = session.doc.getTextRange(selection);
             if (selected !== "") {
                 return {
-                    text: '"' + selected + '"',
+                    text: quote + selected + quote,
                     selection: false
-                }
+                };
             } else {
                 var cursor = editor.getCursorPosition();
                 var line = session.doc.getLine(cursor.row);
@@ -453,7 +454,7 @@ var CstyleBehaviour = function () {
                     if (token.type == "string") {
                       quotepos = -1;
                     } else if (quotepos < 0) {
-                      quotepos = token.value.indexOf('"');
+                      quotepos = token.value.indexOf(quote);
                     }
                     if ((token.value.length + col) > selection.start.column) {
                         break;
@@ -462,19 +463,19 @@ var CstyleBehaviour = function () {
                 }
 
                 // Try and be smart about when we auto insert.
-                if (!token || (quotepos < 0 && token.type !== "comment" && (token.type !== "string" || ((selection.start.column !== token.value.length+col-1) && token.value.lastIndexOf('"') === token.value.length-1)))) {
+                if (!token || (quotepos < 0 && token.type !== "comment" && (token.type !== "string" || ((selection.start.column !== token.value.length+col-1) && token.value.lastIndexOf(quote) === token.value.length-1)))) {
                     return {
-                        text: '""',
+                        text: quote + quote,
                         selection: [1,1]
-                    }
+                    };
                 } else if (token && token.type === "string") {
                     // Ignore input and move right one if we're typing over the closing quote.
                     var rightChar = line.substring(cursor.column, cursor.column + 1);
-                    if (rightChar == '"') {
+                    if (rightChar == quote) {
                         return {
                             text: '',
                             selection: [1, 1]
-                        }
+                        };
                     }
                 }
             }
@@ -483,7 +484,7 @@ var CstyleBehaviour = function () {
 
     this.add("string_dquotes", "deletion", function (state, action, editor, session, range) {
         var selected = session.doc.getTextRange(range);
-        if (!range.isMultiLine() && selected == '"') {
+        if (!range.isMultiLine() && (selected == '"' || selected == "'")) {
             var line = session.doc.getLine(range.start.row);
             var rightChar = line.substring(range.start.column + 1, range.start.column + 2);
             if (rightChar == '"') {
@@ -493,7 +494,8 @@ var CstyleBehaviour = function () {
         }
     });
 
-}
+};
+
 oop.inherits(CstyleBehaviour, Behaviour);
 
 exports.CstyleBehaviour = CstyleBehaviour;
@@ -704,13 +706,3 @@ var FoldMode = exports.FoldMode = function() {};
 }).call(FoldMode.prototype);
 
 });
-;
-            (function() {
-                window.require(["ace/ace"], function(a) {
-                    if (!window.ace)
-                        window.ace = {};
-                    for (var key in a) if (a.hasOwnProperty(key))
-                        ace[key] = a[key];
-                });
-            })();
-        
\ No newline at end of file
diff --git a/apps/files_texteditor/js/aceeditor/mode-powershell.js b/apps/files_texteditor/js/aceeditor/mode-powershell.js
old mode 100755
new mode 100644
index 9bbdef6989ba05a50a8af9e320191f307f37845e..6ebaeae5201735c6a24e3f5852fdcf69c12ff5d1
--- a/apps/files_texteditor/js/aceeditor/mode-powershell.js
+++ b/apps/files_texteditor/js/aceeditor/mode-powershell.js
@@ -1 +1 @@
-define("ace/mode/powershell",["require","exports","module","ace/lib/oop","ace/mode/text","ace/tokenizer","ace/mode/powershell_highlight_rules","ace/mode/matching_brace_outdent","ace/mode/behaviour/cstyle","ace/mode/folding/cstyle"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("./text").Mode,f=a("../tokenizer").Tokenizer,g=a("./powershell_highlight_rules").PowershellHighlightRules,h=a("./matching_brace_outdent").MatchingBraceOutdent,i=a("./behaviour/cstyle").CstyleBehaviour,j=a("./folding/cstyle").FoldMode,k=function(){this.$tokenizer=new f((new g).getRules()),this.$outdent=new h,this.$behaviour=new i,this.foldingRules=new j};d.inherits(k,e),function(){this.getNextLineIndent=function(a,b,c){var d=this.$getIndent(b),e=this.$tokenizer.getLineTokens(b,a),f=e.tokens;if(f.length&&f[f.length-1].type=="comment")return d;if(a=="start"){var g=b.match(/^.*[\{\(\[]\s*$/);g&&(d+=c)}return d},this.checkOutdent=function(a,b,c){return this.$outdent.checkOutdent(b,c)},this.autoOutdent=function(a,b,c){this.$outdent.autoOutdent(b,c)},this.createWorker=function(a){return null}}.call(k.prototype),b.Mode=k}),define("ace/mode/powershell_highlight_rules",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/mode/text_highlight_rules"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("../lib/lang"),f=a("./text_highlight_rules").TextHighlightRules,g=function(){var a=e.arrayToMap("function|if|else|elseif|switch|while|default|for|do|until|break|continue|foreach|return|filter|in|trap|throw|param|begin|process|end".split("|")),b=e.arrayToMap("Get-Alias|Import-Alias|New-Alias|Set-Alias|Get-AuthenticodeSignature|Set-AuthenticodeSignature|Set-Location|Get-ChildItem|Clear-Item|Get-Command|Measure-Command|Trace-Command|Add-Computer|Checkpoint-Computer|Remove-Computer|Restart-Computer|Restore-Computer|Stop-Computer|Reset-ComputerMachinePassword|Test-ComputerSecureChannel|Add-Content|Get-Content|Set-Content|Clear-Content|Get-Command|Invoke-Command|Enable-ComputerRestore|Disable-ComputerRestore|Get-ComputerRestorePoint|Test-Connection|ConvertFrom-CSV|ConvertTo-CSV|ConvertTo-Html|ConvertTo-Xml|ConvertFrom-SecureString|ConvertTo-SecureString|Copy-Item|Export-Counter|Get-Counter|Import-Counter|Get-Credential|Get-Culture|Get-ChildItem|Get-Date|Set-Date|Remove-Item|Compare-Object|Get-Event|Get-WinEvent|New-Event|Remove-Event|Unregister-Event|Wait-Event|Clear-EventLog|Get-Eventlog|Limit-EventLog|New-Eventlog|Remove-EventLog|Show-EventLog|Write-EventLog|Get-EventSubscriber|Register-EngineEvent|Register-ObjectEvent|Register-WmiEvent|Get-ExecutionPolicy|Set-ExecutionPolicy|Export-Alias|Export-Clixml|Export-Console|Export-Csv|ForEach-Object|Format-Custom|Format-List|Format-Table|Format-Wide|Export-FormatData|Get-FormatData|Get-Item|Get-ChildItem|Get-Help|Add-History|Clear-History|Get-History|Invoke-History|Get-Host|Read-Host|Write-Host|Get-HotFix|Import-Clixml|Import-Csv|Invoke-Command|Invoke-Expression|Get-Item|Invoke-Item|New-Item|Remove-Item|Set-Item|Clear-ItemProperty|Copy-ItemProperty|Get-ItemProperty|Move-ItemProperty|New-ItemProperty|Remove-ItemProperty|Rename-ItemProperty|Set-ItemProperty|Get-Job|Receive-Job|Remove-Job|Start-Job|Stop-Job|Wait-Job|Stop-Process|Update-List|Get-Location|Pop-Location|Push-Location|Set-Location|Send-MailMessage|Add-Member|Get-Member|Move-Item|Compare-Object|Group-Object|Measure-Object|New-Object|Select-Object|Sort-Object|Where-Object|Out-Default|Out-File|Out-GridView|Out-Host|Out-Null|Out-Printer|Out-String|Convert-Path|Join-Path|Resolve-Path|Split-Path|Test-Path|Get-Pfxcertificate|Pop-Location|Push-Location|Get-Process|Start-Process|Stop-Process|Wait-Process|Enable-PSBreakpoint|Disable-PSBreakpoint|Get-PSBreakpoint|Set-PSBreakpoint|Remove-PSBreakpoint|Get-PSDrive|New-PSDrive|Remove-PSDrive|Get-PSProvider|Set-PSdebug|Enter-PSSession|Exit-PSSession|Export-PSSession|Get-PSSession|Import-PSSession|New-PSSession|Remove-PSSession|Disable-PSSessionConfiguration|Enable-PSSessionConfiguration|Get-PSSessionConfiguration|Register-PSSessionConfiguration|Set-PSSessionConfiguration|Unregister-PSSessionConfiguration|New-PSSessionOption|Add-PsSnapIn|Get-PsSnapin|Remove-PSSnapin|Get-Random|Read-Host|Remove-Item|Rename-Item|Rename-ItemProperty|Select-Object|Select-XML|Send-MailMessage|Get-Service|New-Service|Restart-Service|Resume-Service|Set-Service|Start-Service|Stop-Service|Suspend-Service|Sort-Object|Start-Sleep|ConvertFrom-StringData|Select-String|Tee-Object|New-Timespan|Trace-Command|Get-Tracesource|Set-Tracesource|Start-Transaction|Complete-Transaction|Get-Transaction|Use-Transaction|Undo-Transaction|Start-Transcript|Stop-Transcript|Add-Type|Update-TypeData|Get-Uiculture|Get-Unique|Update-Formatdata|Update-Typedata|Clear-Variable|Get-Variable|New-Variable|Remove-Variable|Set-Variable|New-WebServiceProxy|Where-Object|Write-Debug|Write-Error|Write-Host|Write-Output|Write-Progress|Write-Verbose|Write-Warning|Set-WmiInstance|Invoke-WmiMethod|Get-WmiObject|Remove-WmiObject|Connect-WSMan|Disconnect-WSMan|Test-WSMan|Invoke-WSManAction|Disable-WSManCredSSP|Enable-WSManCredSSP|Get-WSManCredSSP|New-WSManInstance|Get-WSManInstance|Set-WSManInstance|Remove-WSManInstance|Set-WSManQuickConfig|New-WSManSessionOption".split("|")),c="eq|ne|ge|gt|lt|le|like|notlike|match|notmatch|replace|contains|notcontains|ieq|ine|ige|igt|ile|ilt|ilike|inotlike|imatch|inotmatch|ireplace|icontains|inotcontains|is|isnot|as|and|or|band|bor|not";this.$rules={start:[{token:"comment",regex:"#.*$"},{token:"string",regex:'["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'},{token:"string",regex:"['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"},{token:"constant.numeric",regex:"0[xX][0-9a-fA-F]+\\b"},{token:"constant.numeric",regex:"[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"},{token:"constant.language.boolean",regex:"[$](?:[Tt]rue|[Ff]alse)\\b"},{token:"constant.language",regex:"[$][Nn]ull\\b"},{token:"variable.instance",regex:"[$][a-zA-Z][a-zA-Z0-9_]*\\b"},{token:function(c){return a.hasOwnProperty(c)?"keyword":b.hasOwnProperty(c)?"support.function":"identifier"},regex:"[a-zA-Z_$][a-zA-Z0-9_$\\-]*\\b"},{token:"keyword.operator",regex:"\\-(?:"+c+")"},{token:"keyword.operator",regex:"&|\\*|\\+|\\-|\\=|\\+=|\\-="},{token:"lparen",regex:"[[({]"},{token:"rparen",regex:"[\\])}]"},{token:"text",regex:"\\s+"}],comment:[{token:"comment",regex:".*?\\*\\/",next:"start"},{token:"comment",merge:!0,regex:".+"}]}};d.inherits(g,f),b.PowershellHighlightRules=g}),define("ace/mode/matching_brace_outdent",["require","exports","module","ace/range"],function(a,b,c){"use strict";var d=a("../range").Range,e=function(){};((function(){this.checkOutdent=function(a,b){return/^\s+$/.test(a)?/^\s*\}/.test(b):!1},this.autoOutdent=function(a,b){var c=a.getLine(b),e=c.match(/^(\s*\})/);if(!e)return 0;var f=e[1].length,g=a.findMatchingBracket({row:b,column:f});if(!g||g.row==b)return 0;var h=this.$getIndent(a.getLine(g.row));a.replace(new d(b,0,b,f-1),h)},this.$getIndent=function(a){var b=a.match(/^(\s+)/);return b?b[1]:""}})).call(e.prototype),b.MatchingBraceOutdent=e}),define("ace/mode/behaviour/cstyle",["require","exports","module","ace/lib/oop","ace/mode/behaviour"],function(a,b,c){"use strict";var d=a("../../lib/oop"),e=a("../behaviour").Behaviour,f=function(){this.add("braces","insertion",function(a,b,c,d,e){if(e=="{"){var f=c.getSelectionRange(),g=d.doc.getTextRange(f);return g!==""?{text:"{"+g+"}",selection:!1}:{text:"{}",selection:[1,1]}}if(e=="}"){var h=c.getCursorPosition(),i=d.doc.getLine(h.row),j=i.substring(h.column,h.column+1);if(j=="}"){var k=d.$findOpeningBracket("}",{column:h.column+1,row:h.row});if(k!==null)return{text:"",selection:[1,1]}}}else if(e=="\n"){var h=c.getCursorPosition(),i=d.doc.getLine(h.row),j=i.substring(h.column,h.column+1);if(j=="}"){var l=d.findMatchingBracket({row:h.row,column:h.column+1});if(!l)return null;var m=this.getNextLineIndent(a,i.substring(0,i.length-1),d.getTabString()),n=this.$getIndent(d.doc.getLine(l.row));return{text:"\n"+m+"\n"+n,selection:[1,m.length,1,m.length]}}}}),this.add("braces","deletion",function(a,b,c,d,e){var f=d.doc.getTextRange(e);if(!e.isMultiLine()&&f=="{"){var g=d.doc.getLine(e.start.row),h=g.substring(e.end.column,e.end.column+1);if(h=="}")return e.end.column++,e}}),this.add("parens","insertion",function(a,b,c,d,e){if(e=="("){var f=c.getSelectionRange(),g=d.doc.getTextRange(f);return g!==""?{text:"("+g+")",selection:!1}:{text:"()",selection:[1,1]}}if(e==")"){var h=c.getCursorPosition(),i=d.doc.getLine(h.row),j=i.substring(h.column,h.column+1);if(j==")"){var k=d.$findOpeningBracket(")",{column:h.column+1,row:h.row});if(k!==null)return{text:"",selection:[1,1]}}}}),this.add("parens","deletion",function(a,b,c,d,e){var f=d.doc.getTextRange(e);if(!e.isMultiLine()&&f=="("){var g=d.doc.getLine(e.start.row),h=g.substring(e.start.column+1,e.start.column+2);if(h==")")return e.end.column++,e}}),this.add("string_dquotes","insertion",function(a,b,c,d,e){if(e=='"'){var f=c.getSelectionRange(),g=d.doc.getTextRange(f);if(g!=="")return{text:'"'+g+'"',selection:!1};var h=c.getCursorPosition(),i=d.doc.getLine(h.row),j=i.substring(h.column-1,h.column);if(j=="\\")return null;var k=d.getTokens(f.start.row,f.start.row)[0].tokens,l=0,m,n=-1;for(var o=0;o<k.length;o++){m=k[o],m.type=="string"?n=-1:n<0&&(n=m.value.indexOf('"'));if(m.value.length+l>f.start.column)break;l+=k[o].value.length}if(!m||n<0&&m.type!=="comment"&&(m.type!=="string"||f.start.column!==m.value.length+l-1&&m.value.lastIndexOf('"')===m.value.length-1))return{text:'""',selection:[1,1]};if(m&&m.type==="string"){var p=i.substring(h.column,h.column+1);if(p=='"')return{text:"",selection:[1,1]}}}}),this.add("string_dquotes","deletion",function(a,b,c,d,e){var f=d.doc.getTextRange(e);if(!e.isMultiLine()&&f=='"'){var g=d.doc.getLine(e.start.row),h=g.substring(e.start.column+1,e.start.column+2);if(h=='"')return e.end.column++,e}})};d.inherits(f,e),b.CstyleBehaviour=f}),define("ace/mode/folding/cstyle",["require","exports","module","ace/lib/oop","ace/range","ace/mode/folding/fold_mode"],function(a,b,c){"use strict";var d=a("../../lib/oop"),e=a("../../range").Range,f=a("./fold_mode").FoldMode,g=b.FoldMode=function(){};d.inherits(g,f),function(){this.foldingStartMarker=/(\{|\[)[^\}\]]*$|^\s*(\/\*)/,this.foldingStopMarker=/^[^\[\{]*(\}|\])|^[\s\*]*(\*\/)/,this.getFoldWidgetRange=function(a,b,c){var d=a.getLine(c),f=d.match(this.foldingStartMarker);if(f){var g=f.index;if(f[1])return this.openingBracketBlock(a,f[1],c,g);var h=a.getCommentFoldRange(c,g+f[0].length);return h.end.column-=2,h}if(b!=="markbeginend")return;var f=d.match(this.foldingStopMarker);if(f){var g=f.index+f[0].length;if(f[2]){var h=a.getCommentFoldRange(c,g);return h.end.column-=2,h}var i={row:c,column:g},j=a.$findOpeningBracket(f[1],i);if(!j)return;return j.column++,i.column--,e.fromPoints(j,i)}}}.call(g.prototype)}),define("ace/mode/folding/fold_mode",["require","exports","module","ace/range"],function(a,b,c){"use strict";var d=a("../../range").Range,e=b.FoldMode=function(){};((function(){this.foldingStartMarker=null,this.foldingStopMarker=null,this.getFoldWidget=function(a,b,c){var d=a.getLine(c);return this.foldingStartMarker.test(d)?"start":b=="markbeginend"&&this.foldingStopMarker&&this.foldingStopMarker.test(d)?"end":""},this.getFoldWidgetRange=function(a,b,c){return null},this.indentationBlock=function(a,b,c){var e=/^\s*/,f=b,g=b,h=a.getLine(b),i=c||h.length,j=h.match(e)[0].length,k=a.getLength();while(++b<k){h=a.getLine(b);var l=h.match(e)[0].length;if(l==h.length)continue;if(l<=j)break;g=b}if(g>f){var m=a.getLine(g).length;return new d(f,i,g,m)}},this.openingBracketBlock=function(a,b,c,e){var f={row:c,column:e+1},g=a.$findClosingBracket(b,f);if(!g)return;var h=a.foldWidgets[g.row];return h==null&&(h=this.getFoldWidget(a,g.row)),h=="start"&&(g.row--,g.column=a.getLine(g.row).length),d.fromPoints(f,g)}})).call(e.prototype)}),function(){window.require(["ace/ace"],function(a){window.ace||(window.ace={});for(var b in a)a.hasOwnProperty(b)&&(ace[b]=a[b])})}()
\ No newline at end of file
+define("ace/mode/powershell",["require","exports","module","ace/lib/oop","ace/mode/text","ace/tokenizer","ace/mode/powershell_highlight_rules","ace/mode/matching_brace_outdent","ace/mode/behaviour/cstyle","ace/mode/folding/cstyle"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("./text").Mode,f=a("../tokenizer").Tokenizer,g=a("./powershell_highlight_rules").PowershellHighlightRules,h=a("./matching_brace_outdent").MatchingBraceOutdent,i=a("./behaviour/cstyle").CstyleBehaviour,j=a("./folding/cstyle").FoldMode,k=function(){this.$tokenizer=new f((new g).getRules()),this.$outdent=new h,this.$behaviour=new i,this.foldingRules=new j};d.inherits(k,e),function(){this.getNextLineIndent=function(a,b,c){var d=this.$getIndent(b),e=this.$tokenizer.getLineTokens(b,a),f=e.tokens;if(f.length&&f[f.length-1].type=="comment")return d;if(a=="start"){var g=b.match(/^.*[\{\(\[]\s*$/);g&&(d+=c)}return d},this.checkOutdent=function(a,b,c){return this.$outdent.checkOutdent(b,c)},this.autoOutdent=function(a,b,c){this.$outdent.autoOutdent(b,c)},this.createWorker=function(a){return null}}.call(k.prototype),b.Mode=k}),define("ace/mode/powershell_highlight_rules",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/mode/text_highlight_rules"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("../lib/lang"),f=a("./text_highlight_rules").TextHighlightRules,g=function(){var a=e.arrayToMap("function|if|else|elseif|switch|while|default|for|do|until|break|continue|foreach|return|filter|in|trap|throw|param|begin|process|end".split("|")),b=e.arrayToMap("Get-Alias|Import-Alias|New-Alias|Set-Alias|Get-AuthenticodeSignature|Set-AuthenticodeSignature|Set-Location|Get-ChildItem|Clear-Item|Get-Command|Measure-Command|Trace-Command|Add-Computer|Checkpoint-Computer|Remove-Computer|Restart-Computer|Restore-Computer|Stop-Computer|Reset-ComputerMachinePassword|Test-ComputerSecureChannel|Add-Content|Get-Content|Set-Content|Clear-Content|Get-Command|Invoke-Command|Enable-ComputerRestore|Disable-ComputerRestore|Get-ComputerRestorePoint|Test-Connection|ConvertFrom-CSV|ConvertTo-CSV|ConvertTo-Html|ConvertTo-Xml|ConvertFrom-SecureString|ConvertTo-SecureString|Copy-Item|Export-Counter|Get-Counter|Import-Counter|Get-Credential|Get-Culture|Get-ChildItem|Get-Date|Set-Date|Remove-Item|Compare-Object|Get-Event|Get-WinEvent|New-Event|Remove-Event|Unregister-Event|Wait-Event|Clear-EventLog|Get-Eventlog|Limit-EventLog|New-Eventlog|Remove-EventLog|Show-EventLog|Write-EventLog|Get-EventSubscriber|Register-EngineEvent|Register-ObjectEvent|Register-WmiEvent|Get-ExecutionPolicy|Set-ExecutionPolicy|Export-Alias|Export-Clixml|Export-Console|Export-Csv|ForEach-Object|Format-Custom|Format-List|Format-Table|Format-Wide|Export-FormatData|Get-FormatData|Get-Item|Get-ChildItem|Get-Help|Add-History|Clear-History|Get-History|Invoke-History|Get-Host|Read-Host|Write-Host|Get-HotFix|Import-Clixml|Import-Csv|Invoke-Command|Invoke-Expression|Get-Item|Invoke-Item|New-Item|Remove-Item|Set-Item|Clear-ItemProperty|Copy-ItemProperty|Get-ItemProperty|Move-ItemProperty|New-ItemProperty|Remove-ItemProperty|Rename-ItemProperty|Set-ItemProperty|Get-Job|Receive-Job|Remove-Job|Start-Job|Stop-Job|Wait-Job|Stop-Process|Update-List|Get-Location|Pop-Location|Push-Location|Set-Location|Send-MailMessage|Add-Member|Get-Member|Move-Item|Compare-Object|Group-Object|Measure-Object|New-Object|Select-Object|Sort-Object|Where-Object|Out-Default|Out-File|Out-GridView|Out-Host|Out-Null|Out-Printer|Out-String|Convert-Path|Join-Path|Resolve-Path|Split-Path|Test-Path|Get-Pfxcertificate|Pop-Location|Push-Location|Get-Process|Start-Process|Stop-Process|Wait-Process|Enable-PSBreakpoint|Disable-PSBreakpoint|Get-PSBreakpoint|Set-PSBreakpoint|Remove-PSBreakpoint|Get-PSDrive|New-PSDrive|Remove-PSDrive|Get-PSProvider|Set-PSdebug|Enter-PSSession|Exit-PSSession|Export-PSSession|Get-PSSession|Import-PSSession|New-PSSession|Remove-PSSession|Disable-PSSessionConfiguration|Enable-PSSessionConfiguration|Get-PSSessionConfiguration|Register-PSSessionConfiguration|Set-PSSessionConfiguration|Unregister-PSSessionConfiguration|New-PSSessionOption|Add-PsSnapIn|Get-PsSnapin|Remove-PSSnapin|Get-Random|Read-Host|Remove-Item|Rename-Item|Rename-ItemProperty|Select-Object|Select-XML|Send-MailMessage|Get-Service|New-Service|Restart-Service|Resume-Service|Set-Service|Start-Service|Stop-Service|Suspend-Service|Sort-Object|Start-Sleep|ConvertFrom-StringData|Select-String|Tee-Object|New-Timespan|Trace-Command|Get-Tracesource|Set-Tracesource|Start-Transaction|Complete-Transaction|Get-Transaction|Use-Transaction|Undo-Transaction|Start-Transcript|Stop-Transcript|Add-Type|Update-TypeData|Get-Uiculture|Get-Unique|Update-Formatdata|Update-Typedata|Clear-Variable|Get-Variable|New-Variable|Remove-Variable|Set-Variable|New-WebServiceProxy|Where-Object|Write-Debug|Write-Error|Write-Host|Write-Output|Write-Progress|Write-Verbose|Write-Warning|Set-WmiInstance|Invoke-WmiMethod|Get-WmiObject|Remove-WmiObject|Connect-WSMan|Disconnect-WSMan|Test-WSMan|Invoke-WSManAction|Disable-WSManCredSSP|Enable-WSManCredSSP|Get-WSManCredSSP|New-WSManInstance|Get-WSManInstance|Set-WSManInstance|Remove-WSManInstance|Set-WSManQuickConfig|New-WSManSessionOption".split("|")),c="eq|ne|ge|gt|lt|le|like|notlike|match|notmatch|replace|contains|notcontains|ieq|ine|ige|igt|ile|ilt|ilike|inotlike|imatch|inotmatch|ireplace|icontains|inotcontains|is|isnot|as|and|or|band|bor|not";this.$rules={start:[{token:"comment",regex:"#.*$"},{token:"string",regex:'["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'},{token:"string",regex:"['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"},{token:"constant.numeric",regex:"0[xX][0-9a-fA-F]+\\b"},{token:"constant.numeric",regex:"[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"},{token:"constant.language.boolean",regex:"[$](?:[Tt]rue|[Ff]alse)\\b"},{token:"constant.language",regex:"[$][Nn]ull\\b"},{token:"variable.instance",regex:"[$][a-zA-Z][a-zA-Z0-9_]*\\b"},{token:function(c){return a.hasOwnProperty(c)?"keyword":b.hasOwnProperty(c)?"support.function":"identifier"},regex:"[a-zA-Z_$][a-zA-Z0-9_$\\-]*\\b"},{token:"keyword.operator",regex:"\\-(?:"+c+")"},{token:"keyword.operator",regex:"&|\\*|\\+|\\-|\\=|\\+=|\\-="},{token:"lparen",regex:"[[({]"},{token:"rparen",regex:"[\\])}]"},{token:"text",regex:"\\s+"}],comment:[{token:"comment",regex:".*?\\*\\/",next:"start"},{token:"comment",merge:!0,regex:".+"}]}};d.inherits(g,f),b.PowershellHighlightRules=g}),define("ace/mode/matching_brace_outdent",["require","exports","module","ace/range"],function(a,b,c){"use strict";var d=a("../range").Range,e=function(){};(function(){this.checkOutdent=function(a,b){return/^\s+$/.test(a)?/^\s*\}/.test(b):!1},this.autoOutdent=function(a,b){var c=a.getLine(b),e=c.match(/^(\s*\})/);if(!e)return 0;var f=e[1].length,g=a.findMatchingBracket({row:b,column:f});if(!g||g.row==b)return 0;var h=this.$getIndent(a.getLine(g.row));a.replace(new d(b,0,b,f-1),h)},this.$getIndent=function(a){var b=a.match(/^(\s+)/);return b?b[1]:""}}).call(e.prototype),b.MatchingBraceOutdent=e}),define("ace/mode/behaviour/cstyle",["require","exports","module","ace/lib/oop","ace/mode/behaviour"],function(a,b,c){"use strict";var d=a("../../lib/oop"),e=a("../behaviour").Behaviour,f=function(){this.add("braces","insertion",function(a,b,c,d,e){if(e=="{"){var f=c.getSelectionRange(),g=d.doc.getTextRange(f);return g!==""?{text:"{"+g+"}",selection:!1}:{text:"{}",selection:[1,1]}}if(e=="}"){var h=c.getCursorPosition(),i=d.doc.getLine(h.row),j=i.substring(h.column,h.column+1);if(j=="}"){var k=d.$findOpeningBracket("}",{column:h.column+1,row:h.row});if(k!==null)return{text:"",selection:[1,1]}}}else if(e=="\n"){var h=c.getCursorPosition(),i=d.doc.getLine(h.row),j=i.substring(h.column,h.column+1);if(j=="}"){var l=d.findMatchingBracket({row:h.row,column:h.column+1});if(!l)return null;var m=this.getNextLineIndent(a,i.substring(0,i.length-1),d.getTabString()),n=this.$getIndent(d.doc.getLine(l.row));return{text:"\n"+m+"\n"+n,selection:[1,m.length,1,m.length]}}}}),this.add("braces","deletion",function(a,b,c,d,e){var f=d.doc.getTextRange(e);if(!e.isMultiLine()&&f=="{"){var g=d.doc.getLine(e.start.row),h=g.substring(e.end.column,e.end.column+1);if(h=="}")return e.end.column++,e}}),this.add("parens","insertion",function(a,b,c,d,e){if(e=="("){var f=c.getSelectionRange(),g=d.doc.getTextRange(f);return g!==""?{text:"("+g+")",selection:!1}:{text:"()",selection:[1,1]}}if(e==")"){var h=c.getCursorPosition(),i=d.doc.getLine(h.row),j=i.substring(h.column,h.column+1);if(j==")"){var k=d.$findOpeningBracket(")",{column:h.column+1,row:h.row});if(k!==null)return{text:"",selection:[1,1]}}}}),this.add("parens","deletion",function(a,b,c,d,e){var f=d.doc.getTextRange(e);if(!e.isMultiLine()&&f=="("){var g=d.doc.getLine(e.start.row),h=g.substring(e.start.column+1,e.start.column+2);if(h==")")return e.end.column++,e}}),this.add("string_dquotes","insertion",function(a,b,c,d,e){if(e=='"'||e=="'"){var f=e,g=c.getSelectionRange(),h=d.doc.getTextRange(g);if(h!=="")return{text:f+h+f,selection:!1};var i=c.getCursorPosition(),j=d.doc.getLine(i.row),k=j.substring(i.column-1,i.column);if(k=="\\")return null;var l=d.getTokens(g.start.row,g.start.row)[0].tokens,m=0,n,o=-1;for(var p=0;p<l.length;p++){n=l[p],n.type=="string"?o=-1:o<0&&(o=n.value.indexOf(f));if(n.value.length+m>g.start.column)break;m+=l[p].value.length}if(!n||o<0&&n.type!=="comment"&&(n.type!=="string"||g.start.column!==n.value.length+m-1&&n.value.lastIndexOf(f)===n.value.length-1))return{text:f+f,selection:[1,1]};if(n&&n.type==="string"){var q=j.substring(i.column,i.column+1);if(q==f)return{text:"",selection:[1,1]}}}}),this.add("string_dquotes","deletion",function(a,b,c,d,e){var f=d.doc.getTextRange(e);if(!e.isMultiLine()&&(f=='"'||f=="'")){var g=d.doc.getLine(e.start.row),h=g.substring(e.start.column+1,e.start.column+2);if(h=='"')return e.end.column++,e}})};d.inherits(f,e),b.CstyleBehaviour=f}),define("ace/mode/folding/cstyle",["require","exports","module","ace/lib/oop","ace/range","ace/mode/folding/fold_mode"],function(a,b,c){"use strict";var d=a("../../lib/oop"),e=a("../../range").Range,f=a("./fold_mode").FoldMode,g=b.FoldMode=function(){};d.inherits(g,f),function(){this.foldingStartMarker=/(\{|\[)[^\}\]]*$|^\s*(\/\*)/,this.foldingStopMarker=/^[^\[\{]*(\}|\])|^[\s\*]*(\*\/)/,this.getFoldWidgetRange=function(a,b,c){var d=a.getLine(c),f=d.match(this.foldingStartMarker);if(f){var g=f.index;if(f[1])return this.openingBracketBlock(a,f[1],c,g);var h=a.getCommentFoldRange(c,g+f[0].length);return h.end.column-=2,h}if(b!=="markbeginend")return;var f=d.match(this.foldingStopMarker);if(f){var g=f.index+f[0].length;if(f[2]){var h=a.getCommentFoldRange(c,g);return h.end.column-=2,h}var i={row:c,column:g},j=a.$findOpeningBracket(f[1],i);if(!j)return;return j.column++,i.column--,e.fromPoints(j,i)}}}.call(g.prototype)}),define("ace/mode/folding/fold_mode",["require","exports","module","ace/range"],function(a,b,c){"use strict";var d=a("../../range").Range,e=b.FoldMode=function(){};(function(){this.foldingStartMarker=null,this.foldingStopMarker=null,this.getFoldWidget=function(a,b,c){var d=a.getLine(c);return this.foldingStartMarker.test(d)?"start":b=="markbeginend"&&this.foldingStopMarker&&this.foldingStopMarker.test(d)?"end":""},this.getFoldWidgetRange=function(a,b,c){return null},this.indentationBlock=function(a,b,c){var e=/^\s*/,f=b,g=b,h=a.getLine(b),i=c||h.length,j=h.match(e)[0].length,k=a.getLength();while(++b<k){h=a.getLine(b);var l=h.match(e)[0].length;if(l==h.length)continue;if(l<=j)break;g=b}if(g>f){var m=a.getLine(g).length;return new d(f,i,g,m)}},this.openingBracketBlock=function(a,b,c,e){var f={row:c,column:e+1},g=a.$findClosingBracket(b,f);if(!g)return;var h=a.foldWidgets[g.row];return h==null&&(h=this.getFoldWidget(a,g.row)),h=="start"&&(g.row--,g.column=a.getLine(g.row).length),d.fromPoints(f,g)}}).call(e.prototype)})
\ No newline at end of file
diff --git a/apps/files_texteditor/js/aceeditor/mode-python-uncompressed.js b/apps/files_texteditor/js/aceeditor/mode-python-uncompressed.js
old mode 100755
new mode 100644
index ad0add6d775eb3b1d9ff164dfac55585be31106b..9a12decebda6fd3c28bd1053ddc0caa03029b8e5
--- a/apps/files_texteditor/js/aceeditor/mode-python-uncompressed.js
+++ b/apps/files_texteditor/js/aceeditor/mode-python-uncompressed.js
@@ -504,13 +504,3 @@ var FoldMode = exports.FoldMode = function() {};
 }).call(FoldMode.prototype);
 
 });
-;
-            (function() {
-                window.require(["ace/ace"], function(a) {
-                    if (!window.ace)
-                        window.ace = {};
-                    for (var key in a) if (a.hasOwnProperty(key))
-                        ace[key] = a[key];
-                });
-            })();
-        
\ No newline at end of file
diff --git a/apps/files_texteditor/js/aceeditor/mode-python.js b/apps/files_texteditor/js/aceeditor/mode-python.js
index 116f838b1d9a3b069e8ac2e9464414d27e75ed78..5401407f32bb3b9f46e6419839d15acad79268dd 100644
--- a/apps/files_texteditor/js/aceeditor/mode-python.js
+++ b/apps/files_texteditor/js/aceeditor/mode-python.js
@@ -1 +1 @@
-define("ace/mode/python",["require","exports","module","ace/lib/oop","ace/mode/text","ace/tokenizer","ace/mode/python_highlight_rules","ace/mode/folding/pythonic","ace/range"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("./text").Mode,f=a("../tokenizer").Tokenizer,g=a("./python_highlight_rules").PythonHighlightRules,h=a("./folding/pythonic").FoldMode,i=a("../range").Range,j=function(){this.$tokenizer=new f((new g).getRules()),this.foldingRules=new h("\\:")};d.inherits(j,e),function(){this.toggleCommentLines=function(a,b,c,d){var e=!0,f=/^(\s*)#/;for(var g=c;g<=d;g++)if(!f.test(b.getLine(g))){e=!1;break}if(e){var h=new i(0,0,0,0);for(var g=c;g<=d;g++){var j=b.getLine(g),k=j.match(f);h.start.row=g,h.end.row=g,h.end.column=k[0].length,b.replace(h,k[1])}}else b.indentRows(c,d,"#")},this.getNextLineIndent=function(a,b,c){var d=this.$getIndent(b),e=this.$tokenizer.getLineTokens(b,a),f=e.tokens;if(f.length&&f[f.length-1].type=="comment")return d;if(a=="start"){var g=b.match(/^.*[\{\(\[\:]\s*$/);g&&(d+=c)}return d};var a={pass:1,"return":1,raise:1,"break":1,"continue":1};this.checkOutdent=function(b,c,d){if(d!=="\r\n"&&d!=="\r"&&d!=="\n")return!1;var e=this.$tokenizer.getLineTokens(c.trim(),b).tokens;if(!e)return!1;do var f=e.pop();while(f&&(f.type=="comment"||f.type=="text"&&f.value.match(/^\s+$/)));return f?f.type=="keyword"&&a[f.value]:!1},this.autoOutdent=function(a,b,c){c+=1;var d=this.$getIndent(b.getLine(c)),e=b.getTabString();d.slice(-e.length)==e&&b.remove(new i(c,d.length-e.length,c,d.length))}}.call(j.prototype),b.Mode=j}),define("ace/mode/python_highlight_rules",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/mode/text_highlight_rules"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("../lib/lang"),f=a("./text_highlight_rules").TextHighlightRules,g=function(){var a=e.arrayToMap("and|as|assert|break|class|continue|def|del|elif|else|except|exec|finally|for|from|global|if|import|in|is|lambda|not|or|pass|print|raise|return|try|while|with|yield".split("|")),b=e.arrayToMap("True|False|None|NotImplemented|Ellipsis|__debug__".split("|")),c=e.arrayToMap("abs|divmod|input|open|staticmethod|all|enumerate|int|ord|str|any|eval|isinstance|pow|sum|basestring|execfile|issubclass|print|super|binfile|iter|property|tuple|bool|filter|len|range|type|bytearray|float|list|raw_input|unichr|callable|format|locals|reduce|unicode|chr|frozenset|long|reload|vars|classmethod|getattr|map|repr|xrange|cmp|globals|max|reversed|zip|compile|hasattr|memoryview|round|__import__|complex|hash|min|set|apply|delattr|help|next|setattr|buffer|dict|hex|object|slice|coerce|dir|id|oct|sorted|intern".split("|")),d=e.arrayToMap("".split("|")),f="(?:r|u|ur|R|U|UR|Ur|uR)?",g="(?:(?:[1-9]\\d*)|(?:0))",h="(?:0[oO]?[0-7]+)",i="(?:0[xX][\\dA-Fa-f]+)",j="(?:0[bB][01]+)",k="(?:"+g+"|"+h+"|"+i+"|"+j+")",l="(?:[eE][+-]?\\d+)",m="(?:\\.\\d+)",n="(?:\\d+)",o="(?:(?:"+n+"?"+m+")|(?:"+n+"\\.))",p="(?:(?:"+o+"|"+n+")"+l+")",q="(?:"+p+"|"+o+")";this.$rules={start:[{token:"comment",regex:"#.*$"},{token:"string",regex:f+'"{3}(?:[^\\\\]|\\\\.)*?"{3}'},{token:"string",merge:!0,regex:f+'"{3}.*$',next:"qqstring"},{token:"string",regex:f+'"(?:[^\\\\]|\\\\.)*?"'},{token:"string",regex:f+"'{3}(?:[^\\\\]|\\\\.)*?'{3}"},{token:"string",merge:!0,regex:f+"'{3}.*$",next:"qstring"},{token:"string",regex:f+"'(?:[^\\\\]|\\\\.)*?'"},{token:"constant.numeric",regex:"(?:"+q+"|\\d+)[jJ]\\b"},{token:"constant.numeric",regex:q},{token:"constant.numeric",regex:k+"[lL]\\b"},{token:"constant.numeric",regex:k+"\\b"},{token:function(e){return a.hasOwnProperty(e)?"keyword":b.hasOwnProperty(e)?"constant.language":d.hasOwnProperty(e)?"invalid.illegal":c.hasOwnProperty(e)?"support.function":e=="debugger"?"invalid.deprecated":"identifier"},regex:"[a-zA-Z_$][a-zA-Z0-9_$]*\\b"},{token:"keyword.operator",regex:"\\+|\\-|\\*|\\*\\*|\\/|\\/\\/|%|<<|>>|&|\\||\\^|~|<|>|<=|=>|==|!=|<>|="},{token:"lparen.paren",regex:"[\\[\\(\\{]"},{token:"paren.rparen",regex:"[\\]\\)\\}]"},{token:"text",regex:"\\s+"}],qqstring:[{token:"string",regex:'(?:[^\\\\]|\\\\.)*?"{3}',next:"start"},{token:"string",merge:!0,regex:".+"}],qstring:[{token:"string",regex:"(?:[^\\\\]|\\\\.)*?'{3}",next:"start"},{token:"string",merge:!0,regex:".+"}]}};d.inherits(g,f),b.PythonHighlightRules=g}),define("ace/mode/folding/pythonic",["require","exports","module","ace/lib/oop","ace/mode/folding/fold_mode"],function(a,b,c){"use strict";var d=a("../../lib/oop"),e=a("./fold_mode").FoldMode,f=b.FoldMode=function(a){this.foldingStartMarker=new RegExp("(?:([\\[{])|("+a+"))(?:\\s*)(?:#.*)?$")};d.inherits(f,e),function(){this.getFoldWidgetRange=function(a,b,c){var d=a.getLine(c),e=d.match(this.foldingStartMarker);if(e)return e[1]?this.openingBracketBlock(a,e[1],c,e.index):e[2]?this.indentationBlock(a,c,e.index+e[2].length):this.indentationBlock(a,c)}}.call(f.prototype)}),define("ace/mode/folding/fold_mode",["require","exports","module","ace/range"],function(a,b,c){"use strict";var d=a("../../range").Range,e=b.FoldMode=function(){};((function(){this.foldingStartMarker=null,this.foldingStopMarker=null,this.getFoldWidget=function(a,b,c){var d=a.getLine(c);return this.foldingStartMarker.test(d)?"start":b=="markbeginend"&&this.foldingStopMarker&&this.foldingStopMarker.test(d)?"end":""},this.getFoldWidgetRange=function(a,b,c){return null},this.indentationBlock=function(a,b,c){var e=/^\s*/,f=b,g=b,h=a.getLine(b),i=c||h.length,j=h.match(e)[0].length,k=a.getLength();while(++b<k){h=a.getLine(b);var l=h.match(e)[0].length;if(l==h.length)continue;if(l<=j)break;g=b}if(g>f){var m=a.getLine(g).length;return new d(f,i,g,m)}},this.openingBracketBlock=function(a,b,c,e){var f={row:c,column:e+1},g=a.$findClosingBracket(b,f);if(!g)return;var h=a.foldWidgets[g.row];return h==null&&(h=this.getFoldWidget(a,g.row)),h=="start"&&(g.row--,g.column=a.getLine(g.row).length),d.fromPoints(f,g)}})).call(e.prototype)}),function(){window.require(["ace/ace"],function(a){window.ace||(window.ace={});for(var b in a)a.hasOwnProperty(b)&&(ace[b]=a[b])})}()
\ No newline at end of file
+define("ace/mode/python",["require","exports","module","ace/lib/oop","ace/mode/text","ace/tokenizer","ace/mode/python_highlight_rules","ace/mode/folding/pythonic","ace/range"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("./text").Mode,f=a("../tokenizer").Tokenizer,g=a("./python_highlight_rules").PythonHighlightRules,h=a("./folding/pythonic").FoldMode,i=a("../range").Range,j=function(){this.$tokenizer=new f((new g).getRules()),this.foldingRules=new h("\\:")};d.inherits(j,e),function(){this.toggleCommentLines=function(a,b,c,d){var e=!0,f=/^(\s*)#/;for(var g=c;g<=d;g++)if(!f.test(b.getLine(g))){e=!1;break}if(e){var h=new i(0,0,0,0);for(var g=c;g<=d;g++){var j=b.getLine(g),k=j.match(f);h.start.row=g,h.end.row=g,h.end.column=k[0].length,b.replace(h,k[1])}}else b.indentRows(c,d,"#")},this.getNextLineIndent=function(a,b,c){var d=this.$getIndent(b),e=this.$tokenizer.getLineTokens(b,a),f=e.tokens;if(f.length&&f[f.length-1].type=="comment")return d;if(a=="start"){var g=b.match(/^.*[\{\(\[\:]\s*$/);g&&(d+=c)}return d};var a={pass:1,"return":1,raise:1,"break":1,"continue":1};this.checkOutdent=function(b,c,d){if(d!=="\r\n"&&d!=="\r"&&d!=="\n")return!1;var e=this.$tokenizer.getLineTokens(c.trim(),b).tokens;if(!e)return!1;do var f=e.pop();while(f&&(f.type=="comment"||f.type=="text"&&f.value.match(/^\s+$/)));return f?f.type=="keyword"&&a[f.value]:!1},this.autoOutdent=function(a,b,c){c+=1;var d=this.$getIndent(b.getLine(c)),e=b.getTabString();d.slice(-e.length)==e&&b.remove(new i(c,d.length-e.length,c,d.length))}}.call(j.prototype),b.Mode=j}),define("ace/mode/python_highlight_rules",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/mode/text_highlight_rules"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("../lib/lang"),f=a("./text_highlight_rules").TextHighlightRules,g=function(){var a=e.arrayToMap("and|as|assert|break|class|continue|def|del|elif|else|except|exec|finally|for|from|global|if|import|in|is|lambda|not|or|pass|print|raise|return|try|while|with|yield".split("|")),b=e.arrayToMap("True|False|None|NotImplemented|Ellipsis|__debug__".split("|")),c=e.arrayToMap("abs|divmod|input|open|staticmethod|all|enumerate|int|ord|str|any|eval|isinstance|pow|sum|basestring|execfile|issubclass|print|super|binfile|iter|property|tuple|bool|filter|len|range|type|bytearray|float|list|raw_input|unichr|callable|format|locals|reduce|unicode|chr|frozenset|long|reload|vars|classmethod|getattr|map|repr|xrange|cmp|globals|max|reversed|zip|compile|hasattr|memoryview|round|__import__|complex|hash|min|set|apply|delattr|help|next|setattr|buffer|dict|hex|object|slice|coerce|dir|id|oct|sorted|intern".split("|")),d=e.arrayToMap("".split("|")),f="(?:r|u|ur|R|U|UR|Ur|uR)?",g="(?:(?:[1-9]\\d*)|(?:0))",h="(?:0[oO]?[0-7]+)",i="(?:0[xX][\\dA-Fa-f]+)",j="(?:0[bB][01]+)",k="(?:"+g+"|"+h+"|"+i+"|"+j+")",l="(?:[eE][+-]?\\d+)",m="(?:\\.\\d+)",n="(?:\\d+)",o="(?:(?:"+n+"?"+m+")|(?:"+n+"\\.))",p="(?:(?:"+o+"|"+n+")"+l+")",q="(?:"+p+"|"+o+")";this.$rules={start:[{token:"comment",regex:"#.*$"},{token:"string",regex:f+'"{3}(?:[^\\\\]|\\\\.)*?"{3}'},{token:"string",merge:!0,regex:f+'"{3}.*$',next:"qqstring"},{token:"string",regex:f+'"(?:[^\\\\]|\\\\.)*?"'},{token:"string",regex:f+"'{3}(?:[^\\\\]|\\\\.)*?'{3}"},{token:"string",merge:!0,regex:f+"'{3}.*$",next:"qstring"},{token:"string",regex:f+"'(?:[^\\\\]|\\\\.)*?'"},{token:"constant.numeric",regex:"(?:"+q+"|\\d+)[jJ]\\b"},{token:"constant.numeric",regex:q},{token:"constant.numeric",regex:k+"[lL]\\b"},{token:"constant.numeric",regex:k+"\\b"},{token:function(e){return a.hasOwnProperty(e)?"keyword":b.hasOwnProperty(e)?"constant.language":d.hasOwnProperty(e)?"invalid.illegal":c.hasOwnProperty(e)?"support.function":e=="debugger"?"invalid.deprecated":"identifier"},regex:"[a-zA-Z_$][a-zA-Z0-9_$]*\\b"},{token:"keyword.operator",regex:"\\+|\\-|\\*|\\*\\*|\\/|\\/\\/|%|<<|>>|&|\\||\\^|~|<|>|<=|=>|==|!=|<>|="},{token:"lparen.paren",regex:"[\\[\\(\\{]"},{token:"paren.rparen",regex:"[\\]\\)\\}]"},{token:"text",regex:"\\s+"}],qqstring:[{token:"string",regex:'(?:[^\\\\]|\\\\.)*?"{3}',next:"start"},{token:"string",merge:!0,regex:".+"}],qstring:[{token:"string",regex:"(?:[^\\\\]|\\\\.)*?'{3}",next:"start"},{token:"string",merge:!0,regex:".+"}]}};d.inherits(g,f),b.PythonHighlightRules=g}),define("ace/mode/folding/pythonic",["require","exports","module","ace/lib/oop","ace/mode/folding/fold_mode"],function(a,b,c){"use strict";var d=a("../../lib/oop"),e=a("./fold_mode").FoldMode,f=b.FoldMode=function(a){this.foldingStartMarker=new RegExp("(?:([\\[{])|("+a+"))(?:\\s*)(?:#.*)?$")};d.inherits(f,e),function(){this.getFoldWidgetRange=function(a,b,c){var d=a.getLine(c),e=d.match(this.foldingStartMarker);if(e)return e[1]?this.openingBracketBlock(a,e[1],c,e.index):e[2]?this.indentationBlock(a,c,e.index+e[2].length):this.indentationBlock(a,c)}}.call(f.prototype)}),define("ace/mode/folding/fold_mode",["require","exports","module","ace/range"],function(a,b,c){"use strict";var d=a("../../range").Range,e=b.FoldMode=function(){};(function(){this.foldingStartMarker=null,this.foldingStopMarker=null,this.getFoldWidget=function(a,b,c){var d=a.getLine(c);return this.foldingStartMarker.test(d)?"start":b=="markbeginend"&&this.foldingStopMarker&&this.foldingStopMarker.test(d)?"end":""},this.getFoldWidgetRange=function(a,b,c){return null},this.indentationBlock=function(a,b,c){var e=/^\s*/,f=b,g=b,h=a.getLine(b),i=c||h.length,j=h.match(e)[0].length,k=a.getLength();while(++b<k){h=a.getLine(b);var l=h.match(e)[0].length;if(l==h.length)continue;if(l<=j)break;g=b}if(g>f){var m=a.getLine(g).length;return new d(f,i,g,m)}},this.openingBracketBlock=function(a,b,c,e){var f={row:c,column:e+1},g=a.$findClosingBracket(b,f);if(!g)return;var h=a.foldWidgets[g.row];return h==null&&(h=this.getFoldWidget(a,g.row)),h=="start"&&(g.row--,g.column=a.getLine(g.row).length),d.fromPoints(f,g)}}).call(e.prototype)})
\ No newline at end of file
diff --git a/apps/files_texteditor/js/aceeditor/mode-ruby-uncompressed.js b/apps/files_texteditor/js/aceeditor/mode-ruby-uncompressed.js
old mode 100755
new mode 100644
index 96de75ef8ba6c81600a4c748edd3429a96658086..fa2e06a522e14b2f57be92b5b7896fc0540c08ff
--- a/apps/files_texteditor/js/aceeditor/mode-ruby-uncompressed.js
+++ b/apps/files_texteditor/js/aceeditor/mode-ruby-uncompressed.js
@@ -389,13 +389,3 @@ var MatchingBraceOutdent = function() {};
 
 exports.MatchingBraceOutdent = MatchingBraceOutdent;
 });
-;
-            (function() {
-                window.require(["ace/ace"], function(a) {
-                    if (!window.ace)
-                        window.ace = {};
-                    for (var key in a) if (a.hasOwnProperty(key))
-                        ace[key] = a[key];
-                });
-            })();
-        
\ No newline at end of file
diff --git a/apps/files_texteditor/js/aceeditor/mode-ruby.js b/apps/files_texteditor/js/aceeditor/mode-ruby.js
index 2eeb69f5d5a7e960d2c1a329048c9f090f0cb5ef..7b9df32177e023523474be36194f47b239f72397 100644
--- a/apps/files_texteditor/js/aceeditor/mode-ruby.js
+++ b/apps/files_texteditor/js/aceeditor/mode-ruby.js
@@ -1 +1 @@
-define("ace/mode/ruby",["require","exports","module","ace/lib/oop","ace/mode/text","ace/tokenizer","ace/mode/ruby_highlight_rules","ace/mode/matching_brace_outdent","ace/range"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("./text").Mode,f=a("../tokenizer").Tokenizer,g=a("./ruby_highlight_rules").RubyHighlightRules,h=a("./matching_brace_outdent").MatchingBraceOutdent,i=a("../range").Range,j=function(){this.$tokenizer=new f((new g).getRules()),this.$outdent=new h};d.inherits(j,e),function(){this.toggleCommentLines=function(a,b,c,d){var e=!0,f=/^(\s*)#/;for(var g=c;g<=d;g++)if(!f.test(b.getLine(g))){e=!1;break}if(e){var h=new i(0,0,0,0);for(var g=c;g<=d;g++){var j=b.getLine(g),k=j.match(f);h.start.row=g,h.end.row=g,h.end.column=k[0].length,b.replace(h,k[1])}}else b.indentRows(c,d,"#")},this.getNextLineIndent=function(a,b,c){var d=this.$getIndent(b),e=this.$tokenizer.getLineTokens(b,a),f=e.tokens;if(f.length&&f[f.length-1].type=="comment")return d;if(a=="start"){var g=b.match(/^.*[\{\(\[]\s*$/);g&&(d+=c)}return d},this.checkOutdent=function(a,b,c){return this.$outdent.checkOutdent(b,c)},this.autoOutdent=function(a,b,c){this.$outdent.autoOutdent(b,c)}}.call(j.prototype),b.Mode=j}),define("ace/mode/ruby_highlight_rules",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/mode/text_highlight_rules"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("../lib/lang"),f=a("./text_highlight_rules").TextHighlightRules,g=function(){var a=e.arrayToMap("abort|Array|assert|assert_equal|assert_not_equal|assert_same|assert_not_same|assert_nil|assert_not_nil|assert_match|assert_no_match|assert_in_delta|assert_throws|assert_raise|assert_nothing_raised|assert_instance_of|assert_kind_of|assert_respond_to|assert_operator|assert_send|assert_difference|assert_no_difference|assert_recognizes|assert_generates|assert_response|assert_redirected_to|assert_template|assert_select|assert_select_email|assert_select_rjs|assert_select_encoded|css_select|at_exit|attr|attr_writer|attr_reader|attr_accessor|attr_accessible|autoload|binding|block_given?|callcc|caller|catch|chomp|chomp!|chop|chop!|defined?|delete_via_redirect|eval|exec|exit|exit!|fail|Float|flunk|follow_redirect!|fork|form_for|form_tag|format|gets|global_variables|gsub|gsub!|get_via_redirect|h|host!|https?|https!|include|Integer|lambda|link_to|link_to_unless_current|link_to_function|link_to_remote|load|local_variables|loop|open|open_session|p|print|printf|proc|putc|puts|post_via_redirect|put_via_redirect|raise|rand|raw|readline|readlines|redirect?|request_via_redirect|require|scan|select|set_trace_func|sleep|split|sprintf|srand|String|stylesheet_link_tag|syscall|system|sub|sub!|test|throw|trace_var|trap|untrace_var|atan2|cos|exp|frexp|ldexp|log|log10|sin|sqrt|tan|render|javascript_include_tag|csrf_meta_tag|label_tag|text_field_tag|submit_tag|check_box_tag|content_tag|radio_button_tag|text_area_tag|password_field_tag|hidden_field_tag|fields_for|select_tag|options_for_select|options_from_collection_for_select|collection_select|time_zone_select|select_date|select_time|select_datetime|date_select|time_select|datetime_select|select_year|select_month|select_day|select_hour|select_minute|select_second|file_field_tag|file_field|respond_to|skip_before_filter|around_filter|after_filter|verify|protect_from_forgery|rescue_from|helper_method|redirect_to|before_filter|send_data|send_file|validates_presence_of|validates_uniqueness_of|validates_length_of|validates_format_of|validates_acceptance_of|validates_associated|validates_exclusion_of|validates_inclusion_of|validates_numericality_of|validates_with|validates_each|authenticate_or_request_with_http_basic|authenticate_or_request_with_http_digest|filter_parameter_logging|match|get|post|resources|redirect|scope|assert_routing|translate|localize|extract_locale_from_tld|t|l|caches_page|expire_page|caches_action|expire_action|cache|expire_fragment|expire_cache_for|observe|cache_sweeper|has_many|has_one|belongs_to|has_and_belongs_to_many".split("|")),b=e.arrayToMap("alias|and|BEGIN|begin|break|case|class|def|defined|do|else|elsif|END|end|ensure|__FILE__|finally|for|gem|if|in|__LINE__|module|next|not|or|private|protected|public|redo|rescue|retry|return|super|then|undef|unless|until|when|while|yield".split("|")),c=e.arrayToMap("true|TRUE|false|FALSE|nil|NIL|ARGF|ARGV|DATA|ENV|RUBY_PLATFORM|RUBY_RELEASE_DATE|RUBY_VERSION|STDERR|STDIN|STDOUT|TOPLEVEL_BINDING".split("|")),d=e.arrayToMap("$DEBUG|$defout|$FILENAME|$LOAD_PATH|$SAFE|$stdin|$stdout|$stderr|$VERBOSE|$!|root_url|flash|session|cookies|params|request|response|logger".split("|"));this.$rules={start:[{token:"comment",regex:"#.*$"},{token:"comment",merge:!0,regex:"^=begin$",next:"comment"},{token:"string.regexp",regex:"[/](?:(?:\\[(?:\\\\]|[^\\]])+\\])|(?:\\\\/|[^\\]/]))*[/]\\w*\\s*(?=[).,;]|$)"},{token:"string",regex:'["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'},{token:"string",regex:"['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"},{token:"string",regex:"[`](?:(?:\\\\.)|(?:[^'\\\\]))*?[`]"},{token:"text",regex:"::"},{token:"variable.instancce",regex:"@{1,2}(?:[a-zA-Z_]|d)+"},{token:"variable.class",regex:"[A-Z](?:[a-zA-Z_]|d)+"},{token:"string",regex:"[:](?:[A-Za-z_]|[@$](?=[a-zA-Z0-9_]))[a-zA-Z0-9_]*[!=?]?"},{token:"constant.numeric",regex:"0[xX][0-9a-fA-F](?:[0-9a-fA-F]|_(?=[0-9a-fA-F]))*\\b"},{token:"constant.numeric",regex:"[+-]?\\d(?:\\d|_(?=\\d))*(?:(?:\\.\\d(?:\\d|_(?=\\d))*)?(?:[eE][+-]?\\d+)?)?\\b"},{token:"constant.language.boolean",regex:"(?:true|false)\\b"},{token:function(e){return e=="self"?"variable.language":b.hasOwnProperty(e)?"keyword":c.hasOwnProperty(e)?"constant.language":d.hasOwnProperty(e)?"variable.language":a.hasOwnProperty(e)?"support.function":e=="debugger"?"invalid.deprecated":"identifier"},regex:"[a-zA-Z_$][a-zA-Z0-9_$]*\\b"},{token:"keyword.operator",regex:"!|\\$|%|&|\\*|\\-\\-|\\-|\\+\\+|\\+|~|===|==|=|!=|!==|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\\|\\||\\?\\:|\\*=|%=|\\+=|\\-=|&=|\\^=|\\b(?:in|instanceof|new|delete|typeof|void)"},{token:"paren.lparen",regex:"[[({]"},{token:"paren.rparen",regex:"[\\])}]"},{token:"text",regex:"\\s+"}],comment:[{token:"comment",regex:"^=end$",next:"start"},{token:"comment",merge:!0,regex:".+"}]}};d.inherits(g,f),b.RubyHighlightRules=g}),define("ace/mode/matching_brace_outdent",["require","exports","module","ace/range"],function(a,b,c){"use strict";var d=a("../range").Range,e=function(){};((function(){this.checkOutdent=function(a,b){return/^\s+$/.test(a)?/^\s*\}/.test(b):!1},this.autoOutdent=function(a,b){var c=a.getLine(b),e=c.match(/^(\s*\})/);if(!e)return 0;var f=e[1].length,g=a.findMatchingBracket({row:b,column:f});if(!g||g.row==b)return 0;var h=this.$getIndent(a.getLine(g.row));a.replace(new d(b,0,b,f-1),h)},this.$getIndent=function(a){var b=a.match(/^(\s+)/);return b?b[1]:""}})).call(e.prototype),b.MatchingBraceOutdent=e}),function(){window.require(["ace/ace"],function(a){window.ace||(window.ace={});for(var b in a)a.hasOwnProperty(b)&&(ace[b]=a[b])})}()
\ No newline at end of file
+define("ace/mode/ruby",["require","exports","module","ace/lib/oop","ace/mode/text","ace/tokenizer","ace/mode/ruby_highlight_rules","ace/mode/matching_brace_outdent","ace/range"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("./text").Mode,f=a("../tokenizer").Tokenizer,g=a("./ruby_highlight_rules").RubyHighlightRules,h=a("./matching_brace_outdent").MatchingBraceOutdent,i=a("../range").Range,j=function(){this.$tokenizer=new f((new g).getRules()),this.$outdent=new h};d.inherits(j,e),function(){this.toggleCommentLines=function(a,b,c,d){var e=!0,f=/^(\s*)#/;for(var g=c;g<=d;g++)if(!f.test(b.getLine(g))){e=!1;break}if(e){var h=new i(0,0,0,0);for(var g=c;g<=d;g++){var j=b.getLine(g),k=j.match(f);h.start.row=g,h.end.row=g,h.end.column=k[0].length,b.replace(h,k[1])}}else b.indentRows(c,d,"#")},this.getNextLineIndent=function(a,b,c){var d=this.$getIndent(b),e=this.$tokenizer.getLineTokens(b,a),f=e.tokens;if(f.length&&f[f.length-1].type=="comment")return d;if(a=="start"){var g=b.match(/^.*[\{\(\[]\s*$/);g&&(d+=c)}return d},this.checkOutdent=function(a,b,c){return this.$outdent.checkOutdent(b,c)},this.autoOutdent=function(a,b,c){this.$outdent.autoOutdent(b,c)}}.call(j.prototype),b.Mode=j}),define("ace/mode/ruby_highlight_rules",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/mode/text_highlight_rules"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("../lib/lang"),f=a("./text_highlight_rules").TextHighlightRules,g=function(){var a=e.arrayToMap("abort|Array|assert|assert_equal|assert_not_equal|assert_same|assert_not_same|assert_nil|assert_not_nil|assert_match|assert_no_match|assert_in_delta|assert_throws|assert_raise|assert_nothing_raised|assert_instance_of|assert_kind_of|assert_respond_to|assert_operator|assert_send|assert_difference|assert_no_difference|assert_recognizes|assert_generates|assert_response|assert_redirected_to|assert_template|assert_select|assert_select_email|assert_select_rjs|assert_select_encoded|css_select|at_exit|attr|attr_writer|attr_reader|attr_accessor|attr_accessible|autoload|binding|block_given?|callcc|caller|catch|chomp|chomp!|chop|chop!|defined?|delete_via_redirect|eval|exec|exit|exit!|fail|Float|flunk|follow_redirect!|fork|form_for|form_tag|format|gets|global_variables|gsub|gsub!|get_via_redirect|h|host!|https?|https!|include|Integer|lambda|link_to|link_to_unless_current|link_to_function|link_to_remote|load|local_variables|loop|open|open_session|p|print|printf|proc|putc|puts|post_via_redirect|put_via_redirect|raise|rand|raw|readline|readlines|redirect?|request_via_redirect|require|scan|select|set_trace_func|sleep|split|sprintf|srand|String|stylesheet_link_tag|syscall|system|sub|sub!|test|throw|trace_var|trap|untrace_var|atan2|cos|exp|frexp|ldexp|log|log10|sin|sqrt|tan|render|javascript_include_tag|csrf_meta_tag|label_tag|text_field_tag|submit_tag|check_box_tag|content_tag|radio_button_tag|text_area_tag|password_field_tag|hidden_field_tag|fields_for|select_tag|options_for_select|options_from_collection_for_select|collection_select|time_zone_select|select_date|select_time|select_datetime|date_select|time_select|datetime_select|select_year|select_month|select_day|select_hour|select_minute|select_second|file_field_tag|file_field|respond_to|skip_before_filter|around_filter|after_filter|verify|protect_from_forgery|rescue_from|helper_method|redirect_to|before_filter|send_data|send_file|validates_presence_of|validates_uniqueness_of|validates_length_of|validates_format_of|validates_acceptance_of|validates_associated|validates_exclusion_of|validates_inclusion_of|validates_numericality_of|validates_with|validates_each|authenticate_or_request_with_http_basic|authenticate_or_request_with_http_digest|filter_parameter_logging|match|get|post|resources|redirect|scope|assert_routing|translate|localize|extract_locale_from_tld|t|l|caches_page|expire_page|caches_action|expire_action|cache|expire_fragment|expire_cache_for|observe|cache_sweeper|has_many|has_one|belongs_to|has_and_belongs_to_many".split("|")),b=e.arrayToMap("alias|and|BEGIN|begin|break|case|class|def|defined|do|else|elsif|END|end|ensure|__FILE__|finally|for|gem|if|in|__LINE__|module|next|not|or|private|protected|public|redo|rescue|retry|return|super|then|undef|unless|until|when|while|yield".split("|")),c=e.arrayToMap("true|TRUE|false|FALSE|nil|NIL|ARGF|ARGV|DATA|ENV|RUBY_PLATFORM|RUBY_RELEASE_DATE|RUBY_VERSION|STDERR|STDIN|STDOUT|TOPLEVEL_BINDING".split("|")),d=e.arrayToMap("$DEBUG|$defout|$FILENAME|$LOAD_PATH|$SAFE|$stdin|$stdout|$stderr|$VERBOSE|$!|root_url|flash|session|cookies|params|request|response|logger".split("|"));this.$rules={start:[{token:"comment",regex:"#.*$"},{token:"comment",merge:!0,regex:"^=begin$",next:"comment"},{token:"string.regexp",regex:"[/](?:(?:\\[(?:\\\\]|[^\\]])+\\])|(?:\\\\/|[^\\]/]))*[/]\\w*\\s*(?=[).,;]|$)"},{token:"string",regex:'["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'},{token:"string",regex:"['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"},{token:"string",regex:"[`](?:(?:\\\\.)|(?:[^'\\\\]))*?[`]"},{token:"text",regex:"::"},{token:"variable.instancce",regex:"@{1,2}(?:[a-zA-Z_]|d)+"},{token:"variable.class",regex:"[A-Z](?:[a-zA-Z_]|d)+"},{token:"string",regex:"[:](?:[A-Za-z_]|[@$](?=[a-zA-Z0-9_]))[a-zA-Z0-9_]*[!=?]?"},{token:"constant.numeric",regex:"0[xX][0-9a-fA-F](?:[0-9a-fA-F]|_(?=[0-9a-fA-F]))*\\b"},{token:"constant.numeric",regex:"[+-]?\\d(?:\\d|_(?=\\d))*(?:(?:\\.\\d(?:\\d|_(?=\\d))*)?(?:[eE][+-]?\\d+)?)?\\b"},{token:"constant.language.boolean",regex:"(?:true|false)\\b"},{token:function(e){return e=="self"?"variable.language":b.hasOwnProperty(e)?"keyword":c.hasOwnProperty(e)?"constant.language":d.hasOwnProperty(e)?"variable.language":a.hasOwnProperty(e)?"support.function":e=="debugger"?"invalid.deprecated":"identifier"},regex:"[a-zA-Z_$][a-zA-Z0-9_$]*\\b"},{token:"keyword.operator",regex:"!|\\$|%|&|\\*|\\-\\-|\\-|\\+\\+|\\+|~|===|==|=|!=|!==|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\\|\\||\\?\\:|\\*=|%=|\\+=|\\-=|&=|\\^=|\\b(?:in|instanceof|new|delete|typeof|void)"},{token:"paren.lparen",regex:"[[({]"},{token:"paren.rparen",regex:"[\\])}]"},{token:"text",regex:"\\s+"}],comment:[{token:"comment",regex:"^=end$",next:"start"},{token:"comment",merge:!0,regex:".+"}]}};d.inherits(g,f),b.RubyHighlightRules=g}),define("ace/mode/matching_brace_outdent",["require","exports","module","ace/range"],function(a,b,c){"use strict";var d=a("../range").Range,e=function(){};(function(){this.checkOutdent=function(a,b){return/^\s+$/.test(a)?/^\s*\}/.test(b):!1},this.autoOutdent=function(a,b){var c=a.getLine(b),e=c.match(/^(\s*\})/);if(!e)return 0;var f=e[1].length,g=a.findMatchingBracket({row:b,column:f});if(!g||g.row==b)return 0;var h=this.$getIndent(a.getLine(g.row));a.replace(new d(b,0,b,f-1),h)},this.$getIndent=function(a){var b=a.match(/^(\s+)/);return b?b[1]:""}}).call(e.prototype),b.MatchingBraceOutdent=e})
\ No newline at end of file
diff --git a/apps/files_texteditor/js/aceeditor/mode-scad-uncompressed.js b/apps/files_texteditor/js/aceeditor/mode-scad-uncompressed.js
old mode 100755
new mode 100644
index 07e368130ef80b3c9bd6b036bff53afb3aac17a8..c944ed17e177698f3b678413d962fa1ec11652f7
--- a/apps/files_texteditor/js/aceeditor/mode-scad-uncompressed.js
+++ b/apps/files_texteditor/js/aceeditor/mode-scad-uncompressed.js
@@ -529,12 +529,12 @@ var CstyleBehaviour = function () {
                 return {
                     text: '{' + selected + '}',
                     selection: false
-                }
+                };
             } else {
                 return {
                     text: '{}',
                     selection: [1, 1]
-                }
+                };
             }
         } else if (text == '}') {
             var cursor = editor.getCursorPosition();
@@ -546,7 +546,7 @@ var CstyleBehaviour = function () {
                     return {
                         text: '',
                         selection: [1, 1]
-                    }
+                    };
                 }
             }
         } else if (text == "\n") {
@@ -564,7 +564,7 @@ var CstyleBehaviour = function () {
                 return {
                     text: '\n' + indent + '\n' + next_indent,
                     selection: [1, indent.length, 1, indent.length]
-                }
+                };
             }
         }
     });
@@ -589,12 +589,12 @@ var CstyleBehaviour = function () {
                 return {
                     text: '(' + selected + ')',
                     selection: false
-                }
+                };
             } else {
                 return {
                     text: '()',
                     selection: [1, 1]
-                }
+                };
             }
         } else if (text == ')') {
             var cursor = editor.getCursorPosition();
@@ -606,7 +606,7 @@ var CstyleBehaviour = function () {
                     return {
                         text: '',
                         selection: [1, 1]
-                    }
+                    };
                 }
             }
         }
@@ -625,14 +625,15 @@ var CstyleBehaviour = function () {
     });
 
     this.add("string_dquotes", "insertion", function (state, action, editor, session, text) {
-        if (text == '"') {
+        if (text == '"' || text == "'") {
+            var quote = text;
             var selection = editor.getSelectionRange();
             var selected = session.doc.getTextRange(selection);
             if (selected !== "") {
                 return {
-                    text: '"' + selected + '"',
+                    text: quote + selected + quote,
                     selection: false
-                }
+                };
             } else {
                 var cursor = editor.getCursorPosition();
                 var line = session.doc.getLine(cursor.row);
@@ -653,7 +654,7 @@ var CstyleBehaviour = function () {
                     if (token.type == "string") {
                       quotepos = -1;
                     } else if (quotepos < 0) {
-                      quotepos = token.value.indexOf('"');
+                      quotepos = token.value.indexOf(quote);
                     }
                     if ((token.value.length + col) > selection.start.column) {
                         break;
@@ -662,19 +663,19 @@ var CstyleBehaviour = function () {
                 }
 
                 // Try and be smart about when we auto insert.
-                if (!token || (quotepos < 0 && token.type !== "comment" && (token.type !== "string" || ((selection.start.column !== token.value.length+col-1) && token.value.lastIndexOf('"') === token.value.length-1)))) {
+                if (!token || (quotepos < 0 && token.type !== "comment" && (token.type !== "string" || ((selection.start.column !== token.value.length+col-1) && token.value.lastIndexOf(quote) === token.value.length-1)))) {
                     return {
-                        text: '""',
+                        text: quote + quote,
                         selection: [1,1]
-                    }
+                    };
                 } else if (token && token.type === "string") {
                     // Ignore input and move right one if we're typing over the closing quote.
                     var rightChar = line.substring(cursor.column, cursor.column + 1);
-                    if (rightChar == '"') {
+                    if (rightChar == quote) {
                         return {
                             text: '',
                             selection: [1, 1]
-                        }
+                        };
                     }
                 }
             }
@@ -683,7 +684,7 @@ var CstyleBehaviour = function () {
 
     this.add("string_dquotes", "deletion", function (state, action, editor, session, range) {
         var selected = session.doc.getTextRange(range);
-        if (!range.isMultiLine() && selected == '"') {
+        if (!range.isMultiLine() && (selected == '"' || selected == "'")) {
             var line = session.doc.getLine(range.start.row);
             var rightChar = line.substring(range.start.column + 1, range.start.column + 2);
             if (rightChar == '"') {
@@ -693,7 +694,8 @@ var CstyleBehaviour = function () {
         }
     });
 
-}
+};
+
 oop.inherits(CstyleBehaviour, Behaviour);
 
 exports.CstyleBehaviour = CstyleBehaviour;
@@ -904,13 +906,3 @@ var FoldMode = exports.FoldMode = function() {};
 }).call(FoldMode.prototype);
 
 });
-;
-            (function() {
-                window.require(["ace/ace"], function(a) {
-                    if (!window.ace)
-                        window.ace = {};
-                    for (var key in a) if (a.hasOwnProperty(key))
-                        ace[key] = a[key];
-                });
-            })();
-        
\ No newline at end of file
diff --git a/apps/files_texteditor/js/aceeditor/mode-scad.js b/apps/files_texteditor/js/aceeditor/mode-scad.js
index 1deeef115249862b5a0b4e174b1a77064007074b..eb324e4dc77e7f870badd9df8ed86c1ff9fd28f8 100644
--- a/apps/files_texteditor/js/aceeditor/mode-scad.js
+++ b/apps/files_texteditor/js/aceeditor/mode-scad.js
@@ -1 +1 @@
-define("ace/mode/scad",["require","exports","module","ace/lib/oop","ace/mode/text","ace/tokenizer","ace/mode/scad_highlight_rules","ace/mode/matching_brace_outdent","ace/range","ace/mode/behaviour/cstyle","ace/mode/folding/cstyle"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("./text").Mode,f=a("../tokenizer").Tokenizer,g=a("./scad_highlight_rules").scadHighlightRules,h=a("./matching_brace_outdent").MatchingBraceOutdent,i=a("../range").Range,j=a("./behaviour/cstyle").CstyleBehaviour,k=a("./folding/cstyle").FoldMode,l=function(){this.$tokenizer=new f((new g).getRules()),this.$outdent=new h,this.$behaviour=new j,this.foldingRules=new k};d.inherits(l,e),function(){this.toggleCommentLines=function(a,b,c,d){var e=!0,f=/^(\s*)\/\//;for(var g=c;g<=d;g++)if(!f.test(b.getLine(g))){e=!1;break}if(e){var h=new i(0,0,0,0);for(var g=c;g<=d;g++){var j=b.getLine(g),k=j.match(f);h.start.row=g,h.end.row=g,h.end.column=k[0].length,b.replace(h,k[1])}}else b.indentRows(c,d,"//")},this.getNextLineIndent=function(a,b,c){var d=this.$getIndent(b),e=this.$tokenizer.getLineTokens(b,a),f=e.tokens,g=e.state;if(f.length&&f[f.length-1].type=="comment")return d;if(a=="start"){var h=b.match(/^.*[\{\(\[]\s*$/);h&&(d+=c)}else if(a=="doc-start"){if(g=="start")return"";var h=b.match(/^\s*(\/?)\*/);h&&(h[1]&&(d+=" "),d+="* ")}return d},this.checkOutdent=function(a,b,c){return this.$outdent.checkOutdent(b,c)},this.autoOutdent=function(a,b,c){this.$outdent.autoOutdent(b,c)}}.call(l.prototype),b.Mode=l}),define("ace/mode/scad_highlight_rules",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/mode/doc_comment_highlight_rules","ace/mode/text_highlight_rules"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("../lib/lang"),f=a("./doc_comment_highlight_rules").DocCommentHighlightRules,g=a("./text_highlight_rules").TextHighlightRules,h=function(){var a=e.arrayToMap("module|if|else|for".split("|")),b=e.arrayToMap("NULL".split("|"));this.$rules={start:[{token:"comment",regex:"\\/\\/.*$"},(new f).getStartRule("start"),{token:"comment",merge:!0,regex:"\\/\\*",next:"comment"},{token:"string",regex:'["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'},{token:"string",regex:'["].*\\\\$',next:"qqstring"},{token:"string",regex:"['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"},{token:"string",regex:"['].*\\\\$",next:"qstring"},{token:"constant.numeric",regex:"0[xX][0-9a-fA-F]+\\b"},{token:"constant.numeric",regex:"[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"},{token:"constant",regex:"<[a-zA-Z0-9.]+>"},{token:"keyword",regex:"(?:use|include)"},{token:function(c){return c=="this"?"variable.language":a.hasOwnProperty(c)?"keyword":b.hasOwnProperty(c)?"constant.language":"identifier"},regex:"[a-zA-Z_$][a-zA-Z0-9_$]*\\b"},{token:"keyword.operator",regex:"!|\\$|%|&|\\*|\\-\\-|\\-|\\+\\+|\\+|~|==|=|!=|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\\|\\||\\?\\:|\\*=|%=|\\+=|\\-=|&=|\\^=|\\b(?:in|new|delete|typeof|void)"},{token:"paren.lparen",regex:"[[({]"},{token:"paren.rparen",regex:"[\\])}]"},{token:"text",regex:"\\s+"}],comment:[{token:"comment",regex:".*?\\*\\/",next:"start"},{token:"comment",merge:!0,regex:".+"}],qqstring:[{token:"string",regex:'(?:(?:\\\\.)|(?:[^"\\\\]))*?"',next:"start"},{token:"string",merge:!0,regex:".+"}],qstring:[{token:"string",regex:"(?:(?:\\\\.)|(?:[^'\\\\]))*?'",next:"start"},{token:"string",merge:!0,regex:".+"}]},this.embedRules(f,"doc-",[(new f).getEndRule("start")])};d.inherits(h,g),b.scadHighlightRules=h}),define("ace/mode/doc_comment_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("./text_highlight_rules").TextHighlightRules,f=function(){this.$rules={start:[{token:"comment.doc.tag",regex:"@[\\w\\d_]+"},{token:"comment.doc",merge:!0,regex:"\\s+"},{token:"comment.doc",merge:!0,regex:"TODO"},{token:"comment.doc",merge:!0,regex:"[^@\\*]+"},{token:"comment.doc",merge:!0,regex:"."}]}};d.inherits(f,e),function(){this.getStartRule=function(a){return{token:"comment.doc",merge:!0,regex:"\\/\\*(?=\\*)",next:a}},this.getEndRule=function(a){return{token:"comment.doc",merge:!0,regex:"\\*\\/",next:a}}}.call(f.prototype),b.DocCommentHighlightRules=f}),define("ace/mode/matching_brace_outdent",["require","exports","module","ace/range"],function(a,b,c){"use strict";var d=a("../range").Range,e=function(){};((function(){this.checkOutdent=function(a,b){return/^\s+$/.test(a)?/^\s*\}/.test(b):!1},this.autoOutdent=function(a,b){var c=a.getLine(b),e=c.match(/^(\s*\})/);if(!e)return 0;var f=e[1].length,g=a.findMatchingBracket({row:b,column:f});if(!g||g.row==b)return 0;var h=this.$getIndent(a.getLine(g.row));a.replace(new d(b,0,b,f-1),h)},this.$getIndent=function(a){var b=a.match(/^(\s+)/);return b?b[1]:""}})).call(e.prototype),b.MatchingBraceOutdent=e}),define("ace/mode/behaviour/cstyle",["require","exports","module","ace/lib/oop","ace/mode/behaviour"],function(a,b,c){"use strict";var d=a("../../lib/oop"),e=a("../behaviour").Behaviour,f=function(){this.add("braces","insertion",function(a,b,c,d,e){if(e=="{"){var f=c.getSelectionRange(),g=d.doc.getTextRange(f);return g!==""?{text:"{"+g+"}",selection:!1}:{text:"{}",selection:[1,1]}}if(e=="}"){var h=c.getCursorPosition(),i=d.doc.getLine(h.row),j=i.substring(h.column,h.column+1);if(j=="}"){var k=d.$findOpeningBracket("}",{column:h.column+1,row:h.row});if(k!==null)return{text:"",selection:[1,1]}}}else if(e=="\n"){var h=c.getCursorPosition(),i=d.doc.getLine(h.row),j=i.substring(h.column,h.column+1);if(j=="}"){var l=d.findMatchingBracket({row:h.row,column:h.column+1});if(!l)return null;var m=this.getNextLineIndent(a,i.substring(0,i.length-1),d.getTabString()),n=this.$getIndent(d.doc.getLine(l.row));return{text:"\n"+m+"\n"+n,selection:[1,m.length,1,m.length]}}}}),this.add("braces","deletion",function(a,b,c,d,e){var f=d.doc.getTextRange(e);if(!e.isMultiLine()&&f=="{"){var g=d.doc.getLine(e.start.row),h=g.substring(e.end.column,e.end.column+1);if(h=="}")return e.end.column++,e}}),this.add("parens","insertion",function(a,b,c,d,e){if(e=="("){var f=c.getSelectionRange(),g=d.doc.getTextRange(f);return g!==""?{text:"("+g+")",selection:!1}:{text:"()",selection:[1,1]}}if(e==")"){var h=c.getCursorPosition(),i=d.doc.getLine(h.row),j=i.substring(h.column,h.column+1);if(j==")"){var k=d.$findOpeningBracket(")",{column:h.column+1,row:h.row});if(k!==null)return{text:"",selection:[1,1]}}}}),this.add("parens","deletion",function(a,b,c,d,e){var f=d.doc.getTextRange(e);if(!e.isMultiLine()&&f=="("){var g=d.doc.getLine(e.start.row),h=g.substring(e.start.column+1,e.start.column+2);if(h==")")return e.end.column++,e}}),this.add("string_dquotes","insertion",function(a,b,c,d,e){if(e=='"'){var f=c.getSelectionRange(),g=d.doc.getTextRange(f);if(g!=="")return{text:'"'+g+'"',selection:!1};var h=c.getCursorPosition(),i=d.doc.getLine(h.row),j=i.substring(h.column-1,h.column);if(j=="\\")return null;var k=d.getTokens(f.start.row,f.start.row)[0].tokens,l=0,m,n=-1;for(var o=0;o<k.length;o++){m=k[o],m.type=="string"?n=-1:n<0&&(n=m.value.indexOf('"'));if(m.value.length+l>f.start.column)break;l+=k[o].value.length}if(!m||n<0&&m.type!=="comment"&&(m.type!=="string"||f.start.column!==m.value.length+l-1&&m.value.lastIndexOf('"')===m.value.length-1))return{text:'""',selection:[1,1]};if(m&&m.type==="string"){var p=i.substring(h.column,h.column+1);if(p=='"')return{text:"",selection:[1,1]}}}}),this.add("string_dquotes","deletion",function(a,b,c,d,e){var f=d.doc.getTextRange(e);if(!e.isMultiLine()&&f=='"'){var g=d.doc.getLine(e.start.row),h=g.substring(e.start.column+1,e.start.column+2);if(h=='"')return e.end.column++,e}})};d.inherits(f,e),b.CstyleBehaviour=f}),define("ace/mode/folding/cstyle",["require","exports","module","ace/lib/oop","ace/range","ace/mode/folding/fold_mode"],function(a,b,c){"use strict";var d=a("../../lib/oop"),e=a("../../range").Range,f=a("./fold_mode").FoldMode,g=b.FoldMode=function(){};d.inherits(g,f),function(){this.foldingStartMarker=/(\{|\[)[^\}\]]*$|^\s*(\/\*)/,this.foldingStopMarker=/^[^\[\{]*(\}|\])|^[\s\*]*(\*\/)/,this.getFoldWidgetRange=function(a,b,c){var d=a.getLine(c),f=d.match(this.foldingStartMarker);if(f){var g=f.index;if(f[1])return this.openingBracketBlock(a,f[1],c,g);var h=a.getCommentFoldRange(c,g+f[0].length);return h.end.column-=2,h}if(b!=="markbeginend")return;var f=d.match(this.foldingStopMarker);if(f){var g=f.index+f[0].length;if(f[2]){var h=a.getCommentFoldRange(c,g);return h.end.column-=2,h}var i={row:c,column:g},j=a.$findOpeningBracket(f[1],i);if(!j)return;return j.column++,i.column--,e.fromPoints(j,i)}}}.call(g.prototype)}),define("ace/mode/folding/fold_mode",["require","exports","module","ace/range"],function(a,b,c){"use strict";var d=a("../../range").Range,e=b.FoldMode=function(){};((function(){this.foldingStartMarker=null,this.foldingStopMarker=null,this.getFoldWidget=function(a,b,c){var d=a.getLine(c);return this.foldingStartMarker.test(d)?"start":b=="markbeginend"&&this.foldingStopMarker&&this.foldingStopMarker.test(d)?"end":""},this.getFoldWidgetRange=function(a,b,c){return null},this.indentationBlock=function(a,b,c){var e=/^\s*/,f=b,g=b,h=a.getLine(b),i=c||h.length,j=h.match(e)[0].length,k=a.getLength();while(++b<k){h=a.getLine(b);var l=h.match(e)[0].length;if(l==h.length)continue;if(l<=j)break;g=b}if(g>f){var m=a.getLine(g).length;return new d(f,i,g,m)}},this.openingBracketBlock=function(a,b,c,e){var f={row:c,column:e+1},g=a.$findClosingBracket(b,f);if(!g)return;var h=a.foldWidgets[g.row];return h==null&&(h=this.getFoldWidget(a,g.row)),h=="start"&&(g.row--,g.column=a.getLine(g.row).length),d.fromPoints(f,g)}})).call(e.prototype)}),function(){window.require(["ace/ace"],function(a){window.ace||(window.ace={});for(var b in a)a.hasOwnProperty(b)&&(ace[b]=a[b])})}()
\ No newline at end of file
+define("ace/mode/scad",["require","exports","module","ace/lib/oop","ace/mode/text","ace/tokenizer","ace/mode/scad_highlight_rules","ace/mode/matching_brace_outdent","ace/range","ace/mode/behaviour/cstyle","ace/mode/folding/cstyle"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("./text").Mode,f=a("../tokenizer").Tokenizer,g=a("./scad_highlight_rules").scadHighlightRules,h=a("./matching_brace_outdent").MatchingBraceOutdent,i=a("../range").Range,j=a("./behaviour/cstyle").CstyleBehaviour,k=a("./folding/cstyle").FoldMode,l=function(){this.$tokenizer=new f((new g).getRules()),this.$outdent=new h,this.$behaviour=new j,this.foldingRules=new k};d.inherits(l,e),function(){this.toggleCommentLines=function(a,b,c,d){var e=!0,f=/^(\s*)\/\//;for(var g=c;g<=d;g++)if(!f.test(b.getLine(g))){e=!1;break}if(e){var h=new i(0,0,0,0);for(var g=c;g<=d;g++){var j=b.getLine(g),k=j.match(f);h.start.row=g,h.end.row=g,h.end.column=k[0].length,b.replace(h,k[1])}}else b.indentRows(c,d,"//")},this.getNextLineIndent=function(a,b,c){var d=this.$getIndent(b),e=this.$tokenizer.getLineTokens(b,a),f=e.tokens,g=e.state;if(f.length&&f[f.length-1].type=="comment")return d;if(a=="start"){var h=b.match(/^.*[\{\(\[]\s*$/);h&&(d+=c)}else if(a=="doc-start"){if(g=="start")return"";var h=b.match(/^\s*(\/?)\*/);h&&(h[1]&&(d+=" "),d+="* ")}return d},this.checkOutdent=function(a,b,c){return this.$outdent.checkOutdent(b,c)},this.autoOutdent=function(a,b,c){this.$outdent.autoOutdent(b,c)}}.call(l.prototype),b.Mode=l}),define("ace/mode/scad_highlight_rules",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/mode/doc_comment_highlight_rules","ace/mode/text_highlight_rules"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("../lib/lang"),f=a("./doc_comment_highlight_rules").DocCommentHighlightRules,g=a("./text_highlight_rules").TextHighlightRules,h=function(){var a=e.arrayToMap("module|if|else|for".split("|")),b=e.arrayToMap("NULL".split("|"));this.$rules={start:[{token:"comment",regex:"\\/\\/.*$"},(new f).getStartRule("start"),{token:"comment",merge:!0,regex:"\\/\\*",next:"comment"},{token:"string",regex:'["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'},{token:"string",regex:'["].*\\\\$',next:"qqstring"},{token:"string",regex:"['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"},{token:"string",regex:"['].*\\\\$",next:"qstring"},{token:"constant.numeric",regex:"0[xX][0-9a-fA-F]+\\b"},{token:"constant.numeric",regex:"[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"},{token:"constant",regex:"<[a-zA-Z0-9.]+>"},{token:"keyword",regex:"(?:use|include)"},{token:function(c){return c=="this"?"variable.language":a.hasOwnProperty(c)?"keyword":b.hasOwnProperty(c)?"constant.language":"identifier"},regex:"[a-zA-Z_$][a-zA-Z0-9_$]*\\b"},{token:"keyword.operator",regex:"!|\\$|%|&|\\*|\\-\\-|\\-|\\+\\+|\\+|~|==|=|!=|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\\|\\||\\?\\:|\\*=|%=|\\+=|\\-=|&=|\\^=|\\b(?:in|new|delete|typeof|void)"},{token:"paren.lparen",regex:"[[({]"},{token:"paren.rparen",regex:"[\\])}]"},{token:"text",regex:"\\s+"}],comment:[{token:"comment",regex:".*?\\*\\/",next:"start"},{token:"comment",merge:!0,regex:".+"}],qqstring:[{token:"string",regex:'(?:(?:\\\\.)|(?:[^"\\\\]))*?"',next:"start"},{token:"string",merge:!0,regex:".+"}],qstring:[{token:"string",regex:"(?:(?:\\\\.)|(?:[^'\\\\]))*?'",next:"start"},{token:"string",merge:!0,regex:".+"}]},this.embedRules(f,"doc-",[(new f).getEndRule("start")])};d.inherits(h,g),b.scadHighlightRules=h}),define("ace/mode/doc_comment_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("./text_highlight_rules").TextHighlightRules,f=function(){this.$rules={start:[{token:"comment.doc.tag",regex:"@[\\w\\d_]+"},{token:"comment.doc",merge:!0,regex:"\\s+"},{token:"comment.doc",merge:!0,regex:"TODO"},{token:"comment.doc",merge:!0,regex:"[^@\\*]+"},{token:"comment.doc",merge:!0,regex:"."}]}};d.inherits(f,e),function(){this.getStartRule=function(a){return{token:"comment.doc",merge:!0,regex:"\\/\\*(?=\\*)",next:a}},this.getEndRule=function(a){return{token:"comment.doc",merge:!0,regex:"\\*\\/",next:a}}}.call(f.prototype),b.DocCommentHighlightRules=f}),define("ace/mode/matching_brace_outdent",["require","exports","module","ace/range"],function(a,b,c){"use strict";var d=a("../range").Range,e=function(){};(function(){this.checkOutdent=function(a,b){return/^\s+$/.test(a)?/^\s*\}/.test(b):!1},this.autoOutdent=function(a,b){var c=a.getLine(b),e=c.match(/^(\s*\})/);if(!e)return 0;var f=e[1].length,g=a.findMatchingBracket({row:b,column:f});if(!g||g.row==b)return 0;var h=this.$getIndent(a.getLine(g.row));a.replace(new d(b,0,b,f-1),h)},this.$getIndent=function(a){var b=a.match(/^(\s+)/);return b?b[1]:""}}).call(e.prototype),b.MatchingBraceOutdent=e}),define("ace/mode/behaviour/cstyle",["require","exports","module","ace/lib/oop","ace/mode/behaviour"],function(a,b,c){"use strict";var d=a("../../lib/oop"),e=a("../behaviour").Behaviour,f=function(){this.add("braces","insertion",function(a,b,c,d,e){if(e=="{"){var f=c.getSelectionRange(),g=d.doc.getTextRange(f);return g!==""?{text:"{"+g+"}",selection:!1}:{text:"{}",selection:[1,1]}}if(e=="}"){var h=c.getCursorPosition(),i=d.doc.getLine(h.row),j=i.substring(h.column,h.column+1);if(j=="}"){var k=d.$findOpeningBracket("}",{column:h.column+1,row:h.row});if(k!==null)return{text:"",selection:[1,1]}}}else if(e=="\n"){var h=c.getCursorPosition(),i=d.doc.getLine(h.row),j=i.substring(h.column,h.column+1);if(j=="}"){var l=d.findMatchingBracket({row:h.row,column:h.column+1});if(!l)return null;var m=this.getNextLineIndent(a,i.substring(0,i.length-1),d.getTabString()),n=this.$getIndent(d.doc.getLine(l.row));return{text:"\n"+m+"\n"+n,selection:[1,m.length,1,m.length]}}}}),this.add("braces","deletion",function(a,b,c,d,e){var f=d.doc.getTextRange(e);if(!e.isMultiLine()&&f=="{"){var g=d.doc.getLine(e.start.row),h=g.substring(e.end.column,e.end.column+1);if(h=="}")return e.end.column++,e}}),this.add("parens","insertion",function(a,b,c,d,e){if(e=="("){var f=c.getSelectionRange(),g=d.doc.getTextRange(f);return g!==""?{text:"("+g+")",selection:!1}:{text:"()",selection:[1,1]}}if(e==")"){var h=c.getCursorPosition(),i=d.doc.getLine(h.row),j=i.substring(h.column,h.column+1);if(j==")"){var k=d.$findOpeningBracket(")",{column:h.column+1,row:h.row});if(k!==null)return{text:"",selection:[1,1]}}}}),this.add("parens","deletion",function(a,b,c,d,e){var f=d.doc.getTextRange(e);if(!e.isMultiLine()&&f=="("){var g=d.doc.getLine(e.start.row),h=g.substring(e.start.column+1,e.start.column+2);if(h==")")return e.end.column++,e}}),this.add("string_dquotes","insertion",function(a,b,c,d,e){if(e=='"'||e=="'"){var f=e,g=c.getSelectionRange(),h=d.doc.getTextRange(g);if(h!=="")return{text:f+h+f,selection:!1};var i=c.getCursorPosition(),j=d.doc.getLine(i.row),k=j.substring(i.column-1,i.column);if(k=="\\")return null;var l=d.getTokens(g.start.row,g.start.row)[0].tokens,m=0,n,o=-1;for(var p=0;p<l.length;p++){n=l[p],n.type=="string"?o=-1:o<0&&(o=n.value.indexOf(f));if(n.value.length+m>g.start.column)break;m+=l[p].value.length}if(!n||o<0&&n.type!=="comment"&&(n.type!=="string"||g.start.column!==n.value.length+m-1&&n.value.lastIndexOf(f)===n.value.length-1))return{text:f+f,selection:[1,1]};if(n&&n.type==="string"){var q=j.substring(i.column,i.column+1);if(q==f)return{text:"",selection:[1,1]}}}}),this.add("string_dquotes","deletion",function(a,b,c,d,e){var f=d.doc.getTextRange(e);if(!e.isMultiLine()&&(f=='"'||f=="'")){var g=d.doc.getLine(e.start.row),h=g.substring(e.start.column+1,e.start.column+2);if(h=='"')return e.end.column++,e}})};d.inherits(f,e),b.CstyleBehaviour=f}),define("ace/mode/folding/cstyle",["require","exports","module","ace/lib/oop","ace/range","ace/mode/folding/fold_mode"],function(a,b,c){"use strict";var d=a("../../lib/oop"),e=a("../../range").Range,f=a("./fold_mode").FoldMode,g=b.FoldMode=function(){};d.inherits(g,f),function(){this.foldingStartMarker=/(\{|\[)[^\}\]]*$|^\s*(\/\*)/,this.foldingStopMarker=/^[^\[\{]*(\}|\])|^[\s\*]*(\*\/)/,this.getFoldWidgetRange=function(a,b,c){var d=a.getLine(c),f=d.match(this.foldingStartMarker);if(f){var g=f.index;if(f[1])return this.openingBracketBlock(a,f[1],c,g);var h=a.getCommentFoldRange(c,g+f[0].length);return h.end.column-=2,h}if(b!=="markbeginend")return;var f=d.match(this.foldingStopMarker);if(f){var g=f.index+f[0].length;if(f[2]){var h=a.getCommentFoldRange(c,g);return h.end.column-=2,h}var i={row:c,column:g},j=a.$findOpeningBracket(f[1],i);if(!j)return;return j.column++,i.column--,e.fromPoints(j,i)}}}.call(g.prototype)}),define("ace/mode/folding/fold_mode",["require","exports","module","ace/range"],function(a,b,c){"use strict";var d=a("../../range").Range,e=b.FoldMode=function(){};(function(){this.foldingStartMarker=null,this.foldingStopMarker=null,this.getFoldWidget=function(a,b,c){var d=a.getLine(c);return this.foldingStartMarker.test(d)?"start":b=="markbeginend"&&this.foldingStopMarker&&this.foldingStopMarker.test(d)?"end":""},this.getFoldWidgetRange=function(a,b,c){return null},this.indentationBlock=function(a,b,c){var e=/^\s*/,f=b,g=b,h=a.getLine(b),i=c||h.length,j=h.match(e)[0].length,k=a.getLength();while(++b<k){h=a.getLine(b);var l=h.match(e)[0].length;if(l==h.length)continue;if(l<=j)break;g=b}if(g>f){var m=a.getLine(g).length;return new d(f,i,g,m)}},this.openingBracketBlock=function(a,b,c,e){var f={row:c,column:e+1},g=a.$findClosingBracket(b,f);if(!g)return;var h=a.foldWidgets[g.row];return h==null&&(h=this.getFoldWidget(a,g.row)),h=="start"&&(g.row--,g.column=a.getLine(g.row).length),d.fromPoints(f,g)}}).call(e.prototype)})
\ No newline at end of file
diff --git a/apps/files_texteditor/js/aceeditor/mode-scala-uncompressed.js b/apps/files_texteditor/js/aceeditor/mode-scala-uncompressed.js
old mode 100755
new mode 100644
index 098b14e066c708f23f3b8c25b8416ee09b2bd798..fb6e95f6f684204689f8c71cfffeac08d53ca00e
--- a/apps/files_texteditor/js/aceeditor/mode-scala-uncompressed.js
+++ b/apps/files_texteditor/js/aceeditor/mode-scala-uncompressed.js
@@ -282,12 +282,20 @@ var JavaScriptHighlightRules = function() {
     );
 
     // TODO: Unicode escape sequences
-    var identifierRe = "[" + unicode.packages.L + "\\$_][" 
+    var identifierRe = "[" + unicode.packages.L + "\\$_]["
         + unicode.packages.L
         + unicode.packages.Mn + unicode.packages.Mc
         + unicode.packages.Nd
         + unicode.packages.Pc + "\\$_]*\\b";
-        
+
+    var escapedRe = "\\\\(?:x[0-9a-fA-F]{2}|" + // hex
+        "u[0-9a-fA-F]{4}|" + // unicode
+        "[0-2][0-7]{0,2}|" + // oct
+        "3[0-6][0-7]?|" + // oct
+        "37[0-7]?|" + // oct
+        "[4-7][0-7]?|" + //oct
+        ".)";
+
     // regexp must not have capturing parentheses. Use (?:) instead.
     // regexps are ordered -> the first match is used
 
@@ -295,46 +303,139 @@ var JavaScriptHighlightRules = function() {
         "start" : [
             {
                 token : "comment",
-                regex : "\\/\\/.*$"
+                regex : /\/\/.*$/
             },
             new DocCommentHighlightRules().getStartRule("doc-start"),
             {
                 token : "comment", // multi line comment
                 merge : true,
-                regex : "\\/\\*",
+                regex : /\/\*/,
                 next : "comment"
             }, {
-                token : "string", // single line
-                regex : '["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'
-            }, {
-                token : "string", // multi line string start
-                merge : true,
-                regex : '["].*\\\\$',
-                next : "qqstring"
-            }, {
-                token : "string", // single line
-                regex : "['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"
+                token : "string",
+                regex : "'",
+                next  : "qstring"
             }, {
-                token : "string", // multi line string start
-                merge : true,
-                regex : "['].*\\\\$",
-                next : "qstring"
+                token : "string",
+                regex : '"',
+                next  : "qqstring"
             }, {
                 token : "constant.numeric", // hex
-                regex : "0[xX][0-9a-fA-F]+\\b"
+                regex : /0[xX][0-9a-fA-F]+\b/
             }, {
                 token : "constant.numeric", // float
-                regex : "[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"
-            }, {
-                token : ["keyword.definition", "text", "entity.name.function"],
-                regex : "(function)(\\s+)(" + identifierRe + ")"
+                regex : /[+-]?\d+(?:(?:\.\d*)?(?:[eE][+-]?\d+)?)?\b/
+            }, { // match stuff like: Sound.prototype.play = function() { }
+                token : [
+                    "storage.type",
+                    "punctuation.operator",
+                    "support.function",
+                    "punctuation.operator",
+                    "entity.name.function",
+                    "text",
+                    "keyword.operator",
+                    "text",
+                    "storage.type",
+                    "text",
+                    "paren.lparen",
+                    "variable.parameter",
+                    "paren.rparen"
+                ],
+                regex : "(" + identifierRe + ")(\\.)(prototype)(\\.)(" + identifierRe +")(\\s*)(=)(\\s*)(function)(\\s*)(\\()(.*?)(\\))"
+            }, { // match stuff like: Sound.prototype.play = myfunc
+                token : [
+                    "storage.type",
+                    "punctuation.operator",
+                    "support.function",
+                    "punctuation.operator",
+                    "entity.name.function",
+                    "text",
+                    "keyword.operator",
+                    "text"
+                ],
+                regex : "(" + identifierRe + ")(\\.)(prototype)(\\.)(" + identifierRe +")(\\s*)(=)(\\s*)"
+            }, { // match stuff like: Sound.play = function() {  }
+                token : [
+                    "storage.type",
+                    "punctuation.operator",
+                    "entity.name.function",
+                    "text",
+                    "keyword.operator",
+                    "text",
+                    "storage.type",
+                    "text",
+                    "paren.lparen",
+                    "variable.parameter",
+                    "paren.rparen"
+                ],
+                regex : "(" + identifierRe + ")(\\.)(" + identifierRe +")(\\s*)(=)(\\s*)(function)(\\s*)(\\()(.*?)(\\))"
+            }, { // match stuff like: play = function() {  }
+                token : [
+                    "entity.name.function",
+                    "text",
+                    "keyword.operator",
+                    "text",
+                    "storage.type",
+                    "text",
+                    "paren.lparen",
+                    "variable.parameter",
+                    "paren.rparen"
+                ],
+                regex : "(" + identifierRe +")(\\s*)(=)(\\s*)(function)(\\s*)(\\()(.*?)(\\))"
+            }, { // match regular function like: function myFunc(arg) { }
+                token : [
+                    "storage.type",
+                    "text",
+                    "entity.name.function",
+                    "text",
+                    "paren.lparen",
+                    "variable.parameter",
+                    "paren.rparen"
+                ],
+                regex : "(function)(\\s+)(" + identifierRe + ")(\\s*)(\\()(.*?)(\\))"
+            }, { // match stuff like: foobar: function() { }
+                token : [
+                    "entity.name.function",
+                    "text",
+                    "punctuation.operator",
+                    "text",
+                    "storage.type",
+                    "text",
+                    "paren.lparen",
+                    "variable.parameter",
+                    "paren.rparen"
+                ],
+                regex : "(" + identifierRe + ")(\\s*)(:)(\\s*)(function)(\\s*)(\\()(.*?)(\\))"
+            }, { // Attempt to match : function() { } (this is for issues with 'foo': function() { })
+                token : [
+                    "text",
+                    "text",
+                    "storage.type",
+                    "text",
+                    "paren.lparen",
+                    "variable.parameter",
+                    "paren.rparen"
+                ],
+                regex : "(:)(\\s*)(function)?(\\s*)(\\()([^)]*)(\\))"
             }, {
                 token : "constant.language.boolean",
-                regex : "(?:true|false)\\b"
+                regex : /(?:true|false)\b/
             }, {
                 token : "keyword",
                 regex : "(?:" + kwBeforeRe + ")\\b",
                 next : "regex_allowed"
+            }, {
+                token : ["punctuation.operator", "support.function"],
+                regex : /(\.)(s(?:h(?:ift|ow(?:Mod(?:elessDialog|alDialog)|Help))|croll(?:X|By(?:Pages|Lines)?|Y|To)?|t(?:opzzzz|rike)|i(?:n|zeToContent|debar|gnText)|ort|u(?:p|b(?:str(?:ing)?)?)|pli(?:ce|t)|e(?:nd|t(?:Re(?:sizable|questHeader)|M(?:i(?:nutes|lliseconds)|onth)|Seconds|Ho(?:tKeys|urs)|Year|Cursor|Time(?:out)?|Interval|ZOptions|Date|UTC(?:M(?:i(?:nutes|lliseconds)|onth)|Seconds|Hours|Date|FullYear)|FullYear|Active)|arch)|qrt|lice|avePreferences|mall)|h(?:ome|andleEvent)|navigate|c(?:har(?:CodeAt|At)|o(?:s|n(?:cat|textual|firm)|mpile)|eil|lear(?:Timeout|Interval)?|a(?:ptureEvents|ll)|reate(?:StyleSheet|Popup|EventObject))|t(?:o(?:GMTString|S(?:tring|ource)|U(?:TCString|pperCase)|Lo(?:caleString|werCase))|est|a(?:n|int(?:Enabled)?))|i(?:s(?:NaN|Finite)|ndexOf|talics)|d(?:isableExternalCapture|ump|etachEvent)|u(?:n(?:shift|taint|escape|watch)|pdateCommands)|j(?:oin|avaEnabled)|p(?:o(?:p|w)|ush|lugins.refresh|a(?:ddings|rse(?:Int|Float)?)|r(?:int|ompt|eference))|e(?:scape|nableExternalCapture|val|lementFromPoint|x(?:p|ec(?:Script|Command)?))|valueOf|UTC|queryCommand(?:State|Indeterm|Enabled|Value)|f(?:i(?:nd|le(?:ModifiedDate|Size|CreatedDate|UpdatedDate)|xed)|o(?:nt(?:size|color)|rward)|loor|romCharCode)|watch|l(?:ink|o(?:ad|g)|astIndexOf)|a(?:sin|nchor|cos|t(?:tachEvent|ob|an(?:2)?)|pply|lert|b(?:s|ort))|r(?:ou(?:nd|teEvents)|e(?:size(?:By|To)|calc|turnValue|place|verse|l(?:oad|ease(?:Capture|Events)))|andom)|g(?:o|et(?:ResponseHeader|M(?:i(?:nutes|lliseconds)|onth)|Se(?:conds|lection)|Hours|Year|Time(?:zoneOffset)?|Da(?:y|te)|UTC(?:M(?:i(?:nutes|lliseconds)|onth)|Seconds|Hours|Da(?:y|te)|FullYear)|FullYear|A(?:ttention|llResponseHeaders)))|m(?:in|ove(?:B(?:y|elow)|To(?:Absolute)?|Above)|ergeAttributes|a(?:tch|rgins|x))|b(?:toa|ig|o(?:ld|rderWidths)|link|ack))\b(?=\()/
+            }, {
+                token : ["punctuation.operator", "support.function.dom"],
+                regex : /(\.)(s(?:ub(?:stringData|mit)|plitText|e(?:t(?:NamedItem|Attribute(?:Node)?)|lect))|has(?:ChildNodes|Feature)|namedItem|c(?:l(?:ick|o(?:se|neNode))|reate(?:C(?:omment|DATASection|aption)|T(?:Head|extNode|Foot)|DocumentFragment|ProcessingInstruction|E(?:ntityReference|lement)|Attribute))|tabIndex|i(?:nsert(?:Row|Before|Cell|Data)|tem)|open|delete(?:Row|C(?:ell|aption)|T(?:Head|Foot)|Data)|focus|write(?:ln)?|a(?:dd|ppend(?:Child|Data))|re(?:set|place(?:Child|Data)|move(?:NamedItem|Child|Attribute(?:Node)?)?)|get(?:NamedItem|Element(?:sBy(?:Name|TagName)|ById)|Attribute(?:Node)?)|blur)\b(?=\()/
+            }, {
+                token : ["punctuation.operator", "support.constant"],
+                regex : /(\.)(s(?:ystemLanguage|cr(?:ipts|ollbars|een(?:X|Y|Top|Left))|t(?:yle(?:Sheets)?|atus(?:Text|bar)?)|ibling(?:Below|Above)|ource|uffixes|e(?:curity(?:Policy)?|l(?:ection|f)))|h(?:istory|ost(?:name)?|as(?:h|Focus))|y|X(?:MLDocument|SLDocument)|n(?:ext|ame(?:space(?:s|URI)|Prop))|M(?:IN_VALUE|AX_VALUE)|c(?:haracterSet|o(?:n(?:structor|trollers)|okieEnabled|lorDepth|mp(?:onents|lete))|urrent|puClass|l(?:i(?:p(?:boardData)?|entInformation)|osed|asses)|alle(?:e|r)|rypto)|t(?:o(?:olbar|p)|ext(?:Transform|Indent|Decoration|Align)|ags)|SQRT(?:1_2|2)|i(?:n(?:ner(?:Height|Width)|put)|ds|gnoreCase)|zIndex|o(?:scpu|n(?:readystatechange|Line)|uter(?:Height|Width)|p(?:sProfile|ener)|ffscreenBuffering)|NEGATIVE_INFINITY|d(?:i(?:splay|alog(?:Height|Top|Width|Left|Arguments)|rectories)|e(?:scription|fault(?:Status|Ch(?:ecked|arset)|View)))|u(?:ser(?:Profile|Language|Agent)|n(?:iqueID|defined)|pdateInterval)|_content|p(?:ixelDepth|ort|ersonalbar|kcs11|l(?:ugins|atform)|a(?:thname|dding(?:Right|Bottom|Top|Left)|rent(?:Window|Layer)?|ge(?:X(?:Offset)?|Y(?:Offset)?))|r(?:o(?:to(?:col|type)|duct(?:Sub)?|mpter)|e(?:vious|fix)))|e(?:n(?:coding|abledPlugin)|x(?:ternal|pando)|mbeds)|v(?:isibility|endor(?:Sub)?|Linkcolor)|URLUnencoded|P(?:I|OSITIVE_INFINITY)|f(?:ilename|o(?:nt(?:Size|Family|Weight)|rmName)|rame(?:s|Element)|gColor)|E|whiteSpace|l(?:i(?:stStyleType|n(?:eHeight|kColor))|o(?:ca(?:tion(?:bar)?|lName)|wsrc)|e(?:ngth|ft(?:Context)?)|a(?:st(?:M(?:odified|atch)|Index|Paren)|yer(?:s|X)|nguage))|a(?:pp(?:MinorVersion|Name|Co(?:deName|re)|Version)|vail(?:Height|Top|Width|Left)|ll|r(?:ity|guments)|Linkcolor|bove)|r(?:ight(?:Context)?|e(?:sponse(?:XML|Text)|adyState))|global|x|m(?:imeTypes|ultiline|enubar|argin(?:Right|Bottom|Top|Left))|L(?:N(?:10|2)|OG(?:10E|2E))|b(?:o(?:ttom|rder(?:Width|RightWidth|BottomWidth|Style|Color|TopWidth|LeftWidth))|ufferDepth|elow|ackground(?:Color|Image)))\b/
+            }, {
+                token : ["storage.type", "punctuation.operator", "support.function.firebug"],
+                regex : /(console)(\.)(warn|info|log|error|time|timeEnd|assert)\b/
             }, {
                 token : function(value) {
                     if (globals.hasOwnProperty(value))
@@ -342,7 +443,7 @@ var JavaScriptHighlightRules = function() {
                     else if (deprecated.hasOwnProperty(value))
                         return "invalid.deprecated";
                     else if (definitions.hasOwnProperty(value))
-                        return "keyword.definition";
+                        return "storage.type";
                     else if (keywords.hasOwnProperty(value))
                         return "keyword";
                     else if (buildinConstants.hasOwnProperty(value))
@@ -357,29 +458,29 @@ var JavaScriptHighlightRules = function() {
                 regex : identifierRe
             }, {
                 token : "keyword.operator",
-                regex : "!|\\$|%|&|\\*|\\-\\-|\\-|\\+\\+|\\+|~|===|==|=|!=|!==|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\\|\\||\\?\\:|\\*=|%=|\\+=|\\-=|&=|\\^=|\\b(?:in|instanceof|new|delete|typeof|void)",
+                regex : /!|\$|%|&|\*|\-\-|\-|\+\+|\+|~|===|==|=|!=|!==|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\|\||\?\:|\*=|%=|\+=|\-=|&=|\^=|\b(?:in|instanceof|new|delete|typeof|void)/,
                 next  : "regex_allowed"
             }, {
                 token : "punctuation.operator",
-                regex : "\\?|\\:|\\,|\\;|\\.",
+                regex : /\?|\:|\,|\;|\./,
                 next  : "regex_allowed"
             }, {
                 token : "paren.lparen",
-                regex : "[[({]",
+                regex : /[\[({]/,
                 next  : "regex_allowed"
             }, {
                 token : "paren.rparen",
-                regex : "[\\])}]"
+                regex : /[\])}]/
             }, {
                 token : "keyword.operator",
-                regex : "\\/=?",
+                regex : /\/=?/,
                 next  : "regex_allowed"
             }, {
                 token: "comment",
-                regex: "^#!.*$" 
+                regex: /^#!.*$/
             }, {
                 token : "text",
-                regex : "\\s+"
+                regex : /\s+/
             }
         ],
         // regular expressions are only allowed after certain tokens. This
@@ -404,7 +505,7 @@ var JavaScriptHighlightRules = function() {
             }, {
                 // immediately return to the start mode without matching
                 // anything
-                token: "empty", 
+                token: "empty",
                 regex: "",
                 next: "start"
             }
@@ -416,10 +517,10 @@ var JavaScriptHighlightRules = function() {
                 next: "regex"
             }, {
 				// flag
-                token: "string.regexp", 
+                token: "string.regexp",
                 regex: "/\\w*",
                 next: "start",
-                merge: true 
+                merge: true
             }, {
                 token: "string.regexp",
                 regex: "[^\\\\/\\[]+",
@@ -431,9 +532,9 @@ var JavaScriptHighlightRules = function() {
                 next: "regex_character_class",
                 merge: true
             }, {
-                token: "empty", 
+                token: "empty",
                 regex: "",
-                next: "start" 
+                next: "start"
             }
         ],
         "regex_character_class": [
@@ -452,9 +553,9 @@ var JavaScriptHighlightRules = function() {
                 next: "regex_character_class",
                 merge: true
             }, {
-                token: "empty", 
+                token: "empty",
                 regex: "",
-                next: "start" 
+                next: "start"
             }
         ],
         "comment_regex_allowed" : [
@@ -483,28 +584,32 @@ var JavaScriptHighlightRules = function() {
         ],
         "qqstring" : [
             {
+                token : "constant.language.escape",
+                regex : escapedRe
+            }, {
                 token : "string",
-                regex : '(?:(?:\\\\.)|(?:[^"\\\\]))*?"',
-                next : "start"
+                regex : '[^"\\\\]+'
             }, {
                 token : "string",
-                merge : true,
-                regex : '.+'
+                regex : '"',
+                next  : "start"
             }
         ],
         "qstring" : [
             {
+                token : "constant.language.escape",
+                regex : escapedRe
+            }, {
                 token : "string",
-                regex : "(?:(?:\\\\.)|(?:[^'\\\\]))*?'",
-                next : "start"
+                regex : "[^'\\\\]+"
             }, {
                 token : "string",
-                merge : true,
-                regex : '.+'
+                regex : "'",
+                next  : "start"
             }
         ]
     };
-    
+
     this.embedRules(DocCommentHighlightRules, "doc-",
         [ new DocCommentHighlightRules().getEndRule("start") ]);
 };
@@ -689,195 +794,6 @@ var MatchingBraceOutdent = function() {};
 }).call(MatchingBraceOutdent.prototype);
 
 exports.MatchingBraceOutdent = MatchingBraceOutdent;
-});
-/* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is Ajax.org Code Editor (ACE).
- *
- * The Initial Developer of the Original Code is
- * Ajax.org B.V.
- * Portions created by the Initial Developer are Copyright (C) 2010
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *      Fabian Jakobs <fabian AT ajax DOT org>
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-define('ace/worker/worker_client', ['require', 'exports', 'module' , 'ace/lib/oop', 'ace/lib/event_emitter'], function(require, exports, module) {
-"use strict";
-
-var oop = require("../lib/oop");
-var EventEmitter = require("../lib/event_emitter").EventEmitter;
-
-var WorkerClient = function(topLevelNamespaces, packagedJs, mod, classname) {
-
-    this.changeListener = this.changeListener.bind(this);
-
-    if (module.packaged) {
-        var base = this.$guessBasePath();
-        this.$worker = new Worker(base + packagedJs);
-    }
-    else {
-        var workerUrl = this.$normalizePath(require.nameToUrl("ace/worker/worker", null, "_"));
-        this.$worker = new Worker(workerUrl);
-
-        var tlns = {};
-        for (var i=0; i<topLevelNamespaces.length; i++) {
-            var ns = topLevelNamespaces[i];
-            var path = this.$normalizePath(require.nameToUrl(ns, null, "_").replace(/.js$/, ""));
-
-            tlns[ns] = path;
-        }
-    }
-
-    this.$worker.postMessage({
-        init : true,
-        tlns: tlns,
-        module: mod,
-        classname: classname
-    });
-
-    this.callbackId = 1;
-    this.callbacks = {};
-
-    var _self = this;
-    this.$worker.onerror = function(e) {
-        window.console && console.log && console.log(e);
-        throw e;
-    };
-    this.$worker.onmessage = function(e) {
-        var msg = e.data;
-        switch(msg.type) {
-            case "log":
-                window.console && console.log && console.log(msg.data);
-                break;
-
-            case "event":
-                _self._emit(msg.name, {data: msg.data});
-                break;
-
-            case "call":
-                var callback = _self.callbacks[msg.id];
-                if (callback) {
-                    callback(msg.data);
-                    delete _self.callbacks[msg.id];
-                }
-                break;
-        }
-    };
-};
-
-(function(){
-
-    oop.implement(this, EventEmitter);
-
-    this.$normalizePath = function(path) {
-        path = path.replace(/^[a-z]+:\/\/[^\/]+\//, ""); // Remove domain name and rebuild it
-        path = location.protocol + "//" + location.host
-            // paths starting with a slash are relative to the root (host)
-            + (path.charAt(0) == "/" ? "" : location.pathname.replace(/\/[^\/]*$/, ""))
-            + "/" + path.replace(/^[\/]+/, "");
-        return path;
-    };
-
-    this.$guessBasePath = function() {
-        if (require.aceBaseUrl)
-            return require.aceBaseUrl;
-
-        var scripts = document.getElementsByTagName("script");
-        for (var i=0; i<scripts.length; i++) {
-            var script = scripts[i];
-
-            var base = script.getAttribute("data-ace-base");
-            if (base)
-                return base.replace(/\/*$/, "/");
-
-            var src = script.src || script.getAttribute("src");
-            if (!src) {
-                continue;
-            }
-            var m = src.match(/^(?:(.*\/)ace\.js|(.*\/)ace(-uncompressed)?(-noconflict)?\.js)(?:\?|$)/);
-            if (m)
-                return m[1] || m[2];
-        }
-        return "";
-    };
-
-    this.terminate = function() {
-        this._emit("terminate", {});
-        this.$worker.terminate();
-        this.$worker = null;
-        this.$doc.removeEventListener("change", this.changeListener);
-        this.$doc = null;
-    };
-
-    this.send = function(cmd, args) {
-        this.$worker.postMessage({command: cmd, args: args});
-    };
-
-    this.call = function(cmd, args, callback) {
-        if (callback) {
-            var id = this.callbackId++;
-            this.callbacks[id] = callback;
-            args.push(id);
-        }
-        this.send(cmd, args);
-    };
-
-    this.emit = function(event, data) {
-        try {
-            // firefox refuses to clone objects which have function properties
-            // TODO: cleanup event
-            this.$worker.postMessage({event: event, data: {data: data.data}});
-        }
-        catch(ex) {}
-    };
-
-    this.attachToDocument = function(doc) {
-        if(this.$doc)
-            this.terminate();
-
-        this.$doc = doc;
-        this.call("setValue", [doc.getValue()]);
-        doc.on("change", this.changeListener);
-    };
-
-    this.changeListener = function(e) {
-        e.range = {
-            start: e.data.range.start,
-            end: e.data.range.end
-        };
-        this.emit("change", e);
-    };
-
-}).call(WorkerClient.prototype);
-
-exports.WorkerClient = WorkerClient;
-
 });
 /* vim:ts=4:sts=4:sw=4:
  * ***** BEGIN LICENSE BLOCK *****
@@ -933,12 +849,12 @@ var CstyleBehaviour = function () {
                 return {
                     text: '{' + selected + '}',
                     selection: false
-                }
+                };
             } else {
                 return {
                     text: '{}',
                     selection: [1, 1]
-                }
+                };
             }
         } else if (text == '}') {
             var cursor = editor.getCursorPosition();
@@ -950,7 +866,7 @@ var CstyleBehaviour = function () {
                     return {
                         text: '',
                         selection: [1, 1]
-                    }
+                    };
                 }
             }
         } else if (text == "\n") {
@@ -968,7 +884,7 @@ var CstyleBehaviour = function () {
                 return {
                     text: '\n' + indent + '\n' + next_indent,
                     selection: [1, indent.length, 1, indent.length]
-                }
+                };
             }
         }
     });
@@ -993,12 +909,12 @@ var CstyleBehaviour = function () {
                 return {
                     text: '(' + selected + ')',
                     selection: false
-                }
+                };
             } else {
                 return {
                     text: '()',
                     selection: [1, 1]
-                }
+                };
             }
         } else if (text == ')') {
             var cursor = editor.getCursorPosition();
@@ -1010,7 +926,7 @@ var CstyleBehaviour = function () {
                     return {
                         text: '',
                         selection: [1, 1]
-                    }
+                    };
                 }
             }
         }
@@ -1029,14 +945,15 @@ var CstyleBehaviour = function () {
     });
 
     this.add("string_dquotes", "insertion", function (state, action, editor, session, text) {
-        if (text == '"') {
+        if (text == '"' || text == "'") {
+            var quote = text;
             var selection = editor.getSelectionRange();
             var selected = session.doc.getTextRange(selection);
             if (selected !== "") {
                 return {
-                    text: '"' + selected + '"',
+                    text: quote + selected + quote,
                     selection: false
-                }
+                };
             } else {
                 var cursor = editor.getCursorPosition();
                 var line = session.doc.getLine(cursor.row);
@@ -1057,7 +974,7 @@ var CstyleBehaviour = function () {
                     if (token.type == "string") {
                       quotepos = -1;
                     } else if (quotepos < 0) {
-                      quotepos = token.value.indexOf('"');
+                      quotepos = token.value.indexOf(quote);
                     }
                     if ((token.value.length + col) > selection.start.column) {
                         break;
@@ -1066,19 +983,19 @@ var CstyleBehaviour = function () {
                 }
 
                 // Try and be smart about when we auto insert.
-                if (!token || (quotepos < 0 && token.type !== "comment" && (token.type !== "string" || ((selection.start.column !== token.value.length+col-1) && token.value.lastIndexOf('"') === token.value.length-1)))) {
+                if (!token || (quotepos < 0 && token.type !== "comment" && (token.type !== "string" || ((selection.start.column !== token.value.length+col-1) && token.value.lastIndexOf(quote) === token.value.length-1)))) {
                     return {
-                        text: '""',
+                        text: quote + quote,
                         selection: [1,1]
-                    }
+                    };
                 } else if (token && token.type === "string") {
                     // Ignore input and move right one if we're typing over the closing quote.
                     var rightChar = line.substring(cursor.column, cursor.column + 1);
-                    if (rightChar == '"') {
+                    if (rightChar == quote) {
                         return {
                             text: '',
                             selection: [1, 1]
-                        }
+                        };
                     }
                 }
             }
@@ -1087,7 +1004,7 @@ var CstyleBehaviour = function () {
 
     this.add("string_dquotes", "deletion", function (state, action, editor, session, range) {
         var selected = session.doc.getTextRange(range);
-        if (!range.isMultiLine() && selected == '"') {
+        if (!range.isMultiLine() && (selected == '"' || selected == "'")) {
             var line = session.doc.getLine(range.start.row);
             var rightChar = line.substring(range.start.column + 1, range.start.column + 2);
             if (rightChar == '"') {
@@ -1097,7 +1014,8 @@ var CstyleBehaviour = function () {
         }
     });
 
-}
+};
+
 oop.inherits(CstyleBehaviour, Behaviour);
 
 exports.CstyleBehaviour = CstyleBehaviour;
@@ -1452,13 +1370,3 @@ oop.inherits(ScalaHighlightRules, TextHighlightRules);
 
 exports.ScalaHighlightRules = ScalaHighlightRules;
 });
-;
-            (function() {
-                window.require(["ace/ace"], function(a) {
-                    if (!window.ace)
-                        window.ace = {};
-                    for (var key in a) if (a.hasOwnProperty(key))
-                        ace[key] = a[key];
-                });
-            })();
-        
\ No newline at end of file
diff --git a/apps/files_texteditor/js/aceeditor/mode-scala.js b/apps/files_texteditor/js/aceeditor/mode-scala.js
index c697fe1781aa5f66ba775f062a46fb2f75af5ee5..e0ba4b537d9571e74a5f92be79252cf4ebc94271 100644
--- a/apps/files_texteditor/js/aceeditor/mode-scala.js
+++ b/apps/files_texteditor/js/aceeditor/mode-scala.js
@@ -1 +1 @@
-define("ace/mode/scala",["require","exports","module","ace/lib/oop","ace/mode/javascript","ace/tokenizer","ace/mode/scala_highlight_rules"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("./javascript").Mode,f=a("../tokenizer").Tokenizer,g=a("./scala_highlight_rules").ScalaHighlightRules,h=function(){e.call(this),this.$tokenizer=new f((new g).getRules())};d.inherits(h,e),function(){this.createWorker=function(a){return null}}.call(h.prototype),b.Mode=h}),define("ace/mode/javascript",["require","exports","module","ace/lib/oop","ace/mode/text","ace/tokenizer","ace/mode/javascript_highlight_rules","ace/mode/matching_brace_outdent","ace/range","ace/worker/worker_client","ace/mode/behaviour/cstyle","ace/mode/folding/cstyle"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("./text").Mode,f=a("../tokenizer").Tokenizer,g=a("./javascript_highlight_rules").JavaScriptHighlightRules,h=a("./matching_brace_outdent").MatchingBraceOutdent,i=a("../range").Range,j=a("../worker/worker_client").WorkerClient,k=a("./behaviour/cstyle").CstyleBehaviour,l=a("./folding/cstyle").FoldMode,m=function(){this.$tokenizer=new f((new g).getRules()),this.$outdent=new h,this.$behaviour=new k,this.foldingRules=new l};d.inherits(m,e),function(){this.toggleCommentLines=function(a,b,c,d){var e=!0,f=/^(\s*)\/\//;for(var g=c;g<=d;g++)if(!f.test(b.getLine(g))){e=!1;break}if(e){var h=new i(0,0,0,0);for(var g=c;g<=d;g++){var j=b.getLine(g),k=j.match(f);h.start.row=g,h.end.row=g,h.end.column=k[0].length,b.replace(h,k[1])}}else b.indentRows(c,d,"//")},this.getNextLineIndent=function(a,b,c){var d=this.$getIndent(b),e=this.$tokenizer.getLineTokens(b,a),f=e.tokens,g=e.state;if(f.length&&f[f.length-1].type=="comment")return d;if(a=="start"||a=="regex_allowed"){var h=b.match(/^.*(?:\bcase\b.*\:|[\{\(\[])\s*$/);h&&(d+=c)}else if(a=="doc-start"){if(g=="start"||a=="regex_allowed")return"";var h=b.match(/^\s*(\/?)\*/);h&&(h[1]&&(d+=" "),d+="* ")}return d},this.checkOutdent=function(a,b,c){return this.$outdent.checkOutdent(b,c)},this.autoOutdent=function(a,b,c){this.$outdent.autoOutdent(b,c)},this.createWorker=function(a){var b=new j(["ace"],"worker-javascript.js","ace/mode/javascript_worker","JavaScriptWorker");return b.attachToDocument(a.getDocument()),b.on("jslint",function(b){var c=[];for(var d=0;d<b.data.length;d++){var e=b.data[d];e&&c.push({row:e.line-1,column:e.character-1,text:e.reason,type:"warning",lint:e})}a.setAnnotations(c)}),b.on("narcissus",function(b){a.setAnnotations([b.data])}),b.on("terminate",function(){a.clearAnnotations()}),b}}.call(m.prototype),b.Mode=m}),define("ace/mode/javascript_highlight_rules",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/unicode","ace/mode/doc_comment_highlight_rules","ace/mode/text_highlight_rules"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("../lib/lang"),f=a("../unicode"),g=a("./doc_comment_highlight_rules").DocCommentHighlightRules,h=a("./text_highlight_rules").TextHighlightRules,i=function(){var a=e.arrayToMap("Array|Boolean|Date|Function|Iterator|Number|Object|RegExp|String|Proxy|Namespace|QName|XML|XMLList|ArrayBuffer|Float32Array|Float64Array|Int16Array|Int32Array|Int8Array|Uint16Array|Uint32Array|Uint8Array|Uint8ClampedArray|Error|EvalError|InternalError|RangeError|ReferenceError|StopIteration|SyntaxError|TypeError|URIError|decodeURI|decodeURIComponent|encodeURI|encodeURIComponent|eval|isFinite|isNaN|parseFloat|parseInt|JSON|Math|this|arguments|prototype|window|document".split("|")),b=e.arrayToMap("break|case|catch|continue|default|delete|do|else|finally|for|function|if|in|instanceof|new|return|switch|throw|try|typeof|let|var|while|with|const|yield|import|get|set".split("|")),c="case|do|else|finally|in|instanceof|return|throw|try|typeof|yield",d=e.arrayToMap("__parent__|__count__|escape|unescape|with|__proto__".split("|")),h=e.arrayToMap("const|let|var|function".split("|")),i=e.arrayToMap("null|Infinity|NaN|undefined".split("|")),j=e.arrayToMap("class|enum|extends|super|export|implements|private|public|interface|package|protected|static".split("|")),k="["+f.packages.L+"\\$_]["+f.packages.L+f.packages.Mn+f.packages.Mc+f.packages.Nd+f.packages.Pc+"\\$_]*\\b";this.$rules={start:[{token:"comment",regex:"\\/\\/.*$"},(new g).getStartRule("doc-start"),{token:"comment",merge:!0,regex:"\\/\\*",next:"comment"},{token:"string",regex:'["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'},{token:"string",merge:!0,regex:'["].*\\\\$',next:"qqstring"},{token:"string",regex:"['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"},{token:"string",merge:!0,regex:"['].*\\\\$",next:"qstring"},{token:"constant.numeric",regex:"0[xX][0-9a-fA-F]+\\b"},{token:"constant.numeric",regex:"[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"},{token:["keyword.definition","text","entity.name.function"],regex:"(function)(\\s+)("+k+")"},{token:"constant.language.boolean",regex:"(?:true|false)\\b"},{token:"keyword",regex:"(?:"+c+")\\b",next:"regex_allowed"},{token:function(c){return a.hasOwnProperty(c)?"variable.language":d.hasOwnProperty(c)?"invalid.deprecated":h.hasOwnProperty(c)?"keyword.definition":b.hasOwnProperty(c)?"keyword":i.hasOwnProperty(c)?"constant.language":j.hasOwnProperty(c)?"invalid.illegal":c=="debugger"?"invalid.deprecated":"identifier"},regex:k},{token:"keyword.operator",regex:"!|\\$|%|&|\\*|\\-\\-|\\-|\\+\\+|\\+|~|===|==|=|!=|!==|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\\|\\||\\?\\:|\\*=|%=|\\+=|\\-=|&=|\\^=|\\b(?:in|instanceof|new|delete|typeof|void)",next:"regex_allowed"},{token:"punctuation.operator",regex:"\\?|\\:|\\,|\\;|\\.",next:"regex_allowed"},{token:"paren.lparen",regex:"[[({]",next:"regex_allowed"},{token:"paren.rparen",regex:"[\\])}]"},{token:"keyword.operator",regex:"\\/=?",next:"regex_allowed"},{token:"comment",regex:"^#!.*$"},{token:"text",regex:"\\s+"}],regex_allowed:[{token:"comment",merge:!0,regex:"\\/\\*",next:"comment_regex_allowed"},{token:"comment",regex:"\\/\\/.*$"},{token:"string.regexp",regex:"\\/",next:"regex",merge:!0},{token:"text",regex:"\\s+"},{token:"empty",regex:"",next:"start"}],regex:[{token:"regexp.keyword.operator",regex:"\\\\(?:u[\\da-fA-F]{4}|x[\\da-fA-F]{2}|.)",next:"regex"},{token:"string.regexp",regex:"/\\w*",next:"start",merge:!0},{token:"string.regexp",regex:"[^\\\\/\\[]+",next:"regex",merge:!0},{token:"string.regexp.charachterclass",regex:"\\[",next:"regex_character_class",merge:!0},{token:"empty",regex:"",next:"start"}],regex_character_class:[{token:"regexp.keyword.operator",regex:"\\\\(?:u[\\da-fA-F]{4}|x[\\da-fA-F]{2}|.)",next:"regex_character_class"},{token:"string.regexp.charachterclass",regex:"]",next:"regex",merge:!0},{token:"string.regexp.charachterclass",regex:"[^\\\\\\]]+",next:"regex_character_class",merge:!0},{token:"empty",regex:"",next:"start"}],comment_regex_allowed:[{token:"comment",regex:".*?\\*\\/",merge:!0,next:"regex_allowed"},{token:"comment",merge:!0,regex:".+"}],comment:[{token:"comment",regex:".*?\\*\\/",merge:!0,next:"start"},{token:"comment",merge:!0,regex:".+"}],qqstring:[{token:"string",regex:'(?:(?:\\\\.)|(?:[^"\\\\]))*?"',next:"start"},{token:"string",merge:!0,regex:".+"}],qstring:[{token:"string",regex:"(?:(?:\\\\.)|(?:[^'\\\\]))*?'",next:"start"},{token:"string",merge:!0,regex:".+"}]},this.embedRules(g,"doc-",[(new g).getEndRule("start")])};d.inherits(i,h),b.JavaScriptHighlightRules=i}),define("ace/mode/doc_comment_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("./text_highlight_rules").TextHighlightRules,f=function(){this.$rules={start:[{token:"comment.doc.tag",regex:"@[\\w\\d_]+"},{token:"comment.doc",merge:!0,regex:"\\s+"},{token:"comment.doc",merge:!0,regex:"TODO"},{token:"comment.doc",merge:!0,regex:"[^@\\*]+"},{token:"comment.doc",merge:!0,regex:"."}]}};d.inherits(f,e),function(){this.getStartRule=function(a){return{token:"comment.doc",merge:!0,regex:"\\/\\*(?=\\*)",next:a}},this.getEndRule=function(a){return{token:"comment.doc",merge:!0,regex:"\\*\\/",next:a}}}.call(f.prototype),b.DocCommentHighlightRules=f}),define("ace/mode/matching_brace_outdent",["require","exports","module","ace/range"],function(a,b,c){"use strict";var d=a("../range").Range,e=function(){};((function(){this.checkOutdent=function(a,b){return/^\s+$/.test(a)?/^\s*\}/.test(b):!1},this.autoOutdent=function(a,b){var c=a.getLine(b),e=c.match(/^(\s*\})/);if(!e)return 0;var f=e[1].length,g=a.findMatchingBracket({row:b,column:f});if(!g||g.row==b)return 0;var h=this.$getIndent(a.getLine(g.row));a.replace(new d(b,0,b,f-1),h)},this.$getIndent=function(a){var b=a.match(/^(\s+)/);return b?b[1]:""}})).call(e.prototype),b.MatchingBraceOutdent=e}),define("ace/worker/worker_client",["require","exports","module","ace/lib/oop","ace/lib/event_emitter"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("../lib/event_emitter").EventEmitter,f=function(b,d,e,f){this.changeListener=this.changeListener.bind(this);if(c.packaged){var g=this.$guessBasePath();this.$worker=new Worker(g+d)}else{var h=this.$normalizePath(a.nameToUrl("ace/worker/worker",null,"_"));this.$worker=new Worker(h);var i={};for(var j=0;j<b.length;j++){var k=b[j],l=this.$normalizePath(a.nameToUrl(k,null,"_").replace(/.js$/,""));i[k]=l}}this.$worker.postMessage({init:!0,tlns:i,module:e,classname:f}),this.callbackId=1,this.callbacks={};var m=this;this.$worker.onerror=function(a){throw window.console&&console.log&&console.log(a),a},this.$worker.onmessage=function(a){var b=a.data;switch(b.type){case"log":window.console&&console.log&&console.log(b.data);break;case"event":m._emit(b.name,{data:b.data});break;case"call":var c=m.callbacks[b.id];c&&(c(b.data),delete m.callbacks[b.id])}}};((function(){d.implement(this,e),this.$normalizePath=function(a){return a=a.replace(/^[a-z]+:\/\/[^\/]+\//,""),a=location.protocol+"//"+location.host+(a.charAt(0)=="/"?"":location.pathname.replace(/\/[^\/]*$/,""))+"/"+a.replace(/^[\/]+/,""),a},this.$guessBasePath=function(){if(a.aceBaseUrl)return a.aceBaseUrl;var b=document.getElementsByTagName("script");for(var c=0;c<b.length;c++){var d=b[c],e=d.getAttribute("data-ace-base");if(e)return e.replace(/\/*$/,"/");var f=d.src||d.getAttribute("src");if(!f)continue;var g=f.match(/^(?:(.*\/)ace\.js|(.*\/)ace(-uncompressed)?(-noconflict)?\.js)(?:\?|$)/);if(g)return g[1]||g[2]}return""},this.terminate=function(){this._emit("terminate",{}),this.$worker.terminate(),this.$worker=null,this.$doc.removeEventListener("change",this.changeListener),this.$doc=null},this.send=function(a,b){this.$worker.postMessage({command:a,args:b})},this.call=function(a,b,c){if(c){var d=this.callbackId++;this.callbacks[d]=c,b.push(d)}this.send(a,b)},this.emit=function(a,b){try{this.$worker.postMessage({event:a,data:{data:b.data}})}catch(c){}},this.attachToDocument=function(a){this.$doc&&this.terminate(),this.$doc=a,this.call("setValue",[a.getValue()]),a.on("change",this.changeListener)},this.changeListener=function(a){a.range={start:a.data.range.start,end:a.data.range.end},this.emit("change",a)}})).call(f.prototype),b.WorkerClient=f}),define("ace/mode/behaviour/cstyle",["require","exports","module","ace/lib/oop","ace/mode/behaviour"],function(a,b,c){"use strict";var d=a("../../lib/oop"),e=a("../behaviour").Behaviour,f=function(){this.add("braces","insertion",function(a,b,c,d,e){if(e=="{"){var f=c.getSelectionRange(),g=d.doc.getTextRange(f);return g!==""?{text:"{"+g+"}",selection:!1}:{text:"{}",selection:[1,1]}}if(e=="}"){var h=c.getCursorPosition(),i=d.doc.getLine(h.row),j=i.substring(h.column,h.column+1);if(j=="}"){var k=d.$findOpeningBracket("}",{column:h.column+1,row:h.row});if(k!==null)return{text:"",selection:[1,1]}}}else if(e=="\n"){var h=c.getCursorPosition(),i=d.doc.getLine(h.row),j=i.substring(h.column,h.column+1);if(j=="}"){var l=d.findMatchingBracket({row:h.row,column:h.column+1});if(!l)return null;var m=this.getNextLineIndent(a,i.substring(0,i.length-1),d.getTabString()),n=this.$getIndent(d.doc.getLine(l.row));return{text:"\n"+m+"\n"+n,selection:[1,m.length,1,m.length]}}}}),this.add("braces","deletion",function(a,b,c,d,e){var f=d.doc.getTextRange(e);if(!e.isMultiLine()&&f=="{"){var g=d.doc.getLine(e.start.row),h=g.substring(e.end.column,e.end.column+1);if(h=="}")return e.end.column++,e}}),this.add("parens","insertion",function(a,b,c,d,e){if(e=="("){var f=c.getSelectionRange(),g=d.doc.getTextRange(f);return g!==""?{text:"("+g+")",selection:!1}:{text:"()",selection:[1,1]}}if(e==")"){var h=c.getCursorPosition(),i=d.doc.getLine(h.row),j=i.substring(h.column,h.column+1);if(j==")"){var k=d.$findOpeningBracket(")",{column:h.column+1,row:h.row});if(k!==null)return{text:"",selection:[1,1]}}}}),this.add("parens","deletion",function(a,b,c,d,e){var f=d.doc.getTextRange(e);if(!e.isMultiLine()&&f=="("){var g=d.doc.getLine(e.start.row),h=g.substring(e.start.column+1,e.start.column+2);if(h==")")return e.end.column++,e}}),this.add("string_dquotes","insertion",function(a,b,c,d,e){if(e=='"'){var f=c.getSelectionRange(),g=d.doc.getTextRange(f);if(g!=="")return{text:'"'+g+'"',selection:!1};var h=c.getCursorPosition(),i=d.doc.getLine(h.row),j=i.substring(h.column-1,h.column);if(j=="\\")return null;var k=d.getTokens(f.start.row,f.start.row)[0].tokens,l=0,m,n=-1;for(var o=0;o<k.length;o++){m=k[o],m.type=="string"?n=-1:n<0&&(n=m.value.indexOf('"'));if(m.value.length+l>f.start.column)break;l+=k[o].value.length}if(!m||n<0&&m.type!=="comment"&&(m.type!=="string"||f.start.column!==m.value.length+l-1&&m.value.lastIndexOf('"')===m.value.length-1))return{text:'""',selection:[1,1]};if(m&&m.type==="string"){var p=i.substring(h.column,h.column+1);if(p=='"')return{text:"",selection:[1,1]}}}}),this.add("string_dquotes","deletion",function(a,b,c,d,e){var f=d.doc.getTextRange(e);if(!e.isMultiLine()&&f=='"'){var g=d.doc.getLine(e.start.row),h=g.substring(e.start.column+1,e.start.column+2);if(h=='"')return e.end.column++,e}})};d.inherits(f,e),b.CstyleBehaviour=f}),define("ace/mode/folding/cstyle",["require","exports","module","ace/lib/oop","ace/range","ace/mode/folding/fold_mode"],function(a,b,c){"use strict";var d=a("../../lib/oop"),e=a("../../range").Range,f=a("./fold_mode").FoldMode,g=b.FoldMode=function(){};d.inherits(g,f),function(){this.foldingStartMarker=/(\{|\[)[^\}\]]*$|^\s*(\/\*)/,this.foldingStopMarker=/^[^\[\{]*(\}|\])|^[\s\*]*(\*\/)/,this.getFoldWidgetRange=function(a,b,c){var d=a.getLine(c),f=d.match(this.foldingStartMarker);if(f){var g=f.index;if(f[1])return this.openingBracketBlock(a,f[1],c,g);var h=a.getCommentFoldRange(c,g+f[0].length);return h.end.column-=2,h}if(b!=="markbeginend")return;var f=d.match(this.foldingStopMarker);if(f){var g=f.index+f[0].length;if(f[2]){var h=a.getCommentFoldRange(c,g);return h.end.column-=2,h}var i={row:c,column:g},j=a.$findOpeningBracket(f[1],i);if(!j)return;return j.column++,i.column--,e.fromPoints(j,i)}}}.call(g.prototype)}),define("ace/mode/folding/fold_mode",["require","exports","module","ace/range"],function(a,b,c){"use strict";var d=a("../../range").Range,e=b.FoldMode=function(){};((function(){this.foldingStartMarker=null,this.foldingStopMarker=null,this.getFoldWidget=function(a,b,c){var d=a.getLine(c);return this.foldingStartMarker.test(d)?"start":b=="markbeginend"&&this.foldingStopMarker&&this.foldingStopMarker.test(d)?"end":""},this.getFoldWidgetRange=function(a,b,c){return null},this.indentationBlock=function(a,b,c){var e=/^\s*/,f=b,g=b,h=a.getLine(b),i=c||h.length,j=h.match(e)[0].length,k=a.getLength();while(++b<k){h=a.getLine(b);var l=h.match(e)[0].length;if(l==h.length)continue;if(l<=j)break;g=b}if(g>f){var m=a.getLine(g).length;return new d(f,i,g,m)}},this.openingBracketBlock=function(a,b,c,e){var f={row:c,column:e+1},g=a.$findClosingBracket(b,f);if(!g)return;var h=a.foldWidgets[g.row];return h==null&&(h=this.getFoldWidget(a,g.row)),h=="start"&&(g.row--,g.column=a.getLine(g.row).length),d.fromPoints(f,g)}})).call(e.prototype)}),define("ace/mode/scala_highlight_rules",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/mode/doc_comment_highlight_rules","ace/mode/text_highlight_rules"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("../lib/lang"),f=a("./doc_comment_highlight_rules").DocCommentHighlightRules,g=a("./text_highlight_rules").TextHighlightRules,h=function(){var a=e.arrayToMap("case|default|do|else|for|if|match|while|throw|return|try|catch|finally|yield|abstract|class|def|extends|final|forSome|implicit|implicits|import|lazy|new|object|override|package|private|protected|sealed|super|this|trait|type|val|var|with".split("|")),b=e.arrayToMap("true|false".split("|")),c=e.arrayToMap("AbstractMethodError|AssertionError|ClassCircularityError|ClassFormatError|Deprecated|EnumConstantNotPresentException|ExceptionInInitializerError|IllegalAccessError|IllegalThreadStateException|InstantiationError|InternalError|NegativeArraySizeException|NoSuchFieldError|Override|Process|ProcessBuilder|SecurityManager|StringIndexOutOfBoundsException|SuppressWarnings|TypeNotPresentException|UnknownError|UnsatisfiedLinkError|UnsupportedClassVersionError|VerifyError|InstantiationException|IndexOutOfBoundsException|ArrayIndexOutOfBoundsException|CloneNotSupportedException|NoSuchFieldException|IllegalArgumentException|NumberFormatException|SecurityException|Void|InheritableThreadLocal|IllegalStateException|InterruptedException|NoSuchMethodException|IllegalAccessException|UnsupportedOperationException|Enum|StrictMath|Package|Compiler|Readable|Runtime|StringBuilder|Math|IncompatibleClassChangeError|NoSuchMethodError|ThreadLocal|RuntimePermission|ArithmeticException|NullPointerException|Long|Integer|Short|Byte|Double|Number|Float|Character|Boolean|StackTraceElement|Appendable|StringBuffer|Iterable|ThreadGroup|Runnable|Thread|IllegalMonitorStateException|StackOverflowError|OutOfMemoryError|VirtualMachineError|ArrayStoreException|ClassCastException|LinkageError|NoClassDefFoundError|ClassNotFoundException|RuntimeException|Exception|ThreadDeath|Error|Throwable|System|ClassLoader|Cloneable|Class|CharSequence|Comparable|String|Object|Unit|Any|AnyVal|AnyRef|Null|ScalaObject|Singleton|Seq|Iterable|List|Option|Array|Char|Byte|Short|Int|Long|Nothing".split("|")),d=e.arrayToMap("".split("|"));this.$rules={start:[{token:"comment",regex:"\\/\\/.*$"},(new f).getStartRule("doc-start"),{token:"comment",merge:!0,regex:"\\/\\*",next:"comment"},{token:"string.regexp",regex:"[/](?:(?:\\[(?:\\\\]|[^\\]])+\\])|(?:\\\\/|[^\\]/]))*[/]\\w*\\s*(?=[).,;]|$)"},{token:"string",regex:'["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'},{token:"string",regex:"['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"},{token:"constant.numeric",regex:"0[xX][0-9a-fA-F]+\\b"},{token:"constant.numeric",regex:"[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"},{token:"constant.language.boolean",regex:"(?:true|false)\\b"},{token:function(e){return e=="this"?"variable.language":a.hasOwnProperty(e)?"keyword":c.hasOwnProperty(e)?"support.function":d.hasOwnProperty(e)?"support.function":b.hasOwnProperty(e)?"constant.language":"identifier"},regex:"[a-zA-Z_$][a-zA-Z0-9_$]*\\b"},{token:"keyword.operator",regex:"!|\\$|%|&|\\*|\\-\\-|\\-|\\+\\+|\\+|~|===|==|=|!=|!==|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\\|\\||\\?\\:|\\*=|%=|\\+=|\\-=|&=|\\^=|\\b(?:in|instanceof|new|delete|typeof|void)"},{token:"paren.lparen",regex:"[[({]"},{token:"paren.rparen",regex:"[\\])}]"},{token:"text",regex:"\\s+"}],comment:[{token:"comment",regex:".*?\\*\\/",next:"start"},{token:"comment",merge:!0,regex:".+"}]},this.embedRules(f,"doc-",[(new f).getEndRule("start")])};d.inherits(h,g),b.ScalaHighlightRules=h}),function(){window.require(["ace/ace"],function(a){window.ace||(window.ace={});for(var b in a)a.hasOwnProperty(b)&&(ace[b]=a[b])})}()
\ No newline at end of file
+define("ace/mode/scala",["require","exports","module","ace/lib/oop","ace/mode/javascript","ace/tokenizer","ace/mode/scala_highlight_rules"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("./javascript").Mode,f=a("../tokenizer").Tokenizer,g=a("./scala_highlight_rules").ScalaHighlightRules,h=function(){e.call(this),this.$tokenizer=new f((new g).getRules())};d.inherits(h,e),function(){this.createWorker=function(a){return null}}.call(h.prototype),b.Mode=h}),define("ace/mode/javascript",["require","exports","module","ace/lib/oop","ace/mode/text","ace/tokenizer","ace/mode/javascript_highlight_rules","ace/mode/matching_brace_outdent","ace/range","ace/worker/worker_client","ace/mode/behaviour/cstyle","ace/mode/folding/cstyle"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("./text").Mode,f=a("../tokenizer").Tokenizer,g=a("./javascript_highlight_rules").JavaScriptHighlightRules,h=a("./matching_brace_outdent").MatchingBraceOutdent,i=a("../range").Range,j=a("../worker/worker_client").WorkerClient,k=a("./behaviour/cstyle").CstyleBehaviour,l=a("./folding/cstyle").FoldMode,m=function(){this.$tokenizer=new f((new g).getRules()),this.$outdent=new h,this.$behaviour=new k,this.foldingRules=new l};d.inherits(m,e),function(){this.toggleCommentLines=function(a,b,c,d){var e=!0,f=/^(\s*)\/\//;for(var g=c;g<=d;g++)if(!f.test(b.getLine(g))){e=!1;break}if(e){var h=new i(0,0,0,0);for(var g=c;g<=d;g++){var j=b.getLine(g),k=j.match(f);h.start.row=g,h.end.row=g,h.end.column=k[0].length,b.replace(h,k[1])}}else b.indentRows(c,d,"//")},this.getNextLineIndent=function(a,b,c){var d=this.$getIndent(b),e=this.$tokenizer.getLineTokens(b,a),f=e.tokens,g=e.state;if(f.length&&f[f.length-1].type=="comment")return d;if(a=="start"||a=="regex_allowed"){var h=b.match(/^.*(?:\bcase\b.*\:|[\{\(\[])\s*$/);h&&(d+=c)}else if(a=="doc-start"){if(g=="start"||a=="regex_allowed")return"";var h=b.match(/^\s*(\/?)\*/);h&&(h[1]&&(d+=" "),d+="* ")}return d},this.checkOutdent=function(a,b,c){return this.$outdent.checkOutdent(b,c)},this.autoOutdent=function(a,b,c){this.$outdent.autoOutdent(b,c)},this.createWorker=function(a){var b=new j(["ace"],"worker-javascript.js","ace/mode/javascript_worker","JavaScriptWorker");return b.attachToDocument(a.getDocument()),b.on("jslint",function(b){var c=[];for(var d=0;d<b.data.length;d++){var e=b.data[d];e&&c.push({row:e.line-1,column:e.character-1,text:e.reason,type:"warning",lint:e})}a.setAnnotations(c)}),b.on("narcissus",function(b){a.setAnnotations([b.data])}),b.on("terminate",function(){a.clearAnnotations()}),b}}.call(m.prototype),b.Mode=m}),define("ace/mode/javascript_highlight_rules",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/unicode","ace/mode/doc_comment_highlight_rules","ace/mode/text_highlight_rules"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("../lib/lang"),f=a("../unicode"),g=a("./doc_comment_highlight_rules").DocCommentHighlightRules,h=a("./text_highlight_rules").TextHighlightRules,i=function(){var a=e.arrayToMap("Array|Boolean|Date|Function|Iterator|Number|Object|RegExp|String|Proxy|Namespace|QName|XML|XMLList|ArrayBuffer|Float32Array|Float64Array|Int16Array|Int32Array|Int8Array|Uint16Array|Uint32Array|Uint8Array|Uint8ClampedArray|Error|EvalError|InternalError|RangeError|ReferenceError|StopIteration|SyntaxError|TypeError|URIError|decodeURI|decodeURIComponent|encodeURI|encodeURIComponent|eval|isFinite|isNaN|parseFloat|parseInt|JSON|Math|this|arguments|prototype|window|document".split("|")),b=e.arrayToMap("break|case|catch|continue|default|delete|do|else|finally|for|function|if|in|instanceof|new|return|switch|throw|try|typeof|let|var|while|with|const|yield|import|get|set".split("|")),c="case|do|else|finally|in|instanceof|return|throw|try|typeof|yield",d=e.arrayToMap("__parent__|__count__|escape|unescape|with|__proto__".split("|")),h=e.arrayToMap("const|let|var|function".split("|")),i=e.arrayToMap("null|Infinity|NaN|undefined".split("|")),j=e.arrayToMap("class|enum|extends|super|export|implements|private|public|interface|package|protected|static".split("|")),k="["+f.packages.L+"\\$_]["+f.packages.L+f.packages.Mn+f.packages.Mc+f.packages.Nd+f.packages.Pc+"\\$_]*\\b",l="\\\\(?:x[0-9a-fA-F]{2}|u[0-9a-fA-F]{4}|[0-2][0-7]{0,2}|3[0-6][0-7]?|37[0-7]?|[4-7][0-7]?|.)";this.$rules={start:[{token:"comment",regex:/\/\/.*$/},(new g).getStartRule("doc-start"),{token:"comment",merge:!0,regex:/\/\*/,next:"comment"},{token:"string",regex:"'",next:"qstring"},{token:"string",regex:'"',next:"qqstring"},{token:"constant.numeric",regex:/0[xX][0-9a-fA-F]+\b/},{token:"constant.numeric",regex:/[+-]?\d+(?:(?:\.\d*)?(?:[eE][+-]?\d+)?)?\b/},{token:["storage.type","punctuation.operator","support.function","punctuation.operator","entity.name.function","text","keyword.operator","text","storage.type","text","paren.lparen","variable.parameter","paren.rparen"],regex:"("+k+")(\\.)(prototype)(\\.)("+k+")(\\s*)(=)(\\s*)(function)(\\s*)(\\()(.*?)(\\))"},{token:["storage.type","punctuation.operator","support.function","punctuation.operator","entity.name.function","text","keyword.operator","text"],regex:"("+k+")(\\.)(prototype)(\\.)("+k+")(\\s*)(=)(\\s*)"},{token:["storage.type","punctuation.operator","entity.name.function","text","keyword.operator","text","storage.type","text","paren.lparen","variable.parameter","paren.rparen"],regex:"("+k+")(\\.)("+k+")(\\s*)(=)(\\s*)(function)(\\s*)(\\()(.*?)(\\))"},{token:["entity.name.function","text","keyword.operator","text","storage.type","text","paren.lparen","variable.parameter","paren.rparen"],regex:"("+k+")(\\s*)(=)(\\s*)(function)(\\s*)(\\()(.*?)(\\))"},{token:["storage.type","text","entity.name.function","text","paren.lparen","variable.parameter","paren.rparen"],regex:"(function)(\\s+)("+k+")(\\s*)(\\()(.*?)(\\))"},{token:["entity.name.function","text","punctuation.operator","text","storage.type","text","paren.lparen","variable.parameter","paren.rparen"],regex:"("+k+")(\\s*)(:)(\\s*)(function)(\\s*)(\\()(.*?)(\\))"},{token:["text","text","storage.type","text","paren.lparen","variable.parameter","paren.rparen"],regex:"(:)(\\s*)(function)?(\\s*)(\\()([^)]*)(\\))"},{token:"constant.language.boolean",regex:/(?:true|false)\b/},{token:"keyword",regex:"(?:"+c+")\\b",next:"regex_allowed"},{token:["punctuation.operator","support.function"],regex:/(\.)(s(?:h(?:ift|ow(?:Mod(?:elessDialog|alDialog)|Help))|croll(?:X|By(?:Pages|Lines)?|Y|To)?|t(?:opzzzz|rike)|i(?:n|zeToContent|debar|gnText)|ort|u(?:p|b(?:str(?:ing)?)?)|pli(?:ce|t)|e(?:nd|t(?:Re(?:sizable|questHeader)|M(?:i(?:nutes|lliseconds)|onth)|Seconds|Ho(?:tKeys|urs)|Year|Cursor|Time(?:out)?|Interval|ZOptions|Date|UTC(?:M(?:i(?:nutes|lliseconds)|onth)|Seconds|Hours|Date|FullYear)|FullYear|Active)|arch)|qrt|lice|avePreferences|mall)|h(?:ome|andleEvent)|navigate|c(?:har(?:CodeAt|At)|o(?:s|n(?:cat|textual|firm)|mpile)|eil|lear(?:Timeout|Interval)?|a(?:ptureEvents|ll)|reate(?:StyleSheet|Popup|EventObject))|t(?:o(?:GMTString|S(?:tring|ource)|U(?:TCString|pperCase)|Lo(?:caleString|werCase))|est|a(?:n|int(?:Enabled)?))|i(?:s(?:NaN|Finite)|ndexOf|talics)|d(?:isableExternalCapture|ump|etachEvent)|u(?:n(?:shift|taint|escape|watch)|pdateCommands)|j(?:oin|avaEnabled)|p(?:o(?:p|w)|ush|lugins.refresh|a(?:ddings|rse(?:Int|Float)?)|r(?:int|ompt|eference))|e(?:scape|nableExternalCapture|val|lementFromPoint|x(?:p|ec(?:Script|Command)?))|valueOf|UTC|queryCommand(?:State|Indeterm|Enabled|Value)|f(?:i(?:nd|le(?:ModifiedDate|Size|CreatedDate|UpdatedDate)|xed)|o(?:nt(?:size|color)|rward)|loor|romCharCode)|watch|l(?:ink|o(?:ad|g)|astIndexOf)|a(?:sin|nchor|cos|t(?:tachEvent|ob|an(?:2)?)|pply|lert|b(?:s|ort))|r(?:ou(?:nd|teEvents)|e(?:size(?:By|To)|calc|turnValue|place|verse|l(?:oad|ease(?:Capture|Events)))|andom)|g(?:o|et(?:ResponseHeader|M(?:i(?:nutes|lliseconds)|onth)|Se(?:conds|lection)|Hours|Year|Time(?:zoneOffset)?|Da(?:y|te)|UTC(?:M(?:i(?:nutes|lliseconds)|onth)|Seconds|Hours|Da(?:y|te)|FullYear)|FullYear|A(?:ttention|llResponseHeaders)))|m(?:in|ove(?:B(?:y|elow)|To(?:Absolute)?|Above)|ergeAttributes|a(?:tch|rgins|x))|b(?:toa|ig|o(?:ld|rderWidths)|link|ack))\b(?=\()/},{token:["punctuation.operator","support.function.dom"],regex:/(\.)(s(?:ub(?:stringData|mit)|plitText|e(?:t(?:NamedItem|Attribute(?:Node)?)|lect))|has(?:ChildNodes|Feature)|namedItem|c(?:l(?:ick|o(?:se|neNode))|reate(?:C(?:omment|DATASection|aption)|T(?:Head|extNode|Foot)|DocumentFragment|ProcessingInstruction|E(?:ntityReference|lement)|Attribute))|tabIndex|i(?:nsert(?:Row|Before|Cell|Data)|tem)|open|delete(?:Row|C(?:ell|aption)|T(?:Head|Foot)|Data)|focus|write(?:ln)?|a(?:dd|ppend(?:Child|Data))|re(?:set|place(?:Child|Data)|move(?:NamedItem|Child|Attribute(?:Node)?)?)|get(?:NamedItem|Element(?:sBy(?:Name|TagName)|ById)|Attribute(?:Node)?)|blur)\b(?=\()/},{token:["punctuation.operator","support.constant"],regex:/(\.)(s(?:ystemLanguage|cr(?:ipts|ollbars|een(?:X|Y|Top|Left))|t(?:yle(?:Sheets)?|atus(?:Text|bar)?)|ibling(?:Below|Above)|ource|uffixes|e(?:curity(?:Policy)?|l(?:ection|f)))|h(?:istory|ost(?:name)?|as(?:h|Focus))|y|X(?:MLDocument|SLDocument)|n(?:ext|ame(?:space(?:s|URI)|Prop))|M(?:IN_VALUE|AX_VALUE)|c(?:haracterSet|o(?:n(?:structor|trollers)|okieEnabled|lorDepth|mp(?:onents|lete))|urrent|puClass|l(?:i(?:p(?:boardData)?|entInformation)|osed|asses)|alle(?:e|r)|rypto)|t(?:o(?:olbar|p)|ext(?:Transform|Indent|Decoration|Align)|ags)|SQRT(?:1_2|2)|i(?:n(?:ner(?:Height|Width)|put)|ds|gnoreCase)|zIndex|o(?:scpu|n(?:readystatechange|Line)|uter(?:Height|Width)|p(?:sProfile|ener)|ffscreenBuffering)|NEGATIVE_INFINITY|d(?:i(?:splay|alog(?:Height|Top|Width|Left|Arguments)|rectories)|e(?:scription|fault(?:Status|Ch(?:ecked|arset)|View)))|u(?:ser(?:Profile|Language|Agent)|n(?:iqueID|defined)|pdateInterval)|_content|p(?:ixelDepth|ort|ersonalbar|kcs11|l(?:ugins|atform)|a(?:thname|dding(?:Right|Bottom|Top|Left)|rent(?:Window|Layer)?|ge(?:X(?:Offset)?|Y(?:Offset)?))|r(?:o(?:to(?:col|type)|duct(?:Sub)?|mpter)|e(?:vious|fix)))|e(?:n(?:coding|abledPlugin)|x(?:ternal|pando)|mbeds)|v(?:isibility|endor(?:Sub)?|Linkcolor)|URLUnencoded|P(?:I|OSITIVE_INFINITY)|f(?:ilename|o(?:nt(?:Size|Family|Weight)|rmName)|rame(?:s|Element)|gColor)|E|whiteSpace|l(?:i(?:stStyleType|n(?:eHeight|kColor))|o(?:ca(?:tion(?:bar)?|lName)|wsrc)|e(?:ngth|ft(?:Context)?)|a(?:st(?:M(?:odified|atch)|Index|Paren)|yer(?:s|X)|nguage))|a(?:pp(?:MinorVersion|Name|Co(?:deName|re)|Version)|vail(?:Height|Top|Width|Left)|ll|r(?:ity|guments)|Linkcolor|bove)|r(?:ight(?:Context)?|e(?:sponse(?:XML|Text)|adyState))|global|x|m(?:imeTypes|ultiline|enubar|argin(?:Right|Bottom|Top|Left))|L(?:N(?:10|2)|OG(?:10E|2E))|b(?:o(?:ttom|rder(?:Width|RightWidth|BottomWidth|Style|Color|TopWidth|LeftWidth))|ufferDepth|elow|ackground(?:Color|Image)))\b/},{token:["storage.type","punctuation.operator","support.function.firebug"],regex:/(console)(\.)(warn|info|log|error|time|timeEnd|assert)\b/},{token:function(c){return a.hasOwnProperty(c)?"variable.language":d.hasOwnProperty(c)?"invalid.deprecated":h.hasOwnProperty(c)?"storage.type":b.hasOwnProperty(c)?"keyword":i.hasOwnProperty(c)?"constant.language":j.hasOwnProperty(c)?"invalid.illegal":c=="debugger"?"invalid.deprecated":"identifier"},regex:k},{token:"keyword.operator",regex:/!|\$|%|&|\*|\-\-|\-|\+\+|\+|~|===|==|=|!=|!==|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\|\||\?\:|\*=|%=|\+=|\-=|&=|\^=|\b(?:in|instanceof|new|delete|typeof|void)/,next:"regex_allowed"},{token:"punctuation.operator",regex:/\?|\:|\,|\;|\./,next:"regex_allowed"},{token:"paren.lparen",regex:/[\[({]/,next:"regex_allowed"},{token:"paren.rparen",regex:/[\])}]/},{token:"keyword.operator",regex:/\/=?/,next:"regex_allowed"},{token:"comment",regex:/^#!.*$/},{token:"text",regex:/\s+/}],regex_allowed:[{token:"comment",merge:!0,regex:"\\/\\*",next:"comment_regex_allowed"},{token:"comment",regex:"\\/\\/.*$"},{token:"string.regexp",regex:"\\/",next:"regex",merge:!0},{token:"text",regex:"\\s+"},{token:"empty",regex:"",next:"start"}],regex:[{token:"regexp.keyword.operator",regex:"\\\\(?:u[\\da-fA-F]{4}|x[\\da-fA-F]{2}|.)",next:"regex"},{token:"string.regexp",regex:"/\\w*",next:"start",merge:!0},{token:"string.regexp",regex:"[^\\\\/\\[]+",next:"regex",merge:!0},{token:"string.regexp.charachterclass",regex:"\\[",next:"regex_character_class",merge:!0},{token:"empty",regex:"",next:"start"}],regex_character_class:[{token:"regexp.keyword.operator",regex:"\\\\(?:u[\\da-fA-F]{4}|x[\\da-fA-F]{2}|.)",next:"regex_character_class"},{token:"string.regexp.charachterclass",regex:"]",next:"regex",merge:!0},{token:"string.regexp.charachterclass",regex:"[^\\\\\\]]+",next:"regex_character_class",merge:!0},{token:"empty",regex:"",next:"start"}],comment_regex_allowed:[{token:"comment",regex:".*?\\*\\/",merge:!0,next:"regex_allowed"},{token:"comment",merge:!0,regex:".+"}],comment:[{token:"comment",regex:".*?\\*\\/",merge:!0,next:"start"},{token:"comment",merge:!0,regex:".+"}],qqstring:[{token:"constant.language.escape",regex:l},{token:"string",regex:'[^"\\\\]+'},{token:"string",regex:'"',next:"start"}],qstring:[{token:"constant.language.escape",regex:l},{token:"string",regex:"[^'\\\\]+"},{token:"string",regex:"'",next:"start"}]},this.embedRules(g,"doc-",[(new g).getEndRule("start")])};d.inherits(i,h),b.JavaScriptHighlightRules=i}),define("ace/mode/doc_comment_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("./text_highlight_rules").TextHighlightRules,f=function(){this.$rules={start:[{token:"comment.doc.tag",regex:"@[\\w\\d_]+"},{token:"comment.doc",merge:!0,regex:"\\s+"},{token:"comment.doc",merge:!0,regex:"TODO"},{token:"comment.doc",merge:!0,regex:"[^@\\*]+"},{token:"comment.doc",merge:!0,regex:"."}]}};d.inherits(f,e),function(){this.getStartRule=function(a){return{token:"comment.doc",merge:!0,regex:"\\/\\*(?=\\*)",next:a}},this.getEndRule=function(a){return{token:"comment.doc",merge:!0,regex:"\\*\\/",next:a}}}.call(f.prototype),b.DocCommentHighlightRules=f}),define("ace/mode/matching_brace_outdent",["require","exports","module","ace/range"],function(a,b,c){"use strict";var d=a("../range").Range,e=function(){};(function(){this.checkOutdent=function(a,b){return/^\s+$/.test(a)?/^\s*\}/.test(b):!1},this.autoOutdent=function(a,b){var c=a.getLine(b),e=c.match(/^(\s*\})/);if(!e)return 0;var f=e[1].length,g=a.findMatchingBracket({row:b,column:f});if(!g||g.row==b)return 0;var h=this.$getIndent(a.getLine(g.row));a.replace(new d(b,0,b,f-1),h)},this.$getIndent=function(a){var b=a.match(/^(\s+)/);return b?b[1]:""}}).call(e.prototype),b.MatchingBraceOutdent=e}),define("ace/mode/behaviour/cstyle",["require","exports","module","ace/lib/oop","ace/mode/behaviour"],function(a,b,c){"use strict";var d=a("../../lib/oop"),e=a("../behaviour").Behaviour,f=function(){this.add("braces","insertion",function(a,b,c,d,e){if(e=="{"){var f=c.getSelectionRange(),g=d.doc.getTextRange(f);return g!==""?{text:"{"+g+"}",selection:!1}:{text:"{}",selection:[1,1]}}if(e=="}"){var h=c.getCursorPosition(),i=d.doc.getLine(h.row),j=i.substring(h.column,h.column+1);if(j=="}"){var k=d.$findOpeningBracket("}",{column:h.column+1,row:h.row});if(k!==null)return{text:"",selection:[1,1]}}}else if(e=="\n"){var h=c.getCursorPosition(),i=d.doc.getLine(h.row),j=i.substring(h.column,h.column+1);if(j=="}"){var l=d.findMatchingBracket({row:h.row,column:h.column+1});if(!l)return null;var m=this.getNextLineIndent(a,i.substring(0,i.length-1),d.getTabString()),n=this.$getIndent(d.doc.getLine(l.row));return{text:"\n"+m+"\n"+n,selection:[1,m.length,1,m.length]}}}}),this.add("braces","deletion",function(a,b,c,d,e){var f=d.doc.getTextRange(e);if(!e.isMultiLine()&&f=="{"){var g=d.doc.getLine(e.start.row),h=g.substring(e.end.column,e.end.column+1);if(h=="}")return e.end.column++,e}}),this.add("parens","insertion",function(a,b,c,d,e){if(e=="("){var f=c.getSelectionRange(),g=d.doc.getTextRange(f);return g!==""?{text:"("+g+")",selection:!1}:{text:"()",selection:[1,1]}}if(e==")"){var h=c.getCursorPosition(),i=d.doc.getLine(h.row),j=i.substring(h.column,h.column+1);if(j==")"){var k=d.$findOpeningBracket(")",{column:h.column+1,row:h.row});if(k!==null)return{text:"",selection:[1,1]}}}}),this.add("parens","deletion",function(a,b,c,d,e){var f=d.doc.getTextRange(e);if(!e.isMultiLine()&&f=="("){var g=d.doc.getLine(e.start.row),h=g.substring(e.start.column+1,e.start.column+2);if(h==")")return e.end.column++,e}}),this.add("string_dquotes","insertion",function(a,b,c,d,e){if(e=='"'||e=="'"){var f=e,g=c.getSelectionRange(),h=d.doc.getTextRange(g);if(h!=="")return{text:f+h+f,selection:!1};var i=c.getCursorPosition(),j=d.doc.getLine(i.row),k=j.substring(i.column-1,i.column);if(k=="\\")return null;var l=d.getTokens(g.start.row,g.start.row)[0].tokens,m=0,n,o=-1;for(var p=0;p<l.length;p++){n=l[p],n.type=="string"?o=-1:o<0&&(o=n.value.indexOf(f));if(n.value.length+m>g.start.column)break;m+=l[p].value.length}if(!n||o<0&&n.type!=="comment"&&(n.type!=="string"||g.start.column!==n.value.length+m-1&&n.value.lastIndexOf(f)===n.value.length-1))return{text:f+f,selection:[1,1]};if(n&&n.type==="string"){var q=j.substring(i.column,i.column+1);if(q==f)return{text:"",selection:[1,1]}}}}),this.add("string_dquotes","deletion",function(a,b,c,d,e){var f=d.doc.getTextRange(e);if(!e.isMultiLine()&&(f=='"'||f=="'")){var g=d.doc.getLine(e.start.row),h=g.substring(e.start.column+1,e.start.column+2);if(h=='"')return e.end.column++,e}})};d.inherits(f,e),b.CstyleBehaviour=f}),define("ace/mode/folding/cstyle",["require","exports","module","ace/lib/oop","ace/range","ace/mode/folding/fold_mode"],function(a,b,c){"use strict";var d=a("../../lib/oop"),e=a("../../range").Range,f=a("./fold_mode").FoldMode,g=b.FoldMode=function(){};d.inherits(g,f),function(){this.foldingStartMarker=/(\{|\[)[^\}\]]*$|^\s*(\/\*)/,this.foldingStopMarker=/^[^\[\{]*(\}|\])|^[\s\*]*(\*\/)/,this.getFoldWidgetRange=function(a,b,c){var d=a.getLine(c),f=d.match(this.foldingStartMarker);if(f){var g=f.index;if(f[1])return this.openingBracketBlock(a,f[1],c,g);var h=a.getCommentFoldRange(c,g+f[0].length);return h.end.column-=2,h}if(b!=="markbeginend")return;var f=d.match(this.foldingStopMarker);if(f){var g=f.index+f[0].length;if(f[2]){var h=a.getCommentFoldRange(c,g);return h.end.column-=2,h}var i={row:c,column:g},j=a.$findOpeningBracket(f[1],i);if(!j)return;return j.column++,i.column--,e.fromPoints(j,i)}}}.call(g.prototype)}),define("ace/mode/folding/fold_mode",["require","exports","module","ace/range"],function(a,b,c){"use strict";var d=a("../../range").Range,e=b.FoldMode=function(){};(function(){this.foldingStartMarker=null,this.foldingStopMarker=null,this.getFoldWidget=function(a,b,c){var d=a.getLine(c);return this.foldingStartMarker.test(d)?"start":b=="markbeginend"&&this.foldingStopMarker&&this.foldingStopMarker.test(d)?"end":""},this.getFoldWidgetRange=function(a,b,c){return null},this.indentationBlock=function(a,b,c){var e=/^\s*/,f=b,g=b,h=a.getLine(b),i=c||h.length,j=h.match(e)[0].length,k=a.getLength();while(++b<k){h=a.getLine(b);var l=h.match(e)[0].length;if(l==h.length)continue;if(l<=j)break;g=b}if(g>f){var m=a.getLine(g).length;return new d(f,i,g,m)}},this.openingBracketBlock=function(a,b,c,e){var f={row:c,column:e+1},g=a.$findClosingBracket(b,f);if(!g)return;var h=a.foldWidgets[g.row];return h==null&&(h=this.getFoldWidget(a,g.row)),h=="start"&&(g.row--,g.column=a.getLine(g.row).length),d.fromPoints(f,g)}}).call(e.prototype)}),define("ace/mode/scala_highlight_rules",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/mode/doc_comment_highlight_rules","ace/mode/text_highlight_rules"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("../lib/lang"),f=a("./doc_comment_highlight_rules").DocCommentHighlightRules,g=a("./text_highlight_rules").TextHighlightRules,h=function(){var a=e.arrayToMap("case|default|do|else|for|if|match|while|throw|return|try|catch|finally|yield|abstract|class|def|extends|final|forSome|implicit|implicits|import|lazy|new|object|override|package|private|protected|sealed|super|this|trait|type|val|var|with".split("|")),b=e.arrayToMap("true|false".split("|")),c=e.arrayToMap("AbstractMethodError|AssertionError|ClassCircularityError|ClassFormatError|Deprecated|EnumConstantNotPresentException|ExceptionInInitializerError|IllegalAccessError|IllegalThreadStateException|InstantiationError|InternalError|NegativeArraySizeException|NoSuchFieldError|Override|Process|ProcessBuilder|SecurityManager|StringIndexOutOfBoundsException|SuppressWarnings|TypeNotPresentException|UnknownError|UnsatisfiedLinkError|UnsupportedClassVersionError|VerifyError|InstantiationException|IndexOutOfBoundsException|ArrayIndexOutOfBoundsException|CloneNotSupportedException|NoSuchFieldException|IllegalArgumentException|NumberFormatException|SecurityException|Void|InheritableThreadLocal|IllegalStateException|InterruptedException|NoSuchMethodException|IllegalAccessException|UnsupportedOperationException|Enum|StrictMath|Package|Compiler|Readable|Runtime|StringBuilder|Math|IncompatibleClassChangeError|NoSuchMethodError|ThreadLocal|RuntimePermission|ArithmeticException|NullPointerException|Long|Integer|Short|Byte|Double|Number|Float|Character|Boolean|StackTraceElement|Appendable|StringBuffer|Iterable|ThreadGroup|Runnable|Thread|IllegalMonitorStateException|StackOverflowError|OutOfMemoryError|VirtualMachineError|ArrayStoreException|ClassCastException|LinkageError|NoClassDefFoundError|ClassNotFoundException|RuntimeException|Exception|ThreadDeath|Error|Throwable|System|ClassLoader|Cloneable|Class|CharSequence|Comparable|String|Object|Unit|Any|AnyVal|AnyRef|Null|ScalaObject|Singleton|Seq|Iterable|List|Option|Array|Char|Byte|Short|Int|Long|Nothing".split("|")),d=e.arrayToMap("".split("|"));this.$rules={start:[{token:"comment",regex:"\\/\\/.*$"},(new f).getStartRule("doc-start"),{token:"comment",merge:!0,regex:"\\/\\*",next:"comment"},{token:"string.regexp",regex:"[/](?:(?:\\[(?:\\\\]|[^\\]])+\\])|(?:\\\\/|[^\\]/]))*[/]\\w*\\s*(?=[).,;]|$)"},{token:"string",regex:'["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'},{token:"string",regex:"['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"},{token:"constant.numeric",regex:"0[xX][0-9a-fA-F]+\\b"},{token:"constant.numeric",regex:"[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"},{token:"constant.language.boolean",regex:"(?:true|false)\\b"},{token:function(e){return e=="this"?"variable.language":a.hasOwnProperty(e)?"keyword":c.hasOwnProperty(e)?"support.function":d.hasOwnProperty(e)?"support.function":b.hasOwnProperty(e)?"constant.language":"identifier"},regex:"[a-zA-Z_$][a-zA-Z0-9_$]*\\b"},{token:"keyword.operator",regex:"!|\\$|%|&|\\*|\\-\\-|\\-|\\+\\+|\\+|~|===|==|=|!=|!==|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\\|\\||\\?\\:|\\*=|%=|\\+=|\\-=|&=|\\^=|\\b(?:in|instanceof|new|delete|typeof|void)"},{token:"paren.lparen",regex:"[[({]"},{token:"paren.rparen",regex:"[\\])}]"},{token:"text",regex:"\\s+"}],comment:[{token:"comment",regex:".*?\\*\\/",next:"start"},{token:"comment",merge:!0,regex:".+"}]},this.embedRules(f,"doc-",[(new f).getEndRule("start")])};d.inherits(h,g),b.ScalaHighlightRules=h})
\ No newline at end of file
diff --git a/apps/files_texteditor/js/aceeditor/mode-scss-uncompressed.js b/apps/files_texteditor/js/aceeditor/mode-scss-uncompressed.js
old mode 100755
new mode 100644
index 9639f0d4d2a7d35731db9e1d283285efe85a55f5..fc6d611f261d7636d10f9f5d7c1e4e0c1c95f00a
--- a/apps/files_texteditor/js/aceeditor/mode-scss-uncompressed.js
+++ b/apps/files_texteditor/js/aceeditor/mode-scss-uncompressed.js
@@ -676,13 +676,3 @@ var FoldMode = exports.FoldMode = function() {};
 }).call(FoldMode.prototype);
 
 });
-;
-            (function() {
-                window.require(["ace/ace"], function(a) {
-                    if (!window.ace)
-                        window.ace = {};
-                    for (var key in a) if (a.hasOwnProperty(key))
-                        ace[key] = a[key];
-                });
-            })();
-        
\ No newline at end of file
diff --git a/apps/files_texteditor/js/aceeditor/mode-scss.js b/apps/files_texteditor/js/aceeditor/mode-scss.js
index 3f63dc4305dfc753f268c09b89ab23cde8d75ec1..214bfe3485998955d121f19214505ad93ecc9215 100644
--- a/apps/files_texteditor/js/aceeditor/mode-scss.js
+++ b/apps/files_texteditor/js/aceeditor/mode-scss.js
@@ -1 +1 @@
-define("ace/mode/scss",["require","exports","module","ace/lib/oop","ace/mode/text","ace/tokenizer","ace/mode/scss_highlight_rules","ace/mode/matching_brace_outdent","ace/mode/folding/cstyle"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("./text").Mode,f=a("../tokenizer").Tokenizer,g=a("./scss_highlight_rules").ScssHighlightRules,h=a("./matching_brace_outdent").MatchingBraceOutdent,i=a("./folding/cstyle").FoldMode,j=function(){this.$tokenizer=new f((new g).getRules(),"i"),this.$outdent=new h,this.foldingRules=new i};d.inherits(j,e),function(){this.getNextLineIndent=function(a,b,c){var d=this.$getIndent(b),e=this.$tokenizer.getLineTokens(b,a).tokens;if(e.length&&e[e.length-1].type=="comment")return d;var f=b.match(/^.*\{\s*$/);return f&&(d+=c),d},this.checkOutdent=function(a,b,c){return this.$outdent.checkOutdent(b,c)},this.autoOutdent=function(a,b,c){this.$outdent.autoOutdent(b,c)}}.call(j.prototype),b.Mode=j}),define("ace/mode/scss_highlight_rules",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/mode/text_highlight_rules"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("../lib/lang"),f=a("./text_highlight_rules").TextHighlightRules,g=function(){var a=e.arrayToMap(function(){var a="-webkit-|-moz-|-o-|-ms-|-svg-|-pie-|-khtml-".split("|"),b="appearance|background-clip|background-inline-policy|background-origin|background-size|binding|border-bottom-colors|border-left-colors|border-right-colors|border-top-colors|border-end|border-end-color|border-end-style|border-end-width|border-image|border-start|border-start-color|border-start-style|border-start-width|box-align|box-direction|box-flex|box-flexgroup|box-ordinal-group|box-orient|box-pack|box-sizing|column-count|column-gap|column-width|column-rule|column-rule-width|column-rule-style|column-rule-color|float-edge|font-feature-settings|font-language-override|force-broken-image-icon|image-region|margin-end|margin-start|opacity|outline|outline-color|outline-offset|outline-radius|outline-radius-bottomleft|outline-radius-bottomright|outline-radius-topleft|outline-radius-topright|outline-style|outline-width|padding-end|padding-start|stack-sizing|tab-size|text-blink|text-decoration-color|text-decoration-line|text-decoration-style|transform|transform-origin|transition|transition-delay|transition-duration|transition-property|transition-timing-function|user-focus|user-input|user-modify|user-select|window-shadow|border-radius".split("|"),c="azimuth|background-attachment|background-color|background-image|background-position|background-repeat|background|border-bottom-color|border-bottom-style|border-bottom-width|border-bottom|border-collapse|border-color|border-left-color|border-left-style|border-left-width|border-left|border-right-color|border-right-style|border-right-width|border-right|border-spacing|border-style|border-top-color|border-top-style|border-top-width|border-top|border-width|border|bottom|box-sizing|caption-side|clear|clip|color|content|counter-increment|counter-reset|cue-after|cue-before|cue|cursor|direction|display|elevation|empty-cells|float|font-family|font-size-adjust|font-size|font-stretch|font-style|font-variant|font-weight|font|height|left|letter-spacing|line-height|list-style-image|list-style-position|list-style-type|list-style|margin-bottom|margin-left|margin-right|margin-top|marker-offset|margin|marks|max-height|max-width|min-height|min-width|opacity|orphans|outline-color|outline-style|outline-width|outline|overflow|overflow-x|overflow-y|padding-bottom|padding-left|padding-right|padding-top|padding|page-break-after|page-break-before|page-break-inside|page|pause-after|pause-before|pause|pitch-range|pitch|play-during|position|quotes|richness|right|size|speak-header|speak-numeral|speak-punctuation|speech-rate|speak|stress|table-layout|text-align|text-decoration|text-indent|text-shadow|text-transform|top|unicode-bidi|vertical-align|visibility|voice-family|volume|white-space|widows|width|word-spacing|z-index".split("|"),d=[];for(var e=0,f=a.length;e<f;e++)Array.prototype.push.apply(d,(a[e]+b.join("|"+a[e])).split("|"));return Array.prototype.push.apply(d,b),Array.prototype.push.apply(d,c),d}()),b=e.arrayToMap("hsl|hsla|rgb|rgba|url|attr|counter|counters|abs|adjust_color|adjust_hue|alpha|join|blue|ceil|change_color|comparable|complement|darken|desaturate|floor|grayscale|green|hue|if|invert|join|length|lighten|lightness|mix|nth|opacify|opacity|percentage|quote|red|round|saturate|saturation|scale_color|transparentize|type_of|unit|unitless|unqoute".split("|")),c=e.arrayToMap("absolute|all-scroll|always|armenian|auto|baseline|below|bidi-override|block|bold|bolder|border-box|both|bottom|break-all|break-word|capitalize|center|char|circle|cjk-ideographic|col-resize|collapse|content-box|crosshair|dashed|decimal-leading-zero|decimal|default|disabled|disc|distribute-all-lines|distribute-letter|distribute-space|distribute|dotted|double|e-resize|ellipsis|fixed|georgian|groove|hand|hebrew|help|hidden|hiragana-iroha|hiragana|horizontal|ideograph-alpha|ideograph-numeric|ideograph-parenthesis|ideograph-space|inactive|inherit|inline-block|inline|inset|inside|inter-ideograph|inter-word|italic|justify|katakana-iroha|katakana|keep-all|left|lighter|line-edge|line-through|line|list-item|loose|lower-alpha|lower-greek|lower-latin|lower-roman|lowercase|lr-tb|ltr|medium|middle|move|n-resize|ne-resize|newspaper|no-drop|no-repeat|nw-resize|none|normal|not-allowed|nowrap|oblique|outset|outside|overline|pointer|progress|relative|repeat-x|repeat-y|repeat|right|ridge|row-resize|rtl|s-resize|scroll|se-resize|separate|small-caps|solid|square|static|strict|super|sw-resize|table-footer-group|table-header-group|tb-rl|text-bottom|text-top|text|thick|thin|top|transparent|underline|upper-alpha|upper-latin|upper-roman|uppercase|vertical-ideographic|vertical-text|visible|w-resize|wait|whitespace|zero".split("|")),d=e.arrayToMap("aqua|black|blue|fuchsia|gray|green|lime|maroon|navy|olive|orange|purple|red|silver|teal|white|yellow".split("|")),f=e.arrayToMap("@mixin|@extend|@include|@import|@media|@debug|@warn|@if|@for|@each|@while|@else|@font-face|@-webkit-keyframes|if|and|!default|module|def|end|declare".split("|")),g=e.arrayToMap("a|abbr|acronym|address|applet|area|article|aside|audio|b|base|basefont|bdo|big|blockquote|body|br|button|canvas|caption|center|cite|code|col|colgroup|command|datalist|dd|del|details|dfn|dir|div|dl|dt|em|embed|fieldset|figcaption|figure|font|footer|form|frame|frameset|h1|h2|h3|h4|h5|h6|head|header|hgroup|hr|html|i|iframe|img|input|ins|keygen|kbd|label|legend|li|link|map|mark|menu|meta|meter|nav|noframes|noscript|object|ol|optgroup|option|output|p|param|pre|progress|q|rp|rt|ruby|s|samp|script|section|select|small|source|span|strike|strong|style|sub|summary|sup|table|tbody|td|textarea|tfoot|th|thead|time|title|tr|tt|u|ul|var|video|wbr|xmp".split("|")),h="\\-?(?:(?:[0-9]+)|(?:[0-9]*\\.[0-9]+))";this.$rules={start:[{token:"comment",regex:"\\/\\/.*$"},{token:"comment",merge:!0,regex:"\\/\\*",next:"comment"},{token:"string",regex:'["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'},{token:"string",merge:!0,regex:'["].*\\\\$',next:"qqstring"},{token:"string",regex:"['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"},{token:"string",merge:!0,regex:"['].*\\\\$",next:"qstring"},{token:"constant.numeric",regex:h+"(?:em|ex|px|cm|mm|in|pt|pc|deg|rad|grad|ms|s|hz|khz|%)"},{token:"constant.numeric",regex:"#[a-f0-9]{6}"},{token:"constant.numeric",regex:"#[a-f0-9]{3}"},{token:"constant.numeric",regex:h},{token:function(e){return a.hasOwnProperty(e.toLowerCase())?"support.type":f.hasOwnProperty(e)?"keyword":c.hasOwnProperty(e)?"constant.language":b.hasOwnProperty(e)?"support.function":d.hasOwnProperty(e.toLowerCase())?"support.constant.color":g.hasOwnProperty(e.toLowerCase())?"variable.language":"text"},regex:"\\-?[@a-z_][@a-z0-9_\\-]*"},{token:"variable",regex:"[a-z_\\-$][a-z0-9_\\-$]*\\b"},{token:"variable.language",regex:"#[a-z0-9-_]+"},{token:"variable.language",regex:"\\.[a-z0-9-_]+"},{token:"variable.language",regex:":[a-z0-9-_]+"},{token:"constant",regex:"[a-z0-9-_]+"},{token:"keyword.operator",regex:"<|>|<=|>=|==|!=|-|%|#|\\+|\\$|\\+|\\*"},{token:"paren.lparen",regex:"[[({]"},{token:"paren.rparen",regex:"[\\])}]"},{token:"text",regex:"\\s+"}],comment:[{token:"comment",regex:".*?\\*\\/",next:"start"},{token:"comment",merge:!0,regex:".+"}],qqstring:[{token:"string",regex:'(?:(?:\\\\.)|(?:[^"\\\\]))*?"',next:"start"},{token:"string",merge:!0,regex:".+"}],qstring:[{token:"string",regex:"(?:(?:\\\\.)|(?:[^'\\\\]))*?'",next:"start"},{token:"string",merge:!0,regex:".+"}]}};d.inherits(g,f),b.ScssHighlightRules=g}),define("ace/mode/matching_brace_outdent",["require","exports","module","ace/range"],function(a,b,c){"use strict";var d=a("../range").Range,e=function(){};((function(){this.checkOutdent=function(a,b){return/^\s+$/.test(a)?/^\s*\}/.test(b):!1},this.autoOutdent=function(a,b){var c=a.getLine(b),e=c.match(/^(\s*\})/);if(!e)return 0;var f=e[1].length,g=a.findMatchingBracket({row:b,column:f});if(!g||g.row==b)return 0;var h=this.$getIndent(a.getLine(g.row));a.replace(new d(b,0,b,f-1),h)},this.$getIndent=function(a){var b=a.match(/^(\s+)/);return b?b[1]:""}})).call(e.prototype),b.MatchingBraceOutdent=e}),define("ace/mode/folding/cstyle",["require","exports","module","ace/lib/oop","ace/range","ace/mode/folding/fold_mode"],function(a,b,c){"use strict";var d=a("../../lib/oop"),e=a("../../range").Range,f=a("./fold_mode").FoldMode,g=b.FoldMode=function(){};d.inherits(g,f),function(){this.foldingStartMarker=/(\{|\[)[^\}\]]*$|^\s*(\/\*)/,this.foldingStopMarker=/^[^\[\{]*(\}|\])|^[\s\*]*(\*\/)/,this.getFoldWidgetRange=function(a,b,c){var d=a.getLine(c),f=d.match(this.foldingStartMarker);if(f){var g=f.index;if(f[1])return this.openingBracketBlock(a,f[1],c,g);var h=a.getCommentFoldRange(c,g+f[0].length);return h.end.column-=2,h}if(b!=="markbeginend")return;var f=d.match(this.foldingStopMarker);if(f){var g=f.index+f[0].length;if(f[2]){var h=a.getCommentFoldRange(c,g);return h.end.column-=2,h}var i={row:c,column:g},j=a.$findOpeningBracket(f[1],i);if(!j)return;return j.column++,i.column--,e.fromPoints(j,i)}}}.call(g.prototype)}),define("ace/mode/folding/fold_mode",["require","exports","module","ace/range"],function(a,b,c){"use strict";var d=a("../../range").Range,e=b.FoldMode=function(){};((function(){this.foldingStartMarker=null,this.foldingStopMarker=null,this.getFoldWidget=function(a,b,c){var d=a.getLine(c);return this.foldingStartMarker.test(d)?"start":b=="markbeginend"&&this.foldingStopMarker&&this.foldingStopMarker.test(d)?"end":""},this.getFoldWidgetRange=function(a,b,c){return null},this.indentationBlock=function(a,b,c){var e=/^\s*/,f=b,g=b,h=a.getLine(b),i=c||h.length,j=h.match(e)[0].length,k=a.getLength();while(++b<k){h=a.getLine(b);var l=h.match(e)[0].length;if(l==h.length)continue;if(l<=j)break;g=b}if(g>f){var m=a.getLine(g).length;return new d(f,i,g,m)}},this.openingBracketBlock=function(a,b,c,e){var f={row:c,column:e+1},g=a.$findClosingBracket(b,f);if(!g)return;var h=a.foldWidgets[g.row];return h==null&&(h=this.getFoldWidget(a,g.row)),h=="start"&&(g.row--,g.column=a.getLine(g.row).length),d.fromPoints(f,g)}})).call(e.prototype)}),function(){window.require(["ace/ace"],function(a){window.ace||(window.ace={});for(var b in a)a.hasOwnProperty(b)&&(ace[b]=a[b])})}()
\ No newline at end of file
+define("ace/mode/scss",["require","exports","module","ace/lib/oop","ace/mode/text","ace/tokenizer","ace/mode/scss_highlight_rules","ace/mode/matching_brace_outdent","ace/mode/folding/cstyle"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("./text").Mode,f=a("../tokenizer").Tokenizer,g=a("./scss_highlight_rules").ScssHighlightRules,h=a("./matching_brace_outdent").MatchingBraceOutdent,i=a("./folding/cstyle").FoldMode,j=function(){this.$tokenizer=new f((new g).getRules(),"i"),this.$outdent=new h,this.foldingRules=new i};d.inherits(j,e),function(){this.getNextLineIndent=function(a,b,c){var d=this.$getIndent(b),e=this.$tokenizer.getLineTokens(b,a).tokens;if(e.length&&e[e.length-1].type=="comment")return d;var f=b.match(/^.*\{\s*$/);return f&&(d+=c),d},this.checkOutdent=function(a,b,c){return this.$outdent.checkOutdent(b,c)},this.autoOutdent=function(a,b,c){this.$outdent.autoOutdent(b,c)}}.call(j.prototype),b.Mode=j}),define("ace/mode/scss_highlight_rules",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/mode/text_highlight_rules"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("../lib/lang"),f=a("./text_highlight_rules").TextHighlightRules,g=function(){var a=e.arrayToMap(function(){var a="-webkit-|-moz-|-o-|-ms-|-svg-|-pie-|-khtml-".split("|"),b="appearance|background-clip|background-inline-policy|background-origin|background-size|binding|border-bottom-colors|border-left-colors|border-right-colors|border-top-colors|border-end|border-end-color|border-end-style|border-end-width|border-image|border-start|border-start-color|border-start-style|border-start-width|box-align|box-direction|box-flex|box-flexgroup|box-ordinal-group|box-orient|box-pack|box-sizing|column-count|column-gap|column-width|column-rule|column-rule-width|column-rule-style|column-rule-color|float-edge|font-feature-settings|font-language-override|force-broken-image-icon|image-region|margin-end|margin-start|opacity|outline|outline-color|outline-offset|outline-radius|outline-radius-bottomleft|outline-radius-bottomright|outline-radius-topleft|outline-radius-topright|outline-style|outline-width|padding-end|padding-start|stack-sizing|tab-size|text-blink|text-decoration-color|text-decoration-line|text-decoration-style|transform|transform-origin|transition|transition-delay|transition-duration|transition-property|transition-timing-function|user-focus|user-input|user-modify|user-select|window-shadow|border-radius".split("|"),c="azimuth|background-attachment|background-color|background-image|background-position|background-repeat|background|border-bottom-color|border-bottom-style|border-bottom-width|border-bottom|border-collapse|border-color|border-left-color|border-left-style|border-left-width|border-left|border-right-color|border-right-style|border-right-width|border-right|border-spacing|border-style|border-top-color|border-top-style|border-top-width|border-top|border-width|border|bottom|box-sizing|caption-side|clear|clip|color|content|counter-increment|counter-reset|cue-after|cue-before|cue|cursor|direction|display|elevation|empty-cells|float|font-family|font-size-adjust|font-size|font-stretch|font-style|font-variant|font-weight|font|height|left|letter-spacing|line-height|list-style-image|list-style-position|list-style-type|list-style|margin-bottom|margin-left|margin-right|margin-top|marker-offset|margin|marks|max-height|max-width|min-height|min-width|opacity|orphans|outline-color|outline-style|outline-width|outline|overflow|overflow-x|overflow-y|padding-bottom|padding-left|padding-right|padding-top|padding|page-break-after|page-break-before|page-break-inside|page|pause-after|pause-before|pause|pitch-range|pitch|play-during|position|quotes|richness|right|size|speak-header|speak-numeral|speak-punctuation|speech-rate|speak|stress|table-layout|text-align|text-decoration|text-indent|text-shadow|text-transform|top|unicode-bidi|vertical-align|visibility|voice-family|volume|white-space|widows|width|word-spacing|z-index".split("|"),d=[];for(var e=0,f=a.length;e<f;e++)Array.prototype.push.apply(d,(a[e]+b.join("|"+a[e])).split("|"));return Array.prototype.push.apply(d,b),Array.prototype.push.apply(d,c),d}()),b=e.arrayToMap("hsl|hsla|rgb|rgba|url|attr|counter|counters|abs|adjust_color|adjust_hue|alpha|join|blue|ceil|change_color|comparable|complement|darken|desaturate|floor|grayscale|green|hue|if|invert|join|length|lighten|lightness|mix|nth|opacify|opacity|percentage|quote|red|round|saturate|saturation|scale_color|transparentize|type_of|unit|unitless|unqoute".split("|")),c=e.arrayToMap("absolute|all-scroll|always|armenian|auto|baseline|below|bidi-override|block|bold|bolder|border-box|both|bottom|break-all|break-word|capitalize|center|char|circle|cjk-ideographic|col-resize|collapse|content-box|crosshair|dashed|decimal-leading-zero|decimal|default|disabled|disc|distribute-all-lines|distribute-letter|distribute-space|distribute|dotted|double|e-resize|ellipsis|fixed|georgian|groove|hand|hebrew|help|hidden|hiragana-iroha|hiragana|horizontal|ideograph-alpha|ideograph-numeric|ideograph-parenthesis|ideograph-space|inactive|inherit|inline-block|inline|inset|inside|inter-ideograph|inter-word|italic|justify|katakana-iroha|katakana|keep-all|left|lighter|line-edge|line-through|line|list-item|loose|lower-alpha|lower-greek|lower-latin|lower-roman|lowercase|lr-tb|ltr|medium|middle|move|n-resize|ne-resize|newspaper|no-drop|no-repeat|nw-resize|none|normal|not-allowed|nowrap|oblique|outset|outside|overline|pointer|progress|relative|repeat-x|repeat-y|repeat|right|ridge|row-resize|rtl|s-resize|scroll|se-resize|separate|small-caps|solid|square|static|strict|super|sw-resize|table-footer-group|table-header-group|tb-rl|text-bottom|text-top|text|thick|thin|top|transparent|underline|upper-alpha|upper-latin|upper-roman|uppercase|vertical-ideographic|vertical-text|visible|w-resize|wait|whitespace|zero".split("|")),d=e.arrayToMap("aqua|black|blue|fuchsia|gray|green|lime|maroon|navy|olive|orange|purple|red|silver|teal|white|yellow".split("|")),f=e.arrayToMap("@mixin|@extend|@include|@import|@media|@debug|@warn|@if|@for|@each|@while|@else|@font-face|@-webkit-keyframes|if|and|!default|module|def|end|declare".split("|")),g=e.arrayToMap("a|abbr|acronym|address|applet|area|article|aside|audio|b|base|basefont|bdo|big|blockquote|body|br|button|canvas|caption|center|cite|code|col|colgroup|command|datalist|dd|del|details|dfn|dir|div|dl|dt|em|embed|fieldset|figcaption|figure|font|footer|form|frame|frameset|h1|h2|h3|h4|h5|h6|head|header|hgroup|hr|html|i|iframe|img|input|ins|keygen|kbd|label|legend|li|link|map|mark|menu|meta|meter|nav|noframes|noscript|object|ol|optgroup|option|output|p|param|pre|progress|q|rp|rt|ruby|s|samp|script|section|select|small|source|span|strike|strong|style|sub|summary|sup|table|tbody|td|textarea|tfoot|th|thead|time|title|tr|tt|u|ul|var|video|wbr|xmp".split("|")),h="\\-?(?:(?:[0-9]+)|(?:[0-9]*\\.[0-9]+))";this.$rules={start:[{token:"comment",regex:"\\/\\/.*$"},{token:"comment",merge:!0,regex:"\\/\\*",next:"comment"},{token:"string",regex:'["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'},{token:"string",merge:!0,regex:'["].*\\\\$',next:"qqstring"},{token:"string",regex:"['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"},{token:"string",merge:!0,regex:"['].*\\\\$",next:"qstring"},{token:"constant.numeric",regex:h+"(?:em|ex|px|cm|mm|in|pt|pc|deg|rad|grad|ms|s|hz|khz|%)"},{token:"constant.numeric",regex:"#[a-f0-9]{6}"},{token:"constant.numeric",regex:"#[a-f0-9]{3}"},{token:"constant.numeric",regex:h},{token:function(e){return a.hasOwnProperty(e.toLowerCase())?"support.type":f.hasOwnProperty(e)?"keyword":c.hasOwnProperty(e)?"constant.language":b.hasOwnProperty(e)?"support.function":d.hasOwnProperty(e.toLowerCase())?"support.constant.color":g.hasOwnProperty(e.toLowerCase())?"variable.language":"text"},regex:"\\-?[@a-z_][@a-z0-9_\\-]*"},{token:"variable",regex:"[a-z_\\-$][a-z0-9_\\-$]*\\b"},{token:"variable.language",regex:"#[a-z0-9-_]+"},{token:"variable.language",regex:"\\.[a-z0-9-_]+"},{token:"variable.language",regex:":[a-z0-9-_]+"},{token:"constant",regex:"[a-z0-9-_]+"},{token:"keyword.operator",regex:"<|>|<=|>=|==|!=|-|%|#|\\+|\\$|\\+|\\*"},{token:"paren.lparen",regex:"[[({]"},{token:"paren.rparen",regex:"[\\])}]"},{token:"text",regex:"\\s+"}],comment:[{token:"comment",regex:".*?\\*\\/",next:"start"},{token:"comment",merge:!0,regex:".+"}],qqstring:[{token:"string",regex:'(?:(?:\\\\.)|(?:[^"\\\\]))*?"',next:"start"},{token:"string",merge:!0,regex:".+"}],qstring:[{token:"string",regex:"(?:(?:\\\\.)|(?:[^'\\\\]))*?'",next:"start"},{token:"string",merge:!0,regex:".+"}]}};d.inherits(g,f),b.ScssHighlightRules=g}),define("ace/mode/matching_brace_outdent",["require","exports","module","ace/range"],function(a,b,c){"use strict";var d=a("../range").Range,e=function(){};(function(){this.checkOutdent=function(a,b){return/^\s+$/.test(a)?/^\s*\}/.test(b):!1},this.autoOutdent=function(a,b){var c=a.getLine(b),e=c.match(/^(\s*\})/);if(!e)return 0;var f=e[1].length,g=a.findMatchingBracket({row:b,column:f});if(!g||g.row==b)return 0;var h=this.$getIndent(a.getLine(g.row));a.replace(new d(b,0,b,f-1),h)},this.$getIndent=function(a){var b=a.match(/^(\s+)/);return b?b[1]:""}}).call(e.prototype),b.MatchingBraceOutdent=e}),define("ace/mode/folding/cstyle",["require","exports","module","ace/lib/oop","ace/range","ace/mode/folding/fold_mode"],function(a,b,c){"use strict";var d=a("../../lib/oop"),e=a("../../range").Range,f=a("./fold_mode").FoldMode,g=b.FoldMode=function(){};d.inherits(g,f),function(){this.foldingStartMarker=/(\{|\[)[^\}\]]*$|^\s*(\/\*)/,this.foldingStopMarker=/^[^\[\{]*(\}|\])|^[\s\*]*(\*\/)/,this.getFoldWidgetRange=function(a,b,c){var d=a.getLine(c),f=d.match(this.foldingStartMarker);if(f){var g=f.index;if(f[1])return this.openingBracketBlock(a,f[1],c,g);var h=a.getCommentFoldRange(c,g+f[0].length);return h.end.column-=2,h}if(b!=="markbeginend")return;var f=d.match(this.foldingStopMarker);if(f){var g=f.index+f[0].length;if(f[2]){var h=a.getCommentFoldRange(c,g);return h.end.column-=2,h}var i={row:c,column:g},j=a.$findOpeningBracket(f[1],i);if(!j)return;return j.column++,i.column--,e.fromPoints(j,i)}}}.call(g.prototype)}),define("ace/mode/folding/fold_mode",["require","exports","module","ace/range"],function(a,b,c){"use strict";var d=a("../../range").Range,e=b.FoldMode=function(){};(function(){this.foldingStartMarker=null,this.foldingStopMarker=null,this.getFoldWidget=function(a,b,c){var d=a.getLine(c);return this.foldingStartMarker.test(d)?"start":b=="markbeginend"&&this.foldingStopMarker&&this.foldingStopMarker.test(d)?"end":""},this.getFoldWidgetRange=function(a,b,c){return null},this.indentationBlock=function(a,b,c){var e=/^\s*/,f=b,g=b,h=a.getLine(b),i=c||h.length,j=h.match(e)[0].length,k=a.getLength();while(++b<k){h=a.getLine(b);var l=h.match(e)[0].length;if(l==h.length)continue;if(l<=j)break;g=b}if(g>f){var m=a.getLine(g).length;return new d(f,i,g,m)}},this.openingBracketBlock=function(a,b,c,e){var f={row:c,column:e+1},g=a.$findClosingBracket(b,f);if(!g)return;var h=a.foldWidgets[g.row];return h==null&&(h=this.getFoldWidget(a,g.row)),h=="start"&&(g.row--,g.column=a.getLine(g.row).length),d.fromPoints(f,g)}}).call(e.prototype)})
\ No newline at end of file
diff --git a/apps/files_texteditor/js/aceeditor/mode-sh-uncompressed.js b/apps/files_texteditor/js/aceeditor/mode-sh-uncompressed.js
new file mode 100644
index 0000000000000000000000000000000000000000..c341067efb92ad8527f296ff32e2dfe19d8f0782
--- /dev/null
+++ b/apps/files_texteditor/js/aceeditor/mode-sh-uncompressed.js
@@ -0,0 +1,281 @@
+/* ***** BEGIN LICENSE BLOCK *****
+* Version: MPL 1.1/GPL 2.0/LGPL 2.1
+*
+* The contents of this file are subject to the Mozilla Public License Version
+* 1.1 (the "License"); you may not use this file except in compliance with
+* the License. You may obtain a copy of the License at
+* http://www.mozilla.org/MPL/
+*
+* Software distributed under the License is distributed on an "AS IS" basis,
+* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+* for the specific language governing rights and limitations under the
+* License.
+*
+* The Original Code is Ajax.org Code Editor (ACE).
+*
+* The Initial Developer of the Original Code is
+* Ajax.org B.V.
+* Portions created by the Initial Developer are Copyright (C) 2010
+* the Initial Developer. All Rights Reserved.
+*
+* Contributor(s):
+*      Rich Healey <richo AT psych0tik DOT net>
+*
+* Alternatively, the contents of this file may be used under the terms of
+* either the GNU General Public License Version 2 or later (the "GPL"), or
+* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+* in which case the provisions of the GPL or the LGPL are applicable instead
+* of those above. If you wish to allow use of your version of this file only
+* under the terms of either the GPL or the LGPL, and not to allow others to
+* use your version of this file under the terms of the MPL, indicate your
+* decision by deleting the provisions above and replace them with the notice
+* and other provisions required by the GPL or the LGPL. If you do not delete
+* the provisions above, a recipient may use your version of this file under
+* the terms of any one of the MPL, the GPL or the LGPL.
+*
+* ***** END LICENSE BLOCK ***** */
+
+define('ace/mode/sh', ['require', 'exports', 'module' , 'ace/lib/oop', 'ace/mode/text', 'ace/tokenizer', 'ace/mode/sh_highlight_rules', 'ace/range'], function(require, exports, module) {
+"use strict";
+
+var oop = require("../lib/oop");
+var TextMode = require("./text").Mode;
+var Tokenizer = require("../tokenizer").Tokenizer;
+var ShHighlightRules = require("./sh_highlight_rules").ShHighlightRules;
+var Range = require("../range").Range;
+
+var Mode = function() {
+    this.$tokenizer = new Tokenizer(new ShHighlightRules().getRules());
+};
+oop.inherits(Mode, TextMode);
+
+(function() {
+
+    this.toggleCommentLines = function(state, doc, startRow, endRow) {
+        var outdent = true;
+        var re = /^(\s*)#/;
+
+        for (var i=startRow; i<= endRow; i++) {
+            if (!re.test(doc.getLine(i))) {
+                outdent = false;
+                break;
+            }
+        }
+
+        if (outdent) {
+            var deleteRange = new Range(0, 0, 0, 0);
+            for (var i=startRow; i<= endRow; i++)
+            {
+                var line = doc.getLine(i);
+                var m = line.match(re);
+                deleteRange.start.row = i;
+                deleteRange.end.row = i;
+                deleteRange.end.column = m[0].length;
+                doc.replace(deleteRange, m[1]);
+            }
+        }
+        else {
+            doc.indentRows(startRow, endRow, "#");
+        }
+    };
+
+    this.getNextLineIndent = function(state, line, tab) {
+        var indent = this.$getIndent(line);
+
+        var tokenizedLine = this.$tokenizer.getLineTokens(line, state);
+        var tokens = tokenizedLine.tokens;
+
+        if (tokens.length && tokens[tokens.length-1].type == "comment") {
+            return indent;
+        }
+
+        if (state == "start") {
+            var match = line.match(/^.*[\{\(\[\:]\s*$/);
+            if (match) {
+                indent += tab;
+            }
+        }
+
+        return indent;
+    };
+
+    var outdents = {
+        "pass": 1,
+        "return": 1,
+        "raise": 1,
+        "break": 1,
+        "continue": 1
+    };
+
+    this.checkOutdent = function(state, line, input) {
+        if (input !== "\r\n" && input !== "\r" && input !== "\n")
+            return false;
+
+        var tokens = this.$tokenizer.getLineTokens(line.trim(), state).tokens;
+
+        if (!tokens)
+            return false;
+
+        // ignore trailing comments
+        do {
+            var last = tokens.pop();
+        } while (last && (last.type == "comment" || (last.type == "text" && last.value.match(/^\s+$/))));
+
+        if (!last)
+            return false;
+
+        return (last.type == "keyword" && outdents[last.value]);
+    };
+
+    this.autoOutdent = function(state, doc, row) {
+        // outdenting in sh is slightly different because it always applies
+        // to the next line and only of a new line is inserted
+
+        row += 1;
+        var indent = this.$getIndent(doc.getLine(row));
+        var tab = doc.getTabString();
+        if (indent.slice(-tab.length) == tab)
+            doc.remove(new Range(row, indent.length-tab.length, row, indent.length));
+    };
+
+}).call(Mode.prototype);
+
+exports.Mode = Mode;
+});
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Ajax.org Code Editor (ACE).
+ *
+ * The Initial Developer of the Original Code is
+ * Ajax.org B.V.
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *      Rich Healey <richo AT psych0tik DOT net>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK *****
+ */
+define('ace/mode/sh_highlight_rules', ['require', 'exports', 'module' , 'ace/lib/oop', 'ace/lib/lang', 'ace/mode/text_highlight_rules'], function(require, exports, module) {
+"use strict";
+
+var oop = require("../lib/oop");
+var lang = require("../lib/lang");
+var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
+
+var ShHighlightRules = function() {
+
+    var reservedKeywords = lang.arrayToMap(
+        ('!|{|}|case|do|done|elif|else|'+
+        'esac|fi|for|if|in|then|until|while|'+
+        '&|;'
+        ).split('|')
+    );
+
+    var languageConstructs = lang.arrayToMap(
+            // TODO
+        ('echo|exit|eval|source|[|]|test|'+
+         'true|false|read'
+         ).split('|')
+    );
+
+    var integer = "(?:(?:[1-9]\\d*)|(?:0))";
+    // var integer = "(?:" + decimalInteger + ")";
+
+    var fraction = "(?:\\.\\d+)";
+    var intPart = "(?:\\d+)";
+    var pointFloat = "(?:(?:" + intPart + "?" + fraction + ")|(?:" + intPart + "\\.))";
+    var exponentFloat = "(?:(?:" + pointFloat + "|" +  intPart + ")" + ")";
+    var floatNumber = "(?:" + exponentFloat + "|" + pointFloat + ")";
+    var fileDescriptor = "(?:&" + intPart + ")";
+
+    var variableName = "[a-zA-Z][a-zA-Z0-9_]*";
+    var variable = "(?:(?:\\$" + variableName + ")|(?:" + variableName + "=))";
+
+    var builtinVariable = "(?:\\$(?:SHLVL|\\$|\\!|\\?))";
+
+    var func = "(?:" + variableName + "\\s*\\(\\))";
+
+    this.$rules = {
+        "start" : [ {
+            token : "comment",
+            regex : "#.*$"
+        }, {
+            token : "string",           // " string
+            regex : '"(?:[^\\\\]|\\\\.)*?"'
+        }, {
+            token : "variable.language",
+            regex : builtinVariable
+        }, {
+            token : "variable",
+            regex : variable
+        }, {
+            token : "support.function",
+            regex : func,
+        }, {
+            token : "support.function",
+            regex : fileDescriptor
+        }, {
+            token : "string",           // ' string
+            regex : "'(?:[^\\\\]|\\\\.)*?'"
+        }, {
+            token : "constant.numeric", // float
+            regex : floatNumber
+        }, {
+            token : "constant.numeric", // integer
+            regex : integer + "\\b"
+        }, {
+            token : function(value) {
+                if (reservedKeywords.hasOwnProperty(value))
+                    return "keyword";
+                else if (languageConstructs.hasOwnProperty(value))
+                    return "constant.language";
+                else if (value == "debugger")
+                    return "invalid.deprecated";
+                else
+                    return "identifier";
+            },
+            regex : "[a-zA-Z_$][a-zA-Z0-9_$]*\\b"
+        }, {
+            token : "keyword.operator",
+            regex : "\\+|\\-|\\*|\\*\\*|\\/|\\/\\/|~|<|>|<=|=>|=|!="
+        }, {
+            token : "lparen.paren",
+            regex : "[\\[\\(\\{]"
+        }, {
+            token : "paren.rparen",
+            regex : "[\\]\\)\\}]"
+        }, {
+            token : "text",
+            regex : "\\s+"
+        } ]
+    };
+};
+
+oop.inherits(ShHighlightRules, TextHighlightRules);
+
+exports.ShHighlightRules = ShHighlightRules;
+});
diff --git a/apps/files_texteditor/js/aceeditor/mode-sh.js b/apps/files_texteditor/js/aceeditor/mode-sh.js
new file mode 100644
index 0000000000000000000000000000000000000000..272aaccc85071bd33016d80d51a1815f54fc6331
--- /dev/null
+++ b/apps/files_texteditor/js/aceeditor/mode-sh.js
@@ -0,0 +1 @@
+define("ace/mode/sh",["require","exports","module","ace/lib/oop","ace/mode/text","ace/tokenizer","ace/mode/sh_highlight_rules","ace/range"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("./text").Mode,f=a("../tokenizer").Tokenizer,g=a("./sh_highlight_rules").ShHighlightRules,h=a("../range").Range,i=function(){this.$tokenizer=new f((new g).getRules())};d.inherits(i,e),function(){this.toggleCommentLines=function(a,b,c,d){var e=!0,f=/^(\s*)#/;for(var g=c;g<=d;g++)if(!f.test(b.getLine(g))){e=!1;break}if(e){var i=new h(0,0,0,0);for(var g=c;g<=d;g++){var j=b.getLine(g),k=j.match(f);i.start.row=g,i.end.row=g,i.end.column=k[0].length,b.replace(i,k[1])}}else b.indentRows(c,d,"#")},this.getNextLineIndent=function(a,b,c){var d=this.$getIndent(b),e=this.$tokenizer.getLineTokens(b,a),f=e.tokens;if(f.length&&f[f.length-1].type=="comment")return d;if(a=="start"){var g=b.match(/^.*[\{\(\[\:]\s*$/);g&&(d+=c)}return d};var a={pass:1,"return":1,raise:1,"break":1,"continue":1};this.checkOutdent=function(b,c,d){if(d!=="\r\n"&&d!=="\r"&&d!=="\n")return!1;var e=this.$tokenizer.getLineTokens(c.trim(),b).tokens;if(!e)return!1;do var f=e.pop();while(f&&(f.type=="comment"||f.type=="text"&&f.value.match(/^\s+$/)));return f?f.type=="keyword"&&a[f.value]:!1},this.autoOutdent=function(a,b,c){c+=1;var d=this.$getIndent(b.getLine(c)),e=b.getTabString();d.slice(-e.length)==e&&b.remove(new h(c,d.length-e.length,c,d.length))}}.call(i.prototype),b.Mode=i}),define("ace/mode/sh_highlight_rules",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/mode/text_highlight_rules"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("../lib/lang"),f=a("./text_highlight_rules").TextHighlightRules,g=function(){var a=e.arrayToMap("!|{|}|case|do|done|elif|else|esac|fi|for|if|in|then|until|while|&|;".split("|")),b=e.arrayToMap("echo|exit|eval|source|[|]|test|true|false|read".split("|")),c="(?:(?:[1-9]\\d*)|(?:0))",d="(?:\\.\\d+)",f="(?:\\d+)",g="(?:(?:"+f+"?"+d+")|(?:"+f+"\\.))",h="(?:(?:"+g+"|"+f+")"+")",i="(?:"+h+"|"+g+")",j="(?:&"+f+")",k="[a-zA-Z][a-zA-Z0-9_]*",l="(?:(?:\\$"+k+")|(?:"+k+"=))",m="(?:\\$(?:SHLVL|\\$|\\!|\\?))",n="(?:"+k+"\\s*\\(\\))";this.$rules={start:[{token:"comment",regex:"#.*$"},{token:"string",regex:'"(?:[^\\\\]|\\\\.)*?"'},{token:"variable.language",regex:m},{token:"variable",regex:l},{token:"support.function",regex:n},{token:"support.function",regex:j},{token:"string",regex:"'(?:[^\\\\]|\\\\.)*?'"},{token:"constant.numeric",regex:i},{token:"constant.numeric",regex:c+"\\b"},{token:function(c){return a.hasOwnProperty(c)?"keyword":b.hasOwnProperty(c)?"constant.language":c=="debugger"?"invalid.deprecated":"identifier"},regex:"[a-zA-Z_$][a-zA-Z0-9_$]*\\b"},{token:"keyword.operator",regex:"\\+|\\-|\\*|\\*\\*|\\/|\\/\\/|~|<|>|<=|=>|=|!="},{token:"lparen.paren",regex:"[\\[\\(\\{]"},{token:"paren.rparen",regex:"[\\]\\)\\}]"},{token:"text",regex:"\\s+"}]}};d.inherits(g,f),b.ShHighlightRules=g})
\ No newline at end of file
diff --git a/apps/files_texteditor/js/aceeditor/mode-sql-uncompressed.js b/apps/files_texteditor/js/aceeditor/mode-sql-uncompressed.js
old mode 100755
new mode 100644
index 61195988d98c6fd30727d6932d831dbbc1c0f101..e56ac4cb119d8a0de84931361d4a3ad65b01cef8
--- a/apps/files_texteditor/js/aceeditor/mode-sql-uncompressed.js
+++ b/apps/files_texteditor/js/aceeditor/mode-sql-uncompressed.js
@@ -157,13 +157,3 @@ oop.inherits(SqlHighlightRules, TextHighlightRules);
 exports.SqlHighlightRules = SqlHighlightRules;
 });
 
-;
-            (function() {
-                window.require(["ace/ace"], function(a) {
-                    if (!window.ace)
-                        window.ace = {};
-                    for (var key in a) if (a.hasOwnProperty(key))
-                        ace[key] = a[key];
-                });
-            })();
-        
\ No newline at end of file
diff --git a/apps/files_texteditor/js/aceeditor/mode-sql.js b/apps/files_texteditor/js/aceeditor/mode-sql.js
old mode 100755
new mode 100644
index 3ca95359086c97048b2171120d80925cf3ffa422..e81fadfb36915ff84af3bc829d70bd2843981630
--- a/apps/files_texteditor/js/aceeditor/mode-sql.js
+++ b/apps/files_texteditor/js/aceeditor/mode-sql.js
@@ -1 +1 @@
-define("ace/mode/sql",["require","exports","module","ace/lib/oop","ace/mode/text","ace/tokenizer","ace/mode/sql_highlight_rules","ace/range"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("./text").Mode,f=a("../tokenizer").Tokenizer,g=a("./sql_highlight_rules").SqlHighlightRules,h=a("../range").Range,i=function(){this.$tokenizer=new f((new g).getRules())};d.inherits(i,e),function(){this.toggleCommentLines=function(a,b,c,d){var e=!0,f=[],g=/^(\s*)--/;for(var i=c;i<=d;i++)if(!g.test(b.getLine(i))){e=!1;break}if(e){var j=new h(0,0,0,0);for(var i=c;i<=d;i++){var k=b.getLine(i),l=k.match(g);j.start.row=i,j.end.row=i,j.end.column=l[0].length,b.replace(j,l[1])}}else b.indentRows(c,d,"--")}}.call(i.prototype),b.Mode=i}),define("ace/mode/sql_highlight_rules",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/mode/text_highlight_rules"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("../lib/lang"),f=a("./text_highlight_rules").TextHighlightRules,g=function(){var a=e.arrayToMap("select|from|where|and|or|group|by|order|limit|offset|having|as|case|when|else|end|type|left|right|join|on|outer|desc|asc".split("|")),b=e.arrayToMap("true|false|null".split("|")),c=e.arrayToMap("count|min|max|avg|sum|rank|now|coalesce".split("|"));this.$rules={start:[{token:"comment",regex:"--.*$"},{token:"string",regex:'".*"'},{token:"string",regex:"'.*'"},{token:"constant.numeric",regex:"[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"},{token:function(d){return d=d.toLowerCase(),a.hasOwnProperty(d)?"keyword":b.hasOwnProperty(d)?"constant.language":c.hasOwnProperty(d)?"support.function":"identifier"},regex:"[a-zA-Z_$][a-zA-Z0-9_$]*\\b"},{token:"keyword.operator",regex:"\\+|\\-|\\/|\\/\\/|%|<@>|@>|<@|&|\\^|~|<|>|<=|=>|==|!=|<>|="},{token:"lparen.paren",regex:"[\\(]"},{token:"paren.rparen",regex:"[\\)]"},{token:"text",regex:"\\s+"}]}};d.inherits(g,f),b.SqlHighlightRules=g}),function(){window.require(["ace/ace"],function(a){window.ace||(window.ace={});for(var b in a)a.hasOwnProperty(b)&&(ace[b]=a[b])})}()
\ No newline at end of file
+define("ace/mode/sql",["require","exports","module","ace/lib/oop","ace/mode/text","ace/tokenizer","ace/mode/sql_highlight_rules","ace/range"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("./text").Mode,f=a("../tokenizer").Tokenizer,g=a("./sql_highlight_rules").SqlHighlightRules,h=a("../range").Range,i=function(){this.$tokenizer=new f((new g).getRules())};d.inherits(i,e),function(){this.toggleCommentLines=function(a,b,c,d){var e=!0,f=[],g=/^(\s*)--/;for(var i=c;i<=d;i++)if(!g.test(b.getLine(i))){e=!1;break}if(e){var j=new h(0,0,0,0);for(var i=c;i<=d;i++){var k=b.getLine(i),l=k.match(g);j.start.row=i,j.end.row=i,j.end.column=l[0].length,b.replace(j,l[1])}}else b.indentRows(c,d,"--")}}.call(i.prototype),b.Mode=i}),define("ace/mode/sql_highlight_rules",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/mode/text_highlight_rules"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("../lib/lang"),f=a("./text_highlight_rules").TextHighlightRules,g=function(){var a=e.arrayToMap("select|from|where|and|or|group|by|order|limit|offset|having|as|case|when|else|end|type|left|right|join|on|outer|desc|asc".split("|")),b=e.arrayToMap("true|false|null".split("|")),c=e.arrayToMap("count|min|max|avg|sum|rank|now|coalesce".split("|"));this.$rules={start:[{token:"comment",regex:"--.*$"},{token:"string",regex:'".*"'},{token:"string",regex:"'.*'"},{token:"constant.numeric",regex:"[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"},{token:function(d){return d=d.toLowerCase(),a.hasOwnProperty(d)?"keyword":b.hasOwnProperty(d)?"constant.language":c.hasOwnProperty(d)?"support.function":"identifier"},regex:"[a-zA-Z_$][a-zA-Z0-9_$]*\\b"},{token:"keyword.operator",regex:"\\+|\\-|\\/|\\/\\/|%|<@>|@>|<@|&|\\^|~|<|>|<=|=>|==|!=|<>|="},{token:"lparen.paren",regex:"[\\(]"},{token:"paren.rparen",regex:"[\\)]"},{token:"text",regex:"\\s+"}]}};d.inherits(g,f),b.SqlHighlightRules=g})
\ No newline at end of file
diff --git a/apps/files_texteditor/js/aceeditor/mode-svg-uncompressed.js b/apps/files_texteditor/js/aceeditor/mode-svg-uncompressed.js
old mode 100755
new mode 100644
index 8d3bb3b873a4847c43fda6bfdc7e2538da6d0da0..1025d99bd3c107f94c08f919426f95ec9285b1f3
--- a/apps/files_texteditor/js/aceeditor/mode-svg-uncompressed.js
+++ b/apps/files_texteditor/js/aceeditor/mode-svg-uncompressed.js
@@ -202,6 +202,9 @@ var XmlHighlightRules = function() {
             merge : true,
             regex : "<\\!--",
             next : "comment"
+        }, {
+            token : "xml_pe",
+            regex : "<\\!.*?>"
         }, {
             token : "meta.tag", // opening tag
             regex : "<\\/?",
@@ -209,6 +212,9 @@ var XmlHighlightRules = function() {
         }, {
             token : "text",
             regex : "\\s+"
+        }, {
+            token : "constant.character.entity",
+            regex : "(?:&#[0-9]+;)|(?:&#x[0-9a-fA-F]+;)|(?:&[a-zA-Z0-9_:\\.-]+;)"
         }, {
             token : "text",
             regex : "[^<]+"
@@ -302,7 +308,7 @@ function string(state) {
         token : "string", // multi line string start
         merge : true,
         regex : '["].*',
-        next : state + "-qqstring"
+        next : state + "_qqstring"
     }, {
         token : "string",
         regex : "'.*?'"
@@ -310,7 +316,7 @@ function string(state) {
         token : "string", // multi line string start
         merge : true,
         regex : "['].*",
-        next : state + "-qstring"
+        next : state + "_qstring"
     }];
 }
 
@@ -358,18 +364,18 @@ exports.tag = function(states, name, nextState) {
             }
         },        
         merge : true,
-        regex : "[-_a-zA-Z0-9:!]+",
-        next : name + "embed-attribute-list" 
+        regex : "[-_a-zA-Z0-9:]+",
+        next : name + "_embed_attribute_list" 
     }, {
         token: "empty",
         regex: "",
-        next : name + "embed-attribute-list"
+        next : name + "_embed_attribute_list"
     }];
 
-    states[name + "-qstring"] = multiLineString("'", name + "embed-attribute-list");
-    states[name + "-qqstring"] = multiLineString("\"", name + "embed-attribute-list");
+    states[name + "_qstring"] = multiLineString("'", name + "_embed_attribute_list");
+    states[name + "_qqstring"] = multiLineString("\"", name + "_embed_attribute_list");
     
-    states[name + "embed-attribute-list"] = [{
+    states[name + "_embed_attribute_list"] = [{
         token : "meta.tag",
         merge : true,
         regex : "\/?>",
@@ -535,12 +541,12 @@ var CstyleBehaviour = function () {
                 return {
                     text: '{' + selected + '}',
                     selection: false
-                }
+                };
             } else {
                 return {
                     text: '{}',
                     selection: [1, 1]
-                }
+                };
             }
         } else if (text == '}') {
             var cursor = editor.getCursorPosition();
@@ -552,7 +558,7 @@ var CstyleBehaviour = function () {
                     return {
                         text: '',
                         selection: [1, 1]
-                    }
+                    };
                 }
             }
         } else if (text == "\n") {
@@ -570,7 +576,7 @@ var CstyleBehaviour = function () {
                 return {
                     text: '\n' + indent + '\n' + next_indent,
                     selection: [1, indent.length, 1, indent.length]
-                }
+                };
             }
         }
     });
@@ -595,12 +601,12 @@ var CstyleBehaviour = function () {
                 return {
                     text: '(' + selected + ')',
                     selection: false
-                }
+                };
             } else {
                 return {
                     text: '()',
                     selection: [1, 1]
-                }
+                };
             }
         } else if (text == ')') {
             var cursor = editor.getCursorPosition();
@@ -612,7 +618,7 @@ var CstyleBehaviour = function () {
                     return {
                         text: '',
                         selection: [1, 1]
-                    }
+                    };
                 }
             }
         }
@@ -631,14 +637,15 @@ var CstyleBehaviour = function () {
     });
 
     this.add("string_dquotes", "insertion", function (state, action, editor, session, text) {
-        if (text == '"') {
+        if (text == '"' || text == "'") {
+            var quote = text;
             var selection = editor.getSelectionRange();
             var selected = session.doc.getTextRange(selection);
             if (selected !== "") {
                 return {
-                    text: '"' + selected + '"',
+                    text: quote + selected + quote,
                     selection: false
-                }
+                };
             } else {
                 var cursor = editor.getCursorPosition();
                 var line = session.doc.getLine(cursor.row);
@@ -659,7 +666,7 @@ var CstyleBehaviour = function () {
                     if (token.type == "string") {
                       quotepos = -1;
                     } else if (quotepos < 0) {
-                      quotepos = token.value.indexOf('"');
+                      quotepos = token.value.indexOf(quote);
                     }
                     if ((token.value.length + col) > selection.start.column) {
                         break;
@@ -668,19 +675,19 @@ var CstyleBehaviour = function () {
                 }
 
                 // Try and be smart about when we auto insert.
-                if (!token || (quotepos < 0 && token.type !== "comment" && (token.type !== "string" || ((selection.start.column !== token.value.length+col-1) && token.value.lastIndexOf('"') === token.value.length-1)))) {
+                if (!token || (quotepos < 0 && token.type !== "comment" && (token.type !== "string" || ((selection.start.column !== token.value.length+col-1) && token.value.lastIndexOf(quote) === token.value.length-1)))) {
                     return {
-                        text: '""',
+                        text: quote + quote,
                         selection: [1,1]
-                    }
+                    };
                 } else if (token && token.type === "string") {
                     // Ignore input and move right one if we're typing over the closing quote.
                     var rightChar = line.substring(cursor.column, cursor.column + 1);
-                    if (rightChar == '"') {
+                    if (rightChar == quote) {
                         return {
                             text: '',
                             selection: [1, 1]
-                        }
+                        };
                     }
                 }
             }
@@ -689,7 +696,7 @@ var CstyleBehaviour = function () {
 
     this.add("string_dquotes", "deletion", function (state, action, editor, session, range) {
         var selected = session.doc.getTextRange(range);
-        if (!range.isMultiLine() && selected == '"') {
+        if (!range.isMultiLine() && (selected == '"' || selected == "'")) {
             var line = session.doc.getLine(range.start.row);
             var rightChar = line.substring(range.start.column + 1, range.start.column + 2);
             if (rightChar == '"') {
@@ -699,7 +706,8 @@ var CstyleBehaviour = function () {
         }
     });
 
-}
+};
+
 oop.inherits(CstyleBehaviour, Behaviour);
 
 exports.CstyleBehaviour = CstyleBehaviour;
@@ -1336,12 +1344,20 @@ var JavaScriptHighlightRules = function() {
     );
 
     // TODO: Unicode escape sequences
-    var identifierRe = "[" + unicode.packages.L + "\\$_][" 
+    var identifierRe = "[" + unicode.packages.L + "\\$_]["
         + unicode.packages.L
         + unicode.packages.Mn + unicode.packages.Mc
         + unicode.packages.Nd
         + unicode.packages.Pc + "\\$_]*\\b";
-        
+
+    var escapedRe = "\\\\(?:x[0-9a-fA-F]{2}|" + // hex
+        "u[0-9a-fA-F]{4}|" + // unicode
+        "[0-2][0-7]{0,2}|" + // oct
+        "3[0-6][0-7]?|" + // oct
+        "37[0-7]?|" + // oct
+        "[4-7][0-7]?|" + //oct
+        ".)";
+
     // regexp must not have capturing parentheses. Use (?:) instead.
     // regexps are ordered -> the first match is used
 
@@ -1349,46 +1365,139 @@ var JavaScriptHighlightRules = function() {
         "start" : [
             {
                 token : "comment",
-                regex : "\\/\\/.*$"
+                regex : /\/\/.*$/
             },
             new DocCommentHighlightRules().getStartRule("doc-start"),
             {
                 token : "comment", // multi line comment
                 merge : true,
-                regex : "\\/\\*",
+                regex : /\/\*/,
                 next : "comment"
             }, {
-                token : "string", // single line
-                regex : '["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'
-            }, {
-                token : "string", // multi line string start
-                merge : true,
-                regex : '["].*\\\\$',
-                next : "qqstring"
-            }, {
-                token : "string", // single line
-                regex : "['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"
+                token : "string",
+                regex : "'",
+                next  : "qstring"
             }, {
-                token : "string", // multi line string start
-                merge : true,
-                regex : "['].*\\\\$",
-                next : "qstring"
+                token : "string",
+                regex : '"',
+                next  : "qqstring"
             }, {
                 token : "constant.numeric", // hex
-                regex : "0[xX][0-9a-fA-F]+\\b"
+                regex : /0[xX][0-9a-fA-F]+\b/
             }, {
                 token : "constant.numeric", // float
-                regex : "[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"
-            }, {
-                token : ["keyword.definition", "text", "entity.name.function"],
-                regex : "(function)(\\s+)(" + identifierRe + ")"
+                regex : /[+-]?\d+(?:(?:\.\d*)?(?:[eE][+-]?\d+)?)?\b/
+            }, { // match stuff like: Sound.prototype.play = function() { }
+                token : [
+                    "storage.type",
+                    "punctuation.operator",
+                    "support.function",
+                    "punctuation.operator",
+                    "entity.name.function",
+                    "text",
+                    "keyword.operator",
+                    "text",
+                    "storage.type",
+                    "text",
+                    "paren.lparen",
+                    "variable.parameter",
+                    "paren.rparen"
+                ],
+                regex : "(" + identifierRe + ")(\\.)(prototype)(\\.)(" + identifierRe +")(\\s*)(=)(\\s*)(function)(\\s*)(\\()(.*?)(\\))"
+            }, { // match stuff like: Sound.prototype.play = myfunc
+                token : [
+                    "storage.type",
+                    "punctuation.operator",
+                    "support.function",
+                    "punctuation.operator",
+                    "entity.name.function",
+                    "text",
+                    "keyword.operator",
+                    "text"
+                ],
+                regex : "(" + identifierRe + ")(\\.)(prototype)(\\.)(" + identifierRe +")(\\s*)(=)(\\s*)"
+            }, { // match stuff like: Sound.play = function() {  }
+                token : [
+                    "storage.type",
+                    "punctuation.operator",
+                    "entity.name.function",
+                    "text",
+                    "keyword.operator",
+                    "text",
+                    "storage.type",
+                    "text",
+                    "paren.lparen",
+                    "variable.parameter",
+                    "paren.rparen"
+                ],
+                regex : "(" + identifierRe + ")(\\.)(" + identifierRe +")(\\s*)(=)(\\s*)(function)(\\s*)(\\()(.*?)(\\))"
+            }, { // match stuff like: play = function() {  }
+                token : [
+                    "entity.name.function",
+                    "text",
+                    "keyword.operator",
+                    "text",
+                    "storage.type",
+                    "text",
+                    "paren.lparen",
+                    "variable.parameter",
+                    "paren.rparen"
+                ],
+                regex : "(" + identifierRe +")(\\s*)(=)(\\s*)(function)(\\s*)(\\()(.*?)(\\))"
+            }, { // match regular function like: function myFunc(arg) { }
+                token : [
+                    "storage.type",
+                    "text",
+                    "entity.name.function",
+                    "text",
+                    "paren.lparen",
+                    "variable.parameter",
+                    "paren.rparen"
+                ],
+                regex : "(function)(\\s+)(" + identifierRe + ")(\\s*)(\\()(.*?)(\\))"
+            }, { // match stuff like: foobar: function() { }
+                token : [
+                    "entity.name.function",
+                    "text",
+                    "punctuation.operator",
+                    "text",
+                    "storage.type",
+                    "text",
+                    "paren.lparen",
+                    "variable.parameter",
+                    "paren.rparen"
+                ],
+                regex : "(" + identifierRe + ")(\\s*)(:)(\\s*)(function)(\\s*)(\\()(.*?)(\\))"
+            }, { // Attempt to match : function() { } (this is for issues with 'foo': function() { })
+                token : [
+                    "text",
+                    "text",
+                    "storage.type",
+                    "text",
+                    "paren.lparen",
+                    "variable.parameter",
+                    "paren.rparen"
+                ],
+                regex : "(:)(\\s*)(function)?(\\s*)(\\()([^)]*)(\\))"
             }, {
                 token : "constant.language.boolean",
-                regex : "(?:true|false)\\b"
+                regex : /(?:true|false)\b/
             }, {
                 token : "keyword",
                 regex : "(?:" + kwBeforeRe + ")\\b",
                 next : "regex_allowed"
+            }, {
+                token : ["punctuation.operator", "support.function"],
+                regex : /(\.)(s(?:h(?:ift|ow(?:Mod(?:elessDialog|alDialog)|Help))|croll(?:X|By(?:Pages|Lines)?|Y|To)?|t(?:opzzzz|rike)|i(?:n|zeToContent|debar|gnText)|ort|u(?:p|b(?:str(?:ing)?)?)|pli(?:ce|t)|e(?:nd|t(?:Re(?:sizable|questHeader)|M(?:i(?:nutes|lliseconds)|onth)|Seconds|Ho(?:tKeys|urs)|Year|Cursor|Time(?:out)?|Interval|ZOptions|Date|UTC(?:M(?:i(?:nutes|lliseconds)|onth)|Seconds|Hours|Date|FullYear)|FullYear|Active)|arch)|qrt|lice|avePreferences|mall)|h(?:ome|andleEvent)|navigate|c(?:har(?:CodeAt|At)|o(?:s|n(?:cat|textual|firm)|mpile)|eil|lear(?:Timeout|Interval)?|a(?:ptureEvents|ll)|reate(?:StyleSheet|Popup|EventObject))|t(?:o(?:GMTString|S(?:tring|ource)|U(?:TCString|pperCase)|Lo(?:caleString|werCase))|est|a(?:n|int(?:Enabled)?))|i(?:s(?:NaN|Finite)|ndexOf|talics)|d(?:isableExternalCapture|ump|etachEvent)|u(?:n(?:shift|taint|escape|watch)|pdateCommands)|j(?:oin|avaEnabled)|p(?:o(?:p|w)|ush|lugins.refresh|a(?:ddings|rse(?:Int|Float)?)|r(?:int|ompt|eference))|e(?:scape|nableExternalCapture|val|lementFromPoint|x(?:p|ec(?:Script|Command)?))|valueOf|UTC|queryCommand(?:State|Indeterm|Enabled|Value)|f(?:i(?:nd|le(?:ModifiedDate|Size|CreatedDate|UpdatedDate)|xed)|o(?:nt(?:size|color)|rward)|loor|romCharCode)|watch|l(?:ink|o(?:ad|g)|astIndexOf)|a(?:sin|nchor|cos|t(?:tachEvent|ob|an(?:2)?)|pply|lert|b(?:s|ort))|r(?:ou(?:nd|teEvents)|e(?:size(?:By|To)|calc|turnValue|place|verse|l(?:oad|ease(?:Capture|Events)))|andom)|g(?:o|et(?:ResponseHeader|M(?:i(?:nutes|lliseconds)|onth)|Se(?:conds|lection)|Hours|Year|Time(?:zoneOffset)?|Da(?:y|te)|UTC(?:M(?:i(?:nutes|lliseconds)|onth)|Seconds|Hours|Da(?:y|te)|FullYear)|FullYear|A(?:ttention|llResponseHeaders)))|m(?:in|ove(?:B(?:y|elow)|To(?:Absolute)?|Above)|ergeAttributes|a(?:tch|rgins|x))|b(?:toa|ig|o(?:ld|rderWidths)|link|ack))\b(?=\()/
+            }, {
+                token : ["punctuation.operator", "support.function.dom"],
+                regex : /(\.)(s(?:ub(?:stringData|mit)|plitText|e(?:t(?:NamedItem|Attribute(?:Node)?)|lect))|has(?:ChildNodes|Feature)|namedItem|c(?:l(?:ick|o(?:se|neNode))|reate(?:C(?:omment|DATASection|aption)|T(?:Head|extNode|Foot)|DocumentFragment|ProcessingInstruction|E(?:ntityReference|lement)|Attribute))|tabIndex|i(?:nsert(?:Row|Before|Cell|Data)|tem)|open|delete(?:Row|C(?:ell|aption)|T(?:Head|Foot)|Data)|focus|write(?:ln)?|a(?:dd|ppend(?:Child|Data))|re(?:set|place(?:Child|Data)|move(?:NamedItem|Child|Attribute(?:Node)?)?)|get(?:NamedItem|Element(?:sBy(?:Name|TagName)|ById)|Attribute(?:Node)?)|blur)\b(?=\()/
+            }, {
+                token : ["punctuation.operator", "support.constant"],
+                regex : /(\.)(s(?:ystemLanguage|cr(?:ipts|ollbars|een(?:X|Y|Top|Left))|t(?:yle(?:Sheets)?|atus(?:Text|bar)?)|ibling(?:Below|Above)|ource|uffixes|e(?:curity(?:Policy)?|l(?:ection|f)))|h(?:istory|ost(?:name)?|as(?:h|Focus))|y|X(?:MLDocument|SLDocument)|n(?:ext|ame(?:space(?:s|URI)|Prop))|M(?:IN_VALUE|AX_VALUE)|c(?:haracterSet|o(?:n(?:structor|trollers)|okieEnabled|lorDepth|mp(?:onents|lete))|urrent|puClass|l(?:i(?:p(?:boardData)?|entInformation)|osed|asses)|alle(?:e|r)|rypto)|t(?:o(?:olbar|p)|ext(?:Transform|Indent|Decoration|Align)|ags)|SQRT(?:1_2|2)|i(?:n(?:ner(?:Height|Width)|put)|ds|gnoreCase)|zIndex|o(?:scpu|n(?:readystatechange|Line)|uter(?:Height|Width)|p(?:sProfile|ener)|ffscreenBuffering)|NEGATIVE_INFINITY|d(?:i(?:splay|alog(?:Height|Top|Width|Left|Arguments)|rectories)|e(?:scription|fault(?:Status|Ch(?:ecked|arset)|View)))|u(?:ser(?:Profile|Language|Agent)|n(?:iqueID|defined)|pdateInterval)|_content|p(?:ixelDepth|ort|ersonalbar|kcs11|l(?:ugins|atform)|a(?:thname|dding(?:Right|Bottom|Top|Left)|rent(?:Window|Layer)?|ge(?:X(?:Offset)?|Y(?:Offset)?))|r(?:o(?:to(?:col|type)|duct(?:Sub)?|mpter)|e(?:vious|fix)))|e(?:n(?:coding|abledPlugin)|x(?:ternal|pando)|mbeds)|v(?:isibility|endor(?:Sub)?|Linkcolor)|URLUnencoded|P(?:I|OSITIVE_INFINITY)|f(?:ilename|o(?:nt(?:Size|Family|Weight)|rmName)|rame(?:s|Element)|gColor)|E|whiteSpace|l(?:i(?:stStyleType|n(?:eHeight|kColor))|o(?:ca(?:tion(?:bar)?|lName)|wsrc)|e(?:ngth|ft(?:Context)?)|a(?:st(?:M(?:odified|atch)|Index|Paren)|yer(?:s|X)|nguage))|a(?:pp(?:MinorVersion|Name|Co(?:deName|re)|Version)|vail(?:Height|Top|Width|Left)|ll|r(?:ity|guments)|Linkcolor|bove)|r(?:ight(?:Context)?|e(?:sponse(?:XML|Text)|adyState))|global|x|m(?:imeTypes|ultiline|enubar|argin(?:Right|Bottom|Top|Left))|L(?:N(?:10|2)|OG(?:10E|2E))|b(?:o(?:ttom|rder(?:Width|RightWidth|BottomWidth|Style|Color|TopWidth|LeftWidth))|ufferDepth|elow|ackground(?:Color|Image)))\b/
+            }, {
+                token : ["storage.type", "punctuation.operator", "support.function.firebug"],
+                regex : /(console)(\.)(warn|info|log|error|time|timeEnd|assert)\b/
             }, {
                 token : function(value) {
                     if (globals.hasOwnProperty(value))
@@ -1396,7 +1505,7 @@ var JavaScriptHighlightRules = function() {
                     else if (deprecated.hasOwnProperty(value))
                         return "invalid.deprecated";
                     else if (definitions.hasOwnProperty(value))
-                        return "keyword.definition";
+                        return "storage.type";
                     else if (keywords.hasOwnProperty(value))
                         return "keyword";
                     else if (buildinConstants.hasOwnProperty(value))
@@ -1411,29 +1520,29 @@ var JavaScriptHighlightRules = function() {
                 regex : identifierRe
             }, {
                 token : "keyword.operator",
-                regex : "!|\\$|%|&|\\*|\\-\\-|\\-|\\+\\+|\\+|~|===|==|=|!=|!==|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\\|\\||\\?\\:|\\*=|%=|\\+=|\\-=|&=|\\^=|\\b(?:in|instanceof|new|delete|typeof|void)",
+                regex : /!|\$|%|&|\*|\-\-|\-|\+\+|\+|~|===|==|=|!=|!==|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\|\||\?\:|\*=|%=|\+=|\-=|&=|\^=|\b(?:in|instanceof|new|delete|typeof|void)/,
                 next  : "regex_allowed"
             }, {
                 token : "punctuation.operator",
-                regex : "\\?|\\:|\\,|\\;|\\.",
+                regex : /\?|\:|\,|\;|\./,
                 next  : "regex_allowed"
             }, {
                 token : "paren.lparen",
-                regex : "[[({]",
+                regex : /[\[({]/,
                 next  : "regex_allowed"
             }, {
                 token : "paren.rparen",
-                regex : "[\\])}]"
+                regex : /[\])}]/
             }, {
                 token : "keyword.operator",
-                regex : "\\/=?",
+                regex : /\/=?/,
                 next  : "regex_allowed"
             }, {
                 token: "comment",
-                regex: "^#!.*$" 
+                regex: /^#!.*$/
             }, {
                 token : "text",
-                regex : "\\s+"
+                regex : /\s+/
             }
         ],
         // regular expressions are only allowed after certain tokens. This
@@ -1458,7 +1567,7 @@ var JavaScriptHighlightRules = function() {
             }, {
                 // immediately return to the start mode without matching
                 // anything
-                token: "empty", 
+                token: "empty",
                 regex: "",
                 next: "start"
             }
@@ -1470,10 +1579,10 @@ var JavaScriptHighlightRules = function() {
                 next: "regex"
             }, {
 				// flag
-                token: "string.regexp", 
+                token: "string.regexp",
                 regex: "/\\w*",
                 next: "start",
-                merge: true 
+                merge: true
             }, {
                 token: "string.regexp",
                 regex: "[^\\\\/\\[]+",
@@ -1485,9 +1594,9 @@ var JavaScriptHighlightRules = function() {
                 next: "regex_character_class",
                 merge: true
             }, {
-                token: "empty", 
+                token: "empty",
                 regex: "",
-                next: "start" 
+                next: "start"
             }
         ],
         "regex_character_class": [
@@ -1506,9 +1615,9 @@ var JavaScriptHighlightRules = function() {
                 next: "regex_character_class",
                 merge: true
             }, {
-                token: "empty", 
+                token: "empty",
                 regex: "",
-                next: "start" 
+                next: "start"
             }
         ],
         "comment_regex_allowed" : [
@@ -1537,28 +1646,32 @@ var JavaScriptHighlightRules = function() {
         ],
         "qqstring" : [
             {
+                token : "constant.language.escape",
+                regex : escapedRe
+            }, {
                 token : "string",
-                regex : '(?:(?:\\\\.)|(?:[^"\\\\]))*?"',
-                next : "start"
+                regex : '[^"\\\\]+'
             }, {
                 token : "string",
-                merge : true,
-                regex : '.+'
+                regex : '"',
+                next  : "start"
             }
         ],
         "qstring" : [
             {
+                token : "constant.language.escape",
+                regex : escapedRe
+            }, {
                 token : "string",
-                regex : "(?:(?:\\\\.)|(?:[^'\\\\]))*?'",
-                next : "start"
+                regex : "[^'\\\\]+"
             }, {
                 token : "string",
-                merge : true,
-                regex : '.+'
+                regex : "'",
+                next  : "start"
             }
         ]
     };
-    
+
     this.embedRules(DocCommentHighlightRules, "doc-",
         [ new DocCommentHighlightRules().getEndRule("start") ]);
 };
@@ -1743,195 +1856,6 @@ var MatchingBraceOutdent = function() {};
 }).call(MatchingBraceOutdent.prototype);
 
 exports.MatchingBraceOutdent = MatchingBraceOutdent;
-});
-/* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is Ajax.org Code Editor (ACE).
- *
- * The Initial Developer of the Original Code is
- * Ajax.org B.V.
- * Portions created by the Initial Developer are Copyright (C) 2010
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *      Fabian Jakobs <fabian AT ajax DOT org>
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-define('ace/worker/worker_client', ['require', 'exports', 'module' , 'ace/lib/oop', 'ace/lib/event_emitter'], function(require, exports, module) {
-"use strict";
-
-var oop = require("../lib/oop");
-var EventEmitter = require("../lib/event_emitter").EventEmitter;
-
-var WorkerClient = function(topLevelNamespaces, packagedJs, mod, classname) {
-
-    this.changeListener = this.changeListener.bind(this);
-
-    if (module.packaged) {
-        var base = this.$guessBasePath();
-        this.$worker = new Worker(base + packagedJs);
-    }
-    else {
-        var workerUrl = this.$normalizePath(require.nameToUrl("ace/worker/worker", null, "_"));
-        this.$worker = new Worker(workerUrl);
-
-        var tlns = {};
-        for (var i=0; i<topLevelNamespaces.length; i++) {
-            var ns = topLevelNamespaces[i];
-            var path = this.$normalizePath(require.nameToUrl(ns, null, "_").replace(/.js$/, ""));
-
-            tlns[ns] = path;
-        }
-    }
-
-    this.$worker.postMessage({
-        init : true,
-        tlns: tlns,
-        module: mod,
-        classname: classname
-    });
-
-    this.callbackId = 1;
-    this.callbacks = {};
-
-    var _self = this;
-    this.$worker.onerror = function(e) {
-        window.console && console.log && console.log(e);
-        throw e;
-    };
-    this.$worker.onmessage = function(e) {
-        var msg = e.data;
-        switch(msg.type) {
-            case "log":
-                window.console && console.log && console.log(msg.data);
-                break;
-
-            case "event":
-                _self._emit(msg.name, {data: msg.data});
-                break;
-
-            case "call":
-                var callback = _self.callbacks[msg.id];
-                if (callback) {
-                    callback(msg.data);
-                    delete _self.callbacks[msg.id];
-                }
-                break;
-        }
-    };
-};
-
-(function(){
-
-    oop.implement(this, EventEmitter);
-
-    this.$normalizePath = function(path) {
-        path = path.replace(/^[a-z]+:\/\/[^\/]+\//, ""); // Remove domain name and rebuild it
-        path = location.protocol + "//" + location.host
-            // paths starting with a slash are relative to the root (host)
-            + (path.charAt(0) == "/" ? "" : location.pathname.replace(/\/[^\/]*$/, ""))
-            + "/" + path.replace(/^[\/]+/, "");
-        return path;
-    };
-
-    this.$guessBasePath = function() {
-        if (require.aceBaseUrl)
-            return require.aceBaseUrl;
-
-        var scripts = document.getElementsByTagName("script");
-        for (var i=0; i<scripts.length; i++) {
-            var script = scripts[i];
-
-            var base = script.getAttribute("data-ace-base");
-            if (base)
-                return base.replace(/\/*$/, "/");
-
-            var src = script.src || script.getAttribute("src");
-            if (!src) {
-                continue;
-            }
-            var m = src.match(/^(?:(.*\/)ace\.js|(.*\/)ace(-uncompressed)?(-noconflict)?\.js)(?:\?|$)/);
-            if (m)
-                return m[1] || m[2];
-        }
-        return "";
-    };
-
-    this.terminate = function() {
-        this._emit("terminate", {});
-        this.$worker.terminate();
-        this.$worker = null;
-        this.$doc.removeEventListener("change", this.changeListener);
-        this.$doc = null;
-    };
-
-    this.send = function(cmd, args) {
-        this.$worker.postMessage({command: cmd, args: args});
-    };
-
-    this.call = function(cmd, args, callback) {
-        if (callback) {
-            var id = this.callbackId++;
-            this.callbacks[id] = callback;
-            args.push(id);
-        }
-        this.send(cmd, args);
-    };
-
-    this.emit = function(event, data) {
-        try {
-            // firefox refuses to clone objects which have function properties
-            // TODO: cleanup event
-            this.$worker.postMessage({event: event, data: {data: data.data}});
-        }
-        catch(ex) {}
-    };
-
-    this.attachToDocument = function(doc) {
-        if(this.$doc)
-            this.terminate();
-
-        this.$doc = doc;
-        this.call("setValue", [doc.getValue()]);
-        doc.on("change", this.changeListener);
-    };
-
-    this.changeListener = function(e) {
-        e.range = {
-            start: e.data.range.start,
-            end: e.data.range.end
-        };
-        this.emit("change", e);
-    };
-
-}).call(WorkerClient.prototype);
-
-exports.WorkerClient = WorkerClient;
-
 });
 /* ***** BEGIN LICENSE BLOCK *****
  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
@@ -2185,13 +2109,4 @@ oop.inherits(FoldMode, BaseFoldMode);
 
 }).call(FoldMode.prototype);
 
-});;
-            (function() {
-                window.require(["ace/ace"], function(a) {
-                    if (!window.ace)
-                        window.ace = {};
-                    for (var key in a) if (a.hasOwnProperty(key))
-                        ace[key] = a[key];
-                });
-            })();
-        
\ No newline at end of file
+});
\ No newline at end of file
diff --git a/apps/files_texteditor/js/aceeditor/mode-svg.js b/apps/files_texteditor/js/aceeditor/mode-svg.js
index e3865a788d365ebd56676064d47dd9b72ba6bf93..e006aaaf36a8b77bd46455fad6da4b54757b7d48 100644
--- a/apps/files_texteditor/js/aceeditor/mode-svg.js
+++ b/apps/files_texteditor/js/aceeditor/mode-svg.js
@@ -1 +1 @@
-define("ace/mode/svg",["require","exports","module","ace/lib/oop","ace/mode/xml","ace/mode/javascript","ace/tokenizer","ace/mode/svg_highlight_rules","ace/mode/folding/mixed","ace/mode/folding/xml","ace/mode/folding/cstyle"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("./xml").Mode,f=a("./javascript").Mode,g=a("../tokenizer").Tokenizer,h=a("./svg_highlight_rules").SvgHighlightRules,i=a("./folding/mixed").FoldMode,j=a("./folding/xml").FoldMode,k=a("./folding/cstyle").FoldMode,l=function(){e.call(this),this.highlighter=new h,this.$tokenizer=new g(this.highlighter.getRules()),this.$embeds=this.highlighter.getEmbeds(),this.createModeDelegates({"js-":f}),this.foldingRules=new i(new j({}),{"js-":new k})};d.inherits(l,e),function(){this.getNextLineIndent=function(a,b,c){return this.$getIndent(b)}}.call(l.prototype),b.Mode=l}),define("ace/mode/xml",["require","exports","module","ace/lib/oop","ace/mode/text","ace/tokenizer","ace/mode/xml_highlight_rules","ace/mode/behaviour/xml","ace/mode/folding/xml"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("./text").Mode,f=a("../tokenizer").Tokenizer,g=a("./xml_highlight_rules").XmlHighlightRules,h=a("./behaviour/xml").XmlBehaviour,i=a("./folding/xml").FoldMode,j=function(){this.$tokenizer=new f((new g).getRules()),this.$behaviour=new h,this.foldingRules=new i};d.inherits(j,e),function(){this.getNextLineIndent=function(a,b,c){return this.$getIndent(b)}}.call(j.prototype),b.Mode=j}),define("ace/mode/xml_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/xml_util","ace/mode/text_highlight_rules"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("./xml_util"),f=a("./text_highlight_rules").TextHighlightRules,g=function(){this.$rules={start:[{token:"text",regex:"<\\!\\[CDATA\\[",next:"cdata"},{token:"xml_pe",regex:"<\\?.*?\\?>"},{token:"comment",merge:!0,regex:"<\\!--",next:"comment"},{token:"meta.tag",regex:"<\\/?",next:"tag"},{token:"text",regex:"\\s+"},{token:"text",regex:"[^<]+"}],cdata:[{token:"text",regex:"\\]\\]>",next:"start"},{token:"text",regex:"\\s+"},{token:"text",regex:"(?:[^\\]]|\\](?!\\]>))+"}],comment:[{token:"comment",regex:".*?-->",next:"start"},{token:"comment",merge:!0,regex:".+"}]},e.tag(this.$rules,"tag","start")};d.inherits(g,f),b.XmlHighlightRules=g}),define("ace/mode/xml_util",["require","exports","module","ace/lib/lang"],function(a,b,c){function g(a){return[{token:"string",regex:'".*?"'},{token:"string",merge:!0,regex:'["].*',next:a+"-qqstring"},{token:"string",regex:"'.*?'"},{token:"string",merge:!0,regex:"['].*",next:a+"-qstring"}]}function h(a,b){return[{token:"string",merge:!0,regex:".*?"+a,next:b},{token:"string",merge:!0,regex:".+"}]}"use strict";var d=a("../lib/lang"),e=d.arrayToMap("button|form|input|label|select|textarea".split("|")),f=d.arrayToMap("table|tbody|td|tfoot|th|tr".split("|"));b.tag=function(a,b,c){a[b]=[{token:"text",regex:"\\s+"},{token:function(a){return a==="a"?"meta.tag.anchor":a==="img"?"meta.tag.image":a==="script"?"meta.tag.script":a==="style"?"meta.tag.style":e.hasOwnProperty(a.toLowerCase())?"meta.tag.form":f.hasOwnProperty(a.toLowerCase())?"meta.tag.table":"meta.tag"},merge:!0,regex:"[-_a-zA-Z0-9:!]+",next:b+"embed-attribute-list"},{token:"empty",regex:"",next:b+"embed-attribute-list"}],a[b+"-qstring"]=h("'",b+"embed-attribute-list"),a[b+"-qqstring"]=h('"',b+"embed-attribute-list"),a[b+"embed-attribute-list"]=[{token:"meta.tag",merge:!0,regex:"/?>",next:c},{token:"keyword.operator",regex:"="},{token:"entity.other.attribute-name",regex:"[-_a-zA-Z0-9:]+"},{token:"constant.numeric",regex:"[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"},{token:"text",regex:"\\s+"}].concat(g(b))}}),define("ace/mode/behaviour/xml",["require","exports","module","ace/lib/oop","ace/mode/behaviour","ace/mode/behaviour/cstyle"],function(a,b,c){"use strict";var d=a("../../lib/oop"),e=a("../behaviour").Behaviour,f=a("./cstyle").CstyleBehaviour,g=function(){this.inherit(f,["string_dquotes"]),this.add("brackets","insertion",function(a,b,c,d,e){if(e=="<"){var f=c.getSelectionRange(),g=d.doc.getTextRange(f);return g!==""?!1:{text:"<>",selection:[1,1]}}if(e==">"){var h=c.getCursorPosition(),i=d.doc.getLine(h.row),j=i.substring(h.column,h.column+1);if(j==">")return{text:"",selection:[1,1]}}else if(e=="\n"){var h=c.getCursorPosition(),i=d.doc.getLine(h.row),k=i.substring(h.column,h.column+2);if(k=="</"){var l=this.$getIndent(d.doc.getLine(h.row))+d.getTabString(),m=this.$getIndent(d.doc.getLine(h.row));return{text:"\n"+l+"\n"+m,selection:[1,l.length,1,l.length]}}}})};d.inherits(g,e),b.XmlBehaviour=g}),define("ace/mode/behaviour/cstyle",["require","exports","module","ace/lib/oop","ace/mode/behaviour"],function(a,b,c){"use strict";var d=a("../../lib/oop"),e=a("../behaviour").Behaviour,f=function(){this.add("braces","insertion",function(a,b,c,d,e){if(e=="{"){var f=c.getSelectionRange(),g=d.doc.getTextRange(f);return g!==""?{text:"{"+g+"}",selection:!1}:{text:"{}",selection:[1,1]}}if(e=="}"){var h=c.getCursorPosition(),i=d.doc.getLine(h.row),j=i.substring(h.column,h.column+1);if(j=="}"){var k=d.$findOpeningBracket("}",{column:h.column+1,row:h.row});if(k!==null)return{text:"",selection:[1,1]}}}else if(e=="\n"){var h=c.getCursorPosition(),i=d.doc.getLine(h.row),j=i.substring(h.column,h.column+1);if(j=="}"){var l=d.findMatchingBracket({row:h.row,column:h.column+1});if(!l)return null;var m=this.getNextLineIndent(a,i.substring(0,i.length-1),d.getTabString()),n=this.$getIndent(d.doc.getLine(l.row));return{text:"\n"+m+"\n"+n,selection:[1,m.length,1,m.length]}}}}),this.add("braces","deletion",function(a,b,c,d,e){var f=d.doc.getTextRange(e);if(!e.isMultiLine()&&f=="{"){var g=d.doc.getLine(e.start.row),h=g.substring(e.end.column,e.end.column+1);if(h=="}")return e.end.column++,e}}),this.add("parens","insertion",function(a,b,c,d,e){if(e=="("){var f=c.getSelectionRange(),g=d.doc.getTextRange(f);return g!==""?{text:"("+g+")",selection:!1}:{text:"()",selection:[1,1]}}if(e==")"){var h=c.getCursorPosition(),i=d.doc.getLine(h.row),j=i.substring(h.column,h.column+1);if(j==")"){var k=d.$findOpeningBracket(")",{column:h.column+1,row:h.row});if(k!==null)return{text:"",selection:[1,1]}}}}),this.add("parens","deletion",function(a,b,c,d,e){var f=d.doc.getTextRange(e);if(!e.isMultiLine()&&f=="("){var g=d.doc.getLine(e.start.row),h=g.substring(e.start.column+1,e.start.column+2);if(h==")")return e.end.column++,e}}),this.add("string_dquotes","insertion",function(a,b,c,d,e){if(e=='"'){var f=c.getSelectionRange(),g=d.doc.getTextRange(f);if(g!=="")return{text:'"'+g+'"',selection:!1};var h=c.getCursorPosition(),i=d.doc.getLine(h.row),j=i.substring(h.column-1,h.column);if(j=="\\")return null;var k=d.getTokens(f.start.row,f.start.row)[0].tokens,l=0,m,n=-1;for(var o=0;o<k.length;o++){m=k[o],m.type=="string"?n=-1:n<0&&(n=m.value.indexOf('"'));if(m.value.length+l>f.start.column)break;l+=k[o].value.length}if(!m||n<0&&m.type!=="comment"&&(m.type!=="string"||f.start.column!==m.value.length+l-1&&m.value.lastIndexOf('"')===m.value.length-1))return{text:'""',selection:[1,1]};if(m&&m.type==="string"){var p=i.substring(h.column,h.column+1);if(p=='"')return{text:"",selection:[1,1]}}}}),this.add("string_dquotes","deletion",function(a,b,c,d,e){var f=d.doc.getTextRange(e);if(!e.isMultiLine()&&f=='"'){var g=d.doc.getLine(e.start.row),h=g.substring(e.start.column+1,e.start.column+2);if(h=='"')return e.end.column++,e}})};d.inherits(f,e),b.CstyleBehaviour=f}),define("ace/mode/folding/xml",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/range","ace/mode/folding/fold_mode","ace/token_iterator"],function(a,b,c){"use strict";var d=a("../../lib/oop"),e=a("../../lib/lang"),f=a("../../range").Range,g=a("./fold_mode").FoldMode,h=a("../../token_iterator").TokenIterator,i=b.FoldMode=function(a){g.call(this),this.voidElements=a||{}};d.inherits(i,g),function(){this.getFoldWidget=function(a,b,c){var d=this._getFirstTagInLine(a,c);return d.closing?b=="markbeginend"?"end":"":!d.tagName||this.voidElements[d.tagName.toLowerCase()]?"":d.selfClosing?"":d.value.indexOf("/"+d.tagName)!==-1?"":"start"},this._getFirstTagInLine=function(a,b){var c=a.getTokens(b,b)[0].tokens,d="";for(var f=0;f<c.length;f++){var g=c[f];g.type.indexOf("meta.tag")===0?d+=g.value:d+=e.stringRepeat(" ",g.value.length)}return this._parseTag(d)},this.tagRe=/^(\s*)(<?(\/?)([-_a-zA-Z0-9:!]*)\s*(\/?)>?)/,this._parseTag=function(a){var b=this.tagRe.exec(a),c=this.tagRe.lastIndex||0;return this.tagRe.lastIndex=0,{value:a,match:b?b[2]:"",closing:b?!!b[3]:!1,selfClosing:b?!!b[5]||b[2]=="/>":!1,tagName:b?b[4]:"",column:b[1]?c+b[1].length:c}},this._readTagForward=function(a){var b=a.getCurrentToken();if(!b)return null;var c="",d;do if(b.type.indexOf("meta.tag")===0){if(!d)var d={row:a.getCurrentTokenRow(),column:a.getCurrentTokenColumn()};c+=b.value;if(c.indexOf(">")!==-1){var e=this._parseTag(c);return e.start=d,e.end={row:a.getCurrentTokenRow(),column:a.getCurrentTokenColumn()+b.value.length},a.stepForward(),e}}while(b=a.stepForward());return null},this._readTagBackward=function(a){var b=a.getCurrentToken();if(!b)return null;var c="",d;do if(b.type.indexOf("meta.tag")===0){d||(d={row:a.getCurrentTokenRow(),column:a.getCurrentTokenColumn()+b.value.length}),c=b.value+c;if(c.indexOf("<")!==-1){var e=this._parseTag(c);return e.end=d,e.start={row:a.getCurrentTokenRow(),column:a.getCurrentTokenColumn()},a.stepBackward(),e}}while(b=a.stepBackward());return null},this._pop=function(a,b){while(a.length){var c=a[a.length-1];if(!b||c.tagName==b.tagName)return a.pop();if(this.voidElements[b.tagName])return;if(this.voidElements[c.tagName]){a.pop();continue}return null}},this.getFoldWidgetRange=function(a,b,c){var d=this._getFirstTagInLine(a,c);if(!d.match)return null;var e=d.closing||d.selfClosing,g=[],i;if(!e){var j=new h(a,c,d.column),k={row:c,column:d.column+d.tagName.length+2};while(i=this._readTagForward(j)){if(i.selfClosing){if(!g.length)return i.start.column+=i.tagName.length+2,i.end.column-=2,f.fromPoints(i.start,i.end);continue}if(i.closing){this._pop(g,i);if(g.length==0)return f.fromPoints(k,i.start)}else g.push(i)}}else{var j=new h(a,c,d.column+d.match.length),l={row:c,column:d.column};while(i=this._readTagBackward(j)){if(i.selfClosing){if(!g.length)return i.start.column+=i.tagName.length+2,i.end.column-=2,f.fromPoints(i.start,i.end);continue}if(!i.closing){this._pop(g,i);if(g.length==0)return i.start.column+=i.tagName.length+2,f.fromPoints(i.start,l)}else g.push(i)}}}}.call(i.prototype)}),define("ace/mode/folding/fold_mode",["require","exports","module","ace/range"],function(a,b,c){"use strict";var d=a("../../range").Range,e=b.FoldMode=function(){};((function(){this.foldingStartMarker=null,this.foldingStopMarker=null,this.getFoldWidget=function(a,b,c){var d=a.getLine(c);return this.foldingStartMarker.test(d)?"start":b=="markbeginend"&&this.foldingStopMarker&&this.foldingStopMarker.test(d)?"end":""},this.getFoldWidgetRange=function(a,b,c){return null},this.indentationBlock=function(a,b,c){var e=/^\s*/,f=b,g=b,h=a.getLine(b),i=c||h.length,j=h.match(e)[0].length,k=a.getLength();while(++b<k){h=a.getLine(b);var l=h.match(e)[0].length;if(l==h.length)continue;if(l<=j)break;g=b}if(g>f){var m=a.getLine(g).length;return new d(f,i,g,m)}},this.openingBracketBlock=function(a,b,c,e){var f={row:c,column:e+1},g=a.$findClosingBracket(b,f);if(!g)return;var h=a.foldWidgets[g.row];return h==null&&(h=this.getFoldWidget(a,g.row)),h=="start"&&(g.row--,g.column=a.getLine(g.row).length),d.fromPoints(f,g)}})).call(e.prototype)}),define("ace/mode/javascript",["require","exports","module","ace/lib/oop","ace/mode/text","ace/tokenizer","ace/mode/javascript_highlight_rules","ace/mode/matching_brace_outdent","ace/range","ace/worker/worker_client","ace/mode/behaviour/cstyle","ace/mode/folding/cstyle"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("./text").Mode,f=a("../tokenizer").Tokenizer,g=a("./javascript_highlight_rules").JavaScriptHighlightRules,h=a("./matching_brace_outdent").MatchingBraceOutdent,i=a("../range").Range,j=a("../worker/worker_client").WorkerClient,k=a("./behaviour/cstyle").CstyleBehaviour,l=a("./folding/cstyle").FoldMode,m=function(){this.$tokenizer=new f((new g).getRules()),this.$outdent=new h,this.$behaviour=new k,this.foldingRules=new l};d.inherits(m,e),function(){this.toggleCommentLines=function(a,b,c,d){var e=!0,f=/^(\s*)\/\//;for(var g=c;g<=d;g++)if(!f.test(b.getLine(g))){e=!1;break}if(e){var h=new i(0,0,0,0);for(var g=c;g<=d;g++){var j=b.getLine(g),k=j.match(f);h.start.row=g,h.end.row=g,h.end.column=k[0].length,b.replace(h,k[1])}}else b.indentRows(c,d,"//")},this.getNextLineIndent=function(a,b,c){var d=this.$getIndent(b),e=this.$tokenizer.getLineTokens(b,a),f=e.tokens,g=e.state;if(f.length&&f[f.length-1].type=="comment")return d;if(a=="start"||a=="regex_allowed"){var h=b.match(/^.*(?:\bcase\b.*\:|[\{\(\[])\s*$/);h&&(d+=c)}else if(a=="doc-start"){if(g=="start"||a=="regex_allowed")return"";var h=b.match(/^\s*(\/?)\*/);h&&(h[1]&&(d+=" "),d+="* ")}return d},this.checkOutdent=function(a,b,c){return this.$outdent.checkOutdent(b,c)},this.autoOutdent=function(a,b,c){this.$outdent.autoOutdent(b,c)},this.createWorker=function(a){var b=new j(["ace"],"worker-javascript.js","ace/mode/javascript_worker","JavaScriptWorker");return b.attachToDocument(a.getDocument()),b.on("jslint",function(b){var c=[];for(var d=0;d<b.data.length;d++){var e=b.data[d];e&&c.push({row:e.line-1,column:e.character-1,text:e.reason,type:"warning",lint:e})}a.setAnnotations(c)}),b.on("narcissus",function(b){a.setAnnotations([b.data])}),b.on("terminate",function(){a.clearAnnotations()}),b}}.call(m.prototype),b.Mode=m}),define("ace/mode/javascript_highlight_rules",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/unicode","ace/mode/doc_comment_highlight_rules","ace/mode/text_highlight_rules"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("../lib/lang"),f=a("../unicode"),g=a("./doc_comment_highlight_rules").DocCommentHighlightRules,h=a("./text_highlight_rules").TextHighlightRules,i=function(){var a=e.arrayToMap("Array|Boolean|Date|Function|Iterator|Number|Object|RegExp|String|Proxy|Namespace|QName|XML|XMLList|ArrayBuffer|Float32Array|Float64Array|Int16Array|Int32Array|Int8Array|Uint16Array|Uint32Array|Uint8Array|Uint8ClampedArray|Error|EvalError|InternalError|RangeError|ReferenceError|StopIteration|SyntaxError|TypeError|URIError|decodeURI|decodeURIComponent|encodeURI|encodeURIComponent|eval|isFinite|isNaN|parseFloat|parseInt|JSON|Math|this|arguments|prototype|window|document".split("|")),b=e.arrayToMap("break|case|catch|continue|default|delete|do|else|finally|for|function|if|in|instanceof|new|return|switch|throw|try|typeof|let|var|while|with|const|yield|import|get|set".split("|")),c="case|do|else|finally|in|instanceof|return|throw|try|typeof|yield",d=e.arrayToMap("__parent__|__count__|escape|unescape|with|__proto__".split("|")),h=e.arrayToMap("const|let|var|function".split("|")),i=e.arrayToMap("null|Infinity|NaN|undefined".split("|")),j=e.arrayToMap("class|enum|extends|super|export|implements|private|public|interface|package|protected|static".split("|")),k="["+f.packages.L+"\\$_]["+f.packages.L+f.packages.Mn+f.packages.Mc+f.packages.Nd+f.packages.Pc+"\\$_]*\\b";this.$rules={start:[{token:"comment",regex:"\\/\\/.*$"},(new g).getStartRule("doc-start"),{token:"comment",merge:!0,regex:"\\/\\*",next:"comment"},{token:"string",regex:'["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'},{token:"string",merge:!0,regex:'["].*\\\\$',next:"qqstring"},{token:"string",regex:"['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"},{token:"string",merge:!0,regex:"['].*\\\\$",next:"qstring"},{token:"constant.numeric",regex:"0[xX][0-9a-fA-F]+\\b"},{token:"constant.numeric",regex:"[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"},{token:["keyword.definition","text","entity.name.function"],regex:"(function)(\\s+)("+k+")"},{token:"constant.language.boolean",regex:"(?:true|false)\\b"},{token:"keyword",regex:"(?:"+c+")\\b",next:"regex_allowed"},{token:function(c){return a.hasOwnProperty(c)?"variable.language":d.hasOwnProperty(c)?"invalid.deprecated":h.hasOwnProperty(c)?"keyword.definition":b.hasOwnProperty(c)?"keyword":i.hasOwnProperty(c)?"constant.language":j.hasOwnProperty(c)?"invalid.illegal":c=="debugger"?"invalid.deprecated":"identifier"},regex:k},{token:"keyword.operator",regex:"!|\\$|%|&|\\*|\\-\\-|\\-|\\+\\+|\\+|~|===|==|=|!=|!==|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\\|\\||\\?\\:|\\*=|%=|\\+=|\\-=|&=|\\^=|\\b(?:in|instanceof|new|delete|typeof|void)",next:"regex_allowed"},{token:"punctuation.operator",regex:"\\?|\\:|\\,|\\;|\\.",next:"regex_allowed"},{token:"paren.lparen",regex:"[[({]",next:"regex_allowed"},{token:"paren.rparen",regex:"[\\])}]"},{token:"keyword.operator",regex:"\\/=?",next:"regex_allowed"},{token:"comment",regex:"^#!.*$"},{token:"text",regex:"\\s+"}],regex_allowed:[{token:"comment",merge:!0,regex:"\\/\\*",next:"comment_regex_allowed"},{token:"comment",regex:"\\/\\/.*$"},{token:"string.regexp",regex:"\\/",next:"regex",merge:!0},{token:"text",regex:"\\s+"},{token:"empty",regex:"",next:"start"}],regex:[{token:"regexp.keyword.operator",regex:"\\\\(?:u[\\da-fA-F]{4}|x[\\da-fA-F]{2}|.)",next:"regex"},{token:"string.regexp",regex:"/\\w*",next:"start",merge:!0},{token:"string.regexp",regex:"[^\\\\/\\[]+",next:"regex",merge:!0},{token:"string.regexp.charachterclass",regex:"\\[",next:"regex_character_class",merge:!0},{token:"empty",regex:"",next:"start"}],regex_character_class:[{token:"regexp.keyword.operator",regex:"\\\\(?:u[\\da-fA-F]{4}|x[\\da-fA-F]{2}|.)",next:"regex_character_class"},{token:"string.regexp.charachterclass",regex:"]",next:"regex",merge:!0},{token:"string.regexp.charachterclass",regex:"[^\\\\\\]]+",next:"regex_character_class",merge:!0},{token:"empty",regex:"",next:"start"}],comment_regex_allowed:[{token:"comment",regex:".*?\\*\\/",merge:!0,next:"regex_allowed"},{token:"comment",merge:!0,regex:".+"}],comment:[{token:"comment",regex:".*?\\*\\/",merge:!0,next:"start"},{token:"comment",merge:!0,regex:".+"}],qqstring:[{token:"string",regex:'(?:(?:\\\\.)|(?:[^"\\\\]))*?"',next:"start"},{token:"string",merge:!0,regex:".+"}],qstring:[{token:"string",regex:"(?:(?:\\\\.)|(?:[^'\\\\]))*?'",next:"start"},{token:"string",merge:!0,regex:".+"}]},this.embedRules(g,"doc-",[(new g).getEndRule("start")])};d.inherits(i,h),b.JavaScriptHighlightRules=i}),define("ace/mode/doc_comment_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("./text_highlight_rules").TextHighlightRules,f=function(){this.$rules={start:[{token:"comment.doc.tag",regex:"@[\\w\\d_]+"},{token:"comment.doc",merge:!0,regex:"\\s+"},{token:"comment.doc",merge:!0,regex:"TODO"},{token:"comment.doc",merge:!0,regex:"[^@\\*]+"},{token:"comment.doc",merge:!0,regex:"."}]}};d.inherits(f,e),function(){this.getStartRule=function(a){return{token:"comment.doc",merge:!0,regex:"\\/\\*(?=\\*)",next:a}},this.getEndRule=function(a){return{token:"comment.doc",merge:!0,regex:"\\*\\/",next:a}}}.call(f.prototype),b.DocCommentHighlightRules=f}),define("ace/mode/matching_brace_outdent",["require","exports","module","ace/range"],function(a,b,c){"use strict";var d=a("../range").Range,e=function(){};((function(){this.checkOutdent=function(a,b){return/^\s+$/.test(a)?/^\s*\}/.test(b):!1},this.autoOutdent=function(a,b){var c=a.getLine(b),e=c.match(/^(\s*\})/);if(!e)return 0;var f=e[1].length,g=a.findMatchingBracket({row:b,column:f});if(!g||g.row==b)return 0;var h=this.$getIndent(a.getLine(g.row));a.replace(new d(b,0,b,f-1),h)},this.$getIndent=function(a){var b=a.match(/^(\s+)/);return b?b[1]:""}})).call(e.prototype),b.MatchingBraceOutdent=e}),define("ace/worker/worker_client",["require","exports","module","ace/lib/oop","ace/lib/event_emitter"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("../lib/event_emitter").EventEmitter,f=function(b,d,e,f){this.changeListener=this.changeListener.bind(this);if(c.packaged){var g=this.$guessBasePath();this.$worker=new Worker(g+d)}else{var h=this.$normalizePath(a.nameToUrl("ace/worker/worker",null,"_"));this.$worker=new Worker(h);var i={};for(var j=0;j<b.length;j++){var k=b[j],l=this.$normalizePath(a.nameToUrl(k,null,"_").replace(/.js$/,""));i[k]=l}}this.$worker.postMessage({init:!0,tlns:i,module:e,classname:f}),this.callbackId=1,this.callbacks={};var m=this;this.$worker.onerror=function(a){throw window.console&&console.log&&console.log(a),a},this.$worker.onmessage=function(a){var b=a.data;switch(b.type){case"log":window.console&&console.log&&console.log(b.data);break;case"event":m._emit(b.name,{data:b.data});break;case"call":var c=m.callbacks[b.id];c&&(c(b.data),delete m.callbacks[b.id])}}};((function(){d.implement(this,e),this.$normalizePath=function(a){return a=a.replace(/^[a-z]+:\/\/[^\/]+\//,""),a=location.protocol+"//"+location.host+(a.charAt(0)=="/"?"":location.pathname.replace(/\/[^\/]*$/,""))+"/"+a.replace(/^[\/]+/,""),a},this.$guessBasePath=function(){if(a.aceBaseUrl)return a.aceBaseUrl;var b=document.getElementsByTagName("script");for(var c=0;c<b.length;c++){var d=b[c],e=d.getAttribute("data-ace-base");if(e)return e.replace(/\/*$/,"/");var f=d.src||d.getAttribute("src");if(!f)continue;var g=f.match(/^(?:(.*\/)ace\.js|(.*\/)ace(-uncompressed)?(-noconflict)?\.js)(?:\?|$)/);if(g)return g[1]||g[2]}return""},this.terminate=function(){this._emit("terminate",{}),this.$worker.terminate(),this.$worker=null,this.$doc.removeEventListener("change",this.changeListener),this.$doc=null},this.send=function(a,b){this.$worker.postMessage({command:a,args:b})},this.call=function(a,b,c){if(c){var d=this.callbackId++;this.callbacks[d]=c,b.push(d)}this.send(a,b)},this.emit=function(a,b){try{this.$worker.postMessage({event:a,data:{data:b.data}})}catch(c){}},this.attachToDocument=function(a){this.$doc&&this.terminate(),this.$doc=a,this.call("setValue",[a.getValue()]),a.on("change",this.changeListener)},this.changeListener=function(a){a.range={start:a.data.range.start,end:a.data.range.end},this.emit("change",a)}})).call(f.prototype),b.WorkerClient=f}),define("ace/mode/folding/cstyle",["require","exports","module","ace/lib/oop","ace/range","ace/mode/folding/fold_mode"],function(a,b,c){"use strict";var d=a("../../lib/oop"),e=a("../../range").Range,f=a("./fold_mode").FoldMode,g=b.FoldMode=function(){};d.inherits(g,f),function(){this.foldingStartMarker=/(\{|\[)[^\}\]]*$|^\s*(\/\*)/,this.foldingStopMarker=/^[^\[\{]*(\}|\])|^[\s\*]*(\*\/)/,this.getFoldWidgetRange=function(a,b,c){var d=a.getLine(c),f=d.match(this.foldingStartMarker);if(f){var g=f.index;if(f[1])return this.openingBracketBlock(a,f[1],c,g);var h=a.getCommentFoldRange(c,g+f[0].length);return h.end.column-=2,h}if(b!=="markbeginend")return;var f=d.match(this.foldingStopMarker);if(f){var g=f.index+f[0].length;if(f[2]){var h=a.getCommentFoldRange(c,g);return h.end.column-=2,h}var i={row:c,column:g},j=a.$findOpeningBracket(f[1],i);if(!j)return;return j.column++,i.column--,e.fromPoints(j,i)}}}.call(g.prototype)}),define("ace/mode/svg_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/javascript_highlight_rules","ace/mode/xml_highlight_rules","ace/mode/xml_util"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("./javascript_highlight_rules").JavaScriptHighlightRules,f=a("./xml_highlight_rules").XmlHighlightRules,g=a("./xml_util"),h=function(){f.call(this),this.$rules.start.splice(3,0,{token:"meta.tag",regex:"<(?=s*script)",next:"script"}),g.tag(this.$rules,"script","js-start"),this.embedRules(e,"js-",[{token:"comment",regex:"\\/\\/.*(?=<\\/script>)",next:"tag"},{token:"meta.tag",regex:"<\\/(?=script)",next:"tag"}])};d.inherits(h,f),b.SvgHighlightRules=h}),define("ace/mode/folding/mixed",["require","exports","module","ace/lib/oop","ace/mode/folding/fold_mode"],function(a,b,c){"use strict";var d=a("../../lib/oop"),e=a("./fold_mode").FoldMode,f=b.FoldMode=function(a,b){this.defaultMode=a,this.subModes=b};d.inherits(f,e),function(){this.$getMode=function(a){for(var b in this.subModes)if(a.indexOf(b)===0)return this.subModes[b];return null},this.$tryMode=function(a,b,c,d){var e=this.$getMode(a);return e?e.getFoldWidget(b,c,d):""},this.getFoldWidget=function(a,b,c){return this.$tryMode(a.getState(c-1),a,b,c)||this.$tryMode(a.getState(c),a,b,c)||this.defaultMode.getFoldWidget(a,b,c)},this.getFoldWidgetRange=function(a,b,c){var d=this.$getMode(a.getState(c-1));if(!d||!d.getFoldWidget(a,b,c))d=this.$getMode(a.getState(c));if(!d||!d.getFoldWidget(a,b,c))d=this.defaultMode;return d.getFoldWidgetRange(a,b,c)}}.call(f.prototype)}),function(){window.require(["ace/ace"],function(a){window.ace||(window.ace={});for(var b in a)a.hasOwnProperty(b)&&(ace[b]=a[b])})}()
\ No newline at end of file
+define("ace/mode/svg",["require","exports","module","ace/lib/oop","ace/mode/xml","ace/mode/javascript","ace/tokenizer","ace/mode/svg_highlight_rules","ace/mode/folding/mixed","ace/mode/folding/xml","ace/mode/folding/cstyle"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("./xml").Mode,f=a("./javascript").Mode,g=a("../tokenizer").Tokenizer,h=a("./svg_highlight_rules").SvgHighlightRules,i=a("./folding/mixed").FoldMode,j=a("./folding/xml").FoldMode,k=a("./folding/cstyle").FoldMode,l=function(){e.call(this),this.highlighter=new h,this.$tokenizer=new g(this.highlighter.getRules()),this.$embeds=this.highlighter.getEmbeds(),this.createModeDelegates({"js-":f}),this.foldingRules=new i(new j({}),{"js-":new k})};d.inherits(l,e),function(){this.getNextLineIndent=function(a,b,c){return this.$getIndent(b)}}.call(l.prototype),b.Mode=l}),define("ace/mode/xml",["require","exports","module","ace/lib/oop","ace/mode/text","ace/tokenizer","ace/mode/xml_highlight_rules","ace/mode/behaviour/xml","ace/mode/folding/xml"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("./text").Mode,f=a("../tokenizer").Tokenizer,g=a("./xml_highlight_rules").XmlHighlightRules,h=a("./behaviour/xml").XmlBehaviour,i=a("./folding/xml").FoldMode,j=function(){this.$tokenizer=new f((new g).getRules()),this.$behaviour=new h,this.foldingRules=new i};d.inherits(j,e),function(){this.getNextLineIndent=function(a,b,c){return this.$getIndent(b)}}.call(j.prototype),b.Mode=j}),define("ace/mode/xml_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/xml_util","ace/mode/text_highlight_rules"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("./xml_util"),f=a("./text_highlight_rules").TextHighlightRules,g=function(){this.$rules={start:[{token:"text",regex:"<\\!\\[CDATA\\[",next:"cdata"},{token:"xml_pe",regex:"<\\?.*?\\?>"},{token:"comment",merge:!0,regex:"<\\!--",next:"comment"},{token:"xml_pe",regex:"<\\!.*?>"},{token:"meta.tag",regex:"<\\/?",next:"tag"},{token:"text",regex:"\\s+"},{token:"constant.character.entity",regex:"(?:&#[0-9]+;)|(?:&#x[0-9a-fA-F]+;)|(?:&[a-zA-Z0-9_:\\.-]+;)"},{token:"text",regex:"[^<]+"}],cdata:[{token:"text",regex:"\\]\\]>",next:"start"},{token:"text",regex:"\\s+"},{token:"text",regex:"(?:[^\\]]|\\](?!\\]>))+"}],comment:[{token:"comment",regex:".*?-->",next:"start"},{token:"comment",merge:!0,regex:".+"}]},e.tag(this.$rules,"tag","start")};d.inherits(g,f),b.XmlHighlightRules=g}),define("ace/mode/xml_util",["require","exports","module","ace/lib/lang"],function(a,b,c){function g(a){return[{token:"string",regex:'".*?"'},{token:"string",merge:!0,regex:'["].*',next:a+"_qqstring"},{token:"string",regex:"'.*?'"},{token:"string",merge:!0,regex:"['].*",next:a+"_qstring"}]}function h(a,b){return[{token:"string",merge:!0,regex:".*?"+a,next:b},{token:"string",merge:!0,regex:".+"}]}"use strict";var d=a("../lib/lang"),e=d.arrayToMap("button|form|input|label|select|textarea".split("|")),f=d.arrayToMap("table|tbody|td|tfoot|th|tr".split("|"));b.tag=function(a,b,c){a[b]=[{token:"text",regex:"\\s+"},{token:function(a){return a==="a"?"meta.tag.anchor":a==="img"?"meta.tag.image":a==="script"?"meta.tag.script":a==="style"?"meta.tag.style":e.hasOwnProperty(a.toLowerCase())?"meta.tag.form":f.hasOwnProperty(a.toLowerCase())?"meta.tag.table":"meta.tag"},merge:!0,regex:"[-_a-zA-Z0-9:]+",next:b+"_embed_attribute_list"},{token:"empty",regex:"",next:b+"_embed_attribute_list"}],a[b+"_qstring"]=h("'",b+"_embed_attribute_list"),a[b+"_qqstring"]=h('"',b+"_embed_attribute_list"),a[b+"_embed_attribute_list"]=[{token:"meta.tag",merge:!0,regex:"/?>",next:c},{token:"keyword.operator",regex:"="},{token:"entity.other.attribute-name",regex:"[-_a-zA-Z0-9:]+"},{token:"constant.numeric",regex:"[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"},{token:"text",regex:"\\s+"}].concat(g(b))}}),define("ace/mode/behaviour/xml",["require","exports","module","ace/lib/oop","ace/mode/behaviour","ace/mode/behaviour/cstyle"],function(a,b,c){"use strict";var d=a("../../lib/oop"),e=a("../behaviour").Behaviour,f=a("./cstyle").CstyleBehaviour,g=function(){this.inherit(f,["string_dquotes"]),this.add("brackets","insertion",function(a,b,c,d,e){if(e=="<"){var f=c.getSelectionRange(),g=d.doc.getTextRange(f);return g!==""?!1:{text:"<>",selection:[1,1]}}if(e==">"){var h=c.getCursorPosition(),i=d.doc.getLine(h.row),j=i.substring(h.column,h.column+1);if(j==">")return{text:"",selection:[1,1]}}else if(e=="\n"){var h=c.getCursorPosition(),i=d.doc.getLine(h.row),k=i.substring(h.column,h.column+2);if(k=="</"){var l=this.$getIndent(d.doc.getLine(h.row))+d.getTabString(),m=this.$getIndent(d.doc.getLine(h.row));return{text:"\n"+l+"\n"+m,selection:[1,l.length,1,l.length]}}}})};d.inherits(g,e),b.XmlBehaviour=g}),define("ace/mode/behaviour/cstyle",["require","exports","module","ace/lib/oop","ace/mode/behaviour"],function(a,b,c){"use strict";var d=a("../../lib/oop"),e=a("../behaviour").Behaviour,f=function(){this.add("braces","insertion",function(a,b,c,d,e){if(e=="{"){var f=c.getSelectionRange(),g=d.doc.getTextRange(f);return g!==""?{text:"{"+g+"}",selection:!1}:{text:"{}",selection:[1,1]}}if(e=="}"){var h=c.getCursorPosition(),i=d.doc.getLine(h.row),j=i.substring(h.column,h.column+1);if(j=="}"){var k=d.$findOpeningBracket("}",{column:h.column+1,row:h.row});if(k!==null)return{text:"",selection:[1,1]}}}else if(e=="\n"){var h=c.getCursorPosition(),i=d.doc.getLine(h.row),j=i.substring(h.column,h.column+1);if(j=="}"){var l=d.findMatchingBracket({row:h.row,column:h.column+1});if(!l)return null;var m=this.getNextLineIndent(a,i.substring(0,i.length-1),d.getTabString()),n=this.$getIndent(d.doc.getLine(l.row));return{text:"\n"+m+"\n"+n,selection:[1,m.length,1,m.length]}}}}),this.add("braces","deletion",function(a,b,c,d,e){var f=d.doc.getTextRange(e);if(!e.isMultiLine()&&f=="{"){var g=d.doc.getLine(e.start.row),h=g.substring(e.end.column,e.end.column+1);if(h=="}")return e.end.column++,e}}),this.add("parens","insertion",function(a,b,c,d,e){if(e=="("){var f=c.getSelectionRange(),g=d.doc.getTextRange(f);return g!==""?{text:"("+g+")",selection:!1}:{text:"()",selection:[1,1]}}if(e==")"){var h=c.getCursorPosition(),i=d.doc.getLine(h.row),j=i.substring(h.column,h.column+1);if(j==")"){var k=d.$findOpeningBracket(")",{column:h.column+1,row:h.row});if(k!==null)return{text:"",selection:[1,1]}}}}),this.add("parens","deletion",function(a,b,c,d,e){var f=d.doc.getTextRange(e);if(!e.isMultiLine()&&f=="("){var g=d.doc.getLine(e.start.row),h=g.substring(e.start.column+1,e.start.column+2);if(h==")")return e.end.column++,e}}),this.add("string_dquotes","insertion",function(a,b,c,d,e){if(e=='"'||e=="'"){var f=e,g=c.getSelectionRange(),h=d.doc.getTextRange(g);if(h!=="")return{text:f+h+f,selection:!1};var i=c.getCursorPosition(),j=d.doc.getLine(i.row),k=j.substring(i.column-1,i.column);if(k=="\\")return null;var l=d.getTokens(g.start.row,g.start.row)[0].tokens,m=0,n,o=-1;for(var p=0;p<l.length;p++){n=l[p],n.type=="string"?o=-1:o<0&&(o=n.value.indexOf(f));if(n.value.length+m>g.start.column)break;m+=l[p].value.length}if(!n||o<0&&n.type!=="comment"&&(n.type!=="string"||g.start.column!==n.value.length+m-1&&n.value.lastIndexOf(f)===n.value.length-1))return{text:f+f,selection:[1,1]};if(n&&n.type==="string"){var q=j.substring(i.column,i.column+1);if(q==f)return{text:"",selection:[1,1]}}}}),this.add("string_dquotes","deletion",function(a,b,c,d,e){var f=d.doc.getTextRange(e);if(!e.isMultiLine()&&(f=='"'||f=="'")){var g=d.doc.getLine(e.start.row),h=g.substring(e.start.column+1,e.start.column+2);if(h=='"')return e.end.column++,e}})};d.inherits(f,e),b.CstyleBehaviour=f}),define("ace/mode/folding/xml",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/range","ace/mode/folding/fold_mode","ace/token_iterator"],function(a,b,c){"use strict";var d=a("../../lib/oop"),e=a("../../lib/lang"),f=a("../../range").Range,g=a("./fold_mode").FoldMode,h=a("../../token_iterator").TokenIterator,i=b.FoldMode=function(a){g.call(this),this.voidElements=a||{}};d.inherits(i,g),function(){this.getFoldWidget=function(a,b,c){var d=this._getFirstTagInLine(a,c);return d.closing?b=="markbeginend"?"end":"":!d.tagName||this.voidElements[d.tagName.toLowerCase()]?"":d.selfClosing?"":d.value.indexOf("/"+d.tagName)!==-1?"":"start"},this._getFirstTagInLine=function(a,b){var c=a.getTokens(b,b)[0].tokens,d="";for(var f=0;f<c.length;f++){var g=c[f];g.type.indexOf("meta.tag")===0?d+=g.value:d+=e.stringRepeat(" ",g.value.length)}return this._parseTag(d)},this.tagRe=/^(\s*)(<?(\/?)([-_a-zA-Z0-9:!]*)\s*(\/?)>?)/,this._parseTag=function(a){var b=this.tagRe.exec(a),c=this.tagRe.lastIndex||0;return this.tagRe.lastIndex=0,{value:a,match:b?b[2]:"",closing:b?!!b[3]:!1,selfClosing:b?!!b[5]||b[2]=="/>":!1,tagName:b?b[4]:"",column:b[1]?c+b[1].length:c}},this._readTagForward=function(a){var b=a.getCurrentToken();if(!b)return null;var c="",d;do if(b.type.indexOf("meta.tag")===0){if(!d)var d={row:a.getCurrentTokenRow(),column:a.getCurrentTokenColumn()};c+=b.value;if(c.indexOf(">")!==-1){var e=this._parseTag(c);return e.start=d,e.end={row:a.getCurrentTokenRow(),column:a.getCurrentTokenColumn()+b.value.length},a.stepForward(),e}}while(b=a.stepForward());return null},this._readTagBackward=function(a){var b=a.getCurrentToken();if(!b)return null;var c="",d;do if(b.type.indexOf("meta.tag")===0){d||(d={row:a.getCurrentTokenRow(),column:a.getCurrentTokenColumn()+b.value.length}),c=b.value+c;if(c.indexOf("<")!==-1){var e=this._parseTag(c);return e.end=d,e.start={row:a.getCurrentTokenRow(),column:a.getCurrentTokenColumn()},a.stepBackward(),e}}while(b=a.stepBackward());return null},this._pop=function(a,b){while(a.length){var c=a[a.length-1];if(!b||c.tagName==b.tagName)return a.pop();if(this.voidElements[b.tagName])return;if(this.voidElements[c.tagName]){a.pop();continue}return null}},this.getFoldWidgetRange=function(a,b,c){var d=this._getFirstTagInLine(a,c);if(!d.match)return null;var e=d.closing||d.selfClosing,g=[],i;if(!e){var j=new h(a,c,d.column),k={row:c,column:d.column+d.tagName.length+2};while(i=this._readTagForward(j)){if(i.selfClosing){if(!g.length)return i.start.column+=i.tagName.length+2,i.end.column-=2,f.fromPoints(i.start,i.end);continue}if(i.closing){this._pop(g,i);if(g.length==0)return f.fromPoints(k,i.start)}else g.push(i)}}else{var j=new h(a,c,d.column+d.match.length),l={row:c,column:d.column};while(i=this._readTagBackward(j)){if(i.selfClosing){if(!g.length)return i.start.column+=i.tagName.length+2,i.end.column-=2,f.fromPoints(i.start,i.end);continue}if(!i.closing){this._pop(g,i);if(g.length==0)return i.start.column+=i.tagName.length+2,f.fromPoints(i.start,l)}else g.push(i)}}}}.call(i.prototype)}),define("ace/mode/folding/fold_mode",["require","exports","module","ace/range"],function(a,b,c){"use strict";var d=a("../../range").Range,e=b.FoldMode=function(){};(function(){this.foldingStartMarker=null,this.foldingStopMarker=null,this.getFoldWidget=function(a,b,c){var d=a.getLine(c);return this.foldingStartMarker.test(d)?"start":b=="markbeginend"&&this.foldingStopMarker&&this.foldingStopMarker.test(d)?"end":""},this.getFoldWidgetRange=function(a,b,c){return null},this.indentationBlock=function(a,b,c){var e=/^\s*/,f=b,g=b,h=a.getLine(b),i=c||h.length,j=h.match(e)[0].length,k=a.getLength();while(++b<k){h=a.getLine(b);var l=h.match(e)[0].length;if(l==h.length)continue;if(l<=j)break;g=b}if(g>f){var m=a.getLine(g).length;return new d(f,i,g,m)}},this.openingBracketBlock=function(a,b,c,e){var f={row:c,column:e+1},g=a.$findClosingBracket(b,f);if(!g)return;var h=a.foldWidgets[g.row];return h==null&&(h=this.getFoldWidget(a,g.row)),h=="start"&&(g.row--,g.column=a.getLine(g.row).length),d.fromPoints(f,g)}}).call(e.prototype)}),define("ace/mode/javascript",["require","exports","module","ace/lib/oop","ace/mode/text","ace/tokenizer","ace/mode/javascript_highlight_rules","ace/mode/matching_brace_outdent","ace/range","ace/worker/worker_client","ace/mode/behaviour/cstyle","ace/mode/folding/cstyle"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("./text").Mode,f=a("../tokenizer").Tokenizer,g=a("./javascript_highlight_rules").JavaScriptHighlightRules,h=a("./matching_brace_outdent").MatchingBraceOutdent,i=a("../range").Range,j=a("../worker/worker_client").WorkerClient,k=a("./behaviour/cstyle").CstyleBehaviour,l=a("./folding/cstyle").FoldMode,m=function(){this.$tokenizer=new f((new g).getRules()),this.$outdent=new h,this.$behaviour=new k,this.foldingRules=new l};d.inherits(m,e),function(){this.toggleCommentLines=function(a,b,c,d){var e=!0,f=/^(\s*)\/\//;for(var g=c;g<=d;g++)if(!f.test(b.getLine(g))){e=!1;break}if(e){var h=new i(0,0,0,0);for(var g=c;g<=d;g++){var j=b.getLine(g),k=j.match(f);h.start.row=g,h.end.row=g,h.end.column=k[0].length,b.replace(h,k[1])}}else b.indentRows(c,d,"//")},this.getNextLineIndent=function(a,b,c){var d=this.$getIndent(b),e=this.$tokenizer.getLineTokens(b,a),f=e.tokens,g=e.state;if(f.length&&f[f.length-1].type=="comment")return d;if(a=="start"||a=="regex_allowed"){var h=b.match(/^.*(?:\bcase\b.*\:|[\{\(\[])\s*$/);h&&(d+=c)}else if(a=="doc-start"){if(g=="start"||a=="regex_allowed")return"";var h=b.match(/^\s*(\/?)\*/);h&&(h[1]&&(d+=" "),d+="* ")}return d},this.checkOutdent=function(a,b,c){return this.$outdent.checkOutdent(b,c)},this.autoOutdent=function(a,b,c){this.$outdent.autoOutdent(b,c)},this.createWorker=function(a){var b=new j(["ace"],"worker-javascript.js","ace/mode/javascript_worker","JavaScriptWorker");return b.attachToDocument(a.getDocument()),b.on("jslint",function(b){var c=[];for(var d=0;d<b.data.length;d++){var e=b.data[d];e&&c.push({row:e.line-1,column:e.character-1,text:e.reason,type:"warning",lint:e})}a.setAnnotations(c)}),b.on("narcissus",function(b){a.setAnnotations([b.data])}),b.on("terminate",function(){a.clearAnnotations()}),b}}.call(m.prototype),b.Mode=m}),define("ace/mode/javascript_highlight_rules",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/unicode","ace/mode/doc_comment_highlight_rules","ace/mode/text_highlight_rules"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("../lib/lang"),f=a("../unicode"),g=a("./doc_comment_highlight_rules").DocCommentHighlightRules,h=a("./text_highlight_rules").TextHighlightRules,i=function(){var a=e.arrayToMap("Array|Boolean|Date|Function|Iterator|Number|Object|RegExp|String|Proxy|Namespace|QName|XML|XMLList|ArrayBuffer|Float32Array|Float64Array|Int16Array|Int32Array|Int8Array|Uint16Array|Uint32Array|Uint8Array|Uint8ClampedArray|Error|EvalError|InternalError|RangeError|ReferenceError|StopIteration|SyntaxError|TypeError|URIError|decodeURI|decodeURIComponent|encodeURI|encodeURIComponent|eval|isFinite|isNaN|parseFloat|parseInt|JSON|Math|this|arguments|prototype|window|document".split("|")),b=e.arrayToMap("break|case|catch|continue|default|delete|do|else|finally|for|function|if|in|instanceof|new|return|switch|throw|try|typeof|let|var|while|with|const|yield|import|get|set".split("|")),c="case|do|else|finally|in|instanceof|return|throw|try|typeof|yield",d=e.arrayToMap("__parent__|__count__|escape|unescape|with|__proto__".split("|")),h=e.arrayToMap("const|let|var|function".split("|")),i=e.arrayToMap("null|Infinity|NaN|undefined".split("|")),j=e.arrayToMap("class|enum|extends|super|export|implements|private|public|interface|package|protected|static".split("|")),k="["+f.packages.L+"\\$_]["+f.packages.L+f.packages.Mn+f.packages.Mc+f.packages.Nd+f.packages.Pc+"\\$_]*\\b",l="\\\\(?:x[0-9a-fA-F]{2}|u[0-9a-fA-F]{4}|[0-2][0-7]{0,2}|3[0-6][0-7]?|37[0-7]?|[4-7][0-7]?|.)";this.$rules={start:[{token:"comment",regex:/\/\/.*$/},(new g).getStartRule("doc-start"),{token:"comment",merge:!0,regex:/\/\*/,next:"comment"},{token:"string",regex:"'",next:"qstring"},{token:"string",regex:'"',next:"qqstring"},{token:"constant.numeric",regex:/0[xX][0-9a-fA-F]+\b/},{token:"constant.numeric",regex:/[+-]?\d+(?:(?:\.\d*)?(?:[eE][+-]?\d+)?)?\b/},{token:["storage.type","punctuation.operator","support.function","punctuation.operator","entity.name.function","text","keyword.operator","text","storage.type","text","paren.lparen","variable.parameter","paren.rparen"],regex:"("+k+")(\\.)(prototype)(\\.)("+k+")(\\s*)(=)(\\s*)(function)(\\s*)(\\()(.*?)(\\))"},{token:["storage.type","punctuation.operator","support.function","punctuation.operator","entity.name.function","text","keyword.operator","text"],regex:"("+k+")(\\.)(prototype)(\\.)("+k+")(\\s*)(=)(\\s*)"},{token:["storage.type","punctuation.operator","entity.name.function","text","keyword.operator","text","storage.type","text","paren.lparen","variable.parameter","paren.rparen"],regex:"("+k+")(\\.)("+k+")(\\s*)(=)(\\s*)(function)(\\s*)(\\()(.*?)(\\))"},{token:["entity.name.function","text","keyword.operator","text","storage.type","text","paren.lparen","variable.parameter","paren.rparen"],regex:"("+k+")(\\s*)(=)(\\s*)(function)(\\s*)(\\()(.*?)(\\))"},{token:["storage.type","text","entity.name.function","text","paren.lparen","variable.parameter","paren.rparen"],regex:"(function)(\\s+)("+k+")(\\s*)(\\()(.*?)(\\))"},{token:["entity.name.function","text","punctuation.operator","text","storage.type","text","paren.lparen","variable.parameter","paren.rparen"],regex:"("+k+")(\\s*)(:)(\\s*)(function)(\\s*)(\\()(.*?)(\\))"},{token:["text","text","storage.type","text","paren.lparen","variable.parameter","paren.rparen"],regex:"(:)(\\s*)(function)?(\\s*)(\\()([^)]*)(\\))"},{token:"constant.language.boolean",regex:/(?:true|false)\b/},{token:"keyword",regex:"(?:"+c+")\\b",next:"regex_allowed"},{token:["punctuation.operator","support.function"],regex:/(\.)(s(?:h(?:ift|ow(?:Mod(?:elessDialog|alDialog)|Help))|croll(?:X|By(?:Pages|Lines)?|Y|To)?|t(?:opzzzz|rike)|i(?:n|zeToContent|debar|gnText)|ort|u(?:p|b(?:str(?:ing)?)?)|pli(?:ce|t)|e(?:nd|t(?:Re(?:sizable|questHeader)|M(?:i(?:nutes|lliseconds)|onth)|Seconds|Ho(?:tKeys|urs)|Year|Cursor|Time(?:out)?|Interval|ZOptions|Date|UTC(?:M(?:i(?:nutes|lliseconds)|onth)|Seconds|Hours|Date|FullYear)|FullYear|Active)|arch)|qrt|lice|avePreferences|mall)|h(?:ome|andleEvent)|navigate|c(?:har(?:CodeAt|At)|o(?:s|n(?:cat|textual|firm)|mpile)|eil|lear(?:Timeout|Interval)?|a(?:ptureEvents|ll)|reate(?:StyleSheet|Popup|EventObject))|t(?:o(?:GMTString|S(?:tring|ource)|U(?:TCString|pperCase)|Lo(?:caleString|werCase))|est|a(?:n|int(?:Enabled)?))|i(?:s(?:NaN|Finite)|ndexOf|talics)|d(?:isableExternalCapture|ump|etachEvent)|u(?:n(?:shift|taint|escape|watch)|pdateCommands)|j(?:oin|avaEnabled)|p(?:o(?:p|w)|ush|lugins.refresh|a(?:ddings|rse(?:Int|Float)?)|r(?:int|ompt|eference))|e(?:scape|nableExternalCapture|val|lementFromPoint|x(?:p|ec(?:Script|Command)?))|valueOf|UTC|queryCommand(?:State|Indeterm|Enabled|Value)|f(?:i(?:nd|le(?:ModifiedDate|Size|CreatedDate|UpdatedDate)|xed)|o(?:nt(?:size|color)|rward)|loor|romCharCode)|watch|l(?:ink|o(?:ad|g)|astIndexOf)|a(?:sin|nchor|cos|t(?:tachEvent|ob|an(?:2)?)|pply|lert|b(?:s|ort))|r(?:ou(?:nd|teEvents)|e(?:size(?:By|To)|calc|turnValue|place|verse|l(?:oad|ease(?:Capture|Events)))|andom)|g(?:o|et(?:ResponseHeader|M(?:i(?:nutes|lliseconds)|onth)|Se(?:conds|lection)|Hours|Year|Time(?:zoneOffset)?|Da(?:y|te)|UTC(?:M(?:i(?:nutes|lliseconds)|onth)|Seconds|Hours|Da(?:y|te)|FullYear)|FullYear|A(?:ttention|llResponseHeaders)))|m(?:in|ove(?:B(?:y|elow)|To(?:Absolute)?|Above)|ergeAttributes|a(?:tch|rgins|x))|b(?:toa|ig|o(?:ld|rderWidths)|link|ack))\b(?=\()/},{token:["punctuation.operator","support.function.dom"],regex:/(\.)(s(?:ub(?:stringData|mit)|plitText|e(?:t(?:NamedItem|Attribute(?:Node)?)|lect))|has(?:ChildNodes|Feature)|namedItem|c(?:l(?:ick|o(?:se|neNode))|reate(?:C(?:omment|DATASection|aption)|T(?:Head|extNode|Foot)|DocumentFragment|ProcessingInstruction|E(?:ntityReference|lement)|Attribute))|tabIndex|i(?:nsert(?:Row|Before|Cell|Data)|tem)|open|delete(?:Row|C(?:ell|aption)|T(?:Head|Foot)|Data)|focus|write(?:ln)?|a(?:dd|ppend(?:Child|Data))|re(?:set|place(?:Child|Data)|move(?:NamedItem|Child|Attribute(?:Node)?)?)|get(?:NamedItem|Element(?:sBy(?:Name|TagName)|ById)|Attribute(?:Node)?)|blur)\b(?=\()/},{token:["punctuation.operator","support.constant"],regex:/(\.)(s(?:ystemLanguage|cr(?:ipts|ollbars|een(?:X|Y|Top|Left))|t(?:yle(?:Sheets)?|atus(?:Text|bar)?)|ibling(?:Below|Above)|ource|uffixes|e(?:curity(?:Policy)?|l(?:ection|f)))|h(?:istory|ost(?:name)?|as(?:h|Focus))|y|X(?:MLDocument|SLDocument)|n(?:ext|ame(?:space(?:s|URI)|Prop))|M(?:IN_VALUE|AX_VALUE)|c(?:haracterSet|o(?:n(?:structor|trollers)|okieEnabled|lorDepth|mp(?:onents|lete))|urrent|puClass|l(?:i(?:p(?:boardData)?|entInformation)|osed|asses)|alle(?:e|r)|rypto)|t(?:o(?:olbar|p)|ext(?:Transform|Indent|Decoration|Align)|ags)|SQRT(?:1_2|2)|i(?:n(?:ner(?:Height|Width)|put)|ds|gnoreCase)|zIndex|o(?:scpu|n(?:readystatechange|Line)|uter(?:Height|Width)|p(?:sProfile|ener)|ffscreenBuffering)|NEGATIVE_INFINITY|d(?:i(?:splay|alog(?:Height|Top|Width|Left|Arguments)|rectories)|e(?:scription|fault(?:Status|Ch(?:ecked|arset)|View)))|u(?:ser(?:Profile|Language|Agent)|n(?:iqueID|defined)|pdateInterval)|_content|p(?:ixelDepth|ort|ersonalbar|kcs11|l(?:ugins|atform)|a(?:thname|dding(?:Right|Bottom|Top|Left)|rent(?:Window|Layer)?|ge(?:X(?:Offset)?|Y(?:Offset)?))|r(?:o(?:to(?:col|type)|duct(?:Sub)?|mpter)|e(?:vious|fix)))|e(?:n(?:coding|abledPlugin)|x(?:ternal|pando)|mbeds)|v(?:isibility|endor(?:Sub)?|Linkcolor)|URLUnencoded|P(?:I|OSITIVE_INFINITY)|f(?:ilename|o(?:nt(?:Size|Family|Weight)|rmName)|rame(?:s|Element)|gColor)|E|whiteSpace|l(?:i(?:stStyleType|n(?:eHeight|kColor))|o(?:ca(?:tion(?:bar)?|lName)|wsrc)|e(?:ngth|ft(?:Context)?)|a(?:st(?:M(?:odified|atch)|Index|Paren)|yer(?:s|X)|nguage))|a(?:pp(?:MinorVersion|Name|Co(?:deName|re)|Version)|vail(?:Height|Top|Width|Left)|ll|r(?:ity|guments)|Linkcolor|bove)|r(?:ight(?:Context)?|e(?:sponse(?:XML|Text)|adyState))|global|x|m(?:imeTypes|ultiline|enubar|argin(?:Right|Bottom|Top|Left))|L(?:N(?:10|2)|OG(?:10E|2E))|b(?:o(?:ttom|rder(?:Width|RightWidth|BottomWidth|Style|Color|TopWidth|LeftWidth))|ufferDepth|elow|ackground(?:Color|Image)))\b/},{token:["storage.type","punctuation.operator","support.function.firebug"],regex:/(console)(\.)(warn|info|log|error|time|timeEnd|assert)\b/},{token:function(c){return a.hasOwnProperty(c)?"variable.language":d.hasOwnProperty(c)?"invalid.deprecated":h.hasOwnProperty(c)?"storage.type":b.hasOwnProperty(c)?"keyword":i.hasOwnProperty(c)?"constant.language":j.hasOwnProperty(c)?"invalid.illegal":c=="debugger"?"invalid.deprecated":"identifier"},regex:k},{token:"keyword.operator",regex:/!|\$|%|&|\*|\-\-|\-|\+\+|\+|~|===|==|=|!=|!==|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\|\||\?\:|\*=|%=|\+=|\-=|&=|\^=|\b(?:in|instanceof|new|delete|typeof|void)/,next:"regex_allowed"},{token:"punctuation.operator",regex:/\?|\:|\,|\;|\./,next:"regex_allowed"},{token:"paren.lparen",regex:/[\[({]/,next:"regex_allowed"},{token:"paren.rparen",regex:/[\])}]/},{token:"keyword.operator",regex:/\/=?/,next:"regex_allowed"},{token:"comment",regex:/^#!.*$/},{token:"text",regex:/\s+/}],regex_allowed:[{token:"comment",merge:!0,regex:"\\/\\*",next:"comment_regex_allowed"},{token:"comment",regex:"\\/\\/.*$"},{token:"string.regexp",regex:"\\/",next:"regex",merge:!0},{token:"text",regex:"\\s+"},{token:"empty",regex:"",next:"start"}],regex:[{token:"regexp.keyword.operator",regex:"\\\\(?:u[\\da-fA-F]{4}|x[\\da-fA-F]{2}|.)",next:"regex"},{token:"string.regexp",regex:"/\\w*",next:"start",merge:!0},{token:"string.regexp",regex:"[^\\\\/\\[]+",next:"regex",merge:!0},{token:"string.regexp.charachterclass",regex:"\\[",next:"regex_character_class",merge:!0},{token:"empty",regex:"",next:"start"}],regex_character_class:[{token:"regexp.keyword.operator",regex:"\\\\(?:u[\\da-fA-F]{4}|x[\\da-fA-F]{2}|.)",next:"regex_character_class"},{token:"string.regexp.charachterclass",regex:"]",next:"regex",merge:!0},{token:"string.regexp.charachterclass",regex:"[^\\\\\\]]+",next:"regex_character_class",merge:!0},{token:"empty",regex:"",next:"start"}],comment_regex_allowed:[{token:"comment",regex:".*?\\*\\/",merge:!0,next:"regex_allowed"},{token:"comment",merge:!0,regex:".+"}],comment:[{token:"comment",regex:".*?\\*\\/",merge:!0,next:"start"},{token:"comment",merge:!0,regex:".+"}],qqstring:[{token:"constant.language.escape",regex:l},{token:"string",regex:'[^"\\\\]+'},{token:"string",regex:'"',next:"start"}],qstring:[{token:"constant.language.escape",regex:l},{token:"string",regex:"[^'\\\\]+"},{token:"string",regex:"'",next:"start"}]},this.embedRules(g,"doc-",[(new g).getEndRule("start")])};d.inherits(i,h),b.JavaScriptHighlightRules=i}),define("ace/mode/doc_comment_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("./text_highlight_rules").TextHighlightRules,f=function(){this.$rules={start:[{token:"comment.doc.tag",regex:"@[\\w\\d_]+"},{token:"comment.doc",merge:!0,regex:"\\s+"},{token:"comment.doc",merge:!0,regex:"TODO"},{token:"comment.doc",merge:!0,regex:"[^@\\*]+"},{token:"comment.doc",merge:!0,regex:"."}]}};d.inherits(f,e),function(){this.getStartRule=function(a){return{token:"comment.doc",merge:!0,regex:"\\/\\*(?=\\*)",next:a}},this.getEndRule=function(a){return{token:"comment.doc",merge:!0,regex:"\\*\\/",next:a}}}.call(f.prototype),b.DocCommentHighlightRules=f}),define("ace/mode/matching_brace_outdent",["require","exports","module","ace/range"],function(a,b,c){"use strict";var d=a("../range").Range,e=function(){};(function(){this.checkOutdent=function(a,b){return/^\s+$/.test(a)?/^\s*\}/.test(b):!1},this.autoOutdent=function(a,b){var c=a.getLine(b),e=c.match(/^(\s*\})/);if(!e)return 0;var f=e[1].length,g=a.findMatchingBracket({row:b,column:f});if(!g||g.row==b)return 0;var h=this.$getIndent(a.getLine(g.row));a.replace(new d(b,0,b,f-1),h)},this.$getIndent=function(a){var b=a.match(/^(\s+)/);return b?b[1]:""}}).call(e.prototype),b.MatchingBraceOutdent=e}),define("ace/mode/folding/cstyle",["require","exports","module","ace/lib/oop","ace/range","ace/mode/folding/fold_mode"],function(a,b,c){"use strict";var d=a("../../lib/oop"),e=a("../../range").Range,f=a("./fold_mode").FoldMode,g=b.FoldMode=function(){};d.inherits(g,f),function(){this.foldingStartMarker=/(\{|\[)[^\}\]]*$|^\s*(\/\*)/,this.foldingStopMarker=/^[^\[\{]*(\}|\])|^[\s\*]*(\*\/)/,this.getFoldWidgetRange=function(a,b,c){var d=a.getLine(c),f=d.match(this.foldingStartMarker);if(f){var g=f.index;if(f[1])return this.openingBracketBlock(a,f[1],c,g);var h=a.getCommentFoldRange(c,g+f[0].length);return h.end.column-=2,h}if(b!=="markbeginend")return;var f=d.match(this.foldingStopMarker);if(f){var g=f.index+f[0].length;if(f[2]){var h=a.getCommentFoldRange(c,g);return h.end.column-=2,h}var i={row:c,column:g},j=a.$findOpeningBracket(f[1],i);if(!j)return;return j.column++,i.column--,e.fromPoints(j,i)}}}.call(g.prototype)}),define("ace/mode/svg_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/javascript_highlight_rules","ace/mode/xml_highlight_rules","ace/mode/xml_util"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("./javascript_highlight_rules").JavaScriptHighlightRules,f=a("./xml_highlight_rules").XmlHighlightRules,g=a("./xml_util"),h=function(){f.call(this),this.$rules.start.splice(3,0,{token:"meta.tag",regex:"<(?=s*script)",next:"script"}),g.tag(this.$rules,"script","js-start"),this.embedRules(e,"js-",[{token:"comment",regex:"\\/\\/.*(?=<\\/script>)",next:"tag"},{token:"meta.tag",regex:"<\\/(?=script)",next:"tag"}])};d.inherits(h,f),b.SvgHighlightRules=h}),define("ace/mode/folding/mixed",["require","exports","module","ace/lib/oop","ace/mode/folding/fold_mode"],function(a,b,c){"use strict";var d=a("../../lib/oop"),e=a("./fold_mode").FoldMode,f=b.FoldMode=function(a,b){this.defaultMode=a,this.subModes=b};d.inherits(f,e),function(){this.$getMode=function(a){for(var b in this.subModes)if(a.indexOf(b)===0)return this.subModes[b];return null},this.$tryMode=function(a,b,c,d){var e=this.$getMode(a);return e?e.getFoldWidget(b,c,d):""},this.getFoldWidget=function(a,b,c){return this.$tryMode(a.getState(c-1),a,b,c)||this.$tryMode(a.getState(c),a,b,c)||this.defaultMode.getFoldWidget(a,b,c)},this.getFoldWidgetRange=function(a,b,c){var d=this.$getMode(a.getState(c-1));if(!d||!d.getFoldWidget(a,b,c))d=this.$getMode(a.getState(c));if(!d||!d.getFoldWidget(a,b,c))d=this.defaultMode;return d.getFoldWidgetRange(a,b,c)}}.call(f.prototype)})
\ No newline at end of file
diff --git a/apps/files_texteditor/js/aceeditor/mode-text-uncompressed.js b/apps/files_texteditor/js/aceeditor/mode-text-uncompressed.js
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/apps/files_texteditor/js/aceeditor/mode-text.js b/apps/files_texteditor/js/aceeditor/mode-text.js
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/apps/files_texteditor/js/aceeditor/mode-textile-uncompressed.js b/apps/files_texteditor/js/aceeditor/mode-textile-uncompressed.js
old mode 100755
new mode 100644
index 8512479596ef2ec2967c9e82ab373fc5023876a9..37a85c316ec8063e4d138e6f25463647db790e9f
--- a/apps/files_texteditor/js/aceeditor/mode-textile-uncompressed.js
+++ b/apps/files_texteditor/js/aceeditor/mode-textile-uncompressed.js
@@ -252,13 +252,3 @@ var MatchingBraceOutdent = function() {};
 
 exports.MatchingBraceOutdent = MatchingBraceOutdent;
 });
-;
-            (function() {
-                window.require(["ace/ace"], function(a) {
-                    if (!window.ace)
-                        window.ace = {};
-                    for (var key in a) if (a.hasOwnProperty(key))
-                        ace[key] = a[key];
-                });
-            })();
-        
\ No newline at end of file
diff --git a/apps/files_texteditor/js/aceeditor/mode-textile.js b/apps/files_texteditor/js/aceeditor/mode-textile.js
index ad30c2d579e30bc8b99d79b1141619590dfd41f2..3b36437c493678962a9c064ae42556f7e2fc6f9e 100644
--- a/apps/files_texteditor/js/aceeditor/mode-textile.js
+++ b/apps/files_texteditor/js/aceeditor/mode-textile.js
@@ -1 +1 @@
-define("ace/mode/textile",["require","exports","module","ace/lib/oop","ace/mode/text","ace/tokenizer","ace/mode/textile_highlight_rules","ace/mode/matching_brace_outdent"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("./text").Mode,f=a("../tokenizer").Tokenizer,g=a("./textile_highlight_rules").TextileHighlightRules,h=a("./matching_brace_outdent").MatchingBraceOutdent,i=function(){this.$tokenizer=new f((new g).getRules()),this.$outdent=new h};d.inherits(i,e),function(){this.getNextLineIndent=function(a,b,c){return a=="intag"?c:""},this.checkOutdent=function(a,b,c){return this.$outdent.checkOutdent(b,c)},this.autoOutdent=function(a,b,c){this.$outdent.autoOutdent(b,c)}}.call(i.prototype),b.Mode=i}),define("ace/mode/textile_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("./text_highlight_rules").TextHighlightRules,f=function(){this.$rules={start:[{token:function(a){return a.match(/^h\d$/)?"markup.heading."+a.charAt(1):"markup.heading"},regex:"h1|h2|h3|h4|h5|h6|bq|p|bc|pre",next:"blocktag"},{token:"keyword",regex:"[\\*]+|[#]+"},{token:"text",regex:".+"}],blocktag:[{token:"keyword",regex:"\\. ",next:"start"},{token:"keyword",regex:"\\(",next:"blocktagproperties"}],blocktagproperties:[{token:"keyword",regex:"\\)",next:"blocktag"},{token:"string",regex:"[a-zA-Z0-9\\-_]+"},{token:"keyword",regex:"#"}]}};d.inherits(f,e),b.TextileHighlightRules=f}),define("ace/mode/matching_brace_outdent",["require","exports","module","ace/range"],function(a,b,c){"use strict";var d=a("../range").Range,e=function(){};((function(){this.checkOutdent=function(a,b){return/^\s+$/.test(a)?/^\s*\}/.test(b):!1},this.autoOutdent=function(a,b){var c=a.getLine(b),e=c.match(/^(\s*\})/);if(!e)return 0;var f=e[1].length,g=a.findMatchingBracket({row:b,column:f});if(!g||g.row==b)return 0;var h=this.$getIndent(a.getLine(g.row));a.replace(new d(b,0,b,f-1),h)},this.$getIndent=function(a){var b=a.match(/^(\s+)/);return b?b[1]:""}})).call(e.prototype),b.MatchingBraceOutdent=e}),function(){window.require(["ace/ace"],function(a){window.ace||(window.ace={});for(var b in a)a.hasOwnProperty(b)&&(ace[b]=a[b])})}()
\ No newline at end of file
+define("ace/mode/textile",["require","exports","module","ace/lib/oop","ace/mode/text","ace/tokenizer","ace/mode/textile_highlight_rules","ace/mode/matching_brace_outdent"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("./text").Mode,f=a("../tokenizer").Tokenizer,g=a("./textile_highlight_rules").TextileHighlightRules,h=a("./matching_brace_outdent").MatchingBraceOutdent,i=function(){this.$tokenizer=new f((new g).getRules()),this.$outdent=new h};d.inherits(i,e),function(){this.getNextLineIndent=function(a,b,c){return a=="intag"?c:""},this.checkOutdent=function(a,b,c){return this.$outdent.checkOutdent(b,c)},this.autoOutdent=function(a,b,c){this.$outdent.autoOutdent(b,c)}}.call(i.prototype),b.Mode=i}),define("ace/mode/textile_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("./text_highlight_rules").TextHighlightRules,f=function(){this.$rules={start:[{token:function(a){return a.match(/^h\d$/)?"markup.heading."+a.charAt(1):"markup.heading"},regex:"h1|h2|h3|h4|h5|h6|bq|p|bc|pre",next:"blocktag"},{token:"keyword",regex:"[\\*]+|[#]+"},{token:"text",regex:".+"}],blocktag:[{token:"keyword",regex:"\\. ",next:"start"},{token:"keyword",regex:"\\(",next:"blocktagproperties"}],blocktagproperties:[{token:"keyword",regex:"\\)",next:"blocktag"},{token:"string",regex:"[a-zA-Z0-9\\-_]+"},{token:"keyword",regex:"#"}]}};d.inherits(f,e),b.TextileHighlightRules=f}),define("ace/mode/matching_brace_outdent",["require","exports","module","ace/range"],function(a,b,c){"use strict";var d=a("../range").Range,e=function(){};(function(){this.checkOutdent=function(a,b){return/^\s+$/.test(a)?/^\s*\}/.test(b):!1},this.autoOutdent=function(a,b){var c=a.getLine(b),e=c.match(/^(\s*\})/);if(!e)return 0;var f=e[1].length,g=a.findMatchingBracket({row:b,column:f});if(!g||g.row==b)return 0;var h=this.$getIndent(a.getLine(g.row));a.replace(new d(b,0,b,f-1),h)},this.$getIndent=function(a){var b=a.match(/^(\s+)/);return b?b[1]:""}}).call(e.prototype),b.MatchingBraceOutdent=e})
\ No newline at end of file
diff --git a/apps/files_texteditor/js/aceeditor/mode-xml-uncompressed.js b/apps/files_texteditor/js/aceeditor/mode-xml-uncompressed.js
old mode 100755
new mode 100644
index bc27c17f55b687884f7e66b14fd5578ac2405d3f..e1af69123b25029317a98492cba7d70771fdcba7
--- a/apps/files_texteditor/js/aceeditor/mode-xml-uncompressed.js
+++ b/apps/files_texteditor/js/aceeditor/mode-xml-uncompressed.js
@@ -124,6 +124,9 @@ var XmlHighlightRules = function() {
             merge : true,
             regex : "<\\!--",
             next : "comment"
+        }, {
+            token : "xml_pe",
+            regex : "<\\!.*?>"
         }, {
             token : "meta.tag", // opening tag
             regex : "<\\/?",
@@ -131,6 +134,9 @@ var XmlHighlightRules = function() {
         }, {
             token : "text",
             regex : "\\s+"
+        }, {
+            token : "constant.character.entity",
+            regex : "(?:&#[0-9]+;)|(?:&#x[0-9a-fA-F]+;)|(?:&[a-zA-Z0-9_:\\.-]+;)"
         }, {
             token : "text",
             regex : "[^<]+"
@@ -224,7 +230,7 @@ function string(state) {
         token : "string", // multi line string start
         merge : true,
         regex : '["].*',
-        next : state + "-qqstring"
+        next : state + "_qqstring"
     }, {
         token : "string",
         regex : "'.*?'"
@@ -232,7 +238,7 @@ function string(state) {
         token : "string", // multi line string start
         merge : true,
         regex : "['].*",
-        next : state + "-qstring"
+        next : state + "_qstring"
     }];
 }
 
@@ -280,18 +286,18 @@ exports.tag = function(states, name, nextState) {
             }
         },        
         merge : true,
-        regex : "[-_a-zA-Z0-9:!]+",
-        next : name + "embed-attribute-list" 
+        regex : "[-_a-zA-Z0-9:]+",
+        next : name + "_embed_attribute_list" 
     }, {
         token: "empty",
         regex: "",
-        next : name + "embed-attribute-list"
+        next : name + "_embed_attribute_list"
     }];
 
-    states[name + "-qstring"] = multiLineString("'", name + "embed-attribute-list");
-    states[name + "-qqstring"] = multiLineString("\"", name + "embed-attribute-list");
+    states[name + "_qstring"] = multiLineString("'", name + "_embed_attribute_list");
+    states[name + "_qqstring"] = multiLineString("\"", name + "_embed_attribute_list");
     
-    states[name + "embed-attribute-list"] = [{
+    states[name + "_embed_attribute_list"] = [{
         token : "meta.tag",
         merge : true,
         regex : "\/?>",
@@ -457,12 +463,12 @@ var CstyleBehaviour = function () {
                 return {
                     text: '{' + selected + '}',
                     selection: false
-                }
+                };
             } else {
                 return {
                     text: '{}',
                     selection: [1, 1]
-                }
+                };
             }
         } else if (text == '}') {
             var cursor = editor.getCursorPosition();
@@ -474,7 +480,7 @@ var CstyleBehaviour = function () {
                     return {
                         text: '',
                         selection: [1, 1]
-                    }
+                    };
                 }
             }
         } else if (text == "\n") {
@@ -492,7 +498,7 @@ var CstyleBehaviour = function () {
                 return {
                     text: '\n' + indent + '\n' + next_indent,
                     selection: [1, indent.length, 1, indent.length]
-                }
+                };
             }
         }
     });
@@ -517,12 +523,12 @@ var CstyleBehaviour = function () {
                 return {
                     text: '(' + selected + ')',
                     selection: false
-                }
+                };
             } else {
                 return {
                     text: '()',
                     selection: [1, 1]
-                }
+                };
             }
         } else if (text == ')') {
             var cursor = editor.getCursorPosition();
@@ -534,7 +540,7 @@ var CstyleBehaviour = function () {
                     return {
                         text: '',
                         selection: [1, 1]
-                    }
+                    };
                 }
             }
         }
@@ -553,14 +559,15 @@ var CstyleBehaviour = function () {
     });
 
     this.add("string_dquotes", "insertion", function (state, action, editor, session, text) {
-        if (text == '"') {
+        if (text == '"' || text == "'") {
+            var quote = text;
             var selection = editor.getSelectionRange();
             var selected = session.doc.getTextRange(selection);
             if (selected !== "") {
                 return {
-                    text: '"' + selected + '"',
+                    text: quote + selected + quote,
                     selection: false
-                }
+                };
             } else {
                 var cursor = editor.getCursorPosition();
                 var line = session.doc.getLine(cursor.row);
@@ -581,7 +588,7 @@ var CstyleBehaviour = function () {
                     if (token.type == "string") {
                       quotepos = -1;
                     } else if (quotepos < 0) {
-                      quotepos = token.value.indexOf('"');
+                      quotepos = token.value.indexOf(quote);
                     }
                     if ((token.value.length + col) > selection.start.column) {
                         break;
@@ -590,19 +597,19 @@ var CstyleBehaviour = function () {
                 }
 
                 // Try and be smart about when we auto insert.
-                if (!token || (quotepos < 0 && token.type !== "comment" && (token.type !== "string" || ((selection.start.column !== token.value.length+col-1) && token.value.lastIndexOf('"') === token.value.length-1)))) {
+                if (!token || (quotepos < 0 && token.type !== "comment" && (token.type !== "string" || ((selection.start.column !== token.value.length+col-1) && token.value.lastIndexOf(quote) === token.value.length-1)))) {
                     return {
-                        text: '""',
+                        text: quote + quote,
                         selection: [1,1]
-                    }
+                    };
                 } else if (token && token.type === "string") {
                     // Ignore input and move right one if we're typing over the closing quote.
                     var rightChar = line.substring(cursor.column, cursor.column + 1);
-                    if (rightChar == '"') {
+                    if (rightChar == quote) {
                         return {
                             text: '',
                             selection: [1, 1]
-                        }
+                        };
                     }
                 }
             }
@@ -611,7 +618,7 @@ var CstyleBehaviour = function () {
 
     this.add("string_dquotes", "deletion", function (state, action, editor, session, range) {
         var selected = session.doc.getTextRange(range);
-        if (!range.isMultiLine() && selected == '"') {
+        if (!range.isMultiLine() && (selected == '"' || selected == "'")) {
             var line = session.doc.getLine(range.start.row);
             var rightChar = line.substring(range.start.column + 1, range.start.column + 2);
             if (rightChar == '"') {
@@ -621,7 +628,8 @@ var CstyleBehaviour = function () {
         }
     });
 
-}
+};
+
 oop.inherits(CstyleBehaviour, Behaviour);
 
 exports.CstyleBehaviour = CstyleBehaviour;
@@ -999,13 +1007,3 @@ var FoldMode = exports.FoldMode = function() {};
 }).call(FoldMode.prototype);
 
 });
-;
-            (function() {
-                window.require(["ace/ace"], function(a) {
-                    if (!window.ace)
-                        window.ace = {};
-                    for (var key in a) if (a.hasOwnProperty(key))
-                        ace[key] = a[key];
-                });
-            })();
-        
\ No newline at end of file
diff --git a/apps/files_texteditor/js/aceeditor/mode-xml.js b/apps/files_texteditor/js/aceeditor/mode-xml.js
index 236ab2430eb2e36096a13cbf094046a5ca7151da..27c038a13b94bcf0f417b75a88a467e7e0f281a0 100644
--- a/apps/files_texteditor/js/aceeditor/mode-xml.js
+++ b/apps/files_texteditor/js/aceeditor/mode-xml.js
@@ -1 +1 @@
-define("ace/mode/xml",["require","exports","module","ace/lib/oop","ace/mode/text","ace/tokenizer","ace/mode/xml_highlight_rules","ace/mode/behaviour/xml","ace/mode/folding/xml"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("./text").Mode,f=a("../tokenizer").Tokenizer,g=a("./xml_highlight_rules").XmlHighlightRules,h=a("./behaviour/xml").XmlBehaviour,i=a("./folding/xml").FoldMode,j=function(){this.$tokenizer=new f((new g).getRules()),this.$behaviour=new h,this.foldingRules=new i};d.inherits(j,e),function(){this.getNextLineIndent=function(a,b,c){return this.$getIndent(b)}}.call(j.prototype),b.Mode=j}),define("ace/mode/xml_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/xml_util","ace/mode/text_highlight_rules"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("./xml_util"),f=a("./text_highlight_rules").TextHighlightRules,g=function(){this.$rules={start:[{token:"text",regex:"<\\!\\[CDATA\\[",next:"cdata"},{token:"xml_pe",regex:"<\\?.*?\\?>"},{token:"comment",merge:!0,regex:"<\\!--",next:"comment"},{token:"meta.tag",regex:"<\\/?",next:"tag"},{token:"text",regex:"\\s+"},{token:"text",regex:"[^<]+"}],cdata:[{token:"text",regex:"\\]\\]>",next:"start"},{token:"text",regex:"\\s+"},{token:"text",regex:"(?:[^\\]]|\\](?!\\]>))+"}],comment:[{token:"comment",regex:".*?-->",next:"start"},{token:"comment",merge:!0,regex:".+"}]},e.tag(this.$rules,"tag","start")};d.inherits(g,f),b.XmlHighlightRules=g}),define("ace/mode/xml_util",["require","exports","module","ace/lib/lang"],function(a,b,c){function g(a){return[{token:"string",regex:'".*?"'},{token:"string",merge:!0,regex:'["].*',next:a+"-qqstring"},{token:"string",regex:"'.*?'"},{token:"string",merge:!0,regex:"['].*",next:a+"-qstring"}]}function h(a,b){return[{token:"string",merge:!0,regex:".*?"+a,next:b},{token:"string",merge:!0,regex:".+"}]}"use strict";var d=a("../lib/lang"),e=d.arrayToMap("button|form|input|label|select|textarea".split("|")),f=d.arrayToMap("table|tbody|td|tfoot|th|tr".split("|"));b.tag=function(a,b,c){a[b]=[{token:"text",regex:"\\s+"},{token:function(a){return a==="a"?"meta.tag.anchor":a==="img"?"meta.tag.image":a==="script"?"meta.tag.script":a==="style"?"meta.tag.style":e.hasOwnProperty(a.toLowerCase())?"meta.tag.form":f.hasOwnProperty(a.toLowerCase())?"meta.tag.table":"meta.tag"},merge:!0,regex:"[-_a-zA-Z0-9:!]+",next:b+"embed-attribute-list"},{token:"empty",regex:"",next:b+"embed-attribute-list"}],a[b+"-qstring"]=h("'",b+"embed-attribute-list"),a[b+"-qqstring"]=h('"',b+"embed-attribute-list"),a[b+"embed-attribute-list"]=[{token:"meta.tag",merge:!0,regex:"/?>",next:c},{token:"keyword.operator",regex:"="},{token:"entity.other.attribute-name",regex:"[-_a-zA-Z0-9:]+"},{token:"constant.numeric",regex:"[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"},{token:"text",regex:"\\s+"}].concat(g(b))}}),define("ace/mode/behaviour/xml",["require","exports","module","ace/lib/oop","ace/mode/behaviour","ace/mode/behaviour/cstyle"],function(a,b,c){"use strict";var d=a("../../lib/oop"),e=a("../behaviour").Behaviour,f=a("./cstyle").CstyleBehaviour,g=function(){this.inherit(f,["string_dquotes"]),this.add("brackets","insertion",function(a,b,c,d,e){if(e=="<"){var f=c.getSelectionRange(),g=d.doc.getTextRange(f);return g!==""?!1:{text:"<>",selection:[1,1]}}if(e==">"){var h=c.getCursorPosition(),i=d.doc.getLine(h.row),j=i.substring(h.column,h.column+1);if(j==">")return{text:"",selection:[1,1]}}else if(e=="\n"){var h=c.getCursorPosition(),i=d.doc.getLine(h.row),k=i.substring(h.column,h.column+2);if(k=="</"){var l=this.$getIndent(d.doc.getLine(h.row))+d.getTabString(),m=this.$getIndent(d.doc.getLine(h.row));return{text:"\n"+l+"\n"+m,selection:[1,l.length,1,l.length]}}}})};d.inherits(g,e),b.XmlBehaviour=g}),define("ace/mode/behaviour/cstyle",["require","exports","module","ace/lib/oop","ace/mode/behaviour"],function(a,b,c){"use strict";var d=a("../../lib/oop"),e=a("../behaviour").Behaviour,f=function(){this.add("braces","insertion",function(a,b,c,d,e){if(e=="{"){var f=c.getSelectionRange(),g=d.doc.getTextRange(f);return g!==""?{text:"{"+g+"}",selection:!1}:{text:"{}",selection:[1,1]}}if(e=="}"){var h=c.getCursorPosition(),i=d.doc.getLine(h.row),j=i.substring(h.column,h.column+1);if(j=="}"){var k=d.$findOpeningBracket("}",{column:h.column+1,row:h.row});if(k!==null)return{text:"",selection:[1,1]}}}else if(e=="\n"){var h=c.getCursorPosition(),i=d.doc.getLine(h.row),j=i.substring(h.column,h.column+1);if(j=="}"){var l=d.findMatchingBracket({row:h.row,column:h.column+1});if(!l)return null;var m=this.getNextLineIndent(a,i.substring(0,i.length-1),d.getTabString()),n=this.$getIndent(d.doc.getLine(l.row));return{text:"\n"+m+"\n"+n,selection:[1,m.length,1,m.length]}}}}),this.add("braces","deletion",function(a,b,c,d,e){var f=d.doc.getTextRange(e);if(!e.isMultiLine()&&f=="{"){var g=d.doc.getLine(e.start.row),h=g.substring(e.end.column,e.end.column+1);if(h=="}")return e.end.column++,e}}),this.add("parens","insertion",function(a,b,c,d,e){if(e=="("){var f=c.getSelectionRange(),g=d.doc.getTextRange(f);return g!==""?{text:"("+g+")",selection:!1}:{text:"()",selection:[1,1]}}if(e==")"){var h=c.getCursorPosition(),i=d.doc.getLine(h.row),j=i.substring(h.column,h.column+1);if(j==")"){var k=d.$findOpeningBracket(")",{column:h.column+1,row:h.row});if(k!==null)return{text:"",selection:[1,1]}}}}),this.add("parens","deletion",function(a,b,c,d,e){var f=d.doc.getTextRange(e);if(!e.isMultiLine()&&f=="("){var g=d.doc.getLine(e.start.row),h=g.substring(e.start.column+1,e.start.column+2);if(h==")")return e.end.column++,e}}),this.add("string_dquotes","insertion",function(a,b,c,d,e){if(e=='"'){var f=c.getSelectionRange(),g=d.doc.getTextRange(f);if(g!=="")return{text:'"'+g+'"',selection:!1};var h=c.getCursorPosition(),i=d.doc.getLine(h.row),j=i.substring(h.column-1,h.column);if(j=="\\")return null;var k=d.getTokens(f.start.row,f.start.row)[0].tokens,l=0,m,n=-1;for(var o=0;o<k.length;o++){m=k[o],m.type=="string"?n=-1:n<0&&(n=m.value.indexOf('"'));if(m.value.length+l>f.start.column)break;l+=k[o].value.length}if(!m||n<0&&m.type!=="comment"&&(m.type!=="string"||f.start.column!==m.value.length+l-1&&m.value.lastIndexOf('"')===m.value.length-1))return{text:'""',selection:[1,1]};if(m&&m.type==="string"){var p=i.substring(h.column,h.column+1);if(p=='"')return{text:"",selection:[1,1]}}}}),this.add("string_dquotes","deletion",function(a,b,c,d,e){var f=d.doc.getTextRange(e);if(!e.isMultiLine()&&f=='"'){var g=d.doc.getLine(e.start.row),h=g.substring(e.start.column+1,e.start.column+2);if(h=='"')return e.end.column++,e}})};d.inherits(f,e),b.CstyleBehaviour=f}),define("ace/mode/folding/xml",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/range","ace/mode/folding/fold_mode","ace/token_iterator"],function(a,b,c){"use strict";var d=a("../../lib/oop"),e=a("../../lib/lang"),f=a("../../range").Range,g=a("./fold_mode").FoldMode,h=a("../../token_iterator").TokenIterator,i=b.FoldMode=function(a){g.call(this),this.voidElements=a||{}};d.inherits(i,g),function(){this.getFoldWidget=function(a,b,c){var d=this._getFirstTagInLine(a,c);return d.closing?b=="markbeginend"?"end":"":!d.tagName||this.voidElements[d.tagName.toLowerCase()]?"":d.selfClosing?"":d.value.indexOf("/"+d.tagName)!==-1?"":"start"},this._getFirstTagInLine=function(a,b){var c=a.getTokens(b,b)[0].tokens,d="";for(var f=0;f<c.length;f++){var g=c[f];g.type.indexOf("meta.tag")===0?d+=g.value:d+=e.stringRepeat(" ",g.value.length)}return this._parseTag(d)},this.tagRe=/^(\s*)(<?(\/?)([-_a-zA-Z0-9:!]*)\s*(\/?)>?)/,this._parseTag=function(a){var b=this.tagRe.exec(a),c=this.tagRe.lastIndex||0;return this.tagRe.lastIndex=0,{value:a,match:b?b[2]:"",closing:b?!!b[3]:!1,selfClosing:b?!!b[5]||b[2]=="/>":!1,tagName:b?b[4]:"",column:b[1]?c+b[1].length:c}},this._readTagForward=function(a){var b=a.getCurrentToken();if(!b)return null;var c="",d;do if(b.type.indexOf("meta.tag")===0){if(!d)var d={row:a.getCurrentTokenRow(),column:a.getCurrentTokenColumn()};c+=b.value;if(c.indexOf(">")!==-1){var e=this._parseTag(c);return e.start=d,e.end={row:a.getCurrentTokenRow(),column:a.getCurrentTokenColumn()+b.value.length},a.stepForward(),e}}while(b=a.stepForward());return null},this._readTagBackward=function(a){var b=a.getCurrentToken();if(!b)return null;var c="",d;do if(b.type.indexOf("meta.tag")===0){d||(d={row:a.getCurrentTokenRow(),column:a.getCurrentTokenColumn()+b.value.length}),c=b.value+c;if(c.indexOf("<")!==-1){var e=this._parseTag(c);return e.end=d,e.start={row:a.getCurrentTokenRow(),column:a.getCurrentTokenColumn()},a.stepBackward(),e}}while(b=a.stepBackward());return null},this._pop=function(a,b){while(a.length){var c=a[a.length-1];if(!b||c.tagName==b.tagName)return a.pop();if(this.voidElements[b.tagName])return;if(this.voidElements[c.tagName]){a.pop();continue}return null}},this.getFoldWidgetRange=function(a,b,c){var d=this._getFirstTagInLine(a,c);if(!d.match)return null;var e=d.closing||d.selfClosing,g=[],i;if(!e){var j=new h(a,c,d.column),k={row:c,column:d.column+d.tagName.length+2};while(i=this._readTagForward(j)){if(i.selfClosing){if(!g.length)return i.start.column+=i.tagName.length+2,i.end.column-=2,f.fromPoints(i.start,i.end);continue}if(i.closing){this._pop(g,i);if(g.length==0)return f.fromPoints(k,i.start)}else g.push(i)}}else{var j=new h(a,c,d.column+d.match.length),l={row:c,column:d.column};while(i=this._readTagBackward(j)){if(i.selfClosing){if(!g.length)return i.start.column+=i.tagName.length+2,i.end.column-=2,f.fromPoints(i.start,i.end);continue}if(!i.closing){this._pop(g,i);if(g.length==0)return i.start.column+=i.tagName.length+2,f.fromPoints(i.start,l)}else g.push(i)}}}}.call(i.prototype)}),define("ace/mode/folding/fold_mode",["require","exports","module","ace/range"],function(a,b,c){"use strict";var d=a("../../range").Range,e=b.FoldMode=function(){};((function(){this.foldingStartMarker=null,this.foldingStopMarker=null,this.getFoldWidget=function(a,b,c){var d=a.getLine(c);return this.foldingStartMarker.test(d)?"start":b=="markbeginend"&&this.foldingStopMarker&&this.foldingStopMarker.test(d)?"end":""},this.getFoldWidgetRange=function(a,b,c){return null},this.indentationBlock=function(a,b,c){var e=/^\s*/,f=b,g=b,h=a.getLine(b),i=c||h.length,j=h.match(e)[0].length,k=a.getLength();while(++b<k){h=a.getLine(b);var l=h.match(e)[0].length;if(l==h.length)continue;if(l<=j)break;g=b}if(g>f){var m=a.getLine(g).length;return new d(f,i,g,m)}},this.openingBracketBlock=function(a,b,c,e){var f={row:c,column:e+1},g=a.$findClosingBracket(b,f);if(!g)return;var h=a.foldWidgets[g.row];return h==null&&(h=this.getFoldWidget(a,g.row)),h=="start"&&(g.row--,g.column=a.getLine(g.row).length),d.fromPoints(f,g)}})).call(e.prototype)}),function(){window.require(["ace/ace"],function(a){window.ace||(window.ace={});for(var b in a)a.hasOwnProperty(b)&&(ace[b]=a[b])})}()
\ No newline at end of file
+define("ace/mode/xml",["require","exports","module","ace/lib/oop","ace/mode/text","ace/tokenizer","ace/mode/xml_highlight_rules","ace/mode/behaviour/xml","ace/mode/folding/xml"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("./text").Mode,f=a("../tokenizer").Tokenizer,g=a("./xml_highlight_rules").XmlHighlightRules,h=a("./behaviour/xml").XmlBehaviour,i=a("./folding/xml").FoldMode,j=function(){this.$tokenizer=new f((new g).getRules()),this.$behaviour=new h,this.foldingRules=new i};d.inherits(j,e),function(){this.getNextLineIndent=function(a,b,c){return this.$getIndent(b)}}.call(j.prototype),b.Mode=j}),define("ace/mode/xml_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/xml_util","ace/mode/text_highlight_rules"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("./xml_util"),f=a("./text_highlight_rules").TextHighlightRules,g=function(){this.$rules={start:[{token:"text",regex:"<\\!\\[CDATA\\[",next:"cdata"},{token:"xml_pe",regex:"<\\?.*?\\?>"},{token:"comment",merge:!0,regex:"<\\!--",next:"comment"},{token:"xml_pe",regex:"<\\!.*?>"},{token:"meta.tag",regex:"<\\/?",next:"tag"},{token:"text",regex:"\\s+"},{token:"constant.character.entity",regex:"(?:&#[0-9]+;)|(?:&#x[0-9a-fA-F]+;)|(?:&[a-zA-Z0-9_:\\.-]+;)"},{token:"text",regex:"[^<]+"}],cdata:[{token:"text",regex:"\\]\\]>",next:"start"},{token:"text",regex:"\\s+"},{token:"text",regex:"(?:[^\\]]|\\](?!\\]>))+"}],comment:[{token:"comment",regex:".*?-->",next:"start"},{token:"comment",merge:!0,regex:".+"}]},e.tag(this.$rules,"tag","start")};d.inherits(g,f),b.XmlHighlightRules=g}),define("ace/mode/xml_util",["require","exports","module","ace/lib/lang"],function(a,b,c){function g(a){return[{token:"string",regex:'".*?"'},{token:"string",merge:!0,regex:'["].*',next:a+"_qqstring"},{token:"string",regex:"'.*?'"},{token:"string",merge:!0,regex:"['].*",next:a+"_qstring"}]}function h(a,b){return[{token:"string",merge:!0,regex:".*?"+a,next:b},{token:"string",merge:!0,regex:".+"}]}"use strict";var d=a("../lib/lang"),e=d.arrayToMap("button|form|input|label|select|textarea".split("|")),f=d.arrayToMap("table|tbody|td|tfoot|th|tr".split("|"));b.tag=function(a,b,c){a[b]=[{token:"text",regex:"\\s+"},{token:function(a){return a==="a"?"meta.tag.anchor":a==="img"?"meta.tag.image":a==="script"?"meta.tag.script":a==="style"?"meta.tag.style":e.hasOwnProperty(a.toLowerCase())?"meta.tag.form":f.hasOwnProperty(a.toLowerCase())?"meta.tag.table":"meta.tag"},merge:!0,regex:"[-_a-zA-Z0-9:]+",next:b+"_embed_attribute_list"},{token:"empty",regex:"",next:b+"_embed_attribute_list"}],a[b+"_qstring"]=h("'",b+"_embed_attribute_list"),a[b+"_qqstring"]=h('"',b+"_embed_attribute_list"),a[b+"_embed_attribute_list"]=[{token:"meta.tag",merge:!0,regex:"/?>",next:c},{token:"keyword.operator",regex:"="},{token:"entity.other.attribute-name",regex:"[-_a-zA-Z0-9:]+"},{token:"constant.numeric",regex:"[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"},{token:"text",regex:"\\s+"}].concat(g(b))}}),define("ace/mode/behaviour/xml",["require","exports","module","ace/lib/oop","ace/mode/behaviour","ace/mode/behaviour/cstyle"],function(a,b,c){"use strict";var d=a("../../lib/oop"),e=a("../behaviour").Behaviour,f=a("./cstyle").CstyleBehaviour,g=function(){this.inherit(f,["string_dquotes"]),this.add("brackets","insertion",function(a,b,c,d,e){if(e=="<"){var f=c.getSelectionRange(),g=d.doc.getTextRange(f);return g!==""?!1:{text:"<>",selection:[1,1]}}if(e==">"){var h=c.getCursorPosition(),i=d.doc.getLine(h.row),j=i.substring(h.column,h.column+1);if(j==">")return{text:"",selection:[1,1]}}else if(e=="\n"){var h=c.getCursorPosition(),i=d.doc.getLine(h.row),k=i.substring(h.column,h.column+2);if(k=="</"){var l=this.$getIndent(d.doc.getLine(h.row))+d.getTabString(),m=this.$getIndent(d.doc.getLine(h.row));return{text:"\n"+l+"\n"+m,selection:[1,l.length,1,l.length]}}}})};d.inherits(g,e),b.XmlBehaviour=g}),define("ace/mode/behaviour/cstyle",["require","exports","module","ace/lib/oop","ace/mode/behaviour"],function(a,b,c){"use strict";var d=a("../../lib/oop"),e=a("../behaviour").Behaviour,f=function(){this.add("braces","insertion",function(a,b,c,d,e){if(e=="{"){var f=c.getSelectionRange(),g=d.doc.getTextRange(f);return g!==""?{text:"{"+g+"}",selection:!1}:{text:"{}",selection:[1,1]}}if(e=="}"){var h=c.getCursorPosition(),i=d.doc.getLine(h.row),j=i.substring(h.column,h.column+1);if(j=="}"){var k=d.$findOpeningBracket("}",{column:h.column+1,row:h.row});if(k!==null)return{text:"",selection:[1,1]}}}else if(e=="\n"){var h=c.getCursorPosition(),i=d.doc.getLine(h.row),j=i.substring(h.column,h.column+1);if(j=="}"){var l=d.findMatchingBracket({row:h.row,column:h.column+1});if(!l)return null;var m=this.getNextLineIndent(a,i.substring(0,i.length-1),d.getTabString()),n=this.$getIndent(d.doc.getLine(l.row));return{text:"\n"+m+"\n"+n,selection:[1,m.length,1,m.length]}}}}),this.add("braces","deletion",function(a,b,c,d,e){var f=d.doc.getTextRange(e);if(!e.isMultiLine()&&f=="{"){var g=d.doc.getLine(e.start.row),h=g.substring(e.end.column,e.end.column+1);if(h=="}")return e.end.column++,e}}),this.add("parens","insertion",function(a,b,c,d,e){if(e=="("){var f=c.getSelectionRange(),g=d.doc.getTextRange(f);return g!==""?{text:"("+g+")",selection:!1}:{text:"()",selection:[1,1]}}if(e==")"){var h=c.getCursorPosition(),i=d.doc.getLine(h.row),j=i.substring(h.column,h.column+1);if(j==")"){var k=d.$findOpeningBracket(")",{column:h.column+1,row:h.row});if(k!==null)return{text:"",selection:[1,1]}}}}),this.add("parens","deletion",function(a,b,c,d,e){var f=d.doc.getTextRange(e);if(!e.isMultiLine()&&f=="("){var g=d.doc.getLine(e.start.row),h=g.substring(e.start.column+1,e.start.column+2);if(h==")")return e.end.column++,e}}),this.add("string_dquotes","insertion",function(a,b,c,d,e){if(e=='"'||e=="'"){var f=e,g=c.getSelectionRange(),h=d.doc.getTextRange(g);if(h!=="")return{text:f+h+f,selection:!1};var i=c.getCursorPosition(),j=d.doc.getLine(i.row),k=j.substring(i.column-1,i.column);if(k=="\\")return null;var l=d.getTokens(g.start.row,g.start.row)[0].tokens,m=0,n,o=-1;for(var p=0;p<l.length;p++){n=l[p],n.type=="string"?o=-1:o<0&&(o=n.value.indexOf(f));if(n.value.length+m>g.start.column)break;m+=l[p].value.length}if(!n||o<0&&n.type!=="comment"&&(n.type!=="string"||g.start.column!==n.value.length+m-1&&n.value.lastIndexOf(f)===n.value.length-1))return{text:f+f,selection:[1,1]};if(n&&n.type==="string"){var q=j.substring(i.column,i.column+1);if(q==f)return{text:"",selection:[1,1]}}}}),this.add("string_dquotes","deletion",function(a,b,c,d,e){var f=d.doc.getTextRange(e);if(!e.isMultiLine()&&(f=='"'||f=="'")){var g=d.doc.getLine(e.start.row),h=g.substring(e.start.column+1,e.start.column+2);if(h=='"')return e.end.column++,e}})};d.inherits(f,e),b.CstyleBehaviour=f}),define("ace/mode/folding/xml",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/range","ace/mode/folding/fold_mode","ace/token_iterator"],function(a,b,c){"use strict";var d=a("../../lib/oop"),e=a("../../lib/lang"),f=a("../../range").Range,g=a("./fold_mode").FoldMode,h=a("../../token_iterator").TokenIterator,i=b.FoldMode=function(a){g.call(this),this.voidElements=a||{}};d.inherits(i,g),function(){this.getFoldWidget=function(a,b,c){var d=this._getFirstTagInLine(a,c);return d.closing?b=="markbeginend"?"end":"":!d.tagName||this.voidElements[d.tagName.toLowerCase()]?"":d.selfClosing?"":d.value.indexOf("/"+d.tagName)!==-1?"":"start"},this._getFirstTagInLine=function(a,b){var c=a.getTokens(b,b)[0].tokens,d="";for(var f=0;f<c.length;f++){var g=c[f];g.type.indexOf("meta.tag")===0?d+=g.value:d+=e.stringRepeat(" ",g.value.length)}return this._parseTag(d)},this.tagRe=/^(\s*)(<?(\/?)([-_a-zA-Z0-9:!]*)\s*(\/?)>?)/,this._parseTag=function(a){var b=this.tagRe.exec(a),c=this.tagRe.lastIndex||0;return this.tagRe.lastIndex=0,{value:a,match:b?b[2]:"",closing:b?!!b[3]:!1,selfClosing:b?!!b[5]||b[2]=="/>":!1,tagName:b?b[4]:"",column:b[1]?c+b[1].length:c}},this._readTagForward=function(a){var b=a.getCurrentToken();if(!b)return null;var c="",d;do if(b.type.indexOf("meta.tag")===0){if(!d)var d={row:a.getCurrentTokenRow(),column:a.getCurrentTokenColumn()};c+=b.value;if(c.indexOf(">")!==-1){var e=this._parseTag(c);return e.start=d,e.end={row:a.getCurrentTokenRow(),column:a.getCurrentTokenColumn()+b.value.length},a.stepForward(),e}}while(b=a.stepForward());return null},this._readTagBackward=function(a){var b=a.getCurrentToken();if(!b)return null;var c="",d;do if(b.type.indexOf("meta.tag")===0){d||(d={row:a.getCurrentTokenRow(),column:a.getCurrentTokenColumn()+b.value.length}),c=b.value+c;if(c.indexOf("<")!==-1){var e=this._parseTag(c);return e.end=d,e.start={row:a.getCurrentTokenRow(),column:a.getCurrentTokenColumn()},a.stepBackward(),e}}while(b=a.stepBackward());return null},this._pop=function(a,b){while(a.length){var c=a[a.length-1];if(!b||c.tagName==b.tagName)return a.pop();if(this.voidElements[b.tagName])return;if(this.voidElements[c.tagName]){a.pop();continue}return null}},this.getFoldWidgetRange=function(a,b,c){var d=this._getFirstTagInLine(a,c);if(!d.match)return null;var e=d.closing||d.selfClosing,g=[],i;if(!e){var j=new h(a,c,d.column),k={row:c,column:d.column+d.tagName.length+2};while(i=this._readTagForward(j)){if(i.selfClosing){if(!g.length)return i.start.column+=i.tagName.length+2,i.end.column-=2,f.fromPoints(i.start,i.end);continue}if(i.closing){this._pop(g,i);if(g.length==0)return f.fromPoints(k,i.start)}else g.push(i)}}else{var j=new h(a,c,d.column+d.match.length),l={row:c,column:d.column};while(i=this._readTagBackward(j)){if(i.selfClosing){if(!g.length)return i.start.column+=i.tagName.length+2,i.end.column-=2,f.fromPoints(i.start,i.end);continue}if(!i.closing){this._pop(g,i);if(g.length==0)return i.start.column+=i.tagName.length+2,f.fromPoints(i.start,l)}else g.push(i)}}}}.call(i.prototype)}),define("ace/mode/folding/fold_mode",["require","exports","module","ace/range"],function(a,b,c){"use strict";var d=a("../../range").Range,e=b.FoldMode=function(){};(function(){this.foldingStartMarker=null,this.foldingStopMarker=null,this.getFoldWidget=function(a,b,c){var d=a.getLine(c);return this.foldingStartMarker.test(d)?"start":b=="markbeginend"&&this.foldingStopMarker&&this.foldingStopMarker.test(d)?"end":""},this.getFoldWidgetRange=function(a,b,c){return null},this.indentationBlock=function(a,b,c){var e=/^\s*/,f=b,g=b,h=a.getLine(b),i=c||h.length,j=h.match(e)[0].length,k=a.getLength();while(++b<k){h=a.getLine(b);var l=h.match(e)[0].length;if(l==h.length)continue;if(l<=j)break;g=b}if(g>f){var m=a.getLine(g).length;return new d(f,i,g,m)}},this.openingBracketBlock=function(a,b,c,e){var f={row:c,column:e+1},g=a.$findClosingBracket(b,f);if(!g)return;var h=a.foldWidgets[g.row];return h==null&&(h=this.getFoldWidget(a,g.row)),h=="start"&&(g.row--,g.column=a.getLine(g.row).length),d.fromPoints(f,g)}}).call(e.prototype)})
\ No newline at end of file
diff --git a/apps/files_texteditor/js/aceeditor/mode-xquery-uncompressed.js b/apps/files_texteditor/js/aceeditor/mode-xquery-uncompressed.js
new file mode 100644
index 0000000000000000000000000000000000000000..69effad6e21d0d9fa4659cba4177753af2fe0edb
--- /dev/null
+++ b/apps/files_texteditor/js/aceeditor/mode-xquery-uncompressed.js
@@ -0,0 +1,540 @@
+/*
+ *  eXide - web-based XQuery IDE
+ *  
+ *  Copyright (C) 2011 Wolfgang Meier
+ *
+ *  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/>.
+ */
+define('ace/mode/xquery', ['require', 'exports', 'module' , 'ace/lib/oop', 'ace/mode/text', 'ace/tokenizer', 'ace/mode/xquery_highlight_rules', 'ace/mode/behaviour/xquery', 'ace/range'], function(require, exports, module) {
+"use strict";
+
+var oop = require("../lib/oop");
+var TextMode = require("./text").Mode;
+var Tokenizer = require("../tokenizer").Tokenizer;
+var XQueryHighlightRules = require("./xquery_highlight_rules").XQueryHighlightRules;
+var XQueryBehaviour = require("./behaviour/xquery").XQueryBehaviour;
+var Range = require("../range").Range;
+
+var Mode = function(parent) {
+    this.$tokenizer = new Tokenizer(new XQueryHighlightRules().getRules());
+    this.$behaviour = new XQueryBehaviour(parent);
+};
+
+oop.inherits(Mode, TextMode);
+
+(function() {
+
+    this.getNextLineIndent = function(state, line, tab) {
+      var indent = this.$getIndent(line);
+      var match = line.match(/\s*(?:then|else|return|[{\(]|<\w+>)\s*$/);
+      if (match)
+        indent += tab;
+        return indent;
+    };
+    
+    this.checkOutdent = function(state, line, input) {
+      if (! /^\s+$/.test(line))
+            return false;
+
+        return /^\s*[\}\)]/.test(input);
+    };
+    
+    this.autoOutdent = function(state, doc, row) {
+      var line = doc.getLine(row);
+        var match = line.match(/^(\s*[\}\)])/);
+
+        if (!match) return 0;
+
+        var column = match[1].length;
+        var openBracePos = doc.findMatchingBracket({row: row, column: column});
+
+        if (!openBracePos || openBracePos.row == row) return 0;
+
+        var indent = this.$getIndent(doc.getLine(openBracePos.row));
+        doc.replace(new Range(row, 0, row, column-1), indent);
+    };
+
+    this.$getIndent = function(line) {
+        var match = line.match(/^(\s+)/);
+        if (match) {
+            return match[1];
+        }
+
+        return "";
+    };
+    
+    this.toggleCommentLines = function(state, doc, startRow, endRow) {
+        var i, line;
+        var outdent = true;
+        var re = /^\s*\(:(.*):\)/;
+
+        for (i=startRow; i<= endRow; i++) {
+            if (!re.test(doc.getLine(i))) {
+                outdent = false;
+                break;
+            }
+        }
+
+        var range = new Range(0, 0, 0, 0);
+        for (i=startRow; i<= endRow; i++) {
+            line = doc.getLine(i);
+            range.start.row  = i;
+            range.end.row    = i;
+            range.end.column = line.length;
+
+            doc.replace(range, outdent ? line.match(re)[1] : "(:" + line + ":)");
+        }
+    };
+}).call(Mode.prototype);
+
+exports.Mode = Mode;
+});
+/*
+ *  eXide - web-based XQuery IDE
+ *  
+ *  Copyright (C) 2011 Wolfgang Meier
+ *
+ *  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/>.
+ */
+define('ace/mode/xquery_highlight_rules', ['require', 'exports', 'module' , 'ace/lib/oop', 'ace/lib/lang', 'ace/mode/text_highlight_rules'], function(require, exports, module) {
+"use strict";
+
+var oop = require("../lib/oop");
+var lang = require("../lib/lang");
+var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
+
+var XQueryHighlightRules = function() {
+
+  var keywords = lang.arrayToMap(
+    ("return|for|let|where|order|by|declare|function|variable|xquery|version|option|namespace|import|module|when|encoding|" +
+     "switch|default|try|catch|group|tumbling|sliding|window|start|end|at|only|" +
+     "using|stemming|" +
+     "while|" + 
+     "external|" +
+     "if|then|else|as|and|or|typeswitch|case|ascending|descending|empty|in|count|updating|insert|delete|replace|value|node|attribute|text|element|into|of|with|contains").split("|")
+    );
+
+    // regexp must not have capturing parentheses
+    // regexps are ordered -> the first match is used
+
+    this.$rules = {
+        start : [ {
+            token : "text",
+            regex : "<\\!\\[CDATA\\[",
+            next : "cdata"
+        }, {
+            token : "xml_pe",
+            regex : "<\\?.*?\\?>"
+        }, {
+            token : "comment",
+            regex : "<\\!--",
+            next : "comment"
+    }, {
+      token : "comment",
+      regex : "\\(:",
+      next : "comment"
+        }, {
+            token : "text", // opening tag
+            regex : "<\\/?",
+            next : "tag"
+        }, {
+            token : "constant", // number
+            regex : "[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"
+    }, {
+            token : "variable", // variable
+            regex : "\\$[a-zA-Z_][a-zA-Z0-9_\\-:]*\\b"
+    }, {
+      token: "string",
+      regex : '".*?"'
+    }, {
+      token: "string",
+      regex : "'.*?'"
+        }, {
+            token : "text",
+            regex : "\\s+"
+        }, {
+            token: "support.function",
+            regex: "\\w[\\w+_\\-:]+(?=\\()"
+        }, {
+      token : function(value) {
+            if (keywords[value])
+                return "keyword";
+            else
+                return "identifier";
+      },
+      regex : "[a-zA-Z_$][a-zA-Z0-9_$]*\\b"
+    }, {
+            token: "keyword.operator",
+            regex: "\\*|=|<|>|\\-|\\+|and|or|eq|ne|lt|gt"
+        }, {
+            token: "lparen",
+            regex: "[[({]"
+        }, {
+            token: "rparen",
+            regex: "[\\])}]"
+        } ],
+
+        tag : [ {
+            token : "text",
+            regex : ">",
+            next : "start"
+        }, {
+            token : "meta.tag",
+            regex : "[-_a-zA-Z0-9:]+"
+        }, {
+            token : "text",
+            regex : "\\s+"
+        }, {
+            token : "string",
+            regex : '".*?"'
+        }, {
+            token : "string",
+            regex : "'.*?'"
+        } ],
+
+        cdata : [ {
+            token : "text",
+            regex : "\\]\\]>",
+            next : "start"
+        }, {
+            token : "text",
+            regex : "\\s+"
+        }, {
+            token : "text",
+            regex : "(?:[^\\]]|\\](?!\\]>))+"
+        } ],
+
+        comment : [ {
+            token : "comment",
+            regex : ".*?-->",
+            next : "start"
+        }, {
+      token: "comment",
+      regex : ".*:\\)",
+      next : "start"
+        }, {
+            token : "comment",
+            regex : ".+"
+    } ]
+    };
+};
+
+oop.inherits(XQueryHighlightRules, TextHighlightRules);
+
+exports.XQueryHighlightRules = XQueryHighlightRules;
+});
+/*
+*  eXide - web-based XQuery IDE
+*  
+*  Copyright (C) 2011 Wolfgang Meier
+*
+*  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/>.
+*/
+define('ace/mode/behaviour/xquery', ['require', 'exports', 'module' , 'ace/lib/oop', 'ace/mode/behaviour', 'ace/mode/behaviour/cstyle'], function(require, exports, module) {
+"use strict";
+
+  var oop = require("../../lib/oop");
+  var Behaviour = require('../behaviour').Behaviour;
+  var CstyleBehaviour = require('./cstyle').CstyleBehaviour;
+
+  var XQueryBehaviour = function (parent) {
+      
+      this.inherit(CstyleBehaviour, ["braces", "parens", "string_dquotes"]); // Get string behaviour
+      this.parent = parent;
+      
+      this.add("brackets", "insertion", function (state, action, editor, session, text) {
+          if (text == "\n") {
+              var cursor = editor.getCursorPosition();
+              var line = session.doc.getLine(cursor.row);
+              var rightChars = line.substring(cursor.column, cursor.column + 2);
+              if (rightChars == '</') {
+                  var indent = this.$getIndent(session.doc.getLine(cursor.row)) + session.getTabString();
+                  var next_indent = this.$getIndent(session.doc.getLine(cursor.row));
+
+                  return {
+                      text: '\n' + indent + '\n' + next_indent,
+                      selection: [1, indent.length, 1, indent.length]
+                  }
+              }
+          }
+          return false;
+      });
+
+      // Check for open tag if user enters / and auto-close it.
+      this.add("slash", "insertion", function (state, action, editor, session, text) {
+        if (text == "/") {
+          var cursor = editor.getCursorPosition();
+        var line = session.doc.getLine(cursor.row);
+        if (cursor.column > 0 && line.charAt(cursor.column - 1) == "<") {
+          line = line.substring(0, cursor.column) + "/" + line.substring(cursor.column);
+          var lines = session.doc.getAllLines();
+          lines[cursor.row] = line;
+          // call mode helper to close the tag if possible
+          parent.exec("closeTag", lines.join(session.doc.getNewLineCharacter()), cursor.row);
+        }
+        }
+      return false;
+      });
+  }
+  oop.inherits(XQueryBehaviour, Behaviour);
+
+  exports.XQueryBehaviour = XQueryBehaviour;
+});
+/* vim:ts=4:sts=4:sw=4:
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Ajax.org Code Editor (ACE).
+ *
+ * The Initial Developer of the Original Code is
+ * Ajax.org B.V.
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *      Chris Spencer <chris.ag.spencer AT googlemail DOT com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+define('ace/mode/behaviour/cstyle', ['require', 'exports', 'module' , 'ace/lib/oop', 'ace/mode/behaviour'], function(require, exports, module) {
+"use strict";
+
+var oop = require("../../lib/oop");
+var Behaviour = require('../behaviour').Behaviour;
+
+var CstyleBehaviour = function () {
+
+    this.add("braces", "insertion", function (state, action, editor, session, text) {
+        if (text == '{') {
+            var selection = editor.getSelectionRange();
+            var selected = session.doc.getTextRange(selection);
+            if (selected !== "") {
+                return {
+                    text: '{' + selected + '}',
+                    selection: false
+                };
+            } else {
+                return {
+                    text: '{}',
+                    selection: [1, 1]
+                };
+            }
+        } else if (text == '}') {
+            var cursor = editor.getCursorPosition();
+            var line = session.doc.getLine(cursor.row);
+            var rightChar = line.substring(cursor.column, cursor.column + 1);
+            if (rightChar == '}') {
+                var matching = session.$findOpeningBracket('}', {column: cursor.column + 1, row: cursor.row});
+                if (matching !== null) {
+                    return {
+                        text: '',
+                        selection: [1, 1]
+                    };
+                }
+            }
+        } else if (text == "\n") {
+            var cursor = editor.getCursorPosition();
+            var line = session.doc.getLine(cursor.row);
+            var rightChar = line.substring(cursor.column, cursor.column + 1);
+            if (rightChar == '}') {
+                var openBracePos = session.findMatchingBracket({row: cursor.row, column: cursor.column + 1});
+                if (!openBracePos)
+                     return null;
+
+                var indent = this.getNextLineIndent(state, line.substring(0, line.length - 1), session.getTabString());
+                var next_indent = this.$getIndent(session.doc.getLine(openBracePos.row));
+
+                return {
+                    text: '\n' + indent + '\n' + next_indent,
+                    selection: [1, indent.length, 1, indent.length]
+                };
+            }
+        }
+    });
+
+    this.add("braces", "deletion", function (state, action, editor, session, range) {
+        var selected = session.doc.getTextRange(range);
+        if (!range.isMultiLine() && selected == '{') {
+            var line = session.doc.getLine(range.start.row);
+            var rightChar = line.substring(range.end.column, range.end.column + 1);
+            if (rightChar == '}') {
+                range.end.column++;
+                return range;
+            }
+        }
+    });
+
+    this.add("parens", "insertion", function (state, action, editor, session, text) {
+        if (text == '(') {
+            var selection = editor.getSelectionRange();
+            var selected = session.doc.getTextRange(selection);
+            if (selected !== "") {
+                return {
+                    text: '(' + selected + ')',
+                    selection: false
+                };
+            } else {
+                return {
+                    text: '()',
+                    selection: [1, 1]
+                };
+            }
+        } else if (text == ')') {
+            var cursor = editor.getCursorPosition();
+            var line = session.doc.getLine(cursor.row);
+            var rightChar = line.substring(cursor.column, cursor.column + 1);
+            if (rightChar == ')') {
+                var matching = session.$findOpeningBracket(')', {column: cursor.column + 1, row: cursor.row});
+                if (matching !== null) {
+                    return {
+                        text: '',
+                        selection: [1, 1]
+                    };
+                }
+            }
+        }
+    });
+
+    this.add("parens", "deletion", function (state, action, editor, session, range) {
+        var selected = session.doc.getTextRange(range);
+        if (!range.isMultiLine() && selected == '(') {
+            var line = session.doc.getLine(range.start.row);
+            var rightChar = line.substring(range.start.column + 1, range.start.column + 2);
+            if (rightChar == ')') {
+                range.end.column++;
+                return range;
+            }
+        }
+    });
+
+    this.add("string_dquotes", "insertion", function (state, action, editor, session, text) {
+        if (text == '"' || text == "'") {
+            var quote = text;
+            var selection = editor.getSelectionRange();
+            var selected = session.doc.getTextRange(selection);
+            if (selected !== "") {
+                return {
+                    text: quote + selected + quote,
+                    selection: false
+                };
+            } else {
+                var cursor = editor.getCursorPosition();
+                var line = session.doc.getLine(cursor.row);
+                var leftChar = line.substring(cursor.column-1, cursor.column);
+
+                // We're escaped.
+                if (leftChar == '\\') {
+                    return null;
+                }
+
+                // Find what token we're inside.
+                var tokens = session.getTokens(selection.start.row, selection.start.row)[0].tokens;
+                var col = 0, token;
+                var quotepos = -1; // Track whether we're inside an open quote.
+
+                for (var x = 0; x < tokens.length; x++) {
+                    token = tokens[x];
+                    if (token.type == "string") {
+                      quotepos = -1;
+                    } else if (quotepos < 0) {
+                      quotepos = token.value.indexOf(quote);
+                    }
+                    if ((token.value.length + col) > selection.start.column) {
+                        break;
+                    }
+                    col += tokens[x].value.length;
+                }
+
+                // Try and be smart about when we auto insert.
+                if (!token || (quotepos < 0 && token.type !== "comment" && (token.type !== "string" || ((selection.start.column !== token.value.length+col-1) && token.value.lastIndexOf(quote) === token.value.length-1)))) {
+                    return {
+                        text: quote + quote,
+                        selection: [1,1]
+                    };
+                } else if (token && token.type === "string") {
+                    // Ignore input and move right one if we're typing over the closing quote.
+                    var rightChar = line.substring(cursor.column, cursor.column + 1);
+                    if (rightChar == quote) {
+                        return {
+                            text: '',
+                            selection: [1, 1]
+                        };
+                    }
+                }
+            }
+        }
+    });
+
+    this.add("string_dquotes", "deletion", function (state, action, editor, session, range) {
+        var selected = session.doc.getTextRange(range);
+        if (!range.isMultiLine() && (selected == '"' || selected == "'")) {
+            var line = session.doc.getLine(range.start.row);
+            var rightChar = line.substring(range.start.column + 1, range.start.column + 2);
+            if (rightChar == '"') {
+                range.end.column++;
+                return range;
+            }
+        }
+    });
+
+};
+
+oop.inherits(CstyleBehaviour, Behaviour);
+
+exports.CstyleBehaviour = CstyleBehaviour;
+});
\ No newline at end of file
diff --git a/apps/files_texteditor/js/aceeditor/mode-xquery.js b/apps/files_texteditor/js/aceeditor/mode-xquery.js
new file mode 100644
index 0000000000000000000000000000000000000000..cb6fb87cc6ae9031630f1795938c9bfcd67d4558
--- /dev/null
+++ b/apps/files_texteditor/js/aceeditor/mode-xquery.js
@@ -0,0 +1 @@
+define("ace/mode/xquery",["require","exports","module","ace/lib/oop","ace/mode/text","ace/tokenizer","ace/mode/xquery_highlight_rules","ace/mode/behaviour/xquery","ace/range"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("./text").Mode,f=a("../tokenizer").Tokenizer,g=a("./xquery_highlight_rules").XQueryHighlightRules,h=a("./behaviour/xquery").XQueryBehaviour,i=a("../range").Range,j=function(a){this.$tokenizer=new f((new g).getRules()),this.$behaviour=new h(a)};d.inherits(j,e),function(){this.getNextLineIndent=function(a,b,c){var d=this.$getIndent(b),e=b.match(/\s*(?:then|else|return|[{\(]|<\w+>)\s*$/);return e&&(d+=c),d},this.checkOutdent=function(a,b,c){return/^\s+$/.test(b)?/^\s*[\}\)]/.test(c):!1},this.autoOutdent=function(a,b,c){var d=b.getLine(c),e=d.match(/^(\s*[\}\)])/);if(!e)return 0;var f=e[1].length,g=b.findMatchingBracket({row:c,column:f});if(!g||g.row==c)return 0;var h=this.$getIndent(b.getLine(g.row));b.replace(new i(c,0,c,f-1),h)},this.$getIndent=function(a){var b=a.match(/^(\s+)/);return b?b[1]:""},this.toggleCommentLines=function(a,b,c,d){var e,f,g=!0,h=/^\s*\(:(.*):\)/;for(e=c;e<=d;e++)if(!h.test(b.getLine(e))){g=!1;break}var j=new i(0,0,0,0);for(e=c;e<=d;e++)f=b.getLine(e),j.start.row=e,j.end.row=e,j.end.column=f.length,b.replace(j,g?f.match(h)[1]:"(:"+f+":)")}}.call(j.prototype),b.Mode=j}),define("ace/mode/xquery_highlight_rules",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/mode/text_highlight_rules"],function(a,b,c){"use strict";var d=a("../lib/oop"),e=a("../lib/lang"),f=a("./text_highlight_rules").TextHighlightRules,g=function(){var a=e.arrayToMap("return|for|let|where|order|by|declare|function|variable|xquery|version|option|namespace|import|module|when|encoding|switch|default|try|catch|group|tumbling|sliding|window|start|end|at|only|using|stemming|while|external|if|then|else|as|and|or|typeswitch|case|ascending|descending|empty|in|count|updating|insert|delete|replace|value|node|attribute|text|element|into|of|with|contains".split("|"));this.$rules={start:[{token:"text",regex:"<\\!\\[CDATA\\[",next:"cdata"},{token:"xml_pe",regex:"<\\?.*?\\?>"},{token:"comment",regex:"<\\!--",next:"comment"},{token:"comment",regex:"\\(:",next:"comment"},{token:"text",regex:"<\\/?",next:"tag"},{token:"constant",regex:"[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"},{token:"variable",regex:"\\$[a-zA-Z_][a-zA-Z0-9_\\-:]*\\b"},{token:"string",regex:'".*?"'},{token:"string",regex:"'.*?'"},{token:"text",regex:"\\s+"},{token:"support.function",regex:"\\w[\\w+_\\-:]+(?=\\()"},{token:function(b){return a[b]?"keyword":"identifier"},regex:"[a-zA-Z_$][a-zA-Z0-9_$]*\\b"},{token:"keyword.operator",regex:"\\*|=|<|>|\\-|\\+|and|or|eq|ne|lt|gt"},{token:"lparen",regex:"[[({]"},{token:"rparen",regex:"[\\])}]"}],tag:[{token:"text",regex:">",next:"start"},{token:"meta.tag",regex:"[-_a-zA-Z0-9:]+"},{token:"text",regex:"\\s+"},{token:"string",regex:'".*?"'},{token:"string",regex:"'.*?'"}],cdata:[{token:"text",regex:"\\]\\]>",next:"start"},{token:"text",regex:"\\s+"},{token:"text",regex:"(?:[^\\]]|\\](?!\\]>))+"}],comment:[{token:"comment",regex:".*?-->",next:"start"},{token:"comment",regex:".*:\\)",next:"start"},{token:"comment",regex:".+"}]}};d.inherits(g,f),b.XQueryHighlightRules=g}),define("ace/mode/behaviour/xquery",["require","exports","module","ace/lib/oop","ace/mode/behaviour","ace/mode/behaviour/cstyle"],function(a,b,c){"use strict";var d=a("../../lib/oop"),e=a("../behaviour").Behaviour,f=a("./cstyle").CstyleBehaviour,g=function(a){this.inherit(f,["braces","parens","string_dquotes"]),this.parent=a,this.add("brackets","insertion",function(a,b,c,d,e){if(e=="\n"){var f=c.getCursorPosition(),g=d.doc.getLine(f.row),h=g.substring(f.column,f.column+2);if(h=="</"){var i=this.$getIndent(d.doc.getLine(f.row))+d.getTabString(),j=this.$getIndent(d.doc.getLine(f.row));return{text:"\n"+i+"\n"+j,selection:[1,i.length,1,i.length]}}}return!1}),this.add("slash","insertion",function(b,c,d,e,f){if(f=="/"){var g=d.getCursorPosition(),h=e.doc.getLine(g.row);if(g.column>0&&h.charAt(g.column-1)=="<"){h=h.substring(0,g.column)+"/"+h.substring(g.column);var i=e.doc.getAllLines();i[g.row]=h,a.exec("closeTag",i.join(e.doc.getNewLineCharacter()),g.row)}}return!1})};d.inherits(g,e),b.XQueryBehaviour=g}),define("ace/mode/behaviour/cstyle",["require","exports","module","ace/lib/oop","ace/mode/behaviour"],function(a,b,c){"use strict";var d=a("../../lib/oop"),e=a("../behaviour").Behaviour,f=function(){this.add("braces","insertion",function(a,b,c,d,e){if(e=="{"){var f=c.getSelectionRange(),g=d.doc.getTextRange(f);return g!==""?{text:"{"+g+"}",selection:!1}:{text:"{}",selection:[1,1]}}if(e=="}"){var h=c.getCursorPosition(),i=d.doc.getLine(h.row),j=i.substring(h.column,h.column+1);if(j=="}"){var k=d.$findOpeningBracket("}",{column:h.column+1,row:h.row});if(k!==null)return{text:"",selection:[1,1]}}}else if(e=="\n"){var h=c.getCursorPosition(),i=d.doc.getLine(h.row),j=i.substring(h.column,h.column+1);if(j=="}"){var l=d.findMatchingBracket({row:h.row,column:h.column+1});if(!l)return null;var m=this.getNextLineIndent(a,i.substring(0,i.length-1),d.getTabString()),n=this.$getIndent(d.doc.getLine(l.row));return{text:"\n"+m+"\n"+n,selection:[1,m.length,1,m.length]}}}}),this.add("braces","deletion",function(a,b,c,d,e){var f=d.doc.getTextRange(e);if(!e.isMultiLine()&&f=="{"){var g=d.doc.getLine(e.start.row),h=g.substring(e.end.column,e.end.column+1);if(h=="}")return e.end.column++,e}}),this.add("parens","insertion",function(a,b,c,d,e){if(e=="("){var f=c.getSelectionRange(),g=d.doc.getTextRange(f);return g!==""?{text:"("+g+")",selection:!1}:{text:"()",selection:[1,1]}}if(e==")"){var h=c.getCursorPosition(),i=d.doc.getLine(h.row),j=i.substring(h.column,h.column+1);if(j==")"){var k=d.$findOpeningBracket(")",{column:h.column+1,row:h.row});if(k!==null)return{text:"",selection:[1,1]}}}}),this.add("parens","deletion",function(a,b,c,d,e){var f=d.doc.getTextRange(e);if(!e.isMultiLine()&&f=="("){var g=d.doc.getLine(e.start.row),h=g.substring(e.start.column+1,e.start.column+2);if(h==")")return e.end.column++,e}}),this.add("string_dquotes","insertion",function(a,b,c,d,e){if(e=='"'||e=="'"){var f=e,g=c.getSelectionRange(),h=d.doc.getTextRange(g);if(h!=="")return{text:f+h+f,selection:!1};var i=c.getCursorPosition(),j=d.doc.getLine(i.row),k=j.substring(i.column-1,i.column);if(k=="\\")return null;var l=d.getTokens(g.start.row,g.start.row)[0].tokens,m=0,n,o=-1;for(var p=0;p<l.length;p++){n=l[p],n.type=="string"?o=-1:o<0&&(o=n.value.indexOf(f));if(n.value.length+m>g.start.column)break;m+=l[p].value.length}if(!n||o<0&&n.type!=="comment"&&(n.type!=="string"||g.start.column!==n.value.length+m-1&&n.value.lastIndexOf(f)===n.value.length-1))return{text:f+f,selection:[1,1]};if(n&&n.type==="string"){var q=j.substring(i.column,i.column+1);if(q==f)return{text:"",selection:[1,1]}}}}),this.add("string_dquotes","deletion",function(a,b,c,d,e){var f=d.doc.getTextRange(e);if(!e.isMultiLine()&&(f=='"'||f=="'")){var g=d.doc.getLine(e.start.row),h=g.substring(e.start.column+1,e.start.column+2);if(h=='"')return e.end.column++,e}})};d.inherits(f,e),b.CstyleBehaviour=f})
\ No newline at end of file
diff --git a/apps/files_texteditor/js/aceeditor/theme-clouds-uncompressed.js b/apps/files_texteditor/js/aceeditor/theme-clouds-uncompressed.js
old mode 100755
new mode 100644
index 0c0445151b54feacfcc3c2f1f72ef2b321fdb2f1..03048077b70645e9682516bfc90c0b377741fe33
--- a/apps/files_texteditor/js/aceeditor/theme-clouds-uncompressed.js
+++ b/apps/files_texteditor/js/aceeditor/theme-clouds-uncompressed.js
@@ -35,7 +35,7 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
-define('ace/theme/clouds', ['require', 'exports', 'module' ], function(require, exports, module) {
+define('ace/theme/clouds', ['require', 'exports', 'module' , 'ace/lib/dom'], function(require, exports, module) {
 
 exports.isDark = false;
 exports.cssClass = "ace-clouds";
@@ -68,14 +68,14 @@ exports.cssText = "\
 }\
 \
 .ace-clouds .ace_cursor {\
-  border-left: 2px solid #000000;\
+  border-left: 1px solid #000000;\
 }\
 \
 .ace-clouds .ace_cursor.ace_overwrite {\
   border-left: 0px;\
   border-bottom: 1px solid #000000;\
 }\
- \
+\
 .ace-clouds .ace_marker-layer .ace_selection {\
   background: #BDD5FC;\
 }\
@@ -96,12 +96,12 @@ exports.cssText = "\
 .ace-clouds .ace_marker-layer .ace_selected_word {\
   border: 1px solid #BDD5FC;\
 }\
-       \
+\
 .ace-clouds .ace_invisible {\
   color: #BFBFBF;\
 }\
 \
-.ace-clouds .ace_keyword {\
+.ace-clouds .ace_keyword, .ace-clouds .ace_meta {\
   color:#AF956F;\
 }\
 \
@@ -130,6 +130,10 @@ exports.cssText = "\
   color:#C52727;\
 }\
 \
+.ace-clouds .ace_storage {\
+  color:#C52727;\
+}\
+\
 .ace-clouds .ace_string {\
   color:#5D90CD;\
 }\
@@ -146,17 +150,6 @@ exports.cssText = "\
     text-decoration:underline;\
 }";
 
-var dom = require("../lib/dom");
-dom.importCssString(exports.cssText, exports.cssClass);
-
+    var dom = require("../lib/dom");
+    dom.importCssString(exports.cssText, exports.cssClass);
 });
-;
-            (function() {
-                window.require(["ace/ace"], function(a) {
-                    if (!window.ace)
-                        window.ace = {};
-                    for (var key in a) if (a.hasOwnProperty(key))
-                        ace[key] = a[key];
-                });
-            })();
-        
\ No newline at end of file
diff --git a/apps/files_texteditor/js/aceeditor/theme-clouds.js b/apps/files_texteditor/js/aceeditor/theme-clouds.js
index 78a1d5b5e5c68894329c021cfc37ece2c55c1b65..de651e6c5972f5bef859e528415f4a1d2e5158ff 100644
--- a/apps/files_texteditor/js/aceeditor/theme-clouds.js
+++ b/apps/files_texteditor/js/aceeditor/theme-clouds.js
@@ -1 +1 @@
-define("ace/theme/clouds",["require","exports","module"],function(a,b,c){b.isDark=!1,b.cssClass="ace-clouds",b.cssText=".ace-clouds .ace_editor {  border: 2px solid rgb(159, 159, 159);}.ace-clouds .ace_editor.ace_focus {  border: 2px solid #327fbd;}.ace-clouds .ace_gutter {  background: #e8e8e8;  color: #333;}.ace-clouds .ace_print_margin {  width: 1px;  background: #e8e8e8;}.ace-clouds .ace_scroller {  background-color: #FFFFFF;}.ace-clouds .ace_text-layer {  cursor: text;  color: #000000;}.ace-clouds .ace_cursor {  border-left: 2px solid #000000;}.ace-clouds .ace_cursor.ace_overwrite {  border-left: 0px;  border-bottom: 1px solid #000000;} .ace-clouds .ace_marker-layer .ace_selection {  background: #BDD5FC;}.ace-clouds .ace_marker-layer .ace_step {  background: rgb(198, 219, 174);}.ace-clouds .ace_marker-layer .ace_bracket {  margin: -1px 0 0 -1px;  border: 1px solid #BFBFBF;}.ace-clouds .ace_marker-layer .ace_active_line {  background: #FFFBD1;}.ace-clouds .ace_marker-layer .ace_selected_word {  border: 1px solid #BDD5FC;}       .ace-clouds .ace_invisible {  color: #BFBFBF;}.ace-clouds .ace_keyword {  color:#AF956F;}.ace-clouds .ace_keyword.ace_operator {  color:#484848;}.ace-clouds .ace_constant.ace_language {  color:#39946A;}.ace-clouds .ace_constant.ace_numeric {  color:#46A609;}.ace-clouds .ace_invalid {  background-color:#FF002A;}.ace-clouds .ace_fold {    background-color: #AF956F;    border-color: #000000;}.ace-clouds .ace_support.ace_function {  color:#C52727;}.ace-clouds .ace_string {  color:#5D90CD;}.ace-clouds .ace_comment {  color:#BCC8BA;}.ace-clouds .ace_entity.ace_other.ace_attribute-name {  color:#606060;}.ace-clouds .ace_markup.ace_underline {    text-decoration:underline;}";var d=a("../lib/dom");d.importCssString(b.cssText,b.cssClass)}),function(){window.require(["ace/ace"],function(a){window.ace||(window.ace={});for(var b in a)a.hasOwnProperty(b)&&(ace[b]=a[b])})}()
\ No newline at end of file
+define("ace/theme/clouds",["require","exports","module","ace/lib/dom"],function(a,b,c){b.isDark=!1,b.cssClass="ace-clouds",b.cssText=".ace-clouds .ace_editor {  border: 2px solid rgb(159, 159, 159);}.ace-clouds .ace_editor.ace_focus {  border: 2px solid #327fbd;}.ace-clouds .ace_gutter {  background: #e8e8e8;  color: #333;}.ace-clouds .ace_print_margin {  width: 1px;  background: #e8e8e8;}.ace-clouds .ace_scroller {  background-color: #FFFFFF;}.ace-clouds .ace_text-layer {  cursor: text;  color: #000000;}.ace-clouds .ace_cursor {  border-left: 1px solid #000000;}.ace-clouds .ace_cursor.ace_overwrite {  border-left: 0px;  border-bottom: 1px solid #000000;}.ace-clouds .ace_marker-layer .ace_selection {  background: #BDD5FC;}.ace-clouds .ace_marker-layer .ace_step {  background: rgb(198, 219, 174);}.ace-clouds .ace_marker-layer .ace_bracket {  margin: -1px 0 0 -1px;  border: 1px solid #BFBFBF;}.ace-clouds .ace_marker-layer .ace_active_line {  background: #FFFBD1;}.ace-clouds .ace_marker-layer .ace_selected_word {  border: 1px solid #BDD5FC;}.ace-clouds .ace_invisible {  color: #BFBFBF;}.ace-clouds .ace_keyword, .ace-clouds .ace_meta {  color:#AF956F;}.ace-clouds .ace_keyword.ace_operator {  color:#484848;}.ace-clouds .ace_constant.ace_language {  color:#39946A;}.ace-clouds .ace_constant.ace_numeric {  color:#46A609;}.ace-clouds .ace_invalid {  background-color:#FF002A;}.ace-clouds .ace_fold {    background-color: #AF956F;    border-color: #000000;}.ace-clouds .ace_support.ace_function {  color:#C52727;}.ace-clouds .ace_storage {  color:#C52727;}.ace-clouds .ace_string {  color:#5D90CD;}.ace-clouds .ace_comment {  color:#BCC8BA;}.ace-clouds .ace_entity.ace_other.ace_attribute-name {  color:#606060;}.ace-clouds .ace_markup.ace_underline {    text-decoration:underline;}";var d=a("../lib/dom");d.importCssString(b.cssText,b.cssClass)})
\ No newline at end of file
diff --git a/apps/files_texteditor/js/aceeditor/worker-coffee.js b/apps/files_texteditor/js/aceeditor/worker-coffee.js
index d47238ceb7d9a1ba6570196cd11076087e46f2d5..704ee4f3228d80571b76913558ed2d9768ba813c 100644
--- a/apps/files_texteditor/js/aceeditor/worker-coffee.js
+++ b/apps/files_texteditor/js/aceeditor/worker-coffee.js
@@ -198,7 +198,7 @@ define('ace/lib/regexp', ['require', 'exports', 'module' ], function(require, ex
     RegExp.prototype.exec = function (str) {
         var match = real.exec.apply(this, arguments),
             name, r2;
-        if (match) {
+        if ( typeof(str) == 'string' && match) {
             // Fix browsers whose `exec` methods don't consistently return `undefined` for
             // nonparticipating capturing groups
             if (!compliantExecNpcg && match.length > 1 && indexOf(match, "") > -1) {
@@ -263,7 +263,8 @@ define('ace/lib/regexp', ['require', 'exports', 'module' ], function(require, ex
         return -1;
     };
 
-});// vim: ts=4 sts=4 sw=4 expandtab
+});
+// vim: ts=4 sts=4 sw=4 expandtab
 // -- kriskowal Kris Kowal Copyright (C) 2009-2011 MIT License
 // -- tlrobinson Tom Robinson Copyright (C) 2009-2010 MIT License (Narwhal Project)
 // -- dantman Daniel Friesen Copyright (C) 2010 XXX TODO License or CLA
@@ -1538,10 +1539,10 @@ exports.implement = function(proto, mixin) {
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
- 
+
 define('ace/mode/coffee_worker', ['require', 'exports', 'module' , 'ace/lib/oop', 'ace/worker/mirror', 'ace/mode/coffee/coffee-script'], function(require, exports, module) {
 "use strict";
-    
+
 var oop = require("../lib/oop");
 var Mirror = require("../worker/mirror").Mirror;
 var coffee = require("../mode/coffee/coffee-script");
@@ -1557,29 +1558,29 @@ var Worker = exports.Worker = function(sender) {
 oop.inherits(Worker, Mirror);
 
 (function() {
-    
+
     this.onUpdate = function() {
         var value = this.doc.getValue();
-        
+
         try {
             coffee.parse(value);
         } catch(e) {
             var m = e.message.match(/Parse error on line (\d+): (.*)/);
             if (m) {
                 this.sender.emit("error", {
-                    row: parseInt(m[1]) - 1,
+                    row: parseInt(m[1], 10) - 1,
                     column: null,
                     text: m[2],
                     type: "error"
                 });
                 return;
             }
-            
+
             if (e instanceof SyntaxError) {
                 var m = e.message.match(/ on line (\d+)/);
-                if (m) {                    
+                if (m) {
                     this.sender.emit("error", {
-                        row: parseInt(m[1]) - 1,
+                        row: parseInt(m[1], 10) - 1,
                         column: null,
                         text: e.message.replace(m[0], ""),
                         type: "error"
@@ -1590,7 +1591,7 @@ oop.inherits(Worker, Mirror);
         }
         this.sender.emit("ok");
     };
-    
+
 }).call(Worker.prototype);
 
 });define('ace/worker/mirror', ['require', 'exports', 'module' , 'ace/document', 'ace/lib/lang'], function(require, exports, module) {
@@ -1810,11 +1811,12 @@ var Document = function(text) {
     };
 
     this.insert = function(position, text) {
-        if (text.length == 0)
+        if (!text || text.length === 0)
             return position;
 
         position = this.$clipPosition(position);
 
+        // only detect new lines if the document has no line break yet
         if (this.getLength() <= 1)
             this.$detectNewLine(text);
 
@@ -2094,7 +2096,7 @@ var Range = function(startRow, startColumn, endRow, endColumn) {
 };
 
 (function() {
-    this.isEequal = function(range) {
+    this.isEqual = function(range) {
         return this.start.row == range.start.row &&
             this.end.row == range.end.row &&
             this.start.column == range.start.column &&
@@ -2160,6 +2162,11 @@ var Range = function(startRow, startColumn, endRow, endColumn) {
         return this.comparePoint(range.start) == 0 && this.comparePoint(range.end) == 0;
     }
 
+    this.intersectsRange = function(range) {
+        var cmp = this.compareRange(range);
+        return (cmp == -1 || cmp == 0 || cmp == 1);
+    }
+
     this.isEnd = function(row, column) {
         return this.end.row == row && this.end.column == column;
     }
@@ -2319,6 +2326,21 @@ var Range = function(startRow, startColumn, endRow, endColumn) {
         return Range.fromPoints(start || this.start, end || this.end);
     };
 
+    this.fixOrientation = function() {
+        if (
+            this.start.row < this.end.row 
+            || (this.start.row == this.end.row && this.start.column < this.end.column)
+        ) {
+            return false;
+        }
+        
+        var temp = this.start;
+        this.end = this.start;
+        this.start = temp;
+        return true;
+    };
+
+
     this.isEmpty = function() {
         return (this.start.row == this.end.row && this.start.column == this.end.column);
     };
@@ -2766,7 +2788,7 @@ define('ace/mode/coffee/coffee-script', ['require', 'exports', 'module' , 'ace/m
     };
 });/**
  * Copyright (c) 2011 Jeremy Ashkenas
- *
+ * 
  * Permission is hereby granted, free of charge, to any person
  * obtaining a copy of this software and associated documentation
  * files (the "Software"), to deal in the Software without
@@ -2790,26 +2812,25 @@ define('ace/mode/coffee/coffee-script', ['require', 'exports', 'module' , 'ace/m
  */
 
 define('ace/mode/coffee/lexer', ['require', 'exports', 'module' , 'ace/mode/coffee/rewriter', 'ace/mode/coffee/helpers'], function(require, exports, module) {
-    
-  var ASSIGNED, BOOL, CALLABLE, CODE, COFFEE_ALIASES, COFFEE_ALIAS_MAP, COFFEE_KEYWORDS, COMMENT, COMPARE, COMPOUND_ASSIGN, HEREDOC, HEREDOC_ILLEGAL, HEREDOC_INDENT, HEREGEX, HEREGEX_OMIT, IDENTIFIER, INDEXABLE, JSTOKEN, JS_FORBIDDEN, JS_KEYWORDS, LINE_BREAK, LINE_CONTINUER, LOGIC, Lexer, MATH, MULTILINER, MULTI_DENT, NOT_REGEX, NOT_SPACED_REGEX, NO_NEWLINE, NUMBER, OPERATOR, REGEX, RELATION, RESERVED, Rewriter, SHIFT, SIMPLESTR, TRAILING_SPACES, UNARY, WHITESPACE, compact, count, key, last, starts, _ref;
-  var __indexOf = Array.prototype.indexOf || function(item) {
-    for (var i = 0, l = this.length; i < l; i++) {
-      if (this[i] === item) return i;
-    }
-    return -1;
-  };
-  Rewriter = require('./rewriter').Rewriter;
-  _ref = require('./helpers'), count = _ref.count, starts = _ref.starts, compact = _ref.compact, last = _ref.last;
+// Generated by CoffeeScript 1.2.1-pre
+
+  var BOOL, CALLABLE, CODE, COFFEE_ALIASES, COFFEE_ALIAS_MAP, COFFEE_KEYWORDS, COMMENT, COMPARE, COMPOUND_ASSIGN, HEREDOC, HEREDOC_ILLEGAL, HEREDOC_INDENT, HEREGEX, HEREGEX_OMIT, IDENTIFIER, INDEXABLE, INVERSES, JSTOKEN, JS_FORBIDDEN, JS_KEYWORDS, LINE_BREAK, LINE_CONTINUER, LOGIC, Lexer, MATH, MULTILINER, MULTI_DENT, NOT_REGEX, NOT_SPACED_REGEX, NUMBER, OPERATOR, REGEX, RELATION, RESERVED, Rewriter, SHIFT, SIMPLESTR, STRICT_PROSCRIBED, TRAILING_SPACES, UNARY, WHITESPACE, compact, count, key, last, starts, _ref, _ref1,
+    __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
+
+  _ref = require('./rewriter'), Rewriter = _ref.Rewriter, INVERSES = _ref.INVERSES;
+
+  _ref1 = require('./helpers'), count = _ref1.count, starts = _ref1.starts, compact = _ref1.compact, last = _ref1.last;
+
   exports.Lexer = Lexer = (function() {
+
+    Lexer.name = 'Lexer';
+
     function Lexer() {}
+
     Lexer.prototype.tokenize = function(code, opts) {
-      var i;
-      if (opts == null) {
-        opts = {};
-      }
-      if (WHITESPACE.test(code)) {
-        code = "\n" + code;
-      }
+      var i, tag;
+      if (opts == null) opts = {};
+      if (WHITESPACE.test(code)) code = "\n" + code;
       code = code.replace(/\r/g, '').replace(TRAILING_SPACES, '');
       this.code = code;
       this.line = opts.line || 0;
@@ -2817,22 +2838,21 @@ define('ace/mode/coffee/lexer', ['require', 'exports', 'module' , 'ace/mode/coff
       this.indebt = 0;
       this.outdebt = 0;
       this.indents = [];
+      this.ends = [];
       this.tokens = [];
       i = 0;
       while (this.chunk = code.slice(i)) {
         i += this.identifierToken() || this.commentToken() || this.whitespaceToken() || this.lineToken() || this.heredocToken() || this.stringToken() || this.numberToken() || this.regexToken() || this.jsToken() || this.literalToken();
       }
       this.closeIndentation();
-      if (opts.rewrite === false) {
-        return this.tokens;
-      }
+      if (tag = this.ends.pop()) this.error("missing " + tag);
+      if (opts.rewrite === false) return this.tokens;
       return (new Rewriter).rewrite(this.tokens);
     };
+
     Lexer.prototype.identifierToken = function() {
       var colon, forcedIdentifier, id, input, match, prev, tag, _ref2, _ref3;
-      if (!(match = IDENTIFIER.exec(this.chunk))) {
-        return 0;
-      }
+      if (!(match = IDENTIFIER.exec(this.chunk))) return 0;
       input = match[0], id = match[1], colon = match[2];
       if (id === 'own' && this.tag() === 'FOR') {
         this.token('OWN', id);
@@ -2840,7 +2860,7 @@ define('ace/mode/coffee/lexer', ['require', 'exports', 'module' , 'ace/mode/coff
       }
       forcedIdentifier = colon || (prev = last(this.tokens)) && (((_ref2 = prev[0]) === '.' || _ref2 === '?.' || _ref2 === '::') || !prev.spaced && prev[0] === '@');
       tag = 'IDENTIFIER';
-      if (__indexOf.call(JS_KEYWORDS, id) >= 0 || !forcedIdentifier && __indexOf.call(COFFEE_KEYWORDS, id) >= 0) {
+      if (!forcedIdentifier && (__indexOf.call(JS_KEYWORDS, id) >= 0 || __indexOf.call(COFFEE_KEYWORDS, id) >= 0)) {
         tag = id.toUpperCase();
         if (tag === 'WHEN' && (_ref3 = this.tag(), __indexOf.call(LINE_BREAK, _ref3) >= 0)) {
           tag = 'LEADING_WHEN';
@@ -2869,13 +2889,11 @@ define('ace/mode/coffee/lexer', ['require', 'exports', 'module' , 'ace/mode/coff
           id = new String(id);
           id.reserved = true;
         } else if (__indexOf.call(RESERVED, id) >= 0) {
-          this.identifierError(id);
+          this.error("reserved word \"" + id + "\"");
         }
       }
       if (!forcedIdentifier) {
-        if (__indexOf.call(COFFEE_ALIASES, id) >= 0) {
-          id = COFFEE_ALIAS_MAP[id];
-        }
+        if (__indexOf.call(COFFEE_ALIASES, id) >= 0) id = COFFEE_ALIAS_MAP[id];
         tag = (function() {
           switch (id) {
             case '!':
@@ -2893,7 +2911,6 @@ define('ace/mode/coffee/lexer', ['require', 'exports', 'module' , 'ace/mode/coff
               return 'BOOL';
             case 'break':
             case 'continue':
-            case 'debugger':
               return 'STATEMENT';
             default:
               return tag;
@@ -2901,33 +2918,43 @@ define('ace/mode/coffee/lexer', ['require', 'exports', 'module' , 'ace/mode/coff
         })();
       }
       this.token(tag, id);
-      if (colon) {
-        this.token(':', ':');
-      }
+      if (colon) this.token(':', ':');
       return input.length;
     };
+
     Lexer.prototype.numberToken = function() {
-      var match, number;
-      if (!(match = NUMBER.exec(this.chunk))) {
-        return 0;
-      }
+      var binaryLiteral, lexedLength, match, number, octalLiteral;
+      if (!(match = NUMBER.exec(this.chunk))) return 0;
       number = match[0];
+      if (/E/.test(number)) {
+        this.error("exponential notation '" + number + "' must be indicated with a lowercase 'e'");
+      } else if (/[BOX]/.test(number)) {
+        this.error("radix prefix '" + number + "' must be lowercase");
+      } else if (/^0[89]/.test(number)) {
+        this.error("decimal literal '" + number + "' must not be prefixed with '0'");
+      } else if (/^0[0-7]/.test(number)) {
+        this.error("octal literal '" + number + "' must be prefixed with '0o'");
+      }
+      lexedLength = number.length;
+      if (octalLiteral = /0o([0-7]+)/.exec(number)) {
+        number = (parseInt(octalLiteral[1], 8)).toString();
+      }
+      if (binaryLiteral = /0b([01]+)/.exec(number)) {
+        number = (parseInt(binaryLiteral[1], 2)).toString();
+      }
       this.token('NUMBER', number);
-      return number.length;
+      return lexedLength;
     };
+
     Lexer.prototype.stringToken = function() {
-      var match, string;
+      var match, octalEsc, string;
       switch (this.chunk.charAt(0)) {
         case "'":
-          if (!(match = SIMPLESTR.exec(this.chunk))) {
-            return 0;
-          }
+          if (!(match = SIMPLESTR.exec(this.chunk))) return 0;
           this.token('STRING', (string = match[0]).replace(MULTILINER, '\\\n'));
           break;
         case '"':
-          if (!(string = this.balancedString(this.chunk, '"'))) {
-            return 0;
-          }
+          if (!(string = this.balancedString(this.chunk, '"'))) return 0;
           if (0 < string.indexOf('#{', 1)) {
             this.interpolateString(string.slice(1, -1));
           } else {
@@ -2937,14 +2964,16 @@ define('ace/mode/coffee/lexer', ['require', 'exports', 'module' , 'ace/mode/coff
         default:
           return 0;
       }
+      if (octalEsc = /^(?:\\.|[^\\])*\\[0-7]/.test(string)) {
+        this.error("octal escape sequences " + string + " are not allowed");
+      }
       this.line += count(string, '\n');
       return string.length;
     };
+
     Lexer.prototype.heredocToken = function() {
       var doc, heredoc, match, quote;
-      if (!(match = HEREDOC.exec(this.chunk))) {
-        return 0;
-      }
+      if (!(match = HEREDOC.exec(this.chunk))) return 0;
       heredoc = match[0];
       quote = heredoc.charAt(0);
       doc = this.sanitizeHeredoc(match[2], {
@@ -2961,22 +2990,21 @@ define('ace/mode/coffee/lexer', ['require', 'exports', 'module' , 'ace/mode/coff
       this.line += count(heredoc, '\n');
       return heredoc.length;
     };
+
     Lexer.prototype.commentToken = function() {
       var comment, here, match;
-      if (!(match = this.chunk.match(COMMENT))) {
-        return 0;
-      }
+      if (!(match = this.chunk.match(COMMENT))) return 0;
       comment = match[0], here = match[1];
       if (here) {
         this.token('HERECOMMENT', this.sanitizeHeredoc(here, {
           herecomment: true,
           indent: Array(this.indent + 1).join(' ')
         }));
-        this.token('TERMINATOR', '\n');
       }
       this.line += count(comment, '\n');
       return comment.length;
     };
+
     Lexer.prototype.jsToken = function() {
       var match, script;
       if (!(this.chunk.charAt(0) === '`' && (match = JSTOKEN.exec(this.chunk)))) {
@@ -2985,31 +3013,37 @@ define('ace/mode/coffee/lexer', ['require', 'exports', 'module' , 'ace/mode/coff
       this.token('JS', (script = match[0]).slice(1, -1));
       return script.length;
     };
+
     Lexer.prototype.regexToken = function() {
-      var match, prev, regex, _ref2;
-      if (this.chunk.charAt(0) !== '/') {
-        return 0;
-      }
+      var flags, length, match, prev, regex, _ref2, _ref3;
+      if (this.chunk.charAt(0) !== '/') return 0;
       if (match = HEREGEX.exec(this.chunk)) {
-        this.line += count(match[0], '\n');        
-        return this.heregexToken(match);
+        length = this.heregexToken(match);
+        this.line += count(match[0], '\n');
+        return length;
       }
       prev = last(this.tokens);
       if (prev && (_ref2 = prev[0], __indexOf.call((prev.spaced ? NOT_REGEX : NOT_SPACED_REGEX), _ref2) >= 0)) {
         return 0;
       }
-      if (!(match = REGEX.exec(this.chunk))) {
-        return 0;
+      if (!(match = REGEX.exec(this.chunk))) return 0;
+      _ref3 = match, match = _ref3[0], regex = _ref3[1], flags = _ref3[2];
+      if (regex.slice(0, 2) === '/*') {
+        this.error('regular expressions cannot begin with `*`');
       }
-      regex = match[0];
-      this.token('REGEX', regex === '//' ? '/(?:)/' : regex);
-      return regex.length;
+      if (regex === '//') regex = '/(?:)/';
+      this.token('REGEX', "" + regex + flags);
+      return match.length;
     };
+
     Lexer.prototype.heregexToken = function(match) {
       var body, flags, heregex, re, tag, tokens, value, _i, _len, _ref2, _ref3, _ref4, _ref5;
       heregex = match[0], body = match[1], flags = match[2];
       if (0 > body.indexOf('#{')) {
         re = body.replace(HEREGEX_OMIT, '').replace(/\//g, '\\/');
+        if (re.match(/^\*/)) {
+          this.error('regular expressions cannot begin with `*`');
+        }
         this.token('REGEX', "/" + (re || '(?:)') + "/" + flags);
         return heregex.length;
       }
@@ -3024,9 +3058,7 @@ define('ace/mode/coffee/lexer', ['require', 'exports', 'module' , 'ace/mode/coff
         if (tag === 'TOKENS') {
           tokens.push.apply(tokens, value);
         } else {
-          if (!(value = value.replace(HEREGEX_OMIT, ''))) {
-            continue;
-          }
+          if (!(value = value.replace(HEREGEX_OMIT, ''))) continue;
           value = value.replace(/\\/g, '\\\\');
           tokens.push(['STRING', this.makeString(value, '"', true)]);
         }
@@ -3037,19 +3069,17 @@ define('ace/mode/coffee/lexer', ['require', 'exports', 'module' , 'ace/mode/coff
         this.tokens.push(['STRING', '""'], ['+', '+']);
       }
       (_ref5 = this.tokens).push.apply(_ref5, tokens);
-      if (flags) {
-        this.tokens.push([',', ','], ['STRING', '"' + flags + '"']);
-      }
+      if (flags) this.tokens.push([',', ','], ['STRING', '"' + flags + '"']);
       this.token(')', ')');
       return heregex.length;
     };
+
     Lexer.prototype.lineToken = function() {
       var diff, indent, match, noNewlines, prev, size;
-      if (!(match = MULTI_DENT.exec(this.chunk))) {
-        return 0;
-      }
+      if (!(match = MULTI_DENT.exec(this.chunk))) return 0;
       indent = match[0];
       this.line += count(indent, '\n');
+      this.seenFor = false;
       prev = last(this.tokens, 1);
       size = indent.length - 1 - indent.lastIndexOf('\n');
       noNewlines = this.unfinished();
@@ -3070,6 +3100,7 @@ define('ace/mode/coffee/lexer', ['require', 'exports', 'module' , 'ace/mode/coff
         diff = size - this.indent + this.outdebt;
         this.token('INDENT', diff);
         this.indents.push(diff);
+        this.ends.push('OUTDENT');
         this.outdebt = this.indebt = 0;
       } else {
         this.indebt = 0;
@@ -3078,7 +3109,8 @@ define('ace/mode/coffee/lexer', ['require', 'exports', 'module' , 'ace/mode/coff
       this.indent = size;
       return indent.length;
     };
-    Lexer.prototype.outdentToken = function(moveOut, noNewlines, close) {
+
+    Lexer.prototype.outdentToken = function(moveOut, noNewlines) {
       var dent, len;
       while (moveOut > 0) {
         len = this.indents.length - 1;
@@ -3094,51 +3126,52 @@ define('ace/mode/coffee/lexer', ['require', 'exports', 'module' , 'ace/mode/coff
           dent = this.indents.pop() - this.outdebt;
           moveOut -= dent;
           this.outdebt = 0;
+          this.pair('OUTDENT');
           this.token('OUTDENT', dent);
         }
       }
-      if (dent) {
-        this.outdebt -= moveOut;
+      if (dent) this.outdebt -= moveOut;
+      while (this.value() === ';') {
+        this.tokens.pop();
       }
       if (!(this.tag() === 'TERMINATOR' || noNewlines)) {
         this.token('TERMINATOR', '\n');
       }
       return this;
     };
+
     Lexer.prototype.whitespaceToken = function() {
       var match, nline, prev;
       if (!((match = WHITESPACE.exec(this.chunk)) || (nline = this.chunk.charAt(0) === '\n'))) {
         return 0;
       }
       prev = last(this.tokens);
-      if (prev) {
-        prev[match ? 'spaced' : 'newLine'] = true;
-      }
+      if (prev) prev[match ? 'spaced' : 'newLine'] = true;
       if (match) {
         return match[0].length;
       } else {
         return 0;
       }
     };
+
     Lexer.prototype.newlineToken = function() {
-      if (this.tag() !== 'TERMINATOR') {
-        this.token('TERMINATOR', '\n');
+      while (this.value() === ';') {
+        this.tokens.pop();
       }
+      if (this.tag() !== 'TERMINATOR') this.token('TERMINATOR', '\n');
       return this;
     };
+
     Lexer.prototype.suppressNewlines = function() {
-      if (this.value() === '\\') {
-        this.tokens.pop();
-      }
+      if (this.value() === '\\') this.tokens.pop();
       return this;
     };
+
     Lexer.prototype.literalToken = function() {
       var match, prev, tag, value, _ref2, _ref3, _ref4, _ref5;
       if (match = OPERATOR.exec(this.chunk)) {
         value = match[0];
-        if (CODE.test(value)) {
-          this.tagParameters();
-        }
+        if (CODE.test(value)) this.tagParameters();
       } else {
         value = this.chunk.charAt(0);
       }
@@ -3146,7 +3179,7 @@ define('ace/mode/coffee/lexer', ['require', 'exports', 'module' , 'ace/mode/coff
       prev = last(this.tokens);
       if (value === '=' && prev) {
         if (!prev[1].reserved && (_ref2 = prev[1], __indexOf.call(JS_FORBIDDEN, _ref2) >= 0)) {
-          this.assignmentError();
+          this.error("reserved word \"" + (this.value()) + "\" can't be assigned");
         }
         if ((_ref3 = prev[1]) === '||' || _ref3 === '&&') {
           prev[0] = 'COMPOUND_ASSIGN';
@@ -3155,6 +3188,7 @@ define('ace/mode/coffee/lexer', ['require', 'exports', 'module' , 'ace/mode/coff
         }
       }
       if (value === ';') {
+        this.seenFor = false;
         tag = 'TERMINATOR';
       } else if (__indexOf.call(MATH, value) >= 0) {
         tag = 'MATH';
@@ -3170,34 +3204,39 @@ define('ace/mode/coffee/lexer', ['require', 'exports', 'module' , 'ace/mode/coff
         tag = 'LOGIC';
       } else if (prev && !prev.spaced) {
         if (value === '(' && (_ref4 = prev[0], __indexOf.call(CALLABLE, _ref4) >= 0)) {
-          if (prev[0] === '?') {
-            prev[0] = 'FUNC_EXIST';
-          }
+          if (prev[0] === '?') prev[0] = 'FUNC_EXIST';
           tag = 'CALL_START';
         } else if (value === '[' && (_ref5 = prev[0], __indexOf.call(INDEXABLE, _ref5) >= 0)) {
           tag = 'INDEX_START';
           switch (prev[0]) {
             case '?':
               prev[0] = 'INDEX_SOAK';
-              break;
-            case '::':
-              prev[0] = 'INDEX_PROTO';
           }
         }
       }
+      switch (value) {
+        case '(':
+        case '{':
+        case '[':
+          this.ends.push(INVERSES[value]);
+          break;
+        case ')':
+        case '}':
+        case ']':
+          this.pair(value);
+      }
       this.token(tag, value);
       return value.length;
     };
+
     Lexer.prototype.sanitizeHeredoc = function(doc, options) {
       var attempt, herecomment, indent, match, _ref2;
       indent = options.indent, herecomment = options.herecomment;
       if (herecomment) {
         if (HEREDOC_ILLEGAL.test(doc)) {
-          throw new Error("block comment cannot contain \"*/\", starting on line " + (this.line + 1));
-        }
-        if (doc.indexOf('\n') <= 0) {
-          return doc;
+          this.error("block comment cannot contain \"*/\", starting");
         }
+        if (doc.indexOf('\n') <= 0) return doc;
       } else {
         while (match = HEREDOC_INDENT.exec(doc)) {
           attempt = match[1];
@@ -3206,19 +3245,14 @@ define('ace/mode/coffee/lexer', ['require', 'exports', 'module' , 'ace/mode/coff
           }
         }
       }
-      if (indent) {
-        doc = doc.replace(RegExp("\\n" + indent, "g"), '\n');
-      }
-      if (!herecomment) {
-        doc = doc.replace(/^\n/, '');
-      }
+      if (indent) doc = doc.replace(RegExp("\\n" + indent, "g"), '\n');
+      if (!herecomment) doc = doc.replace(/^\n/, '');
       return doc;
     };
+
     Lexer.prototype.tagParameters = function() {
       var i, stack, tok, tokens;
-      if (this.tag() !== ')') {
-        return this;
-      }
+      if (this.tag() !== ')') return this;
       stack = [];
       tokens = this.tokens;
       i = tokens.length;
@@ -3235,38 +3269,41 @@ define('ace/mode/coffee/lexer', ['require', 'exports', 'module' , 'ace/mode/coff
             } else if (tok[0] === '(') {
               tok[0] = 'PARAM_START';
               return this;
+            } else {
+              return this;
             }
         }
       }
       return this;
     };
+
     Lexer.prototype.closeIndentation = function() {
       return this.outdentToken(this.indent);
     };
-    Lexer.prototype.identifierError = function(word) {
-      throw SyntaxError("Reserved word \"" + word + "\" on line " + (this.line + 1));
-    };
-    Lexer.prototype.assignmentError = function() {
-      throw SyntaxError("Reserved word \"" + (this.value()) + "\" on line " + (this.line + 1) + " can't be assigned");
-    };
+
     Lexer.prototype.balancedString = function(str, end) {
-      var i, letter, prev, stack, _ref2;
+      var continueCount, i, letter, match, prev, stack, _i, _ref2;
+      continueCount = 0;
       stack = [end];
-      for (i = 1, _ref2 = str.length; 1 <= _ref2 ? i < _ref2 : i > _ref2; 1 <= _ref2 ? i++ : i--) {
+      for (i = _i = 1, _ref2 = str.length; 1 <= _ref2 ? _i < _ref2 : _i > _ref2; i = 1 <= _ref2 ? ++_i : --_i) {
+        if (continueCount) {
+          --continueCount;
+          continue;
+        }
         switch (letter = str.charAt(i)) {
           case '\\':
-            i++;
+            ++continueCount;
             continue;
           case end:
             stack.pop();
-            if (!stack.length) {
-              return str.slice(0, i + 1);
-            }
+            if (!stack.length) return str.slice(0, i + 1 || 9e9);
             end = stack[stack.length - 1];
             continue;
         }
         if (end === '}' && (letter === '"' || letter === "'")) {
           stack.push(end = letter);
+        } else if (end === '}' && letter === '/' && (match = HEREGEX.exec(str.slice(i)) || REGEX.exec(str.slice(i)))) {
+          continueCount += match[0].length - 1;
         } else if (end === '}' && letter === '{') {
           stack.push(end = '}');
         } else if (end === '"' && prev === '#' && letter === '{') {
@@ -3274,13 +3311,12 @@ define('ace/mode/coffee/lexer', ['require', 'exports', 'module' , 'ace/mode/coff
         }
         prev = letter;
       }
-      throw new Error("missing " + (stack.pop()) + ", starting on line " + (this.line + 1));
+      return this.error("missing " + (stack.pop()) + ", starting");
     };
+
     Lexer.prototype.interpolateString = function(str, options) {
-      var expr, heredoc, i, inner, interpolated, len, letter, nested, pi, regex, tag, tokens, value, _len, _ref2, _ref3, _ref4;
-      if (options == null) {
-        options = {};
-      }
+      var expr, heredoc, i, inner, interpolated, len, letter, nested, pi, regex, tag, tokens, value, _i, _len, _ref2, _ref3, _ref4;
+      if (options == null) options = {};
       heredoc = options.heredoc, regex = options.regex;
       tokens = [];
       pi = 0;
@@ -3293,9 +3329,7 @@ define('ace/mode/coffee/lexer', ['require', 'exports', 'module' , 'ace/mode/coff
         if (!(letter === '#' && str.charAt(i + 1) === '{' && (expr = this.balancedString(str.slice(i + 1), '}')))) {
           continue;
         }
-        if (pi < i) {
-          tokens.push(['NEOSTRING', str.slice(pi, i)]);
-        }
+        if (pi < i) tokens.push(['NEOSTRING', str.slice(pi, i)]);
         inner = expr.slice(1, -1);
         if (inner.length) {
           nested = new Lexer().tokenize(inner, {
@@ -3308,8 +3342,8 @@ define('ace/mode/coffee/lexer', ['require', 'exports', 'module' , 'ace/mode/coff
           }
           if (len = nested.length) {
             if (len > 1) {
-              nested.unshift(['(', '(']);
-              nested.push([')', ')']);
+              nested.unshift(['(', '(', this.line]);
+              nested.push([')', ')', this.line]);
             }
             tokens.push(['TOKENS', nested]);
           }
@@ -3317,59 +3351,60 @@ define('ace/mode/coffee/lexer', ['require', 'exports', 'module' , 'ace/mode/coff
         i += expr.length;
         pi = i + 1;
       }
-      if ((i > pi && pi < str.length)) {
-        tokens.push(['NEOSTRING', str.slice(pi)]);
-      }
-      if (regex) {
-        return tokens;
-      }
-      if (!tokens.length) {
-        return this.token('STRING', '""');
-      }
-      if (tokens[0][0] !== 'NEOSTRING') {
-        tokens.unshift(['', '']);
-      }
-      if (interpolated = tokens.length > 1) {
-        this.token('(', '(');
-      }
-      for (i = 0, _len = tokens.length; i < _len; i++) {
+      if ((i > pi && pi < str.length)) tokens.push(['NEOSTRING', str.slice(pi)]);
+      if (regex) return tokens;
+      if (!tokens.length) return this.token('STRING', '""');
+      if (tokens[0][0] !== 'NEOSTRING') tokens.unshift(['', '']);
+      if (interpolated = tokens.length > 1) this.token('(', '(');
+      for (i = _i = 0, _len = tokens.length; _i < _len; i = ++_i) {
         _ref3 = tokens[i], tag = _ref3[0], value = _ref3[1];
-        if (i) {
-          this.token('+', '+');
-        }
+        if (i) this.token('+', '+');
         if (tag === 'TOKENS') {
           (_ref4 = this.tokens).push.apply(_ref4, value);
         } else {
           this.token('STRING', this.makeString(value, '"', heredoc));
         }
       }
-      if (interpolated) {
-        this.token(')', ')');
-      }
+      if (interpolated) this.token(')', ')');
       return tokens;
     };
+
+    Lexer.prototype.pair = function(tag) {
+      var size, wanted;
+      if (tag !== (wanted = last(this.ends))) {
+        if ('OUTDENT' !== wanted) this.error("unmatched " + tag);
+        this.indent -= size = last(this.indents);
+        this.outdentToken(size, true);
+        return this.pair(tag);
+      }
+      return this.ends.pop();
+    };
+
     Lexer.prototype.token = function(tag, value) {
       return this.tokens.push([tag, value, this.line]);
     };
+
     Lexer.prototype.tag = function(index, tag) {
       var tok;
       return (tok = last(this.tokens, index)) && (tag ? tok[0] = tag : tok[0]);
     };
+
     Lexer.prototype.value = function(index, val) {
       var tok;
       return (tok = last(this.tokens, index)) && (val ? tok[1] = val : tok[1]);
     };
+
     Lexer.prototype.unfinished = function() {
-      var prev, value;
-      return LINE_CONTINUER.test(this.chunk) || (prev = last(this.tokens, 1)) && prev[0] !== '.' && (value = this.value()) && !value.reserved && NO_NEWLINE.test(value) && !CODE.test(value) && !ASSIGNED.test(this.chunk);
+      var _ref2;
+      return LINE_CONTINUER.test(this.chunk) || ((_ref2 = this.tag()) === '\\' || _ref2 === '.' || _ref2 === '?.' || _ref2 === 'UNARY' || _ref2 === 'MATH' || _ref2 === '+' || _ref2 === '-' || _ref2 === 'SHIFT' || _ref2 === 'RELATION' || _ref2 === 'COMPARE' || _ref2 === 'LOGIC' || _ref2 === 'THROW' || _ref2 === 'EXTENDS');
     };
+
     Lexer.prototype.escapeLines = function(str, heredoc) {
       return str.replace(MULTILINER, heredoc ? '\\n' : '');
     };
+
     Lexer.prototype.makeString = function(body, quote, heredoc) {
-      if (!body) {
-        return quote + quote;
-      }
+      if (!body) return quote + quote;
       body = body.replace(/\\([\s\S])/g, function(match, contents) {
         if (contents === '\n' || contents === quote) {
           return contents;
@@ -3380,10 +3415,19 @@ define('ace/mode/coffee/lexer', ['require', 'exports', 'module' , 'ace/mode/coff
       body = body.replace(RegExp("" + quote, "g"), '\\$&');
       return quote + this.escapeLines(body, heredoc) + quote;
     };
+
+    Lexer.prototype.error = function(message) {
+      throw SyntaxError("" + message + " on line " + (this.line + 1));
+    };
+
     return Lexer;
+
   })();
+
   JS_KEYWORDS = ['true', 'false', 'null', 'this', 'new', 'delete', 'typeof', 'in', 'instanceof', 'return', 'throw', 'break', 'continue', 'debugger', 'if', 'else', 'switch', 'for', 'while', 'do', 'try', 'catch', 'finally', 'class', 'extends', 'super'];
+
   COFFEE_KEYWORDS = ['undefined', 'then', 'unless', 'until', 'loop', 'of', 'by', 'when'];
+
   COFFEE_ALIAS_MAP = {
     and: '&&',
     or: '||',
@@ -3395,6 +3439,7 @@ define('ace/mode/coffee/lexer', ['require', 'exports', 'module' , 'ace/mode/coff
     on: 'true',
     off: 'false'
   };
+
   COFFEE_ALIASES = (function() {
     var _results;
     _results = [];
@@ -3403,47 +3448,85 @@ define('ace/mode/coffee/lexer', ['require', 'exports', 'module' , 'ace/mode/coff
     }
     return _results;
   })();
+
   COFFEE_KEYWORDS = COFFEE_KEYWORDS.concat(COFFEE_ALIASES);
-  RESERVED = ['case', 'default', 'function', 'var', 'void', 'with', 'const', 'let', 'enum', 'export', 'import', 'native', '__hasProp', '__extends', '__slice', '__bind', '__indexOf'];
-  JS_FORBIDDEN = JS_KEYWORDS.concat(RESERVED);
-  exports.RESERVED = RESERVED.concat(JS_KEYWORDS).concat(COFFEE_KEYWORDS);
+
+  RESERVED = ['case', 'default', 'function', 'var', 'void', 'with', 'const', 'let', 'enum', 'export', 'import', 'native', '__hasProp', '__extends', '__slice', '__bind', '__indexOf', 'implements', 'interface', 'let', 'package', 'private', 'protected', 'public', 'static', 'yield'];
+
+  STRICT_PROSCRIBED = ['arguments', 'eval'];
+
+  JS_FORBIDDEN = JS_KEYWORDS.concat(RESERVED).concat(STRICT_PROSCRIBED);
+
+  exports.RESERVED = RESERVED.concat(JS_KEYWORDS).concat(COFFEE_KEYWORDS).concat(STRICT_PROSCRIBED);
+
+  exports.STRICT_PROSCRIBED = STRICT_PROSCRIBED;
+
   IDENTIFIER = /^([$A-Za-z_\x7f-\uffff][$\w\x7f-\uffff]*)([^\n\S]*:(?!:))?/;
-  NUMBER = /^0x[\da-f]+|^(?:\d+(\.\d+)?|\.\d+)(?:e[+-]?\d+)?/i;
+
+  NUMBER = /^0b[01]+|^0o[0-7]+|^0x[\da-f]+|^\d*\.?\d+(?:e[+-]?\d+)?/i;
+
   HEREDOC = /^("""|''')([\s\S]*?)(?:\n[^\n\S]*)?\1/;
+
   OPERATOR = /^(?:[-=]>|[-+*\/%<>&|^!?=]=|>>>=?|([-+:])\1|([&|<>])\2=?|\?\.|\.{2,3})/;
+
   WHITESPACE = /^[^\n\S]+/;
+
   COMMENT = /^###([^#][\s\S]*?)(?:###[^\n\S]*|(?:###)?$)|^(?:\s*#(?!##[^#]).*)+/;
+
   CODE = /^[-=]>/;
+
   MULTI_DENT = /^(?:\n[^\n\S]*)+/;
+
   SIMPLESTR = /^'[^\\']*(?:\\.[^\\']*)*'/;
+
   JSTOKEN = /^`[^\\`]*(?:\\.[^\\`]*)*`/;
-  REGEX = /^\/(?![\s=])[^[\/\n\\]*(?:(?:\\[\s\S]|\[[^\]\n\\]*(?:\\[\s\S][^\]\n\\]*)*])[^[\/\n\\]*)*\/[imgy]{0,4}(?!\w)/;
+
+  REGEX = /^(\/(?![\s=])[^[\/\n\\]*(?:(?:\\[\s\S]|\[[^\]\n\\]*(?:\\[\s\S][^\]\n\\]*)*])[^[\/\n\\]*)*\/)([imgy]{0,4})(?!\w)/;
+
   HEREGEX = /^\/{3}([\s\S]+?)\/{3}([imgy]{0,4})(?!\w)/;
+
   HEREGEX_OMIT = /\s+(?:#.*)?/g;
+
   MULTILINER = /\n/g;
+
   HEREDOC_INDENT = /\n+([^\n\S]*)/g;
+
   HEREDOC_ILLEGAL = /\*\//;
-  ASSIGNED = /^\s*@?([$A-Za-z_][$\w\x7f-\uffff]*|['"].*['"])[^\n\S]*?[:=][^:=>]/;
+
   LINE_CONTINUER = /^\s*(?:,|\??\.(?![.\d])|::)/;
+
   TRAILING_SPACES = /\s+$/;
-  NO_NEWLINE = /^(?:[-+*&|\/%=<>!.\\][<>=&|]*|and|or|is(?:nt)?|n(?:ot|ew)|delete|typeof|instanceof)$/;
+
   COMPOUND_ASSIGN = ['-=', '+=', '/=', '*=', '%=', '||=', '&&=', '?=', '<<=', '>>=', '>>>=', '&=', '^=', '|='];
+
   UNARY = ['!', '~', 'NEW', 'TYPEOF', 'DELETE', 'DO'];
+
   LOGIC = ['&&', '||', '&', '|', '^'];
+
   SHIFT = ['<<', '>>', '>>>'];
+
   COMPARE = ['==', '!=', '<', '>', '<=', '>='];
+
   MATH = ['*', '/', '%'];
+
   RELATION = ['IN', 'OF', 'INSTANCEOF'];
+
   BOOL = ['TRUE', 'FALSE', 'NULL', 'UNDEFINED'];
+
   NOT_REGEX = ['NUMBER', 'REGEX', 'BOOL', '++', '--', ']'];
+
   NOT_SPACED_REGEX = NOT_REGEX.concat(')', '}', 'THIS', 'IDENTIFIER', 'STRING');
+
   CALLABLE = ['IDENTIFIER', 'STRING', 'REGEX', ')', ']', '}', '?', '::', '@', 'THIS', 'SUPER'];
+
   INDEXABLE = CALLABLE.concat('NUMBER', 'BOOL');
+
   LINE_BREAK = ['INDENT', 'OUTDENT', 'TERMINATOR'];
-});
-/**
+
+
+});/**
  * Copyright (c) 2011 Jeremy Ashkenas
- *
+ * 
  * Permission is hereby granted, free of charge, to any person
  * obtaining a copy of this software and associated documentation
  * files (the "Software"), to deal in the Software without
@@ -3467,16 +3550,18 @@ define('ace/mode/coffee/lexer', ['require', 'exports', 'module' , 'ace/mode/coff
  */
 
 define('ace/mode/coffee/rewriter', ['require', 'exports', 'module' ], function(require, exports, module) {
-    
-  var BALANCED_PAIRS, EXPRESSION_CLOSE, EXPRESSION_END, EXPRESSION_START, IMPLICIT_BLOCK, IMPLICIT_CALL, IMPLICIT_END, IMPLICIT_FUNC, IMPLICIT_UNSPACED_CALL, INVERSES, LINEBREAKS, SINGLE_CLOSERS, SINGLE_LINERS, left, rite, _i, _len, _ref;
-  var __indexOf = Array.prototype.indexOf || function(item) {
-    for (var i = 0, l = this.length; i < l; i++) {
-      if (this[i] === item) return i;
-    }
-    return -1;
-  }, __slice = Array.prototype.slice;
+// Generated by CoffeeScript 1.2.1-pre
+
+  var BALANCED_PAIRS, EXPRESSION_CLOSE, EXPRESSION_END, EXPRESSION_START, IMPLICIT_BLOCK, IMPLICIT_CALL, IMPLICIT_END, IMPLICIT_FUNC, IMPLICIT_UNSPACED_CALL, INVERSES, LINEBREAKS, SINGLE_CLOSERS, SINGLE_LINERS, left, rite, _i, _len, _ref,
+    __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; },
+    __slice = [].slice;
+
   exports.Rewriter = (function() {
+
+    Rewriter.name = 'Rewriter';
+
     function Rewriter() {}
+
     Rewriter.prototype.rewrite = function(tokens) {
       this.tokens = tokens;
       this.removeLeadingNewlines();
@@ -3487,10 +3572,9 @@ define('ace/mode/coffee/rewriter', ['require', 'exports', 'module' ], function(r
       this.tagPostfixConditionals();
       this.addImplicitBraces();
       this.addImplicitParentheses();
-      this.ensureBalance(BALANCED_PAIRS);
-      this.rewriteClosingParens();
       return this.tokens;
     };
+
     Rewriter.prototype.scanTokens = function(block) {
       var i, token, tokens;
       tokens = this.tokens;
@@ -3500,39 +3584,36 @@ define('ace/mode/coffee/rewriter', ['require', 'exports', 'module' ], function(r
       }
       return true;
     };
+
     Rewriter.prototype.detectEnd = function(i, condition, action) {
-      var levels, token, tokens, _ref, _ref2;
+      var levels, token, tokens, _ref, _ref1;
       tokens = this.tokens;
       levels = 0;
       while (token = tokens[i]) {
         if (levels === 0 && condition.call(this, token, i)) {
           return action.call(this, token, i);
         }
-        if (!token || levels < 0) {
-          return action.call(this, token, i - 1);
-        }
+        if (!token || levels < 0) return action.call(this, token, i - 1);
         if (_ref = token[0], __indexOf.call(EXPRESSION_START, _ref) >= 0) {
           levels += 1;
-        } else if (_ref2 = token[0], __indexOf.call(EXPRESSION_END, _ref2) >= 0) {
+        } else if (_ref1 = token[0], __indexOf.call(EXPRESSION_END, _ref1) >= 0) {
           levels -= 1;
         }
         i += 1;
       }
       return i - 1;
     };
+
     Rewriter.prototype.removeLeadingNewlines = function() {
-      var i, tag, _len, _ref;
+      var i, tag, _i, _len, _ref;
       _ref = this.tokens;
-      for (i = 0, _len = _ref.length; i < _len; i++) {
+      for (i = _i = 0, _len = _ref.length; _i < _len; i = ++_i) {
         tag = _ref[i][0];
-        if (tag !== 'TERMINATOR') {
-          break;
-        }
-      }
-      if (i) {
-        return this.tokens.splice(0, i);
+        if (tag !== 'TERMINATOR') break;
       }
+      if (i) return this.tokens.splice(0, i);
     };
+
     Rewriter.prototype.removeMidExpressionNewlines = function() {
       return this.scanTokens(function(token, i, tokens) {
         var _ref;
@@ -3543,6 +3624,7 @@ define('ace/mode/coffee/rewriter', ['require', 'exports', 'module' ], function(r
         return 0;
       });
     };
+
     Rewriter.prototype.closeOpenCalls = function() {
       var action, condition;
       condition = function(token, i) {
@@ -3553,12 +3635,11 @@ define('ace/mode/coffee/rewriter', ['require', 'exports', 'module' ], function(r
         return this.tokens[token[0] === 'OUTDENT' ? i - 1 : i][0] = 'CALL_END';
       };
       return this.scanTokens(function(token, i) {
-        if (token[0] === 'CALL_START') {
-          this.detectEnd(i + 1, condition, action);
-        }
+        if (token[0] === 'CALL_START') this.detectEnd(i + 1, condition, action);
         return 1;
       });
     };
+
     Rewriter.prototype.closeOpenIndexes = function() {
       var action, condition;
       condition = function(token, i) {
@@ -3569,34 +3650,33 @@ define('ace/mode/coffee/rewriter', ['require', 'exports', 'module' ], function(r
         return token[0] = 'INDEX_END';
       };
       return this.scanTokens(function(token, i) {
-        if (token[0] === 'INDEX_START') {
-          this.detectEnd(i + 1, condition, action);
-        }
+        if (token[0] === 'INDEX_START') this.detectEnd(i + 1, condition, action);
         return 1;
       });
     };
+
     Rewriter.prototype.addImplicitBraces = function() {
-      var action, condition, stack, start, startIndent;
+      var action, condition, sameLine, stack, start, startIndent, startsLine;
       stack = [];
       start = null;
+      startsLine = null;
+      sameLine = true;
       startIndent = 0;
       condition = function(token, i) {
-        var one, tag, three, two, _ref, _ref2;
-        _ref = this.tokens.slice(i + 1, (i + 3 + 1) || 9e9), one = _ref[0], two = _ref[1], three = _ref[2];
-        if ('HERECOMMENT' === (one != null ? one[0] : void 0)) {
-          return false;
-        }
+        var one, tag, three, two, _ref, _ref1;
+        _ref = this.tokens.slice(i + 1, (i + 3) + 1 || 9e9), one = _ref[0], two = _ref[1], three = _ref[2];
+        if ('HERECOMMENT' === (one != null ? one[0] : void 0)) return false;
         tag = token[0];
-        return ((tag === 'TERMINATOR' || tag === 'OUTDENT') && !((two != null ? two[0] : void 0) === ':' || (one != null ? one[0] : void 0) === '@' && (three != null ? three[0] : void 0) === ':')) || (tag === ',' && one && ((_ref2 = one[0]) !== 'IDENTIFIER' && _ref2 !== 'NUMBER' && _ref2 !== 'STRING' && _ref2 !== '@' && _ref2 !== 'TERMINATOR' && _ref2 !== 'OUTDENT'));
+        if (__indexOf.call(LINEBREAKS, tag) >= 0) sameLine = false;
+        return (((tag === 'TERMINATOR' || tag === 'OUTDENT') || (__indexOf.call(IMPLICIT_END, tag) >= 0 && sameLine)) && ((!startsLine && this.tag(i - 1) !== ',') || !((two != null ? two[0] : void 0) === ':' || (one != null ? one[0] : void 0) === '@' && (three != null ? three[0] : void 0) === ':'))) || (tag === ',' && one && ((_ref1 = one[0]) !== 'IDENTIFIER' && _ref1 !== 'NUMBER' && _ref1 !== 'STRING' && _ref1 !== '@' && _ref1 !== 'TERMINATOR' && _ref1 !== 'OUTDENT'));
       };
       action = function(token, i) {
         var tok;
-        tok = ['}', '}', token[2]];
-        tok.generated = true;
+        tok = this.generate('}', '}', token[2]);
         return this.tokens.splice(i, 0, tok);
       };
       return this.scanTokens(function(token, i, tokens) {
-        var ago, idx, tag, tok, value, _ref, _ref2;
+        var ago, idx, prevTag, tag, tok, value, _ref, _ref1;
         if (_ref = (tag = token[0]), __indexOf.call(EXPRESSION_START, _ref) >= 0) {
           stack.push([(tag === 'INDENT' && this.tag(i - 1) === '{' ? '{' : tag), i]);
           return 1;
@@ -3605,80 +3685,82 @@ define('ace/mode/coffee/rewriter', ['require', 'exports', 'module' ], function(r
           start = stack.pop();
           return 1;
         }
-        if (!(tag === ':' && ((ago = this.tag(i - 2)) === ':' || ((_ref2 = stack[stack.length - 1]) != null ? _ref2[0] : void 0) !== '{'))) {
+        if (!(tag === ':' && ((ago = this.tag(i - 2)) === ':' || ((_ref1 = stack[stack.length - 1]) != null ? _ref1[0] : void 0) !== '{'))) {
           return 1;
         }
+        sameLine = true;
         stack.push(['{']);
         idx = ago === '@' ? i - 2 : i - 1;
         while (this.tag(idx - 2) === 'HERECOMMENT') {
           idx -= 2;
         }
+        prevTag = this.tag(idx - 1);
+        startsLine = !prevTag || (__indexOf.call(LINEBREAKS, prevTag) >= 0);
         value = new String('{');
         value.generated = true;
-        tok = ['{', value, token[2]];
-        tok.generated = true;
+        tok = this.generate('{', value, token[2]);
         tokens.splice(idx, 0, tok);
         this.detectEnd(i + 2, condition, action);
         return 2;
       });
     };
+
     Rewriter.prototype.addImplicitParentheses = function() {
-      var action, noCall;
-      noCall = false;
+      var action, condition, noCall, seenControl, seenSingle;
+      noCall = seenSingle = seenControl = false;
+      condition = function(token, i) {
+        var post, tag, _ref, _ref1;
+        tag = token[0];
+        if (!seenSingle && token.fromThen) return true;
+        if (tag === 'IF' || tag === 'ELSE' || tag === 'CATCH' || tag === '->' || tag === '=>' || tag === 'CLASS') {
+          seenSingle = true;
+        }
+        if (tag === 'IF' || tag === 'ELSE' || tag === 'SWITCH' || tag === 'TRY' || tag === '=') {
+          seenControl = true;
+        }
+        if ((tag === '.' || tag === '?.' || tag === '::') && this.tag(i - 1) === 'OUTDENT') {
+          return true;
+        }
+        return !token.generated && this.tag(i - 1) !== ',' && (__indexOf.call(IMPLICIT_END, tag) >= 0 || (tag === 'INDENT' && !seenControl)) && (tag !== 'INDENT' || (((_ref = this.tag(i - 2)) !== 'CLASS' && _ref !== 'EXTENDS') && (_ref1 = this.tag(i - 1), __indexOf.call(IMPLICIT_BLOCK, _ref1) < 0) && !((post = this.tokens[i + 1]) && post.generated && post[0] === '{')));
+      };
       action = function(token, i) {
-        var idx;
-        idx = token[0] === 'OUTDENT' ? i + 1 : i;
-        return this.tokens.splice(idx, 0, ['CALL_END', ')', token[2]]);
+        return this.tokens.splice(i, 0, this.generate('CALL_END', ')', token[2]));
       };
       return this.scanTokens(function(token, i, tokens) {
-        var callObject, current, next, prev, seenControl, seenSingle, tag, _ref, _ref2, _ref3;
+        var callObject, current, next, prev, tag, _ref, _ref1, _ref2;
         tag = token[0];
-        if (tag === 'CLASS' || tag === 'IF') {
+        if (tag === 'CLASS' || tag === 'IF' || tag === 'FOR' || tag === 'WHILE') {
           noCall = true;
         }
-        _ref = tokens.slice(i - 1, (i + 1 + 1) || 9e9), prev = _ref[0], current = _ref[1], next = _ref[2];
-        callObject = !noCall && tag === 'INDENT' && next && next.generated && next[0] === '{' && prev && (_ref2 = prev[0], __indexOf.call(IMPLICIT_FUNC, _ref2) >= 0);
+        _ref = tokens.slice(i - 1, (i + 1) + 1 || 9e9), prev = _ref[0], current = _ref[1], next = _ref[2];
+        callObject = !noCall && tag === 'INDENT' && next && next.generated && next[0] === '{' && prev && (_ref1 = prev[0], __indexOf.call(IMPLICIT_FUNC, _ref1) >= 0);
         seenSingle = false;
         seenControl = false;
-        if (__indexOf.call(LINEBREAKS, tag) >= 0) {
-          noCall = false;
-        }
-        if (prev && !prev.spaced && tag === '?') {
-          token.call = true;
-        }
-        if (token.fromThen) {
-          return 1;
-        }
-        if (!(callObject || (prev != null ? prev.spaced : void 0) && (prev.call || (_ref3 = prev[0], __indexOf.call(IMPLICIT_FUNC, _ref3) >= 0)) && (__indexOf.call(IMPLICIT_CALL, tag) >= 0 || !(token.spaced || token.newLine) && __indexOf.call(IMPLICIT_UNSPACED_CALL, tag) >= 0))) {
+        if (__indexOf.call(LINEBREAKS, tag) >= 0) noCall = false;
+        if (prev && !prev.spaced && tag === '?') token.call = true;
+        if (token.fromThen) return 1;
+        if (!(callObject || (prev != null ? prev.spaced : void 0) && (prev.call || (_ref2 = prev[0], __indexOf.call(IMPLICIT_FUNC, _ref2) >= 0)) && (__indexOf.call(IMPLICIT_CALL, tag) >= 0 || !(token.spaced || token.newLine) && __indexOf.call(IMPLICIT_UNSPACED_CALL, tag) >= 0))) {
           return 1;
         }
-        tokens.splice(i, 0, ['CALL_START', '(', token[2]]);
-        this.detectEnd(i + 1, function(token, i) {
-          var post, _ref4;
-          tag = token[0];
-          if (!seenSingle && token.fromThen) {
-            return true;
-          }
-          if (tag === 'IF' || tag === 'ELSE' || tag === 'CATCH' || tag === '->' || tag === '=>') {
-            seenSingle = true;
-          }
-          if (tag === 'IF' || tag === 'ELSE' || tag === 'SWITCH' || tag === 'TRY') {
-            seenControl = true;
-          }
-          if ((tag === '.' || tag === '?.' || tag === '::') && this.tag(i - 1) === 'OUTDENT') {
-            return true;
-          }
-          return !token.generated && this.tag(i - 1) !== ',' && (__indexOf.call(IMPLICIT_END, tag) >= 0 || (tag === 'INDENT' && !seenControl)) && (tag !== 'INDENT' || (this.tag(i - 2) !== 'CLASS' && (_ref4 = this.tag(i - 1), __indexOf.call(IMPLICIT_BLOCK, _ref4) < 0) && !((post = this.tokens[i + 1]) && post.generated && post[0] === '{')));
-        }, action);
-        if (prev[0] === '?') {
-          prev[0] = 'FUNC_EXIST';
-        }
+        tokens.splice(i, 0, this.generate('CALL_START', '(', token[2]));
+        this.detectEnd(i + 1, condition, action);
+        if (prev[0] === '?') prev[0] = 'FUNC_EXIST';
         return 2;
       });
     };
+
     Rewriter.prototype.addImplicitIndentation = function() {
+      var action, condition, indent, outdent, starter;
+      starter = indent = outdent = null;
+      condition = function(token, i) {
+        var _ref;
+        return token[1] !== ';' && (_ref = token[0], __indexOf.call(SINGLE_CLOSERS, _ref) >= 0) && !(token[0] === 'ELSE' && (starter !== 'IF' && starter !== 'THEN'));
+      };
+      action = function(token, i) {
+        return this.tokens.splice((this.tag(i - 1) === ',' ? i - 1 : i), 0, outdent);
+      };
       return this.scanTokens(function(token, i, tokens) {
-        var action, condition, indent, outdent, starter, tag, _ref, _ref2;
+        var tag, _ref, _ref1;
         tag = token[0];
         if (tag === 'TERMINATOR' && this.tag(i + 1) === 'THEN') {
           tokens.splice(i, 1);
@@ -3694,145 +3776,98 @@ define('ace/mode/coffee/rewriter', ['require', 'exports', 'module' ], function(r
         }
         if (__indexOf.call(SINGLE_LINERS, tag) >= 0 && this.tag(i + 1) !== 'INDENT' && !(tag === 'ELSE' && this.tag(i + 1) === 'IF')) {
           starter = tag;
-          _ref2 = this.indentation(token), indent = _ref2[0], outdent = _ref2[1];
-          if (starter === 'THEN') {
-            indent.fromThen = true;
-          }
-          indent.generated = outdent.generated = true;
+          _ref1 = this.indentation(token, true), indent = _ref1[0], outdent = _ref1[1];
+          if (starter === 'THEN') indent.fromThen = true;
           tokens.splice(i + 1, 0, indent);
-          condition = function(token, i) {
-            var _ref3;
-            return token[1] !== ';' && (_ref3 = token[0], __indexOf.call(SINGLE_CLOSERS, _ref3) >= 0) && !(token[0] === 'ELSE' && (starter !== 'IF' && starter !== 'THEN'));
-          };
-          action = function(token, i) {
-            return this.tokens.splice((this.tag(i - 1) === ',' ? i - 1 : i), 0, outdent);
-          };
           this.detectEnd(i + 2, condition, action);
-          if (tag === 'THEN') {
-            tokens.splice(i, 1);
-          }
+          if (tag === 'THEN') tokens.splice(i, 1);
           return 1;
         }
         return 1;
       });
     };
+
     Rewriter.prototype.tagPostfixConditionals = function() {
-      var condition;
+      var action, condition, original;
+      original = null;
       condition = function(token, i) {
         var _ref;
         return (_ref = token[0]) === 'TERMINATOR' || _ref === 'INDENT';
       };
-      return this.scanTokens(function(token, i) {
-        var original;
-        if (token[0] !== 'IF') {
-          return 1;
+      action = function(token, i) {
+        if (token[0] !== 'INDENT' || (token.generated && !token.fromThen)) {
+          return original[0] = 'POST_' + original[0];
         }
+      };
+      return this.scanTokens(function(token, i) {
+        if (token[0] !== 'IF') return 1;
         original = token;
-        this.detectEnd(i + 1, condition, function(token, i) {
-          if (token[0] !== 'INDENT') {
-            return original[0] = 'POST_' + original[0];
-          }
-        });
+        this.detectEnd(i + 1, condition, action);
         return 1;
       });
     };
-    Rewriter.prototype.ensureBalance = function(pairs) {
-      var close, level, levels, open, openLine, tag, token, _i, _j, _len, _len2, _ref, _ref2;
-      levels = {};
-      openLine = {};
-      _ref = this.tokens;
-      for (_i = 0, _len = _ref.length; _i < _len; _i++) {
-        token = _ref[_i];
-        tag = token[0];
-        for (_j = 0, _len2 = pairs.length; _j < _len2; _j++) {
-          _ref2 = pairs[_j], open = _ref2[0], close = _ref2[1];
-          levels[open] |= 0;
-          if (tag === open) {
-            if (levels[open]++ === 0) {
-              openLine[open] = token[2];
-            }
-          } else if (tag === close && --levels[open] < 0) {
-            throw Error("too many " + token[1] + " on line " + (token[2] + 1));
-          }
-        }
-      }
-      for (open in levels) {
-        level = levels[open];
-        if (level > 0) {
-          throw Error("unclosed " + open + " on line " + (openLine[open] + 1));
-        }
-      }
-      return this;
+
+    Rewriter.prototype.indentation = function(token, implicit) {
+      var indent, outdent;
+      if (implicit == null) implicit = false;
+      indent = ['INDENT', 2, token[2]];
+      outdent = ['OUTDENT', 2, token[2]];
+      if (implicit) indent.generated = outdent.generated = true;
+      return [indent, outdent];
     };
-    Rewriter.prototype.rewriteClosingParens = function() {
-      var debt, key, stack;
-      stack = [];
-      debt = {};
-      for (key in INVERSES) {
-        debt[key] = 0;
-      }
-      return this.scanTokens(function(token, i, tokens) {
-        var inv, match, mtag, oppos, tag, val, _ref;
-        if (_ref = (tag = token[0]), __indexOf.call(EXPRESSION_START, _ref) >= 0) {
-          stack.push(token);
-          return 1;
-        }
-        if (__indexOf.call(EXPRESSION_END, tag) < 0) {
-          return 1;
-        }
-        if (debt[inv = INVERSES[tag]] > 0) {
-          debt[inv] -= 1;
-          tokens.splice(i, 1);
-          return 0;
-        }
-        match = stack.pop();
-        mtag = match[0];
-        oppos = INVERSES[mtag];
-        if (tag === oppos) {
-          return 1;
-        }
-        debt[mtag] += 1;
-        val = [oppos, mtag === 'INDENT' ? match[1] : oppos];
-        if (this.tag(i + 2) === mtag) {
-          tokens.splice(i + 3, 0, val);
-          stack.push(match);
-        } else {
-          tokens.splice(i, 0, val);
-        }
-        return 1;
-      });
-    };
-    Rewriter.prototype.indentation = function(token) {
-      return [['INDENT', 2, token[2]], ['OUTDENT', 2, token[2]]];
+
+    Rewriter.prototype.generate = function(tag, value, line) {
+      var tok;
+      tok = [tag, value, line];
+      tok.generated = true;
+      return tok;
     };
+
     Rewriter.prototype.tag = function(i) {
       var _ref;
       return (_ref = this.tokens[i]) != null ? _ref[0] : void 0;
     };
+
     return Rewriter;
+
   })();
+
   BALANCED_PAIRS = [['(', ')'], ['[', ']'], ['{', '}'], ['INDENT', 'OUTDENT'], ['CALL_START', 'CALL_END'], ['PARAM_START', 'PARAM_END'], ['INDEX_START', 'INDEX_END']];
-  INVERSES = {};
+
+  exports.INVERSES = INVERSES = {};
+
   EXPRESSION_START = [];
+
   EXPRESSION_END = [];
+
   for (_i = 0, _len = BALANCED_PAIRS.length; _i < _len; _i++) {
     _ref = BALANCED_PAIRS[_i], left = _ref[0], rite = _ref[1];
     EXPRESSION_START.push(INVERSES[rite] = left);
     EXPRESSION_END.push(INVERSES[left] = rite);
   }
+
   EXPRESSION_CLOSE = ['CATCH', 'WHEN', 'ELSE', 'FINALLY'].concat(EXPRESSION_END);
+
   IMPLICIT_FUNC = ['IDENTIFIER', 'SUPER', ')', 'CALL_END', ']', 'INDEX_END', '@', 'THIS'];
+
   IMPLICIT_CALL = ['IDENTIFIER', 'NUMBER', 'STRING', 'JS', 'REGEX', 'NEW', 'PARAM_START', 'CLASS', 'IF', 'TRY', 'SWITCH', 'THIS', 'BOOL', 'UNARY', 'SUPER', '@', '->', '=>', '[', '(', '{', '--', '++'];
+
   IMPLICIT_UNSPACED_CALL = ['+', '-'];
+
   IMPLICIT_BLOCK = ['->', '=>', '{', '[', ','];
+
   IMPLICIT_END = ['POST_IF', 'FOR', 'WHILE', 'UNTIL', 'WHEN', 'BY', 'LOOP', 'TERMINATOR'];
+
   SINGLE_LINERS = ['ELSE', '->', '=>', 'TRY', 'FINALLY', 'THEN'];
+
   SINGLE_CLOSERS = ['TERMINATOR', 'CATCH', 'FINALLY', 'ELSE', 'OUTDENT', 'LEADING_WHEN'];
+
   LINEBREAKS = ['TERMINATOR', 'INDENT', 'OUTDENT'];
-});
-/**
+
+
+});/**
  * Copyright (c) 2011 Jeremy Ashkenas
- *
+ * 
  * Permission is hereby granted, free of charge, to any person
  * obtaining a copy of this software and associated documentation
  * files (the "Software"), to deal in the Software without
@@ -3856,41 +3891,44 @@ define('ace/mode/coffee/rewriter', ['require', 'exports', 'module' ], function(r
  */
 
 define('ace/mode/coffee/helpers', ['require', 'exports', 'module' ], function(require, exports, module) {
-    
+// Generated by CoffeeScript 1.2.1-pre
+
   var extend, flatten;
+
   exports.starts = function(string, literal, start) {
     return literal === string.substr(start, literal.length);
   };
+
   exports.ends = function(string, literal, back) {
     var len;
     len = literal.length;
     return literal === string.substr(string.length - len - (back || 0), len);
   };
+
   exports.compact = function(array) {
     var item, _i, _len, _results;
     _results = [];
     for (_i = 0, _len = array.length; _i < _len; _i++) {
       item = array[_i];
-      if (item) {
-        _results.push(item);
-      }
+      if (item) _results.push(item);
     }
     return _results;
   };
+
   exports.count = function(string, substr) {
     var num, pos;
     num = pos = 0;
-    if (!substr.length) {
-      return 1 / 0;
-    }
+    if (!substr.length) return 1 / 0;
     while (pos = 1 + string.indexOf(substr, pos)) {
       num++;
     }
     return num;
   };
+
   exports.merge = function(options, overrides) {
     return extend(extend({}, options), overrides);
   };
+
   extend = exports.extend = function(object, properties) {
     var key, val;
     for (key in properties) {
@@ -3899,6 +3937,7 @@ define('ace/mode/coffee/helpers', ['require', 'exports', 'module' ], function(re
     }
     return object;
   };
+
   exports.flatten = flatten = function(array) {
     var element, flattened, _i, _len;
     flattened = [];
@@ -3912,19 +3951,22 @@ define('ace/mode/coffee/helpers', ['require', 'exports', 'module' ], function(re
     }
     return flattened;
   };
+
   exports.del = function(obj, key) {
     var val;
     val = obj[key];
     delete obj[key];
     return val;
   };
+
   exports.last = function(array, back) {
     return array[array.length - (back || 0) - 1];
   };
-});
-/**
+
+
+});/**
  * Copyright (c) 2011 Jeremy Ashkenas
- *
+ * 
  * Permission is hereby granted, free of charge, to any person
  * obtaining a copy of this software and associated documentation
  * files (the "Software"), to deal in the Software without
@@ -3948,13 +3990,14 @@ define('ace/mode/coffee/helpers', ['require', 'exports', 'module' ], function(re
  */
 
 define('ace/mode/coffee/parser', ['require', 'exports', 'module' ], function(require, exports, module) {
-
 /* Jison generated parser */
+
+undefined
 var parser = {trace: function trace() { },
 yy: {},
-symbols_: {"error":2,"Root":3,"Body":4,"Block":5,"TERMINATOR":6,"Line":7,"Expression":8,"Statement":9,"Return":10,"Throw":11,"Comment":12,"STATEMENT":13,"Value":14,"Invocation":15,"Code":16,"Operation":17,"Assign":18,"If":19,"Try":20,"While":21,"For":22,"Switch":23,"Class":24,"INDENT":25,"OUTDENT":26,"Identifier":27,"IDENTIFIER":28,"AlphaNumeric":29,"NUMBER":30,"STRING":31,"Literal":32,"JS":33,"REGEX":34,"BOOL":35,"Assignable":36,"=":37,"AssignObj":38,"ObjAssignable":39,":":40,"ThisProperty":41,"RETURN":42,"HERECOMMENT":43,"PARAM_START":44,"ParamList":45,"PARAM_END":46,"FuncGlyph":47,"->":48,"=>":49,"OptComma":50,",":51,"Param":52,"ParamVar":53,"...":54,"Array":55,"Object":56,"Splat":57,"SimpleAssignable":58,"Accessor":59,"Parenthetical":60,"Range":61,"This":62,".":63,"?.":64,"::":65,"Index":66,"INDEX_START":67,"IndexValue":68,"INDEX_END":69,"INDEX_SOAK":70,"INDEX_PROTO":71,"Slice":72,"{":73,"AssignList":74,"}":75,"CLASS":76,"EXTENDS":77,"OptFuncExist":78,"Arguments":79,"SUPER":80,"FUNC_EXIST":81,"CALL_START":82,"CALL_END":83,"ArgList":84,"THIS":85,"@":86,"[":87,"]":88,"RangeDots":89,"..":90,"Arg":91,"SimpleArgs":92,"TRY":93,"Catch":94,"FINALLY":95,"CATCH":96,"THROW":97,"(":98,")":99,"WhileSource":100,"WHILE":101,"WHEN":102,"UNTIL":103,"Loop":104,"LOOP":105,"ForBody":106,"FOR":107,"ForStart":108,"ForSource":109,"ForVariables":110,"OWN":111,"ForValue":112,"FORIN":113,"FOROF":114,"BY":115,"SWITCH":116,"Whens":117,"ELSE":118,"When":119,"LEADING_WHEN":120,"IfBlock":121,"IF":122,"POST_IF":123,"UNARY":124,"-":125,"+":126,"--":127,"++":128,"?":129,"MATH":130,"SHIFT":131,"COMPARE":132,"LOGIC":133,"RELATION":134,"COMPOUND_ASSIGN":135,"$accept":0,"$end":1},
-terminals_: {2:"error",6:"TERMINATOR",13:"STATEMENT",25:"INDENT",26:"OUTDENT",28:"IDENTIFIER",30:"NUMBER",31:"STRING",33:"JS",34:"REGEX",35:"BOOL",37:"=",40:":",42:"RETURN",43:"HERECOMMENT",44:"PARAM_START",46:"PARAM_END",48:"->",49:"=>",51:",",54:"...",63:".",64:"?.",65:"::",67:"INDEX_START",69:"INDEX_END",70:"INDEX_SOAK",71:"INDEX_PROTO",73:"{",75:"}",76:"CLASS",77:"EXTENDS",80:"SUPER",81:"FUNC_EXIST",82:"CALL_START",83:"CALL_END",85:"THIS",86:"@",87:"[",88:"]",90:"..",93:"TRY",95:"FINALLY",96:"CATCH",97:"THROW",98:"(",99:")",101:"WHILE",102:"WHEN",103:"UNTIL",105:"LOOP",107:"FOR",111:"OWN",113:"FORIN",114:"FOROF",115:"BY",116:"SWITCH",118:"ELSE",120:"LEADING_WHEN",122:"IF",123:"POST_IF",124:"UNARY",125:"-",126:"+",127:"--",128:"++",129:"?",130:"MATH",131:"SHIFT",132:"COMPARE",133:"LOGIC",134:"RELATION",135:"COMPOUND_ASSIGN"},
-productions_: [0,[3,0],[3,1],[3,2],[4,1],[4,3],[4,2],[7,1],[7,1],[9,1],[9,1],[9,1],[9,1],[8,1],[8,1],[8,1],[8,1],[8,1],[8,1],[8,1],[8,1],[8,1],[8,1],[8,1],[5,2],[5,3],[27,1],[29,1],[29,1],[32,1],[32,1],[32,1],[32,1],[18,3],[18,5],[38,1],[38,3],[38,5],[38,1],[39,1],[39,1],[39,1],[10,2],[10,1],[12,1],[16,5],[16,2],[47,1],[47,1],[50,0],[50,1],[45,0],[45,1],[45,3],[52,1],[52,2],[52,3],[53,1],[53,1],[53,1],[53,1],[57,2],[58,1],[58,2],[58,2],[58,1],[36,1],[36,1],[36,1],[14,1],[14,1],[14,1],[14,1],[14,1],[59,2],[59,2],[59,2],[59,1],[59,1],[66,3],[66,2],[66,2],[68,1],[68,1],[56,4],[74,0],[74,1],[74,3],[74,4],[74,6],[24,1],[24,2],[24,3],[24,4],[24,2],[24,3],[24,4],[24,5],[15,3],[15,3],[15,1],[15,2],[78,0],[78,1],[79,2],[79,4],[62,1],[62,1],[41,2],[55,2],[55,4],[89,1],[89,1],[61,5],[72,3],[72,2],[72,2],[84,1],[84,3],[84,4],[84,4],[84,6],[91,1],[91,1],[92,1],[92,3],[20,2],[20,3],[20,4],[20,5],[94,3],[11,2],[60,3],[60,5],[100,2],[100,4],[100,2],[100,4],[21,2],[21,2],[21,2],[21,1],[104,2],[104,2],[22,2],[22,2],[22,2],[106,2],[106,2],[108,2],[108,3],[112,1],[112,1],[112,1],[110,1],[110,3],[109,2],[109,2],[109,4],[109,4],[109,4],[109,6],[109,6],[23,5],[23,7],[23,4],[23,6],[117,1],[117,2],[119,3],[119,4],[121,3],[121,5],[19,1],[19,3],[19,3],[19,3],[17,2],[17,2],[17,2],[17,2],[17,2],[17,2],[17,2],[17,2],[17,3],[17,3],[17,3],[17,3],[17,3],[17,3],[17,3],[17,3],[17,5],[17,3]],
+symbols_: {"error":2,"Root":3,"Body":4,"Block":5,"TERMINATOR":6,"Line":7,"Expression":8,"Statement":9,"Return":10,"Comment":11,"STATEMENT":12,"Value":13,"Invocation":14,"Code":15,"Operation":16,"Assign":17,"If":18,"Try":19,"While":20,"For":21,"Switch":22,"Class":23,"Throw":24,"INDENT":25,"OUTDENT":26,"Identifier":27,"IDENTIFIER":28,"AlphaNumeric":29,"NUMBER":30,"STRING":31,"Literal":32,"JS":33,"REGEX":34,"DEBUGGER":35,"BOOL":36,"Assignable":37,"=":38,"AssignObj":39,"ObjAssignable":40,":":41,"ThisProperty":42,"RETURN":43,"HERECOMMENT":44,"PARAM_START":45,"ParamList":46,"PARAM_END":47,"FuncGlyph":48,"->":49,"=>":50,"OptComma":51,",":52,"Param":53,"ParamVar":54,"...":55,"Array":56,"Object":57,"Splat":58,"SimpleAssignable":59,"Accessor":60,"Parenthetical":61,"Range":62,"This":63,".":64,"?.":65,"::":66,"Index":67,"INDEX_START":68,"IndexValue":69,"INDEX_END":70,"INDEX_SOAK":71,"Slice":72,"{":73,"AssignList":74,"}":75,"CLASS":76,"EXTENDS":77,"OptFuncExist":78,"Arguments":79,"SUPER":80,"FUNC_EXIST":81,"CALL_START":82,"CALL_END":83,"ArgList":84,"THIS":85,"@":86,"[":87,"]":88,"RangeDots":89,"..":90,"Arg":91,"SimpleArgs":92,"TRY":93,"Catch":94,"FINALLY":95,"CATCH":96,"THROW":97,"(":98,")":99,"WhileSource":100,"WHILE":101,"WHEN":102,"UNTIL":103,"Loop":104,"LOOP":105,"ForBody":106,"FOR":107,"ForStart":108,"ForSource":109,"ForVariables":110,"OWN":111,"ForValue":112,"FORIN":113,"FOROF":114,"BY":115,"SWITCH":116,"Whens":117,"ELSE":118,"When":119,"LEADING_WHEN":120,"IfBlock":121,"IF":122,"POST_IF":123,"UNARY":124,"-":125,"+":126,"--":127,"++":128,"?":129,"MATH":130,"SHIFT":131,"COMPARE":132,"LOGIC":133,"RELATION":134,"COMPOUND_ASSIGN":135,"$accept":0,"$end":1},
+terminals_: {2:"error",6:"TERMINATOR",12:"STATEMENT",25:"INDENT",26:"OUTDENT",28:"IDENTIFIER",30:"NUMBER",31:"STRING",33:"JS",34:"REGEX",35:"DEBUGGER",36:"BOOL",38:"=",41:":",43:"RETURN",44:"HERECOMMENT",45:"PARAM_START",47:"PARAM_END",49:"->",50:"=>",52:",",55:"...",64:".",65:"?.",66:"::",68:"INDEX_START",70:"INDEX_END",71:"INDEX_SOAK",73:"{",75:"}",76:"CLASS",77:"EXTENDS",80:"SUPER",81:"FUNC_EXIST",82:"CALL_START",83:"CALL_END",85:"THIS",86:"@",87:"[",88:"]",90:"..",93:"TRY",95:"FINALLY",96:"CATCH",97:"THROW",98:"(",99:")",101:"WHILE",102:"WHEN",103:"UNTIL",105:"LOOP",107:"FOR",111:"OWN",113:"FORIN",114:"FOROF",115:"BY",116:"SWITCH",118:"ELSE",120:"LEADING_WHEN",122:"IF",123:"POST_IF",124:"UNARY",125:"-",126:"+",127:"--",128:"++",129:"?",130:"MATH",131:"SHIFT",132:"COMPARE",133:"LOGIC",134:"RELATION",135:"COMPOUND_ASSIGN"},
+productions_: [0,[3,0],[3,1],[3,2],[4,1],[4,3],[4,2],[7,1],[7,1],[9,1],[9,1],[9,1],[8,1],[8,1],[8,1],[8,1],[8,1],[8,1],[8,1],[8,1],[8,1],[8,1],[8,1],[8,1],[5,2],[5,3],[27,1],[29,1],[29,1],[32,1],[32,1],[32,1],[32,1],[32,1],[17,3],[17,4],[17,5],[39,1],[39,3],[39,5],[39,1],[40,1],[40,1],[40,1],[10,2],[10,1],[11,1],[15,5],[15,2],[48,1],[48,1],[51,0],[51,1],[46,0],[46,1],[46,3],[53,1],[53,2],[53,3],[54,1],[54,1],[54,1],[54,1],[58,2],[59,1],[59,2],[59,2],[59,1],[37,1],[37,1],[37,1],[13,1],[13,1],[13,1],[13,1],[13,1],[60,2],[60,2],[60,2],[60,1],[60,1],[67,3],[67,2],[69,1],[69,1],[57,4],[74,0],[74,1],[74,3],[74,4],[74,6],[23,1],[23,2],[23,3],[23,4],[23,2],[23,3],[23,4],[23,5],[14,3],[14,3],[14,1],[14,2],[78,0],[78,1],[79,2],[79,4],[63,1],[63,1],[42,2],[56,2],[56,4],[89,1],[89,1],[62,5],[72,3],[72,2],[72,2],[72,1],[84,1],[84,3],[84,4],[84,4],[84,6],[91,1],[91,1],[92,1],[92,3],[19,2],[19,3],[19,4],[19,5],[94,3],[24,2],[61,3],[61,5],[100,2],[100,4],[100,2],[100,4],[20,2],[20,2],[20,2],[20,1],[104,2],[104,2],[21,2],[21,2],[21,2],[106,2],[106,2],[108,2],[108,3],[112,1],[112,1],[112,1],[110,1],[110,3],[109,2],[109,2],[109,4],[109,4],[109,4],[109,6],[109,6],[22,5],[22,7],[22,4],[22,6],[117,1],[117,2],[119,3],[119,4],[121,3],[121,5],[18,1],[18,3],[18,3],[18,3],[16,2],[16,2],[16,2],[16,2],[16,2],[16,2],[16,2],[16,2],[16,3],[16,3],[16,3],[16,3],[16,3],[16,3],[16,3],[16,3],[16,5],[16,3]],
 performAction: function anonymous(yytext,yyleng,yylineno,yy,yystate,$$,_$) {
 
 var $0 = $$.length - 1;
@@ -3979,9 +4022,9 @@ case 9:this.$ = $$[$0];
 break;
 case 10:this.$ = $$[$0];
 break;
-case 11:this.$ = $$[$0];
+case 11:this.$ = new yy.Literal($$[$0]);
 break;
-case 12:this.$ = new yy.Literal($$[$0]);
+case 12:this.$ = $$[$0];
 break;
 case 13:this.$ = $$[$0];
 break;
@@ -4021,386 +4064,386 @@ case 30:this.$ = new yy.Literal($$[$0]);
 break;
 case 31:this.$ = new yy.Literal($$[$0]);
 break;
-case 32:this.$ = (function () {
+case 32:this.$ = new yy.Literal($$[$0]);
+break;
+case 33:this.$ = (function () {
         var val;
         val = new yy.Literal($$[$0]);
-        if ($$[$0] === 'undefined') {
-          val.isUndefined = true;
-        }
+        if ($$[$0] === 'undefined') val.isUndefined = true;
         return val;
       }());
 break;
-case 33:this.$ = new yy.Assign($$[$0-2], $$[$0]);
-break;
-case 34:this.$ = new yy.Assign($$[$0-4], $$[$0-1]);
+case 34:this.$ = new yy.Assign($$[$0-2], $$[$0]);
 break;
-case 35:this.$ = new yy.Value($$[$0]);
+case 35:this.$ = new yy.Assign($$[$0-3], $$[$0]);
 break;
-case 36:this.$ = new yy.Assign(new yy.Value($$[$0-2]), $$[$0], 'object');
+case 36:this.$ = new yy.Assign($$[$0-4], $$[$0-1]);
 break;
-case 37:this.$ = new yy.Assign(new yy.Value($$[$0-4]), $$[$0-1], 'object');
+case 37:this.$ = new yy.Value($$[$0]);
 break;
-case 38:this.$ = $$[$0];
+case 38:this.$ = new yy.Assign(new yy.Value($$[$0-2]), $$[$0], 'object');
 break;
-case 39:this.$ = $$[$0];
+case 39:this.$ = new yy.Assign(new yy.Value($$[$0-4]), $$[$0-1], 'object');
 break;
 case 40:this.$ = $$[$0];
 break;
 case 41:this.$ = $$[$0];
 break;
-case 42:this.$ = new yy.Return($$[$0]);
+case 42:this.$ = $$[$0];
 break;
-case 43:this.$ = new yy.Return;
+case 43:this.$ = $$[$0];
 break;
-case 44:this.$ = new yy.Comment($$[$0]);
+case 44:this.$ = new yy.Return($$[$0]);
 break;
-case 45:this.$ = new yy.Code($$[$0-3], $$[$0], $$[$0-1]);
+case 45:this.$ = new yy.Return;
 break;
-case 46:this.$ = new yy.Code([], $$[$0], $$[$0-1]);
+case 46:this.$ = new yy.Comment($$[$0]);
 break;
-case 47:this.$ = 'func';
+case 47:this.$ = new yy.Code($$[$0-3], $$[$0], $$[$0-1]);
 break;
-case 48:this.$ = 'boundfunc';
+case 48:this.$ = new yy.Code([], $$[$0], $$[$0-1]);
 break;
-case 49:this.$ = $$[$0];
+case 49:this.$ = 'func';
 break;
-case 50:this.$ = $$[$0];
+case 50:this.$ = 'boundfunc';
 break;
-case 51:this.$ = [];
+case 51:this.$ = $$[$0];
 break;
-case 52:this.$ = [$$[$0]];
+case 52:this.$ = $$[$0];
 break;
-case 53:this.$ = $$[$0-2].concat($$[$0]);
+case 53:this.$ = [];
 break;
-case 54:this.$ = new yy.Param($$[$0]);
+case 54:this.$ = [$$[$0]];
 break;
-case 55:this.$ = new yy.Param($$[$0-1], null, true);
+case 55:this.$ = $$[$0-2].concat($$[$0]);
 break;
-case 56:this.$ = new yy.Param($$[$0-2], $$[$0]);
+case 56:this.$ = new yy.Param($$[$0]);
 break;
-case 57:this.$ = $$[$0];
+case 57:this.$ = new yy.Param($$[$0-1], null, true);
 break;
-case 58:this.$ = $$[$0];
+case 58:this.$ = new yy.Param($$[$0-2], $$[$0]);
 break;
 case 59:this.$ = $$[$0];
 break;
 case 60:this.$ = $$[$0];
 break;
-case 61:this.$ = new yy.Splat($$[$0-1]);
+case 61:this.$ = $$[$0];
 break;
-case 62:this.$ = new yy.Value($$[$0]);
+case 62:this.$ = $$[$0];
 break;
-case 63:this.$ = $$[$0-1].push($$[$0]);
+case 63:this.$ = new yy.Splat($$[$0-1]);
 break;
-case 64:this.$ = new yy.Value($$[$0-1], [$$[$0]]);
+case 64:this.$ = new yy.Value($$[$0]);
 break;
-case 65:this.$ = $$[$0];
+case 65:this.$ = $$[$0-1].add($$[$0]);
 break;
-case 66:this.$ = $$[$0];
+case 66:this.$ = new yy.Value($$[$0-1], [].concat($$[$0]));
 break;
-case 67:this.$ = new yy.Value($$[$0]);
+case 67:this.$ = $$[$0];
 break;
-case 68:this.$ = new yy.Value($$[$0]);
+case 68:this.$ = $$[$0];
 break;
-case 69:this.$ = $$[$0];
+case 69:this.$ = new yy.Value($$[$0]);
 break;
 case 70:this.$ = new yy.Value($$[$0]);
 break;
-case 71:this.$ = new yy.Value($$[$0]);
+case 71:this.$ = $$[$0];
 break;
 case 72:this.$ = new yy.Value($$[$0]);
 break;
-case 73:this.$ = $$[$0];
+case 73:this.$ = new yy.Value($$[$0]);
 break;
-case 74:this.$ = new yy.Access($$[$0]);
+case 74:this.$ = new yy.Value($$[$0]);
 break;
-case 75:this.$ = new yy.Access($$[$0], 'soak');
+case 75:this.$ = $$[$0];
 break;
-case 76:this.$ = new yy.Access($$[$0], 'proto');
+case 76:this.$ = new yy.Access($$[$0]);
 break;
-case 77:this.$ = new yy.Access(new yy.Literal('prototype'));
+case 77:this.$ = new yy.Access($$[$0], 'soak');
 break;
-case 78:this.$ = $$[$0];
+case 78:this.$ = [new yy.Access(new yy.Literal('prototype')), new yy.Access($$[$0])];
 break;
-case 79:this.$ = $$[$0-1];
+case 79:this.$ = new yy.Access(new yy.Literal('prototype'));
 break;
-case 80:this.$ = yy.extend($$[$0], {
-          soak: true
-        });
+case 80:this.$ = $$[$0];
 break;
-case 81:this.$ = yy.extend($$[$0], {
-          proto: true
-        });
+case 81:this.$ = $$[$0-1];
 break;
-case 82:this.$ = new yy.Index($$[$0]);
+case 82:this.$ = yy.extend($$[$0], {
+          soak: true
+        });
 break;
-case 83:this.$ = new yy.Slice($$[$0]);
+case 83:this.$ = new yy.Index($$[$0]);
 break;
-case 84:this.$ = new yy.Obj($$[$0-2], $$[$0-3].generated);
+case 84:this.$ = new yy.Slice($$[$0]);
 break;
-case 85:this.$ = [];
+case 85:this.$ = new yy.Obj($$[$0-2], $$[$0-3].generated);
 break;
-case 86:this.$ = [$$[$0]];
+case 86:this.$ = [];
 break;
-case 87:this.$ = $$[$0-2].concat($$[$0]);
+case 87:this.$ = [$$[$0]];
 break;
-case 88:this.$ = $$[$0-3].concat($$[$0]);
+case 88:this.$ = $$[$0-2].concat($$[$0]);
 break;
-case 89:this.$ = $$[$0-5].concat($$[$0-2]);
+case 89:this.$ = $$[$0-3].concat($$[$0]);
 break;
-case 90:this.$ = new yy.Class;
+case 90:this.$ = $$[$0-5].concat($$[$0-2]);
 break;
-case 91:this.$ = new yy.Class(null, null, $$[$0]);
+case 91:this.$ = new yy.Class;
 break;
-case 92:this.$ = new yy.Class(null, $$[$0]);
+case 92:this.$ = new yy.Class(null, null, $$[$0]);
 break;
-case 93:this.$ = new yy.Class(null, $$[$0-1], $$[$0]);
+case 93:this.$ = new yy.Class(null, $$[$0]);
 break;
-case 94:this.$ = new yy.Class($$[$0]);
+case 94:this.$ = new yy.Class(null, $$[$0-1], $$[$0]);
 break;
-case 95:this.$ = new yy.Class($$[$0-1], null, $$[$0]);
+case 95:this.$ = new yy.Class($$[$0]);
 break;
-case 96:this.$ = new yy.Class($$[$0-2], $$[$0]);
+case 96:this.$ = new yy.Class($$[$0-1], null, $$[$0]);
 break;
-case 97:this.$ = new yy.Class($$[$0-3], $$[$0-1], $$[$0]);
+case 97:this.$ = new yy.Class($$[$0-2], $$[$0]);
 break;
-case 98:this.$ = new yy.Call($$[$0-2], $$[$0], $$[$0-1]);
+case 98:this.$ = new yy.Class($$[$0-3], $$[$0-1], $$[$0]);
 break;
 case 99:this.$ = new yy.Call($$[$0-2], $$[$0], $$[$0-1]);
 break;
-case 100:this.$ = new yy.Call('super', [new yy.Splat(new yy.Literal('arguments'))]);
+case 100:this.$ = new yy.Call($$[$0-2], $$[$0], $$[$0-1]);
 break;
-case 101:this.$ = new yy.Call('super', $$[$0]);
+case 101:this.$ = new yy.Call('super', [new yy.Splat(new yy.Literal('arguments'))]);
 break;
-case 102:this.$ = false;
+case 102:this.$ = new yy.Call('super', $$[$0]);
 break;
-case 103:this.$ = true;
+case 103:this.$ = false;
 break;
-case 104:this.$ = [];
+case 104:this.$ = true;
 break;
-case 105:this.$ = $$[$0-2];
+case 105:this.$ = [];
 break;
-case 106:this.$ = new yy.Value(new yy.Literal('this'));
+case 106:this.$ = $$[$0-2];
 break;
 case 107:this.$ = new yy.Value(new yy.Literal('this'));
 break;
-case 108:this.$ = new yy.Value(new yy.Literal('this'), [new yy.Access($$[$0])], 'this');
+case 108:this.$ = new yy.Value(new yy.Literal('this'));
 break;
-case 109:this.$ = new yy.Arr([]);
+case 109:this.$ = new yy.Value(new yy.Literal('this'), [new yy.Access($$[$0])], 'this');
 break;
-case 110:this.$ = new yy.Arr($$[$0-2]);
+case 110:this.$ = new yy.Arr([]);
 break;
-case 111:this.$ = 'inclusive';
+case 111:this.$ = new yy.Arr($$[$0-2]);
 break;
-case 112:this.$ = 'exclusive';
+case 112:this.$ = 'inclusive';
 break;
-case 113:this.$ = new yy.Range($$[$0-3], $$[$0-1], $$[$0-2]);
+case 113:this.$ = 'exclusive';
 break;
-case 114:this.$ = new yy.Range($$[$0-2], $$[$0], $$[$0-1]);
+case 114:this.$ = new yy.Range($$[$0-3], $$[$0-1], $$[$0-2]);
 break;
-case 115:this.$ = new yy.Range($$[$0-1], null, $$[$0]);
+case 115:this.$ = new yy.Range($$[$0-2], $$[$0], $$[$0-1]);
 break;
-case 116:this.$ = new yy.Range(null, $$[$0], $$[$0-1]);
+case 116:this.$ = new yy.Range($$[$0-1], null, $$[$0]);
 break;
-case 117:this.$ = [$$[$0]];
+case 117:this.$ = new yy.Range(null, $$[$0], $$[$0-1]);
 break;
-case 118:this.$ = $$[$0-2].concat($$[$0]);
+case 118:this.$ = new yy.Range(null, null, $$[$0]);
 break;
-case 119:this.$ = $$[$0-3].concat($$[$0]);
+case 119:this.$ = [$$[$0]];
 break;
-case 120:this.$ = $$[$0-2];
+case 120:this.$ = $$[$0-2].concat($$[$0]);
 break;
-case 121:this.$ = $$[$0-5].concat($$[$0-2]);
+case 121:this.$ = $$[$0-3].concat($$[$0]);
 break;
-case 122:this.$ = $$[$0];
+case 122:this.$ = $$[$0-2];
 break;
-case 123:this.$ = $$[$0];
+case 123:this.$ = $$[$0-5].concat($$[$0-2]);
 break;
 case 124:this.$ = $$[$0];
 break;
-case 125:this.$ = [].concat($$[$0-2], $$[$0]);
+case 125:this.$ = $$[$0];
+break;
+case 126:this.$ = $$[$0];
 break;
-case 126:this.$ = new yy.Try($$[$0]);
+case 127:this.$ = [].concat($$[$0-2], $$[$0]);
 break;
-case 127:this.$ = new yy.Try($$[$0-1], $$[$0][0], $$[$0][1]);
+case 128:this.$ = new yy.Try($$[$0]);
 break;
-case 128:this.$ = new yy.Try($$[$0-2], null, null, $$[$0]);
+case 129:this.$ = new yy.Try($$[$0-1], $$[$0][0], $$[$0][1]);
 break;
-case 129:this.$ = new yy.Try($$[$0-3], $$[$0-2][0], $$[$0-2][1], $$[$0]);
+case 130:this.$ = new yy.Try($$[$0-2], null, null, $$[$0]);
 break;
-case 130:this.$ = [$$[$0-1], $$[$0]];
+case 131:this.$ = new yy.Try($$[$0-3], $$[$0-2][0], $$[$0-2][1], $$[$0]);
 break;
-case 131:this.$ = new yy.Throw($$[$0]);
+case 132:this.$ = [$$[$0-1], $$[$0]];
 break;
-case 132:this.$ = new yy.Parens($$[$0-1]);
+case 133:this.$ = new yy.Throw($$[$0]);
 break;
-case 133:this.$ = new yy.Parens($$[$0-2]);
+case 134:this.$ = new yy.Parens($$[$0-1]);
 break;
-case 134:this.$ = new yy.While($$[$0]);
+case 135:this.$ = new yy.Parens($$[$0-2]);
 break;
-case 135:this.$ = new yy.While($$[$0-2], {
+case 136:this.$ = new yy.While($$[$0]);
+break;
+case 137:this.$ = new yy.While($$[$0-2], {
           guard: $$[$0]
         });
 break;
-case 136:this.$ = new yy.While($$[$0], {
+case 138:this.$ = new yy.While($$[$0], {
           invert: true
         });
 break;
-case 137:this.$ = new yy.While($$[$0-2], {
+case 139:this.$ = new yy.While($$[$0-2], {
           invert: true,
           guard: $$[$0]
         });
 break;
-case 138:this.$ = $$[$0-1].addBody($$[$0]);
+case 140:this.$ = $$[$0-1].addBody($$[$0]);
 break;
-case 139:this.$ = $$[$0].addBody(yy.Block.wrap([$$[$0-1]]));
+case 141:this.$ = $$[$0].addBody(yy.Block.wrap([$$[$0-1]]));
 break;
-case 140:this.$ = $$[$0].addBody(yy.Block.wrap([$$[$0-1]]));
+case 142:this.$ = $$[$0].addBody(yy.Block.wrap([$$[$0-1]]));
 break;
-case 141:this.$ = $$[$0];
+case 143:this.$ = $$[$0];
 break;
-case 142:this.$ = new yy.While(new yy.Literal('true')).addBody($$[$0]);
+case 144:this.$ = new yy.While(new yy.Literal('true')).addBody($$[$0]);
 break;
-case 143:this.$ = new yy.While(new yy.Literal('true')).addBody(yy.Block.wrap([$$[$0]]));
+case 145:this.$ = new yy.While(new yy.Literal('true')).addBody(yy.Block.wrap([$$[$0]]));
 break;
-case 144:this.$ = new yy.For($$[$0-1], $$[$0]);
+case 146:this.$ = new yy.For($$[$0-1], $$[$0]);
 break;
-case 145:this.$ = new yy.For($$[$0-1], $$[$0]);
+case 147:this.$ = new yy.For($$[$0-1], $$[$0]);
 break;
-case 146:this.$ = new yy.For($$[$0], $$[$0-1]);
+case 148:this.$ = new yy.For($$[$0], $$[$0-1]);
 break;
-case 147:this.$ = {
+case 149:this.$ = {
           source: new yy.Value($$[$0])
         };
 break;
-case 148:this.$ = (function () {
+case 150:this.$ = (function () {
         $$[$0].own = $$[$0-1].own;
         $$[$0].name = $$[$0-1][0];
         $$[$0].index = $$[$0-1][1];
         return $$[$0];
       }());
 break;
-case 149:this.$ = $$[$0];
+case 151:this.$ = $$[$0];
 break;
-case 150:this.$ = (function () {
+case 152:this.$ = (function () {
         $$[$0].own = true;
         return $$[$0];
       }());
 break;
-case 151:this.$ = $$[$0];
+case 153:this.$ = $$[$0];
 break;
-case 152:this.$ = new yy.Value($$[$0]);
+case 154:this.$ = new yy.Value($$[$0]);
 break;
-case 153:this.$ = new yy.Value($$[$0]);
+case 155:this.$ = new yy.Value($$[$0]);
 break;
-case 154:this.$ = [$$[$0]];
+case 156:this.$ = [$$[$0]];
 break;
-case 155:this.$ = [$$[$0-2], $$[$0]];
+case 157:this.$ = [$$[$0-2], $$[$0]];
 break;
-case 156:this.$ = {
+case 158:this.$ = {
           source: $$[$0]
         };
 break;
-case 157:this.$ = {
+case 159:this.$ = {
           source: $$[$0],
           object: true
         };
 break;
-case 158:this.$ = {
+case 160:this.$ = {
           source: $$[$0-2],
           guard: $$[$0]
         };
 break;
-case 159:this.$ = {
+case 161:this.$ = {
           source: $$[$0-2],
           guard: $$[$0],
           object: true
         };
 break;
-case 160:this.$ = {
+case 162:this.$ = {
           source: $$[$0-2],
           step: $$[$0]
         };
 break;
-case 161:this.$ = {
+case 163:this.$ = {
           source: $$[$0-4],
           guard: $$[$0-2],
           step: $$[$0]
         };
 break;
-case 162:this.$ = {
+case 164:this.$ = {
           source: $$[$0-4],
           step: $$[$0-2],
           guard: $$[$0]
         };
 break;
-case 163:this.$ = new yy.Switch($$[$0-3], $$[$0-1]);
+case 165:this.$ = new yy.Switch($$[$0-3], $$[$0-1]);
 break;
-case 164:this.$ = new yy.Switch($$[$0-5], $$[$0-3], $$[$0-1]);
+case 166:this.$ = new yy.Switch($$[$0-5], $$[$0-3], $$[$0-1]);
 break;
-case 165:this.$ = new yy.Switch(null, $$[$0-1]);
+case 167:this.$ = new yy.Switch(null, $$[$0-1]);
 break;
-case 166:this.$ = new yy.Switch(null, $$[$0-3], $$[$0-1]);
+case 168:this.$ = new yy.Switch(null, $$[$0-3], $$[$0-1]);
 break;
-case 167:this.$ = $$[$0];
+case 169:this.$ = $$[$0];
 break;
-case 168:this.$ = $$[$0-1].concat($$[$0]);
+case 170:this.$ = $$[$0-1].concat($$[$0]);
 break;
-case 169:this.$ = [[$$[$0-1], $$[$0]]];
+case 171:this.$ = [[$$[$0-1], $$[$0]]];
 break;
-case 170:this.$ = [[$$[$0-2], $$[$0-1]]];
+case 172:this.$ = [[$$[$0-2], $$[$0-1]]];
 break;
-case 171:this.$ = new yy.If($$[$0-1], $$[$0], {
+case 173:this.$ = new yy.If($$[$0-1], $$[$0], {
           type: $$[$0-2]
         });
 break;
-case 172:this.$ = $$[$0-4].addElse(new yy.If($$[$0-1], $$[$0], {
+case 174:this.$ = $$[$0-4].addElse(new yy.If($$[$0-1], $$[$0], {
           type: $$[$0-2]
         }));
 break;
-case 173:this.$ = $$[$0];
+case 175:this.$ = $$[$0];
 break;
-case 174:this.$ = $$[$0-2].addElse($$[$0]);
+case 176:this.$ = $$[$0-2].addElse($$[$0]);
 break;
-case 175:this.$ = new yy.If($$[$0], yy.Block.wrap([$$[$0-2]]), {
+case 177:this.$ = new yy.If($$[$0], yy.Block.wrap([$$[$0-2]]), {
           type: $$[$0-1],
           statement: true
         });
 break;
-case 176:this.$ = new yy.If($$[$0], yy.Block.wrap([$$[$0-2]]), {
+case 178:this.$ = new yy.If($$[$0], yy.Block.wrap([$$[$0-2]]), {
           type: $$[$0-1],
           statement: true
         });
 break;
-case 177:this.$ = new yy.Op($$[$0-1], $$[$0]);
-break;
-case 178:this.$ = new yy.Op('-', $$[$0]);
+case 179:this.$ = new yy.Op($$[$0-1], $$[$0]);
 break;
-case 179:this.$ = new yy.Op('+', $$[$0]);
+case 180:this.$ = new yy.Op('-', $$[$0]);
 break;
-case 180:this.$ = new yy.Op('--', $$[$0]);
+case 181:this.$ = new yy.Op('+', $$[$0]);
 break;
-case 181:this.$ = new yy.Op('++', $$[$0]);
+case 182:this.$ = new yy.Op('--', $$[$0]);
 break;
-case 182:this.$ = new yy.Op('--', $$[$0-1], null, true);
+case 183:this.$ = new yy.Op('++', $$[$0]);
 break;
-case 183:this.$ = new yy.Op('++', $$[$0-1], null, true);
+case 184:this.$ = new yy.Op('--', $$[$0-1], null, true);
 break;
-case 184:this.$ = new yy.Existence($$[$0-1]);
+case 185:this.$ = new yy.Op('++', $$[$0-1], null, true);
 break;
-case 185:this.$ = new yy.Op('+', $$[$0-2], $$[$0]);
+case 186:this.$ = new yy.Existence($$[$0-1]);
 break;
-case 186:this.$ = new yy.Op('-', $$[$0-2], $$[$0]);
+case 187:this.$ = new yy.Op('+', $$[$0-2], $$[$0]);
 break;
-case 187:this.$ = new yy.Op($$[$0-1], $$[$0-2], $$[$0]);
-break;
-case 188:this.$ = new yy.Op($$[$0-1], $$[$0-2], $$[$0]);
+case 188:this.$ = new yy.Op('-', $$[$0-2], $$[$0]);
 break;
 case 189:this.$ = new yy.Op($$[$0-1], $$[$0-2], $$[$0]);
 break;
 case 190:this.$ = new yy.Op($$[$0-1], $$[$0-2], $$[$0]);
 break;
-case 191:this.$ = (function () {
+case 191:this.$ = new yy.Op($$[$0-1], $$[$0-2], $$[$0]);
+break;
+case 192:this.$ = new yy.Op($$[$0-1], $$[$0-2], $$[$0]);
+break;
+case 193:this.$ = (function () {
         if ($$[$0-1].charAt(0) === '!') {
           return new yy.Op($$[$0-1].slice(1), $$[$0-2], $$[$0]).invert();
         } else {
@@ -4408,207 +4451,124 @@ case 191:this.$ = (function () {
         }
       }());
 break;
-case 192:this.$ = new yy.Assign($$[$0-2], $$[$0], $$[$0-1]);
+case 194:this.$ = new yy.Assign($$[$0-2], $$[$0], $$[$0-1]);
 break;
-case 193:this.$ = new yy.Assign($$[$0-4], $$[$0-1], $$[$0-3]);
+case 195:this.$ = new yy.Assign($$[$0-4], $$[$0-1], $$[$0-3]);
 break;
-case 194:this.$ = new yy.Extends($$[$0-2], $$[$0]);
+case 196:this.$ = new yy.Extends($$[$0-2], $$[$0]);
 break;
 }
 },
-table: [{1:[2,1],3:1,4:2,5:3,7:4,8:6,9:7,10:19,11:20,12:21,13:[1,22],14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,24:18,25:[1,5],27:59,28:[1,70],29:49,30:[1,68],31:[1,69],32:24,33:[1,50],34:[1,51],35:[1,52],36:23,41:60,42:[1,44],43:[1,46],44:[1,29],47:30,48:[1,57],49:[1,58],55:47,56:48,58:36,60:25,61:26,62:27,73:[1,67],76:[1,43],80:[1,28],85:[1,55],86:[1,56],87:[1,54],93:[1,38],97:[1,45],98:[1,53],100:39,101:[1,62],103:[1,63],104:40,105:[1,64],106:41,107:[1,65],108:66,116:[1,42],121:37,122:[1,61],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{1:[3]},{1:[2,2],6:[1,71]},{6:[1,72]},{1:[2,4],6:[2,4],26:[2,4],99:[2,4]},{4:74,7:4,8:6,9:7,10:19,11:20,12:21,13:[1,22],14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,24:18,26:[1,73],27:59,28:[1,70],29:49,30:[1,68],31:[1,69],32:24,33:[1,50],34:[1,51],35:[1,52],36:23,41:60,42:[1,44],43:[1,46],44:[1,29],47:30,48:[1,57],49:[1,58],55:47,56:48,58:36,60:25,61:26,62:27,73:[1,67],76:[1,43],80:[1,28],85:[1,55],86:[1,56],87:[1,54],93:[1,38],97:[1,45],98:[1,53],100:39,101:[1,62],103:[1,63],104:40,105:[1,64],106:41,107:[1,65],108:66,116:[1,42],121:37,122:[1,61],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{1:[2,7],6:[2,7],26:[2,7],99:[2,7],100:84,101:[1,62],103:[1,63],106:85,107:[1,65],108:66,123:[1,83],125:[1,77],126:[1,76],129:[1,75],130:[1,78],131:[1,79],132:[1,80],133:[1,81],134:[1,82]},{1:[2,8],6:[2,8],26:[2,8],99:[2,8],100:87,101:[1,62],103:[1,63],106:88,107:[1,65],108:66,123:[1,86]},{1:[2,13],6:[2,13],25:[2,13],26:[2,13],46:[2,13],51:[2,13],54:[2,13],59:90,63:[1,92],64:[1,93],65:[1,94],66:95,67:[1,96],69:[2,13],70:[1,97],71:[1,98],75:[2,13],78:89,81:[1,91],82:[2,102],83:[2,13],88:[2,13],90:[2,13],99:[2,13],101:[2,13],102:[2,13],103:[2,13],107:[2,13],115:[2,13],123:[2,13],125:[2,13],126:[2,13],129:[2,13],130:[2,13],131:[2,13],132:[2,13],133:[2,13],134:[2,13]},{1:[2,14],6:[2,14],25:[2,14],26:[2,14],46:[2,14],51:[2,14],54:[2,14],59:100,63:[1,92],64:[1,93],65:[1,94],66:95,67:[1,96],69:[2,14],70:[1,97],71:[1,98],75:[2,14],78:99,81:[1,91],82:[2,102],83:[2,14],88:[2,14],90:[2,14],99:[2,14],101:[2,14],102:[2,14],103:[2,14],107:[2,14],115:[2,14],123:[2,14],125:[2,14],126:[2,14],129:[2,14],130:[2,14],131:[2,14],132:[2,14],133:[2,14],134:[2,14]},{1:[2,15],6:[2,15],25:[2,15],26:[2,15],46:[2,15],51:[2,15],54:[2,15],69:[2,15],75:[2,15],83:[2,15],88:[2,15],90:[2,15],99:[2,15],101:[2,15],102:[2,15],103:[2,15],107:[2,15],115:[2,15],123:[2,15],125:[2,15],126:[2,15],129:[2,15],130:[2,15],131:[2,15],132:[2,15],133:[2,15],134:[2,15]},{1:[2,16],6:[2,16],25:[2,16],26:[2,16],46:[2,16],51:[2,16],54:[2,16],69:[2,16],75:[2,16],83:[2,16],88:[2,16],90:[2,16],99:[2,16],101:[2,16],102:[2,16],103:[2,16],107:[2,16],115:[2,16],123:[2,16],125:[2,16],126:[2,16],129:[2,16],130:[2,16],131:[2,16],132:[2,16],133:[2,16],134:[2,16]},{1:[2,17],6:[2,17],25:[2,17],26:[2,17],46:[2,17],51:[2,17],54:[2,17],69:[2,17],75:[2,17],83:[2,17],88:[2,17],90:[2,17],99:[2,17],101:[2,17],102:[2,17],103:[2,17],107:[2,17],115:[2,17],123:[2,17],125:[2,17],126:[2,17],129:[2,17],130:[2,17],131:[2,17],132:[2,17],133:[2,17],134:[2,17]},{1:[2,18],6:[2,18],25:[2,18],26:[2,18],46:[2,18],51:[2,18],54:[2,18],69:[2,18],75:[2,18],83:[2,18],88:[2,18],90:[2,18],99:[2,18],101:[2,18],102:[2,18],103:[2,18],107:[2,18],115:[2,18],123:[2,18],125:[2,18],126:[2,18],129:[2,18],130:[2,18],131:[2,18],132:[2,18],133:[2,18],134:[2,18]},{1:[2,19],6:[2,19],25:[2,19],26:[2,19],46:[2,19],51:[2,19],54:[2,19],69:[2,19],75:[2,19],83:[2,19],88:[2,19],90:[2,19],99:[2,19],101:[2,19],102:[2,19],103:[2,19],107:[2,19],115:[2,19],123:[2,19],125:[2,19],126:[2,19],129:[2,19],130:[2,19],131:[2,19],132:[2,19],133:[2,19],134:[2,19]},{1:[2,20],6:[2,20],25:[2,20],26:[2,20],46:[2,20],51:[2,20],54:[2,20],69:[2,20],75:[2,20],83:[2,20],88:[2,20],90:[2,20],99:[2,20],101:[2,20],102:[2,20],103:[2,20],107:[2,20],115:[2,20],123:[2,20],125:[2,20],126:[2,20],129:[2,20],130:[2,20],131:[2,20],132:[2,20],133:[2,20],134:[2,20]},{1:[2,21],6:[2,21],25:[2,21],26:[2,21],46:[2,21],51:[2,21],54:[2,21],69:[2,21],75:[2,21],83:[2,21],88:[2,21],90:[2,21],99:[2,21],101:[2,21],102:[2,21],103:[2,21],107:[2,21],115:[2,21],123:[2,21],125:[2,21],126:[2,21],129:[2,21],130:[2,21],131:[2,21],132:[2,21],133:[2,21],134:[2,21]},{1:[2,22],6:[2,22],25:[2,22],26:[2,22],46:[2,22],51:[2,22],54:[2,22],69:[2,22],75:[2,22],83:[2,22],88:[2,22],90:[2,22],99:[2,22],101:[2,22],102:[2,22],103:[2,22],107:[2,22],115:[2,22],123:[2,22],125:[2,22],126:[2,22],129:[2,22],130:[2,22],131:[2,22],132:[2,22],133:[2,22],134:[2,22]},{1:[2,23],6:[2,23],25:[2,23],26:[2,23],46:[2,23],51:[2,23],54:[2,23],69:[2,23],75:[2,23],83:[2,23],88:[2,23],90:[2,23],99:[2,23],101:[2,23],102:[2,23],103:[2,23],107:[2,23],115:[2,23],123:[2,23],125:[2,23],126:[2,23],129:[2,23],130:[2,23],131:[2,23],132:[2,23],133:[2,23],134:[2,23]},{1:[2,9],6:[2,9],26:[2,9],99:[2,9],101:[2,9],103:[2,9],107:[2,9],123:[2,9]},{1:[2,10],6:[2,10],26:[2,10],99:[2,10],101:[2,10],103:[2,10],107:[2,10],123:[2,10]},{1:[2,11],6:[2,11],26:[2,11],99:[2,11],101:[2,11],103:[2,11],107:[2,11],123:[2,11]},{1:[2,12],6:[2,12],26:[2,12],99:[2,12],101:[2,12],103:[2,12],107:[2,12],123:[2,12]},{1:[2,69],6:[2,69],25:[2,69],26:[2,69],37:[1,101],46:[2,69],51:[2,69],54:[2,69],63:[2,69],64:[2,69],65:[2,69],67:[2,69],69:[2,69],70:[2,69],71:[2,69],75:[2,69],81:[2,69],82:[2,69],83:[2,69],88:[2,69],90:[2,69],99:[2,69],101:[2,69],102:[2,69],103:[2,69],107:[2,69],115:[2,69],123:[2,69],125:[2,69],126:[2,69],129:[2,69],130:[2,69],131:[2,69],132:[2,69],133:[2,69],134:[2,69]},{1:[2,70],6:[2,70],25:[2,70],26:[2,70],46:[2,70],51:[2,70],54:[2,70],63:[2,70],64:[2,70],65:[2,70],67:[2,70],69:[2,70],70:[2,70],71:[2,70],75:[2,70],81:[2,70],82:[2,70],83:[2,70],88:[2,70],90:[2,70],99:[2,70],101:[2,70],102:[2,70],103:[2,70],107:[2,70],115:[2,70],123:[2,70],125:[2,70],126:[2,70],129:[2,70],130:[2,70],131:[2,70],132:[2,70],133:[2,70],134:[2,70]},{1:[2,71],6:[2,71],25:[2,71],26:[2,71],46:[2,71],51:[2,71],54:[2,71],63:[2,71],64:[2,71],65:[2,71],67:[2,71],69:[2,71],70:[2,71],71:[2,71],75:[2,71],81:[2,71],82:[2,71],83:[2,71],88:[2,71],90:[2,71],99:[2,71],101:[2,71],102:[2,71],103:[2,71],107:[2,71],115:[2,71],123:[2,71],125:[2,71],126:[2,71],129:[2,71],130:[2,71],131:[2,71],132:[2,71],133:[2,71],134:[2,71]},{1:[2,72],6:[2,72],25:[2,72],26:[2,72],46:[2,72],51:[2,72],54:[2,72],63:[2,72],64:[2,72],65:[2,72],67:[2,72],69:[2,72],70:[2,72],71:[2,72],75:[2,72],81:[2,72],82:[2,72],83:[2,72],88:[2,72],90:[2,72],99:[2,72],101:[2,72],102:[2,72],103:[2,72],107:[2,72],115:[2,72],123:[2,72],125:[2,72],126:[2,72],129:[2,72],130:[2,72],131:[2,72],132:[2,72],133:[2,72],134:[2,72]},{1:[2,73],6:[2,73],25:[2,73],26:[2,73],46:[2,73],51:[2,73],54:[2,73],63:[2,73],64:[2,73],65:[2,73],67:[2,73],69:[2,73],70:[2,73],71:[2,73],75:[2,73],81:[2,73],82:[2,73],83:[2,73],88:[2,73],90:[2,73],99:[2,73],101:[2,73],102:[2,73],103:[2,73],107:[2,73],115:[2,73],123:[2,73],125:[2,73],126:[2,73],129:[2,73],130:[2,73],131:[2,73],132:[2,73],133:[2,73],134:[2,73]},{1:[2,100],6:[2,100],25:[2,100],26:[2,100],46:[2,100],51:[2,100],54:[2,100],63:[2,100],64:[2,100],65:[2,100],67:[2,100],69:[2,100],70:[2,100],71:[2,100],75:[2,100],79:102,81:[2,100],82:[1,103],83:[2,100],88:[2,100],90:[2,100],99:[2,100],101:[2,100],102:[2,100],103:[2,100],107:[2,100],115:[2,100],123:[2,100],125:[2,100],126:[2,100],129:[2,100],130:[2,100],131:[2,100],132:[2,100],133:[2,100],134:[2,100]},{27:107,28:[1,70],41:108,45:104,46:[2,51],51:[2,51],52:105,53:106,55:109,56:110,73:[1,67],86:[1,111],87:[1,112]},{5:113,25:[1,5]},{8:114,9:115,10:19,11:20,12:21,13:[1,22],14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,24:18,27:59,28:[1,70],29:49,30:[1,68],31:[1,69],32:24,33:[1,50],34:[1,51],35:[1,52],36:23,41:60,42:[1,44],43:[1,46],44:[1,29],47:30,48:[1,57],49:[1,58],55:47,56:48,58:36,60:25,61:26,62:27,73:[1,67],76:[1,43],80:[1,28],85:[1,55],86:[1,56],87:[1,54],93:[1,38],97:[1,45],98:[1,53],100:39,101:[1,62],103:[1,63],104:40,105:[1,64],106:41,107:[1,65],108:66,116:[1,42],121:37,122:[1,61],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{8:116,9:115,10:19,11:20,12:21,13:[1,22],14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,24:18,27:59,28:[1,70],29:49,30:[1,68],31:[1,69],32:24,33:[1,50],34:[1,51],35:[1,52],36:23,41:60,42:[1,44],43:[1,46],44:[1,29],47:30,48:[1,57],49:[1,58],55:47,56:48,58:36,60:25,61:26,62:27,73:[1,67],76:[1,43],80:[1,28],85:[1,55],86:[1,56],87:[1,54],93:[1,38],97:[1,45],98:[1,53],100:39,101:[1,62],103:[1,63],104:40,105:[1,64],106:41,107:[1,65],108:66,116:[1,42],121:37,122:[1,61],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{8:117,9:115,10:19,11:20,12:21,13:[1,22],14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,24:18,27:59,28:[1,70],29:49,30:[1,68],31:[1,69],32:24,33:[1,50],34:[1,51],35:[1,52],36:23,41:60,42:[1,44],43:[1,46],44:[1,29],47:30,48:[1,57],49:[1,58],55:47,56:48,58:36,60:25,61:26,62:27,73:[1,67],76:[1,43],80:[1,28],85:[1,55],86:[1,56],87:[1,54],93:[1,38],97:[1,45],98:[1,53],100:39,101:[1,62],103:[1,63],104:40,105:[1,64],106:41,107:[1,65],108:66,116:[1,42],121:37,122:[1,61],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{14:119,15:120,27:59,28:[1,70],29:49,30:[1,68],31:[1,69],32:24,33:[1,50],34:[1,51],35:[1,52],36:121,41:60,55:47,56:48,58:118,60:25,61:26,62:27,73:[1,67],80:[1,28],85:[1,55],86:[1,56],87:[1,54],98:[1,53]},{14:119,15:120,27:59,28:[1,70],29:49,30:[1,68],31:[1,69],32:24,33:[1,50],34:[1,51],35:[1,52],36:121,41:60,55:47,56:48,58:122,60:25,61:26,62:27,73:[1,67],80:[1,28],85:[1,55],86:[1,56],87:[1,54],98:[1,53]},{1:[2,66],6:[2,66],25:[2,66],26:[2,66],37:[2,66],46:[2,66],51:[2,66],54:[2,66],63:[2,66],64:[2,66],65:[2,66],67:[2,66],69:[2,66],70:[2,66],71:[2,66],75:[2,66],77:[1,126],81:[2,66],82:[2,66],83:[2,66],88:[2,66],90:[2,66],99:[2,66],101:[2,66],102:[2,66],103:[2,66],107:[2,66],115:[2,66],123:[2,66],125:[2,66],126:[2,66],127:[1,123],128:[1,124],129:[2,66],130:[2,66],131:[2,66],132:[2,66],133:[2,66],134:[2,66],135:[1,125]},{1:[2,173],6:[2,173],25:[2,173],26:[2,173],46:[2,173],51:[2,173],54:[2,173],69:[2,173],75:[2,173],83:[2,173],88:[2,173],90:[2,173],99:[2,173],101:[2,173],102:[2,173],103:[2,173],107:[2,173],115:[2,173],118:[1,127],123:[2,173],125:[2,173],126:[2,173],129:[2,173],130:[2,173],131:[2,173],132:[2,173],133:[2,173],134:[2,173]},{5:128,25:[1,5]},{5:129,25:[1,5]},{1:[2,141],6:[2,141],25:[2,141],26:[2,141],46:[2,141],51:[2,141],54:[2,141],69:[2,141],75:[2,141],83:[2,141],88:[2,141],90:[2,141],99:[2,141],101:[2,141],102:[2,141],103:[2,141],107:[2,141],115:[2,141],123:[2,141],125:[2,141],126:[2,141],129:[2,141],130:[2,141],131:[2,141],132:[2,141],133:[2,141],134:[2,141]},{5:130,25:[1,5]},{8:131,9:115,10:19,11:20,12:21,13:[1,22],14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,24:18,25:[1,132],27:59,28:[1,70],29:49,30:[1,68],31:[1,69],32:24,33:[1,50],34:[1,51],35:[1,52],36:23,41:60,42:[1,44],43:[1,46],44:[1,29],47:30,48:[1,57],49:[1,58],55:47,56:48,58:36,60:25,61:26,62:27,73:[1,67],76:[1,43],80:[1,28],85:[1,55],86:[1,56],87:[1,54],93:[1,38],97:[1,45],98:[1,53],100:39,101:[1,62],103:[1,63],104:40,105:[1,64],106:41,107:[1,65],108:66,116:[1,42],121:37,122:[1,61],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{1:[2,90],5:133,6:[2,90],14:119,15:120,25:[1,5],26:[2,90],27:59,28:[1,70],29:49,30:[1,68],31:[1,69],32:24,33:[1,50],34:[1,51],35:[1,52],36:121,41:60,46:[2,90],51:[2,90],54:[2,90],55:47,56:48,58:135,60:25,61:26,62:27,69:[2,90],73:[1,67],75:[2,90],77:[1,134],80:[1,28],83:[2,90],85:[1,55],86:[1,56],87:[1,54],88:[2,90],90:[2,90],98:[1,53],99:[2,90],101:[2,90],102:[2,90],103:[2,90],107:[2,90],115:[2,90],123:[2,90],125:[2,90],126:[2,90],129:[2,90],130:[2,90],131:[2,90],132:[2,90],133:[2,90],134:[2,90]},{1:[2,43],6:[2,43],8:136,9:115,10:19,11:20,12:21,13:[1,22],14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,24:18,26:[2,43],27:59,28:[1,70],29:49,30:[1,68],31:[1,69],32:24,33:[1,50],34:[1,51],35:[1,52],36:23,41:60,42:[1,44],43:[1,46],44:[1,29],47:30,48:[1,57],49:[1,58],55:47,56:48,58:36,60:25,61:26,62:27,73:[1,67],76:[1,43],80:[1,28],85:[1,55],86:[1,56],87:[1,54],93:[1,38],97:[1,45],98:[1,53],99:[2,43],100:39,101:[2,43],103:[2,43],104:40,105:[1,64],106:41,107:[2,43],108:66,116:[1,42],121:37,122:[1,61],123:[2,43],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{8:137,9:115,10:19,11:20,12:21,13:[1,22],14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,24:18,27:59,28:[1,70],29:49,30:[1,68],31:[1,69],32:24,33:[1,50],34:[1,51],35:[1,52],36:23,41:60,42:[1,44],43:[1,46],44:[1,29],47:30,48:[1,57],49:[1,58],55:47,56:48,58:36,60:25,61:26,62:27,73:[1,67],76:[1,43],80:[1,28],85:[1,55],86:[1,56],87:[1,54],93:[1,38],97:[1,45],98:[1,53],100:39,101:[1,62],103:[1,63],104:40,105:[1,64],106:41,107:[1,65],108:66,116:[1,42],121:37,122:[1,61],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{1:[2,44],6:[2,44],25:[2,44],26:[2,44],51:[2,44],75:[2,44],99:[2,44],101:[2,44],103:[2,44],107:[2,44],123:[2,44]},{1:[2,67],6:[2,67],25:[2,67],26:[2,67],37:[2,67],46:[2,67],51:[2,67],54:[2,67],63:[2,67],64:[2,67],65:[2,67],67:[2,67],69:[2,67],70:[2,67],71:[2,67],75:[2,67],81:[2,67],82:[2,67],83:[2,67],88:[2,67],90:[2,67],99:[2,67],101:[2,67],102:[2,67],103:[2,67],107:[2,67],115:[2,67],123:[2,67],125:[2,67],126:[2,67],129:[2,67],130:[2,67],131:[2,67],132:[2,67],133:[2,67],134:[2,67]},{1:[2,68],6:[2,68],25:[2,68],26:[2,68],37:[2,68],46:[2,68],51:[2,68],54:[2,68],63:[2,68],64:[2,68],65:[2,68],67:[2,68],69:[2,68],70:[2,68],71:[2,68],75:[2,68],81:[2,68],82:[2,68],83:[2,68],88:[2,68],90:[2,68],99:[2,68],101:[2,68],102:[2,68],103:[2,68],107:[2,68],115:[2,68],123:[2,68],125:[2,68],126:[2,68],129:[2,68],130:[2,68],131:[2,68],132:[2,68],133:[2,68],134:[2,68]},{1:[2,29],6:[2,29],25:[2,29],26:[2,29],46:[2,29],51:[2,29],54:[2,29],63:[2,29],64:[2,29],65:[2,29],67:[2,29],69:[2,29],70:[2,29],71:[2,29],75:[2,29],81:[2,29],82:[2,29],83:[2,29],88:[2,29],90:[2,29],99:[2,29],101:[2,29],102:[2,29],103:[2,29],107:[2,29],115:[2,29],123:[2,29],125:[2,29],126:[2,29],129:[2,29],130:[2,29],131:[2,29],132:[2,29],133:[2,29],134:[2,29]},{1:[2,30],6:[2,30],25:[2,30],26:[2,30],46:[2,30],51:[2,30],54:[2,30],63:[2,30],64:[2,30],65:[2,30],67:[2,30],69:[2,30],70:[2,30],71:[2,30],75:[2,30],81:[2,30],82:[2,30],83:[2,30],88:[2,30],90:[2,30],99:[2,30],101:[2,30],102:[2,30],103:[2,30],107:[2,30],115:[2,30],123:[2,30],125:[2,30],126:[2,30],129:[2,30],130:[2,30],131:[2,30],132:[2,30],133:[2,30],134:[2,30]},{1:[2,31],6:[2,31],25:[2,31],26:[2,31],46:[2,31],51:[2,31],54:[2,31],63:[2,31],64:[2,31],65:[2,31],67:[2,31],69:[2,31],70:[2,31],71:[2,31],75:[2,31],81:[2,31],82:[2,31],83:[2,31],88:[2,31],90:[2,31],99:[2,31],101:[2,31],102:[2,31],103:[2,31],107:[2,31],115:[2,31],123:[2,31],125:[2,31],126:[2,31],129:[2,31],130:[2,31],131:[2,31],132:[2,31],133:[2,31],134:[2,31]},{1:[2,32],6:[2,32],25:[2,32],26:[2,32],46:[2,32],51:[2,32],54:[2,32],63:[2,32],64:[2,32],65:[2,32],67:[2,32],69:[2,32],70:[2,32],71:[2,32],75:[2,32],81:[2,32],82:[2,32],83:[2,32],88:[2,32],90:[2,32],99:[2,32],101:[2,32],102:[2,32],103:[2,32],107:[2,32],115:[2,32],123:[2,32],125:[2,32],126:[2,32],129:[2,32],130:[2,32],131:[2,32],132:[2,32],133:[2,32],134:[2,32]},{4:138,7:4,8:6,9:7,10:19,11:20,12:21,13:[1,22],14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,24:18,25:[1,139],27:59,28:[1,70],29:49,30:[1,68],31:[1,69],32:24,33:[1,50],34:[1,51],35:[1,52],36:23,41:60,42:[1,44],43:[1,46],44:[1,29],47:30,48:[1,57],49:[1,58],55:47,56:48,58:36,60:25,61:26,62:27,73:[1,67],76:[1,43],80:[1,28],85:[1,55],86:[1,56],87:[1,54],93:[1,38],97:[1,45],98:[1,53],100:39,101:[1,62],103:[1,63],104:40,105:[1,64],106:41,107:[1,65],108:66,116:[1,42],121:37,122:[1,61],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{8:140,9:115,10:19,11:20,12:21,13:[1,22],14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,24:18,25:[1,144],27:59,28:[1,70],29:49,30:[1,68],31:[1,69],32:24,33:[1,50],34:[1,51],35:[1,52],36:23,41:60,42:[1,44],43:[1,46],44:[1,29],47:30,48:[1,57],49:[1,58],55:47,56:48,57:145,58:36,60:25,61:26,62:27,73:[1,67],76:[1,43],80:[1,28],84:142,85:[1,55],86:[1,56],87:[1,54],88:[1,141],91:143,93:[1,38],97:[1,45],98:[1,53],100:39,101:[1,62],103:[1,63],104:40,105:[1,64],106:41,107:[1,65],108:66,116:[1,42],121:37,122:[1,61],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{1:[2,106],6:[2,106],25:[2,106],26:[2,106],46:[2,106],51:[2,106],54:[2,106],63:[2,106],64:[2,106],65:[2,106],67:[2,106],69:[2,106],70:[2,106],71:[2,106],75:[2,106],81:[2,106],82:[2,106],83:[2,106],88:[2,106],90:[2,106],99:[2,106],101:[2,106],102:[2,106],103:[2,106],107:[2,106],115:[2,106],123:[2,106],125:[2,106],126:[2,106],129:[2,106],130:[2,106],131:[2,106],132:[2,106],133:[2,106],134:[2,106]},{1:[2,107],6:[2,107],25:[2,107],26:[2,107],27:146,28:[1,70],46:[2,107],51:[2,107],54:[2,107],63:[2,107],64:[2,107],65:[2,107],67:[2,107],69:[2,107],70:[2,107],71:[2,107],75:[2,107],81:[2,107],82:[2,107],83:[2,107],88:[2,107],90:[2,107],99:[2,107],101:[2,107],102:[2,107],103:[2,107],107:[2,107],115:[2,107],123:[2,107],125:[2,107],126:[2,107],129:[2,107],130:[2,107],131:[2,107],132:[2,107],133:[2,107],134:[2,107]},{25:[2,47]},{25:[2,48]},{1:[2,62],6:[2,62],25:[2,62],26:[2,62],37:[2,62],46:[2,62],51:[2,62],54:[2,62],63:[2,62],64:[2,62],65:[2,62],67:[2,62],69:[2,62],70:[2,62],71:[2,62],75:[2,62],77:[2,62],81:[2,62],82:[2,62],83:[2,62],88:[2,62],90:[2,62],99:[2,62],101:[2,62],102:[2,62],103:[2,62],107:[2,62],115:[2,62],123:[2,62],125:[2,62],126:[2,62],127:[2,62],128:[2,62],129:[2,62],130:[2,62],131:[2,62],132:[2,62],133:[2,62],134:[2,62],135:[2,62]},{1:[2,65],6:[2,65],25:[2,65],26:[2,65],37:[2,65],46:[2,65],51:[2,65],54:[2,65],63:[2,65],64:[2,65],65:[2,65],67:[2,65],69:[2,65],70:[2,65],71:[2,65],75:[2,65],77:[2,65],81:[2,65],82:[2,65],83:[2,65],88:[2,65],90:[2,65],99:[2,65],101:[2,65],102:[2,65],103:[2,65],107:[2,65],115:[2,65],123:[2,65],125:[2,65],126:[2,65],127:[2,65],128:[2,65],129:[2,65],130:[2,65],131:[2,65],132:[2,65],133:[2,65],134:[2,65],135:[2,65]},{8:147,9:115,10:19,11:20,12:21,13:[1,22],14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,24:18,27:59,28:[1,70],29:49,30:[1,68],31:[1,69],32:24,33:[1,50],34:[1,51],35:[1,52],36:23,41:60,42:[1,44],43:[1,46],44:[1,29],47:30,48:[1,57],49:[1,58],55:47,56:48,58:36,60:25,61:26,62:27,73:[1,67],76:[1,43],80:[1,28],85:[1,55],86:[1,56],87:[1,54],93:[1,38],97:[1,45],98:[1,53],100:39,101:[1,62],103:[1,63],104:40,105:[1,64],106:41,107:[1,65],108:66,116:[1,42],121:37,122:[1,61],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{8:148,9:115,10:19,11:20,12:21,13:[1,22],14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,24:18,27:59,28:[1,70],29:49,30:[1,68],31:[1,69],32:24,33:[1,50],34:[1,51],35:[1,52],36:23,41:60,42:[1,44],43:[1,46],44:[1,29],47:30,48:[1,57],49:[1,58],55:47,56:48,58:36,60:25,61:26,62:27,73:[1,67],76:[1,43],80:[1,28],85:[1,55],86:[1,56],87:[1,54],93:[1,38],97:[1,45],98:[1,53],100:39,101:[1,62],103:[1,63],104:40,105:[1,64],106:41,107:[1,65],108:66,116:[1,42],121:37,122:[1,61],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{8:149,9:115,10:19,11:20,12:21,13:[1,22],14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,24:18,27:59,28:[1,70],29:49,30:[1,68],31:[1,69],32:24,33:[1,50],34:[1,51],35:[1,52],36:23,41:60,42:[1,44],43:[1,46],44:[1,29],47:30,48:[1,57],49:[1,58],55:47,56:48,58:36,60:25,61:26,62:27,73:[1,67],76:[1,43],80:[1,28],85:[1,55],86:[1,56],87:[1,54],93:[1,38],97:[1,45],98:[1,53],100:39,101:[1,62],103:[1,63],104:40,105:[1,64],106:41,107:[1,65],108:66,116:[1,42],121:37,122:[1,61],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{5:150,8:151,9:115,10:19,11:20,12:21,13:[1,22],14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,24:18,25:[1,5],27:59,28:[1,70],29:49,30:[1,68],31:[1,69],32:24,33:[1,50],34:[1,51],35:[1,52],36:23,41:60,42:[1,44],43:[1,46],44:[1,29],47:30,48:[1,57],49:[1,58],55:47,56:48,58:36,60:25,61:26,62:27,73:[1,67],76:[1,43],80:[1,28],85:[1,55],86:[1,56],87:[1,54],93:[1,38],97:[1,45],98:[1,53],100:39,101:[1,62],103:[1,63],104:40,105:[1,64],106:41,107:[1,65],108:66,116:[1,42],121:37,122:[1,61],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{27:156,28:[1,70],55:157,56:158,61:152,73:[1,67],87:[1,54],110:153,111:[1,154],112:155},{109:159,113:[1,160],114:[1,161]},{6:[2,85],12:165,25:[2,85],27:166,28:[1,70],29:167,30:[1,68],31:[1,69],38:163,39:164,41:168,43:[1,46],51:[2,85],74:162,75:[2,85],86:[1,111]},{1:[2,27],6:[2,27],25:[2,27],26:[2,27],40:[2,27],46:[2,27],51:[2,27],54:[2,27],63:[2,27],64:[2,27],65:[2,27],67:[2,27],69:[2,27],70:[2,27],71:[2,27],75:[2,27],81:[2,27],82:[2,27],83:[2,27],88:[2,27],90:[2,27],99:[2,27],101:[2,27],102:[2,27],103:[2,27],107:[2,27],115:[2,27],123:[2,27],125:[2,27],126:[2,27],129:[2,27],130:[2,27],131:[2,27],132:[2,27],133:[2,27],134:[2,27]},{1:[2,28],6:[2,28],25:[2,28],26:[2,28],40:[2,28],46:[2,28],51:[2,28],54:[2,28],63:[2,28],64:[2,28],65:[2,28],67:[2,28],69:[2,28],70:[2,28],71:[2,28],75:[2,28],81:[2,28],82:[2,28],83:[2,28],88:[2,28],90:[2,28],99:[2,28],101:[2,28],102:[2,28],103:[2,28],107:[2,28],115:[2,28],123:[2,28],125:[2,28],126:[2,28],129:[2,28],130:[2,28],131:[2,28],132:[2,28],133:[2,28],134:[2,28]},{1:[2,26],6:[2,26],25:[2,26],26:[2,26],37:[2,26],40:[2,26],46:[2,26],51:[2,26],54:[2,26],63:[2,26],64:[2,26],65:[2,26],67:[2,26],69:[2,26],70:[2,26],71:[2,26],75:[2,26],77:[2,26],81:[2,26],82:[2,26],83:[2,26],88:[2,26],90:[2,26],99:[2,26],101:[2,26],102:[2,26],103:[2,26],107:[2,26],113:[2,26],114:[2,26],115:[2,26],123:[2,26],125:[2,26],126:[2,26],127:[2,26],128:[2,26],129:[2,26],130:[2,26],131:[2,26],132:[2,26],133:[2,26],134:[2,26],135:[2,26]},{1:[2,6],6:[2,6],7:169,8:6,9:7,10:19,11:20,12:21,13:[1,22],14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,24:18,26:[2,6],27:59,28:[1,70],29:49,30:[1,68],31:[1,69],32:24,33:[1,50],34:[1,51],35:[1,52],36:23,41:60,42:[1,44],43:[1,46],44:[1,29],47:30,48:[1,57],49:[1,58],55:47,56:48,58:36,60:25,61:26,62:27,73:[1,67],76:[1,43],80:[1,28],85:[1,55],86:[1,56],87:[1,54],93:[1,38],97:[1,45],98:[1,53],99:[2,6],100:39,101:[1,62],103:[1,63],104:40,105:[1,64],106:41,107:[1,65],108:66,116:[1,42],121:37,122:[1,61],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{1:[2,3]},{1:[2,24],6:[2,24],25:[2,24],26:[2,24],46:[2,24],51:[2,24],54:[2,24],69:[2,24],75:[2,24],83:[2,24],88:[2,24],90:[2,24],95:[2,24],96:[2,24],99:[2,24],101:[2,24],102:[2,24],103:[2,24],107:[2,24],115:[2,24],118:[2,24],120:[2,24],123:[2,24],125:[2,24],126:[2,24],129:[2,24],130:[2,24],131:[2,24],132:[2,24],133:[2,24],134:[2,24]},{6:[1,71],26:[1,170]},{1:[2,184],6:[2,184],25:[2,184],26:[2,184],46:[2,184],51:[2,184],54:[2,184],69:[2,184],75:[2,184],83:[2,184],88:[2,184],90:[2,184],99:[2,184],101:[2,184],102:[2,184],103:[2,184],107:[2,184],115:[2,184],123:[2,184],125:[2,184],126:[2,184],129:[2,184],130:[2,184],131:[2,184],132:[2,184],133:[2,184],134:[2,184]},{8:171,9:115,10:19,11:20,12:21,13:[1,22],14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,24:18,27:59,28:[1,70],29:49,30:[1,68],31:[1,69],32:24,33:[1,50],34:[1,51],35:[1,52],36:23,41:60,42:[1,44],43:[1,46],44:[1,29],47:30,48:[1,57],49:[1,58],55:47,56:48,58:36,60:25,61:26,62:27,73:[1,67],76:[1,43],80:[1,28],85:[1,55],86:[1,56],87:[1,54],93:[1,38],97:[1,45],98:[1,53],100:39,101:[1,62],103:[1,63],104:40,105:[1,64],106:41,107:[1,65],108:66,116:[1,42],121:37,122:[1,61],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{8:172,9:115,10:19,11:20,12:21,13:[1,22],14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,24:18,27:59,28:[1,70],29:49,30:[1,68],31:[1,69],32:24,33:[1,50],34:[1,51],35:[1,52],36:23,41:60,42:[1,44],43:[1,46],44:[1,29],47:30,48:[1,57],49:[1,58],55:47,56:48,58:36,60:25,61:26,62:27,73:[1,67],76:[1,43],80:[1,28],85:[1,55],86:[1,56],87:[1,54],93:[1,38],97:[1,45],98:[1,53],100:39,101:[1,62],103:[1,63],104:40,105:[1,64],106:41,107:[1,65],108:66,116:[1,42],121:37,122:[1,61],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{8:173,9:115,10:19,11:20,12:21,13:[1,22],14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,24:18,27:59,28:[1,70],29:49,30:[1,68],31:[1,69],32:24,33:[1,50],34:[1,51],35:[1,52],36:23,41:60,42:[1,44],43:[1,46],44:[1,29],47:30,48:[1,57],49:[1,58],55:47,56:48,58:36,60:25,61:26,62:27,73:[1,67],76:[1,43],80:[1,28],85:[1,55],86:[1,56],87:[1,54],93:[1,38],97:[1,45],98:[1,53],100:39,101:[1,62],103:[1,63],104:40,105:[1,64],106:41,107:[1,65],108:66,116:[1,42],121:37,122:[1,61],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{8:174,9:115,10:19,11:20,12:21,13:[1,22],14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,24:18,27:59,28:[1,70],29:49,30:[1,68],31:[1,69],32:24,33:[1,50],34:[1,51],35:[1,52],36:23,41:60,42:[1,44],43:[1,46],44:[1,29],47:30,48:[1,57],49:[1,58],55:47,56:48,58:36,60:25,61:26,62:27,73:[1,67],76:[1,43],80:[1,28],85:[1,55],86:[1,56],87:[1,54],93:[1,38],97:[1,45],98:[1,53],100:39,101:[1,62],103:[1,63],104:40,105:[1,64],106:41,107:[1,65],108:66,116:[1,42],121:37,122:[1,61],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{8:175,9:115,10:19,11:20,12:21,13:[1,22],14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,24:18,27:59,28:[1,70],29:49,30:[1,68],31:[1,69],32:24,33:[1,50],34:[1,51],35:[1,52],36:23,41:60,42:[1,44],43:[1,46],44:[1,29],47:30,48:[1,57],49:[1,58],55:47,56:48,58:36,60:25,61:26,62:27,73:[1,67],76:[1,43],80:[1,28],85:[1,55],86:[1,56],87:[1,54],93:[1,38],97:[1,45],98:[1,53],100:39,101:[1,62],103:[1,63],104:40,105:[1,64],106:41,107:[1,65],108:66,116:[1,42],121:37,122:[1,61],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{8:176,9:115,10:19,11:20,12:21,13:[1,22],14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,24:18,27:59,28:[1,70],29:49,30:[1,68],31:[1,69],32:24,33:[1,50],34:[1,51],35:[1,52],36:23,41:60,42:[1,44],43:[1,46],44:[1,29],47:30,48:[1,57],49:[1,58],55:47,56:48,58:36,60:25,61:26,62:27,73:[1,67],76:[1,43],80:[1,28],85:[1,55],86:[1,56],87:[1,54],93:[1,38],97:[1,45],98:[1,53],100:39,101:[1,62],103:[1,63],104:40,105:[1,64],106:41,107:[1,65],108:66,116:[1,42],121:37,122:[1,61],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{8:177,9:115,10:19,11:20,12:21,13:[1,22],14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,24:18,27:59,28:[1,70],29:49,30:[1,68],31:[1,69],32:24,33:[1,50],34:[1,51],35:[1,52],36:23,41:60,42:[1,44],43:[1,46],44:[1,29],47:30,48:[1,57],49:[1,58],55:47,56:48,58:36,60:25,61:26,62:27,73:[1,67],76:[1,43],80:[1,28],85:[1,55],86:[1,56],87:[1,54],93:[1,38],97:[1,45],98:[1,53],100:39,101:[1,62],103:[1,63],104:40,105:[1,64],106:41,107:[1,65],108:66,116:[1,42],121:37,122:[1,61],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{8:178,9:115,10:19,11:20,12:21,13:[1,22],14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,24:18,27:59,28:[1,70],29:49,30:[1,68],31:[1,69],32:24,33:[1,50],34:[1,51],35:[1,52],36:23,41:60,42:[1,44],43:[1,46],44:[1,29],47:30,48:[1,57],49:[1,58],55:47,56:48,58:36,60:25,61:26,62:27,73:[1,67],76:[1,43],80:[1,28],85:[1,55],86:[1,56],87:[1,54],93:[1,38],97:[1,45],98:[1,53],100:39,101:[1,62],103:[1,63],104:40,105:[1,64],106:41,107:[1,65],108:66,116:[1,42],121:37,122:[1,61],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{1:[2,140],6:[2,140],25:[2,140],26:[2,140],46:[2,140],51:[2,140],54:[2,140],69:[2,140],75:[2,140],83:[2,140],88:[2,140],90:[2,140],99:[2,140],101:[2,140],102:[2,140],103:[2,140],107:[2,140],115:[2,140],123:[2,140],125:[2,140],126:[2,140],129:[2,140],130:[2,140],131:[2,140],132:[2,140],133:[2,140],134:[2,140]},{1:[2,145],6:[2,145],25:[2,145],26:[2,145],46:[2,145],51:[2,145],54:[2,145],69:[2,145],75:[2,145],83:[2,145],88:[2,145],90:[2,145],99:[2,145],101:[2,145],102:[2,145],103:[2,145],107:[2,145],115:[2,145],123:[2,145],125:[2,145],126:[2,145],129:[2,145],130:[2,145],131:[2,145],132:[2,145],133:[2,145],134:[2,145]},{8:179,9:115,10:19,11:20,12:21,13:[1,22],14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,24:18,27:59,28:[1,70],29:49,30:[1,68],31:[1,69],32:24,33:[1,50],34:[1,51],35:[1,52],36:23,41:60,42:[1,44],43:[1,46],44:[1,29],47:30,48:[1,57],49:[1,58],55:47,56:48,58:36,60:25,61:26,62:27,73:[1,67],76:[1,43],80:[1,28],85:[1,55],86:[1,56],87:[1,54],93:[1,38],97:[1,45],98:[1,53],100:39,101:[1,62],103:[1,63],104:40,105:[1,64],106:41,107:[1,65],108:66,116:[1,42],121:37,122:[1,61],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{1:[2,139],6:[2,139],25:[2,139],26:[2,139],46:[2,139],51:[2,139],54:[2,139],69:[2,139],75:[2,139],83:[2,139],88:[2,139],90:[2,139],99:[2,139],101:[2,139],102:[2,139],103:[2,139],107:[2,139],115:[2,139],123:[2,139],125:[2,139],126:[2,139],129:[2,139],130:[2,139],131:[2,139],132:[2,139],133:[2,139],134:[2,139]},{1:[2,144],6:[2,144],25:[2,144],26:[2,144],46:[2,144],51:[2,144],54:[2,144],69:[2,144],75:[2,144],83:[2,144],88:[2,144],90:[2,144],99:[2,144],101:[2,144],102:[2,144],103:[2,144],107:[2,144],115:[2,144],123:[2,144],125:[2,144],126:[2,144],129:[2,144],130:[2,144],131:[2,144],132:[2,144],133:[2,144],134:[2,144]},{79:180,82:[1,103]},{1:[2,63],6:[2,63],25:[2,63],26:[2,63],37:[2,63],46:[2,63],51:[2,63],54:[2,63],63:[2,63],64:[2,63],65:[2,63],67:[2,63],69:[2,63],70:[2,63],71:[2,63],75:[2,63],77:[2,63],81:[2,63],82:[2,63],83:[2,63],88:[2,63],90:[2,63],99:[2,63],101:[2,63],102:[2,63],103:[2,63],107:[2,63],115:[2,63],123:[2,63],125:[2,63],126:[2,63],127:[2,63],128:[2,63],129:[2,63],130:[2,63],131:[2,63],132:[2,63],133:[2,63],134:[2,63],135:[2,63]},{82:[2,103]},{27:181,28:[1,70]},{27:182,28:[1,70]},{1:[2,77],6:[2,77],25:[2,77],26:[2,77],27:183,28:[1,70],37:[2,77],46:[2,77],51:[2,77],54:[2,77],63:[2,77],64:[2,77],65:[2,77],67:[2,77],69:[2,77],70:[2,77],71:[2,77],75:[2,77],77:[2,77],81:[2,77],82:[2,77],83:[2,77],88:[2,77],90:[2,77],99:[2,77],101:[2,77],102:[2,77],103:[2,77],107:[2,77],115:[2,77],123:[2,77],125:[2,77],126:[2,77],127:[2,77],128:[2,77],129:[2,77],130:[2,77],131:[2,77],132:[2,77],133:[2,77],134:[2,77],135:[2,77]},{1:[2,78],6:[2,78],25:[2,78],26:[2,78],37:[2,78],46:[2,78],51:[2,78],54:[2,78],63:[2,78],64:[2,78],65:[2,78],67:[2,78],69:[2,78],70:[2,78],71:[2,78],75:[2,78],77:[2,78],81:[2,78],82:[2,78],83:[2,78],88:[2,78],90:[2,78],99:[2,78],101:[2,78],102:[2,78],103:[2,78],107:[2,78],115:[2,78],123:[2,78],125:[2,78],126:[2,78],127:[2,78],128:[2,78],129:[2,78],130:[2,78],131:[2,78],132:[2,78],133:[2,78],134:[2,78],135:[2,78]},{8:185,9:115,10:19,11:20,12:21,13:[1,22],14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,24:18,27:59,28:[1,70],29:49,30:[1,68],31:[1,69],32:24,33:[1,50],34:[1,51],35:[1,52],36:23,41:60,42:[1,44],43:[1,46],44:[1,29],47:30,48:[1,57],49:[1,58],54:[1,189],55:47,56:48,58:36,60:25,61:26,62:27,68:184,72:186,73:[1,67],76:[1,43],80:[1,28],85:[1,55],86:[1,56],87:[1,54],89:187,90:[1,188],93:[1,38],97:[1,45],98:[1,53],100:39,101:[1,62],103:[1,63],104:40,105:[1,64],106:41,107:[1,65],108:66,116:[1,42],121:37,122:[1,61],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{66:190,67:[1,96],70:[1,97],71:[1,98]},{66:191,67:[1,96],70:[1,97],71:[1,98]},{79:192,82:[1,103]},{1:[2,64],6:[2,64],25:[2,64],26:[2,64],37:[2,64],46:[2,64],51:[2,64],54:[2,64],63:[2,64],64:[2,64],65:[2,64],67:[2,64],69:[2,64],70:[2,64],71:[2,64],75:[2,64],77:[2,64],81:[2,64],82:[2,64],83:[2,64],88:[2,64],90:[2,64],99:[2,64],101:[2,64],102:[2,64],103:[2,64],107:[2,64],115:[2,64],123:[2,64],125:[2,64],126:[2,64],127:[2,64],128:[2,64],129:[2,64],130:[2,64],131:[2,64],132:[2,64],133:[2,64],134:[2,64],135:[2,64]},{8:193,9:115,10:19,11:20,12:21,13:[1,22],14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,24:18,25:[1,194],27:59,28:[1,70],29:49,30:[1,68],31:[1,69],32:24,33:[1,50],34:[1,51],35:[1,52],36:23,41:60,42:[1,44],43:[1,46],44:[1,29],47:30,48:[1,57],49:[1,58],55:47,56:48,58:36,60:25,61:26,62:27,73:[1,67],76:[1,43],80:[1,28],85:[1,55],86:[1,56],87:[1,54],93:[1,38],97:[1,45],98:[1,53],100:39,101:[1,62],103:[1,63],104:40,105:[1,64],106:41,107:[1,65],108:66,116:[1,42],121:37,122:[1,61],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{1:[2,101],6:[2,101],25:[2,101],26:[2,101],46:[2,101],51:[2,101],54:[2,101],63:[2,101],64:[2,101],65:[2,101],67:[2,101],69:[2,101],70:[2,101],71:[2,101],75:[2,101],81:[2,101],82:[2,101],83:[2,101],88:[2,101],90:[2,101],99:[2,101],101:[2,101],102:[2,101],103:[2,101],107:[2,101],115:[2,101],123:[2,101],125:[2,101],126:[2,101],129:[2,101],130:[2,101],131:[2,101],132:[2,101],133:[2,101],134:[2,101]},{8:197,9:115,10:19,11:20,12:21,13:[1,22],14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,24:18,25:[1,144],27:59,28:[1,70],29:49,30:[1,68],31:[1,69],32:24,33:[1,50],34:[1,51],35:[1,52],36:23,41:60,42:[1,44],43:[1,46],44:[1,29],47:30,48:[1,57],49:[1,58],55:47,56:48,57:145,58:36,60:25,61:26,62:27,73:[1,67],76:[1,43],80:[1,28],83:[1,195],84:196,85:[1,55],86:[1,56],87:[1,54],91:143,93:[1,38],97:[1,45],98:[1,53],100:39,101:[1,62],103:[1,63],104:40,105:[1,64],106:41,107:[1,65],108:66,116:[1,42],121:37,122:[1,61],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{46:[1,198],51:[1,199]},{46:[2,52],51:[2,52]},{37:[1,201],46:[2,54],51:[2,54],54:[1,200]},{37:[2,57],46:[2,57],51:[2,57],54:[2,57]},{37:[2,58],46:[2,58],51:[2,58],54:[2,58]},{37:[2,59],46:[2,59],51:[2,59],54:[2,59]},{37:[2,60],46:[2,60],51:[2,60],54:[2,60]},{27:146,28:[1,70]},{8:197,9:115,10:19,11:20,12:21,13:[1,22],14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,24:18,25:[1,144],27:59,28:[1,70],29:49,30:[1,68],31:[1,69],32:24,33:[1,50],34:[1,51],35:[1,52],36:23,41:60,42:[1,44],43:[1,46],44:[1,29],47:30,48:[1,57],49:[1,58],55:47,56:48,57:145,58:36,60:25,61:26,62:27,73:[1,67],76:[1,43],80:[1,28],84:142,85:[1,55],86:[1,56],87:[1,54],88:[1,141],91:143,93:[1,38],97:[1,45],98:[1,53],100:39,101:[1,62],103:[1,63],104:40,105:[1,64],106:41,107:[1,65],108:66,116:[1,42],121:37,122:[1,61],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{1:[2,46],6:[2,46],25:[2,46],26:[2,46],46:[2,46],51:[2,46],54:[2,46],69:[2,46],75:[2,46],83:[2,46],88:[2,46],90:[2,46],99:[2,46],101:[2,46],102:[2,46],103:[2,46],107:[2,46],115:[2,46],123:[2,46],125:[2,46],126:[2,46],129:[2,46],130:[2,46],131:[2,46],132:[2,46],133:[2,46],134:[2,46]},{1:[2,177],6:[2,177],25:[2,177],26:[2,177],46:[2,177],51:[2,177],54:[2,177],69:[2,177],75:[2,177],83:[2,177],88:[2,177],90:[2,177],99:[2,177],100:84,101:[2,177],102:[2,177],103:[2,177],106:85,107:[2,177],108:66,115:[2,177],123:[2,177],125:[2,177],126:[2,177],129:[1,75],130:[2,177],131:[2,177],132:[2,177],133:[2,177],134:[2,177]},{100:87,101:[1,62],103:[1,63],106:88,107:[1,65],108:66,123:[1,86]},{1:[2,178],6:[2,178],25:[2,178],26:[2,178],46:[2,178],51:[2,178],54:[2,178],69:[2,178],75:[2,178],83:[2,178],88:[2,178],90:[2,178],99:[2,178],100:84,101:[2,178],102:[2,178],103:[2,178],106:85,107:[2,178],108:66,115:[2,178],123:[2,178],125:[2,178],126:[2,178],129:[1,75],130:[2,178],131:[2,178],132:[2,178],133:[2,178],134:[2,178]},{1:[2,179],6:[2,179],25:[2,179],26:[2,179],46:[2,179],51:[2,179],54:[2,179],69:[2,179],75:[2,179],83:[2,179],88:[2,179],90:[2,179],99:[2,179],100:84,101:[2,179],102:[2,179],103:[2,179],106:85,107:[2,179],108:66,115:[2,179],123:[2,179],125:[2,179],126:[2,179],129:[1,75],130:[2,179],131:[2,179],132:[2,179],133:[2,179],134:[2,179]},{1:[2,180],6:[2,180],25:[2,180],26:[2,180],46:[2,180],51:[2,180],54:[2,180],63:[2,66],64:[2,66],65:[2,66],67:[2,66],69:[2,180],70:[2,66],71:[2,66],75:[2,180],81:[2,66],82:[2,66],83:[2,180],88:[2,180],90:[2,180],99:[2,180],101:[2,180],102:[2,180],103:[2,180],107:[2,180],115:[2,180],123:[2,180],125:[2,180],126:[2,180],129:[2,180],130:[2,180],131:[2,180],132:[2,180],133:[2,180],134:[2,180]},{59:90,63:[1,92],64:[1,93],65:[1,94],66:95,67:[1,96],70:[1,97],71:[1,98],78:89,81:[1,91],82:[2,102]},{59:100,63:[1,92],64:[1,93],65:[1,94],66:95,67:[1,96],70:[1,97],71:[1,98],78:99,81:[1,91],82:[2,102]},{1:[2,69],6:[2,69],25:[2,69],26:[2,69],46:[2,69],51:[2,69],54:[2,69],63:[2,69],64:[2,69],65:[2,69],67:[2,69],69:[2,69],70:[2,69],71:[2,69],75:[2,69],81:[2,69],82:[2,69],83:[2,69],88:[2,69],90:[2,69],99:[2,69],101:[2,69],102:[2,69],103:[2,69],107:[2,69],115:[2,69],123:[2,69],125:[2,69],126:[2,69],129:[2,69],130:[2,69],131:[2,69],132:[2,69],133:[2,69],134:[2,69]},{1:[2,181],6:[2,181],25:[2,181],26:[2,181],46:[2,181],51:[2,181],54:[2,181],63:[2,66],64:[2,66],65:[2,66],67:[2,66],69:[2,181],70:[2,66],71:[2,66],75:[2,181],81:[2,66],82:[2,66],83:[2,181],88:[2,181],90:[2,181],99:[2,181],101:[2,181],102:[2,181],103:[2,181],107:[2,181],115:[2,181],123:[2,181],125:[2,181],126:[2,181],129:[2,181],130:[2,181],131:[2,181],132:[2,181],133:[2,181],134:[2,181]},{1:[2,182],6:[2,182],25:[2,182],26:[2,182],46:[2,182],51:[2,182],54:[2,182],69:[2,182],75:[2,182],83:[2,182],88:[2,182],90:[2,182],99:[2,182],101:[2,182],102:[2,182],103:[2,182],107:[2,182],115:[2,182],123:[2,182],125:[2,182],126:[2,182],129:[2,182],130:[2,182],131:[2,182],132:[2,182],133:[2,182],134:[2,182]},{1:[2,183],6:[2,183],25:[2,183],26:[2,183],46:[2,183],51:[2,183],54:[2,183],69:[2,183],75:[2,183],83:[2,183],88:[2,183],90:[2,183],99:[2,183],101:[2,183],102:[2,183],103:[2,183],107:[2,183],115:[2,183],123:[2,183],125:[2,183],126:[2,183],129:[2,183],130:[2,183],131:[2,183],132:[2,183],133:[2,183],134:[2,183]},{8:202,9:115,10:19,11:20,12:21,13:[1,22],14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,24:18,25:[1,203],27:59,28:[1,70],29:49,30:[1,68],31:[1,69],32:24,33:[1,50],34:[1,51],35:[1,52],36:23,41:60,42:[1,44],43:[1,46],44:[1,29],47:30,48:[1,57],49:[1,58],55:47,56:48,58:36,60:25,61:26,62:27,73:[1,67],76:[1,43],80:[1,28],85:[1,55],86:[1,56],87:[1,54],93:[1,38],97:[1,45],98:[1,53],100:39,101:[1,62],103:[1,63],104:40,105:[1,64],106:41,107:[1,65],108:66,116:[1,42],121:37,122:[1,61],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{8:204,9:115,10:19,11:20,12:21,13:[1,22],14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,24:18,27:59,28:[1,70],29:49,30:[1,68],31:[1,69],32:24,33:[1,50],34:[1,51],35:[1,52],36:23,41:60,42:[1,44],43:[1,46],44:[1,29],47:30,48:[1,57],49:[1,58],55:47,56:48,58:36,60:25,61:26,62:27,73:[1,67],76:[1,43],80:[1,28],85:[1,55],86:[1,56],87:[1,54],93:[1,38],97:[1,45],98:[1,53],100:39,101:[1,62],103:[1,63],104:40,105:[1,64],106:41,107:[1,65],108:66,116:[1,42],121:37,122:[1,61],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{5:205,25:[1,5],122:[1,206]},{1:[2,126],6:[2,126],25:[2,126],26:[2,126],46:[2,126],51:[2,126],54:[2,126],69:[2,126],75:[2,126],83:[2,126],88:[2,126],90:[2,126],94:207,95:[1,208],96:[1,209],99:[2,126],101:[2,126],102:[2,126],103:[2,126],107:[2,126],115:[2,126],123:[2,126],125:[2,126],126:[2,126],129:[2,126],130:[2,126],131:[2,126],132:[2,126],133:[2,126],134:[2,126]},{1:[2,138],6:[2,138],25:[2,138],26:[2,138],46:[2,138],51:[2,138],54:[2,138],69:[2,138],75:[2,138],83:[2,138],88:[2,138],90:[2,138],99:[2,138],101:[2,138],102:[2,138],103:[2,138],107:[2,138],115:[2,138],123:[2,138],125:[2,138],126:[2,138],129:[2,138],130:[2,138],131:[2,138],132:[2,138],133:[2,138],134:[2,138]},{1:[2,146],6:[2,146],25:[2,146],26:[2,146],46:[2,146],51:[2,146],54:[2,146],69:[2,146],75:[2,146],83:[2,146],88:[2,146],90:[2,146],99:[2,146],101:[2,146],102:[2,146],103:[2,146],107:[2,146],115:[2,146],123:[2,146],125:[2,146],126:[2,146],129:[2,146],130:[2,146],131:[2,146],132:[2,146],133:[2,146],134:[2,146]},{25:[1,210],100:84,101:[1,62],103:[1,63],106:85,107:[1,65],108:66,123:[1,83],125:[1,77],126:[1,76],129:[1,75],130:[1,78],131:[1,79],132:[1,80],133:[1,81],134:[1,82]},{117:211,119:212,120:[1,213]},{1:[2,91],6:[2,91],25:[2,91],26:[2,91],46:[2,91],51:[2,91],54:[2,91],69:[2,91],75:[2,91],83:[2,91],88:[2,91],90:[2,91],99:[2,91],101:[2,91],102:[2,91],103:[2,91],107:[2,91],115:[2,91],123:[2,91],125:[2,91],126:[2,91],129:[2,91],130:[2,91],131:[2,91],132:[2,91],133:[2,91],134:[2,91]},{14:214,15:120,27:59,28:[1,70],29:49,30:[1,68],31:[1,69],32:24,33:[1,50],34:[1,51],35:[1,52],36:121,41:60,55:47,56:48,58:215,60:25,61:26,62:27,73:[1,67],80:[1,28],85:[1,55],86:[1,56],87:[1,54],98:[1,53]},{1:[2,94],5:216,6:[2,94],25:[1,5],26:[2,94],46:[2,94],51:[2,94],54:[2,94],63:[2,66],64:[2,66],65:[2,66],67:[2,66],69:[2,94],70:[2,66],71:[2,66],75:[2,94],77:[1,217],81:[2,66],82:[2,66],83:[2,94],88:[2,94],90:[2,94],99:[2,94],101:[2,94],102:[2,94],103:[2,94],107:[2,94],115:[2,94],123:[2,94],125:[2,94],126:[2,94],129:[2,94],130:[2,94],131:[2,94],132:[2,94],133:[2,94],134:[2,94]},{1:[2,42],6:[2,42],26:[2,42],99:[2,42],100:84,101:[2,42],103:[2,42],106:85,107:[2,42],108:66,123:[2,42],125:[1,77],126:[1,76],129:[1,75],130:[1,78],131:[1,79],132:[1,80],133:[1,81],134:[1,82]},{1:[2,131],6:[2,131],26:[2,131],99:[2,131],100:84,101:[2,131],103:[2,131],106:85,107:[2,131],108:66,123:[2,131],125:[1,77],126:[1,76],129:[1,75],130:[1,78],131:[1,79],132:[1,80],133:[1,81],134:[1,82]},{6:[1,71],99:[1,218]},{4:219,7:4,8:6,9:7,10:19,11:20,12:21,13:[1,22],14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,24:18,27:59,28:[1,70],29:49,30:[1,68],31:[1,69],32:24,33:[1,50],34:[1,51],35:[1,52],36:23,41:60,42:[1,44],43:[1,46],44:[1,29],47:30,48:[1,57],49:[1,58],55:47,56:48,58:36,60:25,61:26,62:27,73:[1,67],76:[1,43],80:[1,28],85:[1,55],86:[1,56],87:[1,54],93:[1,38],97:[1,45],98:[1,53],100:39,101:[1,62],103:[1,63],104:40,105:[1,64],106:41,107:[1,65],108:66,116:[1,42],121:37,122:[1,61],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{6:[2,122],25:[2,122],51:[2,122],54:[1,221],88:[2,122],89:220,90:[1,188],100:84,101:[1,62],103:[1,63],106:85,107:[1,65],108:66,123:[1,83],125:[1,77],126:[1,76],129:[1,75],130:[1,78],131:[1,79],132:[1,80],133:[1,81],134:[1,82]},{1:[2,109],6:[2,109],25:[2,109],26:[2,109],37:[2,109],46:[2,109],51:[2,109],54:[2,109],63:[2,109],64:[2,109],65:[2,109],67:[2,109],69:[2,109],70:[2,109],71:[2,109],75:[2,109],81:[2,109],82:[2,109],83:[2,109],88:[2,109],90:[2,109],99:[2,109],101:[2,109],102:[2,109],103:[2,109],107:[2,109],113:[2,109],114:[2,109],115:[2,109],123:[2,109],125:[2,109],126:[2,109],129:[2,109],130:[2,109],131:[2,109],132:[2,109],133:[2,109],134:[2,109]},{6:[2,49],25:[2,49],50:222,51:[1,223],88:[2,49]},{6:[2,117],25:[2,117],26:[2,117],51:[2,117],83:[2,117],88:[2,117]},{8:197,9:115,10:19,11:20,12:21,13:[1,22],14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,24:18,25:[1,144],27:59,28:[1,70],29:49,30:[1,68],31:[1,69],32:24,33:[1,50],34:[1,51],35:[1,52],36:23,41:60,42:[1,44],43:[1,46],44:[1,29],47:30,48:[1,57],49:[1,58],55:47,56:48,57:145,58:36,60:25,61:26,62:27,73:[1,67],76:[1,43],80:[1,28],84:224,85:[1,55],86:[1,56],87:[1,54],91:143,93:[1,38],97:[1,45],98:[1,53],100:39,101:[1,62],103:[1,63],104:40,105:[1,64],106:41,107:[1,65],108:66,116:[1,42],121:37,122:[1,61],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{6:[2,123],25:[2,123],26:[2,123],51:[2,123],83:[2,123],88:[2,123]},{1:[2,108],6:[2,108],25:[2,108],26:[2,108],37:[2,108],40:[2,108],46:[2,108],51:[2,108],54:[2,108],63:[2,108],64:[2,108],65:[2,108],67:[2,108],69:[2,108],70:[2,108],71:[2,108],75:[2,108],77:[2,108],81:[2,108],82:[2,108],83:[2,108],88:[2,108],90:[2,108],99:[2,108],101:[2,108],102:[2,108],103:[2,108],107:[2,108],115:[2,108],123:[2,108],125:[2,108],126:[2,108],127:[2,108],128:[2,108],129:[2,108],130:[2,108],131:[2,108],132:[2,108],133:[2,108],134:[2,108],135:[2,108]},{5:225,25:[1,5],100:84,101:[1,62],103:[1,63],106:85,107:[1,65],108:66,123:[1,83],125:[1,77],126:[1,76],129:[1,75],130:[1,78],131:[1,79],132:[1,80],133:[1,81],134:[1,82]},{1:[2,134],6:[2,134],25:[2,134],26:[2,134],46:[2,134],51:[2,134],54:[2,134],69:[2,134],75:[2,134],83:[2,134],88:[2,134],90:[2,134],99:[2,134],100:84,101:[1,62],102:[1,226],103:[1,63],106:85,107:[1,65],108:66,115:[2,134],123:[2,134],125:[1,77],126:[1,76],129:[1,75],130:[1,78],131:[1,79],132:[1,80],133:[1,81],134:[1,82]},{1:[2,136],6:[2,136],25:[2,136],26:[2,136],46:[2,136],51:[2,136],54:[2,136],69:[2,136],75:[2,136],83:[2,136],88:[2,136],90:[2,136],99:[2,136],100:84,101:[1,62],102:[1,227],103:[1,63],106:85,107:[1,65],108:66,115:[2,136],123:[2,136],125:[1,77],126:[1,76],129:[1,75],130:[1,78],131:[1,79],132:[1,80],133:[1,81],134:[1,82]},{1:[2,142],6:[2,142],25:[2,142],26:[2,142],46:[2,142],51:[2,142],54:[2,142],69:[2,142],75:[2,142],83:[2,142],88:[2,142],90:[2,142],99:[2,142],101:[2,142],102:[2,142],103:[2,142],107:[2,142],115:[2,142],123:[2,142],125:[2,142],126:[2,142],129:[2,142],130:[2,142],131:[2,142],132:[2,142],133:[2,142],134:[2,142]},{1:[2,143],6:[2,143],25:[2,143],26:[2,143],46:[2,143],51:[2,143],54:[2,143],69:[2,143],75:[2,143],83:[2,143],88:[2,143],90:[2,143],99:[2,143],100:84,101:[1,62],102:[2,143],103:[1,63],106:85,107:[1,65],108:66,115:[2,143],123:[2,143],125:[1,77],126:[1,76],129:[1,75],130:[1,78],131:[1,79],132:[1,80],133:[1,81],134:[1,82]},{1:[2,147],6:[2,147],25:[2,147],26:[2,147],46:[2,147],51:[2,147],54:[2,147],69:[2,147],75:[2,147],83:[2,147],88:[2,147],90:[2,147],99:[2,147],101:[2,147],102:[2,147],103:[2,147],107:[2,147],115:[2,147],123:[2,147],125:[2,147],126:[2,147],129:[2,147],130:[2,147],131:[2,147],132:[2,147],133:[2,147],134:[2,147]},{113:[2,149],114:[2,149]},{27:156,28:[1,70],55:157,56:158,73:[1,67],87:[1,112],110:228,112:155},{51:[1,229],113:[2,154],114:[2,154]},{51:[2,151],113:[2,151],114:[2,151]},{51:[2,152],113:[2,152],114:[2,152]},{51:[2,153],113:[2,153],114:[2,153]},{1:[2,148],6:[2,148],25:[2,148],26:[2,148],46:[2,148],51:[2,148],54:[2,148],69:[2,148],75:[2,148],83:[2,148],88:[2,148],90:[2,148],99:[2,148],101:[2,148],102:[2,148],103:[2,148],107:[2,148],115:[2,148],123:[2,148],125:[2,148],126:[2,148],129:[2,148],130:[2,148],131:[2,148],132:[2,148],133:[2,148],134:[2,148]},{8:230,9:115,10:19,11:20,12:21,13:[1,22],14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,24:18,27:59,28:[1,70],29:49,30:[1,68],31:[1,69],32:24,33:[1,50],34:[1,51],35:[1,52],36:23,41:60,42:[1,44],43:[1,46],44:[1,29],47:30,48:[1,57],49:[1,58],55:47,56:48,58:36,60:25,61:26,62:27,73:[1,67],76:[1,43],80:[1,28],85:[1,55],86:[1,56],87:[1,54],93:[1,38],97:[1,45],98:[1,53],100:39,101:[1,62],103:[1,63],104:40,105:[1,64],106:41,107:[1,65],108:66,116:[1,42],121:37,122:[1,61],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{8:231,9:115,10:19,11:20,12:21,13:[1,22],14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,24:18,27:59,28:[1,70],29:49,30:[1,68],31:[1,69],32:24,33:[1,50],34:[1,51],35:[1,52],36:23,41:60,42:[1,44],43:[1,46],44:[1,29],47:30,48:[1,57],49:[1,58],55:47,56:48,58:36,60:25,61:26,62:27,73:[1,67],76:[1,43],80:[1,28],85:[1,55],86:[1,56],87:[1,54],93:[1,38],97:[1,45],98:[1,53],100:39,101:[1,62],103:[1,63],104:40,105:[1,64],106:41,107:[1,65],108:66,116:[1,42],121:37,122:[1,61],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{6:[2,49],25:[2,49],50:232,51:[1,233],75:[2,49]},{6:[2,86],25:[2,86],26:[2,86],51:[2,86],75:[2,86]},{6:[2,35],25:[2,35],26:[2,35],40:[1,234],51:[2,35],75:[2,35]},{6:[2,38],25:[2,38],26:[2,38],51:[2,38],75:[2,38]},{6:[2,39],25:[2,39],26:[2,39],40:[2,39],51:[2,39],75:[2,39]},{6:[2,40],25:[2,40],26:[2,40],40:[2,40],51:[2,40],75:[2,40]},{6:[2,41],25:[2,41],26:[2,41],40:[2,41],51:[2,41],75:[2,41]},{1:[2,5],6:[2,5],26:[2,5],99:[2,5]},{1:[2,25],6:[2,25],25:[2,25],26:[2,25],46:[2,25],51:[2,25],54:[2,25],69:[2,25],75:[2,25],83:[2,25],88:[2,25],90:[2,25],95:[2,25],96:[2,25],99:[2,25],101:[2,25],102:[2,25],103:[2,25],107:[2,25],115:[2,25],118:[2,25],120:[2,25],123:[2,25],125:[2,25],126:[2,25],129:[2,25],130:[2,25],131:[2,25],132:[2,25],133:[2,25],134:[2,25]},{1:[2,185],6:[2,185],25:[2,185],26:[2,185],46:[2,185],51:[2,185],54:[2,185],69:[2,185],75:[2,185],83:[2,185],88:[2,185],90:[2,185],99:[2,185],100:84,101:[2,185],102:[2,185],103:[2,185],106:85,107:[2,185],108:66,115:[2,185],123:[2,185],125:[2,185],126:[2,185],129:[1,75],130:[1,78],131:[2,185],132:[2,185],133:[2,185],134:[2,185]},{1:[2,186],6:[2,186],25:[2,186],26:[2,186],46:[2,186],51:[2,186],54:[2,186],69:[2,186],75:[2,186],83:[2,186],88:[2,186],90:[2,186],99:[2,186],100:84,101:[2,186],102:[2,186],103:[2,186],106:85,107:[2,186],108:66,115:[2,186],123:[2,186],125:[2,186],126:[2,186],129:[1,75],130:[1,78],131:[2,186],132:[2,186],133:[2,186],134:[2,186]},{1:[2,187],6:[2,187],25:[2,187],26:[2,187],46:[2,187],51:[2,187],54:[2,187],69:[2,187],75:[2,187],83:[2,187],88:[2,187],90:[2,187],99:[2,187],100:84,101:[2,187],102:[2,187],103:[2,187],106:85,107:[2,187],108:66,115:[2,187],123:[2,187],125:[2,187],126:[2,187],129:[1,75],130:[2,187],131:[2,187],132:[2,187],133:[2,187],134:[2,187]},{1:[2,188],6:[2,188],25:[2,188],26:[2,188],46:[2,188],51:[2,188],54:[2,188],69:[2,188],75:[2,188],83:[2,188],88:[2,188],90:[2,188],99:[2,188],100:84,101:[2,188],102:[2,188],103:[2,188],106:85,107:[2,188],108:66,115:[2,188],123:[2,188],125:[1,77],126:[1,76],129:[1,75],130:[1,78],131:[2,188],132:[2,188],133:[2,188],134:[2,188]},{1:[2,189],6:[2,189],25:[2,189],26:[2,189],46:[2,189],51:[2,189],54:[2,189],69:[2,189],75:[2,189],83:[2,189],88:[2,189],90:[2,189],99:[2,189],100:84,101:[2,189],102:[2,189],103:[2,189],106:85,107:[2,189],108:66,115:[2,189],123:[2,189],125:[1,77],126:[1,76],129:[1,75],130:[1,78],131:[1,79],132:[2,189],133:[2,189],134:[1,82]},{1:[2,190],6:[2,190],25:[2,190],26:[2,190],46:[2,190],51:[2,190],54:[2,190],69:[2,190],75:[2,190],83:[2,190],88:[2,190],90:[2,190],99:[2,190],100:84,101:[2,190],102:[2,190],103:[2,190],106:85,107:[2,190],108:66,115:[2,190],123:[2,190],125:[1,77],126:[1,76],129:[1,75],130:[1,78],131:[1,79],132:[1,80],133:[2,190],134:[1,82]},{1:[2,191],6:[2,191],25:[2,191],26:[2,191],46:[2,191],51:[2,191],54:[2,191],69:[2,191],75:[2,191],83:[2,191],88:[2,191],90:[2,191],99:[2,191],100:84,101:[2,191],102:[2,191],103:[2,191],106:85,107:[2,191],108:66,115:[2,191],123:[2,191],125:[1,77],126:[1,76],129:[1,75],130:[1,78],131:[1,79],132:[2,191],133:[2,191],134:[2,191]},{1:[2,176],6:[2,176],25:[2,176],26:[2,176],46:[2,176],51:[2,176],54:[2,176],69:[2,176],75:[2,176],83:[2,176],88:[2,176],90:[2,176],99:[2,176],100:84,101:[1,62],102:[2,176],103:[1,63],106:85,107:[1,65],108:66,115:[2,176],123:[1,83],125:[1,77],126:[1,76],129:[1,75],130:[1,78],131:[1,79],132:[1,80],133:[1,81],134:[1,82]},{1:[2,175],6:[2,175],25:[2,175],26:[2,175],46:[2,175],51:[2,175],54:[2,175],69:[2,175],75:[2,175],83:[2,175],88:[2,175],90:[2,175],99:[2,175],100:84,101:[1,62],102:[2,175],103:[1,63],106:85,107:[1,65],108:66,115:[2,175],123:[1,83],125:[1,77],126:[1,76],129:[1,75],130:[1,78],131:[1,79],132:[1,80],133:[1,81],134:[1,82]},{1:[2,98],6:[2,98],25:[2,98],26:[2,98],46:[2,98],51:[2,98],54:[2,98],63:[2,98],64:[2,98],65:[2,98],67:[2,98],69:[2,98],70:[2,98],71:[2,98],75:[2,98],81:[2,98],82:[2,98],83:[2,98],88:[2,98],90:[2,98],99:[2,98],101:[2,98],102:[2,98],103:[2,98],107:[2,98],115:[2,98],123:[2,98],125:[2,98],126:[2,98],129:[2,98],130:[2,98],131:[2,98],132:[2,98],133:[2,98],134:[2,98]},{1:[2,74],6:[2,74],25:[2,74],26:[2,74],37:[2,74],46:[2,74],51:[2,74],54:[2,74],63:[2,74],64:[2,74],65:[2,74],67:[2,74],69:[2,74],70:[2,74],71:[2,74],75:[2,74],77:[2,74],81:[2,74],82:[2,74],83:[2,74],88:[2,74],90:[2,74],99:[2,74],101:[2,74],102:[2,74],103:[2,74],107:[2,74],115:[2,74],123:[2,74],125:[2,74],126:[2,74],127:[2,74],128:[2,74],129:[2,74],130:[2,74],131:[2,74],132:[2,74],133:[2,74],134:[2,74],135:[2,74]},{1:[2,75],6:[2,75],25:[2,75],26:[2,75],37:[2,75],46:[2,75],51:[2,75],54:[2,75],63:[2,75],64:[2,75],65:[2,75],67:[2,75],69:[2,75],70:[2,75],71:[2,75],75:[2,75],77:[2,75],81:[2,75],82:[2,75],83:[2,75],88:[2,75],90:[2,75],99:[2,75],101:[2,75],102:[2,75],103:[2,75],107:[2,75],115:[2,75],123:[2,75],125:[2,75],126:[2,75],127:[2,75],128:[2,75],129:[2,75],130:[2,75],131:[2,75],132:[2,75],133:[2,75],134:[2,75],135:[2,75]},{1:[2,76],6:[2,76],25:[2,76],26:[2,76],37:[2,76],46:[2,76],51:[2,76],54:[2,76],63:[2,76],64:[2,76],65:[2,76],67:[2,76],69:[2,76],70:[2,76],71:[2,76],75:[2,76],77:[2,76],81:[2,76],82:[2,76],83:[2,76],88:[2,76],90:[2,76],99:[2,76],101:[2,76],102:[2,76],103:[2,76],107:[2,76],115:[2,76],123:[2,76],125:[2,76],126:[2,76],127:[2,76],128:[2,76],129:[2,76],130:[2,76],131:[2,76],132:[2,76],133:[2,76],134:[2,76],135:[2,76]},{69:[1,235]},{54:[1,189],69:[2,82],89:236,90:[1,188],100:84,101:[1,62],103:[1,63],106:85,107:[1,65],108:66,123:[1,83],125:[1,77],126:[1,76],129:[1,75],130:[1,78],131:[1,79],132:[1,80],133:[1,81],134:[1,82]},{69:[2,83]},{8:237,9:115,10:19,11:20,12:21,13:[1,22],14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,24:18,27:59,28:[1,70],29:49,30:[1,68],31:[1,69],32:24,33:[1,50],34:[1,51],35:[1,52],36:23,41:60,42:[1,44],43:[1,46],44:[1,29],47:30,48:[1,57],49:[1,58],55:47,56:48,58:36,60:25,61:26,62:27,73:[1,67],76:[1,43],80:[1,28],85:[1,55],86:[1,56],87:[1,54],93:[1,38],97:[1,45],98:[1,53],100:39,101:[1,62],103:[1,63],104:40,105:[1,64],106:41,107:[1,65],108:66,116:[1,42],121:37,122:[1,61],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{13:[2,111],28:[2,111],30:[2,111],31:[2,111],33:[2,111],34:[2,111],35:[2,111],42:[2,111],43:[2,111],44:[2,111],48:[2,111],49:[2,111],69:[2,111],73:[2,111],76:[2,111],80:[2,111],85:[2,111],86:[2,111],87:[2,111],93:[2,111],97:[2,111],98:[2,111],101:[2,111],103:[2,111],105:[2,111],107:[2,111],116:[2,111],122:[2,111],124:[2,111],125:[2,111],126:[2,111],127:[2,111],128:[2,111]},{13:[2,112],28:[2,112],30:[2,112],31:[2,112],33:[2,112],34:[2,112],35:[2,112],42:[2,112],43:[2,112],44:[2,112],48:[2,112],49:[2,112],69:[2,112],73:[2,112],76:[2,112],80:[2,112],85:[2,112],86:[2,112],87:[2,112],93:[2,112],97:[2,112],98:[2,112],101:[2,112],103:[2,112],105:[2,112],107:[2,112],116:[2,112],122:[2,112],124:[2,112],125:[2,112],126:[2,112],127:[2,112],128:[2,112]},{1:[2,80],6:[2,80],25:[2,80],26:[2,80],37:[2,80],46:[2,80],51:[2,80],54:[2,80],63:[2,80],64:[2,80],65:[2,80],67:[2,80],69:[2,80],70:[2,80],71:[2,80],75:[2,80],77:[2,80],81:[2,80],82:[2,80],83:[2,80],88:[2,80],90:[2,80],99:[2,80],101:[2,80],102:[2,80],103:[2,80],107:[2,80],115:[2,80],123:[2,80],125:[2,80],126:[2,80],127:[2,80],128:[2,80],129:[2,80],130:[2,80],131:[2,80],132:[2,80],133:[2,80],134:[2,80],135:[2,80]},{1:[2,81],6:[2,81],25:[2,81],26:[2,81],37:[2,81],46:[2,81],51:[2,81],54:[2,81],63:[2,81],64:[2,81],65:[2,81],67:[2,81],69:[2,81],70:[2,81],71:[2,81],75:[2,81],77:[2,81],81:[2,81],82:[2,81],83:[2,81],88:[2,81],90:[2,81],99:[2,81],101:[2,81],102:[2,81],103:[2,81],107:[2,81],115:[2,81],123:[2,81],125:[2,81],126:[2,81],127:[2,81],128:[2,81],129:[2,81],130:[2,81],131:[2,81],132:[2,81],133:[2,81],134:[2,81],135:[2,81]},{1:[2,99],6:[2,99],25:[2,99],26:[2,99],46:[2,99],51:[2,99],54:[2,99],63:[2,99],64:[2,99],65:[2,99],67:[2,99],69:[2,99],70:[2,99],71:[2,99],75:[2,99],81:[2,99],82:[2,99],83:[2,99],88:[2,99],90:[2,99],99:[2,99],101:[2,99],102:[2,99],103:[2,99],107:[2,99],115:[2,99],123:[2,99],125:[2,99],126:[2,99],129:[2,99],130:[2,99],131:[2,99],132:[2,99],133:[2,99],134:[2,99]},{1:[2,33],6:[2,33],25:[2,33],26:[2,33],46:[2,33],51:[2,33],54:[2,33],69:[2,33],75:[2,33],83:[2,33],88:[2,33],90:[2,33],99:[2,33],100:84,101:[2,33],102:[2,33],103:[2,33],106:85,107:[2,33],108:66,115:[2,33],123:[2,33],125:[1,77],126:[1,76],129:[1,75],130:[1,78],131:[1,79],132:[1,80],133:[1,81],134:[1,82]},{8:238,9:115,10:19,11:20,12:21,13:[1,22],14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,24:18,27:59,28:[1,70],29:49,30:[1,68],31:[1,69],32:24,33:[1,50],34:[1,51],35:[1,52],36:23,41:60,42:[1,44],43:[1,46],44:[1,29],47:30,48:[1,57],49:[1,58],55:47,56:48,58:36,60:25,61:26,62:27,73:[1,67],76:[1,43],80:[1,28],85:[1,55],86:[1,56],87:[1,54],93:[1,38],97:[1,45],98:[1,53],100:39,101:[1,62],103:[1,63],104:40,105:[1,64],106:41,107:[1,65],108:66,116:[1,42],121:37,122:[1,61],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{1:[2,104],6:[2,104],25:[2,104],26:[2,104],46:[2,104],51:[2,104],54:[2,104],63:[2,104],64:[2,104],65:[2,104],67:[2,104],69:[2,104],70:[2,104],71:[2,104],75:[2,104],81:[2,104],82:[2,104],83:[2,104],88:[2,104],90:[2,104],99:[2,104],101:[2,104],102:[2,104],103:[2,104],107:[2,104],115:[2,104],123:[2,104],125:[2,104],126:[2,104],129:[2,104],130:[2,104],131:[2,104],132:[2,104],133:[2,104],134:[2,104]},{6:[2,49],25:[2,49],50:239,51:[1,223],83:[2,49]},{6:[2,122],25:[2,122],26:[2,122],51:[2,122],54:[1,240],83:[2,122],88:[2,122],100:84,101:[1,62],103:[1,63],106:85,107:[1,65],108:66,123:[1,83],125:[1,77],126:[1,76],129:[1,75],130:[1,78],131:[1,79],132:[1,80],133:[1,81],134:[1,82]},{47:241,48:[1,57],49:[1,58]},{27:107,28:[1,70],41:108,52:242,53:106,55:109,56:110,73:[1,67],86:[1,111],87:[1,112]},{46:[2,55],51:[2,55]},{8:243,9:115,10:19,11:20,12:21,13:[1,22],14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,24:18,27:59,28:[1,70],29:49,30:[1,68],31:[1,69],32:24,33:[1,50],34:[1,51],35:[1,52],36:23,41:60,42:[1,44],43:[1,46],44:[1,29],47:30,48:[1,57],49:[1,58],55:47,56:48,58:36,60:25,61:26,62:27,73:[1,67],76:[1,43],80:[1,28],85:[1,55],86:[1,56],87:[1,54],93:[1,38],97:[1,45],98:[1,53],100:39,101:[1,62],103:[1,63],104:40,105:[1,64],106:41,107:[1,65],108:66,116:[1,42],121:37,122:[1,61],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{1:[2,192],6:[2,192],25:[2,192],26:[2,192],46:[2,192],51:[2,192],54:[2,192],69:[2,192],75:[2,192],83:[2,192],88:[2,192],90:[2,192],99:[2,192],100:84,101:[2,192],102:[2,192],103:[2,192],106:85,107:[2,192],108:66,115:[2,192],123:[2,192],125:[1,77],126:[1,76],129:[1,75],130:[1,78],131:[1,79],132:[1,80],133:[1,81],134:[1,82]},{8:244,9:115,10:19,11:20,12:21,13:[1,22],14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,24:18,27:59,28:[1,70],29:49,30:[1,68],31:[1,69],32:24,33:[1,50],34:[1,51],35:[1,52],36:23,41:60,42:[1,44],43:[1,46],44:[1,29],47:30,48:[1,57],49:[1,58],55:47,56:48,58:36,60:25,61:26,62:27,73:[1,67],76:[1,43],80:[1,28],85:[1,55],86:[1,56],87:[1,54],93:[1,38],97:[1,45],98:[1,53],100:39,101:[1,62],103:[1,63],104:40,105:[1,64],106:41,107:[1,65],108:66,116:[1,42],121:37,122:[1,61],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{1:[2,194],6:[2,194],25:[2,194],26:[2,194],46:[2,194],51:[2,194],54:[2,194],69:[2,194],75:[2,194],83:[2,194],88:[2,194],90:[2,194],99:[2,194],100:84,101:[2,194],102:[2,194],103:[2,194],106:85,107:[2,194],108:66,115:[2,194],123:[2,194],125:[1,77],126:[1,76],129:[1,75],130:[1,78],131:[1,79],132:[1,80],133:[1,81],134:[1,82]},{1:[2,174],6:[2,174],25:[2,174],26:[2,174],46:[2,174],51:[2,174],54:[2,174],69:[2,174],75:[2,174],83:[2,174],88:[2,174],90:[2,174],99:[2,174],101:[2,174],102:[2,174],103:[2,174],107:[2,174],115:[2,174],123:[2,174],125:[2,174],126:[2,174],129:[2,174],130:[2,174],131:[2,174],132:[2,174],133:[2,174],134:[2,174]},{8:245,9:115,10:19,11:20,12:21,13:[1,22],14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,24:18,27:59,28:[1,70],29:49,30:[1,68],31:[1,69],32:24,33:[1,50],34:[1,51],35:[1,52],36:23,41:60,42:[1,44],43:[1,46],44:[1,29],47:30,48:[1,57],49:[1,58],55:47,56:48,58:36,60:25,61:26,62:27,73:[1,67],76:[1,43],80:[1,28],85:[1,55],86:[1,56],87:[1,54],93:[1,38],97:[1,45],98:[1,53],100:39,101:[1,62],103:[1,63],104:40,105:[1,64],106:41,107:[1,65],108:66,116:[1,42],121:37,122:[1,61],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{1:[2,127],6:[2,127],25:[2,127],26:[2,127],46:[2,127],51:[2,127],54:[2,127],69:[2,127],75:[2,127],83:[2,127],88:[2,127],90:[2,127],95:[1,246],99:[2,127],101:[2,127],102:[2,127],103:[2,127],107:[2,127],115:[2,127],123:[2,127],125:[2,127],126:[2,127],129:[2,127],130:[2,127],131:[2,127],132:[2,127],133:[2,127],134:[2,127]},{5:247,25:[1,5]},{27:248,28:[1,70]},{117:249,119:212,120:[1,213]},{26:[1,250],118:[1,251],119:252,120:[1,213]},{26:[2,167],118:[2,167],120:[2,167]},{8:254,9:115,10:19,11:20,12:21,13:[1,22],14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,24:18,27:59,28:[1,70],29:49,30:[1,68],31:[1,69],32:24,33:[1,50],34:[1,51],35:[1,52],36:23,41:60,42:[1,44],43:[1,46],44:[1,29],47:30,48:[1,57],49:[1,58],55:47,56:48,58:36,60:25,61:26,62:27,73:[1,67],76:[1,43],80:[1,28],85:[1,55],86:[1,56],87:[1,54],92:253,93:[1,38],97:[1,45],98:[1,53],100:39,101:[1,62],103:[1,63],104:40,105:[1,64],106:41,107:[1,65],108:66,116:[1,42],121:37,122:[1,61],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{1:[2,92],5:255,6:[2,92],25:[1,5],26:[2,92],46:[2,92],51:[2,92],54:[2,92],59:90,63:[1,92],64:[1,93],65:[1,94],66:95,67:[1,96],69:[2,92],70:[1,97],71:[1,98],75:[2,92],78:89,81:[1,91],82:[2,102],83:[2,92],88:[2,92],90:[2,92],99:[2,92],101:[2,92],102:[2,92],103:[2,92],107:[2,92],115:[2,92],123:[2,92],125:[2,92],126:[2,92],129:[2,92],130:[2,92],131:[2,92],132:[2,92],133:[2,92],134:[2,92]},{1:[2,66],6:[2,66],25:[2,66],26:[2,66],46:[2,66],51:[2,66],54:[2,66],63:[2,66],64:[2,66],65:[2,66],67:[2,66],69:[2,66],70:[2,66],71:[2,66],75:[2,66],81:[2,66],82:[2,66],83:[2,66],88:[2,66],90:[2,66],99:[2,66],101:[2,66],102:[2,66],103:[2,66],107:[2,66],115:[2,66],123:[2,66],125:[2,66],126:[2,66],129:[2,66],130:[2,66],131:[2,66],132:[2,66],133:[2,66],134:[2,66]},{1:[2,95],6:[2,95],25:[2,95],26:[2,95],46:[2,95],51:[2,95],54:[2,95],69:[2,95],75:[2,95],83:[2,95],88:[2,95],90:[2,95],99:[2,95],101:[2,95],102:[2,95],103:[2,95],107:[2,95],115:[2,95],123:[2,95],125:[2,95],126:[2,95],129:[2,95],130:[2,95],131:[2,95],132:[2,95],133:[2,95],134:[2,95]},{14:256,15:120,27:59,28:[1,70],29:49,30:[1,68],31:[1,69],32:24,33:[1,50],34:[1,51],35:[1,52],36:121,41:60,55:47,56:48,58:215,60:25,61:26,62:27,73:[1,67],80:[1,28],85:[1,55],86:[1,56],87:[1,54],98:[1,53]},{1:[2,132],6:[2,132],25:[2,132],26:[2,132],46:[2,132],51:[2,132],54:[2,132],63:[2,132],64:[2,132],65:[2,132],67:[2,132],69:[2,132],70:[2,132],71:[2,132],75:[2,132],81:[2,132],82:[2,132],83:[2,132],88:[2,132],90:[2,132],99:[2,132],101:[2,132],102:[2,132],103:[2,132],107:[2,132],115:[2,132],123:[2,132],125:[2,132],126:[2,132],129:[2,132],130:[2,132],131:[2,132],132:[2,132],133:[2,132],134:[2,132]},{6:[1,71],26:[1,257]},{8:258,9:115,10:19,11:20,12:21,13:[1,22],14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,24:18,27:59,28:[1,70],29:49,30:[1,68],31:[1,69],32:24,33:[1,50],34:[1,51],35:[1,52],36:23,41:60,42:[1,44],43:[1,46],44:[1,29],47:30,48:[1,57],49:[1,58],55:47,56:48,58:36,60:25,61:26,62:27,73:[1,67],76:[1,43],80:[1,28],85:[1,55],86:[1,56],87:[1,54],93:[1,38],97:[1,45],98:[1,53],100:39,101:[1,62],103:[1,63],104:40,105:[1,64],106:41,107:[1,65],108:66,116:[1,42],121:37,122:[1,61],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{6:[2,61],13:[2,112],25:[2,61],28:[2,112],30:[2,112],31:[2,112],33:[2,112],34:[2,112],35:[2,112],42:[2,112],43:[2,112],44:[2,112],48:[2,112],49:[2,112],51:[2,61],73:[2,112],76:[2,112],80:[2,112],85:[2,112],86:[2,112],87:[2,112],88:[2,61],93:[2,112],97:[2,112],98:[2,112],101:[2,112],103:[2,112],105:[2,112],107:[2,112],116:[2,112],122:[2,112],124:[2,112],125:[2,112],126:[2,112],127:[2,112],128:[2,112]},{6:[1,260],25:[1,261],88:[1,259]},{6:[2,50],8:197,9:115,10:19,11:20,12:21,13:[1,22],14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,24:18,25:[2,50],26:[2,50],27:59,28:[1,70],29:49,30:[1,68],31:[1,69],32:24,33:[1,50],34:[1,51],35:[1,52],36:23,41:60,42:[1,44],43:[1,46],44:[1,29],47:30,48:[1,57],49:[1,58],55:47,56:48,57:145,58:36,60:25,61:26,62:27,73:[1,67],76:[1,43],80:[1,28],83:[2,50],85:[1,55],86:[1,56],87:[1,54],88:[2,50],91:262,93:[1,38],97:[1,45],98:[1,53],100:39,101:[1,62],103:[1,63],104:40,105:[1,64],106:41,107:[1,65],108:66,116:[1,42],121:37,122:[1,61],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{6:[2,49],25:[2,49],26:[2,49],50:263,51:[1,223]},{1:[2,171],6:[2,171],25:[2,171],26:[2,171],46:[2,171],51:[2,171],54:[2,171],69:[2,171],75:[2,171],83:[2,171],88:[2,171],90:[2,171],99:[2,171],101:[2,171],102:[2,171],103:[2,171],107:[2,171],115:[2,171],118:[2,171],123:[2,171],125:[2,171],126:[2,171],129:[2,171],130:[2,171],131:[2,171],132:[2,171],133:[2,171],134:[2,171]},{8:264,9:115,10:19,11:20,12:21,13:[1,22],14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,24:18,27:59,28:[1,70],29:49,30:[1,68],31:[1,69],32:24,33:[1,50],34:[1,51],35:[1,52],36:23,41:60,42:[1,44],43:[1,46],44:[1,29],47:30,48:[1,57],49:[1,58],55:47,56:48,58:36,60:25,61:26,62:27,73:[1,67],76:[1,43],80:[1,28],85:[1,55],86:[1,56],87:[1,54],93:[1,38],97:[1,45],98:[1,53],100:39,101:[1,62],103:[1,63],104:40,105:[1,64],106:41,107:[1,65],108:66,116:[1,42],121:37,122:[1,61],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{8:265,9:115,10:19,11:20,12:21,13:[1,22],14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,24:18,27:59,28:[1,70],29:49,30:[1,68],31:[1,69],32:24,33:[1,50],34:[1,51],35:[1,52],36:23,41:60,42:[1,44],43:[1,46],44:[1,29],47:30,48:[1,57],49:[1,58],55:47,56:48,58:36,60:25,61:26,62:27,73:[1,67],76:[1,43],80:[1,28],85:[1,55],86:[1,56],87:[1,54],93:[1,38],97:[1,45],98:[1,53],100:39,101:[1,62],103:[1,63],104:40,105:[1,64],106:41,107:[1,65],108:66,116:[1,42],121:37,122:[1,61],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{113:[2,150],114:[2,150]},{27:156,28:[1,70],55:157,56:158,73:[1,67],87:[1,112],112:266},{1:[2,156],6:[2,156],25:[2,156],26:[2,156],46:[2,156],51:[2,156],54:[2,156],69:[2,156],75:[2,156],83:[2,156],88:[2,156],90:[2,156],99:[2,156],100:84,101:[2,156],102:[1,267],103:[2,156],106:85,107:[2,156],108:66,115:[1,268],123:[2,156],125:[1,77],126:[1,76],129:[1,75],130:[1,78],131:[1,79],132:[1,80],133:[1,81],134:[1,82]},{1:[2,157],6:[2,157],25:[2,157],26:[2,157],46:[2,157],51:[2,157],54:[2,157],69:[2,157],75:[2,157],83:[2,157],88:[2,157],90:[2,157],99:[2,157],100:84,101:[2,157],102:[1,269],103:[2,157],106:85,107:[2,157],108:66,115:[2,157],123:[2,157],125:[1,77],126:[1,76],129:[1,75],130:[1,78],131:[1,79],132:[1,80],133:[1,81],134:[1,82]},{6:[1,271],25:[1,272],75:[1,270]},{6:[2,50],12:165,25:[2,50],26:[2,50],27:166,28:[1,70],29:167,30:[1,68],31:[1,69],38:273,39:164,41:168,43:[1,46],75:[2,50],86:[1,111]},{8:274,9:115,10:19,11:20,12:21,13:[1,22],14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,24:18,25:[1,275],27:59,28:[1,70],29:49,30:[1,68],31:[1,69],32:24,33:[1,50],34:[1,51],35:[1,52],36:23,41:60,42:[1,44],43:[1,46],44:[1,29],47:30,48:[1,57],49:[1,58],55:47,56:48,58:36,60:25,61:26,62:27,73:[1,67],76:[1,43],80:[1,28],85:[1,55],86:[1,56],87:[1,54],93:[1,38],97:[1,45],98:[1,53],100:39,101:[1,62],103:[1,63],104:40,105:[1,64],106:41,107:[1,65],108:66,116:[1,42],121:37,122:[1,61],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{1:[2,79],6:[2,79],25:[2,79],26:[2,79],37:[2,79],46:[2,79],51:[2,79],54:[2,79],63:[2,79],64:[2,79],65:[2,79],67:[2,79],69:[2,79],70:[2,79],71:[2,79],75:[2,79],77:[2,79],81:[2,79],82:[2,79],83:[2,79],88:[2,79],90:[2,79],99:[2,79],101:[2,79],102:[2,79],103:[2,79],107:[2,79],115:[2,79],123:[2,79],125:[2,79],126:[2,79],127:[2,79],128:[2,79],129:[2,79],130:[2,79],131:[2,79],132:[2,79],133:[2,79],134:[2,79],135:[2,79]},{8:276,9:115,10:19,11:20,12:21,13:[1,22],14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,24:18,27:59,28:[1,70],29:49,30:[1,68],31:[1,69],32:24,33:[1,50],34:[1,51],35:[1,52],36:23,41:60,42:[1,44],43:[1,46],44:[1,29],47:30,48:[1,57],49:[1,58],55:47,56:48,58:36,60:25,61:26,62:27,69:[2,115],73:[1,67],76:[1,43],80:[1,28],85:[1,55],86:[1,56],87:[1,54],93:[1,38],97:[1,45],98:[1,53],100:39,101:[1,62],103:[1,63],104:40,105:[1,64],106:41,107:[1,65],108:66,116:[1,42],121:37,122:[1,61],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{69:[2,116],100:84,101:[1,62],103:[1,63],106:85,107:[1,65],108:66,123:[1,83],125:[1,77],126:[1,76],129:[1,75],130:[1,78],131:[1,79],132:[1,80],133:[1,81],134:[1,82]},{26:[1,277],100:84,101:[1,62],103:[1,63],106:85,107:[1,65],108:66,123:[1,83],125:[1,77],126:[1,76],129:[1,75],130:[1,78],131:[1,79],132:[1,80],133:[1,81],134:[1,82]},{6:[1,260],25:[1,261],83:[1,278]},{6:[2,61],25:[2,61],26:[2,61],51:[2,61],83:[2,61],88:[2,61]},{5:279,25:[1,5]},{46:[2,53],51:[2,53]},{46:[2,56],51:[2,56],100:84,101:[1,62],103:[1,63],106:85,107:[1,65],108:66,123:[1,83],125:[1,77],126:[1,76],129:[1,75],130:[1,78],131:[1,79],132:[1,80],133:[1,81],134:[1,82]},{26:[1,280],100:84,101:[1,62],103:[1,63],106:85,107:[1,65],108:66,123:[1,83],125:[1,77],126:[1,76],129:[1,75],130:[1,78],131:[1,79],132:[1,80],133:[1,81],134:[1,82]},{5:281,25:[1,5],100:84,101:[1,62],103:[1,63],106:85,107:[1,65],108:66,123:[1,83],125:[1,77],126:[1,76],129:[1,75],130:[1,78],131:[1,79],132:[1,80],133:[1,81],134:[1,82]},{5:282,25:[1,5]},{1:[2,128],6:[2,128],25:[2,128],26:[2,128],46:[2,128],51:[2,128],54:[2,128],69:[2,128],75:[2,128],83:[2,128],88:[2,128],90:[2,128],99:[2,128],101:[2,128],102:[2,128],103:[2,128],107:[2,128],115:[2,128],123:[2,128],125:[2,128],126:[2,128],129:[2,128],130:[2,128],131:[2,128],132:[2,128],133:[2,128],134:[2,128]},{5:283,25:[1,5]},{26:[1,284],118:[1,285],119:252,120:[1,213]},{1:[2,165],6:[2,165],25:[2,165],26:[2,165],46:[2,165],51:[2,165],54:[2,165],69:[2,165],75:[2,165],83:[2,165],88:[2,165],90:[2,165],99:[2,165],101:[2,165],102:[2,165],103:[2,165],107:[2,165],115:[2,165],123:[2,165],125:[2,165],126:[2,165],129:[2,165],130:[2,165],131:[2,165],132:[2,165],133:[2,165],134:[2,165]},{5:286,25:[1,5]},{26:[2,168],118:[2,168],120:[2,168]},{5:287,25:[1,5],51:[1,288]},{25:[2,124],51:[2,124],100:84,101:[1,62],103:[1,63],106:85,107:[1,65],108:66,123:[1,83],125:[1,77],126:[1,76],129:[1,75],130:[1,78],131:[1,79],132:[1,80],133:[1,81],134:[1,82]},{1:[2,93],6:[2,93],25:[2,93],26:[2,93],46:[2,93],51:[2,93],54:[2,93],69:[2,93],75:[2,93],83:[2,93],88:[2,93],90:[2,93],99:[2,93],101:[2,93],102:[2,93],103:[2,93],107:[2,93],115:[2,93],123:[2,93],125:[2,93],126:[2,93],129:[2,93],130:[2,93],131:[2,93],132:[2,93],133:[2,93],134:[2,93]},{1:[2,96],5:289,6:[2,96],25:[1,5],26:[2,96],46:[2,96],51:[2,96],54:[2,96],59:90,63:[1,92],64:[1,93],65:[1,94],66:95,67:[1,96],69:[2,96],70:[1,97],71:[1,98],75:[2,96],78:89,81:[1,91],82:[2,102],83:[2,96],88:[2,96],90:[2,96],99:[2,96],101:[2,96],102:[2,96],103:[2,96],107:[2,96],115:[2,96],123:[2,96],125:[2,96],126:[2,96],129:[2,96],130:[2,96],131:[2,96],132:[2,96],133:[2,96],134:[2,96]},{99:[1,290]},{88:[1,291],100:84,101:[1,62],103:[1,63],106:85,107:[1,65],108:66,123:[1,83],125:[1,77],126:[1,76],129:[1,75],130:[1,78],131:[1,79],132:[1,80],133:[1,81],134:[1,82]},{1:[2,110],6:[2,110],25:[2,110],26:[2,110],37:[2,110],46:[2,110],51:[2,110],54:[2,110],63:[2,110],64:[2,110],65:[2,110],67:[2,110],69:[2,110],70:[2,110],71:[2,110],75:[2,110],81:[2,110],82:[2,110],83:[2,110],88:[2,110],90:[2,110],99:[2,110],101:[2,110],102:[2,110],103:[2,110],107:[2,110],113:[2,110],114:[2,110],115:[2,110],123:[2,110],125:[2,110],126:[2,110],129:[2,110],130:[2,110],131:[2,110],132:[2,110],133:[2,110],134:[2,110]},{8:197,9:115,10:19,11:20,12:21,13:[1,22],14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,24:18,27:59,28:[1,70],29:49,30:[1,68],31:[1,69],32:24,33:[1,50],34:[1,51],35:[1,52],36:23,41:60,42:[1,44],43:[1,46],44:[1,29],47:30,48:[1,57],49:[1,58],55:47,56:48,57:145,58:36,60:25,61:26,62:27,73:[1,67],76:[1,43],80:[1,28],85:[1,55],86:[1,56],87:[1,54],91:292,93:[1,38],97:[1,45],98:[1,53],100:39,101:[1,62],103:[1,63],104:40,105:[1,64],106:41,107:[1,65],108:66,116:[1,42],121:37,122:[1,61],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{8:197,9:115,10:19,11:20,12:21,13:[1,22],14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,24:18,25:[1,144],27:59,28:[1,70],29:49,30:[1,68],31:[1,69],32:24,33:[1,50],34:[1,51],35:[1,52],36:23,41:60,42:[1,44],43:[1,46],44:[1,29],47:30,48:[1,57],49:[1,58],55:47,56:48,57:145,58:36,60:25,61:26,62:27,73:[1,67],76:[1,43],80:[1,28],84:293,85:[1,55],86:[1,56],87:[1,54],91:143,93:[1,38],97:[1,45],98:[1,53],100:39,101:[1,62],103:[1,63],104:40,105:[1,64],106:41,107:[1,65],108:66,116:[1,42],121:37,122:[1,61],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{6:[2,118],25:[2,118],26:[2,118],51:[2,118],83:[2,118],88:[2,118]},{6:[1,260],25:[1,261],26:[1,294]},{1:[2,135],6:[2,135],25:[2,135],26:[2,135],46:[2,135],51:[2,135],54:[2,135],69:[2,135],75:[2,135],83:[2,135],88:[2,135],90:[2,135],99:[2,135],100:84,101:[1,62],102:[2,135],103:[1,63],106:85,107:[1,65],108:66,115:[2,135],123:[2,135],125:[1,77],126:[1,76],129:[1,75],130:[1,78],131:[1,79],132:[1,80],133:[1,81],134:[1,82]},{1:[2,137],6:[2,137],25:[2,137],26:[2,137],46:[2,137],51:[2,137],54:[2,137],69:[2,137],75:[2,137],83:[2,137],88:[2,137],90:[2,137],99:[2,137],100:84,101:[1,62],102:[2,137],103:[1,63],106:85,107:[1,65],108:66,115:[2,137],123:[2,137],125:[1,77],126:[1,76],129:[1,75],130:[1,78],131:[1,79],132:[1,80],133:[1,81],134:[1,82]},{113:[2,155],114:[2,155]},{8:295,9:115,10:19,11:20,12:21,13:[1,22],14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,24:18,27:59,28:[1,70],29:49,30:[1,68],31:[1,69],32:24,33:[1,50],34:[1,51],35:[1,52],36:23,41:60,42:[1,44],43:[1,46],44:[1,29],47:30,48:[1,57],49:[1,58],55:47,56:48,58:36,60:25,61:26,62:27,73:[1,67],76:[1,43],80:[1,28],85:[1,55],86:[1,56],87:[1,54],93:[1,38],97:[1,45],98:[1,53],100:39,101:[1,62],103:[1,63],104:40,105:[1,64],106:41,107:[1,65],108:66,116:[1,42],121:37,122:[1,61],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{8:296,9:115,10:19,11:20,12:21,13:[1,22],14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,24:18,27:59,28:[1,70],29:49,30:[1,68],31:[1,69],32:24,33:[1,50],34:[1,51],35:[1,52],36:23,41:60,42:[1,44],43:[1,46],44:[1,29],47:30,48:[1,57],49:[1,58],55:47,56:48,58:36,60:25,61:26,62:27,73:[1,67],76:[1,43],80:[1,28],85:[1,55],86:[1,56],87:[1,54],93:[1,38],97:[1,45],98:[1,53],100:39,101:[1,62],103:[1,63],104:40,105:[1,64],106:41,107:[1,65],108:66,116:[1,42],121:37,122:[1,61],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{8:297,9:115,10:19,11:20,12:21,13:[1,22],14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,24:18,27:59,28:[1,70],29:49,30:[1,68],31:[1,69],32:24,33:[1,50],34:[1,51],35:[1,52],36:23,41:60,42:[1,44],43:[1,46],44:[1,29],47:30,48:[1,57],49:[1,58],55:47,56:48,58:36,60:25,61:26,62:27,73:[1,67],76:[1,43],80:[1,28],85:[1,55],86:[1,56],87:[1,54],93:[1,38],97:[1,45],98:[1,53],100:39,101:[1,62],103:[1,63],104:40,105:[1,64],106:41,107:[1,65],108:66,116:[1,42],121:37,122:[1,61],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{1:[2,84],6:[2,84],25:[2,84],26:[2,84],37:[2,84],46:[2,84],51:[2,84],54:[2,84],63:[2,84],64:[2,84],65:[2,84],67:[2,84],69:[2,84],70:[2,84],71:[2,84],75:[2,84],81:[2,84],82:[2,84],83:[2,84],88:[2,84],90:[2,84],99:[2,84],101:[2,84],102:[2,84],103:[2,84],107:[2,84],113:[2,84],114:[2,84],115:[2,84],123:[2,84],125:[2,84],126:[2,84],129:[2,84],130:[2,84],131:[2,84],132:[2,84],133:[2,84],134:[2,84]},{12:165,27:166,28:[1,70],29:167,30:[1,68],31:[1,69],38:298,39:164,41:168,43:[1,46],86:[1,111]},{6:[2,85],12:165,25:[2,85],26:[2,85],27:166,28:[1,70],29:167,30:[1,68],31:[1,69],38:163,39:164,41:168,43:[1,46],51:[2,85],74:299,86:[1,111]},{6:[2,87],25:[2,87],26:[2,87],51:[2,87],75:[2,87]},{6:[2,36],25:[2,36],26:[2,36],51:[2,36],75:[2,36],100:84,101:[1,62],103:[1,63],106:85,107:[1,65],108:66,123:[1,83],125:[1,77],126:[1,76],129:[1,75],130:[1,78],131:[1,79],132:[1,80],133:[1,81],134:[1,82]},{8:300,9:115,10:19,11:20,12:21,13:[1,22],14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,24:18,27:59,28:[1,70],29:49,30:[1,68],31:[1,69],32:24,33:[1,50],34:[1,51],35:[1,52],36:23,41:60,42:[1,44],43:[1,46],44:[1,29],47:30,48:[1,57],49:[1,58],55:47,56:48,58:36,60:25,61:26,62:27,73:[1,67],76:[1,43],80:[1,28],85:[1,55],86:[1,56],87:[1,54],93:[1,38],97:[1,45],98:[1,53],100:39,101:[1,62],103:[1,63],104:40,105:[1,64],106:41,107:[1,65],108:66,116:[1,42],121:37,122:[1,61],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{69:[2,114],100:84,101:[1,62],103:[1,63],106:85,107:[1,65],108:66,123:[1,83],125:[1,77],126:[1,76],129:[1,75],130:[1,78],131:[1,79],132:[1,80],133:[1,81],134:[1,82]},{1:[2,34],6:[2,34],25:[2,34],26:[2,34],46:[2,34],51:[2,34],54:[2,34],69:[2,34],75:[2,34],83:[2,34],88:[2,34],90:[2,34],99:[2,34],101:[2,34],102:[2,34],103:[2,34],107:[2,34],115:[2,34],123:[2,34],125:[2,34],126:[2,34],129:[2,34],130:[2,34],131:[2,34],132:[2,34],133:[2,34],134:[2,34]},{1:[2,105],6:[2,105],25:[2,105],26:[2,105],46:[2,105],51:[2,105],54:[2,105],63:[2,105],64:[2,105],65:[2,105],67:[2,105],69:[2,105],70:[2,105],71:[2,105],75:[2,105],81:[2,105],82:[2,105],83:[2,105],88:[2,105],90:[2,105],99:[2,105],101:[2,105],102:[2,105],103:[2,105],107:[2,105],115:[2,105],123:[2,105],125:[2,105],126:[2,105],129:[2,105],130:[2,105],131:[2,105],132:[2,105],133:[2,105],134:[2,105]},{1:[2,45],6:[2,45],25:[2,45],26:[2,45],46:[2,45],51:[2,45],54:[2,45],69:[2,45],75:[2,45],83:[2,45],88:[2,45],90:[2,45],99:[2,45],101:[2,45],102:[2,45],103:[2,45],107:[2,45],115:[2,45],123:[2,45],125:[2,45],126:[2,45],129:[2,45],130:[2,45],131:[2,45],132:[2,45],133:[2,45],134:[2,45]},{1:[2,193],6:[2,193],25:[2,193],26:[2,193],46:[2,193],51:[2,193],54:[2,193],69:[2,193],75:[2,193],83:[2,193],88:[2,193],90:[2,193],99:[2,193],101:[2,193],102:[2,193],103:[2,193],107:[2,193],115:[2,193],123:[2,193],125:[2,193],126:[2,193],129:[2,193],130:[2,193],131:[2,193],132:[2,193],133:[2,193],134:[2,193]},{1:[2,172],6:[2,172],25:[2,172],26:[2,172],46:[2,172],51:[2,172],54:[2,172],69:[2,172],75:[2,172],83:[2,172],88:[2,172],90:[2,172],99:[2,172],101:[2,172],102:[2,172],103:[2,172],107:[2,172],115:[2,172],118:[2,172],123:[2,172],125:[2,172],126:[2,172],129:[2,172],130:[2,172],131:[2,172],132:[2,172],133:[2,172],134:[2,172]},{1:[2,129],6:[2,129],25:[2,129],26:[2,129],46:[2,129],51:[2,129],54:[2,129],69:[2,129],75:[2,129],83:[2,129],88:[2,129],90:[2,129],99:[2,129],101:[2,129],102:[2,129],103:[2,129],107:[2,129],115:[2,129],123:[2,129],125:[2,129],126:[2,129],129:[2,129],130:[2,129],131:[2,129],132:[2,129],133:[2,129],134:[2,129]},{1:[2,130],6:[2,130],25:[2,130],26:[2,130],46:[2,130],51:[2,130],54:[2,130],69:[2,130],75:[2,130],83:[2,130],88:[2,130],90:[2,130],95:[2,130],99:[2,130],101:[2,130],102:[2,130],103:[2,130],107:[2,130],115:[2,130],123:[2,130],125:[2,130],126:[2,130],129:[2,130],130:[2,130],131:[2,130],132:[2,130],133:[2,130],134:[2,130]},{1:[2,163],6:[2,163],25:[2,163],26:[2,163],46:[2,163],51:[2,163],54:[2,163],69:[2,163],75:[2,163],83:[2,163],88:[2,163],90:[2,163],99:[2,163],101:[2,163],102:[2,163],103:[2,163],107:[2,163],115:[2,163],123:[2,163],125:[2,163],126:[2,163],129:[2,163],130:[2,163],131:[2,163],132:[2,163],133:[2,163],134:[2,163]},{5:301,25:[1,5]},{26:[1,302]},{6:[1,303],26:[2,169],118:[2,169],120:[2,169]},{8:304,9:115,10:19,11:20,12:21,13:[1,22],14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,24:18,27:59,28:[1,70],29:49,30:[1,68],31:[1,69],32:24,33:[1,50],34:[1,51],35:[1,52],36:23,41:60,42:[1,44],43:[1,46],44:[1,29],47:30,48:[1,57],49:[1,58],55:47,56:48,58:36,60:25,61:26,62:27,73:[1,67],76:[1,43],80:[1,28],85:[1,55],86:[1,56],87:[1,54],93:[1,38],97:[1,45],98:[1,53],100:39,101:[1,62],103:[1,63],104:40,105:[1,64],106:41,107:[1,65],108:66,116:[1,42],121:37,122:[1,61],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{1:[2,97],6:[2,97],25:[2,97],26:[2,97],46:[2,97],51:[2,97],54:[2,97],69:[2,97],75:[2,97],83:[2,97],88:[2,97],90:[2,97],99:[2,97],101:[2,97],102:[2,97],103:[2,97],107:[2,97],115:[2,97],123:[2,97],125:[2,97],126:[2,97],129:[2,97],130:[2,97],131:[2,97],132:[2,97],133:[2,97],134:[2,97]},{1:[2,133],6:[2,133],25:[2,133],26:[2,133],46:[2,133],51:[2,133],54:[2,133],63:[2,133],64:[2,133],65:[2,133],67:[2,133],69:[2,133],70:[2,133],71:[2,133],75:[2,133],81:[2,133],82:[2,133],83:[2,133],88:[2,133],90:[2,133],99:[2,133],101:[2,133],102:[2,133],103:[2,133],107:[2,133],115:[2,133],123:[2,133],125:[2,133],126:[2,133],129:[2,133],130:[2,133],131:[2,133],132:[2,133],133:[2,133],134:[2,133]},{1:[2,113],6:[2,113],25:[2,113],26:[2,113],46:[2,113],51:[2,113],54:[2,113],63:[2,113],64:[2,113],65:[2,113],67:[2,113],69:[2,113],70:[2,113],71:[2,113],75:[2,113],81:[2,113],82:[2,113],83:[2,113],88:[2,113],90:[2,113],99:[2,113],101:[2,113],102:[2,113],103:[2,113],107:[2,113],115:[2,113],123:[2,113],125:[2,113],126:[2,113],129:[2,113],130:[2,113],131:[2,113],132:[2,113],133:[2,113],134:[2,113]},{6:[2,119],25:[2,119],26:[2,119],51:[2,119],83:[2,119],88:[2,119]},{6:[2,49],25:[2,49],26:[2,49],50:305,51:[1,223]},{6:[2,120],25:[2,120],26:[2,120],51:[2,120],83:[2,120],88:[2,120]},{1:[2,158],6:[2,158],25:[2,158],26:[2,158],46:[2,158],51:[2,158],54:[2,158],69:[2,158],75:[2,158],83:[2,158],88:[2,158],90:[2,158],99:[2,158],100:84,101:[2,158],102:[2,158],103:[2,158],106:85,107:[2,158],108:66,115:[1,306],123:[2,158],125:[1,77],126:[1,76],129:[1,75],130:[1,78],131:[1,79],132:[1,80],133:[1,81],134:[1,82]},{1:[2,160],6:[2,160],25:[2,160],26:[2,160],46:[2,160],51:[2,160],54:[2,160],69:[2,160],75:[2,160],83:[2,160],88:[2,160],90:[2,160],99:[2,160],100:84,101:[2,160],102:[1,307],103:[2,160],106:85,107:[2,160],108:66,115:[2,160],123:[2,160],125:[1,77],126:[1,76],129:[1,75],130:[1,78],131:[1,79],132:[1,80],133:[1,81],134:[1,82]},{1:[2,159],6:[2,159],25:[2,159],26:[2,159],46:[2,159],51:[2,159],54:[2,159],69:[2,159],75:[2,159],83:[2,159],88:[2,159],90:[2,159],99:[2,159],100:84,101:[2,159],102:[2,159],103:[2,159],106:85,107:[2,159],108:66,115:[2,159],123:[2,159],125:[1,77],126:[1,76],129:[1,75],130:[1,78],131:[1,79],132:[1,80],133:[1,81],134:[1,82]},{6:[2,88],25:[2,88],26:[2,88],51:[2,88],75:[2,88]},{6:[2,49],25:[2,49],26:[2,49],50:308,51:[1,233]},{26:[1,309],100:84,101:[1,62],103:[1,63],106:85,107:[1,65],108:66,123:[1,83],125:[1,77],126:[1,76],129:[1,75],130:[1,78],131:[1,79],132:[1,80],133:[1,81],134:[1,82]},{26:[1,310]},{1:[2,166],6:[2,166],25:[2,166],26:[2,166],46:[2,166],51:[2,166],54:[2,166],69:[2,166],75:[2,166],83:[2,166],88:[2,166],90:[2,166],99:[2,166],101:[2,166],102:[2,166],103:[2,166],107:[2,166],115:[2,166],123:[2,166],125:[2,166],126:[2,166],129:[2,166],130:[2,166],131:[2,166],132:[2,166],133:[2,166],134:[2,166]},{26:[2,170],118:[2,170],120:[2,170]},{25:[2,125],51:[2,125],100:84,101:[1,62],103:[1,63],106:85,107:[1,65],108:66,123:[1,83],125:[1,77],126:[1,76],129:[1,75],130:[1,78],131:[1,79],132:[1,80],133:[1,81],134:[1,82]},{6:[1,260],25:[1,261],26:[1,311]},{8:312,9:115,10:19,11:20,12:21,13:[1,22],14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,24:18,27:59,28:[1,70],29:49,30:[1,68],31:[1,69],32:24,33:[1,50],34:[1,51],35:[1,52],36:23,41:60,42:[1,44],43:[1,46],44:[1,29],47:30,48:[1,57],49:[1,58],55:47,56:48,58:36,60:25,61:26,62:27,73:[1,67],76:[1,43],80:[1,28],85:[1,55],86:[1,56],87:[1,54],93:[1,38],97:[1,45],98:[1,53],100:39,101:[1,62],103:[1,63],104:40,105:[1,64],106:41,107:[1,65],108:66,116:[1,42],121:37,122:[1,61],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{8:313,9:115,10:19,11:20,12:21,13:[1,22],14:8,15:9,16:10,17:11,18:12,19:13,20:14,21:15,22:16,23:17,24:18,27:59,28:[1,70],29:49,30:[1,68],31:[1,69],32:24,33:[1,50],34:[1,51],35:[1,52],36:23,41:60,42:[1,44],43:[1,46],44:[1,29],47:30,48:[1,57],49:[1,58],55:47,56:48,58:36,60:25,61:26,62:27,73:[1,67],76:[1,43],80:[1,28],85:[1,55],86:[1,56],87:[1,54],93:[1,38],97:[1,45],98:[1,53],100:39,101:[1,62],103:[1,63],104:40,105:[1,64],106:41,107:[1,65],108:66,116:[1,42],121:37,122:[1,61],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{6:[1,271],25:[1,272],26:[1,314]},{6:[2,37],25:[2,37],26:[2,37],51:[2,37],75:[2,37]},{1:[2,164],6:[2,164],25:[2,164],26:[2,164],46:[2,164],51:[2,164],54:[2,164],69:[2,164],75:[2,164],83:[2,164],88:[2,164],90:[2,164],99:[2,164],101:[2,164],102:[2,164],103:[2,164],107:[2,164],115:[2,164],123:[2,164],125:[2,164],126:[2,164],129:[2,164],130:[2,164],131:[2,164],132:[2,164],133:[2,164],134:[2,164]},{6:[2,121],25:[2,121],26:[2,121],51:[2,121],83:[2,121],88:[2,121]},{1:[2,161],6:[2,161],25:[2,161],26:[2,161],46:[2,161],51:[2,161],54:[2,161],69:[2,161],75:[2,161],83:[2,161],88:[2,161],90:[2,161],99:[2,161],100:84,101:[2,161],102:[2,161],103:[2,161],106:85,107:[2,161],108:66,115:[2,161],123:[2,161],125:[1,77],126:[1,76],129:[1,75],130:[1,78],131:[1,79],132:[1,80],133:[1,81],134:[1,82]},{1:[2,162],6:[2,162],25:[2,162],26:[2,162],46:[2,162],51:[2,162],54:[2,162],69:[2,162],75:[2,162],83:[2,162],88:[2,162],90:[2,162],99:[2,162],100:84,101:[2,162],102:[2,162],103:[2,162],106:85,107:[2,162],108:66,115:[2,162],123:[2,162],125:[1,77],126:[1,76],129:[1,75],130:[1,78],131:[1,79],132:[1,80],133:[1,81],134:[1,82]},{6:[2,89],25:[2,89],26:[2,89],51:[2,89],75:[2,89]}],
-defaultActions: {57:[2,47],58:[2,48],72:[2,3],91:[2,103],186:[2,83]},
+table: [{1:[2,1],3:1,4:2,5:3,7:4,8:6,9:7,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,25:[1,5],27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{1:[3]},{1:[2,2],6:[1,72]},{6:[1,73]},{1:[2,4],6:[2,4],26:[2,4],99:[2,4]},{4:75,7:4,8:6,9:7,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,26:[1,74],27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{1:[2,7],6:[2,7],26:[2,7],99:[2,7],100:85,101:[1,63],103:[1,64],106:86,107:[1,66],108:67,123:[1,84],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{1:[2,8],6:[2,8],26:[2,8],99:[2,8],100:88,101:[1,63],103:[1,64],106:89,107:[1,66],108:67,123:[1,87]},{1:[2,12],6:[2,12],25:[2,12],26:[2,12],47:[2,12],52:[2,12],55:[2,12],60:91,64:[1,93],65:[1,94],66:[1,95],67:96,68:[1,97],70:[2,12],71:[1,98],75:[2,12],78:90,81:[1,92],82:[2,103],83:[2,12],88:[2,12],90:[2,12],99:[2,12],101:[2,12],102:[2,12],103:[2,12],107:[2,12],115:[2,12],123:[2,12],125:[2,12],126:[2,12],129:[2,12],130:[2,12],131:[2,12],132:[2,12],133:[2,12],134:[2,12]},{1:[2,13],6:[2,13],25:[2,13],26:[2,13],47:[2,13],52:[2,13],55:[2,13],60:100,64:[1,93],65:[1,94],66:[1,95],67:96,68:[1,97],70:[2,13],71:[1,98],75:[2,13],78:99,81:[1,92],82:[2,103],83:[2,13],88:[2,13],90:[2,13],99:[2,13],101:[2,13],102:[2,13],103:[2,13],107:[2,13],115:[2,13],123:[2,13],125:[2,13],126:[2,13],129:[2,13],130:[2,13],131:[2,13],132:[2,13],133:[2,13],134:[2,13]},{1:[2,14],6:[2,14],25:[2,14],26:[2,14],47:[2,14],52:[2,14],55:[2,14],70:[2,14],75:[2,14],83:[2,14],88:[2,14],90:[2,14],99:[2,14],101:[2,14],102:[2,14],103:[2,14],107:[2,14],115:[2,14],123:[2,14],125:[2,14],126:[2,14],129:[2,14],130:[2,14],131:[2,14],132:[2,14],133:[2,14],134:[2,14]},{1:[2,15],6:[2,15],25:[2,15],26:[2,15],47:[2,15],52:[2,15],55:[2,15],70:[2,15],75:[2,15],83:[2,15],88:[2,15],90:[2,15],99:[2,15],101:[2,15],102:[2,15],103:[2,15],107:[2,15],115:[2,15],123:[2,15],125:[2,15],126:[2,15],129:[2,15],130:[2,15],131:[2,15],132:[2,15],133:[2,15],134:[2,15]},{1:[2,16],6:[2,16],25:[2,16],26:[2,16],47:[2,16],52:[2,16],55:[2,16],70:[2,16],75:[2,16],83:[2,16],88:[2,16],90:[2,16],99:[2,16],101:[2,16],102:[2,16],103:[2,16],107:[2,16],115:[2,16],123:[2,16],125:[2,16],126:[2,16],129:[2,16],130:[2,16],131:[2,16],132:[2,16],133:[2,16],134:[2,16]},{1:[2,17],6:[2,17],25:[2,17],26:[2,17],47:[2,17],52:[2,17],55:[2,17],70:[2,17],75:[2,17],83:[2,17],88:[2,17],90:[2,17],99:[2,17],101:[2,17],102:[2,17],103:[2,17],107:[2,17],115:[2,17],123:[2,17],125:[2,17],126:[2,17],129:[2,17],130:[2,17],131:[2,17],132:[2,17],133:[2,17],134:[2,17]},{1:[2,18],6:[2,18],25:[2,18],26:[2,18],47:[2,18],52:[2,18],55:[2,18],70:[2,18],75:[2,18],83:[2,18],88:[2,18],90:[2,18],99:[2,18],101:[2,18],102:[2,18],103:[2,18],107:[2,18],115:[2,18],123:[2,18],125:[2,18],126:[2,18],129:[2,18],130:[2,18],131:[2,18],132:[2,18],133:[2,18],134:[2,18]},{1:[2,19],6:[2,19],25:[2,19],26:[2,19],47:[2,19],52:[2,19],55:[2,19],70:[2,19],75:[2,19],83:[2,19],88:[2,19],90:[2,19],99:[2,19],101:[2,19],102:[2,19],103:[2,19],107:[2,19],115:[2,19],123:[2,19],125:[2,19],126:[2,19],129:[2,19],130:[2,19],131:[2,19],132:[2,19],133:[2,19],134:[2,19]},{1:[2,20],6:[2,20],25:[2,20],26:[2,20],47:[2,20],52:[2,20],55:[2,20],70:[2,20],75:[2,20],83:[2,20],88:[2,20],90:[2,20],99:[2,20],101:[2,20],102:[2,20],103:[2,20],107:[2,20],115:[2,20],123:[2,20],125:[2,20],126:[2,20],129:[2,20],130:[2,20],131:[2,20],132:[2,20],133:[2,20],134:[2,20]},{1:[2,21],6:[2,21],25:[2,21],26:[2,21],47:[2,21],52:[2,21],55:[2,21],70:[2,21],75:[2,21],83:[2,21],88:[2,21],90:[2,21],99:[2,21],101:[2,21],102:[2,21],103:[2,21],107:[2,21],115:[2,21],123:[2,21],125:[2,21],126:[2,21],129:[2,21],130:[2,21],131:[2,21],132:[2,21],133:[2,21],134:[2,21]},{1:[2,22],6:[2,22],25:[2,22],26:[2,22],47:[2,22],52:[2,22],55:[2,22],70:[2,22],75:[2,22],83:[2,22],88:[2,22],90:[2,22],99:[2,22],101:[2,22],102:[2,22],103:[2,22],107:[2,22],115:[2,22],123:[2,22],125:[2,22],126:[2,22],129:[2,22],130:[2,22],131:[2,22],132:[2,22],133:[2,22],134:[2,22]},{1:[2,23],6:[2,23],25:[2,23],26:[2,23],47:[2,23],52:[2,23],55:[2,23],70:[2,23],75:[2,23],83:[2,23],88:[2,23],90:[2,23],99:[2,23],101:[2,23],102:[2,23],103:[2,23],107:[2,23],115:[2,23],123:[2,23],125:[2,23],126:[2,23],129:[2,23],130:[2,23],131:[2,23],132:[2,23],133:[2,23],134:[2,23]},{1:[2,9],6:[2,9],26:[2,9],99:[2,9],101:[2,9],103:[2,9],107:[2,9],123:[2,9]},{1:[2,10],6:[2,10],26:[2,10],99:[2,10],101:[2,10],103:[2,10],107:[2,10],123:[2,10]},{1:[2,11],6:[2,11],26:[2,11],99:[2,11],101:[2,11],103:[2,11],107:[2,11],123:[2,11]},{1:[2,71],6:[2,71],25:[2,71],26:[2,71],38:[1,101],47:[2,71],52:[2,71],55:[2,71],64:[2,71],65:[2,71],66:[2,71],68:[2,71],70:[2,71],71:[2,71],75:[2,71],81:[2,71],82:[2,71],83:[2,71],88:[2,71],90:[2,71],99:[2,71],101:[2,71],102:[2,71],103:[2,71],107:[2,71],115:[2,71],123:[2,71],125:[2,71],126:[2,71],129:[2,71],130:[2,71],131:[2,71],132:[2,71],133:[2,71],134:[2,71]},{1:[2,72],6:[2,72],25:[2,72],26:[2,72],47:[2,72],52:[2,72],55:[2,72],64:[2,72],65:[2,72],66:[2,72],68:[2,72],70:[2,72],71:[2,72],75:[2,72],81:[2,72],82:[2,72],83:[2,72],88:[2,72],90:[2,72],99:[2,72],101:[2,72],102:[2,72],103:[2,72],107:[2,72],115:[2,72],123:[2,72],125:[2,72],126:[2,72],129:[2,72],130:[2,72],131:[2,72],132:[2,72],133:[2,72],134:[2,72]},{1:[2,73],6:[2,73],25:[2,73],26:[2,73],47:[2,73],52:[2,73],55:[2,73],64:[2,73],65:[2,73],66:[2,73],68:[2,73],70:[2,73],71:[2,73],75:[2,73],81:[2,73],82:[2,73],83:[2,73],88:[2,73],90:[2,73],99:[2,73],101:[2,73],102:[2,73],103:[2,73],107:[2,73],115:[2,73],123:[2,73],125:[2,73],126:[2,73],129:[2,73],130:[2,73],131:[2,73],132:[2,73],133:[2,73],134:[2,73]},{1:[2,74],6:[2,74],25:[2,74],26:[2,74],47:[2,74],52:[2,74],55:[2,74],64:[2,74],65:[2,74],66:[2,74],68:[2,74],70:[2,74],71:[2,74],75:[2,74],81:[2,74],82:[2,74],83:[2,74],88:[2,74],90:[2,74],99:[2,74],101:[2,74],102:[2,74],103:[2,74],107:[2,74],115:[2,74],123:[2,74],125:[2,74],126:[2,74],129:[2,74],130:[2,74],131:[2,74],132:[2,74],133:[2,74],134:[2,74]},{1:[2,75],6:[2,75],25:[2,75],26:[2,75],47:[2,75],52:[2,75],55:[2,75],64:[2,75],65:[2,75],66:[2,75],68:[2,75],70:[2,75],71:[2,75],75:[2,75],81:[2,75],82:[2,75],83:[2,75],88:[2,75],90:[2,75],99:[2,75],101:[2,75],102:[2,75],103:[2,75],107:[2,75],115:[2,75],123:[2,75],125:[2,75],126:[2,75],129:[2,75],130:[2,75],131:[2,75],132:[2,75],133:[2,75],134:[2,75]},{1:[2,101],6:[2,101],25:[2,101],26:[2,101],47:[2,101],52:[2,101],55:[2,101],64:[2,101],65:[2,101],66:[2,101],68:[2,101],70:[2,101],71:[2,101],75:[2,101],79:102,81:[2,101],82:[1,103],83:[2,101],88:[2,101],90:[2,101],99:[2,101],101:[2,101],102:[2,101],103:[2,101],107:[2,101],115:[2,101],123:[2,101],125:[2,101],126:[2,101],129:[2,101],130:[2,101],131:[2,101],132:[2,101],133:[2,101],134:[2,101]},{27:107,28:[1,71],42:108,46:104,47:[2,53],52:[2,53],53:105,54:106,56:109,57:110,73:[1,68],86:[1,111],87:[1,112]},{5:113,25:[1,5]},{8:114,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{8:116,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{8:117,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{13:119,14:120,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:121,42:61,56:47,57:48,59:118,61:25,62:26,63:27,73:[1,68],80:[1,28],85:[1,56],86:[1,57],87:[1,55],98:[1,54]},{13:119,14:120,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:121,42:61,56:47,57:48,59:122,61:25,62:26,63:27,73:[1,68],80:[1,28],85:[1,56],86:[1,57],87:[1,55],98:[1,54]},{1:[2,68],6:[2,68],25:[2,68],26:[2,68],38:[2,68],47:[2,68],52:[2,68],55:[2,68],64:[2,68],65:[2,68],66:[2,68],68:[2,68],70:[2,68],71:[2,68],75:[2,68],77:[1,126],81:[2,68],82:[2,68],83:[2,68],88:[2,68],90:[2,68],99:[2,68],101:[2,68],102:[2,68],103:[2,68],107:[2,68],115:[2,68],123:[2,68],125:[2,68],126:[2,68],127:[1,123],128:[1,124],129:[2,68],130:[2,68],131:[2,68],132:[2,68],133:[2,68],134:[2,68],135:[1,125]},{1:[2,175],6:[2,175],25:[2,175],26:[2,175],47:[2,175],52:[2,175],55:[2,175],70:[2,175],75:[2,175],83:[2,175],88:[2,175],90:[2,175],99:[2,175],101:[2,175],102:[2,175],103:[2,175],107:[2,175],115:[2,175],118:[1,127],123:[2,175],125:[2,175],126:[2,175],129:[2,175],130:[2,175],131:[2,175],132:[2,175],133:[2,175],134:[2,175]},{5:128,25:[1,5]},{5:129,25:[1,5]},{1:[2,143],6:[2,143],25:[2,143],26:[2,143],47:[2,143],52:[2,143],55:[2,143],70:[2,143],75:[2,143],83:[2,143],88:[2,143],90:[2,143],99:[2,143],101:[2,143],102:[2,143],103:[2,143],107:[2,143],115:[2,143],123:[2,143],125:[2,143],126:[2,143],129:[2,143],130:[2,143],131:[2,143],132:[2,143],133:[2,143],134:[2,143]},{5:130,25:[1,5]},{8:131,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,25:[1,132],27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{1:[2,91],5:133,6:[2,91],13:119,14:120,25:[1,5],26:[2,91],27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:121,42:61,47:[2,91],52:[2,91],55:[2,91],56:47,57:48,59:135,61:25,62:26,63:27,70:[2,91],73:[1,68],75:[2,91],77:[1,134],80:[1,28],83:[2,91],85:[1,56],86:[1,57],87:[1,55],88:[2,91],90:[2,91],98:[1,54],99:[2,91],101:[2,91],102:[2,91],103:[2,91],107:[2,91],115:[2,91],123:[2,91],125:[2,91],126:[2,91],129:[2,91],130:[2,91],131:[2,91],132:[2,91],133:[2,91],134:[2,91]},{8:136,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{1:[2,45],6:[2,45],8:137,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,26:[2,45],27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],99:[2,45],100:39,101:[2,45],103:[2,45],104:40,105:[1,65],106:41,107:[2,45],108:67,116:[1,42],121:37,122:[1,62],123:[2,45],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{1:[2,46],6:[2,46],25:[2,46],26:[2,46],52:[2,46],75:[2,46],99:[2,46],101:[2,46],103:[2,46],107:[2,46],123:[2,46]},{1:[2,69],6:[2,69],25:[2,69],26:[2,69],38:[2,69],47:[2,69],52:[2,69],55:[2,69],64:[2,69],65:[2,69],66:[2,69],68:[2,69],70:[2,69],71:[2,69],75:[2,69],81:[2,69],82:[2,69],83:[2,69],88:[2,69],90:[2,69],99:[2,69],101:[2,69],102:[2,69],103:[2,69],107:[2,69],115:[2,69],123:[2,69],125:[2,69],126:[2,69],129:[2,69],130:[2,69],131:[2,69],132:[2,69],133:[2,69],134:[2,69]},{1:[2,70],6:[2,70],25:[2,70],26:[2,70],38:[2,70],47:[2,70],52:[2,70],55:[2,70],64:[2,70],65:[2,70],66:[2,70],68:[2,70],70:[2,70],71:[2,70],75:[2,70],81:[2,70],82:[2,70],83:[2,70],88:[2,70],90:[2,70],99:[2,70],101:[2,70],102:[2,70],103:[2,70],107:[2,70],115:[2,70],123:[2,70],125:[2,70],126:[2,70],129:[2,70],130:[2,70],131:[2,70],132:[2,70],133:[2,70],134:[2,70]},{1:[2,29],6:[2,29],25:[2,29],26:[2,29],47:[2,29],52:[2,29],55:[2,29],64:[2,29],65:[2,29],66:[2,29],68:[2,29],70:[2,29],71:[2,29],75:[2,29],81:[2,29],82:[2,29],83:[2,29],88:[2,29],90:[2,29],99:[2,29],101:[2,29],102:[2,29],103:[2,29],107:[2,29],115:[2,29],123:[2,29],125:[2,29],126:[2,29],129:[2,29],130:[2,29],131:[2,29],132:[2,29],133:[2,29],134:[2,29]},{1:[2,30],6:[2,30],25:[2,30],26:[2,30],47:[2,30],52:[2,30],55:[2,30],64:[2,30],65:[2,30],66:[2,30],68:[2,30],70:[2,30],71:[2,30],75:[2,30],81:[2,30],82:[2,30],83:[2,30],88:[2,30],90:[2,30],99:[2,30],101:[2,30],102:[2,30],103:[2,30],107:[2,30],115:[2,30],123:[2,30],125:[2,30],126:[2,30],129:[2,30],130:[2,30],131:[2,30],132:[2,30],133:[2,30],134:[2,30]},{1:[2,31],6:[2,31],25:[2,31],26:[2,31],47:[2,31],52:[2,31],55:[2,31],64:[2,31],65:[2,31],66:[2,31],68:[2,31],70:[2,31],71:[2,31],75:[2,31],81:[2,31],82:[2,31],83:[2,31],88:[2,31],90:[2,31],99:[2,31],101:[2,31],102:[2,31],103:[2,31],107:[2,31],115:[2,31],123:[2,31],125:[2,31],126:[2,31],129:[2,31],130:[2,31],131:[2,31],132:[2,31],133:[2,31],134:[2,31]},{1:[2,32],6:[2,32],25:[2,32],26:[2,32],47:[2,32],52:[2,32],55:[2,32],64:[2,32],65:[2,32],66:[2,32],68:[2,32],70:[2,32],71:[2,32],75:[2,32],81:[2,32],82:[2,32],83:[2,32],88:[2,32],90:[2,32],99:[2,32],101:[2,32],102:[2,32],103:[2,32],107:[2,32],115:[2,32],123:[2,32],125:[2,32],126:[2,32],129:[2,32],130:[2,32],131:[2,32],132:[2,32],133:[2,32],134:[2,32]},{1:[2,33],6:[2,33],25:[2,33],26:[2,33],47:[2,33],52:[2,33],55:[2,33],64:[2,33],65:[2,33],66:[2,33],68:[2,33],70:[2,33],71:[2,33],75:[2,33],81:[2,33],82:[2,33],83:[2,33],88:[2,33],90:[2,33],99:[2,33],101:[2,33],102:[2,33],103:[2,33],107:[2,33],115:[2,33],123:[2,33],125:[2,33],126:[2,33],129:[2,33],130:[2,33],131:[2,33],132:[2,33],133:[2,33],134:[2,33]},{4:138,7:4,8:6,9:7,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,25:[1,139],27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{8:140,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,25:[1,144],27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,58:145,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],84:142,85:[1,56],86:[1,57],87:[1,55],88:[1,141],91:143,93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{1:[2,107],6:[2,107],25:[2,107],26:[2,107],47:[2,107],52:[2,107],55:[2,107],64:[2,107],65:[2,107],66:[2,107],68:[2,107],70:[2,107],71:[2,107],75:[2,107],81:[2,107],82:[2,107],83:[2,107],88:[2,107],90:[2,107],99:[2,107],101:[2,107],102:[2,107],103:[2,107],107:[2,107],115:[2,107],123:[2,107],125:[2,107],126:[2,107],129:[2,107],130:[2,107],131:[2,107],132:[2,107],133:[2,107],134:[2,107]},{1:[2,108],6:[2,108],25:[2,108],26:[2,108],27:146,28:[1,71],47:[2,108],52:[2,108],55:[2,108],64:[2,108],65:[2,108],66:[2,108],68:[2,108],70:[2,108],71:[2,108],75:[2,108],81:[2,108],82:[2,108],83:[2,108],88:[2,108],90:[2,108],99:[2,108],101:[2,108],102:[2,108],103:[2,108],107:[2,108],115:[2,108],123:[2,108],125:[2,108],126:[2,108],129:[2,108],130:[2,108],131:[2,108],132:[2,108],133:[2,108],134:[2,108]},{25:[2,49]},{25:[2,50]},{1:[2,64],6:[2,64],25:[2,64],26:[2,64],38:[2,64],47:[2,64],52:[2,64],55:[2,64],64:[2,64],65:[2,64],66:[2,64],68:[2,64],70:[2,64],71:[2,64],75:[2,64],77:[2,64],81:[2,64],82:[2,64],83:[2,64],88:[2,64],90:[2,64],99:[2,64],101:[2,64],102:[2,64],103:[2,64],107:[2,64],115:[2,64],123:[2,64],125:[2,64],126:[2,64],127:[2,64],128:[2,64],129:[2,64],130:[2,64],131:[2,64],132:[2,64],133:[2,64],134:[2,64],135:[2,64]},{1:[2,67],6:[2,67],25:[2,67],26:[2,67],38:[2,67],47:[2,67],52:[2,67],55:[2,67],64:[2,67],65:[2,67],66:[2,67],68:[2,67],70:[2,67],71:[2,67],75:[2,67],77:[2,67],81:[2,67],82:[2,67],83:[2,67],88:[2,67],90:[2,67],99:[2,67],101:[2,67],102:[2,67],103:[2,67],107:[2,67],115:[2,67],123:[2,67],125:[2,67],126:[2,67],127:[2,67],128:[2,67],129:[2,67],130:[2,67],131:[2,67],132:[2,67],133:[2,67],134:[2,67],135:[2,67]},{8:147,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{8:148,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{8:149,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{5:150,8:151,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,25:[1,5],27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{27:156,28:[1,71],56:157,57:158,62:152,73:[1,68],87:[1,55],110:153,111:[1,154],112:155},{109:159,113:[1,160],114:[1,161]},{6:[2,86],11:165,25:[2,86],27:166,28:[1,71],29:167,30:[1,69],31:[1,70],39:163,40:164,42:168,44:[1,46],52:[2,86],74:162,75:[2,86],86:[1,111]},{1:[2,27],6:[2,27],25:[2,27],26:[2,27],41:[2,27],47:[2,27],52:[2,27],55:[2,27],64:[2,27],65:[2,27],66:[2,27],68:[2,27],70:[2,27],71:[2,27],75:[2,27],81:[2,27],82:[2,27],83:[2,27],88:[2,27],90:[2,27],99:[2,27],101:[2,27],102:[2,27],103:[2,27],107:[2,27],115:[2,27],123:[2,27],125:[2,27],126:[2,27],129:[2,27],130:[2,27],131:[2,27],132:[2,27],133:[2,27],134:[2,27]},{1:[2,28],6:[2,28],25:[2,28],26:[2,28],41:[2,28],47:[2,28],52:[2,28],55:[2,28],64:[2,28],65:[2,28],66:[2,28],68:[2,28],70:[2,28],71:[2,28],75:[2,28],81:[2,28],82:[2,28],83:[2,28],88:[2,28],90:[2,28],99:[2,28],101:[2,28],102:[2,28],103:[2,28],107:[2,28],115:[2,28],123:[2,28],125:[2,28],126:[2,28],129:[2,28],130:[2,28],131:[2,28],132:[2,28],133:[2,28],134:[2,28]},{1:[2,26],6:[2,26],25:[2,26],26:[2,26],38:[2,26],41:[2,26],47:[2,26],52:[2,26],55:[2,26],64:[2,26],65:[2,26],66:[2,26],68:[2,26],70:[2,26],71:[2,26],75:[2,26],77:[2,26],81:[2,26],82:[2,26],83:[2,26],88:[2,26],90:[2,26],99:[2,26],101:[2,26],102:[2,26],103:[2,26],107:[2,26],113:[2,26],114:[2,26],115:[2,26],123:[2,26],125:[2,26],126:[2,26],127:[2,26],128:[2,26],129:[2,26],130:[2,26],131:[2,26],132:[2,26],133:[2,26],134:[2,26],135:[2,26]},{1:[2,6],6:[2,6],7:169,8:6,9:7,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,26:[2,6],27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],99:[2,6],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{1:[2,3]},{1:[2,24],6:[2,24],25:[2,24],26:[2,24],47:[2,24],52:[2,24],55:[2,24],70:[2,24],75:[2,24],83:[2,24],88:[2,24],90:[2,24],95:[2,24],96:[2,24],99:[2,24],101:[2,24],102:[2,24],103:[2,24],107:[2,24],115:[2,24],118:[2,24],120:[2,24],123:[2,24],125:[2,24],126:[2,24],129:[2,24],130:[2,24],131:[2,24],132:[2,24],133:[2,24],134:[2,24]},{6:[1,72],26:[1,170]},{1:[2,186],6:[2,186],25:[2,186],26:[2,186],47:[2,186],52:[2,186],55:[2,186],70:[2,186],75:[2,186],83:[2,186],88:[2,186],90:[2,186],99:[2,186],101:[2,186],102:[2,186],103:[2,186],107:[2,186],115:[2,186],123:[2,186],125:[2,186],126:[2,186],129:[2,186],130:[2,186],131:[2,186],132:[2,186],133:[2,186],134:[2,186]},{8:171,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{8:172,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{8:173,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{8:174,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{8:175,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{8:176,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{8:177,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{8:178,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{1:[2,142],6:[2,142],25:[2,142],26:[2,142],47:[2,142],52:[2,142],55:[2,142],70:[2,142],75:[2,142],83:[2,142],88:[2,142],90:[2,142],99:[2,142],101:[2,142],102:[2,142],103:[2,142],107:[2,142],115:[2,142],123:[2,142],125:[2,142],126:[2,142],129:[2,142],130:[2,142],131:[2,142],132:[2,142],133:[2,142],134:[2,142]},{1:[2,147],6:[2,147],25:[2,147],26:[2,147],47:[2,147],52:[2,147],55:[2,147],70:[2,147],75:[2,147],83:[2,147],88:[2,147],90:[2,147],99:[2,147],101:[2,147],102:[2,147],103:[2,147],107:[2,147],115:[2,147],123:[2,147],125:[2,147],126:[2,147],129:[2,147],130:[2,147],131:[2,147],132:[2,147],133:[2,147],134:[2,147]},{8:179,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{1:[2,141],6:[2,141],25:[2,141],26:[2,141],47:[2,141],52:[2,141],55:[2,141],70:[2,141],75:[2,141],83:[2,141],88:[2,141],90:[2,141],99:[2,141],101:[2,141],102:[2,141],103:[2,141],107:[2,141],115:[2,141],123:[2,141],125:[2,141],126:[2,141],129:[2,141],130:[2,141],131:[2,141],132:[2,141],133:[2,141],134:[2,141]},{1:[2,146],6:[2,146],25:[2,146],26:[2,146],47:[2,146],52:[2,146],55:[2,146],70:[2,146],75:[2,146],83:[2,146],88:[2,146],90:[2,146],99:[2,146],101:[2,146],102:[2,146],103:[2,146],107:[2,146],115:[2,146],123:[2,146],125:[2,146],126:[2,146],129:[2,146],130:[2,146],131:[2,146],132:[2,146],133:[2,146],134:[2,146]},{79:180,82:[1,103]},{1:[2,65],6:[2,65],25:[2,65],26:[2,65],38:[2,65],47:[2,65],52:[2,65],55:[2,65],64:[2,65],65:[2,65],66:[2,65],68:[2,65],70:[2,65],71:[2,65],75:[2,65],77:[2,65],81:[2,65],82:[2,65],83:[2,65],88:[2,65],90:[2,65],99:[2,65],101:[2,65],102:[2,65],103:[2,65],107:[2,65],115:[2,65],123:[2,65],125:[2,65],126:[2,65],127:[2,65],128:[2,65],129:[2,65],130:[2,65],131:[2,65],132:[2,65],133:[2,65],134:[2,65],135:[2,65]},{82:[2,104]},{27:181,28:[1,71]},{27:182,28:[1,71]},{1:[2,79],6:[2,79],25:[2,79],26:[2,79],27:183,28:[1,71],38:[2,79],47:[2,79],52:[2,79],55:[2,79],64:[2,79],65:[2,79],66:[2,79],68:[2,79],70:[2,79],71:[2,79],75:[2,79],77:[2,79],81:[2,79],82:[2,79],83:[2,79],88:[2,79],90:[2,79],99:[2,79],101:[2,79],102:[2,79],103:[2,79],107:[2,79],115:[2,79],123:[2,79],125:[2,79],126:[2,79],127:[2,79],128:[2,79],129:[2,79],130:[2,79],131:[2,79],132:[2,79],133:[2,79],134:[2,79],135:[2,79]},{1:[2,80],6:[2,80],25:[2,80],26:[2,80],38:[2,80],47:[2,80],52:[2,80],55:[2,80],64:[2,80],65:[2,80],66:[2,80],68:[2,80],70:[2,80],71:[2,80],75:[2,80],77:[2,80],81:[2,80],82:[2,80],83:[2,80],88:[2,80],90:[2,80],99:[2,80],101:[2,80],102:[2,80],103:[2,80],107:[2,80],115:[2,80],123:[2,80],125:[2,80],126:[2,80],127:[2,80],128:[2,80],129:[2,80],130:[2,80],131:[2,80],132:[2,80],133:[2,80],134:[2,80],135:[2,80]},{8:185,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],55:[1,189],56:47,57:48,59:36,61:25,62:26,63:27,69:184,72:186,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],89:187,90:[1,188],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{67:190,68:[1,97],71:[1,98]},{79:191,82:[1,103]},{1:[2,66],6:[2,66],25:[2,66],26:[2,66],38:[2,66],47:[2,66],52:[2,66],55:[2,66],64:[2,66],65:[2,66],66:[2,66],68:[2,66],70:[2,66],71:[2,66],75:[2,66],77:[2,66],81:[2,66],82:[2,66],83:[2,66],88:[2,66],90:[2,66],99:[2,66],101:[2,66],102:[2,66],103:[2,66],107:[2,66],115:[2,66],123:[2,66],125:[2,66],126:[2,66],127:[2,66],128:[2,66],129:[2,66],130:[2,66],131:[2,66],132:[2,66],133:[2,66],134:[2,66],135:[2,66]},{6:[1,193],8:192,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,25:[1,194],27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{1:[2,102],6:[2,102],25:[2,102],26:[2,102],47:[2,102],52:[2,102],55:[2,102],64:[2,102],65:[2,102],66:[2,102],68:[2,102],70:[2,102],71:[2,102],75:[2,102],81:[2,102],82:[2,102],83:[2,102],88:[2,102],90:[2,102],99:[2,102],101:[2,102],102:[2,102],103:[2,102],107:[2,102],115:[2,102],123:[2,102],125:[2,102],126:[2,102],129:[2,102],130:[2,102],131:[2,102],132:[2,102],133:[2,102],134:[2,102]},{8:197,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,25:[1,144],27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,58:145,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],83:[1,195],84:196,85:[1,56],86:[1,57],87:[1,55],91:143,93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{47:[1,198],52:[1,199]},{47:[2,54],52:[2,54]},{38:[1,201],47:[2,56],52:[2,56],55:[1,200]},{38:[2,59],47:[2,59],52:[2,59],55:[2,59]},{38:[2,60],47:[2,60],52:[2,60],55:[2,60]},{38:[2,61],47:[2,61],52:[2,61],55:[2,61]},{38:[2,62],47:[2,62],52:[2,62],55:[2,62]},{27:146,28:[1,71]},{8:197,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,25:[1,144],27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,58:145,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],84:142,85:[1,56],86:[1,57],87:[1,55],88:[1,141],91:143,93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{1:[2,48],6:[2,48],25:[2,48],26:[2,48],47:[2,48],52:[2,48],55:[2,48],70:[2,48],75:[2,48],83:[2,48],88:[2,48],90:[2,48],99:[2,48],101:[2,48],102:[2,48],103:[2,48],107:[2,48],115:[2,48],123:[2,48],125:[2,48],126:[2,48],129:[2,48],130:[2,48],131:[2,48],132:[2,48],133:[2,48],134:[2,48]},{1:[2,179],6:[2,179],25:[2,179],26:[2,179],47:[2,179],52:[2,179],55:[2,179],70:[2,179],75:[2,179],83:[2,179],88:[2,179],90:[2,179],99:[2,179],100:85,101:[2,179],102:[2,179],103:[2,179],106:86,107:[2,179],108:67,115:[2,179],123:[2,179],125:[2,179],126:[2,179],129:[1,76],130:[2,179],131:[2,179],132:[2,179],133:[2,179],134:[2,179]},{100:88,101:[1,63],103:[1,64],106:89,107:[1,66],108:67,123:[1,87]},{1:[2,180],6:[2,180],25:[2,180],26:[2,180],47:[2,180],52:[2,180],55:[2,180],70:[2,180],75:[2,180],83:[2,180],88:[2,180],90:[2,180],99:[2,180],100:85,101:[2,180],102:[2,180],103:[2,180],106:86,107:[2,180],108:67,115:[2,180],123:[2,180],125:[2,180],126:[2,180],129:[1,76],130:[2,180],131:[2,180],132:[2,180],133:[2,180],134:[2,180]},{1:[2,181],6:[2,181],25:[2,181],26:[2,181],47:[2,181],52:[2,181],55:[2,181],70:[2,181],75:[2,181],83:[2,181],88:[2,181],90:[2,181],99:[2,181],100:85,101:[2,181],102:[2,181],103:[2,181],106:86,107:[2,181],108:67,115:[2,181],123:[2,181],125:[2,181],126:[2,181],129:[1,76],130:[2,181],131:[2,181],132:[2,181],133:[2,181],134:[2,181]},{1:[2,182],6:[2,182],25:[2,182],26:[2,182],47:[2,182],52:[2,182],55:[2,182],64:[2,68],65:[2,68],66:[2,68],68:[2,68],70:[2,182],71:[2,68],75:[2,182],81:[2,68],82:[2,68],83:[2,182],88:[2,182],90:[2,182],99:[2,182],101:[2,182],102:[2,182],103:[2,182],107:[2,182],115:[2,182],123:[2,182],125:[2,182],126:[2,182],129:[2,182],130:[2,182],131:[2,182],132:[2,182],133:[2,182],134:[2,182]},{60:91,64:[1,93],65:[1,94],66:[1,95],67:96,68:[1,97],71:[1,98],78:90,81:[1,92],82:[2,103]},{60:100,64:[1,93],65:[1,94],66:[1,95],67:96,68:[1,97],71:[1,98],78:99,81:[1,92],82:[2,103]},{64:[2,71],65:[2,71],66:[2,71],68:[2,71],71:[2,71],81:[2,71],82:[2,71]},{1:[2,183],6:[2,183],25:[2,183],26:[2,183],47:[2,183],52:[2,183],55:[2,183],64:[2,68],65:[2,68],66:[2,68],68:[2,68],70:[2,183],71:[2,68],75:[2,183],81:[2,68],82:[2,68],83:[2,183],88:[2,183],90:[2,183],99:[2,183],101:[2,183],102:[2,183],103:[2,183],107:[2,183],115:[2,183],123:[2,183],125:[2,183],126:[2,183],129:[2,183],130:[2,183],131:[2,183],132:[2,183],133:[2,183],134:[2,183]},{1:[2,184],6:[2,184],25:[2,184],26:[2,184],47:[2,184],52:[2,184],55:[2,184],70:[2,184],75:[2,184],83:[2,184],88:[2,184],90:[2,184],99:[2,184],101:[2,184],102:[2,184],103:[2,184],107:[2,184],115:[2,184],123:[2,184],125:[2,184],126:[2,184],129:[2,184],130:[2,184],131:[2,184],132:[2,184],133:[2,184],134:[2,184]},{1:[2,185],6:[2,185],25:[2,185],26:[2,185],47:[2,185],52:[2,185],55:[2,185],70:[2,185],75:[2,185],83:[2,185],88:[2,185],90:[2,185],99:[2,185],101:[2,185],102:[2,185],103:[2,185],107:[2,185],115:[2,185],123:[2,185],125:[2,185],126:[2,185],129:[2,185],130:[2,185],131:[2,185],132:[2,185],133:[2,185],134:[2,185]},{8:202,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,25:[1,203],27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{8:204,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{5:205,25:[1,5],122:[1,206]},{1:[2,128],6:[2,128],25:[2,128],26:[2,128],47:[2,128],52:[2,128],55:[2,128],70:[2,128],75:[2,128],83:[2,128],88:[2,128],90:[2,128],94:207,95:[1,208],96:[1,209],99:[2,128],101:[2,128],102:[2,128],103:[2,128],107:[2,128],115:[2,128],123:[2,128],125:[2,128],126:[2,128],129:[2,128],130:[2,128],131:[2,128],132:[2,128],133:[2,128],134:[2,128]},{1:[2,140],6:[2,140],25:[2,140],26:[2,140],47:[2,140],52:[2,140],55:[2,140],70:[2,140],75:[2,140],83:[2,140],88:[2,140],90:[2,140],99:[2,140],101:[2,140],102:[2,140],103:[2,140],107:[2,140],115:[2,140],123:[2,140],125:[2,140],126:[2,140],129:[2,140],130:[2,140],131:[2,140],132:[2,140],133:[2,140],134:[2,140]},{1:[2,148],6:[2,148],25:[2,148],26:[2,148],47:[2,148],52:[2,148],55:[2,148],70:[2,148],75:[2,148],83:[2,148],88:[2,148],90:[2,148],99:[2,148],101:[2,148],102:[2,148],103:[2,148],107:[2,148],115:[2,148],123:[2,148],125:[2,148],126:[2,148],129:[2,148],130:[2,148],131:[2,148],132:[2,148],133:[2,148],134:[2,148]},{25:[1,210],100:85,101:[1,63],103:[1,64],106:86,107:[1,66],108:67,123:[1,84],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{117:211,119:212,120:[1,213]},{1:[2,92],6:[2,92],25:[2,92],26:[2,92],47:[2,92],52:[2,92],55:[2,92],70:[2,92],75:[2,92],83:[2,92],88:[2,92],90:[2,92],99:[2,92],101:[2,92],102:[2,92],103:[2,92],107:[2,92],115:[2,92],123:[2,92],125:[2,92],126:[2,92],129:[2,92],130:[2,92],131:[2,92],132:[2,92],133:[2,92],134:[2,92]},{8:214,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{1:[2,95],5:215,6:[2,95],25:[1,5],26:[2,95],47:[2,95],52:[2,95],55:[2,95],64:[2,68],65:[2,68],66:[2,68],68:[2,68],70:[2,95],71:[2,68],75:[2,95],77:[1,216],81:[2,68],82:[2,68],83:[2,95],88:[2,95],90:[2,95],99:[2,95],101:[2,95],102:[2,95],103:[2,95],107:[2,95],115:[2,95],123:[2,95],125:[2,95],126:[2,95],129:[2,95],130:[2,95],131:[2,95],132:[2,95],133:[2,95],134:[2,95]},{1:[2,133],6:[2,133],25:[2,133],26:[2,133],47:[2,133],52:[2,133],55:[2,133],70:[2,133],75:[2,133],83:[2,133],88:[2,133],90:[2,133],99:[2,133],100:85,101:[2,133],102:[2,133],103:[2,133],106:86,107:[2,133],108:67,115:[2,133],123:[2,133],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{1:[2,44],6:[2,44],26:[2,44],99:[2,44],100:85,101:[2,44],103:[2,44],106:86,107:[2,44],108:67,123:[2,44],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{6:[1,72],99:[1,217]},{4:218,7:4,8:6,9:7,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{6:[2,124],25:[2,124],52:[2,124],55:[1,220],88:[2,124],89:219,90:[1,188],100:85,101:[1,63],103:[1,64],106:86,107:[1,66],108:67,123:[1,84],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{1:[2,110],6:[2,110],25:[2,110],26:[2,110],38:[2,110],47:[2,110],52:[2,110],55:[2,110],64:[2,110],65:[2,110],66:[2,110],68:[2,110],70:[2,110],71:[2,110],75:[2,110],81:[2,110],82:[2,110],83:[2,110],88:[2,110],90:[2,110],99:[2,110],101:[2,110],102:[2,110],103:[2,110],107:[2,110],113:[2,110],114:[2,110],115:[2,110],123:[2,110],125:[2,110],126:[2,110],129:[2,110],130:[2,110],131:[2,110],132:[2,110],133:[2,110],134:[2,110]},{6:[2,51],25:[2,51],51:221,52:[1,222],88:[2,51]},{6:[2,119],25:[2,119],26:[2,119],52:[2,119],83:[2,119],88:[2,119]},{8:197,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,25:[1,144],27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,58:145,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],84:223,85:[1,56],86:[1,57],87:[1,55],91:143,93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{6:[2,125],25:[2,125],26:[2,125],52:[2,125],83:[2,125],88:[2,125]},{1:[2,109],6:[2,109],25:[2,109],26:[2,109],38:[2,109],41:[2,109],47:[2,109],52:[2,109],55:[2,109],64:[2,109],65:[2,109],66:[2,109],68:[2,109],70:[2,109],71:[2,109],75:[2,109],77:[2,109],81:[2,109],82:[2,109],83:[2,109],88:[2,109],90:[2,109],99:[2,109],101:[2,109],102:[2,109],103:[2,109],107:[2,109],115:[2,109],123:[2,109],125:[2,109],126:[2,109],127:[2,109],128:[2,109],129:[2,109],130:[2,109],131:[2,109],132:[2,109],133:[2,109],134:[2,109],135:[2,109]},{5:224,25:[1,5],100:85,101:[1,63],103:[1,64],106:86,107:[1,66],108:67,123:[1,84],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{1:[2,136],6:[2,136],25:[2,136],26:[2,136],47:[2,136],52:[2,136],55:[2,136],70:[2,136],75:[2,136],83:[2,136],88:[2,136],90:[2,136],99:[2,136],100:85,101:[1,63],102:[1,225],103:[1,64],106:86,107:[1,66],108:67,115:[2,136],123:[2,136],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{1:[2,138],6:[2,138],25:[2,138],26:[2,138],47:[2,138],52:[2,138],55:[2,138],70:[2,138],75:[2,138],83:[2,138],88:[2,138],90:[2,138],99:[2,138],100:85,101:[1,63],102:[1,226],103:[1,64],106:86,107:[1,66],108:67,115:[2,138],123:[2,138],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{1:[2,144],6:[2,144],25:[2,144],26:[2,144],47:[2,144],52:[2,144],55:[2,144],70:[2,144],75:[2,144],83:[2,144],88:[2,144],90:[2,144],99:[2,144],101:[2,144],102:[2,144],103:[2,144],107:[2,144],115:[2,144],123:[2,144],125:[2,144],126:[2,144],129:[2,144],130:[2,144],131:[2,144],132:[2,144],133:[2,144],134:[2,144]},{1:[2,145],6:[2,145],25:[2,145],26:[2,145],47:[2,145],52:[2,145],55:[2,145],70:[2,145],75:[2,145],83:[2,145],88:[2,145],90:[2,145],99:[2,145],100:85,101:[1,63],102:[2,145],103:[1,64],106:86,107:[1,66],108:67,115:[2,145],123:[2,145],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{1:[2,149],6:[2,149],25:[2,149],26:[2,149],47:[2,149],52:[2,149],55:[2,149],70:[2,149],75:[2,149],83:[2,149],88:[2,149],90:[2,149],99:[2,149],101:[2,149],102:[2,149],103:[2,149],107:[2,149],115:[2,149],123:[2,149],125:[2,149],126:[2,149],129:[2,149],130:[2,149],131:[2,149],132:[2,149],133:[2,149],134:[2,149]},{113:[2,151],114:[2,151]},{27:156,28:[1,71],56:157,57:158,73:[1,68],87:[1,112],110:227,112:155},{52:[1,228],113:[2,156],114:[2,156]},{52:[2,153],113:[2,153],114:[2,153]},{52:[2,154],113:[2,154],114:[2,154]},{52:[2,155],113:[2,155],114:[2,155]},{1:[2,150],6:[2,150],25:[2,150],26:[2,150],47:[2,150],52:[2,150],55:[2,150],70:[2,150],75:[2,150],83:[2,150],88:[2,150],90:[2,150],99:[2,150],101:[2,150],102:[2,150],103:[2,150],107:[2,150],115:[2,150],123:[2,150],125:[2,150],126:[2,150],129:[2,150],130:[2,150],131:[2,150],132:[2,150],133:[2,150],134:[2,150]},{8:229,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{8:230,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{6:[2,51],25:[2,51],51:231,52:[1,232],75:[2,51]},{6:[2,87],25:[2,87],26:[2,87],52:[2,87],75:[2,87]},{6:[2,37],25:[2,37],26:[2,37],41:[1,233],52:[2,37],75:[2,37]},{6:[2,40],25:[2,40],26:[2,40],52:[2,40],75:[2,40]},{6:[2,41],25:[2,41],26:[2,41],41:[2,41],52:[2,41],75:[2,41]},{6:[2,42],25:[2,42],26:[2,42],41:[2,42],52:[2,42],75:[2,42]},{6:[2,43],25:[2,43],26:[2,43],41:[2,43],52:[2,43],75:[2,43]},{1:[2,5],6:[2,5],26:[2,5],99:[2,5]},{1:[2,25],6:[2,25],25:[2,25],26:[2,25],47:[2,25],52:[2,25],55:[2,25],70:[2,25],75:[2,25],83:[2,25],88:[2,25],90:[2,25],95:[2,25],96:[2,25],99:[2,25],101:[2,25],102:[2,25],103:[2,25],107:[2,25],115:[2,25],118:[2,25],120:[2,25],123:[2,25],125:[2,25],126:[2,25],129:[2,25],130:[2,25],131:[2,25],132:[2,25],133:[2,25],134:[2,25]},{1:[2,187],6:[2,187],25:[2,187],26:[2,187],47:[2,187],52:[2,187],55:[2,187],70:[2,187],75:[2,187],83:[2,187],88:[2,187],90:[2,187],99:[2,187],100:85,101:[2,187],102:[2,187],103:[2,187],106:86,107:[2,187],108:67,115:[2,187],123:[2,187],125:[2,187],126:[2,187],129:[1,76],130:[1,79],131:[2,187],132:[2,187],133:[2,187],134:[2,187]},{1:[2,188],6:[2,188],25:[2,188],26:[2,188],47:[2,188],52:[2,188],55:[2,188],70:[2,188],75:[2,188],83:[2,188],88:[2,188],90:[2,188],99:[2,188],100:85,101:[2,188],102:[2,188],103:[2,188],106:86,107:[2,188],108:67,115:[2,188],123:[2,188],125:[2,188],126:[2,188],129:[1,76],130:[1,79],131:[2,188],132:[2,188],133:[2,188],134:[2,188]},{1:[2,189],6:[2,189],25:[2,189],26:[2,189],47:[2,189],52:[2,189],55:[2,189],70:[2,189],75:[2,189],83:[2,189],88:[2,189],90:[2,189],99:[2,189],100:85,101:[2,189],102:[2,189],103:[2,189],106:86,107:[2,189],108:67,115:[2,189],123:[2,189],125:[2,189],126:[2,189],129:[1,76],130:[2,189],131:[2,189],132:[2,189],133:[2,189],134:[2,189]},{1:[2,190],6:[2,190],25:[2,190],26:[2,190],47:[2,190],52:[2,190],55:[2,190],70:[2,190],75:[2,190],83:[2,190],88:[2,190],90:[2,190],99:[2,190],100:85,101:[2,190],102:[2,190],103:[2,190],106:86,107:[2,190],108:67,115:[2,190],123:[2,190],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[2,190],132:[2,190],133:[2,190],134:[2,190]},{1:[2,191],6:[2,191],25:[2,191],26:[2,191],47:[2,191],52:[2,191],55:[2,191],70:[2,191],75:[2,191],83:[2,191],88:[2,191],90:[2,191],99:[2,191],100:85,101:[2,191],102:[2,191],103:[2,191],106:86,107:[2,191],108:67,115:[2,191],123:[2,191],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[2,191],133:[2,191],134:[1,83]},{1:[2,192],6:[2,192],25:[2,192],26:[2,192],47:[2,192],52:[2,192],55:[2,192],70:[2,192],75:[2,192],83:[2,192],88:[2,192],90:[2,192],99:[2,192],100:85,101:[2,192],102:[2,192],103:[2,192],106:86,107:[2,192],108:67,115:[2,192],123:[2,192],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[2,192],134:[1,83]},{1:[2,193],6:[2,193],25:[2,193],26:[2,193],47:[2,193],52:[2,193],55:[2,193],70:[2,193],75:[2,193],83:[2,193],88:[2,193],90:[2,193],99:[2,193],100:85,101:[2,193],102:[2,193],103:[2,193],106:86,107:[2,193],108:67,115:[2,193],123:[2,193],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[2,193],133:[2,193],134:[2,193]},{1:[2,178],6:[2,178],25:[2,178],26:[2,178],47:[2,178],52:[2,178],55:[2,178],70:[2,178],75:[2,178],83:[2,178],88:[2,178],90:[2,178],99:[2,178],100:85,101:[1,63],102:[2,178],103:[1,64],106:86,107:[1,66],108:67,115:[2,178],123:[1,84],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{1:[2,177],6:[2,177],25:[2,177],26:[2,177],47:[2,177],52:[2,177],55:[2,177],70:[2,177],75:[2,177],83:[2,177],88:[2,177],90:[2,177],99:[2,177],100:85,101:[1,63],102:[2,177],103:[1,64],106:86,107:[1,66],108:67,115:[2,177],123:[1,84],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{1:[2,99],6:[2,99],25:[2,99],26:[2,99],47:[2,99],52:[2,99],55:[2,99],64:[2,99],65:[2,99],66:[2,99],68:[2,99],70:[2,99],71:[2,99],75:[2,99],81:[2,99],82:[2,99],83:[2,99],88:[2,99],90:[2,99],99:[2,99],101:[2,99],102:[2,99],103:[2,99],107:[2,99],115:[2,99],123:[2,99],125:[2,99],126:[2,99],129:[2,99],130:[2,99],131:[2,99],132:[2,99],133:[2,99],134:[2,99]},{1:[2,76],6:[2,76],25:[2,76],26:[2,76],38:[2,76],47:[2,76],52:[2,76],55:[2,76],64:[2,76],65:[2,76],66:[2,76],68:[2,76],70:[2,76],71:[2,76],75:[2,76],77:[2,76],81:[2,76],82:[2,76],83:[2,76],88:[2,76],90:[2,76],99:[2,76],101:[2,76],102:[2,76],103:[2,76],107:[2,76],115:[2,76],123:[2,76],125:[2,76],126:[2,76],127:[2,76],128:[2,76],129:[2,76],130:[2,76],131:[2,76],132:[2,76],133:[2,76],134:[2,76],135:[2,76]},{1:[2,77],6:[2,77],25:[2,77],26:[2,77],38:[2,77],47:[2,77],52:[2,77],55:[2,77],64:[2,77],65:[2,77],66:[2,77],68:[2,77],70:[2,77],71:[2,77],75:[2,77],77:[2,77],81:[2,77],82:[2,77],83:[2,77],88:[2,77],90:[2,77],99:[2,77],101:[2,77],102:[2,77],103:[2,77],107:[2,77],115:[2,77],123:[2,77],125:[2,77],126:[2,77],127:[2,77],128:[2,77],129:[2,77],130:[2,77],131:[2,77],132:[2,77],133:[2,77],134:[2,77],135:[2,77]},{1:[2,78],6:[2,78],25:[2,78],26:[2,78],38:[2,78],47:[2,78],52:[2,78],55:[2,78],64:[2,78],65:[2,78],66:[2,78],68:[2,78],70:[2,78],71:[2,78],75:[2,78],77:[2,78],81:[2,78],82:[2,78],83:[2,78],88:[2,78],90:[2,78],99:[2,78],101:[2,78],102:[2,78],103:[2,78],107:[2,78],115:[2,78],123:[2,78],125:[2,78],126:[2,78],127:[2,78],128:[2,78],129:[2,78],130:[2,78],131:[2,78],132:[2,78],133:[2,78],134:[2,78],135:[2,78]},{70:[1,234]},{55:[1,189],70:[2,83],89:235,90:[1,188],100:85,101:[1,63],103:[1,64],106:86,107:[1,66],108:67,123:[1,84],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{70:[2,84]},{8:236,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,70:[2,118],73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{12:[2,112],28:[2,112],30:[2,112],31:[2,112],33:[2,112],34:[2,112],35:[2,112],36:[2,112],43:[2,112],44:[2,112],45:[2,112],49:[2,112],50:[2,112],70:[2,112],73:[2,112],76:[2,112],80:[2,112],85:[2,112],86:[2,112],87:[2,112],93:[2,112],97:[2,112],98:[2,112],101:[2,112],103:[2,112],105:[2,112],107:[2,112],116:[2,112],122:[2,112],124:[2,112],125:[2,112],126:[2,112],127:[2,112],128:[2,112]},{12:[2,113],28:[2,113],30:[2,113],31:[2,113],33:[2,113],34:[2,113],35:[2,113],36:[2,113],43:[2,113],44:[2,113],45:[2,113],49:[2,113],50:[2,113],70:[2,113],73:[2,113],76:[2,113],80:[2,113],85:[2,113],86:[2,113],87:[2,113],93:[2,113],97:[2,113],98:[2,113],101:[2,113],103:[2,113],105:[2,113],107:[2,113],116:[2,113],122:[2,113],124:[2,113],125:[2,113],126:[2,113],127:[2,113],128:[2,113]},{1:[2,82],6:[2,82],25:[2,82],26:[2,82],38:[2,82],47:[2,82],52:[2,82],55:[2,82],64:[2,82],65:[2,82],66:[2,82],68:[2,82],70:[2,82],71:[2,82],75:[2,82],77:[2,82],81:[2,82],82:[2,82],83:[2,82],88:[2,82],90:[2,82],99:[2,82],101:[2,82],102:[2,82],103:[2,82],107:[2,82],115:[2,82],123:[2,82],125:[2,82],126:[2,82],127:[2,82],128:[2,82],129:[2,82],130:[2,82],131:[2,82],132:[2,82],133:[2,82],134:[2,82],135:[2,82]},{1:[2,100],6:[2,100],25:[2,100],26:[2,100],47:[2,100],52:[2,100],55:[2,100],64:[2,100],65:[2,100],66:[2,100],68:[2,100],70:[2,100],71:[2,100],75:[2,100],81:[2,100],82:[2,100],83:[2,100],88:[2,100],90:[2,100],99:[2,100],101:[2,100],102:[2,100],103:[2,100],107:[2,100],115:[2,100],123:[2,100],125:[2,100],126:[2,100],129:[2,100],130:[2,100],131:[2,100],132:[2,100],133:[2,100],134:[2,100]},{1:[2,34],6:[2,34],25:[2,34],26:[2,34],47:[2,34],52:[2,34],55:[2,34],70:[2,34],75:[2,34],83:[2,34],88:[2,34],90:[2,34],99:[2,34],100:85,101:[2,34],102:[2,34],103:[2,34],106:86,107:[2,34],108:67,115:[2,34],123:[2,34],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{8:237,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{8:238,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{1:[2,105],6:[2,105],25:[2,105],26:[2,105],47:[2,105],52:[2,105],55:[2,105],64:[2,105],65:[2,105],66:[2,105],68:[2,105],70:[2,105],71:[2,105],75:[2,105],81:[2,105],82:[2,105],83:[2,105],88:[2,105],90:[2,105],99:[2,105],101:[2,105],102:[2,105],103:[2,105],107:[2,105],115:[2,105],123:[2,105],125:[2,105],126:[2,105],129:[2,105],130:[2,105],131:[2,105],132:[2,105],133:[2,105],134:[2,105]},{6:[2,51],25:[2,51],51:239,52:[1,222],83:[2,51]},{6:[2,124],25:[2,124],26:[2,124],52:[2,124],55:[1,240],83:[2,124],88:[2,124],100:85,101:[1,63],103:[1,64],106:86,107:[1,66],108:67,123:[1,84],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{48:241,49:[1,58],50:[1,59]},{27:107,28:[1,71],42:108,53:242,54:106,56:109,57:110,73:[1,68],86:[1,111],87:[1,112]},{47:[2,57],52:[2,57]},{8:243,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{1:[2,194],6:[2,194],25:[2,194],26:[2,194],47:[2,194],52:[2,194],55:[2,194],70:[2,194],75:[2,194],83:[2,194],88:[2,194],90:[2,194],99:[2,194],100:85,101:[2,194],102:[2,194],103:[2,194],106:86,107:[2,194],108:67,115:[2,194],123:[2,194],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{8:244,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{1:[2,196],6:[2,196],25:[2,196],26:[2,196],47:[2,196],52:[2,196],55:[2,196],70:[2,196],75:[2,196],83:[2,196],88:[2,196],90:[2,196],99:[2,196],100:85,101:[2,196],102:[2,196],103:[2,196],106:86,107:[2,196],108:67,115:[2,196],123:[2,196],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{1:[2,176],6:[2,176],25:[2,176],26:[2,176],47:[2,176],52:[2,176],55:[2,176],70:[2,176],75:[2,176],83:[2,176],88:[2,176],90:[2,176],99:[2,176],101:[2,176],102:[2,176],103:[2,176],107:[2,176],115:[2,176],123:[2,176],125:[2,176],126:[2,176],129:[2,176],130:[2,176],131:[2,176],132:[2,176],133:[2,176],134:[2,176]},{8:245,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{1:[2,129],6:[2,129],25:[2,129],26:[2,129],47:[2,129],52:[2,129],55:[2,129],70:[2,129],75:[2,129],83:[2,129],88:[2,129],90:[2,129],95:[1,246],99:[2,129],101:[2,129],102:[2,129],103:[2,129],107:[2,129],115:[2,129],123:[2,129],125:[2,129],126:[2,129],129:[2,129],130:[2,129],131:[2,129],132:[2,129],133:[2,129],134:[2,129]},{5:247,25:[1,5]},{27:248,28:[1,71]},{117:249,119:212,120:[1,213]},{26:[1,250],118:[1,251],119:252,120:[1,213]},{26:[2,169],118:[2,169],120:[2,169]},{8:254,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],92:253,93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{1:[2,93],5:255,6:[2,93],25:[1,5],26:[2,93],47:[2,93],52:[2,93],55:[2,93],70:[2,93],75:[2,93],83:[2,93],88:[2,93],90:[2,93],99:[2,93],100:85,101:[1,63],102:[2,93],103:[1,64],106:86,107:[1,66],108:67,115:[2,93],123:[2,93],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{1:[2,96],6:[2,96],25:[2,96],26:[2,96],47:[2,96],52:[2,96],55:[2,96],70:[2,96],75:[2,96],83:[2,96],88:[2,96],90:[2,96],99:[2,96],101:[2,96],102:[2,96],103:[2,96],107:[2,96],115:[2,96],123:[2,96],125:[2,96],126:[2,96],129:[2,96],130:[2,96],131:[2,96],132:[2,96],133:[2,96],134:[2,96]},{8:256,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{1:[2,134],6:[2,134],25:[2,134],26:[2,134],47:[2,134],52:[2,134],55:[2,134],64:[2,134],65:[2,134],66:[2,134],68:[2,134],70:[2,134],71:[2,134],75:[2,134],81:[2,134],82:[2,134],83:[2,134],88:[2,134],90:[2,134],99:[2,134],101:[2,134],102:[2,134],103:[2,134],107:[2,134],115:[2,134],123:[2,134],125:[2,134],126:[2,134],129:[2,134],130:[2,134],131:[2,134],132:[2,134],133:[2,134],134:[2,134]},{6:[1,72],26:[1,257]},{8:258,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{6:[2,63],12:[2,113],25:[2,63],28:[2,113],30:[2,113],31:[2,113],33:[2,113],34:[2,113],35:[2,113],36:[2,113],43:[2,113],44:[2,113],45:[2,113],49:[2,113],50:[2,113],52:[2,63],73:[2,113],76:[2,113],80:[2,113],85:[2,113],86:[2,113],87:[2,113],88:[2,63],93:[2,113],97:[2,113],98:[2,113],101:[2,113],103:[2,113],105:[2,113],107:[2,113],116:[2,113],122:[2,113],124:[2,113],125:[2,113],126:[2,113],127:[2,113],128:[2,113]},{6:[1,260],25:[1,261],88:[1,259]},{6:[2,52],8:197,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,25:[2,52],26:[2,52],27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,58:145,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],83:[2,52],85:[1,56],86:[1,57],87:[1,55],88:[2,52],91:262,93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{6:[2,51],25:[2,51],26:[2,51],51:263,52:[1,222]},{1:[2,173],6:[2,173],25:[2,173],26:[2,173],47:[2,173],52:[2,173],55:[2,173],70:[2,173],75:[2,173],83:[2,173],88:[2,173],90:[2,173],99:[2,173],101:[2,173],102:[2,173],103:[2,173],107:[2,173],115:[2,173],118:[2,173],123:[2,173],125:[2,173],126:[2,173],129:[2,173],130:[2,173],131:[2,173],132:[2,173],133:[2,173],134:[2,173]},{8:264,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{8:265,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{113:[2,152],114:[2,152]},{27:156,28:[1,71],56:157,57:158,73:[1,68],87:[1,112],112:266},{1:[2,158],6:[2,158],25:[2,158],26:[2,158],47:[2,158],52:[2,158],55:[2,158],70:[2,158],75:[2,158],83:[2,158],88:[2,158],90:[2,158],99:[2,158],100:85,101:[2,158],102:[1,267],103:[2,158],106:86,107:[2,158],108:67,115:[1,268],123:[2,158],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{1:[2,159],6:[2,159],25:[2,159],26:[2,159],47:[2,159],52:[2,159],55:[2,159],70:[2,159],75:[2,159],83:[2,159],88:[2,159],90:[2,159],99:[2,159],100:85,101:[2,159],102:[1,269],103:[2,159],106:86,107:[2,159],108:67,115:[2,159],123:[2,159],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{6:[1,271],25:[1,272],75:[1,270]},{6:[2,52],11:165,25:[2,52],26:[2,52],27:166,28:[1,71],29:167,30:[1,69],31:[1,70],39:273,40:164,42:168,44:[1,46],75:[2,52],86:[1,111]},{8:274,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,25:[1,275],27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{1:[2,81],6:[2,81],25:[2,81],26:[2,81],38:[2,81],47:[2,81],52:[2,81],55:[2,81],64:[2,81],65:[2,81],66:[2,81],68:[2,81],70:[2,81],71:[2,81],75:[2,81],77:[2,81],81:[2,81],82:[2,81],83:[2,81],88:[2,81],90:[2,81],99:[2,81],101:[2,81],102:[2,81],103:[2,81],107:[2,81],115:[2,81],123:[2,81],125:[2,81],126:[2,81],127:[2,81],128:[2,81],129:[2,81],130:[2,81],131:[2,81],132:[2,81],133:[2,81],134:[2,81],135:[2,81]},{8:276,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,70:[2,116],73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{70:[2,117],100:85,101:[1,63],103:[1,64],106:86,107:[1,66],108:67,123:[1,84],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{1:[2,35],6:[2,35],25:[2,35],26:[2,35],47:[2,35],52:[2,35],55:[2,35],70:[2,35],75:[2,35],83:[2,35],88:[2,35],90:[2,35],99:[2,35],100:85,101:[2,35],102:[2,35],103:[2,35],106:86,107:[2,35],108:67,115:[2,35],123:[2,35],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{26:[1,277],100:85,101:[1,63],103:[1,64],106:86,107:[1,66],108:67,123:[1,84],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{6:[1,260],25:[1,261],83:[1,278]},{6:[2,63],25:[2,63],26:[2,63],52:[2,63],83:[2,63],88:[2,63]},{5:279,25:[1,5]},{47:[2,55],52:[2,55]},{47:[2,58],52:[2,58],100:85,101:[1,63],103:[1,64],106:86,107:[1,66],108:67,123:[1,84],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{26:[1,280],100:85,101:[1,63],103:[1,64],106:86,107:[1,66],108:67,123:[1,84],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{5:281,25:[1,5],100:85,101:[1,63],103:[1,64],106:86,107:[1,66],108:67,123:[1,84],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{5:282,25:[1,5]},{1:[2,130],6:[2,130],25:[2,130],26:[2,130],47:[2,130],52:[2,130],55:[2,130],70:[2,130],75:[2,130],83:[2,130],88:[2,130],90:[2,130],99:[2,130],101:[2,130],102:[2,130],103:[2,130],107:[2,130],115:[2,130],123:[2,130],125:[2,130],126:[2,130],129:[2,130],130:[2,130],131:[2,130],132:[2,130],133:[2,130],134:[2,130]},{5:283,25:[1,5]},{26:[1,284],118:[1,285],119:252,120:[1,213]},{1:[2,167],6:[2,167],25:[2,167],26:[2,167],47:[2,167],52:[2,167],55:[2,167],70:[2,167],75:[2,167],83:[2,167],88:[2,167],90:[2,167],99:[2,167],101:[2,167],102:[2,167],103:[2,167],107:[2,167],115:[2,167],123:[2,167],125:[2,167],126:[2,167],129:[2,167],130:[2,167],131:[2,167],132:[2,167],133:[2,167],134:[2,167]},{5:286,25:[1,5]},{26:[2,170],118:[2,170],120:[2,170]},{5:287,25:[1,5],52:[1,288]},{25:[2,126],52:[2,126],100:85,101:[1,63],103:[1,64],106:86,107:[1,66],108:67,123:[1,84],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{1:[2,94],6:[2,94],25:[2,94],26:[2,94],47:[2,94],52:[2,94],55:[2,94],70:[2,94],75:[2,94],83:[2,94],88:[2,94],90:[2,94],99:[2,94],101:[2,94],102:[2,94],103:[2,94],107:[2,94],115:[2,94],123:[2,94],125:[2,94],126:[2,94],129:[2,94],130:[2,94],131:[2,94],132:[2,94],133:[2,94],134:[2,94]},{1:[2,97],5:289,6:[2,97],25:[1,5],26:[2,97],47:[2,97],52:[2,97],55:[2,97],70:[2,97],75:[2,97],83:[2,97],88:[2,97],90:[2,97],99:[2,97],100:85,101:[1,63],102:[2,97],103:[1,64],106:86,107:[1,66],108:67,115:[2,97],123:[2,97],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{99:[1,290]},{88:[1,291],100:85,101:[1,63],103:[1,64],106:86,107:[1,66],108:67,123:[1,84],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{1:[2,111],6:[2,111],25:[2,111],26:[2,111],38:[2,111],47:[2,111],52:[2,111],55:[2,111],64:[2,111],65:[2,111],66:[2,111],68:[2,111],70:[2,111],71:[2,111],75:[2,111],81:[2,111],82:[2,111],83:[2,111],88:[2,111],90:[2,111],99:[2,111],101:[2,111],102:[2,111],103:[2,111],107:[2,111],113:[2,111],114:[2,111],115:[2,111],123:[2,111],125:[2,111],126:[2,111],129:[2,111],130:[2,111],131:[2,111],132:[2,111],133:[2,111],134:[2,111]},{8:197,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,58:145,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],91:292,93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{8:197,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,25:[1,144],27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,58:145,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],84:293,85:[1,56],86:[1,57],87:[1,55],91:143,93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{6:[2,120],25:[2,120],26:[2,120],52:[2,120],83:[2,120],88:[2,120]},{6:[1,260],25:[1,261],26:[1,294]},{1:[2,137],6:[2,137],25:[2,137],26:[2,137],47:[2,137],52:[2,137],55:[2,137],70:[2,137],75:[2,137],83:[2,137],88:[2,137],90:[2,137],99:[2,137],100:85,101:[1,63],102:[2,137],103:[1,64],106:86,107:[1,66],108:67,115:[2,137],123:[2,137],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{1:[2,139],6:[2,139],25:[2,139],26:[2,139],47:[2,139],52:[2,139],55:[2,139],70:[2,139],75:[2,139],83:[2,139],88:[2,139],90:[2,139],99:[2,139],100:85,101:[1,63],102:[2,139],103:[1,64],106:86,107:[1,66],108:67,115:[2,139],123:[2,139],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{113:[2,157],114:[2,157]},{8:295,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{8:296,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{8:297,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{1:[2,85],6:[2,85],25:[2,85],26:[2,85],38:[2,85],47:[2,85],52:[2,85],55:[2,85],64:[2,85],65:[2,85],66:[2,85],68:[2,85],70:[2,85],71:[2,85],75:[2,85],81:[2,85],82:[2,85],83:[2,85],88:[2,85],90:[2,85],99:[2,85],101:[2,85],102:[2,85],103:[2,85],107:[2,85],113:[2,85],114:[2,85],115:[2,85],123:[2,85],125:[2,85],126:[2,85],129:[2,85],130:[2,85],131:[2,85],132:[2,85],133:[2,85],134:[2,85]},{11:165,27:166,28:[1,71],29:167,30:[1,69],31:[1,70],39:298,40:164,42:168,44:[1,46],86:[1,111]},{6:[2,86],11:165,25:[2,86],26:[2,86],27:166,28:[1,71],29:167,30:[1,69],31:[1,70],39:163,40:164,42:168,44:[1,46],52:[2,86],74:299,86:[1,111]},{6:[2,88],25:[2,88],26:[2,88],52:[2,88],75:[2,88]},{6:[2,38],25:[2,38],26:[2,38],52:[2,38],75:[2,38],100:85,101:[1,63],103:[1,64],106:86,107:[1,66],108:67,123:[1,84],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{8:300,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{70:[2,115],100:85,101:[1,63],103:[1,64],106:86,107:[1,66],108:67,123:[1,84],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{1:[2,36],6:[2,36],25:[2,36],26:[2,36],47:[2,36],52:[2,36],55:[2,36],70:[2,36],75:[2,36],83:[2,36],88:[2,36],90:[2,36],99:[2,36],101:[2,36],102:[2,36],103:[2,36],107:[2,36],115:[2,36],123:[2,36],125:[2,36],126:[2,36],129:[2,36],130:[2,36],131:[2,36],132:[2,36],133:[2,36],134:[2,36]},{1:[2,106],6:[2,106],25:[2,106],26:[2,106],47:[2,106],52:[2,106],55:[2,106],64:[2,106],65:[2,106],66:[2,106],68:[2,106],70:[2,106],71:[2,106],75:[2,106],81:[2,106],82:[2,106],83:[2,106],88:[2,106],90:[2,106],99:[2,106],101:[2,106],102:[2,106],103:[2,106],107:[2,106],115:[2,106],123:[2,106],125:[2,106],126:[2,106],129:[2,106],130:[2,106],131:[2,106],132:[2,106],133:[2,106],134:[2,106]},{1:[2,47],6:[2,47],25:[2,47],26:[2,47],47:[2,47],52:[2,47],55:[2,47],70:[2,47],75:[2,47],83:[2,47],88:[2,47],90:[2,47],99:[2,47],101:[2,47],102:[2,47],103:[2,47],107:[2,47],115:[2,47],123:[2,47],125:[2,47],126:[2,47],129:[2,47],130:[2,47],131:[2,47],132:[2,47],133:[2,47],134:[2,47]},{1:[2,195],6:[2,195],25:[2,195],26:[2,195],47:[2,195],52:[2,195],55:[2,195],70:[2,195],75:[2,195],83:[2,195],88:[2,195],90:[2,195],99:[2,195],101:[2,195],102:[2,195],103:[2,195],107:[2,195],115:[2,195],123:[2,195],125:[2,195],126:[2,195],129:[2,195],130:[2,195],131:[2,195],132:[2,195],133:[2,195],134:[2,195]},{1:[2,174],6:[2,174],25:[2,174],26:[2,174],47:[2,174],52:[2,174],55:[2,174],70:[2,174],75:[2,174],83:[2,174],88:[2,174],90:[2,174],99:[2,174],101:[2,174],102:[2,174],103:[2,174],107:[2,174],115:[2,174],118:[2,174],123:[2,174],125:[2,174],126:[2,174],129:[2,174],130:[2,174],131:[2,174],132:[2,174],133:[2,174],134:[2,174]},{1:[2,131],6:[2,131],25:[2,131],26:[2,131],47:[2,131],52:[2,131],55:[2,131],70:[2,131],75:[2,131],83:[2,131],88:[2,131],90:[2,131],99:[2,131],101:[2,131],102:[2,131],103:[2,131],107:[2,131],115:[2,131],123:[2,131],125:[2,131],126:[2,131],129:[2,131],130:[2,131],131:[2,131],132:[2,131],133:[2,131],134:[2,131]},{1:[2,132],6:[2,132],25:[2,132],26:[2,132],47:[2,132],52:[2,132],55:[2,132],70:[2,132],75:[2,132],83:[2,132],88:[2,132],90:[2,132],95:[2,132],99:[2,132],101:[2,132],102:[2,132],103:[2,132],107:[2,132],115:[2,132],123:[2,132],125:[2,132],126:[2,132],129:[2,132],130:[2,132],131:[2,132],132:[2,132],133:[2,132],134:[2,132]},{1:[2,165],6:[2,165],25:[2,165],26:[2,165],47:[2,165],52:[2,165],55:[2,165],70:[2,165],75:[2,165],83:[2,165],88:[2,165],90:[2,165],99:[2,165],101:[2,165],102:[2,165],103:[2,165],107:[2,165],115:[2,165],123:[2,165],125:[2,165],126:[2,165],129:[2,165],130:[2,165],131:[2,165],132:[2,165],133:[2,165],134:[2,165]},{5:301,25:[1,5]},{26:[1,302]},{6:[1,303],26:[2,171],118:[2,171],120:[2,171]},{8:304,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{1:[2,98],6:[2,98],25:[2,98],26:[2,98],47:[2,98],52:[2,98],55:[2,98],70:[2,98],75:[2,98],83:[2,98],88:[2,98],90:[2,98],99:[2,98],101:[2,98],102:[2,98],103:[2,98],107:[2,98],115:[2,98],123:[2,98],125:[2,98],126:[2,98],129:[2,98],130:[2,98],131:[2,98],132:[2,98],133:[2,98],134:[2,98]},{1:[2,135],6:[2,135],25:[2,135],26:[2,135],47:[2,135],52:[2,135],55:[2,135],64:[2,135],65:[2,135],66:[2,135],68:[2,135],70:[2,135],71:[2,135],75:[2,135],81:[2,135],82:[2,135],83:[2,135],88:[2,135],90:[2,135],99:[2,135],101:[2,135],102:[2,135],103:[2,135],107:[2,135],115:[2,135],123:[2,135],125:[2,135],126:[2,135],129:[2,135],130:[2,135],131:[2,135],132:[2,135],133:[2,135],134:[2,135]},{1:[2,114],6:[2,114],25:[2,114],26:[2,114],47:[2,114],52:[2,114],55:[2,114],64:[2,114],65:[2,114],66:[2,114],68:[2,114],70:[2,114],71:[2,114],75:[2,114],81:[2,114],82:[2,114],83:[2,114],88:[2,114],90:[2,114],99:[2,114],101:[2,114],102:[2,114],103:[2,114],107:[2,114],115:[2,114],123:[2,114],125:[2,114],126:[2,114],129:[2,114],130:[2,114],131:[2,114],132:[2,114],133:[2,114],134:[2,114]},{6:[2,121],25:[2,121],26:[2,121],52:[2,121],83:[2,121],88:[2,121]},{6:[2,51],25:[2,51],26:[2,51],51:305,52:[1,222]},{6:[2,122],25:[2,122],26:[2,122],52:[2,122],83:[2,122],88:[2,122]},{1:[2,160],6:[2,160],25:[2,160],26:[2,160],47:[2,160],52:[2,160],55:[2,160],70:[2,160],75:[2,160],83:[2,160],88:[2,160],90:[2,160],99:[2,160],100:85,101:[2,160],102:[2,160],103:[2,160],106:86,107:[2,160],108:67,115:[1,306],123:[2,160],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{1:[2,162],6:[2,162],25:[2,162],26:[2,162],47:[2,162],52:[2,162],55:[2,162],70:[2,162],75:[2,162],83:[2,162],88:[2,162],90:[2,162],99:[2,162],100:85,101:[2,162],102:[1,307],103:[2,162],106:86,107:[2,162],108:67,115:[2,162],123:[2,162],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{1:[2,161],6:[2,161],25:[2,161],26:[2,161],47:[2,161],52:[2,161],55:[2,161],70:[2,161],75:[2,161],83:[2,161],88:[2,161],90:[2,161],99:[2,161],100:85,101:[2,161],102:[2,161],103:[2,161],106:86,107:[2,161],108:67,115:[2,161],123:[2,161],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{6:[2,89],25:[2,89],26:[2,89],52:[2,89],75:[2,89]},{6:[2,51],25:[2,51],26:[2,51],51:308,52:[1,232]},{26:[1,309],100:85,101:[1,63],103:[1,64],106:86,107:[1,66],108:67,123:[1,84],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{26:[1,310]},{1:[2,168],6:[2,168],25:[2,168],26:[2,168],47:[2,168],52:[2,168],55:[2,168],70:[2,168],75:[2,168],83:[2,168],88:[2,168],90:[2,168],99:[2,168],101:[2,168],102:[2,168],103:[2,168],107:[2,168],115:[2,168],123:[2,168],125:[2,168],126:[2,168],129:[2,168],130:[2,168],131:[2,168],132:[2,168],133:[2,168],134:[2,168]},{26:[2,172],118:[2,172],120:[2,172]},{25:[2,127],52:[2,127],100:85,101:[1,63],103:[1,64],106:86,107:[1,66],108:67,123:[1,84],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{6:[1,260],25:[1,261],26:[1,311]},{8:312,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{8:313,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{6:[1,271],25:[1,272],26:[1,314]},{6:[2,39],25:[2,39],26:[2,39],52:[2,39],75:[2,39]},{1:[2,166],6:[2,166],25:[2,166],26:[2,166],47:[2,166],52:[2,166],55:[2,166],70:[2,166],75:[2,166],83:[2,166],88:[2,166],90:[2,166],99:[2,166],101:[2,166],102:[2,166],103:[2,166],107:[2,166],115:[2,166],123:[2,166],125:[2,166],126:[2,166],129:[2,166],130:[2,166],131:[2,166],132:[2,166],133:[2,166],134:[2,166]},{6:[2,123],25:[2,123],26:[2,123],52:[2,123],83:[2,123],88:[2,123]},{1:[2,163],6:[2,163],25:[2,163],26:[2,163],47:[2,163],52:[2,163],55:[2,163],70:[2,163],75:[2,163],83:[2,163],88:[2,163],90:[2,163],99:[2,163],100:85,101:[2,163],102:[2,163],103:[2,163],106:86,107:[2,163],108:67,115:[2,163],123:[2,163],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{1:[2,164],6:[2,164],25:[2,164],26:[2,164],47:[2,164],52:[2,164],55:[2,164],70:[2,164],75:[2,164],83:[2,164],88:[2,164],90:[2,164],99:[2,164],100:85,101:[2,164],102:[2,164],103:[2,164],106:86,107:[2,164],108:67,115:[2,164],123:[2,164],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{6:[2,90],25:[2,90],26:[2,90],52:[2,90],75:[2,90]}],
+defaultActions: {58:[2,49],59:[2,50],73:[2,3],92:[2,104],186:[2,84]},
 parseError: function parseError(str, hash) {
     throw new Error(str);
 },
 parse: function parse(input) {
-    var self = this,
-        stack = [0],
-        vstack = [null], // semantic value stack
-        lstack = [], // location stack
-        table = this.table,
-        yytext = '',
-        yylineno = 0,
-        yyleng = 0,
-        recovering = 0,
-        TERROR = 2,
-        EOF = 1;
-
-    //this.reductionCount = this.shiftCount = 0;
-
+    var self = this, stack = [0], vstack = [null], lstack = [], table = this.table, yytext = "", yylineno = 0, yyleng = 0, recovering = 0, TERROR = 2, EOF = 1;
     this.lexer.setInput(input);
     this.lexer.yy = this.yy;
     this.yy.lexer = this.lexer;
-    if (typeof this.lexer.yylloc == 'undefined')
+    if (typeof this.lexer.yylloc == "undefined")
         this.lexer.yylloc = {};
     var yyloc = this.lexer.yylloc;
     lstack.push(yyloc);
-
-    if (typeof this.yy.parseError === 'function')
+    if (typeof this.yy.parseError === "function")
         this.parseError = this.yy.parseError;
-
-    function popStack (n) {
-        stack.length = stack.length - 2*n;
+    function popStack(n) {
+        stack.length = stack.length - 2 * n;
         vstack.length = vstack.length - n;
         lstack.length = lstack.length - n;
     }
-
     function lex() {
         var token;
-        token = self.lexer.lex() || 1; // $end = 1
-        // if token isn't its numeric value, convert
-        if (typeof token !== 'number') {
+        token = self.lexer.lex() || 1;
+        if (typeof token !== "number") {
             token = self.symbols_[token] || token;
         }
         return token;
-    };
-
-    var symbol, preErrorSymbol, state, action, a, r, yyval={},p,len,newState, expected;
+    }
+    var symbol, preErrorSymbol, state, action, a, r, yyval = {}, p, len, newState, expected;
     while (true) {
-        // retreive state number from top of stack
-        state = stack[stack.length-1];
-
-        // use default actions if available
+        state = stack[stack.length - 1];
         if (this.defaultActions[state]) {
             action = this.defaultActions[state];
         } else {
             if (symbol == null)
                 symbol = lex();
-            // read action for current state and first input
             action = table[state] && table[state][symbol];
         }
-
-        // handle parse error
-        if (typeof action === 'undefined' || !action.length || !action[0]) {
-
+        if (typeof action === "undefined" || !action.length || !action[0]) {
             if (!recovering) {
-                // Report error
                 expected = [];
-                for (p in table[state]) if (this.terminals_[p] && p > 2) {
-                    expected.push("'"+this.terminals_[p]+"'");
-                }
-                var errStr = '';
+                for (p in table[state])
+                    if (this.terminals_[p] && p > 2) {
+                        expected.push("'" + this.terminals_[p] + "'");
+                    }
+                var errStr = "";
                 if (this.lexer.showPosition) {
-                    errStr = 'Parse error on line '+(yylineno+1)+":\n"+this.lexer.showPosition()+'\nExpecting '+expected.join(', ');
+                    errStr = "Parse error on line " + (yylineno + 1) + ":\n" + this.lexer.showPosition() + "\nExpecting " + expected.join(", ") + ", got '" + this.terminals_[symbol] + "'";
                 } else {
-                    errStr = 'Parse error on line '+(yylineno+1)+": Unexpected " +
-                                  (symbol == 1 /*EOF*/ ? "end of input" :
-                                              ("'"+(this.terminals_[symbol] || symbol)+"'"));
+                    errStr = "Parse error on line " + (yylineno + 1) + ": Unexpected " + (symbol == 1?"end of input":"'" + (this.terminals_[symbol] || symbol) + "'");
                 }
-                this.parseError(errStr,
-                    {text: this.lexer.match, token: this.terminals_[symbol] || symbol, line: this.lexer.yylineno, loc: yyloc, expected: expected});
+                this.parseError(errStr, {text: this.lexer.match, token: this.terminals_[symbol] || symbol, line: this.lexer.yylineno, loc: yyloc, expected: expected});
             }
-
-            // just recovered from another error
-            if (recovering == 3) {
-                if (symbol == EOF) {
-                    throw new Error(errStr || 'Parsing halted.');
-                }
-
-                // discard current lookahead and grab another
+        }
+        if (action[0] instanceof Array && action.length > 1) {
+            throw new Error("Parse Error: multiple actions possible at state: " + state + ", token: " + symbol);
+        }
+        switch (action[0]) {
+        case 1:
+            stack.push(symbol);
+            vstack.push(this.lexer.yytext);
+            lstack.push(this.lexer.yylloc);
+            stack.push(action[1]);
+            symbol = null;
+            if (!preErrorSymbol) {
                 yyleng = this.lexer.yyleng;
                 yytext = this.lexer.yytext;
                 yylineno = this.lexer.yylineno;
                 yyloc = this.lexer.yylloc;
-                symbol = lex();
+                if (recovering > 0)
+                    recovering--;
+            } else {
+                symbol = preErrorSymbol;
+                preErrorSymbol = null;
             }
-
-            // try to recover from error
-            while (1) {
-                // check for error recovery rule in this state
-                if ((TERROR.toString()) in table[state]) {
-                    break;
-                }
-                if (state == 0) {
-                    throw new Error(errStr || 'Parsing halted.');
-                }
-                popStack(1);
-                state = stack[stack.length-1];
+            break;
+        case 2:
+            len = this.productions_[action[1]][1];
+            yyval.$ = vstack[vstack.length - len];
+            yyval._$ = {first_line: lstack[lstack.length - (len || 1)].first_line, last_line: lstack[lstack.length - 1].last_line, first_column: lstack[lstack.length - (len || 1)].first_column, last_column: lstack[lstack.length - 1].last_column};
+            r = this.performAction.call(yyval, yytext, yyleng, yylineno, this.yy, action[1], vstack, lstack);
+            if (typeof r !== "undefined") {
+                return r;
             }
-
-            preErrorSymbol = symbol; // save the lookahead token
-            symbol = TERROR;         // insert generic error symbol as new lookahead
-            state = stack[stack.length-1];
-            action = table[state] && table[state][TERROR];
-            recovering = 3; // allow 3 real symbols to be shifted before reporting a new error
-        }
-
-        // this shouldn't happen, unless resolve defaults are off
-        if (action[0] instanceof Array && action.length > 1) {
-            throw new Error('Parse Error: multiple actions possible at state: '+state+', token: '+symbol);
-        }
-
-        switch (action[0]) {
-
-            case 1: // shift
-                //this.shiftCount++;
-
-                stack.push(symbol);
-                vstack.push(this.lexer.yytext);
-                lstack.push(this.lexer.yylloc);
-                stack.push(action[1]); // push state
-                symbol = null;
-                if (!preErrorSymbol) { // normal execution/no error
-                    yyleng = this.lexer.yyleng;
-                    yytext = this.lexer.yytext;
-                    yylineno = this.lexer.yylineno;
-                    yyloc = this.lexer.yylloc;
-                    if (recovering > 0)
-                        recovering--;
-                } else { // error just occurred, resume old lookahead f/ before error
-                    symbol = preErrorSymbol;
-                    preErrorSymbol = null;
-                }
-                break;
-
-            case 2: // reduce
-                //this.reductionCount++;
-
-                len = this.productions_[action[1]][1];
-
-                // perform semantic action
-                yyval.$ = vstack[vstack.length-len]; // default to $$ = $1
-                // default location, uses first token for firsts, last for lasts
-                yyval._$ = {
-                    first_line: lstack[lstack.length-(len||1)].first_line,
-                    last_line: lstack[lstack.length-1].last_line,
-                    first_column: lstack[lstack.length-(len||1)].first_column,
-                    last_column: lstack[lstack.length-1].last_column
-                };
-                r = this.performAction.call(yyval, yytext, yyleng, yylineno, this.yy, action[1], vstack, lstack);
-
-                if (typeof r !== 'undefined') {
-                    return r;
-                }
-
-                // pop off stack
-                if (len) {
-                    stack = stack.slice(0,-1*len*2);
-                    vstack = vstack.slice(0, -1*len);
-                    lstack = lstack.slice(0, -1*len);
-                }
-
-                stack.push(this.productions_[action[1]][0]);    // push nonterminal (reduce)
-                vstack.push(yyval.$);
-                lstack.push(yyval._$);
-                // goto new state = table[STATE][NONTERMINAL]
-                newState = table[stack[stack.length-2]][stack[stack.length-1]];
-                stack.push(newState);
-                break;
-
-            case 3: // accept
-                return true;
+            if (len) {
+                stack = stack.slice(0, -1 * len * 2);
+                vstack = vstack.slice(0, -1 * len);
+                lstack = lstack.slice(0, -1 * len);
+            }
+            stack.push(this.productions_[action[1]][0]);
+            vstack.push(yyval.$);
+            lstack.push(yyval._$);
+            newState = table[stack[stack.length - 2]][stack[stack.length - 1]];
+            stack.push(newState);
+            break;
+        case 3:
+            return true;
         }
-
     }
-
     return true;
-}};
+}
+};
 
 module.exports = parser;
+
+
 });/**
  * Copyright (c) 2011 Jeremy Ashkenas
- *
+ * 
  * Permission is hereby granted, free of charge, to any person
  * obtaining a copy of this software and associated documentation
  * files (the "Software"), to deal in the Software without
@@ -4631,45 +4591,49 @@ module.exports = parser;
  * OTHER DEALINGS IN THE SOFTWARE.
  */
 
-define('ace/mode/coffee/nodes', ['require', 'exports', 'module' , 'ace/mode/coffee/scope', 'ace/mode/coffee/helpers'], function(require, exports, module) {
-  var Access, Arr, Assign, Base, Block, Call, Class, Closure, Code, Comment, Existence, Extends, For, IDENTIFIER, IS_STRING, If, In, Index, LEVEL_ACCESS, LEVEL_COND, LEVEL_LIST, LEVEL_OP, LEVEL_PAREN, LEVEL_TOP, Literal, METHOD_DEF, NEGATE, NO, Obj, Op, Param, Parens, Push, Range, Return, SIMPLENUM, Scope, Slice, Splat, Switch, TAB, THIS, Throw, Try, UTILITIES, Value, While, YES, compact, del, ends, extend, flatten, last, merge, multident, starts, unfoldSoak, utility, _ref;
-  var __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) {
-    for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; }
-    function ctor() { this.constructor = child; }
-    ctor.prototype = parent.prototype;
-    child.prototype = new ctor;
-    child.__super__ = parent.prototype;
-    return child;
-  }, __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }, __indexOf = Array.prototype.indexOf || function(item) {
-    for (var i = 0, l = this.length; i < l; i++) {
-      if (this[i] === item) return i;
-    }
-    return -1;
-  };
+define('ace/mode/coffee/nodes', ['require', 'exports', 'module' , 'ace/mode/coffee/scope', 'ace/mode/coffee/lexer', 'ace/mode/coffee/helpers'], function(require, exports, module) {
+// Generated by CoffeeScript 1.2.1-pre
+
+  var Access, Arr, Assign, Base, Block, Call, Class, Closure, Code, Comment, Existence, Extends, For, IDENTIFIER, IDENTIFIER_STR, IS_STRING, If, In, Index, LEVEL_ACCESS, LEVEL_COND, LEVEL_LIST, LEVEL_OP, LEVEL_PAREN, LEVEL_TOP, Literal, METHOD_DEF, NEGATE, NO, Obj, Op, Param, Parens, RESERVED, Range, Return, SIMPLENUM, STRICT_PROSCRIBED, Scope, Slice, Splat, Switch, TAB, THIS, Throw, Try, UTILITIES, Value, While, YES, compact, del, ends, extend, flatten, last, merge, multident, starts, unfoldSoak, utility, _ref, _ref1,
+    __hasProp = {}.hasOwnProperty,
+    __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor; child.__super__ = parent.prototype; return child; },
+    __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
+
   Scope = require('./scope').Scope;
-  _ref = require('./helpers'), compact = _ref.compact, flatten = _ref.flatten, extend = _ref.extend, merge = _ref.merge, del = _ref.del, starts = _ref.starts, ends = _ref.ends, last = _ref.last;
+
+  _ref = require('./lexer'), RESERVED = _ref.RESERVED, STRICT_PROSCRIBED = _ref.STRICT_PROSCRIBED;
+
+  _ref1 = require('./helpers'), compact = _ref1.compact, flatten = _ref1.flatten, extend = _ref1.extend, merge = _ref1.merge, del = _ref1.del, starts = _ref1.starts, ends = _ref1.ends, last = _ref1.last;
+
   exports.extend = extend;
+
   YES = function() {
     return true;
   };
+
   NO = function() {
     return false;
   };
+
   THIS = function() {
     return this;
   };
+
   NEGATE = function() {
     this.negated = !this.negated;
     return this;
   };
+
   exports.Base = Base = (function() {
+
+    Base.name = 'Base';
+
     function Base() {}
+
     Base.prototype.compile = function(o, lvl) {
       var node;
       o = extend({}, o);
-      if (lvl) {
-        o.level = lvl;
-      }
+      if (lvl) o.level = lvl;
       node = this.unfoldSoak(o) || this;
       node.tab = o.indent;
       if (o.level === LEVEL_TOP || !node.isStatement(o)) {
@@ -4678,13 +4642,15 @@ define('ace/mode/coffee/nodes', ['require', 'exports', 'module' , 'ace/mode/coff
         return node.compileClosure(o);
       }
     };
+
     Base.prototype.compileClosure = function(o) {
-      if (this.jumps() || this instanceof Throw) {
+      if (this.jumps()) {
         throw SyntaxError('cannot use a pure statement in an expression.');
       }
       o.sharedScope = true;
       return Closure.wrap(this).compileNode(o);
     };
+
     Base.prototype.cache = function(o, level, reused) {
       var ref, sub;
       if (!this.isComplex()) {
@@ -4700,6 +4666,7 @@ define('ace/mode/coffee/nodes', ['require', 'exports', 'module' , 'ace/mode/coff
         }
       }
     };
+
     Base.prototype.compileLoopReference = function(o, name) {
       var src, tmp;
       src = tmp = this.compile(o, LEVEL_LIST);
@@ -4708,9 +4675,17 @@ define('ace/mode/coffee/nodes', ['require', 'exports', 'module' , 'ace/mode/coff
       }
       return [src, tmp];
     };
-    Base.prototype.makeReturn = function() {
-      return new Return(this);
+
+    Base.prototype.makeReturn = function(res) {
+      var me;
+      me = this.unwrapAll();
+      if (res) {
+        return new Call(new Literal("" + res + ".push"), [me]);
+      } else {
+        return new Return(me);
+      }
     };
+
     Base.prototype.contains = function(pred) {
       var contains;
       contains = false;
@@ -4722,69 +4697,62 @@ define('ace/mode/coffee/nodes', ['require', 'exports', 'module' , 'ace/mode/coff
       });
       return contains;
     };
+
     Base.prototype.containsType = function(type) {
       return this instanceof type || this.contains(function(node) {
         return node instanceof type;
       });
     };
+
     Base.prototype.lastNonComment = function(list) {
       var i;
       i = list.length;
       while (i--) {
-        if (!(list[i] instanceof Comment)) {
-          return list[i];
-        }
+        if (!(list[i] instanceof Comment)) return list[i];
       }
       return null;
     };
+
     Base.prototype.toString = function(idt, name) {
       var tree;
-      if (idt == null) {
-        idt = '';
-      }
-      if (name == null) {
-        name = this.constructor.name;
-      }
+      if (idt == null) idt = '';
+      if (name == null) name = this.constructor.name;
       tree = '\n' + idt + name;
-      if (this.soak) {
-        tree += '?';
-      }
+      if (this.soak) tree += '?';
       this.eachChild(function(node) {
         return tree += node.toString(idt + TAB);
       });
       return tree;
     };
+
     Base.prototype.eachChild = function(func) {
-      var attr, child, _i, _j, _len, _len2, _ref2, _ref3;
-      if (!this.children) {
-        return this;
-      }
+      var attr, child, _i, _j, _len, _len1, _ref2, _ref3;
+      if (!this.children) return this;
       _ref2 = this.children;
       for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
         attr = _ref2[_i];
         if (this[attr]) {
           _ref3 = flatten([this[attr]]);
-          for (_j = 0, _len2 = _ref3.length; _j < _len2; _j++) {
+          for (_j = 0, _len1 = _ref3.length; _j < _len1; _j++) {
             child = _ref3[_j];
-            if (func(child) === false) {
-              return this;
-            }
+            if (func(child) === false) return this;
           }
         }
       }
       return this;
     };
+
     Base.prototype.traverseChildren = function(crossScope, func) {
       return this.eachChild(function(child) {
-        if (func(child) === false) {
-          return false;
-        }
+        if (func(child) === false) return false;
         return child.traverseChildren(crossScope, func);
       });
     };
+
     Base.prototype.invert = function() {
       return new Op('!', this);
     };
+
     Base.prototype.unwrapAll = function() {
       var node;
       node = this;
@@ -4793,34 +4761,55 @@ define('ace/mode/coffee/nodes', ['require', 'exports', 'module' , 'ace/mode/coff
       }
       return node;
     };
+
     Base.prototype.children = [];
+
     Base.prototype.isStatement = NO;
+
     Base.prototype.jumps = NO;
+
     Base.prototype.isComplex = YES;
+
     Base.prototype.isChainable = NO;
+
     Base.prototype.isAssignable = NO;
+
     Base.prototype.unwrap = THIS;
+
     Base.prototype.unfoldSoak = NO;
+
     Base.prototype.assigns = NO;
+
     return Base;
+
   })();
-  exports.Block = Block = (function() {
-    __extends(Block, Base);
+
+  exports.Block = Block = (function(_super) {
+
+    __extends(Block, _super);
+
+    Block.name = 'Block';
+
     function Block(nodes) {
       this.expressions = compact(flatten(nodes || []));
     }
+
     Block.prototype.children = ['expressions'];
+
     Block.prototype.push = function(node) {
       this.expressions.push(node);
       return this;
     };
+
     Block.prototype.pop = function() {
       return this.expressions.pop();
     };
+
     Block.prototype.unshift = function(node) {
       this.expressions.unshift(node);
       return this;
     };
+
     Block.prototype.unwrap = function() {
       if (this.expressions.length === 1) {
         return this.expressions[0];
@@ -4828,37 +4817,37 @@ define('ace/mode/coffee/nodes', ['require', 'exports', 'module' , 'ace/mode/coff
         return this;
       }
     };
+
     Block.prototype.isEmpty = function() {
       return !this.expressions.length;
     };
+
     Block.prototype.isStatement = function(o) {
       var exp, _i, _len, _ref2;
       _ref2 = this.expressions;
       for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
         exp = _ref2[_i];
-        if (exp.isStatement(o)) {
-          return true;
-        }
+        if (exp.isStatement(o)) return true;
       }
       return false;
     };
+
     Block.prototype.jumps = function(o) {
       var exp, _i, _len, _ref2;
       _ref2 = this.expressions;
       for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
         exp = _ref2[_i];
-        if (exp.jumps(o)) {
-          return exp;
-        }
+        if (exp.jumps(o)) return exp;
       }
     };
-    Block.prototype.makeReturn = function() {
+
+    Block.prototype.makeReturn = function(res) {
       var expr, len;
       len = this.expressions.length;
       while (len--) {
         expr = this.expressions[len];
         if (!(expr instanceof Comment)) {
-          this.expressions[len] = expr.makeReturn();
+          this.expressions[len] = expr.makeReturn(res);
           if (expr instanceof Return && !expr.expression) {
             this.expressions.splice(len, 1);
           }
@@ -4867,16 +4856,16 @@ define('ace/mode/coffee/nodes', ['require', 'exports', 'module' , 'ace/mode/coff
       }
       return this;
     };
+
     Block.prototype.compile = function(o, level) {
-      if (o == null) {
-        o = {};
-      }
+      if (o == null) o = {};
       if (o.scope) {
         return Block.__super__.compile.call(this, o, level);
       } else {
         return this.compileRoot(o);
       }
     };
+
     Block.prototype.compileNode = function(o) {
       var code, codes, node, top, _i, _len, _ref2;
       this.tab = o.indent;
@@ -4887,16 +4876,26 @@ define('ace/mode/coffee/nodes', ['require', 'exports', 'module' , 'ace/mode/coff
         node = _ref2[_i];
         node = node.unwrapAll();
         node = node.unfoldSoak(o) || node;
-        if (top) {
+        if (node instanceof Block) {
+          codes.push(node.compileNode(o));
+        } else if (top) {
           node.front = true;
           code = node.compile(o);
-          codes.push(node.isStatement(o) ? code : this.tab + code + ';');
+          if (!node.isStatement(o)) {
+            code = "" + this.tab + code + ";";
+            if (node instanceof Literal) code = "" + code + "\n";
+          }
+          codes.push(code);
         } else {
           codes.push(node.compile(o, LEVEL_LIST));
         }
       }
       if (top) {
-        return codes.join('\n');
+        if (this.spaced) {
+          return "\n" + (codes.join('\n\n')) + "\n";
+        } else {
+          return codes.join('\n');
+        }
       }
       code = codes.join(', ') || 'void 0';
       if (codes.length > 1 && o.level >= LEVEL_LIST) {
@@ -4905,35 +4904,56 @@ define('ace/mode/coffee/nodes', ['require', 'exports', 'module' , 'ace/mode/coff
         return code;
       }
     };
+
     Block.prototype.compileRoot = function(o) {
-      var code;
-      o.indent = this.tab = o.bare ? '' : TAB;
+      var code, exp, i, prelude, preludeExps, rest;
+      o.indent = o.bare ? '' : TAB;
       o.scope = new Scope(null, this, null);
       o.level = LEVEL_TOP;
-      code = this.compileWithDeclarations(o);
-      if (o.bare) {
-        return code;
-      } else {
-        return "(function() {\n" + code + "\n}).call(this);\n";
+      this.spaced = true;
+      prelude = "";
+      if (!o.bare) {
+        preludeExps = (function() {
+          var _i, _len, _ref2, _results;
+          _ref2 = this.expressions;
+          _results = [];
+          for (i = _i = 0, _len = _ref2.length; _i < _len; i = ++_i) {
+            exp = _ref2[i];
+            if (!(exp.unwrap() instanceof Comment)) break;
+            _results.push(exp);
+          }
+          return _results;
+        }).call(this);
+        rest = this.expressions.slice(preludeExps.length);
+        this.expressions = preludeExps;
+        if (preludeExps.length) {
+          prelude = "" + (this.compileNode(merge(o, {
+            indent: ''
+          }))) + "\n";
+        }
+        this.expressions = rest;
       }
+      code = this.compileWithDeclarations(o);
+      if (o.bare) return code;
+      return "" + prelude + "(function() {\n" + code + "\n}).call(this);\n";
     };
+
     Block.prototype.compileWithDeclarations = function(o) {
-      var assigns, code, declars, exp, i, post, rest, scope, _len, _ref2;
+      var assigns, code, declars, exp, i, post, rest, scope, spaced, _i, _len, _ref2, _ref3, _ref4;
       code = post = '';
       _ref2 = this.expressions;
-      for (i = 0, _len = _ref2.length; i < _len; i++) {
+      for (i = _i = 0, _len = _ref2.length; _i < _len; i = ++_i) {
         exp = _ref2[i];
         exp = exp.unwrap();
-        if (!(exp instanceof Comment || exp instanceof Literal)) {
-          break;
-        }
+        if (!(exp instanceof Comment || exp instanceof Literal)) break;
       }
       o = merge(o, {
         level: LEVEL_TOP
       });
       if (i) {
-        rest = this.expressions.splice(i, this.expressions.length);
-        code = this.compileNode(o);
+        rest = this.expressions.splice(i, 9e9);
+        _ref3 = [this.spaced, false], spaced = _ref3[0], this.spaced = _ref3[1];
+        _ref4 = [this.compileNode(o), spaced], code = _ref4[0], this.spaced = _ref4[1];
         this.expressions = rest;
       }
       post = this.compileNode(o);
@@ -4941,84 +4961,105 @@ define('ace/mode/coffee/nodes', ['require', 'exports', 'module' , 'ace/mode/coff
       if (scope.expressions === this) {
         declars = o.scope.hasDeclarations();
         assigns = scope.hasAssignments;
-        if ((declars || assigns) && i) {
-          code += '\n';
-        }
-        if (declars) {
-          code += "" + this.tab + "var " + (scope.declaredVariables().join(', ')) + ";\n";
-        }
-        if (assigns) {
-          code += "" + this.tab + "var " + (multident(scope.assignedVariables().join(', '), this.tab)) + ";\n";
+        if (declars || assigns) {
+          if (i) code += '\n';
+          code += "" + this.tab + "var ";
+          if (declars) code += scope.declaredVariables().join(', ');
+          if (assigns) {
+            if (declars) code += ",\n" + (this.tab + TAB);
+            code += scope.assignedVariables().join(",\n" + (this.tab + TAB));
+          }
+          code += ';\n';
         }
       }
       return code + post;
     };
+
     Block.wrap = function(nodes) {
-      if (nodes.length === 1 && nodes[0] instanceof Block) {
-        return nodes[0];
-      }
+      if (nodes.length === 1 && nodes[0] instanceof Block) return nodes[0];
       return new Block(nodes);
     };
+
     return Block;
-  })();
-  exports.Literal = Literal = (function() {
-    __extends(Literal, Base);
+
+  })(Base);
+
+  exports.Literal = Literal = (function(_super) {
+
+    __extends(Literal, _super);
+
+    Literal.name = 'Literal';
+
     function Literal(value) {
       this.value = value;
     }
+
     Literal.prototype.makeReturn = function() {
       if (this.isStatement()) {
         return this;
       } else {
-        return new Return(this);
+        return Literal.__super__.makeReturn.apply(this, arguments);
       }
     };
+
     Literal.prototype.isAssignable = function() {
       return IDENTIFIER.test(this.value);
     };
+
     Literal.prototype.isStatement = function() {
       var _ref2;
       return (_ref2 = this.value) === 'break' || _ref2 === 'continue' || _ref2 === 'debugger';
     };
+
     Literal.prototype.isComplex = NO;
+
     Literal.prototype.assigns = function(name) {
       return name === this.value;
     };
+
     Literal.prototype.jumps = function(o) {
-      if (!this.isStatement()) {
-        return false;
-      }
-      if (!(o && (o.loop || o.block && (this.value !== 'continue')))) {
+      if (this.value === 'break' && !((o != null ? o.loop : void 0) || (o != null ? o.block : void 0))) {
         return this;
-      } else {
-        return false;
       }
+      if (this.value === 'continue' && !(o != null ? o.loop : void 0)) return this;
     };
+
     Literal.prototype.compileNode = function(o) {
-      var code;
-      code = this.isUndefined ? o.level >= LEVEL_ACCESS ? '(void 0)' : 'void 0' : this.value.reserved ? "\"" + this.value + "\"" : this.value;
+      var code, _ref2;
+      code = this.isUndefined ? o.level >= LEVEL_ACCESS ? '(void 0)' : 'void 0' : this.value === 'this' ? ((_ref2 = o.scope.method) != null ? _ref2.bound : void 0) ? o.scope.method.context : this.value : this.value.reserved ? "\"" + this.value + "\"" : this.value;
       if (this.isStatement()) {
         return "" + this.tab + code + ";";
       } else {
         return code;
       }
     };
+
     Literal.prototype.toString = function() {
       return ' "' + this.value + '"';
     };
+
     return Literal;
-  })();
-  exports.Return = Return = (function() {
-    __extends(Return, Base);
-    function Return(expr) {
-      if (expr && !expr.unwrap().isUndefined) {
-        this.expression = expr;
-      }
+
+  })(Base);
+
+  exports.Return = Return = (function(_super) {
+
+    __extends(Return, _super);
+
+    Return.name = 'Return';
+
+    function Return(expr) {
+      if (expr && !expr.unwrap().isUndefined) this.expression = expr;
     }
+
     Return.prototype.children = ['expression'];
+
     Return.prototype.isStatement = YES;
+
     Return.prototype.makeReturn = THIS;
+
     Return.prototype.jumps = THIS;
+
     Return.prototype.compile = function(o, level) {
       var expr, _ref2;
       expr = (_ref2 = this.expression) != null ? _ref2.makeReturn() : void 0;
@@ -5028,80 +5069,91 @@ define('ace/mode/coffee/nodes', ['require', 'exports', 'module' , 'ace/mode/coff
         return Return.__super__.compile.call(this, o, level);
       }
     };
+
     Return.prototype.compileNode = function(o) {
-      return this.tab + ("return" + (this.expression ? ' ' + this.expression.compile(o, LEVEL_PAREN) : '') + ";");
+      return this.tab + ("return" + [this.expression ? " " + (this.expression.compile(o, LEVEL_PAREN)) : void 0] + ";");
     };
+
     return Return;
-  })();
-  exports.Value = Value = (function() {
-    __extends(Value, Base);
+
+  })(Base);
+
+  exports.Value = Value = (function(_super) {
+
+    __extends(Value, _super);
+
+    Value.name = 'Value';
+
     function Value(base, props, tag) {
-      if (!props && base instanceof Value) {
-        return base;
-      }
+      if (!props && base instanceof Value) return base;
       this.base = base;
       this.properties = props || [];
-      if (tag) {
-        this[tag] = true;
-      }
+      if (tag) this[tag] = true;
       return this;
     }
+
     Value.prototype.children = ['base', 'properties'];
-    Value.prototype.push = function(prop) {
-      this.properties.push(prop);
+
+    Value.prototype.add = function(props) {
+      this.properties = this.properties.concat(props);
       return this;
     };
+
     Value.prototype.hasProperties = function() {
       return !!this.properties.length;
     };
+
     Value.prototype.isArray = function() {
       return !this.properties.length && this.base instanceof Arr;
     };
+
     Value.prototype.isComplex = function() {
       return this.hasProperties() || this.base.isComplex();
     };
+
     Value.prototype.isAssignable = function() {
       return this.hasProperties() || this.base.isAssignable();
     };
+
     Value.prototype.isSimpleNumber = function() {
       return this.base instanceof Literal && SIMPLENUM.test(this.base.value);
     };
+
+    Value.prototype.isString = function() {
+      return this.base instanceof Literal && IS_STRING.test(this.base.value);
+    };
+
     Value.prototype.isAtomic = function() {
       var node, _i, _len, _ref2;
       _ref2 = this.properties.concat(this.base);
       for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
         node = _ref2[_i];
-        if (node.soak || node instanceof Call) {
-          return false;
-        }
+        if (node.soak || node instanceof Call) return false;
       }
       return true;
     };
+
     Value.prototype.isStatement = function(o) {
       return !this.properties.length && this.base.isStatement(o);
     };
+
     Value.prototype.assigns = function(name) {
       return !this.properties.length && this.base.assigns(name);
     };
+
     Value.prototype.jumps = function(o) {
       return !this.properties.length && this.base.jumps(o);
     };
+
     Value.prototype.isObject = function(onlyGenerated) {
-      if (this.properties.length) {
-        return false;
-      }
+      if (this.properties.length) return false;
       return (this.base instanceof Obj) && (!onlyGenerated || this.base.generated);
     };
+
     Value.prototype.isSplice = function() {
       return last(this.properties) instanceof Slice;
     };
-    Value.prototype.makeReturn = function() {
-      if (this.properties.length) {
-        return Value.__super__.makeReturn.call(this);
-      } else {
-        return this.base.makeReturn();
-      }
-    };
+
     Value.prototype.unwrap = function() {
       if (this.properties.length) {
         return this;
@@ -5109,6 +5161,7 @@ define('ace/mode/coffee/nodes', ['require', 'exports', 'module' , 'ace/mode/coff
         return this.base;
       }
     };
+
     Value.prototype.cacheReference = function(o) {
       var base, bref, name, nref;
       name = last(this.properties);
@@ -5120,23 +5173,22 @@ define('ace/mode/coffee/nodes', ['require', 'exports', 'module' , 'ace/mode/coff
         bref = new Literal(o.scope.freeVariable('base'));
         base = new Value(new Parens(new Assign(bref, base)));
       }
-      if (!name) {
-        return [base, bref];
-      }
+      if (!name) return [base, bref];
       if (name.isComplex()) {
         nref = new Literal(o.scope.freeVariable('name'));
         name = new Index(new Assign(nref, name.index));
         nref = new Index(nref);
       }
-      return [base.push(name), new Value(bref || base.base, [nref || name])];
+      return [base.add(name), new Value(bref || base.base, [nref || name])];
     };
+
     Value.prototype.compileNode = function(o) {
       var code, prop, props, _i, _len;
       this.base.front = this.front;
       props = this.properties;
       code = this.base.compile(o, props.length ? LEVEL_ACCESS : null);
-      if (props[0] instanceof Access && this.isSimpleNumber()) {
-        code = "(" + code + ")";
+      if ((this.base instanceof Parens || props.length) && SIMPLENUM.test(code)) {
+        code = "" + code + ".";
       }
       for (_i = 0, _len = props.length; _i < _len; _i++) {
         prop = props[_i];
@@ -5144,59 +5196,73 @@ define('ace/mode/coffee/nodes', ['require', 'exports', 'module' , 'ace/mode/coff
       }
       return code;
     };
+
     Value.prototype.unfoldSoak = function(o) {
-      var result;
-      if (this.unfoldedSoak != null) {
-        return this.unfoldedSoak;
-      }
-      result = __bind(function() {
-        var fst, i, ifn, prop, ref, snd, _len, _ref2;
-        if (ifn = this.base.unfoldSoak(o)) {
-          Array.prototype.push.apply(ifn.body.properties, this.properties);
+      var result,
+        _this = this;
+      if (this.unfoldedSoak != null) return this.unfoldedSoak;
+      result = (function() {
+        var fst, i, ifn, prop, ref, snd, _i, _len, _ref2;
+        if (ifn = _this.base.unfoldSoak(o)) {
+          Array.prototype.push.apply(ifn.body.properties, _this.properties);
           return ifn;
         }
-        _ref2 = this.properties;
-        for (i = 0, _len = _ref2.length; i < _len; i++) {
+        _ref2 = _this.properties;
+        for (i = _i = 0, _len = _ref2.length; _i < _len; i = ++_i) {
           prop = _ref2[i];
-          if (prop.soak) {
-            prop.soak = false;
-            fst = new Value(this.base, this.properties.slice(0, i));
-            snd = new Value(this.base, this.properties.slice(i));
-            if (fst.isComplex()) {
-              ref = new Literal(o.scope.freeVariable('ref'));
-              fst = new Parens(new Assign(ref, fst));
-              snd.base = ref;
-            }
-            return new If(new Existence(fst), snd, {
-              soak: true
-            });
+          if (!prop.soak) continue;
+          prop.soak = false;
+          fst = new Value(_this.base, _this.properties.slice(0, i));
+          snd = new Value(_this.base, _this.properties.slice(i));
+          if (fst.isComplex()) {
+            ref = new Literal(o.scope.freeVariable('ref'));
+            fst = new Parens(new Assign(ref, fst));
+            snd.base = ref;
           }
+          return new If(new Existence(fst), snd, {
+            soak: true
+          });
         }
         return null;
-      }, this)();
+      })();
       return this.unfoldedSoak = result || false;
     };
+
     return Value;
-  })();
-  exports.Comment = Comment = (function() {
-    __extends(Comment, Base);
+
+  })(Base);
+
+  exports.Comment = Comment = (function(_super) {
+
+    __extends(Comment, _super);
+
+    Comment.name = 'Comment';
+
     function Comment(comment) {
       this.comment = comment;
     }
+
     Comment.prototype.isStatement = YES;
+
     Comment.prototype.makeReturn = THIS;
+
     Comment.prototype.compileNode = function(o, level) {
       var code;
-      code = '/*' + multident(this.comment, this.tab) + '*/';
-      if ((level || o.level) === LEVEL_TOP) {
-        code = o.indent + code;
-      }
+      code = '/*' + multident(this.comment, this.tab) + ("\n" + this.tab + "*/\n");
+      if ((level || o.level) === LEVEL_TOP) code = o.indent + code;
       return code;
     };
+
     return Comment;
-  })();
-  exports.Call = Call = (function() {
-    __extends(Call, Base);
+
+  })(Base);
+
+  exports.Call = Call = (function(_super) {
+
+    __extends(Call, _super);
+
+    Call.name = 'Call';
+
     function Call(variable, args, soak) {
       this.args = args != null ? args : [];
       this.soak = soak;
@@ -5204,40 +5270,45 @@ define('ace/mode/coffee/nodes', ['require', 'exports', 'module' , 'ace/mode/coff
       this.isSuper = variable === 'super';
       this.variable = this.isSuper ? null : variable;
     }
+
     Call.prototype.children = ['variable', 'args'];
+
     Call.prototype.newInstance = function() {
-      var base;
-      base = this.variable.base || this.variable;
-      if (base instanceof Call) {
+      var base, _ref2;
+      base = ((_ref2 = this.variable) != null ? _ref2.base : void 0) || this.variable;
+      if (base instanceof Call && !base.isNew) {
         base.newInstance();
       } else {
         this.isNew = true;
       }
       return this;
     };
+
     Call.prototype.superReference = function(o) {
-      var method, name;
+      var accesses, method, name;
       method = o.scope.method;
-      if (!method) {
-        throw SyntaxError('cannot call super outside of a function.');
-      }
+      if (!method) throw SyntaxError('cannot call super outside of a function.');
       name = method.name;
-      if (!name) {
+      if (name == null) {
         throw SyntaxError('cannot call super on an anonymous function.');
       }
       if (method.klass) {
-        return "" + method.klass + ".__super__." + name;
+        accesses = [new Access(new Literal('__super__'))];
+        if (method["static"]) {
+          accesses.push(new Access(new Literal('constructor')));
+        }
+        accesses.push(new Access(new Literal(name)));
+        return (new Value(new Literal(method.klass), accesses)).compile(o);
       } else {
         return "" + name + ".__super__.constructor";
       }
     };
+
     Call.prototype.unfoldSoak = function(o) {
       var call, ifn, left, list, rite, _i, _len, _ref2, _ref3;
       if (this.soak) {
         if (this.variable) {
-          if (ifn = unfoldSoak(o, this, 'variable')) {
-            return ifn;
-          }
+          if (ifn = unfoldSoak(o, this, 'variable')) return ifn;
           _ref2 = new Value(this.variable).cacheReference(o), left = _ref2[0], rite = _ref2[1];
         } else {
           left = new Literal(this.superReference(o));
@@ -5258,13 +5329,9 @@ define('ace/mode/coffee/nodes', ['require', 'exports', 'module' , 'ace/mode/coff
           call = call.variable;
           continue;
         }
-        if (!(call.variable instanceof Value)) {
-          break;
-        }
+        if (!(call.variable instanceof Value)) break;
         list.push(call);
-        if (!((call = call.variable.base) instanceof Call)) {
-          break;
-        }
+        if (!((call = call.variable.base) instanceof Call)) break;
       }
       _ref3 = list.reverse();
       for (_i = 0, _len = _ref3.length; _i < _len; _i++) {
@@ -5280,8 +5347,9 @@ define('ace/mode/coffee/nodes', ['require', 'exports', 'module' , 'ace/mode/coff
       }
       return ifn;
     };
+
     Call.prototype.filterImplicitObjects = function(list) {
-      var node, nodes, obj, prop, properties, _i, _j, _len, _len2, _ref2;
+      var node, nodes, obj, prop, properties, _i, _j, _len, _len1, _ref2;
       nodes = [];
       for (_i = 0, _len = list.length; _i < _len; _i++) {
         node = list[_i];
@@ -5291,12 +5359,10 @@ define('ace/mode/coffee/nodes', ['require', 'exports', 'module' , 'ace/mode/coff
         }
         obj = null;
         _ref2 = node.base.properties;
-        for (_j = 0, _len2 = _ref2.length; _j < _len2; _j++) {
+        for (_j = 0, _len1 = _ref2.length; _j < _len1; _j++) {
           prop = _ref2[_j];
-          if (prop instanceof Assign) {
-            if (!obj) {
-              nodes.push(obj = new Obj(properties = [], true));
-            }
+          if (prop instanceof Assign || prop instanceof Comment) {
+            if (!obj) nodes.push(obj = new Obj(properties = [], true));
             properties.push(prop);
           } else {
             nodes.push(prop);
@@ -5306,11 +5372,10 @@ define('ace/mode/coffee/nodes', ['require', 'exports', 'module' , 'ace/mode/coff
       }
       return nodes;
     };
+
     Call.prototype.compileNode = function(o) {
       var arg, args, code, _ref2;
-      if ((_ref2 = this.variable) != null) {
-        _ref2.front = this.front;
-      }
+      if ((_ref2 = this.variable) != null) _ref2.front = this.front;
       if (code = Splat.compileSplattedArray(o, this.args, true)) {
         return this.compileSplat(o, code);
       }
@@ -5330,9 +5395,11 @@ define('ace/mode/coffee/nodes', ['require', 'exports', 'module' , 'ace/mode/coff
         return (this.isNew ? 'new ' : '') + this.variable.compile(o, LEVEL_ACCESS) + ("(" + args + ")");
       }
     };
+
     Call.prototype.compileSuper = function(args, o) {
       return "" + (this.superReference(o)) + ".call(this" + (args.length ? ', ' : '') + args + ")";
     };
+
     Call.prototype.compileSplat = function(o, splatArgs) {
       var base, fun, idt, name, ref;
       if (this.isSuper) {
@@ -5340,7 +5407,7 @@ define('ace/mode/coffee/nodes', ['require', 'exports', 'module' , 'ace/mode/coff
       }
       if (this.isNew) {
         idt = this.tab + TAB;
-        return "(function(func, args, ctor) {\n" + idt + "ctor.prototype = func.prototype;\n" + idt + "var child = new ctor, result = func.apply(child, args);\n" + idt + "return typeof result === \"object\" ? result : child;\n" + this.tab + "})(" + (this.variable.compile(o, LEVEL_LIST)) + ", " + splatArgs + ", function() {})";
+        return "(function(func, args, ctor) {\n" + idt + "ctor.prototype = func.prototype;\n" + idt + "var child = new ctor, result = func.apply(child, args), t = typeof result;\n" + idt + "return t == \"object\" || t == \"function\" ? result || child : child;\n" + this.tab + "})(" + (this.variable.compile(o, LEVEL_LIST)) + ", " + splatArgs + ", function(){})";
       }
       base = new Value(this.variable);
       if ((name = base.properties.pop()) && base.isComplex()) {
@@ -5348,9 +5415,7 @@ define('ace/mode/coffee/nodes', ['require', 'exports', 'module' , 'ace/mode/coff
         fun = "(" + ref + " = " + (base.compile(o, LEVEL_LIST)) + ")" + (name.compile(o));
       } else {
         fun = base.compile(o, LEVEL_ACCESS);
-        if (SIMPLENUM.test(fun)) {
-          fun = "(" + fun + ")";
-        }
+        if (SIMPLENUM.test(fun)) fun = "(" + fun + ")";
         if (name) {
           ref = fun;
           fun += name.compile(o);
@@ -5360,109 +5425,143 @@ define('ace/mode/coffee/nodes', ['require', 'exports', 'module' , 'ace/mode/coff
       }
       return "" + fun + ".apply(" + ref + ", " + splatArgs + ")";
     };
+
     return Call;
-  })();
-  exports.Extends = Extends = (function() {
-    __extends(Extends, Base);
+
+  })(Base);
+
+  exports.Extends = Extends = (function(_super) {
+
+    __extends(Extends, _super);
+
+    Extends.name = 'Extends';
+
     function Extends(child, parent) {
       this.child = child;
       this.parent = parent;
     }
+
     Extends.prototype.children = ['child', 'parent'];
+
     Extends.prototype.compile = function(o) {
-      utility('hasProp');
       return new Call(new Value(new Literal(utility('extends'))), [this.child, this.parent]).compile(o);
     };
+
     return Extends;
-  })();
-  exports.Access = Access = (function() {
-    __extends(Access, Base);
+
+  })(Base);
+
+  exports.Access = Access = (function(_super) {
+
+    __extends(Access, _super);
+
+    Access.name = 'Access';
+
     function Access(name, tag) {
       this.name = name;
       this.name.asKey = true;
-      this.proto = tag === 'proto' ? '.prototype' : '';
       this.soak = tag === 'soak';
     }
+
     Access.prototype.children = ['name'];
+
     Access.prototype.compile = function(o) {
       var name;
       name = this.name.compile(o);
-      return this.proto + (IS_STRING.test(name) ? "[" + name + "]" : "." + name);
+      if (IDENTIFIER.test(name)) {
+        return "." + name;
+      } else {
+        return "[" + name + "]";
+      }
     };
+
     Access.prototype.isComplex = NO;
+
     return Access;
-  })();
-  exports.Index = Index = (function() {
-    __extends(Index, Base);
+
+  })(Base);
+
+  exports.Index = Index = (function(_super) {
+
+    __extends(Index, _super);
+
+    Index.name = 'Index';
+
     function Index(index) {
       this.index = index;
     }
+
     Index.prototype.children = ['index'];
+
     Index.prototype.compile = function(o) {
-      return (this.proto ? '.prototype' : '') + ("[" + (this.index.compile(o, LEVEL_PAREN)) + "]");
+      return "[" + (this.index.compile(o, LEVEL_PAREN)) + "]";
     };
+
     Index.prototype.isComplex = function() {
       return this.index.isComplex();
     };
+
     return Index;
-  })();
-  exports.Range = Range = (function() {
-    __extends(Range, Base);
+
+  })(Base);
+
+  exports.Range = Range = (function(_super) {
+
+    __extends(Range, _super);
+
+    Range.name = 'Range';
+
     Range.prototype.children = ['from', 'to'];
+
     function Range(from, to, tag) {
       this.from = from;
       this.to = to;
       this.exclusive = tag === 'exclusive';
       this.equals = this.exclusive ? '' : '=';
     }
+
     Range.prototype.compileVariables = function(o) {
       var step, _ref2, _ref3, _ref4, _ref5;
       o = merge(o, {
         top: true
       });
-      _ref2 = this.from.cache(o, LEVEL_LIST), this.from = _ref2[0], this.fromVar = _ref2[1];
-      _ref3 = this.to.cache(o, LEVEL_LIST), this.to = _ref3[0], this.toVar = _ref3[1];
+      _ref2 = this.from.cache(o, LEVEL_LIST), this.fromC = _ref2[0], this.fromVar = _ref2[1];
+      _ref3 = this.to.cache(o, LEVEL_LIST), this.toC = _ref3[0], this.toVar = _ref3[1];
       if (step = del(o, 'step')) {
         _ref4 = step.cache(o, LEVEL_LIST), this.step = _ref4[0], this.stepVar = _ref4[1];
       }
       _ref5 = [this.fromVar.match(SIMPLENUM), this.toVar.match(SIMPLENUM)], this.fromNum = _ref5[0], this.toNum = _ref5[1];
-      if (this.stepVar) {
-        return this.stepNum = this.stepVar.match(SIMPLENUM);
-      }
+      if (this.stepVar) return this.stepNum = this.stepVar.match(SIMPLENUM);
     };
+
     Range.prototype.compileNode = function(o) {
-      var cond, condPart, from, gt, idx, known, lt, stepPart, to, varPart, _ref2, _ref3;
-      if (!this.fromVar) {
-        this.compileVariables(o);
-      }
-      if (!o.index) {
-        return this.compileArray(o);
-      }
+      var cond, condPart, from, gt, idx, idxName, known, lt, namedIndex, stepPart, to, varPart, _ref2, _ref3;
+      if (!this.fromVar) this.compileVariables(o);
+      if (!o.index) return this.compileArray(o);
       known = this.fromNum && this.toNum;
       idx = del(o, 'index');
-      varPart = "" + idx + " = " + this.from;
-      if (this.to !== this.toVar) {
-        varPart += ", " + this.to;
-      }
-      if (this.step !== this.stepVar) {
-        varPart += ", " + this.step;
-      }
+      idxName = del(o, 'name');
+      namedIndex = idxName && idxName !== idx;
+      varPart = "" + idx + " = " + this.fromC;
+      if (this.toC !== this.toVar) varPart += ", " + this.toC;
+      if (this.step !== this.stepVar) varPart += ", " + this.step;
       _ref2 = ["" + idx + " <" + this.equals, "" + idx + " >" + this.equals], lt = _ref2[0], gt = _ref2[1];
-      condPart = this.stepNum ? condPart = +this.stepNum > 0 ? "" + lt + " " + this.toVar : "" + gt + " " + this.toVar : known ? ((_ref3 = [+this.fromNum, +this.toNum], from = _ref3[0], to = _ref3[1], _ref3), condPart = from <= to ? "" + lt + " " + to : "" + gt + " " + to) : (cond = "" + this.fromVar + " <= " + this.toVar, condPart = "" + cond + " ? " + lt + " " + this.toVar + " : " + gt + " " + this.toVar);
-      stepPart = this.stepVar ? "" + idx + " += " + this.stepVar : known ? from <= to ? "" + idx + "++" : "" + idx + "--" : "" + cond + " ? " + idx + "++ : " + idx + "--";
+      condPart = this.stepNum ? +this.stepNum > 0 ? "" + lt + " " + this.toVar : "" + gt + " " + this.toVar : known ? ((_ref3 = [+this.fromNum, +this.toNum], from = _ref3[0], to = _ref3[1], _ref3), from <= to ? "" + lt + " " + to : "" + gt + " " + to) : (cond = "" + this.fromVar + " <= " + this.toVar, "" + cond + " ? " + lt + " " + this.toVar + " : " + gt + " " + this.toVar);
+      stepPart = this.stepVar ? "" + idx + " += " + this.stepVar : known ? namedIndex ? from <= to ? "++" + idx : "--" + idx : from <= to ? "" + idx + "++" : "" + idx + "--" : namedIndex ? "" + cond + " ? ++" + idx + " : --" + idx : "" + cond + " ? " + idx + "++ : " + idx + "--";
+      if (namedIndex) varPart = "" + idxName + " = " + varPart;
+      if (namedIndex) stepPart = "" + idxName + " = " + stepPart;
       return "" + varPart + "; " + condPart + "; " + stepPart;
     };
+
     Range.prototype.compileArray = function(o) {
-      var body, cond, i, idt, post, pre, range, result, vars, _i, _ref2, _ref3, _results;
+      var args, body, cond, hasArgs, i, idt, post, pre, range, result, vars, _i, _ref2, _ref3, _results;
       if (this.fromNum && this.toNum && Math.abs(this.fromNum - this.toNum) <= 20) {
         range = (function() {
           _results = [];
           for (var _i = _ref2 = +this.fromNum, _ref3 = +this.toNum; _ref2 <= _ref3 ? _i <= _ref3 : _i >= _ref3; _ref2 <= _ref3 ? _i++ : _i--){ _results.push(_i); }
           return _results;
-        }).apply(this, arguments);
-        if (this.exclusive) {
-          range.pop();
-        }
+        }).apply(this);
+        if (this.exclusive) range.pop();
         return "[" + (range.join(', ')) + "]";
       }
       idt = this.tab + TAB;
@@ -5473,54 +5572,85 @@ define('ace/mode/coffee/nodes', ['require', 'exports', 'module' , 'ace/mode/coff
         o.index = i;
         body = this.compileNode(o);
       } else {
-        vars = ("" + i + " = " + this.from) + (this.to !== this.toVar ? ", " + this.to : '');
+        vars = ("" + i + " = " + this.fromC) + (this.toC !== this.toVar ? ", " + this.toC : '');
         cond = "" + this.fromVar + " <= " + this.toVar;
         body = "var " + vars + "; " + cond + " ? " + i + " <" + this.equals + " " + this.toVar + " : " + i + " >" + this.equals + " " + this.toVar + "; " + cond + " ? " + i + "++ : " + i + "--";
       }
       post = "{ " + result + ".push(" + i + "); }\n" + idt + "return " + result + ";\n" + o.indent;
-      return "(function() {" + pre + "\n" + idt + "for (" + body + ")" + post + "}).apply(this, arguments)";
+      hasArgs = function(node) {
+        return node != null ? node.contains(function(n) {
+          return n instanceof Literal && n.value === 'arguments' && !n.asKey;
+        }) : void 0;
+      };
+      if (hasArgs(this.from) || hasArgs(this.to)) args = ', arguments';
+      return "(function() {" + pre + "\n" + idt + "for (" + body + ")" + post + "}).apply(this" + (args != null ? args : '') + ")";
     };
+
     return Range;
-  })();
-  exports.Slice = Slice = (function() {
-    __extends(Slice, Base);
+
+  })(Base);
+
+  exports.Slice = Slice = (function(_super) {
+
+    __extends(Slice, _super);
+
+    Slice.name = 'Slice';
+
     Slice.prototype.children = ['range'];
+
     function Slice(range) {
       this.range = range;
       Slice.__super__.constructor.call(this);
     }
+
     Slice.prototype.compileNode = function(o) {
       var compiled, from, fromStr, to, toStr, _ref2;
       _ref2 = this.range, to = _ref2.to, from = _ref2.from;
       fromStr = from && from.compile(o, LEVEL_PAREN) || '0';
       compiled = to && to.compile(o, LEVEL_PAREN);
       if (to && !(!this.range.exclusive && +compiled === -1)) {
-        toStr = ', ' + (this.range.exclusive ? compiled : SIMPLENUM.test(compiled) ? (+compiled + 1).toString() : "(" + compiled + " + 1) || 9e9");
+        toStr = ', ' + (this.range.exclusive ? compiled : SIMPLENUM.test(compiled) ? "" + (+compiled + 1) : (compiled = to.compile(o, LEVEL_ACCESS), "" + compiled + " + 1 || 9e9"));
       }
       return ".slice(" + fromStr + (toStr || '') + ")";
     };
+
     return Slice;
-  })();
-  exports.Obj = Obj = (function() {
-    __extends(Obj, Base);
+
+  })(Base);
+
+  exports.Obj = Obj = (function(_super) {
+
+    __extends(Obj, _super);
+
+    Obj.name = 'Obj';
+
     function Obj(props, generated) {
       this.generated = generated != null ? generated : false;
       this.objects = this.properties = props || [];
     }
+
     Obj.prototype.children = ['properties'];
+
     Obj.prototype.compileNode = function(o) {
-      var i, idt, indent, join, lastNoncom, node, obj, prop, props, _i, _len;
+      var i, idt, indent, join, lastNoncom, node, obj, prop, propName, propNames, props, _i, _j, _len, _len1, _ref2;
       props = this.properties;
-      if (!props.length) {
-        if (this.front) {
-          return '({})';
-        } else {
-          return '{}';
+      propNames = [];
+      _ref2 = this.properties;
+      for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
+        prop = _ref2[_i];
+        if (prop.isComplex()) prop = prop.variable;
+        if (prop != null) {
+          propName = prop.unwrapAll().value.toString();
+          if (__indexOf.call(propNames, propName) >= 0) {
+            throw SyntaxError("multiple object literal properties named \"" + propName + "\"");
+          }
+          propNames.push(propName);
         }
       }
+      if (!props.length) return (this.front ? '({})' : '{}');
       if (this.generated) {
-        for (_i = 0, _len = props.length; _i < _len; _i++) {
-          node = props[_i];
+        for (_j = 0, _len1 = props.length; _j < _len1; _j++) {
+          node = props[_j];
           if (node instanceof Value) {
             throw new Error('cannot have an implicit value in an implicit object');
           }
@@ -5529,9 +5659,9 @@ define('ace/mode/coffee/nodes', ['require', 'exports', 'module' , 'ace/mode/coff
       idt = o.indent += TAB;
       lastNoncom = this.lastNonComment(this.properties);
       props = (function() {
-        var _len2, _results;
+        var _k, _len2, _results;
         _results = [];
-        for (i = 0, _len2 = props.length; i < _len2; i++) {
+        for (i = _k = 0, _len2 = props.length; _k < _len2; i = ++_k) {
           prop = props[i];
           join = i === props.length - 1 ? '' : prop === lastNoncom || prop instanceof Comment ? '\n' : ',\n';
           indent = prop instanceof Comment ? '' : idt;
@@ -5539,9 +5669,7 @@ define('ace/mode/coffee/nodes', ['require', 'exports', 'module' , 'ace/mode/coff
             prop = new Assign(prop.properties[0].name, prop, 'object');
           }
           if (!(prop instanceof Comment)) {
-            if (!(prop instanceof Assign)) {
-              prop = new Assign(prop, prop, 'object');
-            }
+            if (!(prop instanceof Assign)) prop = new Assign(prop, prop, 'object');
             (prop.variable.base || prop.variable).asKey = true;
           }
           _results.push(indent + prop.compile(o, LEVEL_TOP) + join);
@@ -5556,36 +5684,41 @@ define('ace/mode/coffee/nodes', ['require', 'exports', 'module' , 'ace/mode/coff
         return obj;
       }
     };
+
     Obj.prototype.assigns = function(name) {
       var prop, _i, _len, _ref2;
       _ref2 = this.properties;
       for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
         prop = _ref2[_i];
-        if (prop.assigns(name)) {
-          return true;
-        }
+        if (prop.assigns(name)) return true;
       }
       return false;
     };
+
     return Obj;
-  })();
-  exports.Arr = Arr = (function() {
-    __extends(Arr, Base);
+
+  })(Base);
+
+  exports.Arr = Arr = (function(_super) {
+
+    __extends(Arr, _super);
+
+    Arr.name = 'Arr';
+
     function Arr(objs) {
       this.objects = objs || [];
     }
+
     Arr.prototype.children = ['objects'];
+
     Arr.prototype.filterImplicitObjects = Call.prototype.filterImplicitObjects;
+
     Arr.prototype.compileNode = function(o) {
       var code, obj, objs;
-      if (!this.objects.length) {
-        return '[]';
-      }
+      if (!this.objects.length) return '[]';
       o.indent += TAB;
       objs = this.filterImplicitObjects(this.objects);
-      if (code = Splat.compileSplattedArray(o, objs)) {
-        return code;
-      }
+      if (code = Splat.compileSplattedArray(o, objs)) return code;
       code = ((function() {
         var _i, _len, _results;
         _results = [];
@@ -5601,21 +5734,27 @@ define('ace/mode/coffee/nodes', ['require', 'exports', 'module' , 'ace/mode/coff
         return "[" + code + "]";
       }
     };
+
     Arr.prototype.assigns = function(name) {
       var obj, _i, _len, _ref2;
       _ref2 = this.objects;
       for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
         obj = _ref2[_i];
-        if (obj.assigns(name)) {
-          return true;
-        }
+        if (obj.assigns(name)) return true;
       }
       return false;
     };
+
     return Arr;
-  })();
-  exports.Class = Class = (function() {
-    __extends(Class, Base);
+
+  })(Base);
+
+  exports.Class = Class = (function(_super) {
+
+    __extends(Class, _super);
+
+    Class.name = 'Class';
+
     function Class(variable, parent, body) {
       this.variable = variable;
       this.parent = parent;
@@ -5623,43 +5762,45 @@ define('ace/mode/coffee/nodes', ['require', 'exports', 'module' , 'ace/mode/coff
       this.boundFuncs = [];
       this.body.classBody = true;
     }
+
     Class.prototype.children = ['variable', 'parent', 'body'];
+
     Class.prototype.determineName = function() {
       var decl, tail;
-      if (!this.variable) {
-        return null;
-      }
+      if (!this.variable) return null;
       decl = (tail = last(this.variable.properties)) ? tail instanceof Access && tail.name.value : this.variable.base.value;
+      if (__indexOf.call(STRICT_PROSCRIBED, decl) >= 0) {
+        throw SyntaxError("variable name may not be " + decl);
+      }
       return decl && (decl = IDENTIFIER.test(decl) && decl);
     };
+
     Class.prototype.setContext = function(name) {
       return this.body.traverseChildren(false, function(node) {
-        if (node.classBody) {
-          return false;
-        }
+        if (node.classBody) return false;
         if (node instanceof Literal && node.value === 'this') {
           return node.value = name;
         } else if (node instanceof Code) {
           node.klass = name;
-          if (node.bound) {
-            return node.context = name;
-          }
+          if (node.bound) return node.context = name;
         }
       });
     };
+
     Class.prototype.addBoundFunctions = function(o) {
-      var bname, bvar, _i, _len, _ref2, _results;
+      var bvar, lhs, _i, _len, _ref2, _results;
       if (this.boundFuncs.length) {
         _ref2 = this.boundFuncs;
         _results = [];
         for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
           bvar = _ref2[_i];
-          bname = bvar.compile(o);
-          _results.push(this.ctor.body.unshift(new Literal("this." + bname + " = " + (utility('bind')) + "(this." + bname + ", this)")));
+          lhs = (new Value(new Literal("this"), [new Access(bvar)])).compile(o);
+          _results.push(this.ctor.body.unshift(new Literal("" + lhs + " = " + (utility('bind')) + "(" + lhs + ", this)")));
         }
         return _results;
       }
     };
+
     Class.prototype.addProperties = function(node, name, o) {
       var assign, base, exprs, func, props;
       props = node.base.properties.slice(0);
@@ -5685,12 +5826,15 @@ define('ace/mode/coffee/nodes', ['require', 'exports', 'module' , 'ace/mode/coff
                 assign = new Assign(new Literal(this.externalCtor), func);
               }
             } else {
-              if (!assign.variable["this"]) {
-                assign.variable = new Value(new Literal(name), [new Access(base, 'proto')]);
-              }
-              if (func instanceof Code && func.bound) {
-                this.boundFuncs.push(base);
-                func.bound = false;
+              if (assign.variable["this"]) {
+                func["static"] = true;
+                if (func.bound) func.context = name;
+              } else {
+                assign.variable = new Value(new Literal(name), [new Access(new Literal('prototype')), new Access(base)]);
+                if (func instanceof Code && func.bound) {
+                  this.boundFuncs.push(base);
+                  func.bound = false;
+                }
               }
             }
           }
@@ -5700,24 +5844,35 @@ define('ace/mode/coffee/nodes', ['require', 'exports', 'module' , 'ace/mode/coff
       }).call(this);
       return compact(exprs);
     };
+
     Class.prototype.walkBody = function(name, o) {
-      return this.traverseChildren(false, __bind(function(child) {
-        var exps, i, node, _len, _ref2;
-        if (child instanceof Class) {
-          return false;
-        }
+      var _this = this;
+      return this.traverseChildren(false, function(child) {
+        var exps, i, node, _i, _len, _ref2;
+        if (child instanceof Class) return false;
         if (child instanceof Block) {
           _ref2 = exps = child.expressions;
-          for (i = 0, _len = _ref2.length; i < _len; i++) {
+          for (i = _i = 0, _len = _ref2.length; _i < _len; i = ++_i) {
             node = _ref2[i];
             if (node instanceof Value && node.isObject(true)) {
-              exps[i] = this.addProperties(node, name, o);
+              exps[i] = _this.addProperties(node, name, o);
             }
           }
           return child.expressions = exps = flatten(exps);
         }
-      }, this));
+      });
     };
+
+    Class.prototype.hoistDirectivePrologue = function() {
+      var expressions, index, node;
+      index = 0;
+      expressions = this.body.expressions;
+      while ((node = expressions[index]) && node instanceof Comment || node instanceof Value && node.isString()) {
+        ++index;
+      }
+      return this.directives = expressions.splice(0, index);
+    };
+
     Class.prototype.ensureConstructor = function(name) {
       if (!this.ctor) {
         this.ctor = new Code;
@@ -5727,85 +5882,112 @@ define('ace/mode/coffee/nodes', ['require', 'exports', 'module' , 'ace/mode/coff
         if (this.externalCtor) {
           this.ctor.body.push(new Literal("" + this.externalCtor + ".apply(this, arguments)"));
         }
+        this.ctor.body.makeReturn();
         this.body.expressions.unshift(this.ctor);
       }
       this.ctor.ctor = this.ctor.name = name;
       this.ctor.klass = null;
       return this.ctor.noReturn = true;
     };
+
     Class.prototype.compileNode = function(o) {
-      var decl, klass, lname, name;
+      var call, decl, klass, lname, name, params, _ref2;
       decl = this.determineName();
-      name = decl || this.name || '_Class';
+      name = decl || '_Class';
+      if (name.reserved) name = "_" + name;
       lname = new Literal(name);
+      this.hoistDirectivePrologue();
       this.setContext(name);
       this.walkBody(name, o);
       this.ensureConstructor(name);
-      if (this.parent) {
-        this.body.expressions.unshift(new Extends(lname, this.parent));
-      }
-      if (!(this.ctor instanceof Code)) {
-        this.body.expressions.unshift(this.ctor);
+      this.body.spaced = true;
+      if (!(this.ctor instanceof Code)) this.body.expressions.unshift(this.ctor);
+      if (decl) {
+        this.body.expressions.unshift(new Assign(new Value(new Literal(name), [new Access(new Literal('name'))]), new Literal("'" + name + "'")));
       }
       this.body.expressions.push(lname);
+      (_ref2 = this.body.expressions).unshift.apply(_ref2, this.directives);
       this.addBoundFunctions(o);
-      klass = new Parens(Closure.wrap(this.body), true);
-      if (this.variable) {
-        klass = new Assign(this.variable, klass);
-      }
+      call = Closure.wrap(this.body);
+      if (this.parent) {
+        this.superClass = new Literal(o.scope.freeVariable('super', false));
+        this.body.expressions.unshift(new Extends(lname, this.superClass));
+        call.args.push(this.parent);
+        params = call.variable.params || call.variable.base.params;
+        params.push(new Param(this.superClass));
+      }
+      klass = new Parens(call, true);
+      if (this.variable) klass = new Assign(this.variable, klass);
       return klass.compile(o);
     };
+
     return Class;
-  })();
-  exports.Assign = Assign = (function() {
-    __extends(Assign, Base);
+
+  })(Base);
+
+  exports.Assign = Assign = (function(_super) {
+
+    __extends(Assign, _super);
+
+    Assign.name = 'Assign';
+
     function Assign(variable, value, context, options) {
+      var forbidden, name, _ref2;
       this.variable = variable;
       this.value = value;
       this.context = context;
       this.param = options && options.param;
+      this.subpattern = options && options.subpattern;
+      forbidden = (_ref2 = (name = this.variable.unwrapAll().value), __indexOf.call(STRICT_PROSCRIBED, _ref2) >= 0);
+      if (forbidden && this.context !== 'object') {
+        throw SyntaxError("variable name may not be \"" + name + "\"");
+      }
     }
+
     Assign.prototype.children = ['variable', 'value'];
+
+    Assign.prototype.isStatement = function(o) {
+      return (o != null ? o.level : void 0) === LEVEL_TOP && (this.context != null) && __indexOf.call(this.context, "?") >= 0;
+    };
+
     Assign.prototype.assigns = function(name) {
       return this[this.context === 'object' ? 'value' : 'variable'].assigns(name);
     };
+
     Assign.prototype.unfoldSoak = function(o) {
       return unfoldSoak(o, this, 'variable');
     };
+
     Assign.prototype.compileNode = function(o) {
-      var isValue, match, name, val, _ref2;
+      var isValue, match, name, val, varBase, _ref2, _ref3, _ref4, _ref5;
       if (isValue = this.variable instanceof Value) {
         if (this.variable.isArray() || this.variable.isObject()) {
           return this.compilePatternMatch(o);
         }
-        if (this.variable.isSplice()) {
-          return this.compileSplice(o);
-        }
+        if (this.variable.isSplice()) return this.compileSplice(o);
         if ((_ref2 = this.context) === '||=' || _ref2 === '&&=' || _ref2 === '?=') {
           return this.compileConditional(o);
         }
       }
       name = this.variable.compile(o, LEVEL_LIST);
-      if (!(this.context || this.variable.isAssignable())) {
-        throw SyntaxError("\"" + (this.variable.compile(o)) + "\" cannot be assigned.");
-      }
-      if (!(this.context || isValue && (this.variable.namespaced || this.variable.hasProperties()))) {
-        if (this.param) {
-          o.scope.add(name, 'var');
-        } else {
-          o.scope.find(name);
+      if (!this.context) {
+        if (!(varBase = this.variable.unwrapAll()).isAssignable()) {
+          throw SyntaxError("\"" + (this.variable.compile(o)) + "\" cannot be assigned.");
+        }
+        if (!(typeof varBase.hasProperties === "function" ? varBase.hasProperties() : void 0)) {
+          if (this.param) {
+            o.scope.add(name, 'var');
+          } else {
+            o.scope.find(name);
+          }
         }
       }
       if (this.value instanceof Code && (match = METHOD_DEF.exec(name))) {
-        this.value.name = match[2];
-        if (match[1]) {
-          this.value.klass = match[1];
-        }
+        if (match[1]) this.value.klass = match[1];
+        this.value.name = (_ref3 = (_ref4 = (_ref5 = match[2]) != null ? _ref5 : match[3]) != null ? _ref4 : match[4]) != null ? _ref3 : match[5];
       }
       val = this.value.compile(o, LEVEL_LIST);
-      if (this.context === 'object') {
-        return "" + name + ": " + val;
-      }
+      if (this.context === 'object') return "" + name + ": " + val;
       val = name + (" " + (this.context || '=') + " ") + val;
       if (o.level <= LEVEL_LIST) {
         return val;
@@ -5813,8 +5995,9 @@ define('ace/mode/coffee/nodes', ['require', 'exports', 'module' , 'ace/mode/coff
         return "(" + val + ")";
       }
     };
+
     Assign.prototype.compilePatternMatch = function(o) {
-      var acc, assigns, code, i, idx, isObject, ivar, obj, objects, olen, ref, rest, splat, top, val, value, vvar, _len, _ref2, _ref3, _ref4, _ref5;
+      var acc, assigns, code, i, idx, isObject, ivar, name, obj, objects, olen, ref, rest, splat, top, val, value, vvar, _i, _len, _ref2, _ref3, _ref4, _ref5, _ref6, _ref7, _ref8;
       top = o.level === LEVEL_TOP;
       value = this.value;
       objects = this.variable.base.objects;
@@ -5829,10 +6012,10 @@ define('ace/mode/coffee/nodes', ['require', 'exports', 'module' , 'ace/mode/coff
       isObject = this.variable.isObject();
       if (top && olen === 1 && !((obj = objects[0]) instanceof Splat)) {
         if (obj instanceof Assign) {
-          _ref2 = obj, idx = _ref2.variable.base, obj = _ref2.value;
+          _ref2 = obj, (_ref3 = _ref2.variable, idx = _ref3.base), obj = _ref2.value;
         } else {
           if (obj.base instanceof Parens) {
-            _ref3 = new Value(obj.unwrapAll()).cacheReference(o), obj = _ref3[0], idx = _ref3[1];
+            _ref4 = new Value(obj.unwrapAll()).cacheReference(o), obj = _ref4[0], idx = _ref4[1];
           } else {
             idx = isObject ? obj["this"] ? obj.properties[0].name : obj : new Literal(0);
           }
@@ -5840,6 +6023,9 @@ define('ace/mode/coffee/nodes', ['require', 'exports', 'module' , 'ace/mode/coff
         acc = IDENTIFIER.test(idx.unwrap().value || 0);
         value = new Value(value);
         value.properties.push(new (acc ? Access : Index)(idx));
+        if (_ref5 = obj.unwrap().value, __indexOf.call(RESERVED, _ref5) >= 0) {
+          throw new SyntaxError("assignment to a reserved word: " + (obj.compile(o)) + " = " + (value.compile(o)));
+        }
         return new Assign(obj, value, null, {
           param: this.param
         }).compile(o, LEVEL_TOP);
@@ -5851,21 +6037,23 @@ define('ace/mode/coffee/nodes', ['require', 'exports', 'module' , 'ace/mode/coff
         assigns.push("" + (ref = o.scope.freeVariable('ref')) + " = " + vvar);
         vvar = ref;
       }
-      for (i = 0, _len = objects.length; i < _len; i++) {
+      for (i = _i = 0, _len = objects.length; _i < _len; i = ++_i) {
         obj = objects[i];
         idx = i;
         if (isObject) {
           if (obj instanceof Assign) {
-            _ref4 = obj, idx = _ref4.variable.base, obj = _ref4.value;
+            _ref6 = obj, (_ref7 = _ref6.variable, idx = _ref7.base), obj = _ref6.value;
           } else {
             if (obj.base instanceof Parens) {
-              _ref5 = new Value(obj.unwrapAll()).cacheReference(o), obj = _ref5[0], idx = _ref5[1];
+              _ref8 = new Value(obj.unwrapAll()).cacheReference(o), obj = _ref8[0], idx = _ref8[1];
             } else {
               idx = obj["this"] ? obj.properties[0].name : obj;
             }
           }
         }
         if (!splat && obj instanceof Splat) {
+          name = obj.name.unwrap().value;
+          obj = obj.unwrap();
           val = "" + olen + " <= " + vvar + ".length ? " + (utility('slice')) + ".call(" + vvar + ", " + i;
           if (rest = olen - i - 1) {
             ivar = o.scope.freeVariable('i');
@@ -5876,9 +6064,10 @@ define('ace/mode/coffee/nodes', ['require', 'exports', 'module' , 'ace/mode/coff
           val = new Literal(val);
           splat = "" + ivar + "++";
         } else {
+          name = obj.unwrap().value;
           if (obj instanceof Splat) {
             obj = obj.name.compile(o);
-            throw SyntaxError("multiple splats are disallowed in an assignment: " + obj + " ...");
+            throw new SyntaxError("multiple splats are disallowed in an assignment: " + obj + "...");
           }
           if (typeof idx === 'number') {
             idx = new Literal(splat || idx);
@@ -5888,13 +6077,15 @@ define('ace/mode/coffee/nodes', ['require', 'exports', 'module' , 'ace/mode/coff
           }
           val = new Value(new Literal(vvar), [new (acc ? Access : Index)(idx)]);
         }
+        if ((name != null) && __indexOf.call(RESERVED, name) >= 0) {
+          throw new SyntaxError("assignment to a reserved word: " + (obj.compile(o)) + " = " + (val.compile(o)));
+        }
         assigns.push(new Assign(obj, val, null, {
-          param: this.param
-        }).compile(o, LEVEL_TOP));
-      }
-      if (!top) {
-        assigns.push(vvar);
+          param: this.param,
+          subpattern: true
+        }).compile(o, LEVEL_LIST));
       }
+      if (!(top || this.subpattern)) assigns.push(vvar);
       code = assigns.join(', ');
       if (o.level < LEVEL_LIST) {
         return code;
@@ -5902,14 +6093,17 @@ define('ace/mode/coffee/nodes', ['require', 'exports', 'module' , 'ace/mode/coff
         return "(" + code + ")";
       }
     };
+
     Assign.prototype.compileConditional = function(o) {
-      var left, rite, _ref2;
-      _ref2 = this.variable.cacheReference(o), left = _ref2[0], rite = _ref2[1];
-      if (__indexOf.call(this.context, "?") >= 0) {
-        o.isExistentialEquals = true;
+      var left, right, _ref2;
+      _ref2 = this.variable.cacheReference(o), left = _ref2[0], right = _ref2[1];
+      if (left.base instanceof Literal && left.base.value !== "this" && !o.scope.check(left.base.value)) {
+        throw new Error("the variable \"" + left.base.value + "\" can't be assigned with " + this.context + " because it has not been defined.");
       }
-      return new Op(this.context.slice(0, -1), left, new Assign(rite, this.value, '=')).compile(o);
+      if (__indexOf.call(this.context, "?") >= 0) o.isExistentialEquals = true;
+      return new Op(this.context.slice(0, -1), left, new Assign(right, this.value, '=')).compile(o);
     };
+
     Assign.prototype.compileSplice = function(o) {
       var code, exclusive, from, fromDecl, fromRef, name, to, valDef, valRef, _ref2, _ref3, _ref4;
       _ref2 = this.variable.properties.pop().range, from = _ref2.from, to = _ref2.to, exclusive = _ref2.exclusive;
@@ -5918,14 +6112,10 @@ define('ace/mode/coffee/nodes', ['require', 'exports', 'module' , 'ace/mode/coff
       if (to) {
         if ((from != null ? from.isSimpleNumber() : void 0) && to.isSimpleNumber()) {
           to = +to.compile(o) - +fromRef;
-          if (!exclusive) {
-            to += 1;
-          }
+          if (!exclusive) to += 1;
         } else {
-          to = to.compile(o) + ' - ' + fromRef;
-          if (!exclusive) {
-            to += ' + 1';
-          }
+          to = to.compile(o, LEVEL_ACCESS) + ' - ' + fromRef;
+          if (!exclusive) to += ' + 1';
         }
       } else {
         to = "9e9";
@@ -5938,63 +6128,73 @@ define('ace/mode/coffee/nodes', ['require', 'exports', 'module' , 'ace/mode/coff
         return code;
       }
     };
+
     return Assign;
-  })();
-  exports.Code = Code = (function() {
-    __extends(Code, Base);
-    function Code(params, body, tag) {
-      this.params = params || [];
-      this.body = body || new Block;
+
+  })(Base);
+
+  exports.Code = Code = (function(_super) {
+
+    __extends(Code, _super);
+
+    Code.name = 'Code';
+
+    function Code(params, body, tag) {
+      this.params = params || [];
+      this.body = body || new Block;
       this.bound = tag === 'boundfunc';
-      if (this.bound) {
-        this.context = 'this';
-      }
+      if (this.bound) this.context = '_this';
     }
+
     Code.prototype.children = ['params', 'body'];
+
     Code.prototype.isStatement = function() {
       return !!this.ctor;
     };
+
     Code.prototype.jumps = NO;
+
     Code.prototype.compileNode = function(o) {
-      var code, exprs, i, idt, lit, p, param, ref, splats, v, val, vars, wasEmpty, _i, _j, _k, _len, _len2, _len3, _len4, _ref2, _ref3, _ref4, _ref5;
+      var code, exprs, i, idt, lit, name, p, param, params, ref, splats, uniqs, val, wasEmpty, _i, _j, _k, _l, _len, _len1, _len2, _len3, _len4, _len5, _m, _n, _ref2, _ref3, _ref4, _ref5, _ref6, _ref7, _ref8;
       o.scope = new Scope(o.scope, this.body, this);
       o.scope.shared = del(o, 'sharedScope');
       o.indent += TAB;
       delete o.bare;
-      vars = [];
+      delete o.isExistentialEquals;
+      params = [];
       exprs = [];
-      _ref2 = this.params;
+      _ref2 = this.paramNames();
       for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
-        param = _ref2[_i];
-        if (param.splat) {
-          _ref3 = this.params;
-          for (_j = 0, _len2 = _ref3.length; _j < _len2; _j++) {
-            p = _ref3[_j];
-            if (p.name.value) {
-              o.scope.add(p.name.value, 'var', true);
-            }
+        name = _ref2[_i];
+        if (!o.scope.check(name)) o.scope.parameter(name);
+      }
+      _ref3 = this.params;
+      for (_j = 0, _len1 = _ref3.length; _j < _len1; _j++) {
+        param = _ref3[_j];
+        if (!param.splat) continue;
+        _ref4 = this.params;
+        for (_k = 0, _len2 = _ref4.length; _k < _len2; _k++) {
+          p = _ref4[_k];
+          if (p.name.value) o.scope.add(p.name.value, 'var', true);
+        }
+        splats = new Assign(new Value(new Arr((function() {
+          var _l, _len3, _ref5, _results;
+          _ref5 = this.params;
+          _results = [];
+          for (_l = 0, _len3 = _ref5.length; _l < _len3; _l++) {
+            p = _ref5[_l];
+            _results.push(p.asReference(o));
           }
-          splats = new Assign(new Value(new Arr((function() {
-            var _k, _len3, _ref4, _results;
-            _ref4 = this.params;
-            _results = [];
-            for (_k = 0, _len3 = _ref4.length; _k < _len3; _k++) {
-              p = _ref4[_k];
-              _results.push(p.asReference(o));
-            }
-            return _results;
-          }).call(this))), new Value(new Literal('arguments')));
-          break;
-        }
+          return _results;
+        }).call(this))), new Value(new Literal('arguments')));
+        break;
       }
-      _ref4 = this.params;
-      for (_k = 0, _len3 = _ref4.length; _k < _len3; _k++) {
-        param = _ref4[_k];
+      _ref5 = this.params;
+      for (_l = 0, _len3 = _ref5.length; _l < _len3; _l++) {
+        param = _ref5[_l];
         if (param.isComplex()) {
           val = ref = param.asReference(o);
-          if (param.value) {
-            val = new Op('?', ref, param.value);
-          }
+          if (param.value) val = new Op('?', ref, param.value);
           exprs.push(new Assign(new Value(param.name), val, '=', {
             param: true
           }));
@@ -6006,101 +6206,167 @@ define('ace/mode/coffee/nodes', ['require', 'exports', 'module' , 'ace/mode/coff
             exprs.push(new If(lit, val));
           }
         }
-        if (!splats) {
-          vars.push(ref);
-        }
+        if (!splats) params.push(ref);
       }
       wasEmpty = this.body.isEmpty();
-      if (splats) {
-        exprs.unshift(splats);
-      }
+      if (splats) exprs.unshift(splats);
       if (exprs.length) {
-        (_ref5 = this.body.expressions).unshift.apply(_ref5, exprs);
+        (_ref6 = this.body.expressions).unshift.apply(_ref6, exprs);
       }
-      if (!splats) {
-        for (i = 0, _len4 = vars.length; i < _len4; i++) {
-          v = vars[i];
-          o.scope.parameter(vars[i] = v.compile(o));
+      for (i = _m = 0, _len4 = params.length; _m < _len4; i = ++_m) {
+        p = params[i];
+        o.scope.parameter(params[i] = p.compile(o));
+      }
+      uniqs = [];
+      _ref7 = this.paramNames();
+      for (_n = 0, _len5 = _ref7.length; _n < _len5; _n++) {
+        name = _ref7[_n];
+        if (__indexOf.call(uniqs, name) >= 0) {
+          throw SyntaxError("multiple parameters named '" + name + "'");
         }
+        uniqs.push(name);
       }
-      if (!(wasEmpty || this.noReturn)) {
-        this.body.makeReturn();
+      if (!(wasEmpty || this.noReturn)) this.body.makeReturn();
+      if (this.bound) {
+        if ((_ref8 = o.scope.parent.method) != null ? _ref8.bound : void 0) {
+          this.bound = this.context = o.scope.parent.method.context;
+        } else if (!this["static"]) {
+          o.scope.parent.assign('_this', 'this');
+        }
       }
       idt = o.indent;
       code = 'function';
-      if (this.ctor) {
-        code += ' ' + this.name;
-      }
-      code += '(' + vars.join(', ') + ') {';
+      if (this.ctor) code += ' ' + this.name;
+      code += '(' + params.join(', ') + ') {';
       if (!this.body.isEmpty()) {
         code += "\n" + (this.body.compileWithDeclarations(o)) + "\n" + this.tab;
       }
       code += '}';
-      if (this.ctor) {
-        return this.tab + code;
-      }
-      if (this.bound) {
-        return utility('bind') + ("(" + code + ", " + this.context + ")");
-      }
+      if (this.ctor) return this.tab + code;
       if (this.front || (o.level >= LEVEL_ACCESS)) {
         return "(" + code + ")";
       } else {
         return code;
       }
     };
+
+    Code.prototype.paramNames = function() {
+      var names, param, _i, _len, _ref2;
+      names = [];
+      _ref2 = this.params;
+      for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
+        param = _ref2[_i];
+        names.push.apply(names, param.names());
+      }
+      return names;
+    };
+
     Code.prototype.traverseChildren = function(crossScope, func) {
       if (crossScope) {
         return Code.__super__.traverseChildren.call(this, crossScope, func);
       }
     };
+
     return Code;
-  })();
-  exports.Param = Param = (function() {
-    __extends(Param, Base);
+
+  })(Base);
+
+  exports.Param = Param = (function(_super) {
+
+    __extends(Param, _super);
+
+    Param.name = 'Param';
+
     function Param(name, value, splat) {
+      var _ref2;
       this.name = name;
       this.value = value;
       this.splat = splat;
+      if (_ref2 = (name = this.name.unwrapAll().value), __indexOf.call(STRICT_PROSCRIBED, _ref2) >= 0) {
+        throw SyntaxError("parameter name \"" + name + "\" is not allowed");
+      }
     }
+
     Param.prototype.children = ['name', 'value'];
+
     Param.prototype.compile = function(o) {
       return this.name.compile(o, LEVEL_LIST);
     };
+
     Param.prototype.asReference = function(o) {
       var node;
-      if (this.reference) {
-        return this.reference;
-      }
+      if (this.reference) return this.reference;
       node = this.name;
       if (node["this"]) {
         node = node.properties[0].name;
         if (node.value.reserved) {
-          node = new Literal('_' + node.value);
+          node = new Literal(o.scope.freeVariable(node.value));
         }
       } else if (node.isComplex()) {
         node = new Literal(o.scope.freeVariable('arg'));
       }
       node = new Value(node);
-      if (this.splat) {
-        node = new Splat(node);
-      }
+      if (this.splat) node = new Splat(node);
       return this.reference = node;
     };
+
     Param.prototype.isComplex = function() {
       return this.name.isComplex();
     };
+
+    Param.prototype.names = function(name) {
+      var atParam, names, obj, _i, _len, _ref2;
+      if (name == null) name = this.name;
+      atParam = function(obj) {
+        var value;
+        value = obj.properties[0].name.value;
+        if (value.reserved) {
+          return [];
+        } else {
+          return [value];
+        }
+      };
+      if (name instanceof Literal) return [name.value];
+      if (name instanceof Value) return atParam(name);
+      names = [];
+      _ref2 = name.objects;
+      for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
+        obj = _ref2[_i];
+        if (obj instanceof Assign) {
+          names.push(obj.variable.base.value);
+        } else if (obj.isArray() || obj.isObject()) {
+          names.push.apply(names, this.names(obj.base));
+        } else if (obj["this"]) {
+          names.push.apply(names, atParam(obj));
+        } else {
+          names.push(obj.base.value);
+        }
+      }
+      return names;
+    };
+
     return Param;
-  })();
-  exports.Splat = Splat = (function() {
-    __extends(Splat, Base);
+
+  })(Base);
+
+  exports.Splat = Splat = (function(_super) {
+
+    __extends(Splat, _super);
+
+    Splat.name = 'Splat';
+
     Splat.prototype.children = ['name'];
+
     Splat.prototype.isAssignable = YES;
+
     function Splat(name) {
       this.name = name.compile ? name : new Literal(name);
     }
+
     Splat.prototype.assigns = function(name) {
       return this.name.assigns(name);
     };
+
     Splat.prototype.compile = function(o) {
       if (this.index != null) {
         return this.compileParam(o);
@@ -6108,24 +6374,25 @@ define('ace/mode/coffee/nodes', ['require', 'exports', 'module' , 'ace/mode/coff
         return this.name.compile(o);
       }
     };
+
+    Splat.prototype.unwrap = function() {
+      return this.name;
+    };
+
     Splat.compileSplattedArray = function(o, list, apply) {
-      var args, base, code, i, index, node, _len;
+      var args, base, code, i, index, node, _i, _len;
       index = -1;
       while ((node = list[++index]) && !(node instanceof Splat)) {
         continue;
       }
-      if (index >= list.length) {
-        return '';
-      }
+      if (index >= list.length) return '';
       if (list.length === 1) {
         code = list[0].compile(o, LEVEL_LIST);
-        if (apply) {
-          return code;
-        }
+        if (apply) return code;
         return "" + (utility('slice')) + ".call(" + code + ")";
       }
       args = list.slice(index);
-      for (i = 0, _len = args.length; i < _len; i++) {
+      for (i = _i = 0, _len = args.length; _i < _len; i = ++_i) {
         node = args[i];
         code = node.compile(o, LEVEL_LIST);
         args[i] = node instanceof Splat ? "" + (utility('slice')) + ".call(" + code + ")" : "[" + code + "]";
@@ -6134,51 +6401,66 @@ define('ace/mode/coffee/nodes', ['require', 'exports', 'module' , 'ace/mode/coff
         return args[0] + (".concat(" + (args.slice(1).join(', ')) + ")");
       }
       base = (function() {
-        var _i, _len2, _ref2, _results;
+        var _j, _len1, _ref2, _results;
         _ref2 = list.slice(0, index);
         _results = [];
-        for (_i = 0, _len2 = _ref2.length; _i < _len2; _i++) {
-          node = _ref2[_i];
+        for (_j = 0, _len1 = _ref2.length; _j < _len1; _j++) {
+          node = _ref2[_j];
           _results.push(node.compile(o, LEVEL_LIST));
         }
         return _results;
       })();
       return "[" + (base.join(', ')) + "].concat(" + (args.join(', ')) + ")";
     };
+
     return Splat;
-  })();
-  exports.While = While = (function() {
-    __extends(While, Base);
+
+  })(Base);
+
+  exports.While = While = (function(_super) {
+
+    __extends(While, _super);
+
+    While.name = 'While';
+
     function While(condition, options) {
       this.condition = (options != null ? options.invert : void 0) ? condition.invert() : condition;
       this.guard = options != null ? options.guard : void 0;
     }
+
     While.prototype.children = ['condition', 'guard', 'body'];
+
     While.prototype.isStatement = YES;
-    While.prototype.makeReturn = function() {
-      this.returns = true;
-      return this;
+
+    While.prototype.makeReturn = function(res) {
+      if (res) {
+        return While.__super__.makeReturn.apply(this, arguments);
+      } else {
+        this.returns = !this.jumps({
+          loop: true
+        });
+        return this;
+      }
     };
+
     While.prototype.addBody = function(body) {
       this.body = body;
       return this;
     };
+
     While.prototype.jumps = function() {
       var expressions, node, _i, _len;
       expressions = this.body.expressions;
-      if (!expressions.length) {
-        return false;
-      }
+      if (!expressions.length) return false;
       for (_i = 0, _len = expressions.length; _i < _len; _i++) {
         node = expressions[_i];
         if (node.jumps({
           loop: true
-        })) {
-          return node;
-        }
+        })) return node;
       }
       return false;
     };
+
     While.prototype.compileNode = function(o) {
       var body, code, rvar, set;
       o.indent += TAB;
@@ -6187,41 +6469,40 @@ define('ace/mode/coffee/nodes', ['require', 'exports', 'module' , 'ace/mode/coff
       if (body.isEmpty()) {
         body = '';
       } else {
-        if (o.level > LEVEL_TOP || this.returns) {
-          rvar = o.scope.freeVariable('results');
+        if (this.returns) {
+          body.makeReturn(rvar = o.scope.freeVariable('results'));
           set = "" + this.tab + rvar + " = [];\n";
-          if (body) {
-            body = Push.wrap(rvar, body);
-          }
         }
         if (this.guard) {
-          body = Block.wrap([new If(this.guard, body)]);
+          if (body.expressions.length > 1) {
+            body.expressions.unshift(new If((new Parens(this.guard)).invert(), new Literal("continue")));
+          } else {
+            if (this.guard) body = Block.wrap([new If(this.guard, body)]);
+          }
         }
         body = "\n" + (body.compile(o, LEVEL_TOP)) + "\n" + this.tab;
       }
       code = set + this.tab + ("while (" + (this.condition.compile(o, LEVEL_PAREN)) + ") {" + body + "}");
-      if (this.returns) {
-        code += "\n" + this.tab + "return " + rvar + ";";
-      }
+      if (this.returns) code += "\n" + this.tab + "return " + rvar + ";";
       return code;
     };
+
     return While;
-  })();
-  exports.Op = Op = (function() {
+
+  })(Base);
+
+  exports.Op = Op = (function(_super) {
     var CONVERSIONS, INVERSIONS;
-    __extends(Op, Base);
+
+    __extends(Op, _super);
+
+    Op.name = 'Op';
+
     function Op(op, first, second, flip) {
-      var call;
-      if (op === 'in') {
-        return new In(first, second);
-      }
-      if (op === 'do') {
-        call = new Call(first, first.params || []);
-        call["do"] = true;
-        return call;
-      }
+      if (op === 'in') return new In(first, second);
+      if (op === 'do') return this.generateDo(first);
       if (op === 'new') {
-        if (first instanceof Call && !first["do"]) {
+        if (first instanceof Call && !first["do"] && !first.isNew) {
           return first.newInstance();
         }
         if (first instanceof Code && first.bound || first["do"]) {
@@ -6234,28 +6515,36 @@ define('ace/mode/coffee/nodes', ['require', 'exports', 'module' , 'ace/mode/coff
       this.flip = !!flip;
       return this;
     }
+
     CONVERSIONS = {
       '==': '===',
       '!=': '!==',
       'of': 'in'
     };
+
     INVERSIONS = {
       '!==': '===',
       '===': '!=='
     };
+
     Op.prototype.children = ['first', 'second'];
+
     Op.prototype.isSimpleNumber = NO;
+
     Op.prototype.isUnary = function() {
       return !this.second;
     };
+
     Op.prototype.isComplex = function() {
       var _ref2;
       return !(this.isUnary() && ((_ref2 = this.operator) === '+' || _ref2 === '-')) || this.first.isComplex();
     };
+
     Op.prototype.isChainable = function() {
       var _ref2;
       return (_ref2 = this.operator) === '<' || _ref2 === '>' || _ref2 === '>=' || _ref2 === '<=' || _ref2 === '===' || _ref2 === '!==';
     };
+
     Op.prototype.invert = function() {
       var allInvertable, curr, fst, op, _ref2;
       if (this.isChainable() && this.first.isChainable()) {
@@ -6265,9 +6554,7 @@ define('ace/mode/coffee/nodes', ['require', 'exports', 'module' , 'ace/mode/coff
           allInvertable && (allInvertable = curr.operator in INVERSIONS);
           curr = curr.first;
         }
-        if (!allInvertable) {
-          return new Parens(this).invert();
-        }
+        if (!allInvertable) return new Parens(this).invert();
         curr = this;
         while (curr && curr.operator) {
           curr.invert = !curr.invert;
@@ -6277,9 +6564,7 @@ define('ace/mode/coffee/nodes', ['require', 'exports', 'module' , 'ace/mode/coff
         return this;
       } else if (op = INVERSIONS[this.operator]) {
         this.operator = op;
-        if (this.first.unwrap() instanceof Op) {
-          this.first.invert();
-        }
+        if (this.first.unwrap() instanceof Op) this.first.invert();
         return this;
       } else if (this.second) {
         return new Parens(this).invert();
@@ -6289,22 +6574,44 @@ define('ace/mode/coffee/nodes', ['require', 'exports', 'module' , 'ace/mode/coff
         return new Op('!', this);
       }
     };
+
     Op.prototype.unfoldSoak = function(o) {
       var _ref2;
       return ((_ref2 = this.operator) === '++' || _ref2 === '--' || _ref2 === 'delete') && unfoldSoak(o, this, 'first');
     };
-    Op.prototype.compileNode = function(o) {
-      var code;
-      if (this.isUnary()) {
-        return this.compileUnary(o);
-      }
-      if (this.isChainable() && this.first.isChainable()) {
-        return this.compileChain(o);
-      }
-      if (this.operator === '?') {
-        return this.compileExistence(o);
+
+    Op.prototype.generateDo = function(exp) {
+      var call, func, param, passedParams, ref, _i, _len, _ref2;
+      passedParams = [];
+      func = exp instanceof Assign && (ref = exp.value.unwrap()) instanceof Code ? ref : exp;
+      _ref2 = func.params || [];
+      for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
+        param = _ref2[_i];
+        if (param.value) {
+          passedParams.push(param.value);
+          delete param.value;
+        } else {
+          passedParams.push(param);
+        }
       }
-      this.first.front = this.front;
+      call = new Call(exp, passedParams);
+      call["do"] = true;
+      return call;
+    };
+
+    Op.prototype.compileNode = function(o) {
+      var code, isChain, _ref2, _ref3;
+      isChain = this.isChainable() && this.first.isChainable();
+      if (!isChain) this.first.front = this.front;
+      if (this.operator === 'delete' && o.scope.check(this.first.unwrapAll().value)) {
+        throw SyntaxError('delete operand may not be argument or var');
+      }
+      if (((_ref2 = this.operator) === '--' || _ref2 === '++') && (_ref3 = this.first.unwrapAll().value, __indexOf.call(STRICT_PROSCRIBED, _ref3) >= 0)) {
+        throw SyntaxError('prefix increment/decrement may not have eval or arguments operand');
+      }
+      if (this.isUnary()) return this.compileUnary(o);
+      if (isChain) return this.compileChain(o);
+      if (this.operator === '?') return this.compileExistence(o);
       code = this.first.compile(o, LEVEL_OP) + ' ' + this.operator + ' ' + this.second.compile(o, LEVEL_OP);
       if (o.level <= LEVEL_OP) {
         return code;
@@ -6312,6 +6619,7 @@ define('ace/mode/coffee/nodes', ['require', 'exports', 'module' , 'ace/mode/coff
         return "(" + code + ")";
       }
     };
+
     Op.prototype.compileChain = function(o) {
       var code, fst, shared, _ref2;
       _ref2 = this.first.second.cache(o), this.first.second = _ref2[0], shared = _ref2[1];
@@ -6319,9 +6627,10 @@ define('ace/mode/coffee/nodes', ['require', 'exports', 'module' , 'ace/mode/coff
       code = "" + fst + " " + (this.invert ? '&&' : '||') + " " + (shared.compile(o)) + " " + this.operator + " " + (this.second.compile(o, LEVEL_OP));
       return "(" + code + ")";
     };
+
     Op.prototype.compileExistence = function(o) {
       var fst, ref;
-      if (this.first.isComplex()) {
+      if (this.first.isComplex() && o.level > LEVEL_TOP) {
         ref = new Literal(o.scope.freeVariable('ref'));
         fst = new Parens(new Assign(ref, this.first));
       } else {
@@ -6332,68 +6641,76 @@ define('ace/mode/coffee/nodes', ['require', 'exports', 'module' , 'ace/mode/coff
         type: 'if'
       }).addElse(this.second).compile(o);
     };
+
     Op.prototype.compileUnary = function(o) {
-      var op, parts;
+      var op, parts, plusMinus;
+      if (o.level >= LEVEL_ACCESS) return (new Parens(this)).compile(o);
       parts = [op = this.operator];
-      if ((op === 'new' || op === 'typeof' || op === 'delete') || (op === '+' || op === '-') && this.first instanceof Op && this.first.operator === op) {
+      plusMinus = op === '+' || op === '-';
+      if ((op === 'new' || op === 'typeof' || op === 'delete') || plusMinus && this.first instanceof Op && this.first.operator === op) {
         parts.push(' ');
       }
-      if (op === 'new' && this.first.isStatement(o)) {
+      if ((plusMinus && this.first instanceof Op) || (op === 'new' && this.first.isStatement(o))) {
         this.first = new Parens(this.first);
       }
       parts.push(this.first.compile(o, LEVEL_OP));
-      if (this.flip) {
-        parts.reverse();
-      }
+      if (this.flip) parts.reverse();
       return parts.join('');
     };
+
     Op.prototype.toString = function(idt) {
       return Op.__super__.toString.call(this, idt, this.constructor.name + ' ' + this.operator);
     };
+
     return Op;
-  })();
-  exports.In = In = (function() {
-    __extends(In, Base);
+
+  })(Base);
+
+  exports.In = In = (function(_super) {
+
+    __extends(In, _super);
+
+    In.name = 'In';
+
     function In(object, array) {
       this.object = object;
       this.array = array;
     }
+
     In.prototype.children = ['object', 'array'];
+
     In.prototype.invert = NEGATE;
+
     In.prototype.compileNode = function(o) {
       var hasSplat, obj, _i, _len, _ref2;
       if (this.array instanceof Value && this.array.isArray()) {
         _ref2 = this.array.base.objects;
         for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
           obj = _ref2[_i];
-          if (obj instanceof Splat) {
-            hasSplat = true;
-            break;
-          }
-        }
-        if (!hasSplat) {
-          return this.compileOrTest(o);
+          if (!(obj instanceof Splat)) continue;
+          hasSplat = true;
+          break;
         }
+        if (!hasSplat) return this.compileOrTest(o);
       }
       return this.compileLoopTest(o);
     };
+
     In.prototype.compileOrTest = function(o) {
       var cmp, cnj, i, item, ref, sub, tests, _ref2, _ref3;
+      if (this.array.base.objects.length === 0) return "" + (!!this.negated);
       _ref2 = this.object.cache(o, LEVEL_OP), sub = _ref2[0], ref = _ref2[1];
       _ref3 = this.negated ? [' !== ', ' && '] : [' === ', ' || '], cmp = _ref3[0], cnj = _ref3[1];
       tests = (function() {
-        var _len, _ref4, _results;
+        var _i, _len, _ref4, _results;
         _ref4 = this.array.base.objects;
         _results = [];
-        for (i = 0, _len = _ref4.length; i < _len; i++) {
+        for (i = _i = 0, _len = _ref4.length; _i < _len; i = ++_i) {
           item = _ref4[i];
-          _results.push((i ? ref : sub) + cmp + item.compile(o, LEVEL_OP));
+          _results.push((i ? ref : sub) + cmp + item.compile(o, LEVEL_ACCESS));
         }
         return _results;
       }).call(this);
-      if (tests.length === 0) {
-        return 'false';
-      }
       tests = tests.join(cnj);
       if (o.level < LEVEL_OP) {
         return tests;
@@ -6401,13 +6718,12 @@ define('ace/mode/coffee/nodes', ['require', 'exports', 'module' , 'ace/mode/coff
         return "(" + tests + ")";
       }
     };
+
     In.prototype.compileLoopTest = function(o) {
       var code, ref, sub, _ref2;
       _ref2 = this.object.cache(o, LEVEL_LIST), sub = _ref2[0], ref = _ref2[1];
       code = utility('indexOf') + (".call(" + (this.array.compile(o, LEVEL_LIST)) + ", " + ref + ") ") + (this.negated ? '< 0' : '>= 0');
-      if (sub === ref) {
-        return code;
-      }
+      if (sub === ref) return code;
       code = sub + ', ' + code;
       if (o.level < LEVEL_LIST) {
         return code;
@@ -6415,91 +6731,151 @@ define('ace/mode/coffee/nodes', ['require', 'exports', 'module' , 'ace/mode/coff
         return "(" + code + ")";
       }
     };
+
     In.prototype.toString = function(idt) {
       return In.__super__.toString.call(this, idt, this.constructor.name + (this.negated ? '!' : ''));
     };
+
     return In;
-  })();
-  exports.Try = Try = (function() {
-    __extends(Try, Base);
+
+  })(Base);
+
+  exports.Try = Try = (function(_super) {
+
+    __extends(Try, _super);
+
+    Try.name = 'Try';
+
     function Try(attempt, error, recovery, ensure) {
       this.attempt = attempt;
       this.error = error;
       this.recovery = recovery;
       this.ensure = ensure;
     }
+
     Try.prototype.children = ['attempt', 'recovery', 'ensure'];
+
     Try.prototype.isStatement = YES;
+
     Try.prototype.jumps = function(o) {
       var _ref2;
       return this.attempt.jumps(o) || ((_ref2 = this.recovery) != null ? _ref2.jumps(o) : void 0);
     };
-    Try.prototype.makeReturn = function() {
-      if (this.attempt) {
-        this.attempt = this.attempt.makeReturn();
-      }
-      if (this.recovery) {
-        this.recovery = this.recovery.makeReturn();
-      }
+
+    Try.prototype.makeReturn = function(res) {
+      if (this.attempt) this.attempt = this.attempt.makeReturn(res);
+      if (this.recovery) this.recovery = this.recovery.makeReturn(res);
       return this;
     };
+
     Try.prototype.compileNode = function(o) {
-      var catchPart, errorPart;
+      var catchPart, ensurePart, errorPart, tryPart;
       o.indent += TAB;
       errorPart = this.error ? " (" + (this.error.compile(o)) + ") " : ' ';
-      catchPart = this.recovery ? " catch" + errorPart + "{\n" + (this.recovery.compile(o, LEVEL_TOP)) + "\n" + this.tab + "}" : !(this.ensure || this.recovery) ? ' catch (_e) {}' : void 0;
-      return ("" + this.tab + "try {\n" + (this.attempt.compile(o, LEVEL_TOP)) + "\n" + this.tab + "}" + (catchPart || '')) + (this.ensure ? " finally {\n" + (this.ensure.compile(o, LEVEL_TOP)) + "\n" + this.tab + "}" : '');
+      tryPart = this.attempt.compile(o, LEVEL_TOP);
+      catchPart = (function() {
+        var _ref2;
+        if (this.recovery) {
+          if (_ref2 = this.error.value, __indexOf.call(STRICT_PROSCRIBED, _ref2) >= 0) {
+            throw SyntaxError("catch variable may not be \"" + this.error.value + "\"");
+          }
+          if (!o.scope.check(this.error.value)) {
+            o.scope.add(this.error.value, 'param');
+          }
+          return " catch" + errorPart + "{\n" + (this.recovery.compile(o, LEVEL_TOP)) + "\n" + this.tab + "}";
+        } else if (!(this.ensure || this.recovery)) {
+          return ' catch (_error) {}';
+        }
+      }).call(this);
+      ensurePart = this.ensure ? " finally {\n" + (this.ensure.compile(o, LEVEL_TOP)) + "\n" + this.tab + "}" : '';
+      return "" + this.tab + "try {\n" + tryPart + "\n" + this.tab + "}" + (catchPart || '') + ensurePart;
     };
+
     return Try;
-  })();
-  exports.Throw = Throw = (function() {
-    __extends(Throw, Base);
+
+  })(Base);
+
+  exports.Throw = Throw = (function(_super) {
+
+    __extends(Throw, _super);
+
+    Throw.name = 'Throw';
+
     function Throw(expression) {
       this.expression = expression;
     }
+
     Throw.prototype.children = ['expression'];
+
     Throw.prototype.isStatement = YES;
+
     Throw.prototype.jumps = NO;
+
     Throw.prototype.makeReturn = THIS;
+
     Throw.prototype.compileNode = function(o) {
       return this.tab + ("throw " + (this.expression.compile(o)) + ";");
     };
+
     return Throw;
-  })();
-  exports.Existence = Existence = (function() {
-    __extends(Existence, Base);
+
+  })(Base);
+
+  exports.Existence = Existence = (function(_super) {
+
+    __extends(Existence, _super);
+
+    Existence.name = 'Existence';
+
     function Existence(expression) {
       this.expression = expression;
     }
+
     Existence.prototype.children = ['expression'];
+
     Existence.prototype.invert = NEGATE;
+
     Existence.prototype.compileNode = function(o) {
       var cmp, cnj, code, _ref2;
+      this.expression.front = this.front;
       code = this.expression.compile(o, LEVEL_OP);
-      code = IDENTIFIER.test(code) && !o.scope.check(code) ? ((_ref2 = this.negated ? ['===', '||'] : ['!==', '&&'], cmp = _ref2[0], cnj = _ref2[1], _ref2), "typeof " + code + " " + cmp + " \"undefined\" " + cnj + " " + code + " " + cmp + " null") : "" + code + " " + (this.negated ? '==' : '!=') + " null";
+      if (IDENTIFIER.test(code) && !o.scope.check(code)) {
+        _ref2 = this.negated ? ['===', '||'] : ['!==', '&&'], cmp = _ref2[0], cnj = _ref2[1];
+        code = "typeof " + code + " " + cmp + " \"undefined\" " + cnj + " " + code + " " + cmp + " null";
+      } else {
+        code = "" + code + " " + (this.negated ? '==' : '!=') + " null";
+      }
       if (o.level <= LEVEL_COND) {
         return code;
       } else {
         return "(" + code + ")";
       }
     };
+
     return Existence;
-  })();
-  exports.Parens = Parens = (function() {
-    __extends(Parens, Base);
+
+  })(Base);
+
+  exports.Parens = Parens = (function(_super) {
+
+    __extends(Parens, _super);
+
+    Parens.name = 'Parens';
+
     function Parens(body) {
       this.body = body;
     }
+
     Parens.prototype.children = ['body'];
+
     Parens.prototype.unwrap = function() {
       return this.body;
     };
+
     Parens.prototype.isComplex = function() {
       return this.body.isComplex();
     };
-    Parens.prototype.makeReturn = function() {
-      return this.body.makeReturn();
-    };
+
     Parens.prototype.compileNode = function(o) {
       var bare, code, expr;
       expr = this.body.unwrap();
@@ -6515,10 +6891,17 @@ define('ace/mode/coffee/nodes', ['require', 'exports', 'module' , 'ace/mode/coff
         return "(" + code + ")";
       }
     };
+
     return Parens;
-  })();
-  exports.For = For = (function() {
-    __extends(For, Base);
+
+  })(Base);
+
+  exports.For = For = (function(_super) {
+
+    __extends(For, _super);
+
+    For.name = 'For';
+
     function For(body, source) {
       var _ref2;
       this.source = source.source, this.guard = source.guard, this.step = source.step, this.name = source.name, this.index = source.index;
@@ -6541,20 +6924,14 @@ define('ace/mode/coffee/nodes', ['require', 'exports', 'module' , 'ace/mode/coff
       }
       this.returns = false;
     }
+
     For.prototype.children = ['body', 'source', 'guard', 'step'];
-    For.prototype.isStatement = YES;
-    For.prototype.jumps = While.prototype.jumps;
-    For.prototype.makeReturn = function() {
-      this.returns = true;
-      return this;
-    };
+
     For.prototype.compileNode = function(o) {
-      var body, defPart, forPart, forVarPart, guardPart, idt1, index, ivar, lastJumps, lvar, name, namePart, ref, resultPart, returnResult, rvar, scope, source, stepPart, stepvar, svar, varPart, _ref2;
+      var body, defPart, forPart, forVarPart, guardPart, idt1, index, ivar, kvar, kvarAssign, lastJumps, lvar, name, namePart, ref, resultPart, returnResult, rvar, scope, source, stepPart, stepvar, svar, varPart, _ref2;
       body = Block.wrap([this.body]);
       lastJumps = (_ref2 = last(body.expressions)) != null ? _ref2.jumps() : void 0;
-      if (lastJumps && lastJumps instanceof Return) {
-        this.returns = false;
-      }
+      if (lastJumps && lastJumps instanceof Return) this.returns = false;
       source = this.range ? this.source.base : this.source;
       scope = o.scope;
       name = this.name && this.name.compile(o, LEVEL_LIST);
@@ -6569,16 +6946,12 @@ define('ace/mode/coffee/nodes', ['require', 'exports', 'module' , 'ace/mode/coff
           immediate: true
         });
       }
-      if (this.returns) {
-        rvar = scope.freeVariable('results');
-      }
-      ivar = (this.range ? name : index) || scope.freeVariable('i');
-      if (this.step && !this.range) {
-        stepvar = scope.freeVariable("step");
-      }
-      if (this.pattern) {
-        name = ivar;
-      }
+      if (this.returns) rvar = scope.freeVariable('results');
+      ivar = (this.object && index) || scope.freeVariable('i');
+      kvar = (this.range && name) || index || ivar;
+      kvarAssign = kvar !== ivar ? "" + kvar + " = " : "";
+      if (this.step && !this.range) stepvar = scope.freeVariable("step");
+      if (this.pattern) name = ivar;
       varPart = '';
       guardPart = '';
       defPart = '';
@@ -6586,6 +6959,7 @@ define('ace/mode/coffee/nodes', ['require', 'exports', 'module' , 'ace/mode/coff
       if (this.range) {
         forPart = source.compile(merge(o, {
           index: ivar,
+          name: name,
           step: this.step
         }));
       } else {
@@ -6595,54 +6969,56 @@ define('ace/mode/coffee/nodes', ['require', 'exports', 'module' , 'ace/mode/coff
           svar = ref;
         }
         if (name && !this.pattern) {
-          namePart = "" + name + " = " + svar + "[" + ivar + "]";
+          namePart = "" + name + " = " + svar + "[" + kvar + "]";
         }
         if (!this.object) {
           lvar = scope.freeVariable('len');
-          forVarPart = ("" + ivar + " = 0, " + lvar + " = " + svar + ".length") + (this.step ? ", " + stepvar + " = " + (this.step.compile(o, LEVEL_OP)) : '');
-          stepPart = this.step ? "" + ivar + " += " + stepvar : "" + ivar + "++";
+          forVarPart = "" + kvarAssign + ivar + " = 0, " + lvar + " = " + svar + ".length";
+          if (this.step) {
+            forVarPart += ", " + stepvar + " = " + (this.step.compile(o, LEVEL_OP));
+          }
+          stepPart = "" + kvarAssign + (this.step ? "" + ivar + " += " + stepvar : (kvar !== ivar ? "++" + ivar : "" + ivar + "++"));
           forPart = "" + forVarPart + "; " + ivar + " < " + lvar + "; " + stepPart;
         }
       }
       if (this.returns) {
         resultPart = "" + this.tab + rvar + " = [];\n";
         returnResult = "\n" + this.tab + "return " + rvar + ";";
-        body = Push.wrap(rvar, body);
+        body.makeReturn(rvar);
       }
       if (this.guard) {
-        body = Block.wrap([new If(this.guard, body)]);
+        if (body.expressions.length > 1) {
+          body.expressions.unshift(new If((new Parens(this.guard)).invert(), new Literal("continue")));
+        } else {
+          if (this.guard) body = Block.wrap([new If(this.guard, body)]);
+        }
       }
       if (this.pattern) {
-        body.expressions.unshift(new Assign(this.name, new Literal("" + svar + "[" + ivar + "]")));
+        body.expressions.unshift(new Assign(this.name, new Literal("" + svar + "[" + kvar + "]")));
       }
       defPart += this.pluckDirectCall(o, body);
-      if (namePart) {
-        varPart = "\n" + idt1 + namePart + ";";
-      }
+      if (namePart) varPart = "\n" + idt1 + namePart + ";";
       if (this.object) {
-        forPart = "" + ivar + " in " + svar;
+        forPart = "" + kvar + " in " + svar;
         if (this.own) {
-          guardPart = "\n" + idt1 + "if (!" + (utility('hasProp')) + ".call(" + svar + ", " + ivar + ")) continue;";
+          guardPart = "\n" + idt1 + "if (!" + (utility('hasProp')) + ".call(" + svar + ", " + kvar + ")) continue;";
         }
       }
       body = body.compile(merge(o, {
         indent: idt1
       }), LEVEL_TOP);
-      if (body) {
-        body = '\n' + body + '\n';
-      }
+      if (body) body = '\n' + body + '\n';
       return "" + defPart + (resultPart || '') + this.tab + "for (" + forPart + ") {" + guardPart + varPart + body + this.tab + "}" + (returnResult || '');
     };
+
     For.prototype.pluckDirectCall = function(o, body) {
-      var base, defs, expr, fn, idx, ref, val, _len, _ref2, _ref3, _ref4, _ref5, _ref6, _ref7;
+      var base, defs, expr, fn, idx, ref, val, _i, _len, _ref2, _ref3, _ref4, _ref5, _ref6, _ref7;
       defs = '';
       _ref2 = body.expressions;
-      for (idx = 0, _len = _ref2.length; idx < _len; idx++) {
+      for (idx = _i = 0, _len = _ref2.length; _i < _len; idx = ++_i) {
         expr = _ref2[idx];
         expr = expr.unwrapAll();
-        if (!(expr instanceof Call)) {
-          continue;
-        }
+        if (!(expr instanceof Call)) continue;
         val = expr.variable.unwrapAll();
         if (!((val instanceof Code) || (val instanceof Value && ((_ref3 = val.base) != null ? _ref3.unwrapAll() : void 0) instanceof Code && val.properties.length === 1 && ((_ref4 = (_ref5 = val.properties[0].name) != null ? _ref5.value : void 0) === 'call' || _ref4 === 'apply')))) {
           continue;
@@ -6650,26 +7026,33 @@ define('ace/mode/coffee/nodes', ['require', 'exports', 'module' , 'ace/mode/coff
         fn = ((_ref6 = val.base) != null ? _ref6.unwrapAll() : void 0) || val;
         ref = new Literal(o.scope.freeVariable('fn'));
         base = new Value(ref);
-        if (val.base) {
-          _ref7 = [base, val], val.base = _ref7[0], base = _ref7[1];
-          args.unshift(new Literal('this'));
-        }
+        if (val.base) _ref7 = [base, val], val.base = _ref7[0], base = _ref7[1];
         body.expressions[idx] = new Call(base, expr.args);
         defs += this.tab + new Assign(ref, fn).compile(o, LEVEL_TOP) + ';\n';
       }
       return defs;
     };
+
     return For;
-  })();
-  exports.Switch = Switch = (function() {
-    __extends(Switch, Base);
+
+  })(While);
+
+  exports.Switch = Switch = (function(_super) {
+
+    __extends(Switch, _super);
+
+    Switch.name = 'Switch';
+
     function Switch(subject, cases, otherwise) {
       this.subject = subject;
       this.cases = cases;
       this.otherwise = otherwise;
     }
+
     Switch.prototype.children = ['subject', 'cases', 'otherwise'];
+
     Switch.prototype.isStatement = YES;
+
     Switch.prototype.jumps = function(o) {
       var block, conds, _i, _len, _ref2, _ref3, _ref4;
       if (o == null) {
@@ -6680,46 +7063,41 @@ define('ace/mode/coffee/nodes', ['require', 'exports', 'module' , 'ace/mode/coff
       _ref2 = this.cases;
       for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
         _ref3 = _ref2[_i], conds = _ref3[0], block = _ref3[1];
-        if (block.jumps(o)) {
-          return block;
-        }
+        if (block.jumps(o)) return block;
       }
       return (_ref4 = this.otherwise) != null ? _ref4.jumps(o) : void 0;
     };
-    Switch.prototype.makeReturn = function() {
+
+    Switch.prototype.makeReturn = function(res) {
       var pair, _i, _len, _ref2, _ref3;
       _ref2 = this.cases;
       for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
         pair = _ref2[_i];
-        pair[1].makeReturn();
+        pair[1].makeReturn(res);
       }
-      if ((_ref3 = this.otherwise) != null) {
-        _ref3.makeReturn();
+      if (res) {
+        this.otherwise || (this.otherwise = new Block([new Literal('void 0')]));
       }
+      if ((_ref3 = this.otherwise) != null) _ref3.makeReturn(res);
       return this;
     };
+
     Switch.prototype.compileNode = function(o) {
-      var block, body, code, cond, conditions, expr, i, idt1, idt2, _i, _len, _len2, _ref2, _ref3, _ref4, _ref5;
+      var block, body, code, cond, conditions, expr, i, idt1, idt2, _i, _j, _len, _len1, _ref2, _ref3, _ref4, _ref5;
       idt1 = o.indent + TAB;
       idt2 = o.indent = idt1 + TAB;
       code = this.tab + ("switch (" + (((_ref2 = this.subject) != null ? _ref2.compile(o, LEVEL_PAREN) : void 0) || false) + ") {\n");
       _ref3 = this.cases;
-      for (i = 0, _len = _ref3.length; i < _len; i++) {
+      for (i = _i = 0, _len = _ref3.length; _i < _len; i = ++_i) {
         _ref4 = _ref3[i], conditions = _ref4[0], block = _ref4[1];
         _ref5 = flatten([conditions]);
-        for (_i = 0, _len2 = _ref5.length; _i < _len2; _i++) {
-          cond = _ref5[_i];
-          if (!this.subject) {
-            cond = cond.invert();
-          }
+        for (_j = 0, _len1 = _ref5.length; _j < _len1; _j++) {
+          cond = _ref5[_j];
+          if (!this.subject) cond = cond.invert();
           code += idt1 + ("case " + (cond.compile(o, LEVEL_PAREN)) + ":\n");
         }
-        if (body = block.compile(o, LEVEL_TOP)) {
-          code += body + '\n';
-        }
-        if (i === this.cases.length - 1 && !this.otherwise) {
-          break;
-        }
+        if (body = block.compile(o, LEVEL_TOP)) code += body + '\n';
+        if (i === this.cases.length - 1 && !this.otherwise) break;
         expr = this.lastNonComment(block.expressions);
         if (expr instanceof Return || (expr instanceof Literal && expr.jumps() && expr.value !== 'debugger')) {
           continue;
@@ -6731,29 +7109,38 @@ define('ace/mode/coffee/nodes', ['require', 'exports', 'module' , 'ace/mode/coff
       }
       return code + this.tab + '}';
     };
+
     return Switch;
-  })();
-  exports.If = If = (function() {
-    __extends(If, Base);
+
+  })(Base);
+
+  exports.If = If = (function(_super) {
+
+    __extends(If, _super);
+
+    If.name = 'If';
+
     function If(condition, body, options) {
       this.body = body;
-      if (options == null) {
-        options = {};
-      }
+      if (options == null) options = {};
       this.condition = options.type === 'unless' ? condition.invert() : condition;
       this.elseBody = null;
       this.isChain = false;
       this.soak = options.soak;
     }
+
     If.prototype.children = ['condition', 'body', 'elseBody'];
+
     If.prototype.bodyNode = function() {
       var _ref2;
       return (_ref2 = this.body) != null ? _ref2.unwrap() : void 0;
     };
+
     If.prototype.elseBodyNode = function() {
       var _ref2;
       return (_ref2 = this.elseBody) != null ? _ref2.unwrap() : void 0;
     };
+
     If.prototype.addElse = function(elseBody) {
       if (this.isChain) {
         this.elseBodyNode().addElse(elseBody);
@@ -6763,14 +7150,17 @@ define('ace/mode/coffee/nodes', ['require', 'exports', 'module' , 'ace/mode/coff
       }
       return this;
     };
+
     If.prototype.isStatement = function(o) {
       var _ref2;
       return (o != null ? o.level : void 0) === LEVEL_TOP || this.bodyNode().isStatement(o) || ((_ref2 = this.elseBodyNode()) != null ? _ref2.isStatement(o) : void 0);
     };
+
     If.prototype.jumps = function(o) {
       var _ref2;
       return this.body.jumps(o) || ((_ref2 = this.elseBody) != null ? _ref2.jumps(o) : void 0);
     };
+
     If.prototype.compileNode = function(o) {
       if (this.isStatement(o)) {
         return this.compileStatement(o);
@@ -6778,11 +7168,16 @@ define('ace/mode/coffee/nodes', ['require', 'exports', 'module' , 'ace/mode/coff
         return this.compileExpression(o);
       }
     };
-    If.prototype.makeReturn = function() {
-      this.body && (this.body = new Block([this.body.makeReturn()]));
-      this.elseBody && (this.elseBody = new Block([this.elseBody.makeReturn()]));
+
+    If.prototype.makeReturn = function(res) {
+      if (res) {
+        this.elseBody || (this.elseBody = new Block([new Literal('void 0')]));
+      }
+      this.body && (this.body = new Block([this.body.makeReturn(res)]));
+      this.elseBody && (this.elseBody = new Block([this.elseBody.makeReturn(res)]));
       return this;
     };
+
     If.prototype.ensureBlock = function(node) {
       if (node instanceof Block) {
         return node;
@@ -6790,8 +7185,9 @@ define('ace/mode/coffee/nodes', ['require', 'exports', 'module' , 'ace/mode/coff
         return new Block([node]);
       }
     };
+
     If.prototype.compileStatement = function(o) {
-      var body, child, cond, exeq, ifPart;
+      var body, bodyc, child, cond, exeq, ifPart, _ref2;
       child = del(o, 'chainChild');
       exeq = del(o, 'isExistentialEquals');
       if (exeq) {
@@ -6801,19 +7197,18 @@ define('ace/mode/coffee/nodes', ['require', 'exports', 'module' , 'ace/mode/coff
       }
       cond = this.condition.compile(o, LEVEL_PAREN);
       o.indent += TAB;
-      body = this.ensureBlock(this.body).compile(o);
-      if (body) {
-        body = "\n" + body + "\n" + this.tab;
-      }
-      ifPart = "if (" + cond + ") {" + body + "}";
-      if (!child) {
-        ifPart = this.tab + ifPart;
-      }
-      if (!this.elseBody) {
-        return ifPart;
-      }
+      body = this.ensureBlock(this.body);
+      bodyc = body.compile(o);
+      if (1 === ((_ref2 = body.expressions) != null ? _ref2.length : void 0) && !this.elseBody && !child && bodyc && cond && -1 === (bodyc.indexOf('\n')) && 80 > cond.length + bodyc.length) {
+        return "" + this.tab + "if (" + cond + ") " + (bodyc.replace(/^\s+/, ''));
+      }
+      if (bodyc) bodyc = "\n" + bodyc + "\n" + this.tab;
+      ifPart = "if (" + cond + ") {" + bodyc + "}";
+      if (!child) ifPart = this.tab + ifPart;
+      if (!this.elseBody) return ifPart;
       return ifPart + ' else ' + (this.isChain ? (o.indent = this.tab, o.chainChild = true, this.elseBody.unwrap().compile(o, LEVEL_TOP)) : "{\n" + (this.elseBody.compile(o, LEVEL_TOP)) + "\n" + this.tab + "}");
     };
+
     If.prototype.compileExpression = function(o) {
       var alt, body, code, cond;
       cond = this.condition.compile(o, LEVEL_COND);
@@ -6826,33 +7221,25 @@ define('ace/mode/coffee/nodes', ['require', 'exports', 'module' , 'ace/mode/coff
         return code;
       }
     };
+
     If.prototype.unfoldSoak = function() {
       return this.soak && this;
     };
+
     return If;
-  })();
-  Push = {
-    wrap: function(name, exps) {
-      if (exps.isEmpty() || last(exps.expressions).jumps()) {
-        return exps;
-      }
-      return exps.push(new Call(new Value(new Literal(name), [new Access(new Literal('push'))]), [exps.pop()]));
-    }
-  };
+
+  })(Base);
+
   Closure = {
     wrap: function(expressions, statement, noReturn) {
       var args, call, func, mentionsArgs, meth;
-      if (expressions.jumps()) {
-        return expressions;
-      }
+      if (expressions.jumps()) return expressions;
       func = new Code([], Block.wrap([expressions]));
       args = [];
       if ((mentionsArgs = expressions.contains(this.literalArgs)) || expressions.contains(this.literalThis)) {
         meth = new Literal(mentionsArgs ? 'apply' : 'call');
         args = [new Literal('this')];
-        if (mentionsArgs) {
-          args.push(new Literal('arguments'));
-        }
+        if (mentionsArgs) args.push(new Literal('arguments'));
         func = new Value(func, [new Access(meth)]);
       }
       func.noReturn = noReturn;
@@ -6870,46 +7257,73 @@ define('ace/mode/coffee/nodes', ['require', 'exports', 'module' , 'ace/mode/coff
       return (node instanceof Literal && node.value === 'this' && !node.asKey) || (node instanceof Code && node.bound);
     }
   };
+
   unfoldSoak = function(o, parent, name) {
     var ifn;
-    if (!(ifn = parent[name].unfoldSoak(o))) {
-      return;
-    }
+    if (!(ifn = parent[name].unfoldSoak(o))) return;
     parent[name] = ifn.body;
     ifn.body = new Value(parent);
     return ifn;
   };
+
   UTILITIES = {
-    "extends": 'function(child, parent) {\n  for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; }\n  function ctor() { this.constructor = child; }\n  ctor.prototype = parent.prototype;\n  child.prototype = new ctor;\n  child.__super__ = parent.prototype;\n  return child;\n}',
-    bind: 'function(fn, me){ return function(){ return fn.apply(me, arguments); }; }',
-    indexOf: 'Array.prototype.indexOf || function(item) {\n  for (var i = 0, l = this.length; i < l; i++) {\n    if (this[i] === item) return i;\n  }\n  return -1;\n}',
-    hasProp: 'Object.prototype.hasOwnProperty',
-    slice: 'Array.prototype.slice'
+    "extends": function() {
+      return "function(child, parent) { for (var key in parent) { if (" + (utility('hasProp')) + ".call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor; child.__super__ = parent.prototype; return child; }";
+    },
+    bind: function() {
+      return 'function(fn, me){ return function(){ return fn.apply(me, arguments); }; }';
+    },
+    indexOf: function() {
+      return "[].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }";
+    },
+    hasProp: function() {
+      return '{}.hasOwnProperty';
+    },
+    slice: function() {
+      return '[].slice';
+    }
   };
+
   LEVEL_TOP = 1;
+
   LEVEL_PAREN = 2;
+
   LEVEL_LIST = 3;
+
   LEVEL_COND = 4;
+
   LEVEL_OP = 5;
+
   LEVEL_ACCESS = 6;
+
   TAB = '  ';
-  IDENTIFIER = /^[$A-Za-z_\x7f-\uffff][$\w\x7f-\uffff]*$/;
+
+  IDENTIFIER_STR = "[$A-Za-z_\\x7f-\\uffff][$\\w\\x7f-\\uffff]*";
+
+  IDENTIFIER = RegExp("^" + IDENTIFIER_STR + "$");
+
   SIMPLENUM = /^[+-]?\d+$/;
-  METHOD_DEF = /^(?:([$A-Za-z_][$\w\x7f-\uffff]*)\.prototype\.)?([$A-Za-z_][$\w\x7f-\uffff]*)$/;
+
+  METHOD_DEF = RegExp("^(?:(" + IDENTIFIER_STR + ")\\.prototype(?:\\.(" + IDENTIFIER_STR + ")|\\[(\"(?:[^\\\\\"\\r\\n]|\\\\.)*\"|'(?:[^\\\\'\\r\\n]|\\\\.)*')\\]|\\[(0x[\\da-fA-F]+|\\d*\\.?\\d+(?:[eE][+-]?\\d+)?)\\]))|(" + IDENTIFIER_STR + ")$");
+
   IS_STRING = /^['"]/;
+
   utility = function(name) {
     var ref;
     ref = "__" + name;
-    Scope.root.assign(ref, UTILITIES[name]);
+    Scope.root.assign(ref, UTILITIES[name]());
     return ref;
   };
+
   multident = function(code, tab) {
-    return code.replace(/\n/g, '$&' + tab);
+    code = code.replace(/\n/g, '$&' + tab);
+    return code.replace(/\s+$/, '');
   };
-});
-/**
+
+
+});/**
  * Copyright (c) 2011 Jeremy Ashkenas
- *
+ * 
  * Permission is hereby granted, free of charge, to any person
  * obtaining a copy of this software and associated documentation
  * files (the "Software"), to deal in the Software without
@@ -6933,10 +7347,18 @@ define('ace/mode/coffee/nodes', ['require', 'exports', 'module' , 'ace/mode/coff
  */
 
 define('ace/mode/coffee/scope', ['require', 'exports', 'module' , 'ace/mode/coffee/helpers'], function(require, exports, module) {
+// Generated by CoffeeScript 1.2.1-pre
+
   var Scope, extend, last, _ref;
+
   _ref = require('./helpers'), extend = _ref.extend, last = _ref.last;
+
   exports.Scope = Scope = (function() {
+
+    Scope.name = 'Scope';
+
     Scope.root = null;
+
     function Scope(parent, expressions, method) {
       this.parent = parent;
       this.expressions = expressions;
@@ -6948,17 +7370,13 @@ define('ace/mode/coffee/scope', ['require', 'exports', 'module' , 'ace/mode/coff
         }
       ];
       this.positions = {};
-      if (!this.parent) {
-        Scope.root = this;
-      }
+      if (!this.parent) Scope.root = this;
     }
+
     Scope.prototype.add = function(name, type, immediate) {
-      var pos;
-      if (this.shared && !immediate) {
-        return this.parent.add(name, type, immediate);
-      }
-      if (typeof (pos = this.positions[name]) === 'number') {
-        return this.variables[pos].type = type;
+      if (this.shared && !immediate) return this.parent.add(name, type, immediate);
+      if (Object.prototype.hasOwnProperty.call(this.positions, name)) {
+        return this.variables[this.positions[name]].type = type;
       } else {
         return this.positions[name] = this.variables.push({
           name: name,
@@ -6966,89 +7384,94 @@ define('ace/mode/coffee/scope', ['require', 'exports', 'module' , 'ace/mode/coff
         }) - 1;
       }
     };
+
     Scope.prototype.find = function(name, options) {
-      if (this.check(name, options)) {
-        return true;
-      }
+      if (this.check(name, options)) return true;
       this.add(name, 'var');
       return false;
     };
+
     Scope.prototype.parameter = function(name) {
-      if (this.shared && this.parent.check(name, true)) {
-        return;
-      }
+      if (this.shared && this.parent.check(name, true)) return;
       return this.add(name, 'param');
     };
+
     Scope.prototype.check = function(name, immediate) {
-      var found, _ref2;
+      var found, _ref1;
       found = !!this.type(name);
-      if (found || immediate) {
-        return found;
-      }
-      return !!((_ref2 = this.parent) != null ? _ref2.check(name) : void 0);
+      if (found || immediate) return found;
+      return !!((_ref1 = this.parent) != null ? _ref1.check(name) : void 0);
     };
+
     Scope.prototype.temporary = function(name, index) {
       if (name.length > 1) {
-        return '_' + name + (index > 1 ? index : '');
+        return '_' + name + (index > 1 ? index - 1 : '');
       } else {
         return '_' + (index + parseInt(name, 36)).toString(36).replace(/\d/g, 'a');
       }
     };
+
     Scope.prototype.type = function(name) {
-      var v, _i, _len, _ref2;
-      _ref2 = this.variables;
-      for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
-        v = _ref2[_i];
-        if (v.name === name) {
-          return v.type;
-        }
+      var v, _i, _len, _ref1;
+      _ref1 = this.variables;
+      for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
+        v = _ref1[_i];
+        if (v.name === name) return v.type;
       }
       return null;
     };
-    Scope.prototype.freeVariable = function(type) {
+
+    Scope.prototype.freeVariable = function(name, reserve) {
       var index, temp;
+      if (reserve == null) reserve = true;
       index = 0;
-      while (this.check((temp = this.temporary(type, index)))) {
+      while (this.check((temp = this.temporary(name, index)))) {
         index++;
       }
-      this.add(temp, 'var', true);
+      if (reserve) this.add(temp, 'var', true);
       return temp;
     };
+
     Scope.prototype.assign = function(name, value) {
       this.add(name, {
         value: value,
         assigned: true
-      });
+      }, true);
       return this.hasAssignments = true;
     };
+
     Scope.prototype.hasDeclarations = function() {
       return !!this.declaredVariables().length;
     };
+
     Scope.prototype.declaredVariables = function() {
-      var realVars, tempVars, v, _i, _len, _ref2;
+      var realVars, tempVars, v, _i, _len, _ref1;
       realVars = [];
       tempVars = [];
-      _ref2 = this.variables;
-      for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
-        v = _ref2[_i];
+      _ref1 = this.variables;
+      for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
+        v = _ref1[_i];
         if (v.type === 'var') {
           (v.name.charAt(0) === '_' ? tempVars : realVars).push(v.name);
         }
       }
       return realVars.sort().concat(tempVars.sort());
     };
+
     Scope.prototype.assignedVariables = function() {
-      var v, _i, _len, _ref2, _results;
-      _ref2 = this.variables;
+      var v, _i, _len, _ref1, _results;
+      _ref1 = this.variables;
       _results = [];
-      for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
-        v = _ref2[_i];
-        if (v.type.assigned) {
-          _results.push("" + v.name + " = " + v.type.value);
-        }
+      for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
+        v = _ref1[_i];
+        if (v.type.assigned) _results.push("" + v.name + " = " + v.type.value);
       }
       return _results;
     };
+
     return Scope;
+
   })();
-});
+
+
+});
\ No newline at end of file
diff --git a/apps/files_texteditor/js/aceeditor/worker-css.js b/apps/files_texteditor/js/aceeditor/worker-css.js
index 7b179068ae1ff627f497c35f2daea6e7fd0032e7..7037c9b6aa66fdef8891324ed445b690e5a84fe5 100644
--- a/apps/files_texteditor/js/aceeditor/worker-css.js
+++ b/apps/files_texteditor/js/aceeditor/worker-css.js
@@ -198,7 +198,7 @@ define('ace/lib/regexp', ['require', 'exports', 'module' ], function(require, ex
     RegExp.prototype.exec = function (str) {
         var match = real.exec.apply(this, arguments),
             name, r2;
-        if (match) {
+        if ( typeof(str) == 'string' && match) {
             // Fix browsers whose `exec` methods don't consistently return `undefined` for
             // nonparticipating capturing groups
             if (!compliantExecNpcg && match.length > 1 && indexOf(match, "") > -1) {
@@ -263,7 +263,8 @@ define('ace/lib/regexp', ['require', 'exports', 'module' ], function(require, ex
         return -1;
     };
 
-});// vim: ts=4 sts=4 sw=4 expandtab
+});
+// vim: ts=4 sts=4 sw=4 expandtab
 // -- kriskowal Kris Kowal Copyright (C) 2009-2011 MIT License
 // -- tlrobinson Tom Robinson Copyright (C) 2009-2010 MIT License (Narwhal Project)
 // -- dantman Daniel Friesen Copyright (C) 2010 XXX TODO License or CLA
@@ -1784,11 +1785,12 @@ var Document = function(text) {
     };
 
     this.insert = function(position, text) {
-        if (text.length == 0)
+        if (!text || text.length === 0)
             return position;
 
         position = this.$clipPosition(position);
 
+        // only detect new lines if the document has no line break yet
         if (this.getLength() <= 1)
             this.$detectNewLine(text);
 
@@ -2068,7 +2070,7 @@ var Range = function(startRow, startColumn, endRow, endColumn) {
 };
 
 (function() {
-    this.isEequal = function(range) {
+    this.isEqual = function(range) {
         return this.start.row == range.start.row &&
             this.end.row == range.end.row &&
             this.start.column == range.start.column &&
@@ -2134,6 +2136,11 @@ var Range = function(startRow, startColumn, endRow, endColumn) {
         return this.comparePoint(range.start) == 0 && this.comparePoint(range.end) == 0;
     }
 
+    this.intersectsRange = function(range) {
+        var cmp = this.compareRange(range);
+        return (cmp == -1 || cmp == 0 || cmp == 1);
+    }
+
     this.isEnd = function(row, column) {
         return this.end.row == row && this.end.column == column;
     }
@@ -2293,6 +2300,21 @@ var Range = function(startRow, startColumn, endRow, endColumn) {
         return Range.fromPoints(start || this.start, end || this.end);
     };
 
+    this.fixOrientation = function() {
+        if (
+            this.start.row < this.end.row 
+            || (this.start.row == this.end.row && this.start.column < this.end.column)
+        ) {
+            return false;
+        }
+        
+        var temp = this.start;
+        this.end = this.start;
+        this.start = temp;
+        return true;
+    };
+
+
     this.isEmpty = function() {
         return (this.start.row == this.end.row && this.start.column == this.end.column);
     };
@@ -2676,7 +2698,8 @@ exports.deferredCall = function(fcn) {
 };
 
 });
-/* 
+define('ace/mode/css/csslint', ['require', 'exports', 'module' ], function(require, exports, module) {
+/*!
 CSSLint
 Copyright (c) 2011 Nicole Sullivan and Nicholas C. Zakas. All rights reserved.
 
@@ -2699,7 +2722,8 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 THE SOFTWARE.
 
 */
-define('ace/mode/css/csslint', ['require', 'exports', 'module' ], function(require, exports, module) {
+/* Build time: 2-March-2012 02:47:11 */
+
 /*!
 Parser-Lib
 Copyright (c) 2009-2011 Nicholas C. Zakas. All rights reserved.
@@ -2723,10 +2747,11 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 THE SOFTWARE.
 
 */
-/* Build time: 13-July-2011 04:35:28 */
+/* Version v0.1.6, Build time: 2-March-2012 02:44:32 */
 var parserlib = {};
 (function(){
 
+
 /**
  * A generic base to inherit from for any object
  * that needs event handling.
@@ -2775,11 +2800,11 @@ EventTarget.prototype = {
         if (typeof event == "string"){
             event = { type: event };
         }
-        if (!event.target){
+        if (typeof event.target != "undefined"){
             event.target = this;
         }
         
-        if (!event.type){
+        if (typeof event.type == "undefined"){
             throw new Error("Event object missing 'type' property.");
         }
         
@@ -3126,7 +3151,7 @@ SyntaxError.prototype = new Error();
  * @param {int} line The line of text on which the unit resides.
  * @param {int} col The column of text on which the unit resides.
  */
-function SyntaxUnit(text, line, col){
+function SyntaxUnit(text, line, col, type){
 
 
     /**
@@ -3150,6 +3175,12 @@ function SyntaxUnit(text, line, col){
      */
     this.text = text;
 
+    /**
+     * The type of syntax unit.
+     * @type int
+     * @property type
+     */
+    this.type = type;
 }
 
 /**
@@ -3189,6 +3220,8 @@ SyntaxUnit.prototype = {
     }
 
 };
+/*global StringReader, SyntaxError*/
+
 /**
  * Generic TokenStream providing base functionality.
  * @class TokenStreamBase
@@ -3205,7 +3238,6 @@ function TokenStreamBase(input, tokenData){
      * @property _reader
      * @private
      */
-    //this._reader = (typeof input == "string") ? new StringReader(input) : input;
     this._reader = input ? new StringReader(input.toString()) : null;
     
     /**
@@ -3254,14 +3286,14 @@ function TokenStreamBase(input, tokenData){
  */
 TokenStreamBase.createTokenData = function(tokens){
 
-    var nameMap 	= [],
-        typeMap 	= {},
-		tokenData 	= tokens.concat([]),
-		i			= 0,
-		len			= tokenData.length+1;
+    var nameMap     = [],
+        typeMap     = {},
+        tokenData     = tokens.concat([]),
+        i            = 0,
+        len            = tokenData.length+1;
     
     tokenData.UNKNOWN = -1;
-	tokenData.unshift({name:"EOF"});
+    tokenData.unshift({name:"EOF"});
 
     for (; i < len; i++){
         nameMap.push(tokenData[i].name);
@@ -3278,8 +3310,8 @@ TokenStreamBase.createTokenData = function(tokens){
     tokenData.type = function(c){
         return typeMap[c];
     };
-	
-	return tokenData;
+    
+    return tokenData;
 };
 
 TokenStreamBase.prototype = {
@@ -3340,6 +3372,8 @@ TokenStreamBase.prototype = {
      */    
     mustMatch: function(tokenTypes, channel){
 
+        var token;
+
         //always convert to an array, makes things easier
         if (!(tokenTypes instanceof Array)){
             tokenTypes = [tokenTypes];
@@ -3369,7 +3403,7 @@ TokenStreamBase.prototype = {
      */
     advance: function(tokenTypes, channel){
         
-        while(this.LA(0) != 0 && !this.match(tokenTypes, channel)){
+        while(this.LA(0) !== 0 && !this.match(tokenTypes, channel)){
             this.get();
         }
 
@@ -3416,7 +3450,7 @@ TokenStreamBase.prototype = {
         }
         
         //call token retriever method
-		token = this._getToken();
+        token = this._getToken();
 
         //if it should be hidden, don't save a token
         if (token.type > -1 && !tokenInfo[token.type].hide){
@@ -3589,6 +3623,7 @@ TokenStreamBase.prototype = {
 
 
 
+
 parserlib.util = {
 StringReader: StringReader,
 SyntaxError : SyntaxError,
@@ -3598,6 +3633,7 @@ TokenStreamBase : TokenStreamBase
 };
 })();
 
+
 /* 
 Parser-Lib
 Copyright (c) 2009-2011 Nicholas C. Zakas. All rights reserved.
@@ -3621,7 +3657,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 THE SOFTWARE.
 
 */
-/* Build time: 13-July-2011 04:35:28 */
+/* Version v0.1.6, Build time: 2-March-2012 02:44:32 */
 (function(){
 var EventTarget = parserlib.util.EventTarget,
 TokenStreamBase = parserlib.util.TokenStreamBase,
@@ -3629,6 +3665,7 @@ StringReader = parserlib.util.StringReader,
 SyntaxError = parserlib.util.SyntaxError,
 SyntaxUnit  = parserlib.util.SyntaxUnit;
 
+
 var Colors = {
     aliceblue       :"#f0f8ff",
     antiquewhite    :"#faebd7",
@@ -3697,7 +3734,7 @@ var Colors = {
     lightcoral      :"#f08080",
     lightcyan       :"#e0ffff",
     lightgoldenrodyellow  :"#fafad2",
-    lightgrey       :"#d3d3d3",
+    lightgray       :"#d3d3d3",
     lightgreen      :"#90ee90",
     lightpink       :"#ffb6c1",
     lightsalmon     :"#ffa07a",
@@ -3771,6 +3808,7 @@ var Colors = {
     yellow          :"#ffff00",
     yellowgreen     :"#9acd32"
 };
+/*global SyntaxUnit, Parser*/
 /**
  * Represents a selector combinator (whitespace, +, >).
  * @namespace parserlib.css
@@ -3783,7 +3821,7 @@ var Colors = {
  */
 function Combinator(text, line, col){
     
-    SyntaxUnit.call(this, text, line, col);
+    SyntaxUnit.call(this, text, line, col, Parser.COMBINATOR_TYPE);
 
     /**
      * The type of modifier.
@@ -3809,182 +3847,7 @@ Combinator.prototype = new SyntaxUnit();
 Combinator.prototype.constructor = Combinator;
 
 
-
-var Level1Properties = {
-
-    "background": 1,
-    "background-attachment": 1,
-    "background-color": 1,
-    "background-image": 1,
-    "background-position": 1,
-    "background-repeat": 1,
- 
-    "border": 1,
-    "border-bottom": 1,
-    "border-bottom-width": 1,
-    "border-color": 1,
-    "border-left": 1,
-    "border-left-width": 1,
-    "border-right": 1,
-    "border-right-width": 1,
-    "border-style": 1,
-    "border-top": 1,
-    "border-top-width": 1,
-    "border-width": 1,
- 
-    "clear": 1,
-    "color": 1,
-    "display": 1,
-    "float": 1,
- 
-    "font": 1,
-    "font-family": 1,
-    "font-size": 1,
-    "font-style": 1,
-    "font-variant": 1,
-    "font-weight": 1,
- 
-    "height": 1,
-    "letter-spacing": 1,
-    "line-height": 1,
- 
-    "list-style": 1,
-    "list-style-image": 1,
-    "list-style-position": 1,
-    "list-style-type": 1,
- 
-    "margin": 1,
-    "margin-bottom": 1,
-    "margin-left": 1,
-    "margin-right": 1,
-    "margin-top": 1,
- 
-    "padding": 1,
-    "padding-bottom": 1,
-    "padding-left": 1,
-    "padding-right": 1,
-    "padding-top": 1,
- 
-    "text-align": 1,
-    "text-decoration": 1,
-    "text-indent": 1,
-    "text-transform": 1,
- 
-    "vertical-align": 1,
-    "white-space": 1,
-    "width": 1,
-    "word-spacing": 1
-    
-};
-
-var Level2Properties = {
-
-    //Aural
-    "azimuth": 1,
-    "cue-after": 1,
-    "cue-before": 1,
-    "cue": 1,
-    "elevation": 1,
-    "pause-after": 1,
-    "pause-before": 1,
-    "pause": 1,
-    "pitch-range": 1,
-    "pitch": 1,
-    "play-during": 1,
-    "richness": 1,
-    "speak-header": 1,
-    "speak-numeral": 1,
-    "speak-punctuation": 1,
-    "speak": 1,
-    "speech-rate": 1,
-    "stress": 1,
-    "voice-family": 1,
-    "volume": 1,
-    
-    //Paged
-    "orphans": 1,
-    "page-break-after": 1,
-    "page-break-before": 1,
-    "page-break-inside": 1,
-    "widows": 1,
-
-    //Interactive
-    "cursor": 1,
-    "outline-color": 1,
-    "outline-style": 1,
-    "outline-width": 1,
-    "outline": 1,    
-    
-    //Visual
-    "background-attachment": 1,
-    "background-color": 1,
-    "background-image": 1,
-    "background-position": 1,
-    "background-repeat": 1,
-    "background": 1,    
-    "border-collapse": 1,
-    "border-color": 1,
-    "border-spacing": 1,
-    "border-style": 1,
-    "border-top": 1,
-    "border-top-color": 1,
-    "border-top-style": 1,
-    "border-top-width": 1,
-    "border-width": 1,
-    "border": 1,
-    "bottom": 1,    
-    "caption-side": 1,
-    "clear": 1,
-    "clip": 1,
-    "color": 1,
-    "content": 1,
-    "counter-increment": 1,
-    "counter-reset": 1,
-    "direction": 1,
-    "display": 1,
-    "empty-cells": 1,
-    "float": 1,
-    "font-family": 1,
-    "font-size": 1,
-    "font-style": 1,
-    "font-variant": 1,
-    "font-weight": 1,
-    "font": 1,
-    "height": 1,
-    "left": 1,
-    "letter-spacing": 1,
-    "line-height": 1,
-    "list-style-image": 1,
-    "list-style-position": 1,
-    "list-style-type": 1,
-    "list-style": 1,
-    "margin-right": 1,
-    "margin-top": 1,
-    "margin": 1,
-    "max-height": 1,
-    "max-width": 1,
-    "min-height": 1,
-    "min-width": 1,
-    "overflow": 1,
-    "padding-top": 1,
-    "padding": 1,
-    "position": 1,
-    "quotes": 1,
-    "right": 1,
-    "table-layout": 1,
-    "text-align": 1,
-    "text-decoration": 1,
-    "text-indent": 1,
-    "text-transform": 1,
-    "top": 1,
-    "unicode-bidi": 1,
-    "vertical-align": 1,
-    "visibility": 1,
-    "white-space": 1,
-    "width": 1,
-    "word-spacing": 1,
-    "z-index": 1
-};
+/*global SyntaxUnit, Parser*/
 /**
  * Represents a media feature, such as max-width:500.
  * @namespace parserlib.css
@@ -3996,7 +3859,7 @@ var Level2Properties = {
  */
 function MediaFeature(name, value){
     
-    SyntaxUnit.call(this, "(" + name + (value !== null ? ":" + value : "") + ")", name.startLine, name.startCol);
+    SyntaxUnit.call(this, "(" + name + (value !== null ? ":" + value : "") + ")", name.startLine, name.startCol, Parser.MEDIA_FEATURE_TYPE);
 
     /**
      * The name of the media feature
@@ -4017,6 +3880,7 @@ MediaFeature.prototype = new SyntaxUnit();
 MediaFeature.prototype.constructor = MediaFeature;
 
 
+/*global SyntaxUnit, Parser*/
 /**
  * Represents an individual media query.
  * @namespace parserlib.css
@@ -4031,7 +3895,7 @@ MediaFeature.prototype.constructor = MediaFeature;
  */
 function MediaQuery(modifier, mediaType, features, line, col){
     
-    SyntaxUnit.call(this, (modifier ? modifier + " ": "") + (mediaType ? mediaType + " " : "") + features.join(" and "), line, col);
+    SyntaxUnit.call(this, (modifier ? modifier + " ": "") + (mediaType ? mediaType + " " : "") + features.join(" and "), line, col, Parser.MEDIA_QUERY_TYPE);
 
     /**
      * The media modifier ("not" or "only")
@@ -4060,6 +3924,10 @@ MediaQuery.prototype = new SyntaxUnit();
 MediaQuery.prototype.constructor = MediaQuery;
 
 
+/*global Tokens, TokenStream, SyntaxError, Properties, Validation, ValidationError, SyntaxUnit,
+    PropertyValue, PropertyValuePart, SelectorPart, SelectorSubPart, Selector,
+    PropertyName, Combinator, MediaFeature, MediaQuery, EventTarget */
+
 /**
  * A CSS3 parser.
  * @namespace parserlib.css
@@ -4083,6 +3951,18 @@ function Parser(options){
     this._tokenStream = null;
 }
 
+//Static constants
+Parser.DEFAULT_TYPE = 0;
+Parser.COMBINATOR_TYPE = 1;
+Parser.MEDIA_FEATURE_TYPE = 2;
+Parser.MEDIA_QUERY_TYPE = 3;
+Parser.PROPERTY_NAME_TYPE = 4;
+Parser.PROPERTY_VALUE_TYPE = 5;
+Parser.PROPERTY_VALUE_PART_TYPE = 6;
+Parser.SELECTOR_TYPE = 7;
+Parser.SELECTOR_PART_TYPE = 8;
+Parser.SELECTOR_SUB_PART_TYPE = 9;
+
 Parser.prototype = function(){
 
     var proto = new EventTarget(),  //new prototype
@@ -4091,6 +3971,18 @@ Parser.prototype = function(){
         
             //restore constructor
             constructor: Parser,
+                        
+            //instance constants - yuck
+            DEFAULT_TYPE : 0,
+            COMBINATOR_TYPE : 1,
+            MEDIA_FEATURE_TYPE : 2,
+            MEDIA_QUERY_TYPE : 3,
+            PROPERTY_NAME_TYPE : 4,
+            PROPERTY_VALUE_TYPE : 5,
+            PROPERTY_VALUE_PART_TYPE : 6,
+            SELECTOR_TYPE : 7,
+            SELECTOR_PART_TYPE : 8,
+            SELECTOR_SUB_PART_TYPE : 9,            
         
             //-----------------------------------------------------------------
             // Grammar
@@ -4109,6 +4001,7 @@ Parser.prototype = function(){
                
                 var tokenStream = this._tokenStream,
                     charset     = null,
+                    count,
                     token,
                     tt;
                     
@@ -4155,7 +4048,36 @@ Parser.prototype = function(){
                             case Tokens.KEYFRAMES_SYM:
                                 this._keyframes(); 
                                 this._skipCruft();
-                                break;  
+                                break;                                
+                            case Tokens.UNKNOWN_SYM:  //unknown @ rule
+                                tokenStream.get();
+                                if (!this.options.strict){
+                                
+                                    //fire error event
+                                    this.fire({
+                                        type:       "error",
+                                        error:      null,
+                                        message:    "Unknown @ rule: " + tokenStream.LT(0).value + ".",
+                                        line:       tokenStream.LT(0).startLine,
+                                        col:        tokenStream.LT(0).startCol
+                                    });                          
+                                    
+                                    //skip braces
+                                    count=0;
+                                    while (tokenStream.advance([Tokens.LBRACE, Tokens.RBRACE]) == Tokens.LBRACE){
+                                        count++;    //keep track of nesting depth
+                                    }
+                                    
+                                    while(count){
+                                        tokenStream.advance([Tokens.RBRACE]);
+                                        count--;
+                                    }
+                                    
+                                } else {
+                                    //not a syntax error, rethrow it
+                                    throw new SyntaxError("Unknown @ rule.", tokenStream.LT(0).startLine, tokenStream.LT(0).startCol);
+                                }                                
+                                break;
                             case Tokens.S:
                                 this._readWhitespace();
                                 break;
@@ -5442,7 +5364,9 @@ Parser.prototype = function(){
                 var tokenStream = this._tokenStream,
                     property    = null,
                     expr        = null,
-                    prio        = null;
+                    prio        = null,
+                    error       = null,
+                    invalid     = null;
                 
                 property = this._property();
                 if (property !== null){
@@ -5459,13 +5383,20 @@ Parser.prototype = function(){
                     
                     prio = this._prio();
                     
+                    try {
+                        this._validateProperty(property, expr);
+                    } catch (ex) {
+                        invalid = ex;
+                    }
+                    
                     this.fire({
                         type:       "property",
                         property:   property,
                         value:      expr,
                         important:  prio,
                         line:       property.line,
-                        col:        property.col
+                        col:        property.col,
+                        invalid:    invalid
                     });                      
                     
                     return true;
@@ -5533,7 +5464,7 @@ Parser.prototype = function(){
                     values.push(new PropertyValue(valueParts, valueParts[0].line, valueParts[0].col));
                 }*/
         
-                return values.length > 0 ? new PropertyValue(values, values[0].startLine, values[0].startCol) : null;
+                return values.length > 0 ? new PropertyValue(values, values[0].line, values[0].col) : null;
             },
             
             _term: function(){                       
@@ -5550,6 +5481,7 @@ Parser.prototype = function(){
                 var tokenStream = this._tokenStream,
                     unary       = null,
                     value       = null,
+                    token,
                     line,
                     col;
                     
@@ -5583,8 +5515,8 @@ Parser.prototype = function(){
                 } else {
                 
                     //see if it's a color
-                    value = this._hexcolor();
-                    if (value === null){
+                    token = this._hexcolor();
+                    if (token === null){
                     
                         //if there's no unary, get the start of the next token for line/col info
                         if (unary === null){
@@ -5612,9 +5544,10 @@ Parser.prototype = function(){
                         }*/
                     
                     } else {
+                        value = token.value;
                         if (unary === null){
-                            line = tokenStream.token().startLine;
-                            col = tokenStream.token().startCol;
+                            line = token.startLine;
+                            col = token.startCol;
                         }                    
                     }
                 
@@ -5636,15 +5569,48 @@ Parser.prototype = function(){
                  
                 var tokenStream = this._tokenStream,
                     functionText = null,
-                    expr        = null;
+                    expr        = null,
+                    lt;
                     
                 if (tokenStream.match(Tokens.FUNCTION)){
                     functionText = tokenStream.token().value;
                     this._readWhitespace();
                     expr = this._expr();
+                    functionText += expr;
+                    
+                    //START: Horrible hack in case it's an IE filter
+                    if (this.options.ieFilters && tokenStream.peek() == Tokens.EQUALS){
+                        do {
+                        
+                            if (this._readWhitespace()){
+                                functionText += tokenStream.token().value;
+                            }
+                            
+                            //might be second time in the loop
+                            if (tokenStream.LA(0) == Tokens.COMMA){
+                                functionText += tokenStream.token().value;
+                            }
+                        
+                            tokenStream.match(Tokens.IDENT);
+                            functionText += tokenStream.token().value;
+                            
+                            tokenStream.match(Tokens.EQUALS);
+                            functionText += tokenStream.token().value;
+                            
+                            //functionText += this._term();
+                            lt = tokenStream.peek();
+                            while(lt != Tokens.COMMA && lt != Tokens.S && lt != Tokens.RPAREN){
+                                tokenStream.get();
+                                functionText += tokenStream.token().value;
+                                lt = tokenStream.peek();
+                            }
+                        } while(tokenStream.match([Tokens.COMMA, Tokens.S]));
+                    }
+
+                    //END: Horrible Hack
                     
                     tokenStream.match(Tokens.RPAREN);    
-                    functionText += expr + ")";
+                    functionText += ")";
                     this._readWhitespace();
                 }                
                 
@@ -5714,9 +5680,9 @@ Parser.prototype = function(){
                  */
                  
                 var tokenStream = this._tokenStream,
-                    token,
-                    color = null;
-                
+                    token = null,
+                    color;
+                    
                 if(tokenStream.match(Tokens.HASH)){
                 
                     //need to do some validation here
@@ -5729,7 +5695,7 @@ Parser.prototype = function(){
                     this._readWhitespace();
                 }
                 
-                return color;
+                return token;
             },
             
             //-----------------------------------------------------------------
@@ -5939,7 +5905,7 @@ Parser.prototype = function(){
                     
                     while(true){
                     
-                        if (readMargins && this._margin()){
+                        if (tokenStream.match(Tokens.SEMICOLON) || (readMargins && this._margin())){
                             //noop
                         } else if (this._declaration()){
                             if (!tokenStream.match(Tokens.SEMICOLON)){
@@ -5974,10 +5940,9 @@ Parser.prototype = function(){
                         tt = tokenStream.advance([Tokens.SEMICOLON, Tokens.RBRACE]);
                         if (tt == Tokens.SEMICOLON){
                             //if there's a semicolon, then there might be another declaration
-                            this._readDeclarations(false, readMargins);
-                        } else if (tt == Tokens.RBRACE){
+                            this._readDeclarations(false, readMargins);                            
+                        } else if (tt != Tokens.RBRACE){
                             //if there's a right brace, the rule is finished so don't do anything
-                        } else {
                             //otherwise, rethrow the error because it wasn't handled properly
                             throw ex;
                         }                        
@@ -6035,6 +6000,13 @@ Parser.prototype = function(){
                 }            
             },
             
+            //-----------------------------------------------------------------
+            // Validation methods
+            //-----------------------------------------------------------------
+            _validateProperty: function(property, value){
+                Validation.validate(property, value);
+            },
+            
             //-----------------------------------------------------------------
             // Parsing methods
             //-----------------------------------------------------------------
@@ -6132,13 +6104,27 @@ Parser.prototype = function(){
                 
                 //otherwise return result
                 return result;
+            },
+
+            /**
+             * Parses an HTML style attribute: a set of CSS declarations 
+             * separated by semicolons.
+             * @param {String} input The text to parse as a style attribute
+             * @return {void} 
+             * @method parseStyleAttribute
+             */
+            parseStyleAttribute: function(input){
+                input += "}"; // for error recovery in _readDeclarations()
+                this._tokenStream = new TokenStream(input, Tokens);
+                this._readDeclarations();
             }
-            
         };
         
     //copy over onto prototype
     for (prop in additions){
-        proto[prop] = additions[prop];
+        if (additions.hasOwnProperty(prop)){
+            proto[prop] = additions[prop];
+        }
     }   
     
     return proto;
@@ -6151,6 +6137,485 @@ nth
          ['-'|'+']? INTEGER | {O}{D}{D} | {E}{V}{E}{N} ] S*
   ;
 */
+/*global Validation, ValidationTypes, ValidationError*/
+var Properties = {
+
+    //A
+    "alignment-adjust"              : "auto | baseline | before-edge | text-before-edge | middle | central | after-edge | text-after-edge | ideographic | alphabetic | hanging | mathematical | <percentage> | <length>",
+    "alignment-baseline"            : "baseline | use-script | before-edge | text-before-edge | after-edge | text-after-edge | central | middle | ideographic | alphabetic | hanging | mathematical",
+    "animation"                     : 1,
+    "animation-delay"               : { multi: "<time>", comma: true },
+    "animation-direction"           : { multi: "normal | alternate", comma: true },
+    "animation-duration"            : { multi: "<time>", comma: true },
+    "animation-iteration-count"     : { multi: "<number> | infinite", comma: true },
+    "animation-name"                : { multi: "none | <ident>", comma: true },
+    "animation-play-state"          : { multi: "running | paused", comma: true },
+    "animation-timing-function"     : 1,
+    
+    //vendor prefixed
+    "-moz-animation-delay"               : { multi: "<time>", comma: true },
+    "-moz-animation-direction"           : { multi: "normal | alternate", comma: true },
+    "-moz-animation-duration"            : { multi: "<time>", comma: true },
+    "-moz-animation-iteration-count"     : { multi: "<number> | infinite", comma: true },
+    "-moz-animation-name"                : { multi: "none | <ident>", comma: true },
+    "-moz-animation-play-state"          : { multi: "running | paused", comma: true },
+    
+    "-ms-animation-delay"               : { multi: "<time>", comma: true },
+    "-ms-animation-direction"           : { multi: "normal | alternate", comma: true },
+    "-ms-animation-duration"            : { multi: "<time>", comma: true },
+    "-ms-animation-iteration-count"     : { multi: "<number> | infinite", comma: true },
+    "-ms-animation-name"                : { multi: "none | <ident>", comma: true },
+    "-ms-animation-play-state"          : { multi: "running | paused", comma: true },
+    
+    "-webkit-animation-delay"               : { multi: "<time>", comma: true },
+    "-webkit-animation-direction"           : { multi: "normal | alternate", comma: true },
+    "-webkit-animation-duration"            : { multi: "<time>", comma: true },
+    "-webkit-animation-iteration-count"     : { multi: "<number> | infinite", comma: true },
+    "-webkit-animation-name"                : { multi: "none | <ident>", comma: true },
+    "-webkit-animation-play-state"          : { multi: "running | paused", comma: true },
+    
+    "-o-animation-delay"               : { multi: "<time>", comma: true },
+    "-o-animation-direction"           : { multi: "normal | alternate", comma: true },
+    "-o-animation-duration"            : { multi: "<time>", comma: true },
+    "-o-animation-iteration-count"     : { multi: "<number> | infinite", comma: true },
+    "-o-animation-name"                : { multi: "none | <ident>", comma: true },
+    "-o-animation-play-state"          : { multi: "running | paused", comma: true },        
+    
+    "appearance"                    : "icon | window | desktop | workspace | document | tooltip | dialog | button | push-button | hyperlink | radio-button | checkbox | menu-item | tab | menu | menubar | pull-down-menu | pop-up-menu | list-menu | radio-group | checkbox-group | outline-tree | range | field | combo-box | signature | password | normal | inherit",
+    "azimuth"                       : function (expression) {
+        var simple      = "<angle> | leftwards | rightwards | inherit",
+            direction   = "left-side | far-left | left | center-left | center | center-right | right | far-right | right-side",
+            behind      = false,
+            valid       = false,
+            part;
+        
+        if (!ValidationTypes.isAny(expression, simple)) {
+            if (ValidationTypes.isAny(expression, "behind")) {
+                behind = true;
+                valid = true;
+            }
+            
+            if (ValidationTypes.isAny(expression, direction)) {
+                valid = true;
+                if (!behind) {
+                    ValidationTypes.isAny(expression, "behind");
+                }
+            }
+        }
+        
+        if (expression.hasNext()) {
+            part = expression.next();
+            if (valid) {
+                throw new ValidationError("Expected end of value but found '" + part + "'.", part.line, part.col);
+            } else {
+                throw new ValidationError("Expected (<'azimuth'>) but found '" + part + "'.", part.line, part.col);
+            }
+        }        
+    },
+    
+    //B
+    "backface-visibility"           : "visible | hidden",
+    "background"                    : 1,
+    "background-attachment"         : { multi: "<attachment>", comma: true },
+    "background-clip"               : { multi: "<box>", comma: true },
+    "background-color"              : "<color> | inherit",
+    "background-image"              : { multi: "<bg-image>", comma: true },
+    "background-origin"             : { multi: "<box>", comma: true },
+    "background-position"           : { multi: "<bg-position>", comma: true },
+    "background-repeat"             : { multi: "<repeat-style>" },
+    "background-size"               : { multi: "<bg-size>", comma: true },
+    "baseline-shift"                : "baseline | sub | super | <percentage> | <length>",
+    "binding"                       : 1,
+    "bleed"                         : "<length>",
+    "bookmark-label"                : "<content> | <attr> | <string>",
+    "bookmark-level"                : "none | <integer>",
+    "bookmark-state"                : "open | closed",
+    "bookmark-target"               : "none | <uri> | <attr>",
+    "border"                        : "<border-width> || <border-style> || <color>",
+    "border-bottom"                 : "<border-width> || <border-style> || <color>",
+    "border-bottom-color"           : "<color>",
+    "border-bottom-left-radius"     :  "<x-one-radius>",
+    "border-bottom-right-radius"    :  "<x-one-radius>",
+    "border-bottom-style"           : "<border-style>",
+    "border-bottom-width"           : "<border-width>",
+    "border-collapse"               : "collapse | separate | inherit",
+    "border-color"                  : { multi: "<color> | inherit", max: 4 },
+    "border-image"                  : 1,
+    "border-image-outset"           : { multi: "<length> | <number>", max: 4 },
+    "border-image-repeat"           : { multi: "stretch | repeat | round", max: 2 },
+    "border-image-slice"            : function(expression) {
+        
+        var valid   = false,
+            numeric = "<number> | <percentage>",
+            fill    = false,
+            count   = 0,
+            max     = 4,
+            part;
+        
+        if (ValidationTypes.isAny(expression, "fill")) {
+            fill = true;
+            valid = true;
+        }
+        
+        while (expression.hasNext() && count < max) {
+            valid = ValidationTypes.isAny(expression, numeric);
+            if (!valid) {
+                break;
+            }
+            count++;
+        }
+        
+        
+        if (!fill) {
+            ValidationTypes.isAny(expression, "fill");
+        } else {
+            valid = true;
+        }
+        
+        if (expression.hasNext()) {
+            part = expression.next();
+            if (valid) {
+                throw new ValidationError("Expected end of value but found '" + part + "'.", part.line, part.col);
+            } else {
+                throw new ValidationError("Expected ([<number> | <percentage>]{1,4} && fill?) but found '" + part + "'.", part.line, part.col);
+            }
+        }         
+    },
+    "border-image-source"           : "<image> | none",
+    "border-image-width"            : { multi: "<length> | <percentage> | <number> | auto", max: 4 },
+    "border-left"                   : "<border-width> || <border-style> || <color>",
+    "border-left-color"             : "<color> | inherit",
+    "border-left-style"             : "<border-style>",
+    "border-left-width"             : "<border-width>",
+    "border-radius"                 : function(expression) {
+        
+        var valid   = false,
+            numeric = "<length> | <percentage>",
+            slash   = false,
+            fill    = false,
+            count   = 0,
+            max     = 8,
+            part;
+
+        while (expression.hasNext() && count < max) {
+            valid = ValidationTypes.isAny(expression, numeric);
+            if (!valid) {
+            
+                if (expression.peek() == "/" && count > 1 && !slash) {
+                    slash = true;
+                    max = count + 5;
+                    expression.next();
+                } else {
+                    break;
+                }
+            }
+            count++;
+        }
+        
+        if (expression.hasNext()) {
+            part = expression.next();
+            if (valid) {
+                throw new ValidationError("Expected end of value but found '" + part + "'.", part.line, part.col);
+            } else {
+                throw new ValidationError("Expected (<'border-radius'>) but found '" + part + "'.", part.line, part.col);
+            }
+        }         
+    },
+    "border-right"                  : "<border-width> || <border-style> || <color>",
+    "border-right-color"            : "<color> | inherit",
+    "border-right-style"            : "<border-style>",
+    "border-right-width"            : "<border-width>",
+    "border-spacing"                : { multi: "<length> | inherit", max: 2 },
+    "border-style"                  : { multi: "<border-style>", max: 4 },
+    "border-top"                    : "<border-width> || <border-style> || <color>",
+    "border-top-color"              : "<color> | inherit",
+    "border-top-left-radius"        : "<x-one-radius>",
+    "border-top-right-radius"       : "<x-one-radius>",
+    "border-top-style"              : "<border-style>",
+    "border-top-width"              : "<border-width>",
+    "border-width"                  : { multi: "<border-width>", max: 4 },
+    "bottom"                        : "<margin-width> | inherit", 
+    "box-align"                     : "start | end | center | baseline | stretch",        //http://www.w3.org/TR/2009/WD-css3-flexbox-20090723/
+    "box-decoration-break"          : "slice |clone",
+    "box-direction"                 : "normal | reverse | inherit",
+    "box-flex"                      : "<number>",
+    "box-flex-group"                : "<integer>",
+    "box-lines"                     : "single | multiple",
+    "box-ordinal-group"             : "<integer>",
+    "box-orient"                    : "horizontal | vertical | inline-axis | block-axis | inherit",
+    "box-pack"                      : "start | end | center | justify",
+    "box-shadow"                    : function (expression) {
+        var result      = false,
+            part;
+
+        if (!ValidationTypes.isAny(expression, "none")) {
+            Validation.multiProperty("<shadow>", expression, true, Infinity);                       
+        } else {
+            if (expression.hasNext()) {
+                part = expression.next();
+                throw new ValidationError("Expected end of value but found '" + part + "'.", part.line, part.col);
+            }   
+        }
+    },
+    "box-sizing"                    : "content-box | border-box | inherit",
+    "break-after"                   : "auto | always | avoid | left | right | page | column | avoid-page | avoid-column",
+    "break-before"                  : "auto | always | avoid | left | right | page | column | avoid-page | avoid-column",
+    "break-inside"                  : "auto | avoid | avoid-page | avoid-column",
+    
+    //C
+    "caption-side"                  : "top | bottom | inherit",
+    "clear"                         : "none | right | left | both | inherit",
+    "clip"                          : 1,
+    "color"                         : "<color> | inherit",
+    "color-profile"                 : 1,
+    "column-count"                  : "<integer> | auto",                      //http://www.w3.org/TR/css3-multicol/
+    "column-fill"                   : "auto | balance",
+    "column-gap"                    : "<length> | normal",
+    "column-rule"                   : "<border-width> || <border-style> || <color>",
+    "column-rule-color"             : "<color>",
+    "column-rule-style"             : "<border-style>",
+    "column-rule-width"             : "<border-width>",
+    "column-span"                   : "none | all",
+    "column-width"                  : "<length> | auto",
+    "columns"                       : 1,
+    "content"                       : 1,
+    "counter-increment"             : 1,
+    "counter-reset"                 : 1,
+    "crop"                          : "<shape> | auto",
+    "cue"                           : "cue-after | cue-before | inherit",
+    "cue-after"                     : 1,
+    "cue-before"                    : 1,
+    "cursor"                        : 1,
+    
+    //D
+    "direction"                     : "ltr | rtl | inherit",
+    "display"                       : "inline | block | list-item | inline-block | table | inline-table | table-row-group | table-header-group | table-footer-group | table-row | table-column-group | table-column | table-cell | table-caption | box | inline-box | grid | inline-grid | none | inherit",
+    "dominant-baseline"             : 1,
+    "drop-initial-after-adjust"     : "central | middle | after-edge | text-after-edge | ideographic | alphabetic | mathematical | <percentage> | <length>",
+    "drop-initial-after-align"      : "baseline | use-script | before-edge | text-before-edge | after-edge | text-after-edge | central | middle | ideographic | alphabetic | hanging | mathematical",
+    "drop-initial-before-adjust"    : "before-edge | text-before-edge | central | middle | hanging | mathematical | <percentage> | <length>",
+    "drop-initial-before-align"     : "caps-height | baseline | use-script | before-edge | text-before-edge | after-edge | text-after-edge | central | middle | ideographic | alphabetic | hanging | mathematical",
+    "drop-initial-size"             : "auto | line | <length> | <percentage>",
+    "drop-initial-value"            : "initial | <integer>",
+    
+    //E
+    "elevation"                     : "<angle> | below | level | above | higher | lower | inherit",
+    "empty-cells"                   : "show | hide | inherit",
+    
+    //F
+    "filter"                        : 1,
+    "fit"                           : "fill | hidden | meet | slice",
+    "fit-position"                  : 1,
+    "float"                         : "left | right | none | inherit",    
+    "float-offset"                  : 1,
+    "font"                          : 1,
+    "font-family"                   : 1,
+    "font-size"                     : "<absolute-size> | <relative-size> | <length> | <percentage> | inherit",
+    "font-size-adjust"              : "<number> | none | inherit",
+    "font-stretch"                  : "normal | ultra-condensed | extra-condensed | condensed | semi-condensed | semi-expanded | expanded | extra-expanded | ultra-expanded | inherit",
+    "font-style"                    : "normal | italic | oblique | inherit",
+    "font-variant"                  : "normal | small-caps | inherit",
+    "font-weight"                   : "normal | bold | bolder | lighter | 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900 | inherit",
+    
+    //G
+    "grid-cell-stacking"            : "columns | rows | layer",
+    "grid-column"                   : 1,
+    "grid-columns"                  : 1,
+    "grid-column-align"             : "start | end | center | stretch",
+    "grid-column-sizing"            : 1,
+    "grid-column-span"              : "<integer>",
+    "grid-flow"                     : "none | rows | columns",
+    "grid-layer"                    : "<integer>",
+    "grid-row"                      : 1,
+    "grid-rows"                     : 1,
+    "grid-row-align"                : "start | end | center | stretch",
+    "grid-row-span"                 : "<integer>",
+    "grid-row-sizing"               : 1,
+    
+    //H
+    "hanging-punctuation"           : 1,
+    "height"                        : "<margin-width> | inherit",
+    "hyphenate-after"               : "<integer> | auto",
+    "hyphenate-before"              : "<integer> | auto",
+    "hyphenate-character"           : "<string> | auto",
+    "hyphenate-lines"               : "no-limit | <integer>",
+    "hyphenate-resource"            : 1,
+    "hyphens"                       : "none | manual | auto",
+    
+    //I
+    "icon"                          : 1,
+    "image-orientation"             : "angle | auto",
+    "image-rendering"               : 1,
+    "image-resolution"              : 1,
+    "inline-box-align"              : "initial | last | <integer>",
+    
+    //L
+    "left"                          : "<margin-width> | inherit",
+    "letter-spacing"                : "<length> | normal | inherit",
+    "line-height"                   : "<number> | <length> | <percentage> | normal | inherit",
+    "line-break"                    : "auto | loose | normal | strict",
+    "line-stacking"                 : 1,
+    "line-stacking-ruby"            : "exclude-ruby | include-ruby",
+    "line-stacking-shift"           : "consider-shifts | disregard-shifts",
+    "line-stacking-strategy"        : "inline-line-height | block-line-height | max-height | grid-height",
+    "list-style"                    : 1,
+    "list-style-image"              : "<uri> | none | inherit",
+    "list-style-position"           : "inside | outside | inherit",
+    "list-style-type"               : "disc | circle | square | decimal | decimal-leading-zero | lower-roman | upper-roman | lower-greek | lower-latin | upper-latin | armenian | georgian | lower-alpha | upper-alpha | none | inherit",
+    
+    //M
+    "margin"                        : { multi: "<margin-width> | inherit", max: 4 },
+    "margin-bottom"                 : "<margin-width> | inherit",
+    "margin-left"                   : "<margin-width> | inherit",
+    "margin-right"                  : "<margin-width> | inherit",
+    "margin-top"                    : "<margin-width> | inherit",
+    "mark"                          : 1,
+    "mark-after"                    : 1,
+    "mark-before"                   : 1,
+    "marks"                         : 1,
+    "marquee-direction"             : 1,
+    "marquee-play-count"            : 1,
+    "marquee-speed"                 : 1,
+    "marquee-style"                 : 1,
+    "max-height"                    : "<length> | <percentage> | none | inherit",
+    "max-width"                     : "<length> | <percentage> | none | inherit",
+    "min-height"                    : "<length> | <percentage> | inherit",
+    "min-width"                     : "<length> | <percentage> | inherit",
+    "move-to"                       : 1,
+    
+    //N
+    "nav-down"                      : 1,
+    "nav-index"                     : 1,
+    "nav-left"                      : 1,
+    "nav-right"                     : 1,
+    "nav-up"                        : 1,
+    
+    //O
+    "opacity"                       : "<number> | inherit",
+    "orphans"                       : "<integer> | inherit",
+    "outline"                       : 1,
+    "outline-color"                 : "<color> | invert | inherit",
+    "outline-offset"                : 1,
+    "outline-style"                 : "<border-style> | inherit",
+    "outline-width"                 : "<border-width> | inherit",
+    "overflow"                      : "visible | hidden | scroll | auto | inherit",
+    "overflow-style"                : 1,
+    "overflow-x"                    : 1,
+    "overflow-y"                    : 1,
+    
+    //P
+    "padding"                       : { multi: "<padding-width> | inherit", max: 4 },
+    "padding-bottom"                : "<padding-width> | inherit",
+    "padding-left"                  : "<padding-width> | inherit",
+    "padding-right"                 : "<padding-width> | inherit",
+    "padding-top"                   : "<padding-width> | inherit",
+    "page"                          : 1,
+    "page-break-after"              : "auto | always | avoid | left | right | inherit",
+    "page-break-before"             : "auto | always | avoid | left | right | inherit",
+    "page-break-inside"             : "auto | avoid | inherit",
+    "page-policy"                   : 1,
+    "pause"                         : 1,
+    "pause-after"                   : 1,
+    "pause-before"                  : 1,
+    "perspective"                   : 1,
+    "perspective-origin"            : 1,
+    "phonemes"                      : 1,
+    "pitch"                         : 1,
+    "pitch-range"                   : 1,
+    "play-during"                   : 1,
+    "position"                      : "static | relative | absolute | fixed | inherit",
+    "presentation-level"            : 1,
+    "punctuation-trim"              : 1,
+    
+    //Q
+    "quotes"                        : 1,
+    
+    //R
+    "rendering-intent"              : 1,
+    "resize"                        : 1,
+    "rest"                          : 1,
+    "rest-after"                    : 1,
+    "rest-before"                   : 1,
+    "richness"                      : 1,
+    "right"                         : "<margin-width> | inherit",
+    "rotation"                      : 1,
+    "rotation-point"                : 1,
+    "ruby-align"                    : 1,
+    "ruby-overhang"                 : 1,
+    "ruby-position"                 : 1,
+    "ruby-span"                     : 1,
+    
+    //S
+    "size"                          : 1,
+    "speak"                         : "normal | none | spell-out | inherit",
+    "speak-header"                  : "once | always | inherit",
+    "speak-numeral"                 : "digits | continuous | inherit",
+    "speak-punctuation"             : "code | none | inherit",
+    "speech-rate"                   : 1,
+    "src"                           : 1,
+    "stress"                        : 1,
+    "string-set"                    : 1,
+    
+    "table-layout"                  : "auto | fixed | inherit",
+    "tab-size"                      : "<integer> | <length>",
+    "target"                        : 1,
+    "target-name"                   : 1,
+    "target-new"                    : 1,
+    "target-position"               : 1,
+    "text-align"                    : "left | right | center | justify | inherit" ,
+    "text-align-last"               : 1,
+    "text-decoration"               : 1,
+    "text-emphasis"                 : 1,
+    "text-height"                   : 1,
+    "text-indent"                   : "<length> | <percentage> | inherit",
+    "text-justify"                  : "auto | none | inter-word | inter-ideograph | inter-cluster | distribute | kashida",
+    "text-outline"                  : 1,
+    "text-overflow"                 : 1,
+    "text-shadow"                   : 1,
+    "text-transform"                : "capitalize | uppercase | lowercase | none | inherit",
+    "text-wrap"                     : "normal | none | avoid",
+    "top"                           : "<margin-width> | inherit",
+    "transform"                     : 1,
+    "transform-origin"              : 1,
+    "transform-style"               : 1,
+    "transition"                    : 1,
+    "transition-delay"              : 1,
+    "transition-duration"           : 1,
+    "transition-property"           : 1,
+    "transition-timing-function"    : 1,
+    
+    //U
+    "unicode-bidi"                  : "normal | embed | bidi-override | inherit",
+    "user-modify"                   : "read-only | read-write | write-only | inherit",
+    "user-select"                   : "none | text | toggle | element | elements | all | inherit",
+    
+    //V
+    "vertical-align"                : "<percentage> | <length> | baseline | sub | super | top | text-top | middle | bottom | text-bottom | inherit",
+    "visibility"                    : "visible | hidden | collapse | inherit",
+    "voice-balance"                 : 1,
+    "voice-duration"                : 1,
+    "voice-family"                  : 1,
+    "voice-pitch"                   : 1,
+    "voice-pitch-range"             : 1,
+    "voice-rate"                    : 1,
+    "voice-stress"                  : 1,
+    "voice-volume"                  : 1,
+    "volume"                        : 1,
+    
+    //W
+    "white-space"                   : "normal | pre | nowrap | pre-wrap | pre-line | inherit",
+    "white-space-collapse"          : 1,
+    "widows"                        : "<integer> | inherit",
+    "width"                         : "<length> | <percentage> | auto | inherit" ,
+    "word-break"                    : "normal | keep-all | break-all",
+    "word-spacing"                  : "<length> | normal | inherit",
+    "word-wrap"                     : 1,
+    
+    //Z
+    "z-index"                       : "<integer> | auto | inherit",
+    "zoom"                          : "<number> | <percentage> | normal"
+};
+/*global SyntaxUnit, Parser*/
 /**
  * Represents a selector combinator (whitespace, +, >).
  * @namespace parserlib.css
@@ -6164,7 +6629,7 @@ nth
  */
 function PropertyName(text, hack, line, col){
     
-    SyntaxUnit.call(this, (hack||"") + text, line, col);
+    SyntaxUnit.call(this, text, line, col, Parser.PROPERTY_NAME_TYPE);
 
     /**
      * The type of IE hack applied ("*", "_", or null).
@@ -6177,8 +6642,11 @@ function PropertyName(text, hack, line, col){
 
 PropertyName.prototype = new SyntaxUnit();
 PropertyName.prototype.constructor = PropertyName;
+PropertyName.prototype.toString = function(){
+    return (this.hack ? this.hack : "") + this.text;
+};
 
-
+/*global SyntaxUnit, Parser*/
 /**
  * Represents a single part of a CSS property value, meaning that it represents
  * just everything single part between ":" and ";". If there are multiple values
@@ -6193,7 +6661,7 @@ PropertyName.prototype.constructor = PropertyName;
  */
 function PropertyValue(parts, line, col){
 
-    SyntaxUnit.call(this, parts.join(" "), line, col);
+    SyntaxUnit.call(this, parts.join(" "), line, col, Parser.PROPERTY_VALUE_TYPE);
     
     /**
      * The parts that make up the selector.
@@ -6208,6 +6676,133 @@ PropertyValue.prototype = new SyntaxUnit();
 PropertyValue.prototype.constructor = PropertyValue;
 
 
+/*global SyntaxUnit, Parser*/
+/**
+ * A utility class that allows for easy iteration over the various parts of a
+ * property value.
+ * @param {parserlib.css.PropertyValue} value The property value to iterate over.
+ * @namespace parserlib.css
+ * @class PropertyValueIterator
+ * @constructor
+ */
+function PropertyValueIterator(value){
+
+    /** 
+     * Iterator value
+     * @type int
+     * @property _i
+     * @private
+     */
+    this._i = 0;
+    
+    /**
+     * The parts that make up the value.
+     * @type Array
+     * @property _parts
+     * @private
+     */
+    this._parts = value.parts;
+    
+    /**
+     * Keeps track of bookmarks along the way.
+     * @type Array
+     * @property _marks
+     * @private
+     */
+    this._marks = [];
+    
+    /**
+     * Holds the original property value.
+     * @type parserlib.css.PropertyValue
+     * @property value
+     */
+    this.value = value;
+    
+}
+
+/**
+ * Returns the total number of parts in the value.
+ * @return {int} The total number of parts in the value.
+ * @method count
+ */
+PropertyValueIterator.prototype.count = function(){
+    return this._parts.length;
+};
+
+/**
+ * Indicates if the iterator is positioned at the first item.
+ * @return {Boolean} True if positioned at first item, false if not.
+ * @method isFirst
+ */
+PropertyValueIterator.prototype.isFirst = function(){
+    return this._i === 0;
+};
+
+/**
+ * Indicates if there are more parts of the property value.
+ * @return {Boolean} True if there are more parts, false if not.
+ * @method hasNext
+ */
+PropertyValueIterator.prototype.hasNext = function(){
+    return (this._i < this._parts.length);
+};
+
+/**
+ * Marks the current spot in the iteration so it can be restored to
+ * later on.
+ * @return {void}
+ * @method mark
+ */
+PropertyValueIterator.prototype.mark = function(){
+    this._marks.push(this._i);
+};
+
+/**
+ * Returns the next part of the property value or null if there is no next
+ * part. Does not move the internal counter forward.
+ * @return {parserlib.css.PropertyValuePart} The next part of the property value or null if there is no next
+ * part.
+ * @method peek
+ */
+PropertyValueIterator.prototype.peek = function(count){
+    return this.hasNext() ? this._parts[this._i + (count || 0)] : null;
+};
+
+/**
+ * Returns the next part of the property value or null if there is no next
+ * part.
+ * @return {parserlib.css.PropertyValuePart} The next part of the property value or null if there is no next
+ * part.
+ * @method next
+ */
+PropertyValueIterator.prototype.next = function(){
+    return this.hasNext() ? this._parts[this._i++] : null;
+};
+
+/**
+ * Returns the previous part of the property value or null if there is no
+ * previous part.
+ * @return {parserlib.css.PropertyValuePart} The previous part of the 
+ * property value or null if there is no next part.
+ * @method previous
+ */
+PropertyValueIterator.prototype.previous = function(){
+    return this._i > 0 ? this._parts[--this._i] : null;
+};
+
+/**
+ * Restores the last saved bookmark.
+ * @return {void}
+ * @method restore
+ */
+PropertyValueIterator.prototype.restore = function(){
+    if (this._marks.length){
+        this._i = this._marks.pop();
+    }
+};
+
+
+/*global SyntaxUnit, Parser, Colors*/
 /**
  * Represents a single part of a CSS property value, meaning that it represents
  * just one part of the data between ":" and ";".
@@ -6221,7 +6816,7 @@ PropertyValue.prototype.constructor = PropertyValue;
  */
 function PropertyValuePart(text, line, col){
 
-    SyntaxUnit.apply(this,arguments);
+    SyntaxUnit.call(this, text, line, col, Parser.PROPERTY_VALUE_PART_TYPE);
     
     /**
      * Indicates the type of value unit.
@@ -6252,6 +6847,7 @@ function PropertyValuePart(text, line, col){
             case "in":
             case "pt":
             case "pc":
+            case "ch":
                 this.type = "length";
                 break;
                 
@@ -6315,9 +6911,36 @@ function PropertyValuePart(text, line, col){
         this.red    = +RegExp.$1 * 255 / 100;
         this.green  = +RegExp.$2 * 255 / 100;
         this.blue   = +RegExp.$3 * 255 / 100;
+    } else if (/^rgba\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*,\s*([\d\.]+)\s*\)/i.test(text)){ //rgba() color with absolute numbers
+        this.type   = "color";
+        this.red    = +RegExp.$1;
+        this.green  = +RegExp.$2;
+        this.blue   = +RegExp.$3;
+        this.alpha  = +RegExp.$4;
+    } else if (/^rgba\(\s*(\d+)%\s*,\s*(\d+)%\s*,\s*(\d+)%\s*,\s*([\d\.]+)\s*\)/i.test(text)){ //rgba() color with percentages
+        this.type   = "color";
+        this.red    = +RegExp.$1 * 255 / 100;
+        this.green  = +RegExp.$2 * 255 / 100;
+        this.blue   = +RegExp.$3 * 255 / 100;
+        this.alpha  = +RegExp.$4;        
+    } else if (/^hsl\(\s*(\d+)\s*,\s*(\d+)%\s*,\s*(\d+)%\s*\)/i.test(text)){ //hsl()
+        this.type   = "color";
+        this.hue    = +RegExp.$1;
+        this.saturation = +RegExp.$2 / 100;
+        this.lightness  = +RegExp.$3 / 100;        
+    } else if (/^hsla\(\s*(\d+)\s*,\s*(\d+)%\s*,\s*(\d+)%\s*,\s*([\d\.]+)\s*\)/i.test(text)){ //hsla() color with percentages
+        this.type   = "color";
+        this.hue    = +RegExp.$1;
+        this.saturation = +RegExp.$2 / 100;
+        this.lightness  = +RegExp.$3 / 100;        
+        this.alpha  = +RegExp.$4;        
     } else if (/^url\(["']?([^\)"']+)["']?\)/i.test(text)){ //URI
         this.type   = "uri";
         this.uri    = RegExp.$1;
+    } else if (/^([^\(]+)\(/i.test(text)){
+        this.type   = "function";
+        this.name   = RegExp.$1;
+        this.value  = text;
     } else if (/^["'][^"']*["']/.test(text)){    //string
         this.type   = "string";
         this.value  = eval(text);
@@ -6338,7 +6961,7 @@ function PropertyValuePart(text, line, col){
 }
 
 PropertyValuePart.prototype = new SyntaxUnit();
-PropertyValuePart.prototype.constructor = PropertyValue;
+PropertyValuePart.prototype.constructor = PropertyValuePart;
 
 /**
  * Create a new syntax unit based solely on the given token.
@@ -6352,6 +6975,20 @@ PropertyValuePart.prototype.constructor = PropertyValue;
 PropertyValuePart.fromToken = function(token){
     return new PropertyValuePart(token.value, token.startLine, token.startCol);
 };
+var Pseudos = {
+    ":first-letter": 1,
+    ":first-line":   1,
+    ":before":       1,
+    ":after":        1
+};
+
+Pseudos.ELEMENT = 1;
+Pseudos.CLASS = 2;
+
+Pseudos.isElement = function(pseudo){
+    return pseudo.indexOf("::") === 0 || Pseudos[pseudo.toLowerCase()] == Pseudos.ELEMENT;
+};
+/*global SyntaxUnit, Parser, Specificity*/
 /**
  * Represents an entire single selector, including all parts but not
  * including multiple selectors (those separated by commas).
@@ -6365,7 +7002,7 @@ PropertyValuePart.fromToken = function(token){
  */
 function Selector(parts, line, col){
     
-    SyntaxUnit.call(this, parts.join(" "), line, col);
+    SyntaxUnit.call(this, parts.join(" "), line, col, Parser.SELECTOR_TYPE);
     
     /**
      * The parts that make up the selector.
@@ -6373,6 +7010,13 @@ function Selector(parts, line, col){
      * @property parts
      */
     this.parts = parts;
+    
+    /**
+     * The specificity of the selector.
+     * @type parserlib.css.Specificity
+     * @property specificity
+     */
+    this.specificity = Specificity.calculate(this);
 
 }
 
@@ -6380,6 +7024,7 @@ Selector.prototype = new SyntaxUnit();
 Selector.prototype.constructor = Selector;
 
 
+/*global SyntaxUnit, Parser*/
 /**
  * Represents a single part of a selector string, meaning a single set of
  * element name and modifiers. This does not include combinators such as
@@ -6398,7 +7043,7 @@ Selector.prototype.constructor = Selector;
  */
 function SelectorPart(elementName, modifiers, text, line, col){
     
-    SyntaxUnit.call(this, text, line, col);
+    SyntaxUnit.call(this, text, line, col, Parser.SELECTOR_PART_TYPE);
 
     /**
      * The tag name of the element to which this part
@@ -6422,6 +7067,7 @@ SelectorPart.prototype = new SyntaxUnit();
 SelectorPart.prototype.constructor = SelectorPart;
 
 
+/*global SyntaxUnit, Parser*/
 /**
  * Represents a selector modifier string, meaning a class name, element name,
  * element ID, pseudo rule, etc.
@@ -6436,7 +7082,7 @@ SelectorPart.prototype.constructor = SelectorPart;
  */
 function SelectorSubPart(text, type, line, col){
     
-    SyntaxUnit.call(this, text, line, col);
+    SyntaxUnit.call(this, text, line, col, Parser.SELECTOR_SUB_PART_TYPE);
 
     /**
      * The type of modifier.
@@ -6458,43 +7104,167 @@ SelectorSubPart.prototype = new SyntaxUnit();
 SelectorSubPart.prototype.constructor = SelectorSubPart;
 
 
+/*global Pseudos, SelectorPart*/
+/**
+ * Represents a selector's specificity.
+ * @namespace parserlib.css
+ * @class Specificity
+ * @constructor
+ * @param {int} a Should be 1 for inline styles, zero for stylesheet styles
+ * @param {int} b Number of ID selectors
+ * @param {int} c Number of classes and pseudo classes
+ * @param {int} d Number of element names and pseudo elements
+ */
+function Specificity(a, b, c, d){
+    this.a = a;
+    this.b = b;
+    this.c = c;
+    this.d = d;
+}
+
+Specificity.prototype = {
+    constructor: Specificity,
+    
+    /**
+     * Compare this specificity to another.
+     * @param {Specificity} other The other specificity to compare to.
+     * @return {int} -1 if the other specificity is larger, 1 if smaller, 0 if equal.
+     * @method compare
+     */
+    compare: function(other){
+        var comps = ["a", "b", "c", "d"],
+            i, len;
+            
+        for (i=0, len=comps.length; i < len; i++){
+            if (this[comps[i]] < other[comps[i]]){
+                return -1;
+            } else if (this[comps[i]] > other[comps[i]]){
+                return 1;
+            }
+        }
+        
+        return 0;
+    },
+    
+    /**
+     * Creates a numeric value for the specificity.
+     * @return {int} The numeric value for the specificity.
+     * @method valueOf
+     */
+    valueOf: function(){
+        return (this.a * 1000) + (this.b * 100) + (this.c * 10) + this.d;
+    },
+    
+    /**
+     * Returns a string representation for specificity.
+     * @return {String} The string representation of specificity.
+     * @method toString
+     */
+    toString: function(){
+        return this.a + "," + this.b + "," + this.c + "," + this.d;
+    }
+
+};
+
+/**
+ * Calculates the specificity of the given selector.
+ * @param {parserlib.css.Selector} The selector to calculate specificity for.
+ * @return {parserlib.css.Specificity} The specificity of the selector.
+ * @static
+ * @method calculate
+ */
+Specificity.calculate = function(selector){
+
+    var i, len,
+        part,
+        b=0, c=0, d=0;
+        
+    function updateValues(part){
+    
+        var i, j, len, num,
+            elementName = part.elementName ? part.elementName.text : "",
+            modifier;
+    
+        if (elementName && elementName.charAt(elementName.length-1) != "*") {
+            d++;
+        }    
+    
+        for (i=0, len=part.modifiers.length; i < len; i++){
+            modifier = part.modifiers[i];
+            switch(modifier.type){
+                case "class":
+                case "attribute":
+                    c++;
+                    break;
+                    
+                case "id":
+                    b++;
+                    break;
+                    
+                case "pseudo":
+                    if (Pseudos.isElement(modifier.text)){
+                        d++;
+                    } else {
+                        c++;
+                    }                    
+                    break;
+                    
+                case "not":
+                    for (j=0, num=modifier.args.length; j < num; j++){
+                        updateValues(modifier.args[j]);
+                    }
+            }    
+         }
+    }
+    
+    for (i=0, len=selector.parts.length; i < len; i++){
+        part = selector.parts[i];
+        
+        if (part instanceof SelectorPart){
+            updateValues(part);                
+        }
+    }
+    
+    return new Specificity(0, b, c, d);
+};
+
+/*global Tokens, TokenStreamBase*/
+
+var h = /^[0-9a-fA-F]$/,
+    nonascii = /^[\u0080-\uFFFF]$/,
+    nl = /\n|\r\n|\r|\f/;
+
+//-----------------------------------------------------------------------------
+// Helper functions
+//-----------------------------------------------------------------------------
+
 
-
-var h = /^[0-9a-fA-F]$/,
-    nonascii = /^[\u0080-\uFFFF]$/,
-    nl = /\n|\r\n|\r|\f/;
-
-//-----------------------------------------------------------------------------
-// Helper functions
-//-----------------------------------------------------------------------------
-
-
 function isHexDigit(c){
-    return c != null && h.test(c);
+    return c !== null && h.test(c);
 }
 
 function isDigit(c){
-    return c != null && /\d/.test(c);
+    return c !== null && /\d/.test(c);
 }
 
 function isWhitespace(c){
-    return c != null && /\s/.test(c);
+    return c !== null && /\s/.test(c);
 }
 
 function isNewLine(c){
-    return c != null && nl.test(c);
+    return c !== null && nl.test(c);
 }
 
 function isNameStart(c){
-    return c != null && (/[a-z_\u0080-\uFFFF\\]/i.test(c));
+    return c !== null && (/[a-z_\u0080-\uFFFF\\]/i.test(c));
 }
 
 function isNameChar(c){
-    return c != null && (isNameStart(c) || /[0-9\-\\]/.test(c));
+    return c !== null && (isNameStart(c) || /[0-9\-\\]/.test(c));
 }
 
 function isIdentStart(c){
-    return c != null && (isNameStart(c) || /\-\\/.test(c));
+    return c !== null && (isNameStart(c) || /\-\\/.test(c));
 }
 
 function mix(receiver, supplier){
@@ -6685,8 +7455,7 @@ TokenStream.prototype = mix(new TokenStreamBase(), {
                         token = this.unicodeRangeToken(c, startLine, startCol);
                         break;
                     }
-                    /*falls through*/
-
+                    /* falls through */
                 default:
 
                     /*
@@ -6739,11 +7508,9 @@ TokenStream.prototype = mix(new TokenStreamBase(), {
             //make sure this token is wanted
             //TODO: check channel
             break;
-
-            c = reader.read();
         }
 
-        if (!token && c == null){
+        if (!token && c === null){
             token = this.createToken(Tokens.EOF,null,startLine,startCol);
         }
 
@@ -6822,9 +7589,13 @@ TokenStream.prototype = mix(new TokenStreamBase(), {
 
         //if it's not valid, use the first character only and reset the reader
         if (tt == Tokens.CHAR || tt == Tokens.UNKNOWN){
-            tt = Tokens.CHAR;
-            rule = first;
-            reader.reset();
+            if (rule.length > 1){
+                tt = Tokens.UNKNOWN_SYM;                
+            } else {
+                tt = Tokens.CHAR;
+                rule = first;
+                reader.reset();
+            }
         }
 
         return this.createToken(tt, rule, startLine, startCol);
@@ -7023,7 +7794,7 @@ TokenStream.prototype = mix(new TokenStreamBase(), {
                     break;
                 } else {
                     temp = this.readComment(c);
-                    if (temp == ""){    //broken!
+                    if (temp === ""){    //broken!
                         break;
                     }
                 }
@@ -7164,7 +7935,7 @@ TokenStream.prototype = mix(new TokenStreamBase(), {
         }
 
         //if c is null, that means we're out of input and the string was never closed
-        if (c == null){
+        if (c === null){
             tt = Tokens.INVALID;
         }
 
@@ -7329,7 +8100,7 @@ TokenStream.prototype = mix(new TokenStreamBase(), {
         }
 
         //if c is null, that means we're out of input and the string was never closed
-        if (c == null){
+        if (c === null){
             string = "";
         }
 
@@ -7365,7 +8136,7 @@ TokenStream.prototype = mix(new TokenStreamBase(), {
         }
 
         //if there was no inner value or the next character isn't closing paren, it's not a URI
-        if (inner == "" || c != ")"){
+        if (inner === "" || c != ")"){
             uri = first;
             reader.reset();
         } else {
@@ -7441,7 +8212,7 @@ TokenStream.prototype = mix(new TokenStreamBase(), {
                 comment += c;
 
                 //look for end of comment
-                if (c == "*" && reader.peek() == "/"){
+                if (comment.length > 2 && c == "*" && reader.peek() == "/"){
                     comment += reader.read();
                     break;
                 }
@@ -7491,10 +8262,11 @@ var Tokens  = [
     { name: "FONT_FACE_SYM", text: "@font-face"},
     { name: "CHARSET_SYM", text: "@charset"},
     { name: "NAMESPACE_SYM", text: "@namespace"},
+    { name: "UNKNOWN_SYM" },
     //{ name: "ATKEYWORD"},
     
     //CSS3 animations
-    { name: "KEYFRAMES_SYM", text: [ "@keyframes", "@-webkit-keyframes", "@-moz-keyframes" ] },
+    { name: "KEYFRAMES_SYM", text: [ "@keyframes", "@-webkit-keyframes", "@-moz-keyframes", "@-ms-keyframes" ] },
 
     //important symbol
     { name: "IMPORTANT_SYM"},
@@ -7665,116 +8437,667 @@ var Tokens  = [
 
 
 
+//This file will likely change a lot! Very experimental!
+/*global Properties, ValidationTypes, ValidationError, PropertyValueIterator */
+var Validation = {
 
-parserlib.css = {
-Colors              :Colors,    
-Combinator          :Combinator,                
-Parser              :Parser,
-PropertyName        :PropertyName,
-PropertyValue       :PropertyValue,
-PropertyValuePart   :PropertyValuePart,
-MediaFeature        :MediaFeature,
-MediaQuery          :MediaQuery,
-Selector            :Selector,
-SelectorPart        :SelectorPart,
-SelectorSubPart     :SelectorSubPart,
-TokenStream         :TokenStream,
-Tokens              :Tokens
-};
-})();
+    validate: function(property, value){
+    
+        //normalize name
+        var name        = property.toString().toLowerCase(),
+            parts       = value.parts,
+            expression  = new PropertyValueIterator(value),
+            spec        = Properties[name],
+            part,
+            valid,            
+            j, count,
+            msg,
+            types,
+            last,
+            literals,
+            max, multi, group;
+            
+        if (!spec) {
+            if (name.indexOf("-") !== 0){    //vendor prefixed are ok
+                throw new ValidationError("Unknown property '" + property + "'.", property.line, property.col);
+            }
+        } else if (typeof spec != "number"){
+        
+            //initialization
+            if (typeof spec == "string"){
+                if (spec.indexOf("||") > -1) {
+                    this.groupProperty(spec, expression);
+                } else {
+                    this.singleProperty(spec, expression, 1);
+                }
 
-/**
- * Main CSSLint object.
- * @class CSSLint
- * @static
- * @extends parserlib.util.EventTarget
- */
-var CSSLint = (function(){
+            } else if (spec.multi) {
+                this.multiProperty(spec.multi, expression, spec.comma, spec.max || Infinity);
+            } else if (typeof spec == "function") {
+                spec(expression);
+            }
 
-    var rules      = [],
-        formatters = [],
-        api        = new parserlib.util.EventTarget();
+        }
+
+    },
+    
+    singleProperty: function(types, expression, max, partial) {
+
+        var result      = false,
+            value       = expression.value,
+            count       = 0,
+            part;
+         
+        while (expression.hasNext() && count < max) {
+            result = ValidationTypes.isAny(expression, types);
+            if (!result) {
+                break;
+            }
+            count++;
+        }
         
-    api.version = "@VERSION@";
+        if (!result) {
+            if (expression.hasNext() && !expression.isFirst()) {
+                part = expression.peek();
+                throw new ValidationError("Expected end of value but found '" + part + "'.", part.line, part.col);
+            } else {
+                 throw new ValidationError("Expected (" + types + ") but found '" + value + "'.", value.line, value.col);
+            }        
+        } else if (expression.hasNext()) {
+            part = expression.next();
+            throw new ValidationError("Expected end of value but found '" + part + "'.", part.line, part.col);
+        }          
+                 
+    },    
+    
+    multiProperty: function (types, expression, comma, max) {
 
-    //-------------------------------------------------------------------------
-    // Rule Management
-    //-------------------------------------------------------------------------
+        var result      = false,
+            value       = expression.value,
+            count       = 0,
+            sep         = false,
+            part;
+            
+        while(expression.hasNext() && !result && count < max) {
+            if (ValidationTypes.isAny(expression, types)) {
+                count++;
+                if (!expression.hasNext()) {
+                    result = true;
+
+                } else if (comma) {
+                    if (expression.peek() == ",") {
+                        part = expression.next();
+                    } else {
+                        break;
+                    }
+                }
+            } else {
+                break;
+
+            }
+        }
+        
+        if (!result) {
+            if (expression.hasNext() && !expression.isFirst()) {
+                part = expression.peek();
+                throw new ValidationError("Expected end of value but found '" + part + "'.", part.line, part.col);
+            } else {
+                part = expression.previous();
+                if (comma && part == ",") {
+                    throw new ValidationError("Expected end of value but found '" + part + "'.", part.line, part.col); 
+                } else {
+                    throw new ValidationError("Expected (" + types + ") but found '" + value + "'.", value.line, value.col);
+                }
+            }
+        
+        } else if (expression.hasNext()) {
+            part = expression.next();
+            throw new ValidationError("Expected end of value but found '" + part + "'.", part.line, part.col);
+        }  
+
+    },
+    
+    groupProperty: function (types, expression, comma) {
+
+        var result      = false,
+            value       = expression.value,
+            typeCount   = types.split("||").length,
+            groups      = { count: 0 },
+            partial     = false,
+            name,
+            part;
+            
+        while(expression.hasNext() && !result) {
+            name = ValidationTypes.isAnyOfGroup(expression, types);
+            if (name) {
+            
+                //no dupes
+                if (groups[name]) {
+                    break;
+                } else {
+                    groups[name] = 1;
+                    groups.count++;
+                    partial = true;
+                    
+                    if (groups.count == typeCount || !expression.hasNext()) {
+                        result = true;
+                    }
+                }
+            } else {
+                break;
+            }
+        }
+        
+        if (!result) {        
+            if (partial && expression.hasNext()) {
+                    part = expression.peek();
+                    throw new ValidationError("Expected end of value but found '" + part + "'.", part.line, part.col);
+            } else {
+                throw new ValidationError("Expected (" + types + ") but found '" + value + "'.", value.line, value.col);
+            }
+        } else if (expression.hasNext()) {
+            part = expression.next();
+            throw new ValidationError("Expected end of value but found '" + part + "'.", part.line, part.col);
+        }           
+    }
+
+    
+
+};
+/**
+ * Type to use when a validation error occurs.
+ * @class ValidationError
+ * @namespace parserlib.util
+ * @constructor
+ * @param {String} message The error message.
+ * @param {int} line The line at which the error occurred.
+ * @param {int} col The column at which the error occurred.
+ */
+function ValidationError(message, line, col){
 
     /**
-     * Adds a new rule to the engine.
-     * @param {Object} rule The rule to add.
-     * @method addRule
+     * The column at which the error occurred.
+     * @type int
+     * @property col
      */
-    api.addRule = function(rule){
-        rules.push(rule);
-        rules[rule.id] = rule;
-    };
+    this.col = col;
 
     /**
-     * Clears all rule from the engine.
-     * @method clearRules
+     * The line at which the error occurred.
+     * @type int
+     * @property line
      */
-    api.clearRules = function(){
-        rules = [];
-    };
+    this.line = line;
 
-    //-------------------------------------------------------------------------
-    // Formatters
-    //-------------------------------------------------------------------------
+    /**
+     * The text representation of the unit.
+     * @type String
+     * @property text
+     */
+    this.message = message;
+
+}
 
+//inherit from Error
+ValidationError.prototype = new Error();
+//This file will likely change a lot! Very experimental!
+/*global Properties, Validation, ValidationError, PropertyValueIterator, console*/
+var ValidationTypes = {
+
+    isLiteral: function (part, literals) {
+        var text = part.text.toString().toLowerCase(),
+            args = literals.split(" | "),
+            i, len, found = false;
+        
+        for (i=0,len=args.length; i < len && !found; i++){
+            if (text == args[i]){
+                found = true;
+            }
+        }
+        
+        return found;    
+    },
+    
+    isSimple: function(type) {
+        return !!this.simple[type];
+    },
+    
+    isComplex: function(type) {
+        return !!this.complex[type];
+    },
+    
     /**
-     * Adds a new formatter to the engine.
-     * @param {Object} formatter The formatter to add.
-     * @method addFormatter
+     * Determines if the next part(s) of the given expression
+     * are any of the given types.
      */
-    api.addFormatter = function(formatter) {
-        // formatters.push(formatter);
-        formatters[formatter.id] = formatter;
-    };
+    isAny: function (expression, types) {
+        var args = types.split(" | "),
+            i, len, found = false;
+        
+        for (i=0,len=args.length; i < len && !found && expression.hasNext(); i++){
+            found = this.isType(expression, args[i]);
+        }
+        
+        return found;    
+    },
     
     /**
-     * Retrieves a formatter for use.
-     * @param {String} formatId The name of the format to retrieve.
-     * @return {Object} The formatter or undefined.
-     * @method getFormatter
+     * Determines if the next part(s) of the given expresion
+     * are one of a group.
      */
-    api.getFormatter = function(formatId){
-        return formatters[formatId];
-    };
+    isAnyOfGroup: function(expression, types) {
+        var args = types.split(" || "),
+            i, len, found = false;
+        
+        for (i=0,len=args.length; i < len && !found; i++){
+            found = this.isType(expression, args[i]);
+        }
+        
+        return found ? args[i-1] : false;
+    },
     
     /**
-     * Formats the results in a particular format for a single file.
-     * @param {Object} result The results returned from CSSLint.verify().
-     * @param {String} filename The filename for which the results apply.
-     * @param {String} formatId The name of the formatter to use.
-     * @return {String} A formatted string for the results.
-     * @method format
+     * Determines if the next part(s) of the given expression
+     * are of a given type.
      */
-    api.format = function(results, filename, formatId) {
-        var formatter = this.getFormatter(formatId),
-            result = null;
+    isType: function (expression, type) {
+        var part = expression.peek(),
+            result = false;
             
-        if (formatter){
-            result = formatter.startFormat();
-            result += formatter.formatResults(results, filename);
-            result += formatter.endFormat();
+        if (type.charAt(0) != "<") {
+            result = this.isLiteral(part, type);
+            if (result) {
+                expression.next();
+            }
+        } else if (this.simple[type]) {
+            result = this.simple[type](part);
+            if (result) {
+                expression.next();
+            }
+        } else {
+            result = this.complex[type](expression);
         }
         
         return result;
-    }    
+    },
     
-    /**
-     * Indicates if the given format is supported.
-     * @param {String} formatId The ID of the format to check.
-     * @return {Boolean} True if the format exists, false if not.
-     * @method hasFormat
-     */
-    api.hasFormat = function(formatId){
-        return formatters.hasOwnProperty(formatId);
-    };
+    
+    
+    simple: {
 
-    //-------------------------------------------------------------------------
+        "<absolute-size>": function(part){
+            return ValidationTypes.isLiteral(part, "xx-small | x-small | small | medium | large | x-large | xx-large");
+        },
+        
+        "<attachment>": function(part){
+            return ValidationTypes.isLiteral(part, "scroll | fixed | local");
+        },
+        
+        "<attr>": function(part){
+            return part.type == "function" && part.name == "attr";
+        },
+                
+        "<bg-image>": function(part){
+            return this["<image>"](part) || this["<gradient>"](part) ||  part == "none";
+        },        
+        
+        "<gradient>": function(part) {
+            return part.type == "function" && /^(?:\-(?:ms|moz|o|webkit)\-)?(?:repeating\-)?(?:radial|linear)\-gradient/i.test(part);
+        },
+        
+        "<box>": function(part){
+            return ValidationTypes.isLiteral(part, "padding-box | border-box | content-box");
+        },
+        
+        "<content>": function(part){
+            return part.type == "function" && part.name == "content";
+        },        
+        
+        "<relative-size>": function(part){
+            return ValidationTypes.isLiteral(part, "smaller | larger");
+        },
+        
+        //any identifier
+        "<ident>": function(part){
+            return part.type == "identifier";
+        },
+        
+        "<length>": function(part){
+            return part.type == "length" || part.type == "number" || part.type == "integer" || part == "0";
+        },
+        
+        "<color>": function(part){
+            return part.type == "color" || part == "transparent";
+        },
+        
+        "<number>": function(part){
+            return part.type == "number" || this["<integer>"](part);
+        },
+        
+        "<integer>": function(part){
+            return part.type == "integer";
+        },
+        
+        "<line>": function(part){
+            return part.type == "integer";
+        },
+        
+        "<angle>": function(part){
+            return part.type == "angle";
+        },        
+        
+        "<uri>": function(part){
+            return part.type == "uri";
+        },
+        
+        "<image>": function(part){
+            return this["<uri>"](part);
+        },
+        
+        "<percentage>": function(part){
+            return part.type == "percentage" || part == "0";
+        },
+
+        "<border-width>": function(part){
+            return this["<length>"](part) || ValidationTypes.isLiteral(part, "thin | medium | thick");
+        },
+        
+        "<border-style>": function(part){
+            return ValidationTypes.isLiteral(part, "none | hidden | dotted | dashed | solid | double | groove | ridge | inset | outset");
+        },
+        
+        "<margin-width>": function(part){
+            return this["<length>"](part) || this["<percentage>"](part) || ValidationTypes.isLiteral(part, "auto");
+        },
+        
+        "<padding-width>": function(part){
+            return this["<length>"](part) || this["<percentage>"](part);
+        },
+        
+        "<shape>": function(part){
+            return part.type == "function" && (part.name == "rect" || part.name == "inset-rect");
+        },
+        
+        "<time>": function(part) {
+            return part.type == "time";
+        }
+    },
+    
+    complex: {
+
+        "<bg-position>": function(expression){
+            var types   = this,
+                result  = false,
+                numeric = "<percentage> | <length>",
+                xDir    = "left | center | right",
+                yDir    = "top | center | bottom",
+                part,
+                i, len;
+            
+                
+            if (ValidationTypes.isAny(expression, "top | bottom")) {
+                result = true;
+            } else {
+                
+                //must be two-part
+                if (ValidationTypes.isAny(expression, numeric)){
+                    if (expression.hasNext()){
+                        result = ValidationTypes.isAny(expression, numeric + " | " + yDir);
+                    }
+                } else if (ValidationTypes.isAny(expression, xDir)){
+                    if (expression.hasNext()){
+                        
+                        //two- or three-part
+                        if (ValidationTypes.isAny(expression, yDir)){
+                            result = true;
+                      
+                            ValidationTypes.isAny(expression, numeric);
+                            
+                        } else if (ValidationTypes.isAny(expression, numeric)){
+                        
+                            //could also be two-part, so check the next part
+                            if (ValidationTypes.isAny(expression, yDir)){                                    
+                                ValidationTypes.isAny(expression, numeric);                               
+                            }
+                            
+                            result = true;
+                        }
+                    }
+                }                                 
+            }            
+
+            
+            return result;
+        },
+
+        "<bg-size>": function(expression){
+            //<bg-size> = [ <length> | <percentage> | auto ]{1,2} | cover | contain
+            var types   = this,
+                result  = false,
+                numeric = "<percentage> | <length> | auto",
+                part,
+                i, len;      
+      
+            if (ValidationTypes.isAny(expression, "cover | contain")) {
+                result = true;
+            } else if (ValidationTypes.isAny(expression, numeric)) {
+                result = true;                
+                ValidationTypes.isAny(expression, numeric);
+            }
+            
+            return result;
+        },
+        
+        "<repeat-style>": function(expression){
+            //repeat-x | repeat-y | [repeat | space | round | no-repeat]{1,2}
+            var result  = false,
+                values  = "repeat | space | round | no-repeat",
+                part;
+            
+            if (expression.hasNext()){
+                part = expression.next();
+                
+                if (ValidationTypes.isLiteral(part, "repeat-x | repeat-y")) {
+                    result = true;                    
+                } else if (ValidationTypes.isLiteral(part, values)) {
+                    result = true;
+
+                    if (expression.hasNext() && ValidationTypes.isLiteral(expression.peek(), values)) {
+                        expression.next();
+                    }
+                }
+            }
+            
+            return result;
+            
+        },
+        
+        "<shadow>": function(expression) {
+            //inset? && [ <length>{2,4} && <color>? ]
+            var result  = false,
+                count   = 0,
+                inset   = false,
+                color   = false,
+                part;
+                
+            if (expression.hasNext()) {            
+                
+                if (ValidationTypes.isAny(expression, "inset")){
+                    inset = true;
+                }
+                
+                if (ValidationTypes.isAny(expression, "<color>")) {
+                    color = true;
+                }                
+                
+                while (ValidationTypes.isAny(expression, "<length>") && count < 4) {
+                    count++;
+                }
+                
+                
+                if (expression.hasNext()) {
+                    if (!color) {
+                        ValidationTypes.isAny(expression, "<color>");
+                    }
+                    
+                    if (!inset) {
+                        ValidationTypes.isAny(expression, "inset");
+                    }
+
+                }
+                
+                result = (count >= 2 && count <= 4);
+            
+            }
+            
+            return result;
+        },
+        
+        "<x-one-radius>": function(expression) {
+            //[ <length> | <percentage> ] [ <length> | <percentage> ]?
+            var result  = false,
+                count   = 0,
+                numeric = "<length> | <percentage>",
+                part;
+                
+            if (ValidationTypes.isAny(expression, numeric)){
+                result = true;
+                
+                ValidationTypes.isAny(expression, numeric);
+            }                
+            
+            return result;
+        }
+    }
+};
+
+
+parserlib.css = {
+Colors              :Colors,    
+Combinator          :Combinator,                
+Parser              :Parser,
+PropertyName        :PropertyName,
+PropertyValue       :PropertyValue,
+PropertyValuePart   :PropertyValuePart,
+MediaFeature        :MediaFeature,
+MediaQuery          :MediaQuery,
+Selector            :Selector,
+SelectorPart        :SelectorPart,
+SelectorSubPart     :SelectorSubPart,
+Specificity         :Specificity,
+TokenStream         :TokenStream,
+Tokens              :Tokens,
+ValidationError     :ValidationError
+};
+})();
+
+
+
+/**
+ * Main CSSLint object.
+ * @class CSSLint
+ * @static
+ * @extends parserlib.util.EventTarget
+ */
+/*global parserlib, Reporter*/
+var CSSLint = (function(){
+
+    var rules      = [],
+        formatters = [],
+        api        = new parserlib.util.EventTarget();
+        
+    api.version = "0.9.7";
+
+    //-------------------------------------------------------------------------
+    // Rule Management
+    //-------------------------------------------------------------------------
+
+    /**
+     * Adds a new rule to the engine.
+     * @param {Object} rule The rule to add.
+     * @method addRule
+     */
+    api.addRule = function(rule){
+        rules.push(rule);
+        rules[rule.id] = rule;
+    };
+
+    /**
+     * Clears all rule from the engine.
+     * @method clearRules
+     */
+    api.clearRules = function(){
+        rules = [];
+    };
+    
+    /**
+     * Returns the rule objects.
+     * @return An array of rule objects.
+     * @method getRules
+     */
+    api.getRules = function(){
+        return [].concat(rules).sort(function(a,b){ 
+            return a.id > b.id ? 1 : 0;
+        });
+    };
+
+    //-------------------------------------------------------------------------
+    // Formatters
+    //-------------------------------------------------------------------------
+
+    /**
+     * Adds a new formatter to the engine.
+     * @param {Object} formatter The formatter to add.
+     * @method addFormatter
+     */
+    api.addFormatter = function(formatter) {
+        // formatters.push(formatter);
+        formatters[formatter.id] = formatter;
+    };
+    
+    /**
+     * Retrieves a formatter for use.
+     * @param {String} formatId The name of the format to retrieve.
+     * @return {Object} The formatter or undefined.
+     * @method getFormatter
+     */
+    api.getFormatter = function(formatId){
+        return formatters[formatId];
+    };
+    
+    /**
+     * Formats the results in a particular format for a single file.
+     * @param {Object} result The results returned from CSSLint.verify().
+     * @param {String} filename The filename for which the results apply.
+     * @param {String} formatId The name of the formatter to use.
+     * @param {Object} options (Optional) for special output handling.
+     * @return {String} A formatted string for the results.
+     * @method format
+     */
+    api.format = function(results, filename, formatId, options) {
+        var formatter = this.getFormatter(formatId),
+            result = null;
+            
+        if (formatter){
+            result = formatter.startFormat();
+            result += formatter.formatResults(results, filename, options || {});
+            result += formatter.endFormat();
+        }
+        
+        return result;
+    };
+    
+    /**
+     * Indicates if the given format is supported.
+     * @param {String} formatId The ID of the format to check.
+     * @return {Boolean} True if the format exists, false if not.
+     * @method hasFormat
+     */
+    api.hasFormat = function(formatId){
+        return formatters.hasOwnProperty(formatId);
+    };
+
+    //-------------------------------------------------------------------------
     // Verification
     //-------------------------------------------------------------------------
 
@@ -7782,7 +9105,8 @@ var CSSLint = (function(){
      * Starts the verification process for the given CSS text.
      * @param {String} text The CSS text to verify.
      * @param {Object} ruleset (Optional) List of rules to apply. If null, then
-     *      all rules are used.
+     *      all rules are used. If a rule has a value of 1 then it's a warning,
+     *      a value of 2 means it's an error.
      * @return {Object} Results of the verification.
      * @method verify
      */
@@ -7792,38 +9116,55 @@ var CSSLint = (function(){
             len     = rules.length,
             reporter,
             lines,
+            report,
             parser = new parserlib.css.Parser({ starHack: true, ieFilters: true,
                                                 underscoreHack: true, strict: false });
 
-        lines = text.split(/\n\r?/g);
-        reporter = new Reporter(lines);
-
+        lines = text.replace(/\n\r?/g, "$split$").split('$split$');
+        
         if (!ruleset){
+            ruleset = {};
             while (i < len){
-                rules[i++].init(parser, reporter);
+                ruleset[rules[i++].id] = 1;    //by default, everything is a warning
             }
-        } else {
-            ruleset.errors = 1;       //always report parsing errors
-            for (i in ruleset){
-                if(ruleset.hasOwnProperty(i)){
-                    if (rules[i]){
-                        rules[i].init(parser, reporter);
-                    }
+        }
+        
+        reporter = new Reporter(lines, ruleset);
+        
+        ruleset.errors = 2;       //always report parsing errors as errors
+        for (i in ruleset){
+            if(ruleset.hasOwnProperty(i)){
+                if (rules[i]){
+                    rules[i].init(parser, reporter);
                 }
             }
         }
 
+
         //capture most horrible error type
         try {
             parser.parse(text);
         } catch (ex) {
-            reporter.error("Fatal error, cannot continue: " + ex.message, ex.line, ex.col);
+            reporter.error("Fatal error, cannot continue: " + ex.message, ex.line, ex.col, {});
         }
 
-        return {
+        report = {
             messages    : reporter.messages,
             stats       : reporter.stats
         };
+        
+        //sort by line numbers, rollups at the bottom
+        report.messages.sort(function (a, b){
+            if (a.rollup && !b.rollup){
+                return 1;
+            } else if (!a.rollup && b.rollup){
+                return -1;
+            } else {
+                return a.line - b.line;
+            }
+        });        
+        
+        return report;
     };
 
     //-------------------------------------------------------------------------
@@ -7833,14 +9174,18 @@ var CSSLint = (function(){
     return api;
 
 })();
+
+/*global CSSLint*/
 /**
  * An instance of Report is used to report results of the
  * verification back to the main API.
  * @class Reporter
  * @constructor
  * @param {String[]} lines The text lines of the source.
+ * @param {Object} ruleset The set of rules to work with, including if
+ *      they are errors or warnings.
  */
-function Reporter(lines){
+function Reporter(lines, ruleset){
 
     /**
      * List of messages being reported.
@@ -7863,6 +9208,14 @@ function Reporter(lines){
      * @type String[]
      */
     this.lines = lines;
+    
+    /**
+     * Information about the rules. Used to determine whether an issue is an
+     * error or warning.
+     * @property ruleset
+     * @type Object
+     */
+    this.ruleset = ruleset;
 }
 
 Reporter.prototype = {
@@ -7885,7 +9238,7 @@ Reporter.prototype = {
             col     : col,
             message : message,
             evidence: this.lines[line-1],
-            rule    : rule
+            rule    : rule || {}
         });
     },
 
@@ -7896,10 +9249,23 @@ Reporter.prototype = {
      * @param {int} col The column number.
      * @param {Object} rule The rule this message relates to.
      * @method warn
+     * @deprecated Use report instead.
      */
     warn: function(message, line, col, rule){
+        this.report(message, line, col, rule);
+    },
+
+    /**
+     * Report an issue.
+     * @param {String} message The message to store.
+     * @param {int} line The line number.
+     * @param {int} col The column number.
+     * @param {Object} rule The rule this message relates to.
+     * @method report
+     */
+    report: function(message, line, col, rule){
         this.messages.push({
-            type    : "warning",
+            type    : this.ruleset[rule.id] == 2 ? "error" : "warning",
             line    : line,
             col     : col,
             message : message,
@@ -7967,48 +9333,72 @@ Reporter.prototype = {
         this.stats[name] = value;
     }
 };
-/*
- * Utility functions that make life easier.
- */
+
+//expose for testing purposes
+CSSLint._Reporter = Reporter;
+
+/*global CSSLint*/
 
 /*
- * Adds all properties from supplier onto receiver,
- * overwriting if the same name already exists on
- * reciever.
- * @param {Object} The object to receive the properties.
- * @param {Object} The object to provide the properties.
- * @return {Object} The receiver
+ * Utility functions that make life easier.
  */
-function mix(reciever, supplier){
-    var prop;
+CSSLint.Util = {
+    /*
+     * Adds all properties from supplier onto receiver,
+     * overwriting if the same name already exists on
+     * reciever.
+     * @param {Object} The object to receive the properties.
+     * @param {Object} The object to provide the properties.
+     * @return {Object} The receiver
+     */
+    mix: function(receiver, supplier){
+        var prop;
 
-    for (prop in supplier){
-        if (supplier.hasOwnProperty(prop)){
-            receiver[prop] = supplier[prop];
+        for (prop in supplier){
+            if (supplier.hasOwnProperty(prop)){
+                receiver[prop] = supplier[prop];
+            }
         }
-    }
 
-    return prop;
-}
+        return prop;
+    },
+
+    /*
+     * Polyfill for array indexOf() method.
+     * @param {Array} values The array to search.
+     * @param {Variant} value The value to search for.
+     * @return {int} The index of the value if found, -1 if not.
+     */
+    indexOf: function(values, value){
+        if (values.indexOf){
+            return values.indexOf(value);
+        } else {
+            for (var i=0, len=values.length; i < len; i++){
+                if (values[i] === value){
+                    return i;
+                }
+            }
+            return -1;
+        }
+    },
 
-/*
- * Polyfill for array indexOf() method.
- * @param {Array} values The array to search.
- * @param {Variant} value The value to search for.
- * @return {int} The index of the value if found, -1 if not.
- */
-function indexOf(values, value){
-    if (values.indexOf){
-        return values.indexOf(value);
-    } else {
-        for (var i=0, len=values.length; i < len; i++){
-            if (values[i] === value){
-                return i;
+    /*
+     * Polyfill for array forEach() method.
+     * @param {Array} values The array to operate on.
+     * @param {Function} func The function to call on each item.
+     * @return {void}
+     */
+    forEach: function(values, func) {
+        if (values.forEach){
+            return values.forEach(func);
+        } else {
+            for (var i=0, len=values.length; i < len; i++){
+                func(values[i], i, values);
             }
         }
-        return -1;
     }
-}
+};
+/*global CSSLint*/
 /*
  * Rule: Don't use adjoining classes (.foo.bar).
  */
@@ -8016,7 +9406,7 @@ CSSLint.addRule({
 
     //rule information
     id: "adjoining-classes",
-    name: "Adjoining Classes",
+    name: "Disallow adjoining classes",
     desc: "Don't use adjoining classes.",
     browsers: "IE6",
 
@@ -8035,7 +9425,7 @@ CSSLint.addRule({
                 selector = selectors[i];
                 for (j=0; j < selector.parts.length; j++){
                     part = selector.parts[j];
-                    if (part instanceof parserlib.css.SelectorPart){
+                    if (part.type == parser.SELECTOR_PART_TYPE){
                         classCount = 0;
                         for (k=0; k < part.modifiers.length; k++){
                             modifier = part.modifiers[k];
@@ -8043,7 +9433,7 @@ CSSLint.addRule({
                                 classCount++;
                             }
                             if (classCount > 1){
-                                reporter.warn("Don't use adjoining classes.", part.line, part.col, rule);
+                                reporter.report("Don't use adjoining classes.", part.line, part.col, rule);
                             }
                         }
                     }
@@ -8053,6 +9443,8 @@ CSSLint.addRule({
     }
 
 });
+/*global CSSLint*/
+
 /*
  * Rule: Don't use width or height when using padding or border. 
  */
@@ -8060,7 +9452,7 @@ CSSLint.addRule({
 
     //rule information
     id: "box-model",
-    name: "Box Model",
+    name: "Beware of broken box size",
     desc: "Don't use width or height when using padding or border.",
     browsers: "All",
 
@@ -8085,56 +9477,90 @@ CSSLint.addRule({
             },
             properties;
 
-        parser.addListener("startrule", function(){
-            properties = {
-            };
-        });
-
-        parser.addListener("property", function(event){
-            var name = event.property.text.toLowerCase();
-            
-            if (heightProperties[name] || widthProperties[name]){
-                if (!/^0\S*$/.test(event.value) && !(name == "border" && event.value == "none")){
-                    properties[name] = { line: event.property.line, col: event.property.col, value: event.value };
-                }
-            } else {
-                if (name == "width" || name == "height"){
-                    properties[name] = 1;
-                }
-            }
-            
-        });
+        function startRule(){
+            properties = {};
+        }
 
-        parser.addListener("endrule", function(){
+        function endRule(){
             var prop;
-            if (properties["height"]){
+            if (properties.height){
                 for (prop in heightProperties){
                     if (heightProperties.hasOwnProperty(prop) && properties[prop]){
                     
                         //special case for padding
-                        if (prop == "padding" && properties[prop].value.parts.length == 2 && properties[prop].value.parts[0].value == 0){
-                            //noop
-                        } else {
-                            reporter.warn("Broken box model: using height with " + prop + ".", properties[prop].line, properties[prop].col, rule);
+                        if (!(prop == "padding" && properties[prop].value.parts.length === 2 && properties[prop].value.parts[0].value === 0)){
+                            reporter.report("Using height with " + prop + " can sometimes make elements larger than you expect.", properties[prop].line, properties[prop].col, rule);
                         }
                     }
                 }
             }
 
-            if (properties["width"]){
+            if (properties.width){
                 for (prop in widthProperties){
                     if (widthProperties.hasOwnProperty(prop) && properties[prop]){
 
-                        if (prop == "padding" && properties[prop].value.parts.length == 2 && properties[prop].value.parts[1].value == 0){
-                            //noop
-                        } else {
-                            reporter.warn("Broken box model: using width with " + prop + ".", properties[prop].line, properties[prop].col, rule);
+                        if (!(prop == "padding" && properties[prop].value.parts.length === 2 && properties[prop].value.parts[1].value === 0)){
+                            reporter.report("Using width with " + prop + " can sometimes make elements larger than you expect.", properties[prop].line, properties[prop].col, rule);
                         }
                     }
                 }
-            }
+            }        
+        }
+
+        parser.addListener("startrule", startRule);
+        parser.addListener("startfontface", startRule);
+        parser.addListener("startpage", startRule);
+        parser.addListener("startpagemargin", startRule);
+        parser.addListener("startkeyframerule", startRule); 
 
+        parser.addListener("property", function(event){
+            var name = event.property.text.toLowerCase();
+            
+            if (heightProperties[name] || widthProperties[name]){
+                if (!/^0\S*$/.test(event.value) && !(name == "border" && event.value == "none")){
+                    properties[name] = { line: event.property.line, col: event.property.col, value: event.value };
+                }
+            } else {
+                if (name == "width" || name == "height"){
+                    properties[name] = 1;
+                }
+            }
+            
         });
+
+        parser.addListener("endrule", endRule);
+        parser.addListener("endfontface", endRule);
+        parser.addListener("endpage", endRule);
+        parser.addListener("endpagemargin", endRule);
+        parser.addListener("endkeyframerule", endRule);         
+    }
+
+});
+/*global CSSLint*/
+
+/*
+ * Rule: box-sizing doesn't work in IE6 and IE7.
+ */
+CSSLint.addRule({
+
+    //rule information
+    id: "box-sizing",
+    name: "Disallow use of box-sizing",
+    desc: "The box-sizing properties isn't supported in IE6 and IE7.",
+    browsers: "IE6, IE7",
+    tags: ["Compatibility"],
+
+    //initialization
+    init: function(parser, reporter){
+        var rule = this;
+
+        parser.addListener("property", function(event){
+            var name = event.property.text.toLowerCase();
+   
+            if (name == "box-sizing"){
+                reporter.report("The box-sizing property isn't supported in IE6 and IE7.", event.line, event.col, rule);
+            }
+        });       
     }
 
 });
@@ -8147,7 +9573,7 @@ CSSLint.addRule({
 
     //rule information
     id: "compatible-vendor-prefixes",
-    name: "Compatible Vendor Prefixes",
+    name: "Require compatible vendor prefixes",
     desc: "Include all compatible vendor prefixes to reach a wider range of users.",
     browsers: "All",
 
@@ -8166,15 +9592,15 @@ CSSLint.addRule({
 
         // See http://peter.sh/experiments/vendor-prefixed-css-property-overview/ for details
         compatiblePrefixes = {
-            "animation"                  : "webkit moz",
-            "animation-delay"            : "webkit moz",
-            "animation-direction"        : "webkit moz",
-            "animation-duration"         : "webkit moz",
-            "animation-fill-mode"        : "webkit moz",
-            "animation-iteration-count"  : "webkit moz",
-            "animation-name"             : "webkit moz",
-            "animation-play-state"       : "webkit moz",
-            "animation-timing-function"  : "webkit moz",
+            "animation"                  : "webkit moz ms",
+            "animation-delay"            : "webkit moz ms",
+            "animation-direction"        : "webkit moz ms",
+            "animation-duration"         : "webkit moz ms",
+            "animation-fill-mode"        : "webkit moz ms",
+            "animation-iteration-count"  : "webkit moz ms",
+            "animation-name"             : "webkit moz ms",
+            "animation-play-state"       : "webkit moz ms",
+            "animation-timing-function"  : "webkit moz ms",
             "appearance"                 : "webkit moz",
             "border-end"                 : "webkit moz",
             "border-end-color"           : "webkit moz",
@@ -8195,13 +9621,13 @@ CSSLint.addRule({
             "box-pack"                   : "webkit moz ms",
             "box-sizing"                 : "webkit moz",
             "box-shadow"                 : "webkit moz",
-            "column-count"               : "webkit moz",
-            "column-gap"                 : "webkit moz",
-            "column-rule"                : "webkit moz",
-            "column-rule-color"          : "webkit moz",
-            "column-rule-style"          : "webkit moz",
-            "column-rule-width"          : "webkit moz",
-            "column-width"               : "webkit moz",
+            "column-count"               : "webkit moz ms",
+            "column-gap"                 : "webkit moz ms",
+            "column-rule"                : "webkit moz ms",
+            "column-rule-color"          : "webkit moz ms",
+            "column-rule-style"          : "webkit moz ms",
+            "column-rule-width"          : "webkit moz ms",
+            "column-width"               : "webkit moz ms",
             "hyphens"                    : "epub moz",
             "line-break"                 : "webkit ms",
             "margin-end"                 : "webkit moz",
@@ -8214,17 +9640,18 @@ CSSLint.addRule({
             "text-size-adjust"           : "webkit ms",
             "transform"                  : "webkit moz ms o",
             "transform-origin"           : "webkit moz ms o",
-            "transition"                 : "webkit moz o",
-            "transition-delay"           : "webkit moz o",
-            "transition-duration"        : "webkit moz o",
-            "transition-property"        : "webkit moz o",
-            "transition-timing-function" : "webkit moz o",
+            "transition"                 : "webkit moz o ms",
+            "transition-delay"           : "webkit moz o ms",
+            "transition-duration"        : "webkit moz o ms",
+            "transition-property"        : "webkit moz o ms",
+            "transition-timing-function" : "webkit moz o ms",
             "user-modify"                : "webkit moz",
-            "user-select"                : "webkit moz",
+            "user-select"                : "webkit moz ms",
             "word-break"                 : "epub ms",
             "writing-mode"               : "epub ms"
         };
 
+
         for (prop in compatiblePrefixes) {
             if (compatiblePrefixes.hasOwnProperty(prop)) {
                 variations = [];
@@ -8241,8 +9668,8 @@ CSSLint.addRule({
         });
 
         parser.addListener("property", function (event) {
-            var name = event.property.text;
-            if (applyTo.indexOf(name) > -1) {
+            var name = event.property;
+            if (CSSLint.Util.indexOf(applyTo, name.text) > -1) {
                 properties.push(name);
             }
         });
@@ -8270,15 +9697,17 @@ CSSLint.addRule({
                 for (prop in compatiblePrefixes) {
                     if (compatiblePrefixes.hasOwnProperty(prop)) {
                         variations = compatiblePrefixes[prop];
-                        if (variations.indexOf(name) > -1) {
-                            if (propertyGroups[prop] === undefined) {
+                        if (CSSLint.Util.indexOf(variations, name.text) > -1) {
+                            if (!propertyGroups[prop]) {
                                 propertyGroups[prop] = {
                                     full : variations.slice(0),
-                                    actual : []
+                                    actual : [],
+                                    actualNodes: []
                                 };
                             }
-                            if (propertyGroups[prop].actual.indexOf(name) === -1) {
-                                propertyGroups[prop].actual.push(name);
+                            if (CSSLint.Util.indexOf(propertyGroups[prop].actual, name.text) === -1) {
+                                propertyGroups[prop].actual.push(name.text);
+                                propertyGroups[prop].actualNodes.push(name);
                             }
                         }
                     }
@@ -8294,9 +9723,9 @@ CSSLint.addRule({
                     if (full.length > actual.length) {
                         for (i = 0, len = full.length; i < len; i++) {
                             item = full[i];
-                            if (actual.indexOf(item) === -1) {
+                            if (CSSLint.Util.indexOf(actual, item) === -1) {
                                 propertiesSpecified = (actual.length === 1) ? actual[0] : (actual.length == 2) ? actual.join(" and ") : actual.join(", ");
-                                reporter.warn("The property " + item + " is compatible with " + propertiesSpecified + " and should be included as well.", event.selectors[0].line, event.selectors[0].col, rule); 
+                                reporter.report("The property " + item + " is compatible with " + propertiesSpecified + " and should be included as well.", value.actualNodes[0].line, value.actualNodes[0].col, rule); 
                             }
                         }
 
@@ -8313,11 +9742,12 @@ CSSLint.addRule({
  * - vertical-align should not be used with block
  * - margin, float should not be used with table-*
  */
+/*global CSSLint*/
 CSSLint.addRule({
 
     //rule information
     id: "display-property-grouping",
-    name: "Display Property Grouping",
+    name: "Require properties appropriate for display",
     desc: "Certain properties shouldn't be used with certain display property values.",
     browsers: "All",
 
@@ -8344,19 +9774,19 @@ CSSLint.addRule({
             },
             properties;
 
-        parser.addListener("startrule", function(){
-            properties = {};
-        });
-
-        parser.addListener("property", function(event){
-            var name = event.property.text.toLowerCase();
-
-            if (propertiesToCheck[name]){
-                properties[name] = { value: event.value.text, line: event.property.line, col: event.property.col };                    
+        function reportProperty(name, display, msg){
+            if (properties[name]){
+                if (typeof propertiesToCheck[name] != "string" || properties[name].value.toLowerCase() != propertiesToCheck[name]){
+                    reporter.report(msg || name + " can't be used with display: " + display + ".", properties[name].line, properties[name].col, rule);
+                }
             }
-        });
+        }
+        
+        function startRule(){
+            properties = {};
+        }
 
-        parser.addListener("endrule", function(){
+        function endRule(){
 
             var display = properties.display ? properties.display.value : null;
             if (display){
@@ -8384,7 +9814,7 @@ CSSLint.addRule({
 
                     default:
                         //margin, float should not be used with table
-                        if (display.indexOf("table-") == 0){
+                        if (display.indexOf("table-") === 0){
                             reportProperty("margin", display);
                             reportProperty("margin-left", display);
                             reportProperty("margin-right", display);
@@ -8397,28 +9827,78 @@ CSSLint.addRule({
                 }
             }
           
+        }
+
+        parser.addListener("startrule", startRule);
+        parser.addListener("startfontface", startRule);
+        parser.addListener("startkeyframerule", startRule);
+        parser.addListener("startpagemargin", startRule);
+        parser.addListener("startpage", startRule);
+
+        parser.addListener("property", function(event){
+            var name = event.property.text.toLowerCase();
+
+            if (propertiesToCheck[name]){
+                properties[name] = { value: event.value.text, line: event.property.line, col: event.property.col };                    
+            }
         });
 
+        parser.addListener("endrule", endRule);
+        parser.addListener("endfontface", endRule);
+        parser.addListener("endkeyframerule", endRule);
+        parser.addListener("endpagemargin", endRule);
+        parser.addListener("endpage", endRule);
+
+    }
 
-        function reportProperty(name, display, msg){
-            if (properties[name]){
-                if (!(typeof propertiesToCheck[name] == "string") || properties[name].value.toLowerCase() != propertiesToCheck[name]){
-                    reporter.warn(msg || name + " can't be used with display: " + display + ".", properties[name].line, properties[name].col, rule);
+});
+/*
+ * Rule: Disallow duplicate background-images (using url).
+ */
+/*global CSSLint*/
+CSSLint.addRule({
+
+    //rule information
+    id: "duplicate-background-images",
+    name: "Disallow duplicate background images",
+    desc: "Every background-image should be unique. Use a common class for e.g. sprites.",
+    browsers: "All",
+
+    //initialization
+    init: function(parser, reporter){
+        var rule = this,
+            stack = {};
+
+        parser.addListener("property", function(event){
+            var name = event.property.text,
+                value = event.value,
+                i, len;
+
+            if (name.match(/background/i)) {
+                for (i=0, len=value.parts.length; i < len; i++) {
+                    if (value.parts[i].type == 'uri') {
+                        if (typeof stack[value.parts[i].uri] === 'undefined') {
+                            stack[value.parts[i].uri] = event;
+                        }
+                        else {
+                            reporter.report("Background image '" + value.parts[i].uri + "' was used multiple times, first declared at line " + stack[value.parts[i].uri].line + ", col " + stack[value.parts[i].uri].col + ".", event.line, event.col, rule);
+                        }
+                    }
                 }
             }
-        }
+        });
     }
-
 });
 /*
  * Rule: Duplicate properties must appear one after the other. If an already-defined
  * property appears somewhere else in the rule, then it's likely an error.
  */
+/*global CSSLint*/
 CSSLint.addRule({
 
     //rule information
     id: "duplicate-properties",
-    name: "Duplicate Properties",
+    name: "Disallow duplicate properties",
     desc: "Duplicate properties must appear one after the other.",
     browsers: "All",
 
@@ -8435,13 +9915,15 @@ CSSLint.addRule({
         parser.addListener("startrule", startRule);
         parser.addListener("startfontface", startRule);
         parser.addListener("startpage", startRule);
+        parser.addListener("startpagemargin", startRule);
+        parser.addListener("startkeyframerule", startRule);        
         
         parser.addListener("property", function(event){
             var property = event.property,
                 name = property.text.toLowerCase();
             
             if (properties[name] && (lastProperty != name || properties[name] == event.value.text)){
-                reporter.warn("Duplicate property '" + event.property + "' found.", event.line, event.col, rule);
+                reporter.report("Duplicate property '" + event.property + "' found.", event.line, event.col, rule);
             }
             
             properties[name] = event.value.text;
@@ -8456,11 +9938,12 @@ CSSLint.addRule({
 /*
  * Rule: Style rules without any properties defined should be removed.
  */
+/*global CSSLint*/
 CSSLint.addRule({
 
     //rule information
     id: "empty-rules",
-    name: "Empty Rules",
+    name: "Disallow empty rules",
     desc: "Rules without any properties specified should be removed.",
     browsers: "All",
 
@@ -8479,8 +9962,8 @@ CSSLint.addRule({
 
         parser.addListener("endrule", function(event){
             var selectors = event.selectors;
-            if (count == 0){
-                reporter.warn("Rule is empty.", selectors[0].line, selectors[0].col, rule);
+            if (count === 0){
+                reporter.report("Rule is empty.", selectors[0].line, selectors[0].col, rule);
             }
         });
     }
@@ -8489,6 +9972,7 @@ CSSLint.addRule({
 /*
  * Rule: There should be no syntax errors. (Duh.)
  */
+/*global CSSLint*/
 CSSLint.addRule({
 
     //rule information
@@ -8507,16 +9991,84 @@ CSSLint.addRule({
 
     }
 
+});
+
+/*global CSSLint*/
+CSSLint.addRule({
+
+    //rule information
+    id: "fallback-colors",
+    name: "Require fallback colors",
+    desc: "For older browsers that don't support RGBA, HSL, or HSLA, provide a fallback color.",
+    browsers: "IE6,IE7,IE8",
+
+    //initialization
+    init: function(parser, reporter){
+        var rule = this,
+            lastProperty,
+            propertiesToCheck = {
+                color: 1,
+                background: 1,
+                "background-color": 1                
+            },
+            properties;
+        
+        function startRule(event){
+            properties = {};    
+            lastProperty = null;    
+        }
+        
+        parser.addListener("startrule", startRule);
+        parser.addListener("startfontface", startRule);
+        parser.addListener("startpage", startRule);
+        parser.addListener("startpagemargin", startRule);
+        parser.addListener("startkeyframerule", startRule);        
+        
+        parser.addListener("property", function(event){
+            var property = event.property,
+                name = property.text.toLowerCase(),
+                parts = event.value.parts,
+                i = 0, 
+                colorType = "",
+                len = parts.length;                
+                        
+            if(propertiesToCheck[name]){
+                while(i < len){
+                    if (parts[i].type == "color"){
+                        if ("alpha" in parts[i] || "hue" in parts[i]){
+                            
+                            if (/([^\)]+)\(/.test(parts[i])){
+                                colorType = RegExp.$1.toUpperCase();
+                            }
+                            
+                            if (!lastProperty || (lastProperty.property.text.toLowerCase() != name || lastProperty.colorType != "compat")){
+                                reporter.report("Fallback " + name + " (hex or RGB) should precede " + colorType + " " + name + ".", event.line, event.col, rule);
+                            }
+                        } else {
+                            event.colorType = "compat";
+                        }
+                    }
+                    
+                    i++;
+                }
+            }
+
+            lastProperty = event;
+        });        
+         
+    }
+
 });
 /*
  * Rule: You shouldn't use more than 10 floats. If you do, there's probably
  * room for some abstraction.
  */
+/*global CSSLint*/
 CSSLint.addRule({
 
     //rule information
     id: "floats",
-    name: "Floats",
+    name: "Disallow too many floats",
     desc: "This rule tests if the float property is used too many times",
     browsers: "All",
 
@@ -8546,11 +10098,12 @@ CSSLint.addRule({
 /*
  * Rule: Avoid too many @font-face declarations in the same stylesheet.
  */
+/*global CSSLint*/
 CSSLint.addRule({
 
     //rule information
     id: "font-faces",
-    name: "Font Faces",
+    name: "Don't use too many web fonts",
     desc: "Too many different web fonts in the same stylesheet.",
     browsers: "All",
 
@@ -8576,11 +10129,12 @@ CSSLint.addRule({
  * Rule: You shouldn't need more than 9 font-size declarations.
  */
 
+/*global CSSLint*/
 CSSLint.addRule({
 
     //rule information
     id: "font-sizes",
-    name: "Font Sizes",
+    name: "Disallow too many font sizes",
     desc: "Checks the number of font-size declarations.",
     browsers: "All",
 
@@ -8609,11 +10163,12 @@ CSSLint.addRule({
 /*
  * Rule: When using a vendor-prefixed gradient, make sure to use them all.
  */
+/*global CSSLint*/
 CSSLint.addRule({
 
     //rule information
     id: "gradients",
-    name: "Gradients",
+    name: "Require all gradient definitions",
     desc: "When using a vendor-prefixed gradient, make sure to use them all.",
     browsers: "All",
 
@@ -8626,6 +10181,7 @@ CSSLint.addRule({
             gradients = {
                 moz: 0,
                 webkit: 0,
+                oldWebkit: 0,
                 ms: 0,
                 o: 0
             };
@@ -8633,8 +10189,10 @@ CSSLint.addRule({
 
         parser.addListener("property", function(event){
 
-            if (/\-(moz|ms|o|webkit)(?:\-(?:linear|radial))\-gradient/.test(event.value)){
+            if (/\-(moz|ms|o|webkit)(?:\-(?:linear|radial))\-gradient/i.test(event.value)){
                 gradients[RegExp.$1] = 1;
+            } else if (/\-webkit\-gradient/i.test(event.value)){
+                gradients.oldWebkit = 1;
             }
 
         });
@@ -8647,7 +10205,11 @@ CSSLint.addRule({
             }
 
             if (!gradients.webkit){
-                missing.push("Webkit (Safari, Chrome)");
+                missing.push("Webkit (Safari 5+, Chrome)");
+            }
+            
+            if (!gradients.oldWebkit){
+                missing.push("Old Webkit (Safari 4+, Chrome)");
             }
 
             if (!gradients.ms){
@@ -8658,8 +10220,8 @@ CSSLint.addRule({
                 missing.push("Opera 11.1+");
             }
 
-            if (missing.length && missing.length < 4){            
-                reporter.warn("Missing vendor-prefixed CSS gradients for " + missing.join(", ") + ".", event.selectors[0].line, event.selectors[0].col, rule); 
+            if (missing.length && missing.length < 5){            
+                reporter.report("Missing vendor-prefixed CSS gradients for " + missing.join(", ") + ".", event.selectors[0].line, event.selectors[0].col, rule); 
             }
 
         });
@@ -8670,11 +10232,12 @@ CSSLint.addRule({
 /*
  * Rule: Don't use IDs for selectors.
  */
+/*global CSSLint*/
 CSSLint.addRule({
 
     //rule information
     id: "ids",
-    name: "IDs",
+    name: "Disallow IDs in selectors",
     desc: "Selectors should not contain IDs.",
     browsers: "All",
 
@@ -8695,7 +10258,7 @@ CSSLint.addRule({
 
                 for (j=0; j < selector.parts.length; j++){
                     part = selector.parts[j];
-                    if (part instanceof parserlib.css.SelectorPart){
+                    if (part.type == parser.SELECTOR_PART_TYPE){
                         for (k=0; k < part.modifiers.length; k++){
                             modifier = part.modifiers[k];
                             if (modifier.type == "id"){
@@ -8706,9 +10269,9 @@ CSSLint.addRule({
                 }
 
                 if (idCount == 1){
-                    reporter.warn("Don't use IDs in selectors.", selector.line, selector.col, rule);
+                    reporter.report("Don't use IDs in selectors.", selector.line, selector.col, rule);
                 } else if (idCount > 1){
-                    reporter.warn(idCount + " IDs in the selector, really?", selector.line, selector.col, rule);
+                    reporter.report(idCount + " IDs in the selector, really?", selector.line, selector.col, rule);
                 }
             }
 
@@ -8719,11 +10282,12 @@ CSSLint.addRule({
 /*
  * Rule: Don't use @import, use <link> instead.
  */
+/*global CSSLint*/
 CSSLint.addRule({
 
     //rule information
     id: "import",
-    name: "@import",
+    name: "Disallow @import",
     desc: "Don't use @import, use <link> instead.",
     browsers: "All",
 
@@ -8732,7 +10296,7 @@ CSSLint.addRule({
         var rule = this;
         
         parser.addListener("import", function(event){        
-            reporter.warn("@import prevents parallel downloads, use <link> instead.", event.line, event.col, rule);
+            reporter.report("@import prevents parallel downloads, use <link> instead.", event.line, event.col, rule);
         });
 
     }
@@ -8743,11 +10307,12 @@ CSSLint.addRule({
  * war. Display a warning on !important declarations, an error if it's
  * used more at least 10 times.
  */
+/*global CSSLint*/
 CSSLint.addRule({
 
     //rule information
     id: "important",
-    name: "Important",
+    name: "Disallow !important",
     desc: "Be careful when using !important declaration",
     browsers: "All",
 
@@ -8760,7 +10325,7 @@ CSSLint.addRule({
         parser.addListener("property", function(event){
             if (event.important === true){
                 count++;
-                reporter.warn("Use of !important", event.line, event.col, rule);
+                reporter.report("Use of !important", event.line, event.col, rule);
             }
         });
 
@@ -8778,11 +10343,12 @@ CSSLint.addRule({
  * Rule: Properties should be known (listed in CSS3 specification) or
  * be a vendor-prefixed property.
  */
+/*global CSSLint*/
 CSSLint.addRule({
 
     //rule information
     id: "known-properties",
-    name: "Known Properties",
+    name: "Require use of known properties",
     desc: "Properties should be known (listed in CSS specification) or be a vendor-prefixed property.",
     browsers: "All",
 
@@ -8797,6 +10363,7 @@ CSSLint.addRule({
                 "animation-delay": 1,
                 "animation-direction": 1,
                 "animation-duration": 1,
+                "animation-fill-mode": 1,
                 "animation-iteration-count": 1,
                 "animation-name": 1,
                 "animation-play-state": 1,
@@ -9045,6 +10612,8 @@ CSSLint.addRule({
                 "transition-property": 1,
                 "transition-timing-function": 1,
                 "unicode-bidi": 1,
+                "user-modify": 1,
+                "user-select": 1,
                 "vertical-align": 1,
                 "visibility": 1,
                 "voice-balance": 1,
@@ -9067,28 +10636,108 @@ CSSLint.addRule({
                 
                 //IE
                 "filter": 1,
-                "zoom": 1
+                "zoom": 1,
+                
+                //@font-face
+                "src": 1
             };
 
         parser.addListener("property", function(event){
             var name = event.property.text.toLowerCase();
 
-            if (!properties[name] && name.charAt(0) != "-"){
-                reporter.error("Unknown property '" + event.property + "'.", event.line, event.col, rule);
+            if (event.invalid) {
+                reporter.report(event.invalid.message, event.line, event.col, rule);
+            }
+            //if (!properties[name] && name.charAt(0) != "-"){
+            //    reporter.error("Unknown property '" + event.property + "'.", event.line, event.col, rule);
+            //}
+
+        });
+    }
+
+});
+/*
+ * Rule: outline: none or outline: 0 should only be used in a :focus rule
+ *       and only if there are other properties in the same rule.
+ */
+/*global CSSLint*/
+CSSLint.addRule({
+
+    //rule information
+    id: "outline-none",
+    name: "Disallow outline: none",
+    desc: "Use of outline: none or outline: 0 should be limited to :focus rules.",
+    browsers: "All",
+    tags: ["Accessibility"],
+
+    //initialization
+    init: function(parser, reporter){
+        var rule = this,
+            lastRule;
+
+        function startRule(event){
+            if (event.selectors){
+                lastRule = {
+                    line: event.line,
+                    col: event.col,
+                    selectors: event.selectors,
+                    propCount: 0,
+                    outline: false
+                };
+            } else {
+                lastRule = null;
+            }
+        }
+        
+        function endRule(event){
+            if (lastRule){
+                if (lastRule.outline){
+                    if (lastRule.selectors.toString().toLowerCase().indexOf(":focus") == -1){
+                        reporter.report("Outlines should only be modified using :focus.", lastRule.line, lastRule.col, rule);
+                    } else if (lastRule.propCount == 1) {
+                        reporter.report("Outlines shouldn't be hidden unless other visual changes are made.", lastRule.line, lastRule.col, rule);                        
+                    }
+                }
             }
+        }
+
+        parser.addListener("startrule", startRule);
+        parser.addListener("startfontface", startRule);
+        parser.addListener("startpage", startRule);
+        parser.addListener("startpagemargin", startRule);
+        parser.addListener("startkeyframerule", startRule); 
 
+        parser.addListener("property", function(event){
+            var name = event.property.text.toLowerCase(),
+                value = event.value;                
+                
+            if (lastRule){
+                lastRule.propCount++;
+                if (name == "outline" && (value == "none" || value == "0")){
+                    lastRule.outline = true;
+                }            
+            }
+            
         });
+        
+        parser.addListener("endrule", endRule);
+        parser.addListener("endfontface", endRule);
+        parser.addListener("endpage", endRule);
+        parser.addListener("endpagemargin", endRule);
+        parser.addListener("endkeyframerule", endRule); 
+
     }
 
 });
 /*
  * Rule: Don't use classes or IDs with elements (a.foo or a#foo).
  */
+/*global CSSLint*/
 CSSLint.addRule({
 
     //rule information
     id: "overqualified-elements",
-    name: "Overqualified Elements",
+    name: "Disallow overqualified elements",
     desc: "Don't use classes or IDs with elements (a.foo or a#foo).",
     browsers: "All",
 
@@ -9109,11 +10758,11 @@ CSSLint.addRule({
 
                 for (j=0; j < selector.parts.length; j++){
                     part = selector.parts[j];
-                    if (part instanceof parserlib.css.SelectorPart){
+                    if (part.type == parser.SELECTOR_PART_TYPE){
                         for (k=0; k < part.modifiers.length; k++){
                             modifier = part.modifiers[k];
                             if (part.elementName && modifier.type == "id"){
-                                reporter.warn("Element (" + part + ") is overqualified, just use " + modifier + " without element name.", part.line, part.col, rule);
+                                reporter.report("Element (" + part + ") is overqualified, just use " + modifier + " without element name.", part.line, part.col, rule);
                             } else if (modifier.type == "class"){
                                 
                                 if (!classes[modifier]){
@@ -9135,7 +10784,7 @@ CSSLint.addRule({
                 
                     //one use means that this is overqualified
                     if (classes[prop].length == 1 && classes[prop][0].part.elementName){
-                        reporter.warn("Element (" + classes[prop][0].part + ") is overqualified, just use " + classes[prop][0].modifier + " without element name.", classes[prop][0].part.line, classes[prop][0].part.col, rule);
+                        reporter.report("Element (" + classes[prop][0].part + ") is overqualified, just use " + classes[prop][0].modifier + " without element name.", classes[prop][0].part.line, classes[prop][0].part.col, rule);
                     }
                 }
             }        
@@ -9146,11 +10795,12 @@ CSSLint.addRule({
 /*
  * Rule: Headings (h1-h6) should not be qualified (namespaced).
  */
+/*global CSSLint*/
 CSSLint.addRule({
 
     //rule information
     id: "qualified-headings",
-    name: "Qualified Headings",
+    name: "Disallow qualified headings",
     desc: "Headings should not be qualified (namespaced).",
     browsers: "All",
 
@@ -9169,9 +10819,9 @@ CSSLint.addRule({
 
                 for (j=0; j < selector.parts.length; j++){
                     part = selector.parts[j];
-                    if (part instanceof parserlib.css.SelectorPart){
+                    if (part.type == parser.SELECTOR_PART_TYPE){
                         if (part.elementName && /h[1-6]/.test(part.elementName.toString()) && j > 0){
-                            reporter.warn("Heading (" + part.elementName + ") should not be qualified.", part.line, part.col, rule);
+                            reporter.report("Heading (" + part.elementName + ") should not be qualified.", part.line, part.col, rule);
                         }
                     }
                 }
@@ -9183,11 +10833,12 @@ CSSLint.addRule({
 /*
  * Rule: Selectors that look like regular expressions are slow and should be avoided.
  */
+/*global CSSLint*/
 CSSLint.addRule({
 
     //rule information
     id: "regex-selectors",
-    name: "Regex Selectors",
+    name: "Disallow selectors that look like regexs",
     desc: "Selectors that look like regular expressions are slow and should be avoided.",
     browsers: "All",
 
@@ -9206,12 +10857,12 @@ CSSLint.addRule({
                 selector = selectors[i];
                 for (j=0; j < selector.parts.length; j++){
                     part = selector.parts[j];
-                    if (part instanceof parserlib.css.SelectorPart){
+                    if (part.type == parser.SELECTOR_PART_TYPE){
                         for (k=0; k < part.modifiers.length; k++){
                             modifier = part.modifiers[k];
                             if (modifier.type == "attribute"){
                                 if (/([\~\|\^\$\*]=)/.test(modifier)){
-                                    reporter.warn("Attribute selectors with " + RegExp.$1 + " are slow!", modifier.line, modifier.col, rule);
+                                    reporter.report("Attribute selectors with " + RegExp.$1 + " are slow!", modifier.line, modifier.col, rule);
                                 }
                             }
 
@@ -9226,6 +10877,7 @@ CSSLint.addRule({
 /*
  * Rule: Total number of rules should not exceed x.
  */
+/*global CSSLint*/
 CSSLint.addRule({
 
     //rule information
@@ -9239,14 +10891,101 @@ CSSLint.addRule({
         var rule = this,
             count = 0;
 
-        //count each rule
-        parser.addListener("startrule", function(){
-            count++;
+        //count each rule
+        parser.addListener("startrule", function(){
+            count++;
+        });
+
+        parser.addListener("endstylesheet", function(){
+            reporter.stat("rule-count", count);
+        });
+    }
+
+});
+/*
+ * Rule: Use shorthand properties where possible.
+ * 
+ */
+/*global CSSLint*/
+CSSLint.addRule({
+
+    //rule information
+    id: "shorthand",
+    name: "Require shorthand properties",
+    desc: "Use shorthand properties where possible.",
+    browsers: "All",
+    
+    //initialization
+    init: function(parser, reporter){
+        var rule = this,
+            prop, i, len,
+            propertiesToCheck = {},
+            properties,
+            mapping = {
+                "margin": [
+                    "margin-top",
+                    "margin-bottom",
+                    "margin-left",
+                    "margin-right"
+                ],
+                "padding": [
+                    "padding-top",
+                    "padding-bottom",
+                    "padding-left",
+                    "padding-right"
+                ]              
+            };
+            
+        //initialize propertiesToCheck 
+        for (prop in mapping){
+            if (mapping.hasOwnProperty(prop)){
+                for (i=0, len=mapping[prop].length; i < len; i++){
+                    propertiesToCheck[mapping[prop][i]] = prop;
+                }
+            }
+        }
+            
+        function startRule(event){
+            properties = {};
+        }
+        
+        //event handler for end of rules
+        function endRule(event){
+            
+            var prop, i, len, total;
+            
+            //check which properties this rule has
+            for (prop in mapping){
+                if (mapping.hasOwnProperty(prop)){
+                    total=0;
+                    
+                    for (i=0, len=mapping[prop].length; i < len; i++){
+                        total += properties[mapping[prop][i]] ? 1 : 0;
+                    }
+                    
+                    if (total == mapping[prop].length){
+                        reporter.report("The properties " + mapping[prop].join(", ") + " can be replaced by " + prop + ".", event.line, event.col, rule);
+                    }
+                }
+            }
+        }        
+        
+        parser.addListener("startrule", startRule);
+        parser.addListener("startfontface", startRule);
+    
+        //check for use of "font-size"
+        parser.addListener("property", function(event){
+            var name = event.property.toString().toLowerCase(),
+                value = event.value.parts[0].value;
+
+            if (propertiesToCheck[name]){
+                properties[name] = 1;
+            }
         });
 
-        parser.addListener("endstylesheet", function(){
-            reporter.stat("rule-count", count);
-        });
+        parser.addListener("endrule", endRule);
+        parser.addListener("endfontface", endRule);     
+
     }
 
 });
@@ -9254,42 +10993,62 @@ CSSLint.addRule({
  * Rule: Don't use text-indent for image replacement if you need to support rtl. 
  * 
  */
-/*
- * Should we be checking for rtl/ltr?
- */
-//Commented out due to lack of tests
+/*global CSSLint*/
 CSSLint.addRule({
 
     //rule information
     id: "text-indent",
-    name: "Text Indent",
+    name: "Disallow negative text-indent",
     desc: "Checks for text indent less than -99px",
     browsers: "All",
     
     //initialization
     init: function(parser, reporter){
-        var rule = this;
+        var rule = this,
+            textIndent = false;
+            
+            
+        function startRule(event){
+            textIndent = false;
+        }
+        
+        //event handler for end of rules
+        function endRule(event){
+            if (textIndent){
+                reporter.report("Negative text-indent doesn't work well with RTL. If you use text-indent for image replacement explicitly set direction for that item to ltr.", textIndent.line, textIndent.col, rule);
+            }
+        }        
+        
+        parser.addListener("startrule", startRule);
+        parser.addListener("startfontface", startRule);
     
         //check for use of "font-size"
         parser.addListener("property", function(event){
-            var name = event.property,
-                value = event.value.parts[0].value;
+            var name = event.property.toString().toLowerCase(),
+                value = event.value;
 
-            if (name == "text-indent" && value < -99){
-                reporter.warn("Negative text-indent doesn't work well with RTL. If you use text-indent for image replacement explicitly set text-direction for that item to ltr.", name.line, name.col, rule);
+            if (name == "text-indent" && value.parts[0].value < -99){
+                textIndent = event.property;
+            } else if (name == "direction" && value == "ltr"){
+                textIndent = false;
             }
         });
+
+        parser.addListener("endrule", endRule);
+        parser.addListener("endfontface", endRule);     
+
     }
 
 });
 /*
  * Rule: Headings (h1-h6) should be defined only once.
  */
+/*global CSSLint*/
 CSSLint.addRule({
 
     //rule information
     id: "unique-headings",
-    name: "Unique Headings",
+    name: "Headings should only be defined once",
     desc: "Headings should be defined only once.",
     browsers: "All",
 
@@ -9310,31 +11069,60 @@ CSSLint.addRule({
             var selectors = event.selectors,
                 selector,
                 part,
-                i;
+                pseudo,
+                i, j;
 
             for (i=0; i < selectors.length; i++){
                 selector = selectors[i];
                 part = selector.parts[selector.parts.length-1];
 
-                if (part.elementName && /(h[1-6])/.test(part.elementName.toString())){
-                    headings[RegExp.$1]++;
-                    if (headings[RegExp.$1] > 1) {
-                        reporter.warn("Heading (" + part.elementName + ") has already been defined.", part.line, part.col, rule);
+                if (part.elementName && /(h[1-6])/i.test(part.elementName.toString())){
+                    
+                    for (j=0; j < part.modifiers.length; j++){
+                        if (part.modifiers[j].type == "pseudo"){
+                            pseudo = true;
+                            break;
+                        }
+                    }
+                
+                    if (!pseudo){
+                        headings[RegExp.$1]++;
+                        if (headings[RegExp.$1] > 1) {
+                            reporter.report("Heading (" + part.elementName + ") has already been defined.", part.line, part.col, rule);
+                        }
                     }
                 }
             }
         });
+        
+        parser.addListener("endstylesheet", function(event){
+            var prop,
+                messages = [];
+                
+            for (prop in headings){
+                if (headings.hasOwnProperty(prop)){
+                    if (headings[prop] > 1){
+                        messages.push(headings[prop] + " " + prop + "s");
+                    }
+                }
+            }
+            
+            if (messages.length){
+                reporter.rollupWarn("You have " + messages.join(", ") + " defined in this stylesheet.", rule);
+            }
+        });        
     }
 
 });
 /*
  * Rule: Don't use universal selector because it's slow.
  */
+/*global CSSLint*/
 CSSLint.addRule({
 
     //rule information
     id: "universal-selector",
-    name: "Universal Selector",
+    name: "Disallow universal selector",
     desc: "The universal selector (*) is known to be slow.",
     browsers: "All",
 
@@ -9354,22 +11142,65 @@ CSSLint.addRule({
                 
                 part = selector.parts[selector.parts.length-1];
                 if (part.elementName == "*"){
-                    reporter.warn(rule.desc, part.line, part.col, rule);
+                    reporter.report(rule.desc, part.line, part.col, rule);
                 }
             }
         });
     }
 
+});
+/*
+ * Rule: Don't use unqualified attribute selectors because they're just like universal selectors.
+ */
+/*global CSSLint*/
+CSSLint.addRule({
+
+    //rule information
+    id: "unqualified-attributes",
+    name: "Disallow unqualified attribute selectors",
+    desc: "Unqualified attribute selectors are known to be slow.",
+    browsers: "All",
+
+    //initialization
+    init: function(parser, reporter){
+        var rule = this;
+
+        parser.addListener("startrule", function(event){
+            
+            var selectors = event.selectors,
+                selector,
+                part,
+                modifier,
+                i, j, k;
+
+            for (i=0; i < selectors.length; i++){
+                selector = selectors[i];
+                
+                part = selector.parts[selector.parts.length-1];
+                if (part.type == parser.SELECTOR_PART_TYPE){
+                    for (k=0; k < part.modifiers.length; k++){
+                        modifier = part.modifiers[k];
+                        if (modifier.type == "attribute" && (!part.elementName || part.elementName == "*")){
+                            reporter.report(rule.desc, part.line, part.col, rule);                               
+                        }
+                    }
+                }
+                
+            }            
+        });
+    }
+
 });
 /*
  * Rule: When using a vendor-prefixed property, make sure to
  * include the standard one.
  */
+/*global CSSLint*/
 CSSLint.addRule({
 
     //rule information
     id: "vendor-prefix",
-    name: "Vendor Prefix",
+    name: "Require standard property with vendor prefix",
     desc: "When using a vendor-prefixed property, make sure to include the standard one.",
     browsers: "All",
 
@@ -9379,24 +11210,64 @@ CSSLint.addRule({
             properties,
             num,
             propertiesToCheck = {
-                "-moz-border-radius": "border-radius",
                 "-webkit-border-radius": "border-radius",
                 "-webkit-border-top-left-radius": "border-top-left-radius",
                 "-webkit-border-top-right-radius": "border-top-right-radius",
                 "-webkit-border-bottom-left-radius": "border-bottom-left-radius",
                 "-webkit-border-bottom-right-radius": "border-bottom-right-radius",
+                
+                "-o-border-radius": "border-radius",
+                "-o-border-top-left-radius": "border-top-left-radius",
+                "-o-border-top-right-radius": "border-top-right-radius",
+                "-o-border-bottom-left-radius": "border-bottom-left-radius",
+                "-o-border-bottom-right-radius": "border-bottom-right-radius",
+                
+                "-moz-border-radius": "border-radius",
                 "-moz-border-radius-topleft": "border-top-left-radius",
                 "-moz-border-radius-topright": "border-top-right-radius",
                 "-moz-border-radius-bottomleft": "border-bottom-left-radius",
-                "-moz-border-radius-bottomright": "border-bottom-right-radius",
+                "-moz-border-radius-bottomright": "border-bottom-right-radius",                
+                
+                "-moz-column-count": "column-count",
+                "-webkit-column-count": "column-count",
+                
+                "-moz-column-gap": "column-gap",
+                "-webkit-column-gap": "column-gap",
+                
+                "-moz-column-rule": "column-rule",
+                "-webkit-column-rule": "column-rule",
+                
+                "-moz-column-rule-style": "column-rule-style",
+                "-webkit-column-rule-style": "column-rule-style",
+                
+                "-moz-column-rule-color": "column-rule-color",
+                "-webkit-column-rule-color": "column-rule-color",
+                
+                "-moz-column-rule-width": "column-rule-width",
+                "-webkit-column-rule-width": "column-rule-width",
+                
+                "-moz-column-width": "column-width",
+                "-webkit-column-width": "column-width",
+                
+                "-webkit-column-span": "column-span",
+                "-webkit-columns": "columns",
+                
                 "-moz-box-shadow": "box-shadow",
                 "-webkit-box-shadow": "box-shadow",
+                
                 "-moz-transform" : "transform",
                 "-webkit-transform" : "transform",
                 "-o-transform" : "transform",
                 "-ms-transform" : "transform",
+                
+                "-moz-transform-origin" : "transform-origin",
+                "-webkit-transform-origin" : "transform-origin",
+                "-o-transform-origin" : "transform-origin",
+                "-ms-transform-origin" : "transform-origin",
+                
                 "-moz-box-sizing" : "box-sizing",
                 "-webkit-box-sizing" : "box-sizing",
+                
                 "-moz-user-select" : "user-select",
                 "-khtml-user-select" : "user-select",
                 "-webkit-user-select" : "user-select"                
@@ -9428,11 +11299,11 @@ CSSLint.addRule({
                 actual = needsStandard[i].actual;
 
                 if (!properties[needed]){               
-                    reporter.warn("Missing standard property '" + needed + "' to go along with '" + actual + "'.", event.line, event.col, rule);
+                    reporter.report("Missing standard property '" + needed + "' to go along with '" + actual + "'.", properties[actual][0].name.line, properties[actual][0].name.col, rule);
                 } else {
                     //make sure standard property is last
                     if (properties[needed][0].pos < properties[actual][0].pos){
-                        reporter.warn("Standard property '" + needed + "' should come after vendor-prefixed property '" + actual + "'.", event.line, event.col, rule);
+                        reporter.report("Standard property '" + needed + "' should come after vendor-prefixed property '" + actual + "'.", properties[actual][0].name.line, properties[actual][0].name.col, rule);
                     }
                 }
             }
@@ -9441,6 +11312,9 @@ CSSLint.addRule({
         
         parser.addListener("startrule", startRule);
         parser.addListener("startfontface", startRule);
+        parser.addListener("startpage", startRule);
+        parser.addListener("startpagemargin", startRule);
+        parser.addListener("startkeyframerule", startRule);         
 
         parser.addListener("property", function(event){
             var name = event.property.text.toLowerCase();
@@ -9454,60 +11328,21 @@ CSSLint.addRule({
 
         parser.addListener("endrule", endRule);
         parser.addListener("endfontface", endRule);
+        parser.addListener("endpage", endRule);
+        parser.addListener("endpagemargin", endRule);
+        parser.addListener("endkeyframerule", endRule);         
     }
 
 });
-/*
- * Rule: If an element has a width of 100%, be careful when placing within
- * an element that has padding. It may look strange.
- */
-//Commented out pending further review.
-/*CSSLint.addRule({
-
-    //rule information
-    id: "width-100",
-    name: "Width 100%",
-    desc: "Be careful when using width: 100% on elements.",
-    browsers: "All",
-
-    //initialization
-    init: function(parser, reporter){
-        var rule = this,
-            width100,
-            boxsizing;
-
-        parser.addListener("startrule", function(){
-            width100 = null;
-            boxsizing = false;
-        });
-
-        parser.addListener("property", function(event){
-            var name = event.property.text.toLowerCase(),
-                value = event.value;
-
-            if (name == "width" && value == "100%"){
-                width100 = event.property;
-            } else if (name == "box-sizing" || /\-(?:webkit|ms|moz)\-box-sizing/.test(name)){  //means you know what you're doing
-                boxsizing = true;
-            }
-        });
-        
-        parser.addListener("endrule", function(){
-            if (width100 && !boxsizing){
-                reporter.warn("Elements with a width of 100% may not appear as you expect inside of other elements.", width100.line, width100.col, rule);
-            }
-        });
-    }
-
-});*/
 /*
  * Rule: You don't need to specify units when a value is 0.
  */
+/*global CSSLint*/
 CSSLint.addRule({
 
     //rule information
     id: "zero-units",
-    name: "Zero Units",
+    name: "Disallow units for 0 values",
     desc: "You don't need to specify units when a value is 0.",
     browsers: "All",
 
@@ -9522,8 +11357,8 @@ CSSLint.addRule({
                 len = parts.length;
 
             while(i < len){
-                if ((parts[i].units || parts[i].type == "percentage") && parts[i].value === 0){
-                    reporter.warn("Values of 0 shouldn't have units specified.", parts[i].line, parts[i].col, rule);
+                if ((parts[i].units || parts[i].type == "percentage") && parts[i].value === 0 && parts[i].type != "time"){
+                    reporter.report("Values of 0 shouldn't have units specified.", parts[i].line, parts[i].col, rule);
                 }
                 i++;
             }
@@ -9533,6 +11368,347 @@ CSSLint.addRule({
     }
 
 });
+/*global CSSLint*/
+CSSLint.addFormatter({
+    //format information
+    id: "checkstyle-xml",
+    name: "Checkstyle XML format",
 
-exports.CSSLint = CSSLint;
+    /**
+     * Return opening root XML tag.
+     * @return {String} to prepend before all results
+     */
+    startFormat: function(){
+        return "<?xml version=\"1.0\" encoding=\"utf-8\"?><checkstyle>";
+    },
+
+    /**
+     * Return closing root XML tag.
+     * @return {String} to append after all results
+     */
+    endFormat: function(){
+        return "</checkstyle>";
+    },
+
+    /**
+     * Given CSS Lint results for a file, return output for this format.
+     * @param results {Object} with error and warning messages
+     * @param filename {String} relative file path
+     * @param options {Object} (UNUSED for now) specifies special handling of output
+     * @return {String} output for results
+     */
+    formatResults: function(results, filename, options) {
+        var messages = results.messages,
+            output = [];
+
+        /**
+         * Generate a source string for a rule.
+         * Checkstyle source strings usually resemble Java class names e.g
+         * net.csslint.SomeRuleName
+         * @param {Object} rule
+         * @return rule source as {String}
+         */
+        var generateSource = function(rule) {
+            if (!rule || !('name' in rule)) {
+                return "";
+            }
+            return 'net.csslint.' + rule.name.replace(/\s/g,'');
+        };
+
+        /**
+         * Replace special characters before write to output.
+         *
+         * Rules:
+         *  - single quotes is the escape sequence for double-quotes
+         *  - &lt; is the escape sequence for <
+         *  - &gt; is the escape sequence for >
+         *
+         * @param {String} message to escape
+         * @return escaped message as {String}
+         */
+        var escapeSpecialCharacters = function(str) {
+            if (!str || str.constructor !== String) {
+                return "";
+            }
+            return str.replace(/\"/g, "'").replace(/</g, "&lt;").replace(/>/g, "&gt;");
+        };
+
+        if (messages.length > 0) {
+            output.push("<file name=\""+filename+"\">");
+            CSSLint.Util.forEach(messages, function (message, i) {
+                //ignore rollups for now
+                if (!message.rollup) {
+                  output.push("<error line=\"" + message.line + "\" column=\"" + message.col + "\" severity=\"" + message.type + "\"" +
+                      " message=\"" + escapeSpecialCharacters(message.message) + "\" source=\"" + generateSource(message.rule) +"\"/>");
+                }
+            });
+            output.push("</file>");
+        }
+
+        return output.join("");
+    }
+});
+/*global CSSLint*/
+CSSLint.addFormatter({
+    //format information
+    id: "compact",
+    name: "Compact, 'porcelain' format",
+
+    /**
+     * Return content to be printed before all file results.
+     * @return {String} to prepend before all results
+     */
+    startFormat: function() {
+        return "";
+    },
+
+    /**
+     * Return content to be printed after all file results.
+     * @return {String} to append after all results
+     */
+    endFormat: function() {
+        return "";
+    },
+
+    /**
+     * Given CSS Lint results for a file, return output for this format.
+     * @param results {Object} with error and warning messages
+     * @param filename {String} relative file path
+     * @param options {Object} (Optional) specifies special handling of output
+     * @return {String} output for results
+     */
+    formatResults: function(results, filename, options) {
+        var messages = results.messages,
+            output = "";
+        options = options || {};
+
+        /**
+         * Capitalize and return given string.
+         * @param str {String} to capitalize
+         * @return {String} capitalized
+         */
+        var capitalize = function(str) {
+            return str.charAt(0).toUpperCase() + str.slice(1);
+        };
+
+        if (messages.length === 0) {
+            return options.quiet ? "" : filename + ": Lint Free!";
+        }
+
+        CSSLint.Util.forEach(messages, function(message, i) {
+            if (message.rollup) {
+                output += filename + ": " + capitalize(message.type) + " - " + message.message + "\n";
+            } else {
+                output += filename + ": " + "line " + message.line + 
+                    ", col " + message.col + ", " + capitalize(message.type) + " - " + message.message + "\n";
+            }
+        });
+    
+        return output;
+    }
+});
+/*global CSSLint*/
+CSSLint.addFormatter({
+    //format information
+    id: "csslint-xml",
+    name: "CSSLint XML format",
+
+    /**
+     * Return opening root XML tag.
+     * @return {String} to prepend before all results
+     */
+    startFormat: function(){
+        return "<?xml version=\"1.0\" encoding=\"utf-8\"?><csslint>";
+    },
+
+    /**
+     * Return closing root XML tag.
+     * @return {String} to append after all results
+     */
+    endFormat: function(){
+        return "</csslint>";
+    },
+
+    /**
+     * Given CSS Lint results for a file, return output for this format.
+     * @param results {Object} with error and warning messages
+     * @param filename {String} relative file path
+     * @param options {Object} (UNUSED for now) specifies special handling of output
+     * @return {String} output for results
+     */
+    formatResults: function(results, filename, options) {
+        var messages = results.messages,
+            output = [];
+
+        /**
+         * Replace special characters before write to output.
+         *
+         * Rules:
+         *  - single quotes is the escape sequence for double-quotes
+         *  - &lt; is the escape sequence for <
+         *  - &gt; is the escape sequence for >
+         * 
+         * @param {String} message to escape
+         * @return escaped message as {String}
+         */
+        var escapeSpecialCharacters = function(str) {
+            if (!str || str.constructor !== String) {
+                return "";
+            }
+            return str.replace(/\"/g, "'").replace(/</g, "&lt;").replace(/>/g, "&gt;");
+        };
+
+        if (messages.length > 0) {
+            output.push("<file name=\""+filename+"\">");
+            CSSLint.Util.forEach(messages, function (message, i) {
+                if (message.rollup) {
+                    output.push("<issue severity=\"" + message.type + "\" reason=\"" + escapeSpecialCharacters(message.message) + "\" evidence=\"" + escapeSpecialCharacters(message.evidence) + "\"/>");
+                } else {
+                    output.push("<issue line=\"" + message.line + "\" char=\"" + message.col + "\" severity=\"" + message.type + "\"" +
+                        " reason=\"" + escapeSpecialCharacters(message.message) + "\" evidence=\"" + escapeSpecialCharacters(message.evidence) + "\"/>");
+                }
+            });
+            output.push("</file>");
+        }
+
+        return output.join("");
+    }
+});
+/*global CSSLint*/
+CSSLint.addFormatter({
+    //format information
+    id: "lint-xml",
+    name: "Lint XML format",
+
+    /**
+     * Return opening root XML tag.
+     * @return {String} to prepend before all results
+     */
+    startFormat: function(){
+        return "<?xml version=\"1.0\" encoding=\"utf-8\"?><lint>";
+    },
+
+    /**
+     * Return closing root XML tag.
+     * @return {String} to append after all results
+     */
+    endFormat: function(){
+        return "</lint>";
+    },
+
+    /**
+     * Given CSS Lint results for a file, return output for this format.
+     * @param results {Object} with error and warning messages
+     * @param filename {String} relative file path
+     * @param options {Object} (UNUSED for now) specifies special handling of output
+     * @return {String} output for results
+     */
+    formatResults: function(results, filename, options) {
+        var messages = results.messages,
+            output = [];
+
+        /**
+         * Replace special characters before write to output.
+         *
+         * Rules:
+         *  - single quotes is the escape sequence for double-quotes
+         *  - &lt; is the escape sequence for <
+         *  - &gt; is the escape sequence for >
+         * 
+         * @param {String} message to escape
+         * @return escaped message as {String}
+         */
+        var escapeSpecialCharacters = function(str) {
+            if (!str || str.constructor !== String) {
+                return "";
+            }
+            return str.replace(/\"/g, "'").replace(/</g, "&lt;").replace(/>/g, "&gt;");
+        };
+
+        if (messages.length > 0) {
+        
+            output.push("<file name=\""+filename+"\">");
+            CSSLint.Util.forEach(messages, function (message, i) {
+                if (message.rollup) {
+                    output.push("<issue severity=\"" + message.type + "\" reason=\"" + escapeSpecialCharacters(message.message) + "\" evidence=\"" + escapeSpecialCharacters(message.evidence) + "\"/>");
+                } else {
+                    output.push("<issue line=\"" + message.line + "\" char=\"" + message.col + "\" severity=\"" + message.type + "\"" +
+                        " reason=\"" + escapeSpecialCharacters(message.message) + "\" evidence=\"" + escapeSpecialCharacters(message.evidence) + "\"/>");
+                }
+            });
+            output.push("</file>");
+        }
+
+        return output.join("");
+    }
+});
+/*global CSSLint*/
+CSSLint.addFormatter({
+    //format information
+    id: "text",
+    name: "Plain Text",
+
+    /**
+     * Return content to be printed before all file results.
+     * @return {String} to prepend before all results
+     */
+    startFormat: function() {
+        return "";
+    },
+
+    /**
+     * Return content to be printed after all file results.
+     * @return {String} to append after all results
+     */
+    endFormat: function() {
+        return "";
+    },
+
+    /**
+     * Given CSS Lint results for a file, return output for this format.
+     * @param results {Object} with error and warning messages
+     * @param filename {String} relative file path
+     * @param options {Object} (Optional) specifies special handling of output
+     * @return {String} output for results
+     */
+    formatResults: function(results, filename, options) {
+        var messages = results.messages,
+            output = "";
+        options = options || {};
+
+        if (messages.length === 0) {
+            return options.quiet ? "" : "\n\ncsslint: No errors in " + filename + ".";
+        }
+
+        output = "\n\ncsslint: There are " + messages.length  +  " problems in " + filename + ".";
+        var pos = filename.lastIndexOf("/"),
+            shortFilename = filename;
+
+        if (pos === -1){
+            pos = filename.lastIndexOf("\\");       
+        }
+        if (pos > -1){
+            shortFilename = filename.substring(pos+1);
+        }
+
+        CSSLint.Util.forEach(messages, function (message, i) {
+            output = output + "\n\n" + shortFilename;
+            if (message.rollup) {
+                output += "\n" + (i+1) + ": " + message.type;
+                output += "\n" + message.message;
+            } else {
+                output += "\n" + (i+1) + ": " + message.type + " at line " + message.line + ", col " + message.col;
+                output += "\n" + message.message;
+                output += "\n" + message.evidence;
+            }
+        });
+    
+        return output;
+    }
 });
+
+
+exports.CSSLint = CSSLint;
+
+
+});
\ No newline at end of file
diff --git a/apps/files_texteditor/js/aceeditor/worker-javascript.js b/apps/files_texteditor/js/aceeditor/worker-javascript.js
index e48c6e810dc5bda5057be69116564be560a08333..179228493cec9d0a805d6e74026e98aeb72bec7d 100644
--- a/apps/files_texteditor/js/aceeditor/worker-javascript.js
+++ b/apps/files_texteditor/js/aceeditor/worker-javascript.js
@@ -198,7 +198,7 @@ define('ace/lib/regexp', ['require', 'exports', 'module' ], function(require, ex
     RegExp.prototype.exec = function (str) {
         var match = real.exec.apply(this, arguments),
             name, r2;
-        if (match) {
+        if ( typeof(str) == 'string' && match) {
             // Fix browsers whose `exec` methods don't consistently return `undefined` for
             // nonparticipating capturing groups
             if (!compliantExecNpcg && match.length > 1 && indexOf(match, "") > -1) {
@@ -263,7 +263,8 @@ define('ace/lib/regexp', ['require', 'exports', 'module' ], function(require, ex
         return -1;
     };
 
-});// vim: ts=4 sts=4 sw=4 expandtab
+});
+// vim: ts=4 sts=4 sw=4 expandtab
 // -- kriskowal Kris Kowal Copyright (C) 2009-2011 MIT License
 // -- tlrobinson Tom Robinson Copyright (C) 2009-2010 MIT License (Narwhal Project)
 // -- dantman Daniel Friesen Copyright (C) 2010 XXX TODO License or CLA
@@ -1539,12 +1540,13 @@ exports.implement = function(proto, mixin) {
  *
  * ***** END LICENSE BLOCK ***** */
  
-define('ace/mode/javascript_worker', ['require', 'exports', 'module' , 'ace/lib/oop', 'ace/worker/mirror', 'ace/worker/jshint', 'ace/narcissus/jsparse'], function(require, exports, module) {
+define('ace/mode/javascript_worker', ['require', 'exports', 'module' , 'ace/lib/oop', 'ace/worker/mirror', 'ace/worker/jshint', 'ace/narcissus/parser'], function(require, exports, module) {
 "use strict";
     
 var oop = require("../lib/oop");
 var Mirror = require("../worker/mirror").Mirror;
 var lint = require("../worker/jshint").JSHINT;
+var parser = require("../narcissus/parser");
     
 var JavaScriptWorker = exports.JavaScriptWorker = function(sender) {
     Mirror.call(this, sender);
@@ -1560,7 +1562,6 @@ oop.inherits(JavaScriptWorker, Mirror);
         value = value.replace(/^#!.*\n/, "\n");
         
 //        var start = new Date();
-        var parser = require("../narcissus/jsparse");
         try {
             parser.parse(value);
         } catch(e) {
@@ -1806,11 +1807,12 @@ var Document = function(text) {
     };
 
     this.insert = function(position, text) {
-        if (text.length == 0)
+        if (!text || text.length === 0)
             return position;
 
         position = this.$clipPosition(position);
 
+        // only detect new lines if the document has no line break yet
         if (this.getLength() <= 1)
             this.$detectNewLine(text);
 
@@ -2090,7 +2092,7 @@ var Range = function(startRow, startColumn, endRow, endColumn) {
 };
 
 (function() {
-    this.isEequal = function(range) {
+    this.isEqual = function(range) {
         return this.start.row == range.start.row &&
             this.end.row == range.end.row &&
             this.start.column == range.start.column &&
@@ -2156,6 +2158,11 @@ var Range = function(startRow, startColumn, endRow, endColumn) {
         return this.comparePoint(range.start) == 0 && this.comparePoint(range.end) == 0;
     }
 
+    this.intersectsRange = function(range) {
+        var cmp = this.compareRange(range);
+        return (cmp == -1 || cmp == 0 || cmp == 1);
+    }
+
     this.isEnd = function(row, column) {
         return this.end.row == row && this.end.column == column;
     }
@@ -2315,6 +2322,21 @@ var Range = function(startRow, startColumn, endRow, endColumn) {
         return Range.fromPoints(start || this.start, end || this.end);
     };
 
+    this.fixOrientation = function() {
+        if (
+            this.start.row < this.end.row 
+            || (this.start.row == this.end.row && this.start.column < this.end.column)
+        ) {
+            return false;
+        }
+        
+        var temp = this.start;
+        this.end = this.start;
+        this.start = temp;
+        return true;
+    };
+
+
     this.isEmpty = function() {
         return (this.start.row == this.end.row && this.start.column == this.end.column);
     };
@@ -2829,7 +2851,7 @@ define('ace/worker/jshint', ['require', 'exports', 'module' ], function(require,
      member: {
          STRING: NUMBER
      },
-     unuseds: [
+     unused: [
          {
              name: STRING,
              line: NUMBER
@@ -2853,7 +2875,7 @@ define('ace/worker/jshint', ['require', 'exports', 'module' ], function(require,
 
 /*jshint
  evil: true, nomen: false, onevar: false, regexp: false, strict: true, boss: true,
- undef: true, maxlen: 100
+ undef: true, maxlen: 100, indent:4
 */
 
 /*members "\b", "\t", "\n", "\f", "\r", "!=", "!==", "\"", "%", "(begin)",
@@ -2861,56 +2883,70 @@ define('ace/worker/jshint', ['require', 'exports', 'module' ], function(require,
  "(line)", "(loopage)", "(name)", "(onevar)", "(params)", "(scope)",
  "(statement)", "(verb)", "*", "+", "++", "-", "--", "\/", "<", "<=", "==",
  "===", ">", ">=", $, $$, $A, $F, $H, $R, $break, $continue, $w, Abstract, Ajax,
- __filename, __dirname, ActiveXObject, Array, ArrayBuffer, ArrayBufferView,
+ __filename, __dirname, ActiveXObject, Array, ArrayBuffer, ArrayBufferView, Audio,
  Autocompleter, Assets, Boolean, Builder, Buffer, Browser, COM, CScript, Canvas,
  CustomAnimation, Class, Control, Chain, Color, Cookie, Core, DataView, Date,
- Debug, Draggable, Draggables, Droppables, Document, DomReady, DOMReady, Drag,
+ Debug, Draggable, Draggables, Droppables, Document, DomReady, DOMReady, DOMParser, Drag,
  E, Enumerator, Enumerable, Element, Elements, Error, Effect, EvalError, Event,
  Events, FadeAnimation, Field, Flash, Float32Array, Float64Array, Form,
- FormField, Frame, Function, Fx, GetObject, Group, Hash, HotKey, HTMLElement,
- HtmlTable, Iframe, IframeShim, Image, Int16Array, Int32Array, Int8Array,
+ FormField, Frame, FormData, Function, Fx, GetObject, Group, Hash, HotKey,
+ HTMLElement, HTMLAnchorElement, HTMLBaseElement, HTMLBlockquoteElement,
+ HTMLBodyElement, HTMLBRElement, HTMLButtonElement, HTMLCanvasElement, HTMLDirectoryElement,
+ HTMLDivElement, HTMLDListElement, HTMLFieldSetElement,
+ HTMLFontElement, HTMLFormElement, HTMLFrameElement, HTMLFrameSetElement,
+ HTMLHeadElement, HTMLHeadingElement, HTMLHRElement, HTMLHtmlElement,
+ HTMLIFrameElement, HTMLImageElement, HTMLInputElement, HTMLIsIndexElement,
+ HTMLLabelElement, HTMLLayerElement, HTMLLegendElement, HTMLLIElement,
+ HTMLLinkElement, HTMLMapElement, HTMLMenuElement, HTMLMetaElement,
+ HTMLModElement, HTMLObjectElement, HTMLOListElement, HTMLOptGroupElement,
+ HTMLOptionElement, HTMLParagraphElement, HTMLParamElement, HTMLPreElement,
+ HTMLQuoteElement, HTMLScriptElement, HTMLSelectElement, HTMLStyleElement,
+ HtmlTable, HTMLTableCaptionElement, HTMLTableCellElement, HTMLTableColElement,
+ HTMLTableElement, HTMLTableRowElement, HTMLTableSectionElement,
+ HTMLTextAreaElement, HTMLTitleElement, HTMLUListElement, HTMLVideoElement,
+ Iframe, IframeShim, Image, Int16Array, Int32Array, Int8Array,
  Insertion, InputValidator, JSON, Keyboard, Locale, LN10, LN2, LOG10E, LOG2E,
- MAX_VALUE, MIN_VALUE, Mask, Math, MenuItem, MoveAnimation, MooTools, Native,
- NEGATIVE_INFINITY, Number, Object, ObjectRange, Option, Options, OverText, PI,
- POSITIVE_INFINITY, PeriodicalExecuter, Point, Position, Prototype, RangeError,
- Rectangle, ReferenceError, RegExp, ResizeAnimation, Request, RotateAnimation,
+ MAX_VALUE, MIN_VALUE, Mask, Math, MenuItem, MessageChannel, MessageEvent, MessagePort,
+ MoveAnimation, MooTools, Native, NEGATIVE_INFINITY, Number, Object, ObjectRange, Option,
+ Options, OverText, PI, POSITIVE_INFINITY, PeriodicalExecuter, Point, Position, Prototype,
+ RangeError, Rectangle, ReferenceError, RegExp, ResizeAnimation, Request, RotateAnimation,
  SQRT1_2, SQRT2, ScrollBar, ScriptEngine, ScriptEngineBuildVersion,
  ScriptEngineMajorVersion, ScriptEngineMinorVersion, Scriptaculous, Scroller,
- Slick, Slider, Selector, String, Style, SyntaxError, Sortable, Sortables,
+ Slick, Slider, Selector, SharedWorker, String, Style, SyntaxError, Sortable, Sortables,
  SortableObserver, Sound, Spinner, System, Swiff, Text, TextArea, Template,
- Timer, Tips, Type, TypeError, Toggle, Try, URI, URIError, URL, VBArray, WSH,
- WScript, Web, Window, XMLDOM, XMLHttpRequest, XPathEvaluator, XPathException,
- XPathExpression, XPathNamespace, XPathNSResolver, XPathResult, "\\", a,
- addEventListener, address, alert, apply, applicationCache, arguments, arity,
- asi, b, bitwise, block, blur, boolOptions, boss, browser, c, call, callee,
+ Timer, Tips, Type, TypeError, Toggle, Try, "use strict", unescape, URI, URIError, URL,
+ VBArray, WSH, WScript, XDomainRequest, Web, Window, XMLDOM, XMLHttpRequest, XMLSerializer,
+ XPathEvaluator, XPathException, XPathExpression, XPathNamespace, XPathNSResolver, XPathResult,
+ "\\", a, addEventListener, address, alert, apply, applicationCache, arguments, arity, asi, atob,
+ b, basic, basicToken, bitwise, block, blur, boolOptions, boss, browser, btoa, c, call, callee,
  caller, cases, charAt, charCodeAt, character, clearInterval, clearTimeout,
  close, closed, closure, comment, condition, confirm, console, constructor,
  content, couch, create, css, curly, d, data, datalist, dd, debug, decodeURI,
  decodeURIComponent, defaultStatus, defineClass, deserialize, devel, document,
- dojo, dijit, dojox, define, edition, else, emit, encodeURI, encodeURIComponent,
- entityify, eqeqeq, eqnull, errors, es5, escape, eval, event, evidence, evil,
+ dojo, dijit, dojox, define, else, emit, encodeURI, encodeURIComponent,
+ entityify, eqeqeq, eqnull, errors, es5, escape, esnext, eval, event, evidence, evil,
  ex, exception, exec, exps, expr, exports, FileReader, first, floor, focus,
- forin, fragment, frames, from, fromCharCode, fud, funct, function, functions,
- g, gc, getComputedStyle, getRow, GLOBAL, global, globals, globalstrict,
- hasOwnProperty, help, history, i, id, identifier, immed, implieds, include,
+ forin, fragment, frames, from, fromCharCode, fud, funcscope, funct, function, functions,
+ g, gc, getComputedStyle, getRow, getter, getterToken, GLOBAL, global, globals, globalstrict,
+ hasOwnProperty, help, history, i, id, identifier, immed, implieds, importPackage, include,
  indent, indexOf, init, ins, instanceOf, isAlpha, isApplicationRunning, isArray,
- isDigit, isFinite, isNaN, iterator, join, jshint,
- JSHINT, json, jquery, jQuery, keys, label, labelled, last, lastsemic, laxbreak,
+ isDigit, isFinite, isNaN, iterator, java, join, jshint,
+ JSHINT, json, jquery, jQuery, keys, label, labelled, last, lastsemic, laxbreak, laxcomma,
  latedef, lbp, led, left, length, line, load, loadClass, localStorage, location,
  log, loopfunc, m, match, maxerr, maxlen, member,message, meta, module, moveBy,
- moveTo, mootools, name, navigator, new, newcap, noarg, node, noempty, nomen,
- nonew, nud, onbeforeunload, onblur, onerror, onevar, onfocus, onload, onresize,
- onunload, open, openDatabase, openURL, opener, opera, outer, param, parent,
- parseFloat, parseInt, passfail, plusplus, predef, print, process, prompt,
- proto, prototype, prototypejs, push, quit, range, raw, reach, reason, regexp,
+ moveTo, mootools, multistr, name, navigator, new, newcap, noarg, node, noempty, nomen,
+ nonew, nonstandard, nud, onbeforeunload, onblur, onerror, onevar, onecase, onfocus,
+ onload, onresize, onunload, open, openDatabase, openURL, opener, opera, options, outer, param,
+ parent, parseFloat, parseInt, passfail, plusplus, predef, print, process, prompt,
+ proto, prototype, prototypejs, provides, push, quit, range, raw, reach, reason, regexp,
  readFile, readUrl, regexdash, removeEventListener, replace, report, require,
  reserved, resizeBy, resizeTo, resolvePath, resumeUpdates, respond, rhino, right,
- runCommand, scroll, screen, scripturl, scrollBy, scrollTo, scrollbar, search, seal, send,
- serialize, setInterval, setTimeout, shift, slice, sort,spawn, split, stack,
- status, start, strict, sub, substr, supernew, shadow, supplant, sum, sync,
- test, toLowerCase, toString, toUpperCase, toint32, token, top, trailing, type,
- typeOf, Uint16Array, Uint32Array, Uint8Array, undef, unused, urls, value, valueOf,
- var, version, WebSocket, white, window, Worker, wsh*/
+ runCommand, scroll, screen, scripturl, scrollBy, scrollTo, scrollbar, search, seal,
+ send, serialize, sessionStorage, setInterval, setTimeout, setter, setterToken, shift, slice,
+ smarttabs, sort, spawn, split, stack, status, start, strict, sub, substr, supernew, shadow,
+ supplant, sum, sync, test, toLowerCase, toString, toUpperCase, toint32, token, top, trailing,
+ type, typeOf, Uint16Array, Uint32Array, Uint8Array, undef, undefs, unused, urls, validthis,
+ value, valueOf, var, version, WebSocket, withstmt, white, window, Worker, wsh*/
 
 /*global exports: false */
 
@@ -2941,8 +2977,7 @@ var JSHINT = (function () {
             '%'  : true
         },
 
-// These are the JSHint boolean options.
-
+        // These are the JSHint boolean options.
         boolOptions = {
             asi         : true, // if automatic semicolon insertion should be tolerated
             bitwise     : true, // if bitwise operators should not be allowed
@@ -2951,122 +2986,217 @@ var JSHINT = (function () {
             couch       : true, // if CouchDB globals should be predefined
             curly       : true, // if curly braces around all blocks should be required
             debug       : true, // if debugger statements should be allowed
-            devel       : true, // if logging globals should be predefined (console, alert, etc.)
+            devel       : true, // if logging globals should be predefined (console,
+                                // alert, etc.)
             dojo        : true, // if Dojo Toolkit globals should be predefined
             eqeqeq      : true, // if === should be required
             eqnull      : true, // if == null comparisons should be tolerated
             es5         : true, // if ES5 syntax should be allowed
+            esnext      : true, // if es.next specific syntax should be allowed
             evil        : true, // if eval should be allowed
             expr        : true, // if ExpressionStatement should be allowed as Programs
             forin       : true, // if for in statements must filter
-            globalstrict: true, // if global "use strict"; should be allowed (also enables 'strict')
+            funcscope   : true, // if only function scope should be used for scope tests
+            globalstrict: true, // if global "use strict"; should be allowed (also
+                                // enables 'strict')
             immed       : true, // if immediate invocations must be wrapped in parens
-            iterator    : true, // if the `__iterator__` property should be disallowed
+            iterator    : true, // if the `__iterator__` property should be allowed
             jquery      : true, // if jQuery globals should be predefined
+            lastsemic   : true, // if semicolons may be ommitted for the trailing
+                                // statements inside of a one-line blocks.
             latedef     : true, // if the use before definition should not be tolerated
             laxbreak    : true, // if line breaks should not be checked
-            loopfunc    : true, // if functions should be allowed to be defined within loops
+            laxcomma    : true, // if line breaks should not be checked around commas
+            loopfunc    : true, // if functions should be allowed to be defined within
+                                // loops
             mootools    : true, // if MooTools globals should be predefined
+            multistr    : true, // allow multiline strings
             newcap      : true, // if constructor names must be capitalized
-            noarg       : true, // if arguments.caller and arguments.callee should be disallowed
-            node        : true, // if the Node.js environment globals should be predefined
+            noarg       : true, // if arguments.caller and arguments.callee should be
+                                // disallowed
+            node        : true, // if the Node.js environment globals should be
+                                // predefined
             noempty     : true, // if empty blocks should be disallowed
             nonew       : true, // if using `new` for side-effects should be disallowed
+            nonstandard : true, // if non-standard (but widely adopted) globals should
+                                // be predefined
             nomen       : true, // if names should be checked
-            onevar      : true, // if only one var statement per function should be allowed
+            onevar      : true, // if only one var statement per function should be
+                                // allowed
+            onecase     : true, // if one case switch statements should be allowed
             passfail    : true, // if the scan should stop on first error
             plusplus    : true, // if increment/decrement should not be allowed
-            proto       : true, // if the `__proto__` property should be disallowed
-            prototypejs : true, // if Prototype and Scriptaculous globals should be predefined
-            regexdash   : true, // if unescaped last dash (-) inside brackets should be tolerated
+            proto       : true, // if the `__proto__` property should be allowed
+            prototypejs : true, // if Prototype and Scriptaculous globals should be
+                                // predefined
+            regexdash   : true, // if unescaped first/last dash (-) inside brackets
+                                // should be tolerated
             regexp      : true, // if the . should not be allowed in regexp literals
             rhino       : true, // if the Rhino environment globals should be predefined
             undef       : true, // if variables should be declared before used
             scripturl   : true, // if script-targeted URLs should be tolerated
             shadow      : true, // if variable shadowing should be tolerated
+            smarttabs   : true, // if smarttabs should be tolerated
+                                // (http://www.emacswiki.org/emacs/SmartTabs)
             strict      : true, // require the "use strict"; pragma
             sub         : true, // if all forms of subscript notation are tolerated
             supernew    : true, // if `new function () { ... };` and `new Object;`
                                 // should be tolerated
             trailing    : true, // if trailing whitespace rules apply
+            validthis   : true, // if 'this' inside a non-constructor function is valid.
+                                // This is a function scoped option only.
+            withstmt    : true, // if with statements should be allowed
             white       : true, // if strict whitespace rules apply
-            wsh         : true  // if the Windows Scripting Host environment globals should
-                                // be predefined
+            wsh         : true  // if the Windows Scripting Host environment globals
+                                // should be predefined
+        },
+
+        // These are the JSHint options that can take any value
+        // (we use this object to detect invalid options)
+        valOptions = {
+            maxlen: false,
+            indent: false,
+            maxerr: false,
+            predef: false
         },
 
-// browser contains a set of global names which are commonly provided by a
-// web browser environment.
 
+        // browser contains a set of global names which are commonly provided by a
+        // web browser environment.
         browser = {
-            ArrayBuffer     : false,
-            ArrayBufferView : false,
-            addEventListener: false,
-            applicationCache: false,
-            blur            : false,
-            clearInterval   : false,
-            clearTimeout    : false,
-            close           : false,
-            closed          : false,
-            DataView        : false,
-            defaultStatus   : false,
-            document        : false,
-            event           : false,
-            FileReader      : false,
-            Float32Array    : false,
-            Float64Array    : false,
-            focus           : false,
-            frames          : false,
-            getComputedStyle: false,
-            HTMLElement     : false,
-            history         : false,
-            Int16Array      : false,
-            Int32Array      : false,
-            Int8Array       : false,
-            Image           : false,
-            length          : false,
-            localStorage    : false,
-            location        : false,
-            moveBy          : false,
-            moveTo          : false,
-            name            : false,
-            navigator       : false,
-            onbeforeunload  : true,
-            onblur          : true,
-            onerror         : true,
-            onfocus         : true,
-            onload          : true,
-            onresize        : true,
-            onunload        : true,
-            open            : false,
-            openDatabase    : false,
-            opener          : false,
-            Option          : false,
-            parent          : false,
-            print           : false,
-            removeEventListener: false,
-            resizeBy        : false,
-            resizeTo        : false,
-            screen          : false,
-            scroll          : false,
-            scrollBy        : false,
-            scrollTo        : false,
-            setInterval     : false,
-            setTimeout      : false,
-            status          : false,
-            top             : false,
-            Uint16Array     : false,
-            Uint32Array     : false,
-            Uint8Array      : false,
-            WebSocket       : false,
-            window          : false,
-            Worker          : false,
-            XMLHttpRequest  : false,
-            XPathEvaluator  : false,
-            XPathException  : false,
-            XPathExpression : false,
-            XPathNamespace  : false,
-            XPathNSResolver : false,
-            XPathResult     : false
+            ArrayBuffer              :  false,
+            ArrayBufferView          :  false,
+            Audio                    :  false,
+            addEventListener         :  false,
+            applicationCache         :  false,
+            atob                     :  false,
+            blur                     :  false,
+            btoa                     :  false,
+            clearInterval            :  false,
+            clearTimeout             :  false,
+            close                    :  false,
+            closed                   :  false,
+            DataView                 :  false,
+            DOMParser                :  false,
+            defaultStatus            :  false,
+            document                 :  false,
+            event                    :  false,
+            FileReader               :  false,
+            Float32Array             :  false,
+            Float64Array             :  false,
+            FormData                 :  false,
+            focus                    :  false,
+            frames                   :  false,
+            getComputedStyle         :  false,
+            HTMLElement              :  false,
+            HTMLAnchorElement        :  false,
+            HTMLBaseElement          :  false,
+            HTMLBlockquoteElement    :  false,
+            HTMLBodyElement          :  false,
+            HTMLBRElement            :  false,
+            HTMLButtonElement        :  false,
+            HTMLCanvasElement        :  false,
+            HTMLDirectoryElement     :  false,
+            HTMLDivElement           :  false,
+            HTMLDListElement         :  false,
+            HTMLFieldSetElement      :  false,
+            HTMLFontElement          :  false,
+            HTMLFormElement          :  false,
+            HTMLFrameElement         :  false,
+            HTMLFrameSetElement      :  false,
+            HTMLHeadElement          :  false,
+            HTMLHeadingElement       :  false,
+            HTMLHRElement            :  false,
+            HTMLHtmlElement          :  false,
+            HTMLIFrameElement        :  false,
+            HTMLImageElement         :  false,
+            HTMLInputElement         :  false,
+            HTMLIsIndexElement       :  false,
+            HTMLLabelElement         :  false,
+            HTMLLayerElement         :  false,
+            HTMLLegendElement        :  false,
+            HTMLLIElement            :  false,
+            HTMLLinkElement          :  false,
+            HTMLMapElement           :  false,
+            HTMLMenuElement          :  false,
+            HTMLMetaElement          :  false,
+            HTMLModElement           :  false,
+            HTMLObjectElement        :  false,
+            HTMLOListElement         :  false,
+            HTMLOptGroupElement      :  false,
+            HTMLOptionElement        :  false,
+            HTMLParagraphElement     :  false,
+            HTMLParamElement         :  false,
+            HTMLPreElement           :  false,
+            HTMLQuoteElement         :  false,
+            HTMLScriptElement        :  false,
+            HTMLSelectElement        :  false,
+            HTMLStyleElement         :  false,
+            HTMLTableCaptionElement  :  false,
+            HTMLTableCellElement     :  false,
+            HTMLTableColElement      :  false,
+            HTMLTableElement         :  false,
+            HTMLTableRowElement      :  false,
+            HTMLTableSectionElement  :  false,
+            HTMLTextAreaElement      :  false,
+            HTMLTitleElement         :  false,
+            HTMLUListElement         :  false,
+            HTMLVideoElement         :  false,
+            history                  :  false,
+            Int16Array               :  false,
+            Int32Array               :  false,
+            Int8Array                :  false,
+            Image                    :  false,
+            length                   :  false,
+            localStorage             :  false,
+            location                 :  false,
+            MessageChannel           :  false,
+            MessageEvent             :  false,
+            MessagePort              :  false,
+            moveBy                   :  false,
+            moveTo                   :  false,
+            name                     :  false,
+            navigator                :  false,
+            onbeforeunload           :  true,
+            onblur                   :  true,
+            onerror                  :  true,
+            onfocus                  :  true,
+            onload                   :  true,
+            onresize                 :  true,
+            onunload                 :  true,
+            open                     :  false,
+            openDatabase             :  false,
+            opener                   :  false,
+            Option                   :  false,
+            parent                   :  false,
+            print                    :  false,
+            removeEventListener      :  false,
+            resizeBy                 :  false,
+            resizeTo                 :  false,
+            screen                   :  false,
+            scroll                   :  false,
+            scrollBy                 :  false,
+            scrollTo                 :  false,
+            sessionStorage           :  false,
+            setInterval              :  false,
+            setTimeout               :  false,
+            SharedWorker             :  false,
+            status                   :  false,
+            top                      :  false,
+            Uint16Array              :  false,
+            Uint32Array              :  false,
+            Uint8Array               :  false,
+            WebSocket                :  false,
+            window                   :  false,
+            Worker                   :  false,
+            XMLHttpRequest           :  false,
+            XMLSerializer            :  false,
+            XPathEvaluator           :  false,
+            XPathException           :  false,
+            XPathExpression          :  false,
+            XPathNamespace           :  false,
+            XPathNSResolver          :  false,
+            XPathResult              :  false
         },
 
         couch = {
@@ -3079,7 +3209,8 @@ var JSHINT = (function () {
             sum       : false,
             log       : false,
             exports   : false,
-            module    : false
+            module    : false,
+            provides  : false
         },
 
         devel = {
@@ -3185,15 +3316,20 @@ var JSHINT = (function () {
         nexttoken,
 
         node = {
-            __filename  : false,
-            __dirname   : false,
-            exports     : false,
-            Buffer      : false,
-            GLOBAL      : false,
-            global      : false,
-            module      : false,
-            process     : false,
-            require     : false
+            __filename    : false,
+            __dirname     : false,
+            Buffer        : false,
+            console       : false,
+            exports       : false,
+            GLOBAL        : false,
+            global        : false,
+            module        : false,
+            process       : false,
+            require       : false,
+            setTimeout    : false,
+            clearTimeout  : false,
+            setInterval   : false,
+            clearInterval : false
         },
 
         noreach,
@@ -3244,32 +3380,32 @@ var JSHINT = (function () {
         },
 
         rhino = {
-            defineClass : false,
-            deserialize : false,
-            gc          : false,
-            help        : false,
-            load        : false,
-            loadClass   : false,
-            print       : false,
-            quit        : false,
-            readFile    : false,
-            readUrl     : false,
-            runCommand  : false,
-            seal        : false,
-            serialize   : false,
-            spawn       : false,
-            sync        : false,
-            toint32     : false,
-            version     : false
+            defineClass  : false,
+            deserialize  : false,
+            gc           : false,
+            help         : false,
+            importPackage: false,
+            "java"       : false,
+            load         : false,
+            loadClass    : false,
+            print        : false,
+            quit         : false,
+            readFile     : false,
+            readUrl      : false,
+            runCommand   : false,
+            seal         : false,
+            serialize    : false,
+            spawn        : false,
+            sync         : false,
+            toint32      : false,
+            version      : false
         },
 
         scope,      // The current scope
-        src,
         stack,
 
-// standard contains the global names that are provided by the
-// ECMAScript standard.
-
+        // standard contains the global names that are provided by the
+        // ECMAScript standard.
         standard = {
             Array               : false,
             Boolean             : false,
@@ -3300,6 +3436,12 @@ var JSHINT = (function () {
             URIError            : false
         },
 
+        // widely adopted global names that are not part of ECMAScript standard
+        nonstandard = {
+            escape              : false,
+            unescape            : false
+        },
+
         standard_member = {
             E                   : true,
             LN2                 : true,
@@ -3315,11 +3457,12 @@ var JSHINT = (function () {
             SQRT2               : true
         },
 
-        strict_mode,
+        directive,
         syntax = {},
         tab,
         token,
         urls,
+        useESNextSyntax,
         warnings,
 
         wsh = {
@@ -3332,39 +3475,40 @@ var JSHINT = (function () {
             ScriptEngineMinorVersion  : true,
             VBArray                   : true,
             WSH                       : true,
-            WScript                   : true
+            WScript                   : true,
+            XDomainRequest            : true
         };
 
-        // Regular expressions. Some of these are stupidly long.
-        var ax, cx, tx, nx, nxg, lx, ix, jx, ft;
-        (function () {
-            /*jshint maxlen:300 */
+    // Regular expressions. Some of these are stupidly long.
+    var ax, cx, tx, nx, nxg, lx, ix, jx, ft;
+    (function () {
+        /*jshint maxlen:300 */
 
-            // unsafe comment or string
-            ax = /@cc|<\/?|script|\]\s*\]|<\s*!|&lt/i;
+        // unsafe comment or string
+        ax = /@cc|<\/?|script|\]\s*\]|<\s*!|&lt/i;
 
-            // unsafe characters that are silently deleted by one or more browsers
-            cx = /[\u0000-\u001f\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/;
+        // unsafe characters that are silently deleted by one or more browsers
+        cx = /[\u0000-\u001f\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/;
 
-            // token
-            tx = /^\s*([(){}\[.,:;'"~\?\]#@]|==?=?|\/(\*(jshint|jslint|members?|global)?|=|\/)?|\*[\/=]?|\+(?:=|\++)?|-(?:=|-+)?|%=?|&[&=]?|\|[|=]?|>>?>?=?|<([\/=!]|\!(\[|--)?|<=?)?|\^=?|\!=?=?|[a-zA-Z_$][a-zA-Z0-9_$]*|[0-9]+([xX][0-9a-fA-F]+|\.[0-9]*)?([eE][+\-]?[0-9]+)?)/;
+        // token
+        tx = /^\s*([(){}\[.,:;'"~\?\]#@]|==?=?|\/(\*(jshint|jslint|members?|global)?|=|\/)?|\*[\/=]?|\+(?:=|\++)?|-(?:=|-+)?|%=?|&[&=]?|\|[|=]?|>>?>?=?|<([\/=!]|\!(\[|--)?|<=?)?|\^=?|\!=?=?|[a-zA-Z_$][a-zA-Z0-9_$]*|[0-9]+([xX][0-9a-fA-F]+|\.[0-9]*)?([eE][+\-]?[0-9]+)?)/;
 
-            // characters in strings that need escapement
-            nx = /[\u0000-\u001f&<"\/\\\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/;
-            nxg = /[\u0000-\u001f&<"\/\\\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g;
+        // characters in strings that need escapement
+        nx = /[\u0000-\u001f&<"\/\\\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/;
+        nxg = /[\u0000-\u001f&<"\/\\\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g;
 
-            // star slash
-            lx = /\*\/|\/\*/;
+        // star slash
+        lx = /\*\/|\/\*/;
 
-            // identifier
-            ix = /^([a-zA-Z_$][a-zA-Z0-9_$]*)$/;
+        // identifier
+        ix = /^([a-zA-Z_$][a-zA-Z0-9_$]*)$/;
 
-            // javascript url
-            jx = /^(?:javascript|jscript|ecmascript|vbscript|mocha|livescript)\s*:/i;
+        // javascript url
+        jx = /^(?:javascript|jscript|ecmascript|vbscript|mocha|livescript)\s*:/i;
 
-            // catches /* falls through */ comments
-            ft = /^\s*\/\*\s*falls\sthrough\s*\*\/\s*$/;
-        }());
+        // catches /* falls through */ comments
+        ft = /^\s*\/\*\s*falls\sthrough\s*\*\/\s*$/;
+    }());
 
     function F() {}     // Used by Object.create
 
@@ -3376,6 +3520,12 @@ var JSHINT = (function () {
         return Object.prototype.hasOwnProperty.call(object, name);
     }
 
+    function checkOption(name, t) {
+        if (valOptions[name] === undefined && boolOptions[name] === undefined) {
+            warning("Bad option: '" + name + "'.", t);
+        }
+    }
+
 // Provide critical ES5 functions to ES3.
 
     if (typeof Array.isArray !== 'function') {
@@ -3472,43 +3622,62 @@ var JSHINT = (function () {
     }
 
     function assume() {
-        if (option.couch)
+        if (option.couch) {
             combine(predefined, couch);
+        }
 
-        if (option.rhino)
+        if (option.rhino) {
             combine(predefined, rhino);
+        }
 
-        if (option.prototypejs)
+        if (option.prototypejs) {
             combine(predefined, prototypejs);
+        }
 
-        if (option.node)
+        if (option.node) {
             combine(predefined, node);
+            option.globalstrict = true;
+        }
 
-        if (option.devel)
+        if (option.devel) {
             combine(predefined, devel);
+        }
 
-        if (option.dojo)
+        if (option.dojo) {
             combine(predefined, dojo);
+        }
 
-        if (option.browser)
+        if (option.browser) {
             combine(predefined, browser);
+        }
+
+        if (option.nonstandard) {
+            combine(predefined, nonstandard);
+        }
 
-        if (option.jquery)
+        if (option.jquery) {
             combine(predefined, jquery);
+        }
 
-        if (option.mootools)
+        if (option.mootools) {
             combine(predefined, mootools);
+        }
 
-        if (option.wsh)
+        if (option.wsh) {
             combine(predefined, wsh);
+        }
+
+        if (option.esnext) {
+            useESNextSyntax();
+        }
 
-        if (option.globalstrict && option.strict !== false)
+        if (option.globalstrict && option.strict !== false) {
             option.strict = true;
+        }
     }
 
 
-// Produce an error warning.
-
+    // Produce an error warning.
     function quit(message, line, chr) {
         var percentage = Math.floor((line / lines.length) * 100);
 
@@ -3516,10 +3685,15 @@ var JSHINT = (function () {
             name: 'JSHintError',
             line: line,
             character: chr,
-            message: message + " (" + percentage + "% scanned)."
+            message: message + " (" + percentage + "% scanned).",
+            raw: message
         };
     }
 
+    function isundef(scope, m, t, a) {
+        return JSHINT.undefs.push([scope, m, t, a]);
+    }
+
     function warning(m, t, a, b, c, d) {
         var ch, l, w;
         t = t || nexttoken;
@@ -3560,7 +3734,6 @@ var JSHINT = (function () {
 
     function error(m, t, a, b, c, d) {
         var w = warning(m, t, a, b, c, d);
-        quit("Stopping, unable to continue.", w.line, w.character);
     }
 
     function errorAt(m, l, ch, a, b, c, d) {
@@ -3589,7 +3762,13 @@ var JSHINT = (function () {
             character = 1;
             s = lines[line];
             line += 1;
-            at = s.search(/ \t/);
+
+            // If smarttabs option is used check for spaces followed by tabs only.
+            // Otherwise check for any occurence of mixed tabs and spaces.
+            if (option.smarttabs)
+                at = s.search(/ \t/);
+            else
+                at = s.search(/ \t|\t /);
 
             if (at >= 0)
                 warningAt("Mixed spaces and tabs.", line, at + 1);
@@ -3604,10 +3783,10 @@ var JSHINT = (function () {
                 warningAt("Line too long.", line, s.length);
 
             // Check for trailing whitespaces
-            tw = s.search(/\s+$/);
-            if (option.trailing && ~tw && !~s.search(/^\s+$/))
-                warningAt("Trailing whitespace.", line, tw);
-
+            tw = option.trailing && s.match(/^(.*?)\s+$/);
+            if (tw && !/^\s+$/.test(s)) {
+                warningAt("Trailing whitespace.", line, tw[1].length + 1);
+            }
             return true;
         }
 
@@ -3639,8 +3818,10 @@ var JSHINT = (function () {
                         line, from, value);
                 } else if (option.nomen && (value.charAt(0) === '_' ||
                          value.charAt(value.length - 1) === '_')) {
-                    warningAt("Unexpected {a} in '{b}'.", line, from,
-                        "dangling '_'", value);
+                    if (!option.node || token.id === '.' ||
+                            (value !== '__dirname' && value !== '__filename')) {
+                        warningAt("Unexpected {a} in '{b}'.", line, from, "dangling '_'", value);
+                    }
                 }
             }
             t.value = value;
@@ -3651,13 +3832,13 @@ var JSHINT = (function () {
             if (i !== '(endline)') {
                 prereg = i &&
                     (('(,=:[!&|?{};'.indexOf(i.charAt(i.length - 1)) >= 0) ||
-                    i === 'return');
+                    i === 'return' ||
+                    i === 'case');
             }
             return t;
         }
 
-// Public lex methods
-
+        // Public lex methods
         return {
             init: function (source) {
                 if (typeof source === 'string') {
@@ -3671,7 +3852,7 @@ var JSHINT = (function () {
 
                 // If the first line is a shebang (#!), make it a blank and move on.
                 // Shebangs are used by Node scripts.
-                if (lines[0] && lines[0].substr(0, 2) == '#!')
+                if (lines[0] && lines[0].substr(0, 2) === '#!')
                     lines[0] = '';
 
                 line = 0;
@@ -3706,10 +3887,10 @@ var JSHINT = (function () {
 
             },
 
-// token -- this is called by advance to get the next token.
 
+            // token -- this is called by advance to get the next token
             token: function () {
-                var b, c, captures, d, depth, high, i, l, low, q, t;
+                var b, c, captures, d, depth, high, i, l, low, q, t, isLiteral, isInRange, n;
 
                 function match(x) {
                     var r = x.exec(s), r1;
@@ -3725,7 +3906,7 @@ var JSHINT = (function () {
                 }
 
                 function string(x) {
-                    var c, j, r = '';
+                    var c, j, r = '', allowNewLine = false;
 
                     if (jsonmode && x !== '"') {
                         warningAt("Strings must use doublequote.",
@@ -3743,11 +3924,20 @@ var JSHINT = (function () {
                         c = String.fromCharCode(i);
                     }
                     j = 0;
-                    for (;;) {
+unclosedString:     for (;;) {
                         while (j >= s.length) {
                             j = 0;
+
+                            var cl = line, cf = from;
                             if (!nextLine()) {
-                                errorAt("Unclosed string.", line, from);
+                                errorAt("Unclosed string.", cl, cf);
+                                break unclosedString;
+                            }
+
+                            if (allowNewLine) {
+                                allowNewLine = false;
+                            } else {
+                                warningAt("Unclosed string.", cl, cf);
                             }
                         }
                         c = s.charAt(j);
@@ -3766,6 +3956,7 @@ var JSHINT = (function () {
                             j += 1;
                             character += 1;
                             c = s.charAt(j);
+                            n = s.charAt(j + 1);
                             switch (c) {
                             case '\\':
                             case '"':
@@ -3791,6 +3982,17 @@ var JSHINT = (function () {
                             case 't':
                                 c = '\t';
                                 break;
+                            case '0':
+                                c = '\0';
+                                // Octal literals fail in strict mode
+                                // check if the number is between 00 and 07
+                                // where 'n' is the token next to 'c'
+                                if (n >= 0 && n <= 7 && directive["use strict"]) {
+                                    warningAt(
+                                    "Octal literals are not allowed in strict mode.",
+                                    line, character);
+                                }
+                                break;
                             case 'u':
                                 esc(4);
                                 break;
@@ -3806,6 +4008,22 @@ var JSHINT = (function () {
                                 }
                                 esc(2);
                                 break;
+                            case '':
+                                // last character is escape character
+                                // always allow new line if escaped, but show
+                                // warning if option is not set
+                                allowNewLine = true;
+                                if (option.multistr) {
+                                    if (jsonmode) {
+                                        warningAt("Avoid EOL escapement.", line, character);
+                                    }
+                                    c = '';
+                                    character -= 1;
+                                    break;
+                                }
+                                warningAt("Bad escapement of EOL. Use option multistr if needed.",
+                                    line, character);
+                                break;
                             default:
                                 warningAt("Bad escapement.", line, character);
                             }
@@ -3829,6 +4047,7 @@ var JSHINT = (function () {
                         }
                         if (s) {
                             errorAt("Unexpected '{a}'.", line, character, s.substr(0, 1));
+                            s = '';
                         }
                     } else {
 
@@ -3878,9 +4097,6 @@ var JSHINT = (function () {
     //      // comment
 
                         case '//':
-                            if (src) {
-                                warningAt("Unexpected comment.", line, character);
-                            }
                             s = '';
                             token.comment = true;
                             break;
@@ -3888,9 +4104,6 @@ var JSHINT = (function () {
     //      /* comment
 
                         case '/*':
-                            if (src) {
-                                warningAt("Unexpected comment.", line, character);
-                            }
                             for (;;) {
                                 i = s.search(lx);
                                 if (i >= 0) {
@@ -3929,8 +4142,8 @@ var JSHINT = (function () {
     //      /
                         case '/':
                             if (token.id === '/=') {
-                                errorAt(
-"A regular expression literal can be confused with '/='.", line, from);
+                                errorAt("A regular expression literal can be confused with '/='.",
+                                    line, from);
                             }
                             if (prereg) {
                                 depth = 0;
@@ -3942,13 +4155,12 @@ var JSHINT = (function () {
                                     l += 1;
                                     switch (c) {
                                     case '':
-                                        errorAt("Unclosed regular expression.",
-                                                line, from);
-                                        return;
+                                        errorAt("Unclosed regular expression.", line, from);
+                                        return quit('Stopping.', line, from);
                                     case '/':
                                         if (depth > 0) {
-                                            warningAt("Unescaped '{a}'.",
-                                                    line, from + l, '/');
+                                            warningAt("{a} unterminated regular expression " +
+                                                "group(s).", line, from + l, depth);
                                         }
                                         c = s.substr(0, l - 1);
                                         q = {
@@ -4032,12 +4244,12 @@ var JSHINT = (function () {
                                                     line, from + l, '^');
                                             }
                                         }
-                                        q = false;
                                         if (c === ']') {
                                             warningAt("Empty class.", line,
                                                     from + l - 1);
-                                            q = true;
                                         }
+                                        isLiteral = false;
+                                        isInRange = false;
 klass:                                  do {
                                             c = s.charAt(l);
                                             l += 1;
@@ -4046,19 +4258,31 @@ klass:                                  do {
                                             case '^':
                                                 warningAt("Unescaped '{a}'.",
                                                         line, from + l, c);
-                                                q = true;
+                                                if (isInRange) {
+                                                    isInRange = false;
+                                                } else {
+                                                    isLiteral = true;
+                                                }
                                                 break;
                                             case '-':
-                                                if (q) {
-                                                    q = false;
+                                                if (isLiteral && !isInRange) {
+                                                    isLiteral = false;
+                                                    isInRange = true;
+                                                } else if (isInRange) {
+                                                    isInRange = false;
+                                                } else if (s.charAt(l) === ']') {
+                                                    isInRange = true;
                                                 } else {
-                                                    warningAt("Unescaped '{a}'.",
-                                                            line, from + l, '-');
-                                                    q = true;
+                                                    if (option.regexdash !== (l === 2 || (l === 3 &&
+                                                        s.charAt(1) === '^'))) {
+                                                        warningAt("Unescaped '{a}'.",
+                                                            line, from + l - 1, '-');
+                                                    }
+                                                    isLiteral = true;
                                                 }
                                                 break;
                                             case ']':
-                                                if (!q && !option.regexdash) {
+                                                if (isInRange && !option.regexdash) {
                                                     warningAt("Unescaped '{a}'.",
                                                             line, from + l - 1, '-');
                                                 }
@@ -4073,18 +4297,44 @@ klass:                                  do {
 "Unexpected escaped character '{a}' in regular expression.", line, from + l, c);
                                                 }
                                                 l += 1;
-                                                q = true;
+
+                                                // \w, \s and \d are never part of a character range
+                                                if (/[wsd]/i.test(c)) {
+                                                    if (isInRange) {
+                                                        warningAt("Unescaped '{a}'.",
+                                                            line, from + l, '-');
+                                                        isInRange = false;
+                                                    }
+                                                    isLiteral = false;
+                                                } else if (isInRange) {
+                                                    isInRange = false;
+                                                } else {
+                                                    isLiteral = true;
+                                                }
                                                 break;
                                             case '/':
                                                 warningAt("Unescaped '{a}'.",
                                                         line, from + l - 1, '/');
-                                                q = true;
+
+                                                if (isInRange) {
+                                                    isInRange = false;
+                                                } else {
+                                                    isLiteral = true;
+                                                }
                                                 break;
                                             case '<':
-                                                q = true;
+                                                if (isInRange) {
+                                                    isInRange = false;
+                                                } else {
+                                                    isLiteral = true;
+                                                }
                                                 break;
                                             default:
-                                                q = true;
+                                                if (isInRange) {
+                                                    isInRange = false;
+                                                } else {
+                                                    isLiteral = true;
+                                                }
                                             }
                                         } while (c);
                                         break;
@@ -4192,13 +4442,12 @@ klass:                                  do {
         }
 
 // Define t in the current function in the current scope.
-
         if (is_own(funct, t) && !funct['(global)']) {
             if (funct[t] === true) {
                 if (option.latedef)
                     warning("'{a}' was used before it was defined.", nexttoken, t);
             } else {
-                if (!option.shadow)
+                if (!option.shadow && type !== "exception")
                     warning("'{a}' is already defined.", nexttoken, t);
             }
         }
@@ -4219,6 +4468,7 @@ klass:                                  do {
 
     function doOption() {
         var b, obj, filter, o = nexttoken.value, t, v;
+
         switch (o) {
         case '*/':
             error("Unbegun comment.");
@@ -4242,6 +4492,7 @@ klass:                                  do {
         default:
             error("What?");
         }
+
         t = lex.token();
 loop:   for (;;) {
             for (;;) {
@@ -4257,13 +4508,20 @@ loop:   for (;;) {
                     o !== '/*members') {
                 error("Bad option.", t);
             }
+
             v = lex.token();
             if (v.id === ':') {
                 v = lex.token();
+
                 if (obj === membersOnly) {
                     error("Expected '{a}' and instead saw '{b}'.",
                             t, '*/', ':');
                 }
+
+                if (o === '/*jshint') {
+                    checkOption(t.value, t);
+                }
+
                 if (t.value === 'indent' && (o === '/*jshint' || o === '/*jslint')) {
                     b = +v.value;
                     if (typeof b !== 'number' || !isFinite(b) || b <= 0 ||
@@ -4289,6 +4547,15 @@ loop:   for (;;) {
                                 v, v.value);
                     }
                     obj.maxlen = b;
+                } else if (t.value === 'validthis') {
+                    if (funct['(global)']) {
+                        error("Option 'validthis' can't be used in a global scope.");
+                    } else {
+                        if (v.value === 'true' || v.value === 'false')
+                            obj[t.value] = v.value === 'true';
+                        else
+                            error("Bad option value.", v);
+                    }
                 } else if (v.value === 'true') {
                     obj[t.value] = true;
                 } else if (v.value === 'false') {
@@ -4352,6 +4619,7 @@ loop:   for (;;) {
             }
             break;
         }
+
         if (token.type === '(string)' || token.identifier) {
             anonname = token.value;
         }
@@ -4370,6 +4638,7 @@ loop:   for (;;) {
                         nexttoken, id, nexttoken.value);
             }
         }
+
         prevtoken = token;
         token = nexttoken;
         for (;;) {
@@ -4403,7 +4672,7 @@ loop:   for (;;) {
 // They are elements of the parsing method called Top Down Operator Precedence.
 
     function expression(rbp, initial) {
-        var left, isArray = false;
+        var left, isArray = false, isObject = false;
 
         if (nexttoken.id === '(end)')
             error("Unexpected early end of program.", token);
@@ -4430,10 +4699,13 @@ loop:   for (;;) {
                 }
             }
             while (rbp < nexttoken.lbp) {
-                isArray = token.value == 'Array';
+                isArray = token.value === 'Array';
+                isObject = token.value === 'Object';
                 advance();
-                if (isArray && token.id == '(' && nexttoken.id == ')')
+                if (isArray && token.id === '(' && nexttoken.id === ')')
                     warning("Use the array literal notation [].", token);
+                if (isObject && token.id === '(' && nexttoken.id === ')')
+                    warning("Use the object literal notation {}.", token);
                 if (token.led) {
                     left = token.led(left);
                 } else {
@@ -4453,7 +4725,8 @@ loop:   for (;;) {
         right = right || nexttoken;
         if (option.white) {
             if (left.character !== right.from && left.line === right.line) {
-                warning("Unexpected space after '{a}'.", right, left.value);
+                left.from += (left.character - left.from);
+                warning("Unexpected space after '{a}'.", left, left.value);
             }
         }
     }
@@ -4481,8 +4754,9 @@ loop:   for (;;) {
             left = left || token;
             right = right || nexttoken;
             if (left.line === right.line && left.character === right.from) {
+                left.from += (left.character - left.from);
                 warning("Missing space after '{a}'.",
-                        nexttoken, left.value);
+                        left, left.value);
             }
         }
     }
@@ -4496,8 +4770,9 @@ loop:   for (;;) {
             left = left || token;
             right = right || nexttoken;
             if (left.character === right.from) {
+                left.from += (left.character - left.from);
                 warning("Missing space after '{a}'.",
-                        nexttoken, left.value);
+                        left, left.value);
             }
         }
     }
@@ -4524,11 +4799,16 @@ loop:   for (;;) {
 
     function comma() {
         if (token.line !== nexttoken.line) {
-            if (!option.laxbreak) {
+            if (!option.laxcomma) {
+                if (comma.first) {
+                    warning("Comma warnings can be turned off with 'laxcomma'");
+                    comma.first = false;
+                }
                 warning("Bad line breaking before '{a}'.", token, nexttoken.id);
             }
-        } else if (token.character !== nexttoken.from && option.white) {
-            warning("Unexpected space after '{a}'.", nexttoken, token.value);
+        } else if (!token.comment && token.character !== nexttoken.from && option.white) {
+            token.from += (token.character - token.from);
+            warning("Unexpected space after '{a}'.", token, token.value);
         }
         advance(',');
         nonadjacent(token, nexttoken);
@@ -4633,6 +4913,9 @@ loop:   for (;;) {
                 nobreaknonadjacent(prevtoken, token);
                 nonadjacent(token, nexttoken);
             }
+            if (s === "in" && left.id === "!") {
+                warning("Confusing use of '{a}'.", left, '!');
+            }
             if (typeof f === 'function') {
                 return f(left, this);
             } else {
@@ -4660,7 +4943,7 @@ loop:   for (;;) {
                 warning("Confusing use of '{a}'.", left, '!');
             }
             if (right.id === '!') {
-                warning("Confusing use of '{a}'.", left, '!');
+                warning("Confusing use of '{a}'.", right, '!');
             }
             this.left = left;
             this.right = right;
@@ -4693,6 +4976,9 @@ loop:   for (;;) {
                 warning("'{a}' is a function.", left, left.value);
             }
             if (left) {
+                if (option.esnext && funct[left.value] === 'const') {
+                    warning("Attempting to override '{a}' which is a constant", left, left.value);
+                }
                 if (left.id === '.' || left.id === '[') {
                     if (!left.left || left.left.value === 'arguments') {
                         warning('Bad assignment.', that);
@@ -4783,7 +5069,7 @@ loop:   for (;;) {
                 // `undefined` as a function param is a common pattern to protect
                 // against the case when somebody does `undefined = true` and
                 // help with minification. More info: https://gist.github.com/315916
-                if (!fnparam || token.value != 'undefined') {
+                if (!fnparam || token.value !== 'undefined') {
                     warning("Expected an identifier and instead saw '{a}' (a reserved word).",
                             token, token.id);
                 }
@@ -4820,6 +5106,9 @@ loop:   for (;;) {
             }
             if (t.id !== '(endline)') {
                 if (t.id === 'function') {
+                    if (!option.latedef) {
+                        break;
+                    }
                     warning(
 "Inner functions should be listed at the top of the outer function.", t);
                     break;
@@ -4835,11 +5124,8 @@ loop:   for (;;) {
     function statement(noindent) {
         var i = indent, r, s = scope, t = nexttoken;
 
-// We don't like the empty statement.
-
-        if (t.id === ';') {
-            warning("Unnecessary semicolon.", t);
-            advance(';');
+        if (t.id === ";") {
+            advance(";");
             return;
         }
 
@@ -4869,8 +5155,7 @@ loop:   for (;;) {
         }
         r = expression(0, true);
 
-// Look for the final semicolon.
-
+        // Look for the final semicolon.
         if (!t.block) {
             if (!option.expr && (!r || !r.exps)) {
                 warning("Expected an assignment or function call and instead saw an expression.",
@@ -4878,10 +5163,20 @@ loop:   for (;;) {
             } else if (option.nonew && r.id === '(' && r.left.id === 'new') {
                 warning("Do not use 'new' for side effects.");
             }
+
+            if (nexttoken.id === ',') {
+                return comma();
+            }
+
             if (nexttoken.id !== ';') {
-                if (!option.asi && !(option.lastsemic && nexttoken.id == '}' &&
-                        nexttoken.line == token.line)) {
-                    warningAt("Missing semicolon.", token.line, token.from + token.value.length);
+                if (!option.asi) {
+                    // If this is the last statement in a block that ends on
+                    // the same line *and* option lastsemic is on, ignore the warning.
+                    // Otherwise, complain about missing semicolon.
+                    if (!option.lastsemic || nexttoken.id !== '}' ||
+                            nexttoken.line !== token.line) {
+                        warningAt("Missing semicolon.", token.line, token.character);
+                    }
                 }
             } else {
                 adjacent(token, nexttoken);
@@ -4898,72 +5193,142 @@ loop:   for (;;) {
     }
 
 
-    function use_strict() {
-        if (nexttoken.value === 'use strict') {
-            if (strict_mode) {
-                warning("Unnecessary \"use strict\".");
-            }
-            advance();
-            advance(';');
-            strict_mode = true;
-            option.newcap = true;
-            option.undef = true;
-            return true;
-        } else {
-            return false;
-        }
-    }
-
-
-    function statements(begin) {
+    function statements(startLine) {
         var a = [], f, p;
 
         while (!nexttoken.reach && nexttoken.id !== '(end)') {
             if (nexttoken.id === ';') {
-                warning("Unnecessary semicolon.");
+                p = peek();
+                if (!p || p.id !== "(") {
+                    warning("Unnecessary semicolon.");
+                }
                 advance(';');
             } else {
-                a.push(statement());
+                a.push(statement(startLine === nexttoken.line));
             }
         }
         return a;
     }
 
 
+    /*
+     * read all directives
+     * recognizes a simple form of asi, but always
+     * warns, if it is used
+     */
+    function directives() {
+        var i, p, pn;
+
+        for (;;) {
+            if (nexttoken.id === "(string)") {
+                p = peek(0);
+                if (p.id === "(endline)") {
+                    i = 1;
+                    do {
+                        pn = peek(i);
+                        i = i + 1;
+                    } while (pn.id === "(endline)");
+
+                    if (pn.id !== ";") {
+                        if (pn.id !== "(string)" && pn.id !== "(number)" &&
+                            pn.id !== "(regexp)" && pn.identifier !== true &&
+                            pn.id !== "}") {
+                            break;
+                        }
+                        warning("Missing semicolon.", nexttoken);
+                    } else {
+                        p = pn;
+                    }
+                } else if (p.id === "}") {
+                    // directive with no other statements, warn about missing semicolon
+                    warning("Missing semicolon.", p);
+                } else if (p.id !== ";") {
+                    break;
+                }
+
+                indentation();
+                advance();
+                if (directive[token.value]) {
+                    warning("Unnecessary directive \"{a}\".", token, token.value);
+                }
+
+                if (token.value === "use strict") {
+                    option.newcap = true;
+                    option.undef = true;
+                }
+
+                // there's no directive negation, so always set to true
+                directive[token.value] = true;
+
+                if (p.id === ";") {
+                    advance(";");
+                }
+                continue;
+            }
+            break;
+        }
+    }
+
+
     /*
      * Parses a single block. A block is a sequence of statements wrapped in
      * braces.
      *
      * ordinary - true for everything but function bodies and try blocks.
      * stmt     - true if block can be a single statement (e.g. in if/for/while).
+     * isfunc   - true if block is a function body
      */
-    function block(ordinary, stmt) {
+    function block(ordinary, stmt, isfunc) {
         var a,
             b = inblock,
             old_indent = indent,
-            m = strict_mode,
+            m,
             s = scope,
-            t;
+            t,
+            line,
+            d;
 
         inblock = ordinary;
-        scope = Object.create(scope);
+        if (!ordinary || !option.funcscope) scope = Object.create(scope);
         nonadjacent(token, nexttoken);
         t = nexttoken;
 
         if (nexttoken.id === '{') {
             advance('{');
-            if (nexttoken.id !== '}' || token.line !== nexttoken.line) {
+            line = token.line;
+            if (nexttoken.id !== '}') {
                 indent += option.indent;
                 while (!ordinary && nexttoken.from > indent) {
                     indent += option.indent;
                 }
-                if (!ordinary && !use_strict() && !m && option.strict &&
-                        funct['(context)']['(global)']) {
-                    warning("Missing \"use strict\" statement.");
+
+                if (isfunc) {
+                    m = {};
+                    for (d in directive) {
+                        if (is_own(directive, d)) {
+                            m[d] = directive[d];
+                        }
+                    }
+                    directives();
+
+                    if (option.strict && funct['(context)']['(global)']) {
+                        if (!m["use strict"] && !directive["use strict"]) {
+                            warning("Missing \"use strict\" statement.");
+                        }
+                    }
+                }
+
+                a = statements(line);
+
+                if (isfunc) {
+                    directive = m;
                 }
-                a = statements();
-                strict_mode = m;
+
                 indent -= option.indent;
+                if (line !== nexttoken.line) {
+                    indentation();
+                }
+            } else if (line !== nexttoken.line) {
                 indentation();
             }
             advance('}', t);
@@ -4977,11 +5342,14 @@ loop:   for (;;) {
                         nexttoken, '{', nexttoken.value);
 
             noreach = true;
-            a = [statement()];
+            indent += option.indent;
+            // test indentation only if statement is in new line
+            a = [statement(nexttoken.line === token.line)];
+            indent -= option.indent;
             noreach = false;
         }
         funct['(verb)'] = null;
-        scope = s;
+        if (!ordinary || !option.funcscope) scope = s;
         inblock = b;
         if (ordinary && option.noempty && (!a || a.length === 0)) {
             warning("Empty block.");
@@ -5007,6 +5375,7 @@ loop:   for (;;) {
         if (typeof a === 'function') {
             a = false;
         }
+
         if (!a) {
             a = [line];
             implied[name] = a;
@@ -5015,11 +5384,13 @@ loop:   for (;;) {
         }
     }
 
-// Build the syntax table by declaring the syntactic elements of the language.
+
+    // Build the syntax table by declaring the syntactic elements of the language.
 
     type('(number)', function () {
         return this;
     });
+
     type('(string)', function () {
         return this;
     });
@@ -5032,10 +5403,9 @@ loop:   for (;;) {
             var v = this.value,
                 s = scope[v],
                 f;
-            if (typeof s === 'function') {
-
-// Protection against accidental inheritance.
 
+            if (typeof s === 'function') {
+                // Protection against accidental inheritance.
                 s = undefined;
             } else if (typeof s === 'boolean') {
                 f = funct;
@@ -5045,12 +5415,9 @@ loop:   for (;;) {
                 funct = f;
             }
 
-// The name is in scope and defined in the current function.
-
+            // The name is in scope and defined in the current function.
             if (funct === s) {
-
-//      Change 'unused' to 'var', and reject labels.
-
+                // Change 'unused' to 'var', and reject labels.
                 switch (funct[v]) {
                 case 'unused':
                     funct[v] = 'var';
@@ -5066,25 +5433,28 @@ loop:   for (;;) {
                     warning("'{a}' is a statement label.", token, v);
                     break;
                 }
-
-// The name is not defined in the function.  If we are in the global scope,
-// then we have an undefined variable.
-//
-// Operators typeof and delete do not raise runtime errors even if the base
-// object of a reference is null so no need to display warning if we're
-// inside of typeof or delete.
-
             } else if (funct['(global)']) {
-                if (anonname != 'typeof' && anonname != 'delete' &&
-                    option.undef && typeof predefined[v] !== 'boolean') {
-                    warning("'{a}' is not defined.", token, v);
+                // The name is not defined in the function.  If we are in the global
+                // scope, then we have an undefined variable.
+                //
+                // Operators typeof and delete do not raise runtime errors even if
+                // the base object of a reference is null so no need to display warning
+                // if we're inside of typeof or delete.
+
+                if (option.undef && typeof predefined[v] !== 'boolean') {
+                    // Attempting to subscript a null reference will throw an
+                    // error, even within the typeof and delete operators
+                    if (!(anonname === 'typeof' || anonname === 'delete') ||
+                        (nexttoken && (nexttoken.value === '.' || nexttoken.value === '['))) {
+
+                        isundef(funct, "'{a}' is not defined.", token, v);
+                    }
                 }
                 note_implied(token);
-
-// If the name is already defined in the current
-// function, but not as outer, then there is a scope error.
-
             } else {
+                // If the name is already defined in the current
+                // function, but not as outer, then there is a scope error.
+
                 switch (funct[v]) {
                 case 'closure':
                 case 'function':
@@ -5099,25 +5469,28 @@ loop:   for (;;) {
                 case 'global':
                     break;
                 default:
-
-// If the name is defined in an outer function, make an outer entry, and if
-// it was unused, make it var.
-
+                    // If the name is defined in an outer function, make an outer entry,
+                    // and if it was unused, make it var.
                     if (s === true) {
                         funct[v] = true;
                     } else if (s === null) {
                         warning("'{a}' is not allowed.", token, v);
                         note_implied(token);
                     } else if (typeof s !== 'object') {
-
-// Operators typeof and delete do not raise runtime errors even if the base object of
-// a reference is null so no need to display warning if we're inside of typeof or delete.
-
-                        if (anonname != 'typeof' && anonname != 'delete' && option.undef) {
-                            warning("'{a}' is not defined.", token, v);
-                        } else {
-                            funct[v] = true;
+                        // Operators typeof and delete do not raise runtime errors even
+                        // if the base object of a reference is null so no need to
+                        // display warning if we're inside of typeof or delete.
+                        if (option.undef) {
+                            // Attempting to subscript a null reference will throw an
+                            // error, even within the typeof and delete operators
+                            if (!(anonname === 'typeof' || anonname === 'delete') ||
+                                (nexttoken &&
+                                    (nexttoken.value === '.' || nexttoken.value === '['))) {
+
+                                isundef(funct, "'{a}' is not defined.", token, v);
+                            }
                         }
+                        funct[v] = true;
                         note_implied(token);
                     } else {
                         switch (s[v]) {
@@ -5181,7 +5554,7 @@ loop:   for (;;) {
     reserve('default').reach = true;
     reserve('finally');
     reservevar('arguments', function (x) {
-        if (strict_mode && funct['(global)']) {
+        if (directive['use strict'] && funct['(global)']) {
             warning("Strict violation.", x);
         }
     });
@@ -5191,9 +5564,9 @@ loop:   for (;;) {
     reservevar('NaN');
     reservevar('null');
     reservevar('this', function (x) {
-        if (strict_mode && ((funct['(statement)'] &&
+        if (directive['use strict'] && !option.validthis && ((funct['(statement)'] &&
                 funct['(name)'].charAt(0) > 'Z') || funct['(global)'])) {
-            warning("Strict violation.", x);
+            warning("Possible strict violation.", x);
         }
     });
     reservevar('true');
@@ -5226,25 +5599,21 @@ loop:   for (;;) {
     bitwise('^', 'bitxor', 80);
     bitwise('&', 'bitand', 90);
     relation('==', function (left, right) {
-        var eqnull = option.eqnull &&
-                (left.value == 'null' || right.value == 'null');
+        var eqnull = option.eqnull && (left.value === 'null' || right.value === 'null');
+
+        if (!eqnull && option.eqeqeq)
+            warning("Expected '{a}' and instead saw '{b}'.", this, '===', '==');
+        else if (isPoorRelation(left))
+            warning("Use '{a}' to compare with '{b}'.", this, '===', left.value);
+        else if (isPoorRelation(right))
+            warning("Use '{a}' to compare with '{b}'.", this, '===', right.value);
 
-        if (!eqnull && option.eqeqeq) {
-            warning("Expected '{a}' and instead saw '{b}'.",
-                    this, '===', '==');
-        } else if (isPoorRelation(left)) {
-            warning("Use '{a}' to compare with '{b}'.",
-                this, '===', left.value);
-        } else if (isPoorRelation(right)) {
-            warning("Use '{a}' to compare with '{b}'.",
-                this, '===', right.value);
-        }
         return this;
     });
     relation('===');
     relation('!=', function (left, right) {
         var eqnull = option.eqnull &&
-                (left.value == 'null' || right.value == 'null');
+                (left.value === 'null' || right.value === 'null');
 
         if (!eqnull && option.eqeqeq) {
             warning("Expected '{a}' and instead saw '{b}'.",
@@ -5352,9 +5721,6 @@ loop:   for (;;) {
             if (c.identifier) {
                 c['new'] = true;
                 switch (c.value) {
-                case 'Object':
-                    warning("Use the object literal notation {}.", token);
-                    break;
                 case 'Number':
                 case 'String':
                 case 'Boolean':
@@ -5374,8 +5740,8 @@ loop:   for (;;) {
                     if (c.id !== 'function') {
                         i = c.value.substr(0, 1);
                         if (option.newcap && (i < 'A' || i > 'Z')) {
-                            warning("A constructor name should start with "+
-                                "an uppercase letter.", token);
+                            warning("A constructor name should start with an uppercase letter.",
+                                token);
                         }
                     }
                 }
@@ -5408,9 +5774,11 @@ loop:   for (;;) {
         }
         that.left = left;
         that.right = m;
-        if (option.noarg && left && left.value === 'arguments' &&
-                (m === 'callee' || m === 'caller')) {
-            warning("Avoid arguments.{a}.", left, m);
+        if (left && left.value === 'arguments' && (m === 'callee' || m === 'caller')) {
+            if (option.noarg)
+                warning("Avoid arguments.{a}.", left, m);
+            else if (directive['use strict'])
+                error('Strict violation.');
         } else if (!option.evil && left && left.value === 'document' &&
                 (m === 'write' || m === 'writeln')) {
             warning("document.write can be a form of eval.", left);
@@ -5495,7 +5863,8 @@ loop:   for (;;) {
         advance(')', this);
         nospace(prevtoken, token);
         if (option.immed && v.id === 'function') {
-            if (nexttoken.id === '(') {
+            if (nexttoken.id === '(' ||
+              (nexttoken.id === '.' && (peek().value === 'call' || peek().value === 'apply'))) {
                 warning(
 "Move the invocation into the parens that contain the function.", nexttoken);
             } else {
@@ -5592,7 +5961,6 @@ loop:   for (;;) {
         nospace();
         if (nexttoken.id === ')') {
             advance(')');
-            nospace(prevtoken, token);
             return;
         }
         for (;;) {
@@ -5635,7 +6003,7 @@ loop:   for (;;) {
         }
         funct['(params)'] = functionparams();
 
-        block(false);
+        block(false, false, true);
         scope = oldScope;
         option = oldOption;
         funct['(last)'] = token.line;
@@ -5646,7 +6014,42 @@ loop:   for (;;) {
 
     (function (x) {
         x.nud = function () {
-            var b, f, i, j, p, seen = {}, t;
+            var b, f, i, j, p, t;
+            var props = {}; // All properties, including accessors
+
+            function saveProperty(name, token) {
+                if (props[name] && is_own(props, name))
+                    warning("Duplicate member '{a}'.", nexttoken, i);
+                else
+                    props[name] = {};
+
+                props[name].basic = true;
+                props[name].basicToken = token;
+            }
+
+            function saveSetter(name, token) {
+                if (props[name] && is_own(props, name)) {
+                    if (props[name].basic || props[name].setter)
+                        warning("Duplicate member '{a}'.", nexttoken, i);
+                } else {
+                    props[name] = {};
+                }
+
+                props[name].setter = true;
+                props[name].setterToken = token;
+            }
+
+            function saveGetter(name) {
+                if (props[name] && is_own(props, name)) {
+                    if (props[name].basic || props[name].getter)
+                        warning("Duplicate member '{a}'.", nexttoken, i);
+                } else {
+                    props[name] = {};
+                }
+
+                props[name].getter = true;
+                props[name].getterToken = token;
+            }
 
             b = token.line !== nexttoken.line;
             if (b) {
@@ -5671,33 +6074,35 @@ loop:   for (;;) {
                     if (!i) {
                         error("Missing property name.");
                     }
+                    saveGetter(i);
                     t = nexttoken;
                     adjacent(token, nexttoken);
                     f = doFunction();
-                    if (!option.loopfunc && funct['(loopage)']) {
-                        warning("Don't make functions within a loop.", t);
-                    }
                     p = f['(params)'];
                     if (p) {
                         warning("Unexpected parameter '{a}' in get {b} function.", t, p[0], i);
                     }
                     adjacent(token, nexttoken);
-                    advance(',');
-                    indentation();
+                } else if (nexttoken.value === 'set' && peek().id !== ':') {
                     advance('set');
-                    j = property_name();
-                    if (i !== j) {
-                        error("Expected {a} and instead saw {b}.", token, i, j);
+                    if (!option.es5) {
+                        error("get/set are ES5 features.");
+                    }
+                    i = property_name();
+                    if (!i) {
+                        error("Missing property name.");
                     }
+                    saveSetter(i, nexttoken);
                     t = nexttoken;
                     adjacent(token, nexttoken);
                     f = doFunction();
                     p = f['(params)'];
-                    if (!p || p.length !== 1 || p[0] !== 'value') {
-                        warning("Expected (value) in set {a} function.", t, i);
+                    if (!p || p.length !== 1) {
+                        warning("Expected a single parameter in set {a} function.", t, i);
                     }
                 } else {
                     i = property_name();
+                    saveProperty(i, nexttoken);
                     if (typeof i !== 'string') {
                         break;
                     }
@@ -5705,10 +6110,7 @@ loop:   for (;;) {
                     nonadjacent(token, nexttoken);
                     expression(10);
                 }
-                if (seen[i] === true) {
-                    warning("Duplicate member '{a}'.", nexttoken, i);
-                }
-                seen[i] = true;
+
                 countMember(i);
                 if (nexttoken.id === ',') {
                     comma();
@@ -5726,6 +6128,15 @@ loop:   for (;;) {
                 indentation();
             }
             advance('}', this);
+
+            // Check for lonely setters if in the ES5 mode.
+            if (option.es5) {
+                for (var name in props) {
+                    if (is_own(props, name) && props[name].setter && !props[name].getter) {
+                        warning("Setter is defined without getter.", props[name].setterToken);
+                    }
+                }
+            }
             return this;
         };
         x.fud = function () {
@@ -5733,27 +6144,85 @@ loop:   for (;;) {
         };
     }(delim('{')));
 
-    var varstatement = stmt('var', function (prefix) {
-        // JavaScript does not have block scope. It only has function scope. So,
-        // declaring a variable in a block can have unexpected consequences.
-        var id, name, value;
+// This Function is called when esnext option is set to true
+// it adds the `const` statement to JSHINT
 
-        if (funct['(onevar)'] && option.onevar) {
-            warning("Too many var statements.");
-        } else if (!funct['(global)']) {
-            funct['(onevar)'] = true;
-        }
-        this.first = [];
-        for (;;) {
-            nonadjacent(token, nexttoken);
-            id = identifier();
-            if (funct['(global)'] && predefined[id] === false) {
-                warning("Redefinition of '{a}'.", token, id);
-            }
-            addlabel(id, 'unused');
-            if (prefix) {
-                break;
-            }
+    useESNextSyntax = function () {
+        var conststatement = stmt('const', function (prefix) {
+            var id, name, value;
+
+            this.first = [];
+            for (;;) {
+                nonadjacent(token, nexttoken);
+                id = identifier();
+                if (funct[id] === "const") {
+                    warning("const '" + id + "' has already been declared");
+                }
+                if (funct['(global)'] && predefined[id] === false) {
+                    warning("Redefinition of '{a}'.", token, id);
+                }
+                addlabel(id, 'const');
+                if (prefix) {
+                    break;
+                }
+                name = token;
+                this.first.push(token);
+
+                if (nexttoken.id !== "=") {
+                    warning("const " +
+                      "'{a}' is initialized to 'undefined'.", token, id);
+                }
+
+                if (nexttoken.id === '=') {
+                    nonadjacent(token, nexttoken);
+                    advance('=');
+                    nonadjacent(token, nexttoken);
+                    if (nexttoken.id === 'undefined') {
+                        warning("It is not necessary to initialize " +
+                          "'{a}' to 'undefined'.", token, id);
+                    }
+                    if (peek(0).id === '=' && nexttoken.identifier) {
+                        error("Constant {a} was not declared correctly.",
+                                nexttoken, nexttoken.value);
+                    }
+                    value = expression(0);
+                    name.first = value;
+                }
+
+                if (nexttoken.id !== ',') {
+                    break;
+                }
+                comma();
+            }
+            return this;
+        });
+        conststatement.exps = true;
+    };
+
+    var varstatement = stmt('var', function (prefix) {
+        // JavaScript does not have block scope. It only has function scope. So,
+        // declaring a variable in a block can have unexpected consequences.
+        var id, name, value;
+
+        if (funct['(onevar)'] && option.onevar) {
+            warning("Too many var statements.");
+        } else if (!funct['(global)']) {
+            funct['(onevar)'] = true;
+        }
+        this.first = [];
+        for (;;) {
+            nonadjacent(token, nexttoken);
+            id = identifier();
+            if (option.esnext && funct[id] === "const") {
+                warning("const '" + id + "' has already been declared");
+            }
+            if (funct['(global)'] && predefined[id] === false) {
+                warning("Redefinition of '{a}'.", token, id);
+            }
+            addlabel(id, 'unused');
+            if (prefix) {
+                break;
+            }
             name = token;
             this.first.push(token);
             if (nexttoken.id === '=') {
@@ -5787,6 +6256,9 @@ loop:   for (;;) {
 
         }
         var i = identifier();
+        if (option.esnext && funct[i] === "const") {
+            warning("const '" + i + "' has already been declared");
+        }
         adjacent(token, nexttoken);
         addlabel(i, 'unction');
         doFunction(i, true);
@@ -5894,7 +6366,24 @@ loop:   for (;;) {
         return this;
     }).labelled = true;
 
-    reserve('with');
+    blockstmt('with', function () {
+        var t = nexttoken;
+        if (directive['use strict']) {
+            error("'with' is not allowed in strict mode.", token);
+        } else if (!option.withstmt) {
+            warning("Don't use 'with'.", token);
+        }
+
+        advance('(');
+        nonadjacent(this, t);
+        nospace();
+        expression(0);
+        advance(')', t);
+        nospace(prevtoken, token);
+        block(true, true);
+
+        return this;
+    });
 
     blockstmt('switch', function () {
         var t = nexttoken,
@@ -5965,7 +6454,8 @@ loop:   for (;;) {
                 advance('}', t);
                 if (this.cases.length === 1 || this.condition.id === 'true' ||
                         this.condition.id === 'false') {
-                    warning("This 'switch' should be an 'if'.", this);
+                    if (!option.onecase)
+                        warning("This 'switch' should be an 'if'.", this);
                 }
                 funct['(breakage)'] -= 1;
                 funct['(verb)'] = undefined;
@@ -5980,14 +6470,23 @@ loop:   for (;;) {
                         error("Each value should have its own case label.");
                         return;
                     case ':':
+                        g = false;
                         statements();
                         break;
                     default:
                         error("Missing ':' on a case clause.", token);
+                        return;
                     }
                 } else {
-                    error("Expected '{a}' and instead saw '{b}'.",
-                        nexttoken, 'case', nexttoken.value);
+                    if (token.id === ':') {
+                        advance(':');
+                        error("Unexpected '{a}'.", token, ':');
+                        statements();
+                    } else {
+                        error("Expected '{a}' and instead saw '{b}'.",
+                            nexttoken, 'case', nexttoken.value);
+                        return;
+                    }
                 }
             }
         }
@@ -6055,7 +6554,7 @@ loop:   for (;;) {
             expression(20);
             advance(')', t);
             s = block(true, true);
-            if (option.forin && (s.length > 1 || typeof s[0] !== 'object' ||
+            if (option.forin && s && (s.length > 1 || typeof s[0] !== 'object' ||
                     s[0].value !== 'if')) {
                 warning("The body of a for in should be wrapped in an if statement to filter " +
                         "unwanted properties from the prototype.", this);
@@ -6116,10 +6615,13 @@ loop:   for (;;) {
 
     stmt('break', function () {
         var v = nexttoken.value;
-        if (funct['(breakage)'] === 0) {
+
+        if (funct['(breakage)'] === 0)
             warning("Unexpected '{a}'.", nexttoken, this.value);
-        }
-        nolinebreak(this);
+
+        if (!option.asi)
+            nolinebreak(this);
+
         if (nexttoken.id !== ';') {
             if (token.line === nexttoken.line) {
                 if (funct[v] !== 'label') {
@@ -6138,10 +6640,13 @@ loop:   for (;;) {
 
     stmt('continue', function () {
         var v = nexttoken.value;
-        if (funct['(breakage)'] === 0) {
+
+        if (funct['(breakage)'] === 0)
             warning("Unexpected '{a}'.", nexttoken, this.value);
-        }
-        nolinebreak(this);
+
+        if (!option.asi)
+            nolinebreak(this);
+
         if (nexttoken.id !== ';') {
             if (token.line === nexttoken.line) {
                 if (funct[v] !== 'label') {
@@ -6161,13 +6666,20 @@ loop:   for (;;) {
 
 
     stmt('return', function () {
-        nolinebreak(this);
-        if (nexttoken.id === '(regexp)') {
-            warning("Wrap the /regexp/ literal in parens to disambiguate the slash operator.");
-        }
-        if (nexttoken.id !== ';' && !nexttoken.reach) {
-            nonadjacent(token, nexttoken);
-            this.first = expression(20);
+        if (this.line === nexttoken.line) {
+            if (nexttoken.id === '(regexp)')
+                warning("Wrap the /regexp/ literal in parens to disambiguate the slash operator.");
+
+            if (nexttoken.id !== ';' && !nexttoken.reach) {
+                nonadjacent(token, nexttoken);
+                if (peek().value === "=" && !option.boss) {
+                    warningAt("Did you mean to return a conditional instead of an assignment?",
+                              token.line, token.character + 1);
+                }
+                this.first = expression(0);
+            }
+        } else if (!option.asi) {
+            nolinebreak(this); // always warn (Line breaking error)
         }
         reachable('return');
         return this;
@@ -6230,8 +6742,8 @@ loop:   for (;;) {
                     } else if ((nexttoken.value === '__proto__' &&
                         !option.proto) || (nexttoken.value === '__iterator__' &&
                         !option.iterator)) {
-                            warning("The '{a}' key may produce unexpected results.",
-                                nexttoken, nexttoken.value);
+                        warning("The '{a}' key may produce unexpected results.",
+                            nexttoken, nexttoken.value);
                     } else {
                         o[nexttoken.value] = true;
                     }
@@ -6304,6 +6816,7 @@ loop:   for (;;) {
     var itself = function (s, o, g) {
         var a, i, k;
         JSHINT.errors = [];
+        JSHINT.undefs = [];
         predefined = Object.create(standard);
         combine(predefined, g || {});
         if (o) {
@@ -6343,7 +6856,6 @@ loop:   for (;;) {
         };
         functions = [funct];
         urls = [];
-        src = false;
         stack = null;
         member = {};
         membersOnly = null;
@@ -6354,11 +6866,25 @@ loop:   for (;;) {
         warnings = 0;
         lex.init(s);
         prereg = true;
-        strict_mode = false;
+        directive = {};
 
         prevtoken = token = nexttoken = syntax['(begin)'];
+
+        // Check options
+        for (var name in o) {
+            if (is_own(o, name)) {
+                checkOption(name, token);
+            }
+        }
+
         assume();
 
+        // combine the passed globals after we've assumed all our options
+        combine(predefined, g || {});
+
+        //reset values
+        comma.first = true;
+
         try {
             advance();
             switch (nexttoken.id) {
@@ -6369,32 +6895,83 @@ loop:   for (;;) {
                 jsonValue();
                 break;
             default:
-                if (nexttoken.value === 'use strict') {
-                    if (!option.globalstrict)
-                        warning("Use the function form of \"use strict\".");
-                    use_strict();
+                directives();
+                if (directive["use strict"] && !option.globalstrict) {
+                    warning("Use the function form of \"use strict\".", prevtoken);
                 }
-                statements('lib');
+
+                statements();
             }
             advance('(end)');
+
+            var markDefined = function (name, context) {
+                do {
+                    if (typeof context[name] === 'string') {
+                        // JSHINT marks unused variables as 'unused' and
+                        // unused function declaration as 'unction'. This
+                        // code changes such instances back 'var' and
+                        // 'closure' so that the code in JSHINT.data()
+                        // doesn't think they're unused.
+
+                        if (context[name] === 'unused')
+                            context[name] = 'var';
+                        else if (context[name] === 'unction')
+                            context[name] = 'closure';
+
+                        return true;
+                    }
+
+                    context = context['(context)'];
+                } while (context);
+
+                return false;
+            };
+
+            var clearImplied = function (name, line) {
+                if (!implied[name])
+                    return;
+
+                var newImplied = [];
+                for (var i = 0; i < implied[name].length; i += 1) {
+                    if (implied[name][i] !== line)
+                        newImplied.push(implied[name][i]);
+                }
+
+                if (newImplied.length === 0)
+                    delete implied[name];
+                else
+                    implied[name] = newImplied;
+            };
+
+            // Check queued 'x is not defined' instances to see if they're still undefined.
+            for (i = 0; i < JSHINT.undefs.length; i += 1) {
+                k = JSHINT.undefs[i].slice(0);
+
+                if (markDefined(k[2].value, k[0])) {
+                    clearImplied(k[2].value, k[2].line);
+                } else {
+                    warning.apply(warning, k.slice(1));
+                }
+            }
         } catch (e) {
             if (e) {
+                var nt = nexttoken || {};
                 JSHINT.errors.push({
+                    raw       : e.raw,
                     reason    : e.message,
-                    line      : e.line || nexttoken.line,
-                    character : e.character || nexttoken.from
+                    line      : e.line || nt.line,
+                    character : e.character || nt.from
                 }, null);
             }
         }
+
         return JSHINT.errors.length === 0;
     };
 
-
-// Data summary.
-
+    // Data summary.
     itself.data = function () {
 
-        var data = {functions: []}, fu, globals, implieds = [], f, i, j,
+        var data = { functions: [], options: option }, fu, globals, implieds = [], f, i, j,
             members = [], n, unused = [], v;
         if (itself.errors.length) {
             data.errors = itself.errors;
@@ -6424,7 +7001,6 @@ loop:   for (;;) {
         if (globals.length > 0) {
             data.globals = globals;
         }
-
         for (i = 1; i < functions.length; i += 1) {
             f = functions[i];
             fu = {};
@@ -6602,16 +7178,14 @@ loop:   for (;;) {
         }
         return o.join('');
     };
-    itself.jshint = itself;
 
-    itself.edition = '2011-04-16';
+    itself.jshint = itself;
 
     return itself;
-
 }());
 
 // Make JSHINT a Node module, if possible.
-if (typeof exports == 'object' && exports)
+if (typeof exports === 'object' && exports)
     exports.JSHINT = JSHINT;
 
 });/* -*- Mode: JS; tab-width: 4; indent-tabs-mode: nil; -*-
@@ -6665,598 +7239,648 @@ if (typeof exports == 'object' && exports)
  * Parser.
  */
 
-define('ace/narcissus/jsparse', ['require', 'exports', 'module' , 'ace/narcissus/jslex', 'ace/narcissus/jsdefs'], function(require, exports, module) {
-
-    var lexer = require("./jslex");
-    var definitions = require("./jsdefs");
-
-    const StringMap = definitions.StringMap;
-    const Stack = definitions.Stack;
+define('ace/narcissus/parser', ['require', 'exports', 'module' , 'ace/narcissus/lexer', 'ace/narcissus/definitions', 'ace/narcissus/options'], function(require, exports, module) {
 
-    // Set constants in the local scope.
-    eval(definitions.consts);
+var lexer = require('./lexer');
+var definitions = require('./definitions');
+var options = require('./options');
+var Tokenizer = lexer.Tokenizer;
 
-    // Banned statement types by language version.
-    const blackLists = { 160: {}, 185: {}, harmony: {} };
-    blackLists[160][IMPORT] = true;
-    blackLists[160][EXPORT] = true;
-    blackLists[160][LET] = true;
-    blackLists[160][MODULE] = true;
-    blackLists[160][YIELD] = true;
-    blackLists[185][IMPORT] = true;
-    blackLists[185][EXPORT] = true;
-    blackLists[185][MODULE] = true;
-    blackLists.harmony[WITH] = true;
-
-    /*
-     * pushDestructuringVarDecls :: (node, hoisting node) -> void
-     *
-     * Recursively add all destructured declarations to varDecls.
-     */
-    function pushDestructuringVarDecls(n, s) {
-        for (var i in n) {
-            var sub = n[i];
-            if (sub.type === IDENTIFIER) {
-                s.varDecls.push(sub);
-            } else {
-                pushDestructuringVarDecls(sub, s);
-            }
-        }
-    }
-
-    function StaticContext(parentScript, parentBlock, inModule, inFunction) {
-        this.parentScript = parentScript;
-        this.parentBlock = parentBlock || parentScript;
-        this.inModule = inModule || false;
-        this.inFunction = inFunction || false;
-        this.inForLoopInit = false;
-        this.topLevel = true;
-        this.allLabels = new Stack();
-        this.currentLabels = new Stack();
-        this.labeledTargets = new Stack();
-        this.defaultLoopTarget = null;
-        this.defaultTarget = null;
-        this.blackList = blackLists[Narcissus.options.version];
-        Narcissus.options.ecma3OnlyMode && (this.ecma3OnlyMode = true);
-        Narcissus.options.parenFreeMode && (this.parenFreeMode = true);
-    }
-
-    StaticContext.prototype = {
-        ecma3OnlyMode: false,
-        parenFreeMode: false,
-        // non-destructive update via prototype extension
-        update: function(ext) {
-            var desc = {};
-            for (var key in ext) {
-                desc[key] = {
-                    value: ext[key],
-                    writable: true,
-                    enumerable: true,
-                    configurable: true
-                }
-            }
-            return Object.create(this, desc);
-        },
-        pushLabel: function(label) {
-            return this.update({ currentLabels: this.currentLabels.push(label),
-                                 allLabels: this.allLabels.push(label) });
-        },
-        pushTarget: function(target) {
-            var isDefaultLoopTarget = target.isLoop;
-            var isDefaultTarget = isDefaultLoopTarget || target.type === SWITCH;
+var Dict = definitions.Dict;
+var Stack = definitions.Stack;
 
-            if (this.currentLabels.isEmpty()) {
-                if (isDefaultLoopTarget) this.update({ defaultLoopTarget: target });
-                if (isDefaultTarget) this.update({ defaultTarget: target });
-                return this;
-            }
+// Set constants in the local scope.
+eval(definitions.consts);
 
-            target.labels = new StringMap();
-            this.currentLabels.forEach(function(label) {
-                target.labels.set(label, true);
-            });
-            return this.update({ currentLabels: new Stack(),
-                                 labeledTargets: this.labeledTargets.push(target),
-                                 defaultLoopTarget: isDefaultLoopTarget
-                                                    ? target
-                                                    : this.defaultLoopTarget,
-                                 defaultTarget: isDefaultTarget
-                                                ? target
-                                                : this.defaultTarget });
-        },
-        nest: function() {
-            return this.topLevel ? this.update({ topLevel: false }) : this;
-        },
-        allow: function(type) {
-            switch (type) {
-              case EXPORT:
-                if (!this.inModule || this.inFunction || !this.topLevel)
-                    return false;
-                // FALL THROUGH
+/*
+ * pushDestructuringVarDecls :: (node, hoisting node) -> void
+ *
+ * Recursively add all destructured declarations to varDecls.
+ */
+function pushDestructuringVarDecls(n, s) {
+    for (var i in n) {
+        var sub = n[i];
+        if (sub.type === IDENTIFIER) {
+            s.varDecls.push(sub);
+        } else {
+            pushDestructuringVarDecls(sub, s);
+        }
+    }
+}
 
-              case IMPORT:
-                return !this.inFunction && this.topLevel;
+function Parser(tokenizer) {
+    tokenizer.parser = this;
+    this.t = tokenizer;
+    this.x = null;
+    this.unexpectedEOF = false;
+    options.mozillaMode && (this.mozillaMode = true);
+    options.parenFreeMode && (this.parenFreeMode = true);
+}
 
-              case MODULE:
-                return !this.inFunction && this.topLevel;
+function StaticContext(parentScript, parentBlock, inModule, inFunction, strictMode) {
+    this.parentScript = parentScript;
+    this.parentBlock = parentBlock || parentScript;
+    this.inModule = inModule || false;
+    this.inFunction = inFunction || false;
+    this.inForLoopInit = false;
+    this.topLevel = true;
+    this.allLabels = new Stack();
+    this.currentLabels = new Stack();
+    this.labeledTargets = new Stack();
+    this.defaultLoopTarget = null;
+    this.defaultTarget = null;
+    this.strictMode = strictMode;
+}
 
-              default:
-                return true;
-            }
+StaticContext.prototype = {
+    // non-destructive update via prototype extension
+    update: function(ext) {
+        var desc = {};
+        for (var key in ext) {
+            desc[key] = {
+                value: ext[key],
+                writable: true,
+                enumerable: true,
+                configurable: true
+            }
+        }
+        return Object.create(this, desc);
+    },
+    pushLabel: function(label) {
+        return this.update({ currentLabels: this.currentLabels.push(label),
+                             allLabels: this.allLabels.push(label) });
+    },
+    pushTarget: function(target) {
+        var isDefaultLoopTarget = target.isLoop;
+        var isDefaultTarget = isDefaultLoopTarget || target.type === SWITCH;
+
+        if (this.currentLabels.isEmpty()) {
+            if (isDefaultLoopTarget) this.update({ defaultLoopTarget: target });
+            if (isDefaultTarget) this.update({ defaultTarget: target });
+            return this;
         }
-    };
 
-    /*
-     * Script :: (tokenizer, boolean, boolean) -> node
-     *
-     * Parses the toplevel and module/function bodies.
-     */
-    function Script(t, inModule, inFunction) {
-        var n = new Node(t, scriptInit());
-        Statements(t, new StaticContext(n, n, inModule, inFunction), n);
-        return n;
+        target.labels = new Dict();
+        this.currentLabels.forEach(function(label) {
+            target.labels.set(label, true);
+        });
+        return this.update({ currentLabels: new Stack(),
+                             labeledTargets: this.labeledTargets.push(target),
+                             defaultLoopTarget: isDefaultLoopTarget
+                             ? target
+                             : this.defaultLoopTarget,
+                             defaultTarget: isDefaultTarget
+                             ? target
+                             : this.defaultTarget });
+    },
+    nest: function() {
+        return this.topLevel ? this.update({ topLevel: false }) : this;
+    },
+    canImport: function() {
+        return this.topLevel && !this.inFunction;
+    },
+    canExport: function() {
+        return this.inModule && this.topLevel && !this.inFunction;
+    },
+    banWith: function() {
+        return this.strictMode || this.inModule;
+    },
+    modulesAllowed: function() {
+        return this.topLevel && !this.inFunction;
     }
+};
 
-    // We extend Array slightly with a top-of-stack method.
-    definitions.defineProperty(Array.prototype, "top",
-                               function() {
-                                   return this.length && this[this.length-1];
-                               }, false, false, true);
+var Pp = Parser.prototype;
 
-    /*
-     * Node :: (tokenizer, optional init object) -> node
-     */
-    function Node(t, init) {
-        var token = t.token;
-        if (token) {
-            // If init.type exists it will override token.type.
-            this.type = token.type;
-            this.value = token.value;
-            this.lineno = token.lineno;
-
-            // Start and end are file positions for error handling.
-            this.start = token.start;
-            this.end = token.end;
-        } else {
-            this.lineno = t.lineno;
-        }
+Pp.mozillaMode = false;
 
-        // Node uses a tokenizer for debugging (getSource, filename getter).
-        this.tokenizer = t;
-        this.children = [];
+Pp.parenFreeMode = false;
 
-        for (var prop in init)
-            this[prop] = init[prop];
-    }
+Pp.withContext = function(x, f) {
+    var x0 = this.x;
+    this.x = x;
+    var result = f.call(this);
+    // NB: we don't bother with finally, since exceptions trash the parser
+    this.x = x0;
+    return result;
+};
 
-    /*
-     * SyntheticNode :: (tokenizer, optional init object) -> node
-     */
-    function SyntheticNode(t, init) {
-        // print("SYNTHETIC NODE");
-        // if (init.type === COMMA) {
-        //     print("SYNTHETIC COMMA");
-        //     print(init);
-        // }
-        this.tokenizer = t;
-        this.children = [];
-        for (var prop in init)
-            this[prop] = init[prop];
-        this.synthetic = true;
-    }
-
-    var Np = Node.prototype = SyntheticNode.prototype = {};
-    Np.constructor = Node;
-
-    const TO_SOURCE_SKIP = {
-        type: true,
-        value: true,
-        lineno: true,
-        start: true,
-        end: true,
-        tokenizer: true,
-        assignOp: true
-    };
-    function unevalableConst(code) {
-        var token = definitions.tokens[code];
-        var constName = definitions.opTypeNames.hasOwnProperty(token)
-                      ? definitions.opTypeNames[token]
-                      : token in definitions.keywords
-                      ? token.toUpperCase()
-                      : token;
-        return { toSource: function() { return constName } };
-    }
-    Np.toSource = function toSource() {
-        var mock = {};
-        var self = this;
-        mock.type = unevalableConst(this.type);
-        if ("value" in this)
-            mock.value = this.value;
-        if ("lineno" in this)
-            mock.lineno = this.lineno;
-        if ("start" in this)
-            mock.start = this.start;
-        if ("end" in this)
-            mock.end = this.end;
-        if (this.assignOp)
-            mock.assignOp = unevalableConst(this.assignOp);
-        for (var key in this) {
-            if (this.hasOwnProperty(key) && !(key in TO_SOURCE_SKIP))
-                mock[key] = this[key];
-        }
-        return mock.toSource();
-    };
+Pp.newNode = function newNode(opts) {
+    return new Node(this.t, opts);
+};
 
-    // Always use push to add operands to an expression, to update start and end.
-    Np.push = function (kid) {
-        // kid can be null e.g. [1, , 2].
-        if (kid !== null) {
-            if (kid.start < this.start)
-                this.start = kid.start;
-            if (this.end < kid.end)
-                this.end = kid.end;
-        }
-        return this.children.push(kid);
-    }
+Pp.fail = function fail(msg) {
+    throw this.t.newSyntaxError(msg);
+};
 
-    Node.indentLevel = 0;
+Pp.match = function match(tt, scanOperand, keywordIsName) {
+    return this.t.match(tt, scanOperand, keywordIsName);
+};
 
-    function tokenString(tt) {
-        var t = definitions.tokens[tt];
-        return /^\W/.test(t) ? definitions.opTypeNames[t] : t.toUpperCase();
-    }
+Pp.mustMatch = function mustMatch(tt, keywordIsName) {
+    return this.t.mustMatch(tt, keywordIsName);
+};
 
-    Np.toString = function () {
-        var a = [];
-        for (var i in this) {
-            if (this.hasOwnProperty(i) && i !== 'type' && i !== 'target')
-                a.push({id: i, value: this[i]});
-        }
-        a.sort(function (a,b) { return (a.id < b.id) ? -1 : 1; });
-        const INDENTATION = "    ";
-        var n = ++Node.indentLevel;
-        var s = "{\n" + INDENTATION.repeat(n) + "type: " + tokenString(this.type);
-        for (i = 0; i < a.length; i++)
-            s += ",\n" + INDENTATION.repeat(n) + a[i].id + ": " + a[i].value;
-        n = --Node.indentLevel;
-        s += "\n" + INDENTATION.repeat(n) + "}";
-        return s;
-    }
+Pp.peek = function peek(scanOperand) {
+    return this.t.peek(scanOperand);
+};
 
-    Np.getSource = function () {
-        return this.tokenizer.source.slice(this.start, this.end);
-    };
+Pp.peekOnSameLine = function peekOnSameLine(scanOperand) {
+    return this.t.peekOnSameLine(scanOperand);
+};
 
-    /*
-     * Helper init objects for common nodes.
-     */
+Pp.done = function done() {
+    return this.t.done;
+};
 
-    const LOOP_INIT = { isLoop: true };
+/*
+ * Script :: (boolean, boolean, boolean) -> node
+ *
+ * Parses the toplevel and module/function bodies.
+ */
+Pp.Script = function Script(inModule, inFunction, expectEnd) {
+    var node = this.newNode(scriptInit());
+    var x2 = new StaticContext(node, node, inModule, inFunction);
+    this.withContext(x2, function() {
+        this.Statements(node, true);
+    });
+    if (expectEnd && !this.done())
+        this.fail("expected end of input");
+    return node;
+};
 
-    function blockInit() {
-        return { type: BLOCK, varDecls: [] };
+/*
+ * Pragma :: (expression statement node) -> boolean
+ *
+ * Checks whether a node is a pragma and annotates it.
+ */
+function Pragma(n) {
+    if (n.type === SEMICOLON) {
+        var e = n.expression;
+        if (e.type === STRING && e.value === "use strict") {
+            n.pragma = "strict";
+            return true;
+        }
     }
+    return false;
+}
 
-    function scriptInit() {
-        return { type: SCRIPT,
-                 funDecls: [],
-                 varDecls: [],
-                 modDefns: new StringMap(),
-                 modAssns: new StringMap(),
-                 modDecls: new StringMap(),
-                 modLoads: new StringMap(),
-                 impDecls: [],
-                 expDecls: [],
-                 exports: new StringMap(),
-                 hasEmptyReturn: false,
-                 hasReturnWithValue: false,
-                 isGenerator: false };
+/*
+ * Node :: (tokenizer, optional init object) -> node
+ */
+function Node(t, init) {
+    var token = t.token;
+    if (token) {
+        // If init.type exists it will override token.type.
+        this.type = token.type;
+        this.value = token.value;
+        this.lineno = token.lineno;
+
+        // Start and end are file positions for error handling.
+        this.start = token.start;
+        this.end = token.end;
+    } else {
+        this.lineno = t.lineno;
     }
 
-    definitions.defineGetter(Np, "filename",
-                             function() {
-                                 return this.tokenizer.filename;
-                             });
-
-    definitions.defineGetter(Np, "length",
-                             function() {
-                                 throw new Error("Node.prototype.length is gone; " +
-                                                 "use n.children.length instead");
-                             });
+    this.filename = t.filename;
+    this.children = [];
 
-    definitions.defineProperty(String.prototype, "repeat",
-                               function(n) {
-                                   var s = "", t = this + s;
-                                   while (--n >= 0)
-                                       s += t;
-                                   return s;
-                               }, false, false, true);
+    for (var prop in init)
+        this[prop] = init[prop];
+}
 
-    function MaybeLeftParen(t, x) {
-        if (x.parenFreeMode)
-            return t.match(LEFT_PAREN) ? LEFT_PAREN : END;
-        return t.mustMatch(LEFT_PAREN).type;
-    }
+/*
+ * SyntheticNode :: (optional init object) -> node
+ */
+function SyntheticNode(init) {
+    this.children = [];
+    for (var prop in init)
+        this[prop] = init[prop];
+    this.synthetic = true;
+}
 
-    function MaybeRightParen(t, p) {
-        if (p === LEFT_PAREN)
-            t.mustMatch(RIGHT_PAREN);
+var Np = Node.prototype = SyntheticNode.prototype = {};
+Np.constructor = Node;
+
+var TO_SOURCE_SKIP = {
+    type: true,
+    value: true,
+    lineno: true,
+    start: true,
+    end: true,
+    tokenizer: true,
+    assignOp: true
+};
+function unevalableConst(code) {
+    var token = definitions.tokens[code];
+    var constName = definitions.opTypeNames.hasOwnProperty(token)
+        ? definitions.opTypeNames[token]
+        : token in definitions.keywords
+        ? token.toUpperCase()
+        : token;
+    return { toSource: function() { return constName } };
+}
+Np.toSource = function toSource() {
+    var mock = {};
+    var self = this;
+    mock.type = unevalableConst(this.type);
+    // avoid infinite recursion in case of back-links
+    if (this.generatingSource)
+        return mock.toSource();
+    this.generatingSource = true;
+    if ("value" in this)
+        mock.value = this.value;
+    if ("lineno" in this)
+        mock.lineno = this.lineno;
+    if ("start" in this)
+        mock.start = this.start;
+    if ("end" in this)
+        mock.end = this.end;
+    if (this.assignOp)
+        mock.assignOp = unevalableConst(this.assignOp);
+    for (var key in this) {
+        if (this.hasOwnProperty(key) && !(key in TO_SOURCE_SKIP))
+            mock[key] = this[key];
     }
-
-    /*
-     * Statements :: (tokenizer, compiler context, node) -> void
-     *
-     * Parses a sequence of Statements.
-     */
-    function Statements(t, x, n) {
-        try {
-            while (!t.done && t.peek(true) !== RIGHT_CURLY)
-                n.push(Statement(t, x));
-        } catch (e) {
-            if (t.done)
-                t.unexpectedEOF = true;
-            throw e;
-        }
+    try {
+        return mock.toSource();
+    } finally {
+        delete this.generatingSource;
     }
+};
 
-    function Block(t, x) {
-        t.mustMatch(LEFT_CURLY);
-        var n = new Node(t, blockInit());
-        Statements(t, x.update({ parentBlock: n }).pushTarget(n), n);
-        t.mustMatch(RIGHT_CURLY);
-        return n;
+// Always use push to add operands to an expression, to update start and end.
+Np.push = function (kid) {
+    // kid can be null e.g. [1, , 2].
+    if (kid !== null) {
+        if (kid.start < this.start)
+            this.start = kid.start;
+        if (this.end < kid.end)
+            this.end = kid.end;
     }
+    return this.children.push(kid);
+}
 
-    const DECLARED_FORM = 0, EXPRESSED_FORM = 1, STATEMENT_FORM = 2;
+Node.indentLevel = 0;
 
-    /*
-     * Export :: (binding node, boolean) -> Export
-     *
-     * Static semantic representation of a module export.
-     */
-    function Export(node, isDefinition) {
-        this.node = node;                 // the AST node declaring this individual export
-        this.isDefinition = isDefinition; // is the node an 'export'-annotated definition?
-        this.resolved = null;             // resolved pointer to the target of this export
-    }
+function tokenString(tt) {
+    var t = definitions.tokens[tt];
+    return /^\W/.test(t) ? definitions.opTypeNames[t] : t.toUpperCase();
+}
 
-    /*
-     * registerExport :: (StringMap, EXPORT node) -> void
-     */
-    function registerExport(exports, decl) {
-        function register(name, exp) {
-            if (exports.has(name))
-                throw new SyntaxError("multiple exports of " + name);
-            exports.set(name, exp);
-        }
+Np.toString = function () {
+    var a = [];
+    for (var i in this) {
+        if (this.hasOwnProperty(i) && i !== 'type' && i !== 'target')
+            a.push({id: i, value: this[i]});
+    }
+    a.sort(function (a,b) { return (a.id < b.id) ? -1 : 1; });
+    var INDENTATION = "    ";
+    var n = ++Node.indentLevel;
+    var s = "{\n" + INDENTATION.repeat(n) + "type: " + tokenString(this.type);
+    for (i = 0; i < a.length; i++)
+        s += ",\n" + INDENTATION.repeat(n) + a[i].id + ": " + a[i].value;
+    n = --Node.indentLevel;
+    s += "\n" + INDENTATION.repeat(n) + "}";
+    return s;
+}
 
-        switch (decl.type) {
-          case MODULE:
-          case FUNCTION:
-            register(decl.name, new Export(decl, true));
-            break;
+Np.synth = function(init) {
+    var node = new SyntheticNode(init);
+    node.filename = this.filename;
+    node.lineno = this.lineno;
+    node.start = this.start;
+    node.end = this.end;
+    return node;
+};
 
-          case VAR:
-            for (var i = 0; i < decl.children.length; i++)
-                register(decl.children[i].name, new Export(decl.children[i], true));
-            break;
+/*
+ * Helper init objects for common nodes.
+ */
 
-          case LET:
-          case CONST:
-            throw new Error("NYI: " + definitions.tokens[decl.type]);
-
-          case EXPORT:
-            for (var i = 0; i < decl.pathList.length; i++) {
-                var path = decl.pathList[i];
-                switch (path.type) {
-                  case OBJECT_INIT:
-                    for (var j = 0; j < path.children.length; j++) {
-                        // init :: IDENTIFIER | PROPERTY_INIT
-                        var init = path.children[j];
-                        if (init.type === IDENTIFIER)
-                            register(init.value, new Export(init, false));
-                        else
-                            register(init.children[0].value, new Export(init.children[1], false));
-                    }
-                    break;
+var LOOP_INIT = { isLoop: true };
 
-                  case DOT:
-                    register(path.children[1].value, new Export(path, false));
-                    break;
+function blockInit() {
+    return { type: BLOCK, varDecls: [] };
+}
 
-                  case IDENTIFIER:
-                    register(path.value, new Export(path, false));
-                    break;
+function scriptInit() {
+    return { type: SCRIPT,
+             funDecls: [],
+             varDecls: [],
+             modDefns: new Dict(),
+             modAssns: new Dict(),
+             modDecls: new Dict(),
+             modLoads: new Dict(),
+             impDecls: [],
+             expDecls: [],
+             exports: new Dict(),
+             hasEmptyReturn: false,
+             hasReturnWithValue: false,
+             hasYield: false };
+}
 
-                  default:
-                    throw new Error("unexpected export path: " + definitions.tokens[path.type]);
-                }
-            }
-            break;
+definitions.defineGetter(Np, "length",
+                         function() {
+                             throw new Error("Node.prototype.length is gone; " +
+                                             "use n.children.length instead");
+                         });
+
+definitions.defineProperty(String.prototype, "repeat",
+                           function(n) {
+                               var s = "", t = this + s;
+                               while (--n >= 0)
+                                   s += t;
+                               return s;
+                           }, false, false, true);
+
+Pp.MaybeLeftParen = function MaybeLeftParen() {
+    if (this.parenFreeMode)
+        return this.match(LEFT_PAREN) ? LEFT_PAREN : END;
+    return this.mustMatch(LEFT_PAREN).type;
+};
 
-          default:
-            throw new Error("unexpected export decl: " + definitions.tokens[exp.type]);
-        }
-    }
+Pp.MaybeRightParen = function MaybeRightParen(p) {
+    if (p === LEFT_PAREN)
+        this.mustMatch(RIGHT_PAREN);
+}
 
-    /*
-     * Module :: (node) -> Module
-     *
-     * Static semantic representation of a module.
-     */
-    function Module(node) {
-        var exports = node.body.exports;
-        var modDefns = node.body.modDefns;
-
-        var exportedModules = new StringMap();
-
-        exports.forEach(function(name, exp) {
-            var node = exp.node;
-            if (node.type === MODULE) {
-                exportedModules.set(name, node);
-            } else if (!exp.isDefinition && node.type === IDENTIFIER && modDefns.has(node.value)) {
-                var mod = modDefns.get(node.value);
-                exportedModules.set(name, mod);
+/*
+ * Statements :: (node[, boolean]) -> void
+ *
+ * Parses a sequence of Statements.
+ */
+Pp.Statements = function Statements(n, topLevel) {
+    var prologue = !!topLevel;
+    try {
+        while (!this.done() && this.peek(true) !== RIGHT_CURLY) {
+            var n2 = this.Statement();
+            n.push(n2);
+            if (prologue && Pragma(n2)) {
+                this.x.strictMode = true;
+                n.strict = true;
+            } else {
+                prologue = false;
             }
-        });
-
-        this.node = node;
-        this.exports = exports;
-        this.exportedModules = exportedModules;
+        }
+    } catch (e) {
+        try {
+            if (this.done())
+                this.unexpectedEOF = true;
+        } catch(e) {}
+        throw e;
     }
+}
 
-    /*
-     * Statement :: (tokenizer, compiler context) -> node
-     *
-     * Parses a Statement.
-     */
-    function Statement(t, x) {
-        var i, label, n, n2, p, c, ss, tt = t.get(true), tt2, x2, x3;
+Pp.Block = function Block() {
+    this.mustMatch(LEFT_CURLY);
+    var n = this.newNode(blockInit());
+    var x2 = this.x.update({ parentBlock: n }).pushTarget(n);
+    this.withContext(x2, function() {
+        this.Statements(n);
+    });
+    this.mustMatch(RIGHT_CURLY);
+    return n;
+}
 
-        var comments = t.blockComments;
+var DECLARED_FORM = 0, EXPRESSED_FORM = 1, STATEMENT_FORM = 2;
 
-        if (x.blackList[tt])
-            throw t.newSyntaxError(definitions.tokens[tt] + " statements only allowed in Harmony");
-        if (!x.allow(tt))
-            throw t.newSyntaxError(definitions.tokens[tt] + " statement in illegal context");
+/*
+ * Export :: (binding node, boolean) -> Export
+ *
+ * Static semantic representation of a module export.
+ */
+function Export(node, isDefinition) {
+    this.node = node;                 // the AST node declaring this individual export
+    this.isDefinition = isDefinition; // is the node an 'export'-annotated definition?
+    this.resolved = null;             // resolved pointer to the target of this export
+}
 
-        // Cases for statements ending in a right curly return early, avoiding the
-        // common semicolon insertion magic after this switch.
-        switch (tt) {
-          case IMPORT:
-            n = new Node(t);
-            n.pathList = ImportPathList(t, x);
-            x.parentScript.impDecls.push(n);
-            break;
+/*
+ * registerExport :: (Dict, EXPORT node) -> void
+ */
+function registerExport(exports, decl) {
+    function register(name, exp) {
+        if (exports.has(name))
+            throw new SyntaxError("multiple exports of " + name);
+        exports.set(name, exp);
+    }
+
+    switch (decl.type) {
+      case MODULE:
+      case FUNCTION:
+        register(decl.name, new Export(decl, true));
+        break;
+
+      case VAR:
+        for (var i = 0; i < decl.children.length; i++)
+            register(decl.children[i].name, new Export(decl.children[i], true));
+        break;
+
+      case LET:
+      case CONST:
+        throw new Error("NYI: " + definitions.tokens[decl.type]);
+
+      case EXPORT:
+        for (var i = 0; i < decl.pathList.length; i++) {
+            var path = decl.pathList[i];
+            switch (path.type) {
+              case OBJECT_INIT:
+                for (var j = 0; j < path.children.length; j++) {
+                    // init :: IDENTIFIER | PROPERTY_INIT
+                    var init = path.children[j];
+                    if (init.type === IDENTIFIER)
+                        register(init.value, new Export(init, false));
+                    else
+                        register(init.children[0].value, new Export(init.children[1], false));
+                }
+                break;
 
-          case EXPORT:
-            switch (t.peek()) {
-              case MODULE:
-              case FUNCTION:
-              case LET:
-              case VAR:
-              case CONST:
-                n = Statement(t, x);
-                n.blockComments = comments;
-                n.exported = true;
-                x.parentScript.expDecls.push(n);
-                registerExport(x.parentScript.exports, n);
-                return n;
+              case DOT:
+                register(path.children[1].value, new Export(path, false));
+                break;
 
-              default:
-                n = new Node(t);
-                n.pathList = ExportPathList(t, x);
+              case IDENTIFIER:
+                register(path.value, new Export(path, false));
                 break;
+
+              default:
+                throw new Error("unexpected export path: " + definitions.tokens[path.type]);
             }
-            x.parentScript.expDecls.push(n);
-            registerExport(x.parentScript.exports, n);
-            break;
+        }
+        break;
 
-          case MODULE:
-            n = new Node(t);
-            n.blockComments = comments;
-            t.mustMatch(IDENTIFIER);
-            label = t.token.value;
+      default:
+        throw new Error("unexpected export decl: " + definitions.tokens[exp.type]);
+    }
+}
 
-            if (t.match(LEFT_CURLY)) {
-                n.name = label;
-                n.body = Script(t, true, false);
-                n.module = new Module(n);
-                t.mustMatch(RIGHT_CURLY);
-                x.parentScript.modDefns.set(n.name, n);
-                return n;
-            }
+/*
+ * Module :: (node) -> Module
+ *
+ * Static semantic representation of a module.
+ */
+function Module(node) {
+    var exports = node.body.exports;
+    var modDefns = node.body.modDefns;
 
-            t.unget();
-            ModuleVariables(t, x, n);
-            return n;
+    var exportedModules = new Dict();
 
-          case FUNCTION:
-            // DECLARED_FORM extends funDecls of x, STATEMENT_FORM doesn't.
-            return FunctionDefinition(t, x, true, x.topLevel ? DECLARED_FORM : STATEMENT_FORM, comments);
+    exports.forEach(function(name, exp) {
+        var node = exp.node;
+        if (node.type === MODULE) {
+            exportedModules.set(name, node);
+        } else if (!exp.isDefinition && node.type === IDENTIFIER && modDefns.has(node.value)) {
+            var mod = modDefns.get(node.value);
+            exportedModules.set(name, mod);
+        }
+    });
 
-          case LEFT_CURLY:
-            n = new Node(t, blockInit());
-            Statements(t, x.update({ parentBlock: n }).pushTarget(n).nest(), n);
-            t.mustMatch(RIGHT_CURLY);
-            return n;
+    this.node = node;
+    this.exports = exports;
+    this.exportedModules = exportedModules;
+}
 
-          case IF:
-            n = new Node(t);
-            n.condition = HeadExpression(t, x);
-            x2 = x.pushTarget(n).nest();
-            n.thenPart = Statement(t, x2);
-            n.elsePart = t.match(ELSE, true) ? Statement(t, x2) : null;
+/*
+ * Statement :: () -> node
+ *
+ * Parses a Statement.
+ */
+Pp.Statement = function Statement() {
+    var i, label, n, n2, p, c, ss, tt = this.t.get(true), tt2, x0, x2, x3;
+
+    var comments = this.t.blockComments;
+
+    // Cases for statements ending in a right curly return early, avoiding the
+    // common semicolon insertion magic after this switch.
+    switch (tt) {
+      case IMPORT:
+        if (!this.x.canImport())
+            this.fail("illegal context for import statement");
+        n = this.newNode();
+        n.pathList = this.ImportPathList();
+        this.x.parentScript.impDecls.push(n);
+        break;
+
+      case EXPORT:
+        if (!this.x.canExport())
+            this.fail("export statement not in module top level");
+        switch (this.peek()) {
+          case MODULE:
+          case FUNCTION:
+          case LET:
+          case VAR:
+          case CONST:
+            n = this.Statement();
+            n.blockComments = comments;
+            n.exported = true;
+            this.x.parentScript.expDecls.push(n);
+            registerExport(this.x.parentScript.exports, n);
             return n;
+        }
+        n = this.newNode();
+        n.pathList = this.ExportPathList();
+        this.x.parentScript.expDecls.push(n);
+        registerExport(this.x.parentScript.exports, n);
+        break;
+
+      case FUNCTION:
+        // DECLARED_FORM extends funDecls of x, STATEMENT_FORM doesn't.
+        return this.FunctionDefinition(true, this.x.topLevel ? DECLARED_FORM : STATEMENT_FORM, comments);
+
+      case LEFT_CURLY:
+        n = this.newNode(blockInit());
+        x2 = this.x.update({ parentBlock: n }).pushTarget(n).nest();
+        this.withContext(x2, function() {
+            this.Statements(n);
+        });
+        this.mustMatch(RIGHT_CURLY);
+        return n;
 
-          case SWITCH:
-            // This allows CASEs after a DEFAULT, which is in the standard.
-            n = new Node(t, { cases: [], defaultIndex: -1 });
-            n.discriminant = HeadExpression(t, x);
-            x2 = x.pushTarget(n).nest();
-            t.mustMatch(LEFT_CURLY);
-            while ((tt = t.get()) !== RIGHT_CURLY) {
+      case IF:
+        n = this.newNode();
+        n.condition = this.HeadExpression();
+        x2 = this.x.pushTarget(n).nest();
+        this.withContext(x2, function() {
+            n.thenPart = this.Statement();
+            n.elsePart = this.match(ELSE, true) ? this.Statement() : null;
+        });
+        return n;
+
+      case SWITCH:
+        // This allows CASEs after a DEFAULT, which is in the standard.
+        n = this.newNode({ cases: [], defaultIndex: -1 });
+        n.discriminant = this.HeadExpression();
+        x2 = this.x.pushTarget(n).nest();
+        this.withContext(x2, function() {
+            this.mustMatch(LEFT_CURLY);
+            while ((tt = this.t.get()) !== RIGHT_CURLY) {
                 switch (tt) {
                   case DEFAULT:
                     if (n.defaultIndex >= 0)
-                        throw t.newSyntaxError("More than one switch default");
+                        this.fail("More than one switch default");
                     // FALL THROUGH
                   case CASE:
-                    n2 = new Node(t);
+                    n2 = this.newNode();
                     if (tt === DEFAULT)
                         n.defaultIndex = n.cases.length;
                     else
-                        n2.caseLabel = Expression(t, x2, COLON);
+                        n2.caseLabel = this.Expression(COLON);
                     break;
 
                   default:
-                    throw t.newSyntaxError("Invalid switch case");
+                    this.fail("Invalid switch case");
                 }
-                t.mustMatch(COLON);
-                n2.statements = new Node(t, blockInit());
-                while ((tt=t.peek(true)) !== CASE && tt !== DEFAULT &&
-                        tt !== RIGHT_CURLY)
-                    n2.statements.push(Statement(t, x2));
+                this.mustMatch(COLON);
+                n2.statements = this.newNode(blockInit());
+                while ((tt=this.peek(true)) !== CASE && tt !== DEFAULT &&
+                       tt !== RIGHT_CURLY)
+                    n2.statements.push(this.Statement());
                 n.cases.push(n2);
             }
-            return n;
+        });
+        return n;
 
-          case FOR:
-            n = new Node(t, LOOP_INIT);
-            n.blockComments = comments;
-            if (t.match(IDENTIFIER)) {
-                if (t.token.value === "each")
-                    n.isEach = true;
-                else
-                    t.unget();
-            }
-            if (!x.parenFreeMode)
-                t.mustMatch(LEFT_PAREN);
-            x2 = x.pushTarget(n).nest();
-            x3 = x.update({ inForLoopInit: true });
-            n2 = null;
-            if ((tt = t.peek(true)) !== SEMICOLON) {
+      case FOR:
+        n = this.newNode(LOOP_INIT);
+        n.blockComments = comments;
+        if (this.match(IDENTIFIER)) {
+            if (this.t.token.value === "each")
+                n.isEach = true;
+            else
+                this.t.unget();
+        }
+        if (!this.parenFreeMode)
+            this.mustMatch(LEFT_PAREN);
+        x2 = this.x.pushTarget(n).nest();
+        x3 = this.x.update({ inForLoopInit: true });
+        n2 = null;
+        if ((tt = this.peek(true)) !== SEMICOLON) {
+            this.withContext(x3, function() {
                 if (tt === VAR || tt === CONST) {
-                    t.get();
-                    n2 = Variables(t, x3);
+                    this.t.get();
+                    n2 = this.Variables();
                 } else if (tt === LET) {
-                    t.get();
-                    if (t.peek() === LEFT_PAREN) {
-                        n2 = LetBlock(t, x3, false);
+                    this.t.get();
+                    if (this.peek() === LEFT_PAREN) {
+                        n2 = this.LetBlock(false);
                     } else {
                         // Let in for head, we need to add an implicit block
                         // around the rest of the for.
-                        x3.parentBlock = n;
+                        this.x.parentBlock = n;
                         n.varDecls = [];
-                        n2 = Variables(t, x3);
+                        n2 = this.Variables();
                     }
                 } else {
-                    n2 = Expression(t, x3);
+                    n2 = this.Expression();
                 }
-            }
-            if (n2 && t.match(IN)) {
-                n.type = FOR_IN;
-                n.object = Expression(t, x3);
+            });
+        }
+        if (n2 && this.match(IN)) {
+            n.type = FOR_IN;
+            this.withContext(x3, function() {
+                n.object = this.Expression();
                 if (n2.type === VAR || n2.type === LET) {
                     c = n2.children;
 
@@ -7264,8 +7888,9 @@ define('ace/narcissus/jsparse', ['require', 'exports', 'module' , 'ace/narcissus
                     // there must be only one destructuring or only one
                     // decl.
                     if (c.length !== 1 && n2.destructurings.length !== 1) {
+                        // FIXME: this.fail ?
                         throw new SyntaxError("Invalid for..in left-hand side",
-                                              t.filename, n2.lineno);
+                                              this.filename, n2.lineno);
                     }
                     if (n2.destructurings.length > 0) {
                         n.iterator = n2.destructurings[0];
@@ -7275,1252 +7900,1364 @@ define('ace/narcissus/jsparse', ['require', 'exports', 'module' , 'ace/narcissus
                     n.varDecl = n2;
                 } else {
                     if (n2.type === ARRAY_INIT || n2.type === OBJECT_INIT) {
-                        n2.destructuredNames = checkDestructuring(t, x3, n2);
+                        n2.destructuredNames = this.checkDestructuring(n2);
                     }
                     n.iterator = n2;
                 }
-            } else {
-                x3.inForLoopInit = false;
-                n.setup = n2;
-                t.mustMatch(SEMICOLON);
-                if (n.isEach)
-                    throw t.newSyntaxError("Invalid for each..in loop");
-                n.condition = (t.peek(true) === SEMICOLON)
-                              ? null
-                              : Expression(t, x3);
-                t.mustMatch(SEMICOLON);
-                tt2 = t.peek(true);
-                n.update = (x.parenFreeMode
+            });
+        } else {
+            x3.inForLoopInit = false;
+            n.setup = n2;
+            this.mustMatch(SEMICOLON);
+            if (n.isEach)
+                this.fail("Invalid for each..in loop");
+            this.withContext(x3, function() {
+                n.condition = (this.peek(true) === SEMICOLON)
+                    ? null
+                    : this.Expression();
+                this.mustMatch(SEMICOLON);
+                tt2 = this.peek(true);
+                n.update = (this.parenFreeMode
                             ? tt2 === LEFT_CURLY || definitions.isStatementStartCode[tt2]
                             : tt2 === RIGHT_PAREN)
-                           ? null
-                           : Expression(t, x3);
-            }
-            if (!x.parenFreeMode)
-                t.mustMatch(RIGHT_PAREN);
-            n.body = Statement(t, x2);
-            return n;
+                    ? null
+                    : this.Expression();
+            });
+        }
+        if (!this.parenFreeMode)
+            this.mustMatch(RIGHT_PAREN);
+        this.withContext(x2, function() {
+            n.body = this.Statement();
+        });
+        return n;
 
-          case WHILE:
-            n = new Node(t, { isLoop: true });
-            n.blockComments = comments;
-            n.condition = HeadExpression(t, x);
-            n.body = Statement(t, x.pushTarget(n).nest());
-            return n;
+      case WHILE:
+        n = this.newNode({ isLoop: true });
+        n.blockComments = comments;
+        n.condition = this.HeadExpression();
+        x2 = this.x.pushTarget(n).nest();
+        this.withContext(x2, function() {
+            n.body = this.Statement();
+        });
+        return n;
 
-          case DO:
-            n = new Node(t, { isLoop: true });
-            n.blockComments = comments;
-            n.body = Statement(t, x.pushTarget(n).nest());
-            t.mustMatch(WHILE);
-            n.condition = HeadExpression(t, x);
-            if (!x.ecmaStrictMode) {
-                // <script language="JavaScript"> (without version hints) may need
-                // automatic semicolon insertion without a newline after do-while.
-                // See http://bugzilla.mozilla.org/show_bug.cgi?id=238945.
-                t.match(SEMICOLON);
-                return n;
-            }
-            break;
+      case DO:
+        n = this.newNode({ isLoop: true });
+        n.blockComments = comments;
+        x2 = this.x.pushTarget(n).next();
+        this.withContext(x2, function() {
+            n.body = this.Statement();
+        });
+        this.mustMatch(WHILE);
+        n.condition = this.HeadExpression();
+        // <script language="JavaScript"> (without version hints) may need
+        // automatic semicolon insertion without a newline after do-while.
+        // See http://bugzilla.mozilla.org/show_bug.cgi?id=238945.
+        this.match(SEMICOLON);
+        return n;
 
-          case BREAK:
-          case CONTINUE:
-            n = new Node(t);
-            n.blockComments = comments;
+      case BREAK:
+      case CONTINUE:
+        n = this.newNode();
+        n.blockComments = comments;
 
-            // handle the |foo: break foo;| corner case
-            x2 = x.pushTarget(n);
+        // handle the |foo: break foo;| corner case
+        x2 = this.x.pushTarget(n);
 
-            if (t.peekOnSameLine() === IDENTIFIER) {
-                t.get();
-                n.label = t.token.value;
-            }
+        if (this.peekOnSameLine() === IDENTIFIER) {
+            this.t.get();
+            n.label = this.t.token.value;
+        }
 
-            if (n.label) {
-                n.target = x2.labeledTargets.find(function(target) { return target.labels.has(n.label) });
-            } else if (tt === CONTINUE) {
-                n.target = x2.defaultLoopTarget;
-            } else {
-                n.target = x2.defaultTarget;
-            }
+        if (n.label) {
+            n.target = x2.labeledTargets.find(function(target) {
+                return target.labels.has(n.label)
+            });
+        } else if (tt === CONTINUE) {
+            n.target = x2.defaultLoopTarget;
+        } else {
+            n.target = x2.defaultTarget;
+        }
 
-            if (!n.target)
-                throw t.newSyntaxError("Invalid " + ((tt === BREAK) ? "break" : "continue"));
-            if (!n.target.isLoop && tt === CONTINUE)
-                throw t.newSyntaxError("Invalid continue");
+        if (!n.target)
+            this.fail("Invalid " + ((tt === BREAK) ? "break" : "continue"));
+        if (!n.target.isLoop && tt === CONTINUE)
+            this.fail("Invalid continue");
 
-            break;
+        break;
 
-          case TRY:
-            n = new Node(t, { catchClauses: [] });
-            n.blockComments = comments;
-            n.tryBlock = Block(t, x);
-            while (t.match(CATCH)) {
-                n2 = new Node(t);
-                p = MaybeLeftParen(t, x);
-                switch (t.get()) {
-                  case LEFT_BRACKET:
-                  case LEFT_CURLY:
-                    // Destructured catch identifiers.
-                    t.unget();
-                    n2.varName = DestructuringExpression(t, x, true);
-                    break;
-                  case IDENTIFIER:
-                    n2.varName = t.token.value;
-                    break;
-                  default:
-                    throw t.newSyntaxError("missing identifier in catch");
-                    break;
-                }
-                if (t.match(IF)) {
-                    if (x.ecma3OnlyMode)
-                        throw t.newSyntaxError("Illegal catch guard");
-                    if (n.catchClauses.length && !n.catchClauses.top().guard)
-                        throw t.newSyntaxError("Guarded catch after unguarded");
-                    n2.guard = Expression(t, x);
-                }
-                MaybeRightParen(t, p);
-                n2.block = Block(t, x);
-                n.catchClauses.push(n2);
-            }
-            if (t.match(FINALLY))
-                n.finallyBlock = Block(t, x);
-            if (!n.catchClauses.length && !n.finallyBlock)
-                throw t.newSyntaxError("Invalid try statement");
-            return n;
+      case TRY:
+        n = this.newNode({ catchClauses: [] });
+        n.blockComments = comments;
+        n.tryBlock = this.Block();
+        while (this.match(CATCH)) {
+            n2 = this.newNode();
+            p = this.MaybeLeftParen();
+            switch (this.t.get()) {
+              case LEFT_BRACKET:
+              case LEFT_CURLY:
+                // Destructured catch identifiers.
+                this.t.unget();
+                n2.varName = this.DestructuringExpression(true);
+                break;
+              case IDENTIFIER:
+                n2.varName = this.t.token.value;
+                break;
+              default:
+                this.fail("missing identifier in catch");
+                break;
+            }
+            if (this.match(IF)) {
+                if (!this.mozillaMode)
+                    this.fail("Illegal catch guard");
+                if (n.catchClauses.length && !n.catchClauses.top().guard)
+                    this.fail("Guarded catch after unguarded");
+                n2.guard = this.Expression();
+            }
+            this.MaybeRightParen(p);
+            n2.block = this.Block();
+            n.catchClauses.push(n2);
+        }
+        if (this.match(FINALLY))
+            n.finallyBlock = this.Block();
+        if (!n.catchClauses.length && !n.finallyBlock)
+            this.fail("Invalid try statement");
+        return n;
 
-          case CATCH:
-          case FINALLY:
-            throw t.newSyntaxError(definitions.tokens[tt] + " without preceding try");
+      case CATCH:
+      case FINALLY:
+        this.fail(definitions.tokens[tt] + " without preceding try");
 
-          case THROW:
-            n = new Node(t);
-            n.exception = Expression(t, x);
-            break;
+      case THROW:
+        n = this.newNode();
+        n.exception = this.Expression();
+        break;
 
-          case RETURN:
-            n = ReturnOrYield(t, x);
-            break;
+      case RETURN:
+        n = this.ReturnOrYield();
+        break;
 
-          case WITH:
-            n = new Node(t);
-            n.blockComments = comments;
-            n.object = HeadExpression(t, x);
-            n.body = Statement(t, x.pushTarget(n).nest());
+      case WITH:
+        if (this.x.banWith())
+            this.fail("with statements not allowed in strict code or modules");
+        n = this.newNode();
+        n.blockComments = comments;
+        n.object = this.HeadExpression();
+        x2 = this.x.pushTarget(n).next();
+        this.withContext(x2, function() {
+            n.body = this.Statement();
+        });
+        return n;
+
+      case VAR:
+      case CONST:
+        n = this.Variables();
+        break;
+
+      case LET:
+        if (this.peek() === LEFT_PAREN) {
+            n = this.LetBlock(true);
             return n;
+        }
+        n = this.Variables();
+        break;
 
-          case VAR:
-          case CONST:
-            n = Variables(t, x);
-            break;
+      case DEBUGGER:
+        n = this.newNode();
+        break;
 
-          case LET:
-            if (t.peek() === LEFT_PAREN)
-                n = LetBlock(t, x, true);
-            else
-                n = Variables(t, x);
-            break;
+      case NEWLINE:
+      case SEMICOLON:
+        n = this.newNode({ type: SEMICOLON });
+        n.blockComments = comments;
+        n.expression = null;
+        return n;
 
-          case DEBUGGER:
-            n = new Node(t);
-            break;
+      case IDENTIFIER:
+      case USE:
+      case MODULE:
+        switch (this.t.token.value) {
+          case "use":
+            if (!isPragmaToken(this.peekOnSameLine())) {
+                this.t.unget();
+                break;
+            }
+            return this.newNode({ type: USE, params: this.Pragmas() });
 
-          case NEWLINE:
-          case SEMICOLON:
-            n = new Node(t, { type: SEMICOLON });
+          case "module":
+            if (!this.x.modulesAllowed())
+                this.fail("module declaration not at top level");
+            this.x.parentScript.hasModules = true;
+            tt = this.peekOnSameLine();
+            if (tt !== IDENTIFIER && tt !== LEFT_CURLY) {
+                this.t.unget();
+                break;
+            }
+            n = this.newNode({ type: MODULE });
             n.blockComments = comments;
-            n.expression = null;
+            this.mustMatch(IDENTIFIER);
+            label = this.t.token.value;
+
+            if (this.match(LEFT_CURLY)) {
+                n.name = label;
+                n.body = this.Script(true, false);
+                n.module = new Module(n);
+                this.mustMatch(RIGHT_CURLY);
+                this.x.parentScript.modDefns.set(n.name, n);
+                return n;
+            }
+
+            this.t.unget();
+            this.ModuleVariables(n);
             return n;
 
           default:
-            if (tt === IDENTIFIER) {
-                tt = t.peek();
-                // Labeled statement.
-                if (tt === COLON) {
-                    label = t.token.value;
-                    if (x.allLabels.has(label))
-                        throw t.newSyntaxError("Duplicate label");
-                    t.get();
-                    n = new Node(t, { type: LABEL, label: label });
-                    n.blockComments = comments;
-                    n.statement = Statement(t, x.pushLabel(label).nest());
-                    n.target = (n.statement.type === LABEL) ? n.statement.target : n.statement;
-                    return n;
-                }
+            tt = this.peek();
+            // Labeled statement.
+            if (tt === COLON) {
+                label = this.t.token.value;
+                if (this.x.allLabels.has(label))
+                    this.fail("Duplicate label: " + label);
+                this.t.get();
+                n = this.newNode({ type: LABEL, label: label });
+                n.blockComments = comments;
+                x2 = this.x.pushLabel(label).nest();
+                this.withContext(x2, function() {
+                    n.statement = this.Statement();
+                });
+                n.target = (n.statement.type === LABEL) ? n.statement.target : n.statement;
+                return n;
             }
-
-            // Expression statement.
-            // We unget the current token to parse the expression as a whole.
-            n = new Node(t, { type: SEMICOLON });
-            t.unget();
-            n.blockComments = comments;
-            n.expression = Expression(t, x);
-            n.end = n.expression.end;
-            break;
+            // FALL THROUGH
         }
+        // FALL THROUGH
 
+      default:
+        // Expression statement.
+        // We unget the current token to parse the expression as a whole.
+        n = this.newNode({ type: SEMICOLON });
+        this.t.unget();
         n.blockComments = comments;
-        MagicalSemicolon(t);
-        return n;
+        n.expression = this.Expression();
+        n.end = n.expression.end;
+        break;
     }
 
-    /*
-     * MagicalSemicolon :: (tokenizer) -> void
-     */
-    function MagicalSemicolon(t) {
-        var tt;
-        if (t.lineno === t.token.lineno) {
-            tt = t.peekOnSameLine();
-            if (tt !== END && tt !== NEWLINE && tt !== SEMICOLON && tt !== RIGHT_CURLY)
-                throw t.newSyntaxError("missing ; before statement");
-        }
-        t.match(SEMICOLON);
+    n.blockComments = comments;
+    this.MagicalSemicolon();
+    return n;
+}
+
+/*
+ * isPragmaToken :: (number) -> boolean
+ */
+function isPragmaToken(tt) {
+    switch (tt) {
+      case IDENTIFIER:
+      case STRING:
+      case NUMBER:
+      case NULL:
+      case TRUE:
+      case FALSE:
+        return true;
     }
+    return false;
+}
 
-    /*
-     * ReturnOrYield :: (tokenizer, compiler context) -> (RETURN | YIELD) node
-     */
-    function ReturnOrYield(t, x) {
-        var n, b, tt = t.token.type, tt2;
+/*
+ * Pragmas :: () -> Array[Array[token]]
+ */
+Pp.Pragmas = function Pragmas() {
+    var pragmas = [];
+    do {
+        pragmas.push(this.Pragma());
+    } while (this.match(COMMA));
+    this.MagicalSemicolon();
+    return pragmas;
+}
 
-        var parentScript = x.parentScript;
+/*
+ * Pragmas :: () -> Array[token]
+ */
+Pp.Pragma = function Pragma() {
+    var items = [];
+    var tt;
+    do {
+        tt = this.t.get(true);
+        items.push(this.t.token);
+    } while (isPragmaToken(this.peek()));
+    return items;
+}
+
+/*
+ * MagicalSemicolon :: () -> void
+ */
+Pp.MagicalSemicolon = function MagicalSemicolon() {
+    var tt;
+    if (this.t.lineno === this.t.token.lineno) {
+        tt = this.peekOnSameLine();
+        if (tt !== END && tt !== NEWLINE && tt !== SEMICOLON && tt !== RIGHT_CURLY)
+            this.fail("missing ; before statement");
+    }
+    this.match(SEMICOLON);
+}
 
+/*
+ * ReturnOrYield :: () -> (RETURN | YIELD) node
+ */
+Pp.ReturnOrYield = function ReturnOrYield() {
+    var n, b, tt = this.t.token.type, tt2;
+
+    var parentScript = this.x.parentScript;
+
+    if (tt === RETURN) {
+        if (!this.x.inFunction)
+            this.fail("Return not in function");
+    } else /* if (tt === YIELD) */ {
+        if (!this.x.inFunction)
+            this.fail("Yield not in function");
+        parentScript.hasYield = true;
+    }
+    n = this.newNode({ value: undefined });
+
+    tt2 = (tt === RETURN) ? this.peekOnSameLine(true) : this.peek(true);
+    if (tt2 !== END && tt2 !== NEWLINE &&
+        tt2 !== SEMICOLON && tt2 !== RIGHT_CURLY
+        && (tt !== YIELD ||
+            (tt2 !== tt && tt2 !== RIGHT_BRACKET && tt2 !== RIGHT_PAREN &&
+             tt2 !== COLON && tt2 !== COMMA))) {
         if (tt === RETURN) {
-            if (!x.inFunction)
-                throw t.newSyntaxError("Return not in function");
-        } else /* if (tt === YIELD) */ {
-            if (!x.inFunction)
-                throw t.newSyntaxError("Yield not in function");
-            parentScript.isGenerator = true;
-        }
-        n = new Node(t, { value: undefined });
-
-        tt2 = (tt === RETURN) ? t.peekOnSameLine(true) : t.peek(true);
-        if (tt2 !== END && tt2 !== NEWLINE &&
-            tt2 !== SEMICOLON && tt2 !== RIGHT_CURLY
-            && (tt !== YIELD ||
-                (tt2 !== tt && tt2 !== RIGHT_BRACKET && tt2 !== RIGHT_PAREN &&
-                 tt2 !== COLON && tt2 !== COMMA))) {
-            if (tt === RETURN) {
-                n.value = Expression(t, x);
-                parentScript.hasReturnWithValue = true;
-            } else {
-                n.value = AssignExpression(t, x);
-            }
-        } else if (tt === RETURN) {
-            parentScript.hasEmptyReturn = true;
+            n.value = this.Expression();
+            parentScript.hasReturnWithValue = true;
+        } else {
+            n.value = this.AssignExpression();
         }
-
-        // Disallow return v; in generator.
-        if (parentScript.hasReturnWithValue && parentScript.isGenerator)
-            throw t.newSyntaxError("Generator returns a value");
-
-        return n;
+    } else if (tt === RETURN) {
+        parentScript.hasEmptyReturn = true;
     }
 
-    /*
-     * ModuleExpression :: (tokenizer, compiler context) -> (STRING | IDENTIFIER | DOT) node
-     */
-    function ModuleExpression(t, x) {
-        return t.match(STRING) ? new Node(t) : QualifiedPath(t, x);
-    }
+    return n;
+}
 
-    /*
-     * ImportPathList :: (tokenizer, compiler context) -> Array[DOT node]
-     */
-    function ImportPathList(t, x) {
-        var a = [];
-        do {
-            a.push(ImportPath(t, x));
-        } while (t.match(COMMA));
-        return a;
-    }
+/*
+ * ModuleExpression :: () -> (STRING | IDENTIFIER | DOT) node
+ */
+Pp.ModuleExpression = function ModuleExpression() {
+    return this.match(STRING) ? this.newNode() : this.QualifiedPath();
+}
 
-    /*
-     * ImportPath :: (tokenizer, compiler context) -> DOT node
-     */
-    function ImportPath(t, x) {
-        var n = QualifiedPath(t, x);
-        if (!t.match(DOT)) {
-            if (n.type === IDENTIFIER)
-                throw t.newSyntaxError("cannot import local variable");
-            return n;
-        }
+/*
+ * ImportPathList :: () -> Array[DOT node]
+ */
+Pp.ImportPathList = function ImportPathList() {
+    var a = [];
+    do {
+        a.push(this.ImportPath());
+    } while (this.match(COMMA));
+    return a;
+}
 
-        var n2 = new Node(t);
-        n2.push(n);
-        n2.push(ImportSpecifierSet(t, x));
-        return n2;
+/*
+ * ImportPath :: () -> DOT node
+ */
+Pp.ImportPath = function ImportPath() {
+    var n = this.QualifiedPath();
+    if (!this.match(DOT)) {
+        if (n.type === IDENTIFIER)
+            this.fail("cannot import local variable");
+        return n;
     }
 
-    /*
-     * ExplicitSpecifierSet :: (tokenizer, compiler context, (tokenizer, compiler context) -> node)
-     *                      -> OBJECT_INIT node
-     */
-    function ExplicitSpecifierSet(t, x, SpecifierRHS) {
-        var n, n2, id, tt;
+    var n2 = this.newNode();
+    n2.push(n);
+    n2.push(this.ImportSpecifierSet());
+    return n2;
+}
 
-        n = new Node(t, { type: OBJECT_INIT });
-        t.mustMatch(LEFT_CURLY);
+/*
+ * ExplicitSpecifierSet :: (() -> node) -> OBJECT_INIT node
+ */
+Pp.ExplicitSpecifierSet = function ExplicitSpecifierSet(SpecifierRHS) {
+    var n, n2, id, tt;
 
-        if (!t.match(RIGHT_CURLY)) {
-            do {
-                id = Identifier(t, x);
-                if (t.match(COLON)) {
-                    n2 = new Node(t, { type: PROPERTY_INIT });
-                    n2.push(id);
-                    n2.push(SpecifierRHS(t, x));
-                    n.push(n2);
-                } else {
-                    n.push(id);
-                }
-            } while (!t.match(RIGHT_CURLY) && t.mustMatch(COMMA));
-        }
+    n = this.newNode({ type: OBJECT_INIT });
+    this.mustMatch(LEFT_CURLY);
 
-        return n;
+    if (!this.match(RIGHT_CURLY)) {
+        do {
+            id = this.Identifier();
+            if (this.match(COLON)) {
+                n2 = this.newNode({ type: PROPERTY_INIT });
+                n2.push(id);
+                n2.push(SpecifierRHS());
+                n.push(n2);
+            } else {
+                n.push(id);
+            }
+        } while (!this.match(RIGHT_CURLY) && this.mustMatch(COMMA));
     }
 
-    /*
-     * ImportSpecifierSet :: (tokenizer, compiler context) -> (IDENTIFIER | OBJECT_INIT) node
-     */
-    function ImportSpecifierSet(t, x) {
-        return t.match(MUL)
-             ? new Node(t, { type: IDENTIFIER, name: "*" })
-             : ExplicitSpecifierSet(t, x, Identifier);
-    }
+    return n;
+}
 
-    /*
-     * Identifier :: (tokenizer, compiler context) -> IDENTIFIER node
-     */
-    function Identifier(t, x) {
-        t.mustMatch(IDENTIFIER);
-        return new Node(t, { type: IDENTIFIER });
-    }
+/*
+ * ImportSpecifierSet :: () -> (IDENTIFIER | OBJECT_INIT) node
+ */
+Pp.ImportSpecifierSet = function ImportSpecifierSet() {
+    var self = this;
+    return this.match(MUL)
+        ? this.newNode({ type: IDENTIFIER, name: "*" })
+    : ExplicitSpecifierSet(function() { return self.Identifier() });
+}
 
-    /*
-     * IdentifierName :: (tokenizer) -> IDENTIFIER node
-     */
-    function IdentifierName(t) {
-        if (t.match(IDENTIFIER))
-            return new Node(t, { type: IDENTIFIER });
-        t.get();
-        if (t.token.value in definitions.keywords)
-            return new Node(t, { type: IDENTIFIER });
-        throw t.newSyntaxError("missing IdentifierName");
-    }
+/*
+ * Identifier :: () -> IDENTIFIER node
+ */
+Pp.Identifier = function Identifier() {
+    this.mustMatch(IDENTIFIER);
+    return this.newNode({ type: IDENTIFIER });
+}
 
-    /*
-     * QualifiedPath :: (tokenizer, compiler context) -> (IDENTIFIER | DOT) node
-     */
-    function QualifiedPath(t, x) {
-        var n, n2;
+/*
+ * IdentifierName :: () -> IDENTIFIER node
+ */
+Pp.IdentifierName = function IdentifierName() {
+    this.mustMatch(IDENTIFIER, true);
+    return this.newNode({ type: IDENTIFIER });
+}
 
-        n = Identifier(t, x);
+/*
+ * QualifiedPath :: () -> (IDENTIFIER | DOT) node
+ */
+Pp.QualifiedPath = function QualifiedPath() {
+    var n, n2;
 
-        while (t.match(DOT)) {
-            if (t.peek() !== IDENTIFIER) {
-                // Unget the '.' token, which isn't part of the QualifiedPath.
-                t.unget();
-                break;
-            }
-            n2 = new Node(t);
-            n2.push(n);
-            n2.push(Identifier(t, x));
-            n = n2;
-        }
+    n = this.Identifier();
 
-        return n;
+    while (this.match(DOT)) {
+        if (this.peek() !== IDENTIFIER) {
+            // Unget the '.' token, which isn't part of the QualifiedPath.
+            this.t.unget();
+            break;
+        }
+        n2 = this.newNode();
+        n2.push(n);
+        n2.push(this.Identifier());
+        n = n2;
     }
 
-    /*
-     * ExportPath :: (tokenizer, compiler context) -> (IDENTIFIER | DOT | OBJECT_INIT) node
-     */
-    function ExportPath(t, x) {
-        if (t.peek() === LEFT_CURLY)
-            return ExplicitSpecifierSet(t, x, QualifiedPath);
-        return QualifiedPath(t, x);
-    }
+    return n;
+}
 
-    /*
-     * ExportPathList :: (tokenizer, compiler context)
-     *                -> Array[(IDENTIFIER | DOT | OBJECT_INIT) node]
-     */
-    function ExportPathList(t, x) {
-        var a = [];
-        do {
-            a.push(ExportPath(t, x));
-        } while (t.match(COMMA));
-        return a;
-    }
+/*
+ * ExportPath :: () -> (IDENTIFIER | DOT | OBJECT_INIT) node
+ */
+Pp.ExportPath = function ExportPath() {
+    var self = this;
+    if (this.peek() === LEFT_CURLY)
+        return this.ExplicitSpecifierSet(function() { return self.QualifiedPath() });
+    return this.QualifiedPath();
+}
 
-    /*
-     * FunctionDefinition :: (tokenizer, compiler context, boolean,
-     *                        DECLARED_FORM or EXPRESSED_FORM or STATEMENT_FORM,
-     *                        [string] or null or undefined)
-     *                    -> node
-     */
-    function FunctionDefinition(t, x, requireName, functionForm, comments) {
-        var tt;
-        var f = new Node(t, { params: [], paramComments: [] });
-        if (typeof comment === "undefined")
-            comment = null;
-        f.blockComments = comments;
-        if (f.type !== FUNCTION)
-            f.type = (f.value === "get") ? GETTER : SETTER;
-        if (t.match(IDENTIFIER))
-            f.name = t.token.value;
-        else if (requireName)
-            throw t.newSyntaxError("missing function identifier");
-
-        var inModule = x ? x.inModule : false;
-        var x2 = new StaticContext(null, null, inModule, true);
-
-        t.mustMatch(LEFT_PAREN);
-        if (!t.match(RIGHT_PAREN)) {
+/*
+ * ExportPathList :: () -> Array[(IDENTIFIER | DOT | OBJECT_INIT) node]
+ */
+Pp.ExportPathList = function ExportPathList() {
+    var a = [];
+    do {
+        a.push(this.ExportPath());
+    } while (this.match(COMMA));
+    return a;
+}
+
+/*
+ * FunctionDefinition :: (boolean,
+ *                        DECLARED_FORM or EXPRESSED_FORM or STATEMENT_FORM,
+ *                        [string] or null or undefined)
+ *                    -> node
+ */
+Pp.FunctionDefinition = function FunctionDefinition(requireName, functionForm, comments) {
+    var tt;
+    var f = this.newNode({ params: [], paramComments: [] });
+    if (typeof comments === "undefined")
+        comments = null;
+    f.blockComments = comments;
+    if (f.type !== FUNCTION)
+        f.type = (f.value === "get") ? GETTER : SETTER;
+    if (this.match(MUL))
+        f.isExplicitGenerator = true;
+    if (this.match(IDENTIFIER, false, true))
+        f.name = this.t.token.value;
+    else if (requireName)
+        this.fail("missing function identifier");
+
+    var inModule = this.x.inModule;
+    x2 = new StaticContext(null, null, inModule, true, this.x.strictMode);
+    this.withContext(x2, function() {
+        this.mustMatch(LEFT_PAREN);
+        if (!this.match(RIGHT_PAREN)) {
             do {
-                tt = t.get();
-                f.paramComments.push(t.lastBlockComment());
+                tt = this.t.get();
+                f.paramComments.push(this.t.lastBlockComment());
                 switch (tt) {
                   case LEFT_BRACKET:
                   case LEFT_CURLY:
                     // Destructured formal parameters.
-                    t.unget();
-                    f.params.push(DestructuringExpression(t, x2));
+                    this.t.unget();
+                    f.params.push(this.DestructuringExpression());
                     break;
                   case IDENTIFIER:
-                    f.params.push(t.token.value);
+                    f.params.push(this.t.token.value);
                     break;
                   default:
-                    throw t.newSyntaxError("missing formal parameter");
-                    break;
+                    this.fail("missing formal parameter");
                 }
-            } while (t.match(COMMA));
-            t.mustMatch(RIGHT_PAREN);
+            } while (this.match(COMMA));
+            this.mustMatch(RIGHT_PAREN);
         }
 
         // Do we have an expression closure or a normal body?
-        tt = t.get();
+        tt = this.t.get(true);
         if (tt !== LEFT_CURLY)
-            t.unget();
+            this.t.unget();
 
         if (tt !== LEFT_CURLY) {
-            f.body = AssignExpression(t, x2);
-            if (f.body.isGenerator)
-                throw t.newSyntaxError("Generator returns a value");
+            f.body = this.AssignExpression();
         } else {
-            f.body = Script(t, inModule, true);
-        }
-
-        if (tt === LEFT_CURLY)
-            t.mustMatch(RIGHT_CURLY);
-
-        f.end = t.token.end;
-        f.functionForm = functionForm;
-        if (functionForm === DECLARED_FORM)
-            x.parentScript.funDecls.push(f);
-        return f;
-    }
-
-    /*
-     * ModuleVariables :: (tokenizer, compiler context, MODULE node) -> void
-     *
-     * Parses a comma-separated list of module declarations (and maybe
-     * initializations).
-     */
-    function ModuleVariables(t, x, n) {
-        var n1, n2;
-        do {
-            n1 = Identifier(t, x);
-            if (t.match(ASSIGN)) {
-                n2 = ModuleExpression(t, x);
-                n1.initializer = n2;
-                if (n2.type === STRING)
-                    x.parentScript.modLoads.set(n1.value, n2.value);
-                else
-                    x.parentScript.modAssns.set(n1.value, n1);
-            }
-            n.push(n1);
-        } while (t.match(COMMA));
-    }
-
-    /*
-     * Variables :: (tokenizer, compiler context) -> node
-     *
-     * Parses a comma-separated list of var declarations (and maybe
-     * initializations).
-     */
-    function Variables(t, x, letBlock) {
-        var n, n2, ss, i, s, tt;
-
-        tt = t.token.type;
-        switch (tt) {
-          case VAR:
-          case CONST:
-            s = x.parentScript;
-            break;
-          case LET:
-            s = x.parentBlock;
-            break;
-          case LEFT_PAREN:
-            tt = LET;
-            s = letBlock;
-            break;
+            f.body = this.Script(inModule, true);
         }
+    });
 
-        n = new Node(t, { type: tt, destructurings: [] });
+    if (tt === LEFT_CURLY)
+        this.mustMatch(RIGHT_CURLY);
 
-        do {
-            tt = t.get();
-            if (tt === LEFT_BRACKET || tt === LEFT_CURLY) {
-                // Need to unget to parse the full destructured expression.
-                t.unget();
+    f.end = this.t.token.end;
+    f.functionForm = functionForm;
+    if (functionForm === DECLARED_FORM)
+        this.x.parentScript.funDecls.push(f);
 
-                var dexp = DestructuringExpression(t, x, true);
+    if (this.x.inModule && !f.isExplicitGenerator && f.body.hasYield)
+        this.fail("yield in non-generator function");
 
-                n2 = new Node(t, { type: IDENTIFIER,
-                                   name: dexp,
-                                   readOnly: n.type === CONST });
-                n.push(n2);
-                pushDestructuringVarDecls(n2.name.destructuredNames, s);
-                n.destructurings.push({ exp: dexp, decl: n2 });
+    if (f.isExplicitGenerator || f.body.hasYield)
+        f.body = this.newNode({ type: GENERATOR, body: f.body });
 
-                if (x.inForLoopInit && t.peek() === IN) {
-                    continue;
-                }
+    return f;
+}
 
-                t.mustMatch(ASSIGN);
-                if (t.token.assignOp)
-                    throw t.newSyntaxError("Invalid variable initialization");
+/*
+ * ModuleVariables :: (MODULE node) -> void
+ *
+ * Parses a comma-separated list of module declarations (and maybe
+ * initializations).
+ */
+Pp.ModuleVariables = function ModuleVariables(n) {
+    var n1, n2;
+    do {
+        n1 = this.Identifier();
+        if (this.match(ASSIGN)) {
+            n2 = this.ModuleExpression();
+            n1.initializer = n2;
+            if (n2.type === STRING)
+                this.x.parentScript.modLoads.set(n1.value, n2.value);
+            else
+                this.x.parentScript.modAssns.set(n1.value, n1);
+        }
+        n.push(n1);
+    } while (this.match(COMMA));
+}
 
-                n2.blockComment = t.lastBlockComment();
-                n2.initializer = AssignExpression(t, x);
+/*
+ * Variables :: () -> node
+ *
+ * Parses a comma-separated list of var declarations (and maybe
+ * initializations).
+ */
+Pp.Variables = function Variables(letBlock) {
+    var n, n2, ss, i, s, tt;
+
+    tt = this.t.token.type;
+    switch (tt) {
+      case VAR:
+      case CONST:
+        s = this.x.parentScript;
+        break;
+      case LET:
+        s = this.x.parentBlock;
+        break;
+      case LEFT_PAREN:
+        tt = LET;
+        s = letBlock;
+        break;
+    }
+
+    n = this.newNode({ type: tt, destructurings: [] });
+
+    do {
+        tt = this.t.get();
+        if (tt === LEFT_BRACKET || tt === LEFT_CURLY) {
+            // Need to unget to parse the full destructured expression.
+            this.t.unget();
+
+            var dexp = this.DestructuringExpression(true);
+
+            n2 = this.newNode({ type: IDENTIFIER,
+                                name: dexp,
+                                readOnly: n.type === CONST });
+            n.push(n2);
+            pushDestructuringVarDecls(n2.name.destructuredNames, s);
+            n.destructurings.push({ exp: dexp, decl: n2 });
 
+            if (this.x.inForLoopInit && this.peek() === IN) {
                 continue;
             }
 
-            if (tt !== IDENTIFIER)
-                throw t.newSyntaxError("missing variable name");
-
-            n2 = new Node(t, { type: IDENTIFIER,
-                               name: t.token.value,
-                               readOnly: n.type === CONST });
-            n.push(n2);
-            s.varDecls.push(n2);
+            this.mustMatch(ASSIGN);
+            if (this.t.token.assignOp)
+                this.fail("Invalid variable initialization");
 
-            if (t.match(ASSIGN)) {
-                var comment = t.lastBlockComment();
-                if (t.token.assignOp)
-                    throw t.newSyntaxError("Invalid variable initialization");
+            n2.blockComment = this.t.lastBlockComment();
+            n2.initializer = this.AssignExpression();
 
-                n2.initializer = AssignExpression(t, x);
-            } else {
-                var comment = t.lastBlockComment();
-            }
-            n2.blockComment = comment;
-        } while (t.match(COMMA));
+            continue;
+        }
 
-        return n;
-    }
+        if (tt !== IDENTIFIER)
+            this.fail("missing variable name");
 
-    /*
-     * LetBlock :: (tokenizer, compiler context, boolean) -> node
-     *
-     * Does not handle let inside of for loop init.
-     */
-    function LetBlock(t, x, isStatement) {
-        var n, n2;
+        n2 = this.newNode({ type: IDENTIFIER,
+                            name: this.t.token.value,
+                            readOnly: n.type === CONST });
+        n.push(n2);
+        s.varDecls.push(n2);
 
-        // t.token.type must be LET
-        n = new Node(t, { type: LET_BLOCK, varDecls: [] });
-        t.mustMatch(LEFT_PAREN);
-        n.variables = Variables(t, x, n);
-        t.mustMatch(RIGHT_PAREN);
+        if (this.match(ASSIGN)) {
+            var comment = this.t.lastBlockComment();
+            if (this.t.token.assignOp)
+                this.fail("Invalid variable initialization");
 
-        if (isStatement && t.peek() !== LEFT_CURLY) {
-            /*
-             * If this is really an expression in let statement guise, then we
-             * need to wrap the LET_BLOCK node in a SEMICOLON node so that we pop
-             * the return value of the expression.
-             */
-            n2 = new Node(t, { type: SEMICOLON,
-                               expression: n });
-            isStatement = false;
+            n2.initializer = this.AssignExpression();
+        } else {
+            var comment = this.t.lastBlockComment();
         }
+        n2.blockComment = comment;
+    } while (this.match(COMMA));
 
-        if (isStatement)
-            n.block = Block(t, x);
-        else
-            n.expression = AssignExpression(t, x);
+    return n;
+}
 
-        return n;
+/*
+ * LetBlock :: (boolean) -> node
+ *
+ * Does not handle let inside of for loop init.
+ */
+Pp.LetBlock = function LetBlock(isStatement) {
+    var n, n2;
+
+    // t.token.type must be LET
+    n = this.newNode({ type: LET_BLOCK, varDecls: [] });
+    this.mustMatch(LEFT_PAREN);
+    n.variables = this.Variables(n);
+    this.mustMatch(RIGHT_PAREN);
+
+    if (isStatement && this.peek() !== LEFT_CURLY) {
+        /*
+         * If this is really an expression in let statement guise, then we
+         * need to wrap the LET_BLOCK node in a SEMICOLON node so that we pop
+         * the return value of the expression.
+         */
+        n2 = this.newNode({ type: SEMICOLON, expression: n });
+        isStatement = false;
     }
 
-    function checkDestructuring(t, x, n, simpleNamesOnly) {
-        if (n.type === ARRAY_COMP)
-            throw t.newSyntaxError("Invalid array comprehension left-hand side");
-        if (n.type !== ARRAY_INIT && n.type !== OBJECT_INIT)
-            return;
+    if (isStatement)
+        n.block = this.Block();
+    else
+        n.expression = this.AssignExpression();
 
-        var lhss = {};
-        var nn, n2, idx, sub, cc, c = n.children;
-        for (var i = 0, j = c.length; i < j; i++) {
-            if (!(nn = c[i]))
-                continue;
-            if (nn.type === PROPERTY_INIT) {
-                cc = nn.children;
-                sub = cc[1];
-                idx = cc[0].value;
-            } else if (n.type === OBJECT_INIT) {
-                // Do we have destructuring shorthand {foo, bar}?
-                sub = nn;
-                idx = nn.value;
-            } else {
-                sub = nn;
-                idx = i;
-            }
+    return n;
+}
 
-            if (sub.type === ARRAY_INIT || sub.type === OBJECT_INIT) {
-                lhss[idx] = checkDestructuring(t, x, sub, simpleNamesOnly);
-            } else {
-                if (simpleNamesOnly && sub.type !== IDENTIFIER) {
-                    // In declarations, lhs must be simple names
-                    throw t.newSyntaxError("missing name in pattern");
-                }
+Pp.checkDestructuring = function checkDestructuring(n, simpleNamesOnly) {
+    if (n.type === ARRAY_COMP)
+        this.fail("Invalid array comprehension left-hand side");
+    if (n.type !== ARRAY_INIT && n.type !== OBJECT_INIT)
+        return;
 
-                lhss[idx] = sub;
-            }
+    var lhss = {};
+    var nn, n2, idx, sub, cc, c = n.children;
+    for (var i = 0, j = c.length; i < j; i++) {
+        if (!(nn = c[i]))
+            continue;
+        if (nn.type === PROPERTY_INIT) {
+            cc = nn.children;
+            sub = cc[1];
+            idx = cc[0].value;
+        } else if (n.type === OBJECT_INIT) {
+            // Do we have destructuring shorthand {foo, bar}?
+            sub = nn;
+            idx = nn.value;
+        } else {
+            sub = nn;
+            idx = i;
         }
 
-        return lhss;
-    }
-
-    function DestructuringExpression(t, x, simpleNamesOnly) {
-        var n = PrimaryExpression(t, x);
-        // Keep the list of lefthand sides for varDecls
-        n.destructuredNames = checkDestructuring(t, x, n, simpleNamesOnly);
-        return n;
-    }
+        if (sub.type === ARRAY_INIT || sub.type === OBJECT_INIT) {
+            lhss[idx] = this.checkDestructuring(sub, simpleNamesOnly);
+        } else {
+            if (simpleNamesOnly && sub.type !== IDENTIFIER) {
+                // In declarations, lhs must be simple names
+                this.fail("missing name in pattern");
+            }
 
-    function GeneratorExpression(t, x, e) {
-        return new Node(t, { type: GENERATOR,
-                             expression: e,
-                             tail: ComprehensionTail(t, x) });
+            lhss[idx] = sub;
+        }
     }
 
-    function ComprehensionTail(t, x) {
-        var body, n, n2, n3, p;
-
-        // t.token.type must be FOR
-        body = new Node(t, { type: COMP_TAIL });
-
-        do {
-            // Comprehension tails are always for..in loops.
-            n = new Node(t, { type: FOR_IN, isLoop: true });
-            if (t.match(IDENTIFIER)) {
-                // But sometimes they're for each..in.
-                if (t.token.value === "each")
-                    n.isEach = true;
-                else
-                    t.unget();
-            }
-            p = MaybeLeftParen(t, x);
-            switch(t.get()) {
-              case LEFT_BRACKET:
-              case LEFT_CURLY:
-                t.unget();
-                // Destructured left side of for in comprehension tails.
-                n.iterator = DestructuringExpression(t, x);
-                break;
+    return lhss;
+}
 
-              case IDENTIFIER:
-                n.iterator = n3 = new Node(t, { type: IDENTIFIER });
-                n3.name = n3.value;
-                n.varDecl = n2 = new Node(t, { type: VAR });
-                n2.push(n3);
-                x.parentScript.varDecls.push(n3);
-                // Don't add to varDecls since the semantics of comprehensions is
-                // such that the variables are in their own function when
-                // desugared.
-                break;
+Pp.DestructuringExpression = function DestructuringExpression(simpleNamesOnly) {
+    var n = this.PrimaryExpression();
+    // Keep the list of lefthand sides for varDecls
+    n.destructuredNames = this.checkDestructuring(n, simpleNamesOnly);
+    return n;
+}
 
-              default:
-                throw t.newSyntaxError("missing identifier");
-            }
-            t.mustMatch(IN);
-            n.object = Expression(t, x);
-            MaybeRightParen(t, p);
-            body.push(n);
-        } while (t.match(FOR));
+Pp.GeneratorExpression = function GeneratorExpression(e) {
+    return this.newNode({ type: GENERATOR,
+                          expression: e,
+                          tail: this.ComprehensionTail() });
+}
 
-        // Optional guard.
-        if (t.match(IF))
-            body.guard = HeadExpression(t, x);
+Pp.ComprehensionTail = function ComprehensionTail() {
+    var body, n, n2, n3, p;
 
-        return body;
-    }
+    // t.token.type must be FOR
+    body = this.newNode({ type: COMP_TAIL });
 
-    function HeadExpression(t, x) {
-        var p = MaybeLeftParen(t, x);
-        var n = ParenExpression(t, x);
-        MaybeRightParen(t, p);
-        if (p === END && !n.parenthesized) {
-            var tt = t.peek();
-            if (tt !== LEFT_CURLY && !definitions.isStatementStartCode[tt])
-                throw t.newSyntaxError("Unparenthesized head followed by unbraced body");
+    do {
+        // Comprehension tails are always for..in loops.
+        n = this.newNode({ type: FOR_IN, isLoop: true });
+        if (this.match(IDENTIFIER)) {
+            // But sometimes they're for each..in.
+            if (this.mozillaMode && this.t.token.value === "each")
+                n.isEach = true;
+            else
+                this.t.unget();
         }
-        return n;
-    }
+        p = this.MaybeLeftParen();
+        switch(this.t.get()) {
+          case LEFT_BRACKET:
+          case LEFT_CURLY:
+            this.t.unget();
+            // Destructured left side of for in comprehension tails.
+            n.iterator = this.DestructuringExpression();
+            break;
 
-    function ParenExpression(t, x) {
-        // Always accept the 'in' operator in a parenthesized expression,
-        // where it's unambiguous, even if we might be parsing the init of a
-        // for statement.
-        var n = Expression(t, x.update({ inForLoopInit: x.inForLoopInit &&
-                                                        (t.token.type === LEFT_PAREN) }));
+          case IDENTIFIER:
+            n.iterator = n3 = this.newNode({ type: IDENTIFIER });
+            n3.name = n3.value;
+            n.varDecl = n2 = this.newNode({ type: VAR });
+            n2.push(n3);
+            this.x.parentScript.varDecls.push(n3);
+            // Don't add to varDecls since the semantics of comprehensions is
+            // such that the variables are in their own function when
+            // desugared.
+            break;
 
-        if (t.match(FOR)) {
-            if (n.type === YIELD && !n.parenthesized)
-                throw t.newSyntaxError("Yield expression must be parenthesized");
-            if (n.type === COMMA && !n.parenthesized)
-                throw t.newSyntaxError("Generator expression must be parenthesized");
-            n = GeneratorExpression(t, x, n);
+          default:
+            this.fail("missing identifier");
         }
+        this.mustMatch(IN);
+        n.object = this.Expression();
+        this.MaybeRightParen(p);
+        body.push(n);
+    } while (this.match(FOR));
 
-        return n;
-    }
+    // Optional guard.
+    if (this.match(IF))
+        body.guard = this.HeadExpression();
 
-    /*
-     * Expression :: (tokenizer, compiler context) -> node
-     *
-     * Top-down expression parser matched against SpiderMonkey.
-     */
-    function Expression(t, x) {
-        var n, n2;
+    return body;
+}
 
-        n = AssignExpression(t, x);
-        if (t.match(COMMA)) {
-            n2 = new Node(t, { type: COMMA });
-            n2.push(n);
-            n = n2;
-            do {
-                n2 = n.children[n.children.length-1];
-                if (n2.type === YIELD && !n2.parenthesized)
-                    throw t.newSyntaxError("Yield expression must be parenthesized");
-                n.push(AssignExpression(t, x));
-            } while (t.match(COMMA));
-        }
+Pp.HeadExpression = function HeadExpression() {
+    var p = this.MaybeLeftParen();
+    var n = this.ParenExpression();
+    this.MaybeRightParen(p);
+    if (p === END && !n.parenthesized) {
+        var tt = this.peek();
+        if (tt !== LEFT_CURLY && !definitions.isStatementStartCode[tt])
+            this.fail("Unparenthesized head followed by unbraced body");
+    }
+    return n;
+}
 
-        return n;
+Pp.ParenExpression = function ParenExpression() {
+    // Always accept the 'in' operator in a parenthesized expression,
+    // where it's unambiguous, even if we might be parsing the init of a
+    // for statement.
+    var x2 = this.x.update({
+        inForLoopInit: this.x.inForLoopInit && (this.t.token.type === LEFT_PAREN)
+    });
+    var n = this.withContext(x2, function() {
+        return this.Expression();
+    });
+    if (this.match(FOR)) {
+        if (n.type === YIELD && !n.parenthesized)
+            this.fail("Yield expression must be parenthesized");
+        if (n.type === COMMA && !n.parenthesized)
+            this.fail("Generator expression must be parenthesized");
+        n = this.GeneratorExpression(n);
     }
 
-    function AssignExpression(t, x) {
-        var n, lhs;
+    return n;
+}
 
-        // Have to treat yield like an operand because it could be the leftmost
-        // operand of the expression.
-        if (t.match(YIELD, true))
-            return ReturnOrYield(t, x);
+/*
+ * Expression :: () -> node
+ *
+ * Top-down expression parser matched against SpiderMonkey.
+ */
+Pp.Expression = function Expression() {
+    var n, n2;
 
-        n = new Node(t, { type: ASSIGN });
-        lhs = ConditionalExpression(t, x);
+    n = this.AssignExpression();
+    if (this.match(COMMA)) {
+        n2 = this.newNode({ type: COMMA });
+        n2.push(n);
+        n = n2;
+        do {
+            n2 = n.children[n.children.length-1];
+            if (n2.type === YIELD && !n2.parenthesized)
+                this.fail("Yield expression must be parenthesized");
+            n.push(this.AssignExpression());
+        } while (this.match(COMMA));
+    }
 
-        if (!t.match(ASSIGN)) {
-            return lhs;
-        }
+    return n;
+}
 
-        n.blockComment = t.lastBlockComment();
+Pp.AssignExpression = function AssignExpression() {
+    var n, lhs;
 
-        switch (lhs.type) {
-          case OBJECT_INIT:
-          case ARRAY_INIT:
-            lhs.destructuredNames = checkDestructuring(t, x, lhs);
-            // FALL THROUGH
-          case IDENTIFIER: case DOT: case INDEX: case CALL:
-            break;
-          default:
-            throw t.newSyntaxError("Bad left-hand side of assignment");
-            break;
-        }
+    // Have to treat yield like an operand because it could be the leftmost
+    // operand of the expression.
+    if (this.match(YIELD, true))
+        return this.ReturnOrYield();
 
-        n.assignOp = lhs.assignOp = t.token.assignOp;
-        n.push(lhs);
-        n.push(AssignExpression(t, x));
+    n = this.newNode({ type: ASSIGN });
+    lhs = this.ConditionalExpression();
 
-        return n;
+    if (!this.match(ASSIGN)) {
+        return lhs;
     }
 
-    function ConditionalExpression(t, x) {
-        var n, n2;
-
-        n = OrExpression(t, x);
-        if (t.match(HOOK)) {
-            n2 = n;
-            n = new Node(t, { type: HOOK });
-            n.push(n2);
-            /*
-             * Always accept the 'in' operator in the middle clause of a ternary,
-             * where it's unambiguous, even if we might be parsing the init of a
-             * for statement.
-             */
-            n.push(AssignExpression(t, x.update({ inForLoopInit: false })));
-            if (!t.match(COLON))
-                throw t.newSyntaxError("missing : after ?");
-            n.push(AssignExpression(t, x));
-        }
+    n.blockComment = this.t.lastBlockComment();
 
-        return n;
+    switch (lhs.type) {
+      case OBJECT_INIT:
+      case ARRAY_INIT:
+        lhs.destructuredNames = this.checkDestructuring(lhs);
+        // FALL THROUGH
+      case IDENTIFIER: case DOT: case INDEX: case CALL:
+        break;
+      default:
+        this.fail("Bad left-hand side of assignment");
+        break;
     }
 
-    function OrExpression(t, x) {
-        var n, n2;
+    n.assignOp = lhs.assignOp = this.t.token.assignOp;
+    n.push(lhs);
+    n.push(this.AssignExpression());
 
-        n = AndExpression(t, x);
-        while (t.match(OR)) {
-            n2 = new Node(t);
-            n2.push(n);
-            n2.push(AndExpression(t, x));
-            n = n2;
-        }
+    return n;
+}
 
-        return n;
+Pp.ConditionalExpression = function ConditionalExpression() {
+    var n, n2;
+
+    n = this.OrExpression();
+    if (this.match(HOOK)) {
+        n2 = n;
+        n = this.newNode({ type: HOOK });
+        n.push(n2);
+        /*
+         * Always accept the 'in' operator in the middle clause of a ternary,
+         * where it's unambiguous, even if we might be parsing the init of a
+         * for statement.
+         */
+        var x2 = this.x.update({ inForLoopInit: false });
+        this.withContext(x2, function() {
+            n.push(this.AssignExpression());
+        });
+        if (!this.match(COLON))
+            this.fail("missing : after ?");
+        n.push(this.AssignExpression());
     }
 
-    function AndExpression(t, x) {
-        var n, n2;
+    return n;
+}
 
-        n = BitwiseOrExpression(t, x);
-        while (t.match(AND)) {
-            n2 = new Node(t);
-            n2.push(n);
-            n2.push(BitwiseOrExpression(t, x));
-            n = n2;
-        }
+Pp.OrExpression = function OrExpression() {
+    var n, n2;
 
-        return n;
+    n = this.AndExpression();
+    while (this.match(OR)) {
+        n2 = this.newNode();
+        n2.push(n);
+        n2.push(this.AndExpression());
+        n = n2;
     }
 
-    function BitwiseOrExpression(t, x) {
-        var n, n2;
+    return n;
+}
 
-        n = BitwiseXorExpression(t, x);
-        while (t.match(BITWISE_OR)) {
-            n2 = new Node(t);
-            n2.push(n);
-            n2.push(BitwiseXorExpression(t, x));
-            n = n2;
-        }
+Pp.AndExpression = function AndExpression() {
+    var n, n2;
 
-        return n;
+    n = this.BitwiseOrExpression();
+    while (this.match(AND)) {
+        n2 = this.newNode();
+        n2.push(n);
+        n2.push(this.BitwiseOrExpression());
+        n = n2;
     }
 
-    function BitwiseXorExpression(t, x) {
-        var n, n2;
+    return n;
+}
 
-        n = BitwiseAndExpression(t, x);
-        while (t.match(BITWISE_XOR)) {
-            n2 = new Node(t);
-            n2.push(n);
-            n2.push(BitwiseAndExpression(t, x));
-            n = n2;
-        }
+Pp.BitwiseOrExpression = function BitwiseOrExpression() {
+    var n, n2;
 
-        return n;
+    n = this.BitwiseXorExpression();
+    while (this.match(BITWISE_OR)) {
+        n2 = this.newNode();
+        n2.push(n);
+        n2.push(this.BitwiseXorExpression());
+        n = n2;
     }
 
-    function BitwiseAndExpression(t, x) {
-        var n, n2;
+    return n;
+}
 
-        n = EqualityExpression(t, x);
-        while (t.match(BITWISE_AND)) {
-            n2 = new Node(t);
-            n2.push(n);
-            n2.push(EqualityExpression(t, x));
-            n = n2;
-        }
+Pp.BitwiseXorExpression = function BitwiseXorExpression() {
+    var n, n2;
 
-        return n;
+    n = this.BitwiseAndExpression();
+    while (this.match(BITWISE_XOR)) {
+        n2 = this.newNode();
+        n2.push(n);
+        n2.push(this.BitwiseAndExpression());
+        n = n2;
     }
 
-    function EqualityExpression(t, x) {
-        var n, n2;
+    return n;
+}
 
-        n = RelationalExpression(t, x);
-        while (t.match(EQ) || t.match(NE) ||
-               t.match(STRICT_EQ) || t.match(STRICT_NE)) {
-            n2 = new Node(t);
-            n2.push(n);
-            n2.push(RelationalExpression(t, x));
-            n = n2;
-        }
+Pp.BitwiseAndExpression = function BitwiseAndExpression() {
+    var n, n2;
 
-        return n;
+    n = this.EqualityExpression();
+    while (this.match(BITWISE_AND)) {
+        n2 = this.newNode();
+        n2.push(n);
+        n2.push(this.EqualityExpression());
+        n = n2;
     }
 
-    function RelationalExpression(t, x) {
-        var n, n2;
+    return n;
+}
 
-        /*
-         * Uses of the in operator in shiftExprs are always unambiguous,
-         * so unset the flag that prohibits recognizing it.
-         */
-        var x2 = x.update({ inForLoopInit: false });
-        n = ShiftExpression(t, x2);
-        while ((t.match(LT) || t.match(LE) || t.match(GE) || t.match(GT) ||
-               (!x.inForLoopInit && t.match(IN)) ||
-               t.match(INSTANCEOF))) {
-            n2 = new Node(t);
-            n2.push(n);
-            n2.push(ShiftExpression(t, x2));
-            n = n2;
-        }
+Pp.EqualityExpression = function EqualityExpression() {
+    var n, n2;
 
-        return n;
+    n = this.RelationalExpression();
+    while (this.match(EQ) || this.match(NE) ||
+           this.match(STRICT_EQ) || this.match(STRICT_NE)) {
+        n2 = this.newNode();
+        n2.push(n);
+        n2.push(this.RelationalExpression());
+        n = n2;
     }
 
-    function ShiftExpression(t, x) {
-        var n, n2;
+    return n;
+}
+
+Pp.RelationalExpression = function RelationalExpression() {
+    var n, n2;
 
-        n = AddExpression(t, x);
-        while (t.match(LSH) || t.match(RSH) || t.match(URSH)) {
-            n2 = new Node(t);
+    /*
+     * Uses of the in operator in shiftExprs are always unambiguous,
+     * so unset the flag that prohibits recognizing it.
+     */
+    var x2 = this.x.update({ inForLoopInit: false });
+    this.withContext(x2, function() {
+        n = this.ShiftExpression();
+        while ((this.match(LT) || this.match(LE) || this.match(GE) || this.match(GT) ||
+                (!this.x.inForLoopInit && this.match(IN)) ||
+                this.match(INSTANCEOF))) {
+            n2 = this.newNode();
             n2.push(n);
-            n2.push(AddExpression(t, x));
+            n2.push(this.ShiftExpression());
             n = n2;
         }
+    });
 
-        return n;
+    return n;
+}
+
+Pp.ShiftExpression = function ShiftExpression() {
+    var n, n2;
+
+    n = this.AddExpression();
+    while (this.match(LSH) || this.match(RSH) || this.match(URSH)) {
+        n2 = this.newNode();
+        n2.push(n);
+        n2.push(this.AddExpression());
+        n = n2;
     }
 
-    function AddExpression(t, x) {
-        var n, n2;
+    return n;
+}
 
-        n = MultiplyExpression(t, x);
-        while (t.match(PLUS) || t.match(MINUS)) {
-            n2 = new Node(t);
-            n2.push(n);
-            n2.push(MultiplyExpression(t, x));
-            n = n2;
-        }
+Pp.AddExpression = function AddExpression() {
+    var n, n2;
 
-        return n;
+    n = this.MultiplyExpression();
+    while (this.match(PLUS) || this.match(MINUS)) {
+        n2 = this.newNode();
+        n2.push(n);
+        n2.push(this.MultiplyExpression());
+        n = n2;
     }
 
-    function MultiplyExpression(t, x) {
-        var n, n2;
+    return n;
+}
 
-        n = UnaryExpression(t, x);
-        while (t.match(MUL) || t.match(DIV) || t.match(MOD)) {
-            n2 = new Node(t);
-            n2.push(n);
-            n2.push(UnaryExpression(t, x));
-            n = n2;
-        }
+Pp.MultiplyExpression = function MultiplyExpression() {
+    var n, n2;
 
-        return n;
+    n = this.UnaryExpression();
+    while (this.match(MUL) || this.match(DIV) || this.match(MOD)) {
+        n2 = this.newNode();
+        n2.push(n);
+        n2.push(this.UnaryExpression());
+        n = n2;
     }
 
-    function UnaryExpression(t, x) {
-        var n, n2, tt;
-
-        switch (tt = t.get(true)) {
-          case DELETE: case VOID: case TYPEOF:
-          case NOT: case BITWISE_NOT: case PLUS: case MINUS:
-            if (tt === PLUS)
-                n = new Node(t, { type: UNARY_PLUS });
-            else if (tt === MINUS)
-                n = new Node(t, { type: UNARY_MINUS });
-            else
-                n = new Node(t);
-            n.push(UnaryExpression(t, x));
-            break;
+    return n;
+}
 
-          case INCREMENT:
-          case DECREMENT:
-            // Prefix increment/decrement.
-            n = new Node(t);
-            n.push(MemberExpression(t, x, true));
-            break;
+Pp.UnaryExpression = function UnaryExpression() {
+    var n, n2, tt;
 
-          default:
-            t.unget();
-            n = MemberExpression(t, x, true);
-
-            // Don't look across a newline boundary for a postfix {in,de}crement.
-            if (t.tokens[(t.tokenIndex + t.lookahead - 1) & 3].lineno ===
-                t.lineno) {
-                if (t.match(INCREMENT) || t.match(DECREMENT)) {
-                    n2 = new Node(t, { postfix: true });
-                    n2.push(n);
-                    n = n2;
-                }
+    switch (tt = this.t.get(true)) {
+      case DELETE: case VOID: case TYPEOF:
+      case NOT: case BITWISE_NOT: case PLUS: case MINUS:
+        if (tt === PLUS)
+            n = this.newNode({ type: UNARY_PLUS });
+        else if (tt === MINUS)
+            n = this.newNode({ type: UNARY_MINUS });
+        else
+            n = this.newNode();
+        n.push(this.UnaryExpression());
+        break;
+
+      case INCREMENT:
+      case DECREMENT:
+        // Prefix increment/decrement.
+        n = this.newNode();
+        n.push(this.MemberExpression(true));
+        break;
+
+      default:
+        this.t.unget();
+        n = this.MemberExpression(true);
+
+        // Don't look across a newline boundary for a postfix {in,de}crement.
+        if (this.t.tokens[(this.t.tokenIndex + this.t.lookahead - 1) & 3].lineno ===
+            this.t.lineno) {
+            if (this.match(INCREMENT) || this.match(DECREMENT)) {
+                n2 = this.newNode({ postfix: true });
+                n2.push(n);
+                n = n2;
             }
-            break;
         }
-
-        return n;
+        break;
     }
 
-    function MemberExpression(t, x, allowCallSyntax) {
-        var n, n2, name, tt;
+    return n;
+}
+
+Pp.MemberExpression = function MemberExpression(allowCallSyntax) {
+    var n, n2, name, tt;
 
-        if (t.match(NEW)) {
-            n = new Node(t);
-            n.push(MemberExpression(t, x, false));
-            if (t.match(LEFT_PAREN)) {
-                n.type = NEW_WITH_ARGS;
-                n.push(ArgumentList(t, x));
-            }
-        } else {
-            n = PrimaryExpression(t, x);
+    if (this.match(NEW)) {
+        n = this.newNode();
+        n.push(this.MemberExpression(false));
+        if (this.match(LEFT_PAREN)) {
+            n.type = NEW_WITH_ARGS;
+            n.push(this.ArgumentList());
         }
+    } else {
+        n = this.PrimaryExpression();
+    }
 
-        while ((tt = t.get()) !== END) {
-            switch (tt) {
-              case DOT:
-                n2 = new Node(t);
-                n2.push(n);
-                n2.push(IdentifierName(t));
-                break;
+    while ((tt = this.t.get()) !== END) {
+        switch (tt) {
+          case DOT:
+            n2 = this.newNode();
+            n2.push(n);
+            n2.push(this.IdentifierName());
+            break;
 
-              case LEFT_BRACKET:
-                n2 = new Node(t, { type: INDEX });
+          case LEFT_BRACKET:
+            n2 = this.newNode({ type: INDEX });
+            n2.push(n);
+            n2.push(this.Expression());
+            this.mustMatch(RIGHT_BRACKET);
+            break;
+
+          case LEFT_PAREN:
+            if (allowCallSyntax) {
+                n2 = this.newNode({ type: CALL });
                 n2.push(n);
-                n2.push(Expression(t, x));
-                t.mustMatch(RIGHT_BRACKET);
+                n2.push(this.ArgumentList());
                 break;
-
-              case LEFT_PAREN:
-                if (allowCallSyntax) {
-                    n2 = new Node(t, { type: CALL });
-                    n2.push(n);
-                    n2.push(ArgumentList(t, x));
-                    break;
-                }
-
-                // FALL THROUGH
-              default:
-                t.unget();
-                return n;
             }
 
-            n = n2;
+            // FALL THROUGH
+          default:
+            this.t.unget();
+            return n;
         }
 
-        return n;
+        n = n2;
     }
 
-    function ArgumentList(t, x) {
-        var n, n2;
+    return n;
+}
 
-        n = new Node(t, { type: LIST });
-        if (t.match(RIGHT_PAREN, true))
-            return n;
-        do {
-            n2 = AssignExpression(t, x);
-            if (n2.type === YIELD && !n2.parenthesized && t.peek() === COMMA)
-                throw t.newSyntaxError("Yield expression must be parenthesized");
-            if (t.match(FOR)) {
-                n2 = GeneratorExpression(t, x, n2);
-                if (n.children.length > 1 || t.peek(true) === COMMA)
-                    throw t.newSyntaxError("Generator expression must be parenthesized");
-            }
-            n.push(n2);
-        } while (t.match(COMMA));
-        t.mustMatch(RIGHT_PAREN);
+Pp.ArgumentList = function ArgumentList() {
+    var n, n2;
 
+    n = this.newNode({ type: LIST });
+    if (this.match(RIGHT_PAREN, true))
         return n;
-    }
+    do {
+        n2 = this.AssignExpression();
+        if (n2.type === YIELD && !n2.parenthesized && this.peek() === COMMA)
+            this.fail("Yield expression must be parenthesized");
+        if (this.match(FOR)) {
+            n2 = this.GeneratorExpression(n2);
+            if (n.children.length > 1 || this.peek(true) === COMMA)
+                this.fail("Generator expression must be parenthesized");
+        }
+        n.push(n2);
+    } while (this.match(COMMA));
+    this.mustMatch(RIGHT_PAREN);
 
-    function PrimaryExpression(t, x) {
-        var n, n2, tt = t.get(true);
+    return n;
+}
 
-        switch (tt) {
-          case FUNCTION:
-            n = FunctionDefinition(t, x, false, EXPRESSED_FORM);
-            break;
+Pp.PrimaryExpression = function PrimaryExpression() {
+    var n, n2, tt = this.t.get(true);
 
-          case LEFT_BRACKET:
-            n = new Node(t, { type: ARRAY_INIT });
-            while ((tt = t.peek(true)) !== RIGHT_BRACKET) {
-                if (tt === COMMA) {
-                    t.get();
-                    n.push(null);
-                    continue;
-                }
-                n.push(AssignExpression(t, x));
-                if (tt !== COMMA && !t.match(COMMA))
-                    break;
-            }
+    switch (tt) {
+      case FUNCTION:
+        n = this.FunctionDefinition(false, EXPRESSED_FORM);
+        break;
 
-            // If we matched exactly one element and got a FOR, we have an
-            // array comprehension.
-            if (n.children.length === 1 && t.match(FOR)) {
-                n2 = new Node(t, { type: ARRAY_COMP,
-                                   expression: n.children[0],
-                                   tail: ComprehensionTail(t, x) });
-                n = n2;
+      case LEFT_BRACKET:
+        n = this.newNode({ type: ARRAY_INIT });
+        while ((tt = this.peek(true)) !== RIGHT_BRACKET) {
+            if (tt === COMMA) {
+                this.t.get();
+                n.push(null);
+                continue;
             }
-            t.mustMatch(RIGHT_BRACKET);
-            break;
+            n.push(this.AssignExpression());
+            if (tt !== COMMA && !this.match(COMMA))
+                break;
+        }
 
-          case LEFT_CURLY:
-            var id, fd;
-            n = new Node(t, { type: OBJECT_INIT });
+        // If we matched exactly one element and got a FOR, we have an
+        // array comprehension.
+        if (n.children.length === 1 && this.match(FOR)) {
+            n2 = this.newNode({ type: ARRAY_COMP,
+                                expression: n.children[0],
+                                tail: this.ComprehensionTail() });
+            n = n2;
+        }
+        this.mustMatch(RIGHT_BRACKET);
+        break;
 
-          object_init:
-            if (!t.match(RIGHT_CURLY)) {
-                do {
-                    tt = t.get();
-                    if ((t.token.value === "get" || t.token.value === "set") &&
-                        t.peek() === IDENTIFIER) {
-                        if (x.ecma3OnlyMode)
-                            throw t.newSyntaxError("Illegal property accessor");
-                        n.push(FunctionDefinition(t, x, true, EXPRESSED_FORM));
-                    } else {
-                        var comments = t.blockComments;
-                        switch (tt) {
-                          case IDENTIFIER: case NUMBER: case STRING:
-                            id = new Node(t, { type: IDENTIFIER });
+      case LEFT_CURLY:
+        var id, fd;
+        n = this.newNode({ type: OBJECT_INIT });
+
+        object_init:
+        if (!this.match(RIGHT_CURLY)) {
+            do {
+                tt = this.t.get();
+                if ((this.t.token.value === "get" || this.t.token.value === "set") &&
+                    this.peek() === IDENTIFIER) {
+                    n.push(this.FunctionDefinition(true, EXPRESSED_FORM));
+                } else {
+                    var comments = this.t.blockComments;
+                    switch (tt) {
+                      case IDENTIFIER: case NUMBER: case STRING:
+                        id = this.newNode({ type: IDENTIFIER });
+                        break;
+                      case RIGHT_CURLY:
+                        break object_init;
+                      default:
+                        if (this.t.token.value in definitions.keywords) {
+                            id = this.newNode({ type: IDENTIFIER });
                             break;
-                          case RIGHT_CURLY:
-                            if (x.ecma3OnlyMode)
-                                throw t.newSyntaxError("Illegal trailing ,");
-                            break object_init;
-                          default:
-                            if (t.token.value in definitions.keywords) {
-                                id = new Node(t, { type: IDENTIFIER });
-                                break;
-                            }
-                            throw t.newSyntaxError("Invalid property name");
-                        }
-                        if (t.match(COLON)) {
-                            n2 = new Node(t, { type: PROPERTY_INIT });
-                            n2.push(id);
-                            n2.push(AssignExpression(t, x));
-                            n2.blockComments = comments;
-                            n.push(n2);
-                        } else {
-                            // Support, e.g., |var {x, y} = o| as destructuring shorthand
-                            // for |var {x: x, y: y} = o|, per proposed JS2/ES4 for JS1.8.
-                            if (t.peek() !== COMMA && t.peek() !== RIGHT_CURLY)
-                                throw t.newSyntaxError("missing : after property");
-                            n.push(id);
                         }
+                        this.fail("Invalid property name");
                     }
-                } while (t.match(COMMA));
-                t.mustMatch(RIGHT_CURLY);
-            }
-            break;
-
-          case LEFT_PAREN:
-            n = ParenExpression(t, x);
-            t.mustMatch(RIGHT_PAREN);
-            n.parenthesized = true;
-            break;
+                    if (this.match(COLON)) {
+                        n2 = this.newNode({ type: PROPERTY_INIT });
+                        n2.push(id);
+                        n2.push(this.AssignExpression());
+                        n2.blockComments = comments;
+                        n.push(n2);
+                    } else {
+                        // Support, e.g., |var {x, y} = o| as destructuring shorthand
+                        // for |var {x: x, y: y} = o|, per proposed JS2/ES4 for JS1.8.
+                        if (this.peek() !== COMMA && this.peek() !== RIGHT_CURLY)
+                            this.fail("missing : after property");
+                        n.push(id);
+                    }
+                }
+            } while (this.match(COMMA));
+            this.mustMatch(RIGHT_CURLY);
+        }
+        break;
 
-          case LET:
-            n = LetBlock(t, x, false);
-            break;
+      case LEFT_PAREN:
+        n = this.ParenExpression();
+        this.mustMatch(RIGHT_PAREN);
+        n.parenthesized = true;
+        break;
 
-          case NULL: case THIS: case TRUE: case FALSE:
-          case IDENTIFIER: case NUMBER: case STRING: case REGEXP:
-            n = new Node(t);
-            break;
+      case LET:
+        n = this.LetBlock(false);
+        break;
 
-          default:
-            throw t.newSyntaxError("missing operand");
-            break;
-        }
+      case NULL: case THIS: case TRUE: case FALSE:
+      case IDENTIFIER: case NUMBER: case STRING: case REGEXP:
+        n = this.newNode();
+        break;
 
-        return n;
+      default:
+        this.fail("missing operand; found " + definitions.tokens[tt]);
+        break;
     }
 
-    /*
-     * parse :: (source, filename, line number) -> node
-     */
-    function parse(s, f, l) {
-        var t = new lexer.Tokenizer(s, f, l);
-        var n = Script(t, false, false);
-        if (!t.done)
-            throw t.newSyntaxError("Syntax error");
+    return n;
+}
 
-        return n;
+/*
+ * parse :: (source, filename, line number) -> node
+ */
+function parse(s, f, l) {
+    var t = new Tokenizer(s, f, l, options.allowHTMLComments);
+    var p = new Parser(t);
+    return p.Script(false, false, true);
+}
+
+/*
+ * parseFunction :: (source, boolean,
+ *                   DECLARED_FORM or EXPRESSED_FORM or STATEMENT_FORM,
+ *                   filename, line number)
+ *               -> node
+ */
+function parseFunction(s, requireName, form, f, l) {
+    var t = new Tokenizer(s, f, l);
+    var p = new Parser(t);
+    p.x = new StaticContext(null, null, false, false, false);
+    return p.FunctionDefinition(requireName, form);
+}
+
+/*
+ * parseStdin :: (source, {line number}, string, (string) -> boolean) -> program node
+ */
+function parseStdin(s, ln, prefix, isCommand) {
+    // the special .begin command is only recognized at the beginning
+    if (s.match(/^[\s]*\.begin[\s]*$/)) {
+        ++ln.value;
+        return parseMultiline(ln, prefix);
     }
 
-    /*
-     * parseStdin :: (source, {line number}, string, (string) -> boolean) -> program node
-     */
-    function parseStdin(s, ln, prefix, isCommand) {
-        // the special .begin command is only recognized at the beginning
-        if (s.match(/^[\s]*\.begin[\s]*$/)) {
-            ++ln.value;
-            return parseMultiline(ln, prefix);
-        }
+    // commands at the beginning are treated as the entire input
+    if (isCommand(s.trim()))
+        s = "";
 
-        // commands at the beginning are treated as the entire input
-        if (isCommand(s.trim()))
-            s = "";
+    for (;;) {
+        try {
+            var t = new Tokenizer(s, "stdin", ln.value, false);
+            var p = new Parser(t);
+            var n = p.Script(false, false);
+            ln.value = t.lineno;
+            return n;
+        } catch (e) {
+            if (!p.unexpectedEOF)
+                throw e;
 
-        for (;;) {
-            try {
-                var t = new lexer.Tokenizer(s, "stdin", ln.value);
-                var n = Script(t, false, false);
-                ln.value = t.lineno;
-                return n;
-            } catch (e) {
-                if (!t.unexpectedEOF)
+            // commands in the middle are not treated as part of the input
+            var more;
+            do {
+                if (prefix)
+                    putstr(prefix);
+                more = readline();
+                if (!more)
                     throw e;
+            } while (isCommand(more.trim()));
 
-                // commands in the middle are not treated as part of the input
-                var more;
-                do {
-                    if (prefix)
-                        putstr(prefix);
-                    more = readline();
-                    if (!more)
-                        throw e;
-                } while (isCommand(more.trim()));
-
-                s += "\n" + more;
-            }
+            s += "\n" + more;
         }
     }
+}
 
-    /*
-     * parseMultiline :: ({line number}, string | null) -> program node
-     */
-    function parseMultiline(ln, prefix) {
-        var s = "";
-        for (;;) {
-            if (prefix)
-                putstr(prefix);
-            var more = readline();
-            if (more === null)
-                return null;
-            // the only command recognized in multiline mode is .end
-            if (more.match(/^[\s]*\.end[\s]*$/))
-                break;
-            s += "\n" + more;
-        }
-        var t = new lexer.Tokenizer(s, "stdin", ln.value);
-        var n = Script(t, false, false);
-        ln.value = t.lineno;
-        return n;
+/*
+ * parseMultiline :: ({line number}, string | null) -> program node
+ */
+function parseMultiline(ln, prefix) {
+    var s = "";
+    for (;;) {
+        if (prefix)
+            putstr(prefix);
+        var more = readline();
+        if (more === null)
+            return null;
+        // the only command recognized in multiline mode is .end
+        if (more.match(/^[\s]*\.end[\s]*$/))
+            break;
+        s += "\n" + more;
     }
+    var t = new Tokenizer(s, "stdin", ln.value, false);
+    var p = new Parser(t);
+    var n = p.Script(false, false);
+    ln.value = t.lineno;
+    return n;
+}
 
-    module.exports = {
-        parse: parse,
-        parseStdin: parseStdin,
-        Node: Node,
-        SyntheticNode: SyntheticNode,
-        DECLARED_FORM: DECLARED_FORM,
-        EXPRESSED_FORM: EXPRESSED_FORM,
-        STATEMENT_FORM: STATEMENT_FORM,
-        Tokenizer: lexer.Tokenizer,
-        FunctionDefinition: FunctionDefinition,
-        Module: Module,
-        Export: Export
-    };
+exports.parse = parse;
+exports.parseStdin = parseStdin;
+exports.parseFunction = parseFunction;
+exports.Node = Node;
+exports.DECLARED_FORM = DECLARED_FORM;
+exports.EXPRESSED_FORM = EXPRESSED_FORM;
+exports.STATEMENT_FORM = STATEMENT_FORM;
+exports.Tokenizer = Tokenizer;
+exports.Parser = Parser;
+exports.Module = Module;
+exports.Export = Export;
 
 });/* vim: set sw=4 ts=4 et tw=78: */
 /* ***** BEGIN LICENSE BLOCK *****
@@ -8547,6 +9284,7 @@ define('ace/narcissus/jsparse', ['require', 'exports', 'module' , 'ace/narcissus
  *   Tom Austin <taustin@ucsc.edu>
  *   Brendan Eich <brendan@mozilla.org>
  *   Shu-Yu Guo <shu@rfrn.org>
+ *   Stephan Herhut <stephan.a.herhut@intel.com>
  *   Dave Herman <dherman@mozilla.com>
  *   Dimitris Vardoulakis <dimvar@ccs.neu.edu>
  *   Patrick Walton <pcwalton@mozilla.com>
@@ -8571,507 +9309,554 @@ define('ace/narcissus/jsparse', ['require', 'exports', 'module' , 'ace/narcissus
  * Lexical scanner.
  */
 
- define('ace/narcissus/jslex', ['require', 'exports', 'module' , 'ace/narcissus/jsdefs'], function(require, exports, module) {
+ define('ace/narcissus/lexer', ['require', 'exports', 'module' , 'ace/narcissus/definitions'], function(require, exports, module) {
 
-    var definitions = require("./jsdefs");
+var definitions = require('./definitions');
 
-    // Set constants in the local scope.
-    eval(definitions.consts);
+// Set constants in the local scope.
+eval(definitions.consts);
 
-    // Banned keywords by language version
-    const blackLists = { 160: {}, 185: {}, harmony: {} };
-    blackLists[160][LET] = true;
-    blackLists[160][MODULE] = true;
-    blackLists[160][YIELD] = true;
-    blackLists[185][MODULE] = true;
+// Build up a trie of operator tokens.
+var opTokens = {};
+for (var op in definitions.opTypeNames) {
+    if (op === '\n' || op === '.')
+        continue;
 
-    // Build up a trie of operator tokens.
-    var opTokens = {};
-    for (var op in definitions.opTypeNames) {
-        if (op === '\n' || op === '.')
-            continue;
+    var node = opTokens;
+    for (var i = 0; i < op.length; i++) {
+        var ch = op[i];
+        if (!(ch in node))
+            node[ch] = {};
+        node = node[ch];
+        node.op = op;
+    }
+}
 
-        var node = opTokens;
-        for (var i = 0; i < op.length; i++) {
-            var ch = op[i];
-            if (!(ch in node))
-                node[ch] = {};
-            node = node[ch];
-            node.op = op;
+/*
+ * Since JavaScript provides no convenient way to determine if a
+ * character is in a particular Unicode category, we use
+ * metacircularity to accomplish this (oh yeaaaah!)
+ */
+function isValidIdentifierChar(ch, first) {
+    // check directly for ASCII
+    if (ch <= "\u007F") {
+        if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || ch === '$' || ch === '_' ||
+            (!first && (ch >= '0' && ch <= '9'))) {
+            return true;
         }
+        return false;
     }
 
-    /*
-     * Tokenizer :: (source, filename, line number) -> Tokenizer
-     */
-    function Tokenizer(s, f, l) {
-        this.cursor = 0;
-        this.source = String(s);
-        this.tokens = [];
-        this.tokenIndex = 0;
-        this.lookahead = 0;
-        this.scanNewlines = false;
-        this.unexpectedEOF = false;
-        this.filename = f || "";
-        this.lineno = l || 1;
-        this.blackList = blackLists[Narcissus.options.version];
-        this.blockComments = null;
-    }
-
-    Tokenizer.prototype = {
-        get done() {
-            // We need to set scanOperand to true here because the first thing
-            // might be a regexp.
-            return this.peek(true) === END;
-        },
+    // create an object to test this in
+    var x = {};
+    x["x"+ch] = true;
+    x[ch] = true;
 
-        get token() {
-            return this.tokens[this.tokenIndex];
-        },
+    // then use eval to determine if it's a valid character
+    var valid = false;
+    try {
+        valid = (Function("x", "return (x." + (first?"":"x") + ch + ");")(x) === true);
+    } catch (ex) {}
 
-        match: function (tt, scanOperand) {
-            return this.get(scanOperand) === tt || this.unget();
-        },
+    return valid;
+}
 
-        mustMatch: function (tt) {
-            if (!this.match(tt)) {
-                throw this.newSyntaxError("Missing " +
-                                          definitions.tokens[tt].toLowerCase());
-            }
-            return this.token;
-        },
+function isIdentifier(str) {
+    if (typeof str !== "string")
+        return false;
 
-        peek: function (scanOperand) {
-            var tt, next;
-            if (this.lookahead) {
-                next = this.tokens[(this.tokenIndex + this.lookahead) & 3];
-                tt = (this.scanNewlines && next.lineno !== this.lineno)
-                     ? NEWLINE
-                     : next.type;
-            } else {
-                tt = this.get(scanOperand);
-                this.unget();
-            }
-            return tt;
-        },
+    if (str.length === 0)
+        return false;
 
-        peekOnSameLine: function (scanOperand) {
-            this.scanNewlines = true;
-            var tt = this.peek(scanOperand);
-            this.scanNewlines = false;
-            return tt;
-        },
+    if (!isValidIdentifierChar(str[0], true))
+        return false;
 
-        lastBlockComment: function() {
-            var length = this.blockComments.length;
-            return length ? this.blockComments[length - 1] : null;
-        },
+    for (var i = 1; i < str.length; i++) {
+        if (!isValidIdentifierChar(str[i], false))
+            return false;
+    }
 
-        // Eat comments and whitespace.
-        skip: function () {
-            var input = this.source;
-            this.blockComments = [];
-            for (;;) {
-                var ch = input[this.cursor++];
-                var next = input[this.cursor];
-                // handle \r, \r\n and (always preferable) \n
-                if (ch === '\r') {
-                    // if the next character is \n, we don't care about this at all
-                    if (next === '\n') continue;
-
-                    // otherwise, we want to consider this as a newline
-                    ch = '\n';
-                }
+    return true;
+}
 
-                if (ch === '\n' && !this.scanNewlines) {
-                    this.lineno++;
-                } else if (ch === '/' && next === '*') {
-                    var commentStart = ++this.cursor;
-                    for (;;) {
-                        ch = input[this.cursor++];
-                        if (ch === undefined)
-                            throw this.newSyntaxError("Unterminated comment");
-
-                        if (ch === '*') {
-                            next = input[this.cursor];
-                            if (next === '/') {
-                                var commentEnd = this.cursor - 1;
-                                this.cursor++;
-                                break;
-                            }
-                        } else if (ch === '\n') {
-                            this.lineno++;
-                        }
-                    }
-                    this.blockComments.push(input.substring(commentStart, commentEnd));
-                } else if (ch === '/' && next === '/') {
-                    this.cursor++;
-                    for (;;) {
-                        ch = input[this.cursor++];
-                        next = input[this.cursor];
-                        if (ch === undefined)
-                            return;
+/*
+ * Tokenizer :: (source, filename, line number, boolean) -> Tokenizer
+ */
+function Tokenizer(s, f, l, allowHTMLComments) {
+    this.cursor = 0;
+    this.source = String(s);
+    this.tokens = [];
+    this.tokenIndex = 0;
+    this.lookahead = 0;
+    this.scanNewlines = false;
+    this.filename = f || "";
+    this.lineno = l || 1;
+    this.allowHTMLComments = allowHTMLComments;
+    this.blockComments = null;
+}
 
-                        if (ch === '\r') {
-                            // check for \r\n
-                            if (next !== '\n') ch = '\n';
-                        }
+Tokenizer.prototype = {
+    get done() {
+        // We need to set scanOperand to true here because the first thing
+        // might be a regexp.
+        return this.peek(true) === END;
+    },
+
+    get token() {
+        return this.tokens[this.tokenIndex];
+    },
+
+    match: function (tt, scanOperand, keywordIsName) {
+        return this.get(scanOperand, keywordIsName) === tt || this.unget();
+    },
+
+    mustMatch: function (tt, keywordIsName) {
+        if (!this.match(tt, false, keywordIsName)) {
+            throw this.newSyntaxError("Missing " +
+                                      definitions.tokens[tt].toLowerCase());
+        }
+        return this.token;
+    },
+
+    peek: function (scanOperand) {
+        var tt, next;
+        if (this.lookahead) {
+            next = this.tokens[(this.tokenIndex + this.lookahead) & 3];
+            tt = (this.scanNewlines && next.lineno !== this.lineno)
+                ? NEWLINE
+                : next.type;
+        } else {
+            tt = this.get(scanOperand);
+            this.unget();
+        }
+        return tt;
+    },
 
-                        if (ch === '\n') {
-                            if (this.scanNewlines) {
-                                this.cursor--;
-                            } else {
-                                this.lineno++;
-                            }
+    peekOnSameLine: function (scanOperand) {
+        this.scanNewlines = true;
+        var tt = this.peek(scanOperand);
+        this.scanNewlines = false;
+        return tt;
+    },
+
+    lastBlockComment: function() {
+        var length = this.blockComments.length;
+        return length ? this.blockComments[length - 1] : null;
+    },
+
+    // Eat comments and whitespace.
+    skip: function () {
+        var input = this.source;
+        this.blockComments = [];
+        for (;;) {
+            var ch = input[this.cursor++];
+            var next = input[this.cursor];
+            // handle \r, \r\n and (always preferable) \n
+            if (ch === '\r') {
+                // if the next character is \n, we don't care about this at all
+                if (next === '\n') continue;
+
+                // otherwise, we want to consider this as a newline
+                ch = '\n';
+            }
+
+            if (ch === '\n' && !this.scanNewlines) {
+                this.lineno++;
+            } else if (ch === '/' && next === '*') {
+                var commentStart = ++this.cursor;
+                for (;;) {
+                    ch = input[this.cursor++];
+                    if (ch === undefined)
+                        throw this.newSyntaxError("Unterminated comment");
+
+                    if (ch === '*') {
+                        next = input[this.cursor];
+                        if (next === '/') {
+                            var commentEnd = this.cursor - 1;
+                            this.cursor++;
                             break;
                         }
+                    } else if (ch === '\n') {
+                        this.lineno++;
                     }
-                } else if (!(ch in definitions.whitespace)) {
-                    this.cursor--;
-                    return;
                 }
-            }
-        },
-
-        // Lex the exponential part of a number, if present. Return true iff an
-        // exponential part was found.
-        lexExponent: function() {
-            var input = this.source;
-            var next = input[this.cursor];
-            if (next === 'e' || next === 'E') {
+                this.blockComments.push(input.substring(commentStart, commentEnd));
+            } else if ((ch === '/' && next === '/') ||
+                       (this.allowHTMLComments && ch === '<' && next === '!' &&
+                        input[this.cursor + 1] === '-' && input[this.cursor + 2] === '-' &&
+                        (this.cursor += 2))) {
                 this.cursor++;
-                ch = input[this.cursor++];
-                if (ch === '+' || ch === '-')
+                for (;;) {
                     ch = input[this.cursor++];
+                    next = input[this.cursor];
+                    if (ch === undefined)
+                        return;
 
-                if (ch < '0' || ch > '9')
-                    throw this.newSyntaxError("Missing exponent");
+                    if (ch === '\r') {
+                        // check for \r\n
+                        if (next !== '\n') ch = '\n';
+                    }
 
-                do {
-                    ch = input[this.cursor++];
-                } while (ch >= '0' && ch <= '9');
+                    if (ch === '\n') {
+                        if (this.scanNewlines) {
+                            this.cursor--;
+                        } else {
+                            this.lineno++;
+                        }
+                        break;
+                    }
+                }
+            } else if (!(ch in definitions.whitespace)) {
                 this.cursor--;
-
-                return true;
+                return;
             }
+        }
+    },
 
-            return false;
-        },
-
-        lexZeroNumber: function (ch) {
-            var token = this.token, input = this.source;
-            token.type = NUMBER;
-
+    // Lex the exponential part of a number, if present. Return true iff an
+    // exponential part was found.
+    lexExponent: function() {
+        var input = this.source;
+        var next = input[this.cursor];
+        if (next === 'e' || next === 'E') {
+            this.cursor++;
             ch = input[this.cursor++];
-            if (ch === '.') {
-                do {
-                    ch = input[this.cursor++];
-                } while (ch >= '0' && ch <= '9');
-                this.cursor--;
+            if (ch === '+' || ch === '-')
+                ch = input[this.cursor++];
 
-                this.lexExponent();
-                token.value = parseFloat(token.start, this.cursor);
-            } else if (ch === 'x' || ch === 'X') {
-                do {
-                    ch = input[this.cursor++];
-                } while ((ch >= '0' && ch <= '9') || (ch >= 'a' && ch <= 'f') ||
-                         (ch >= 'A' && ch <= 'F'));
-                this.cursor--;
+            if (ch < '0' || ch > '9')
+                throw this.newSyntaxError("Missing exponent");
 
-                token.value = parseInt(input.substring(token.start, this.cursor));
-            } else if (ch >= '0' && ch <= '7') {
-                do {
-                    ch = input[this.cursor++];
-                } while (ch >= '0' && ch <= '7');
-                this.cursor--;
+            do {
+                ch = input[this.cursor++];
+            } while (ch >= '0' && ch <= '9');
+            this.cursor--;
 
-                token.value = parseInt(input.substring(token.start, this.cursor));
-            } else {
-                this.cursor--;
-                this.lexExponent();     // 0E1, &c.
-                token.value = 0;
-            }
-        },
+            return true;
+        }
 
-        lexNumber: function (ch) {
-            var token = this.token, input = this.source;
-            token.type = NUMBER;
+        return false;
+    },
 
-            var floating = false;
+    lexZeroNumber: function (ch) {
+        var token = this.token, input = this.source;
+        token.type = NUMBER;
+
+        ch = input[this.cursor++];
+        if (ch === '.') {
             do {
                 ch = input[this.cursor++];
-                if (ch === '.' && !floating) {
-                    floating = true;
-                    ch = input[this.cursor++];
-                }
             } while (ch >= '0' && ch <= '9');
-
             this.cursor--;
 
-            var exponent = this.lexExponent();
-            floating = floating || exponent;
+            this.lexExponent();
+            token.value = parseFloat(
+                input.substring(token.start, this.cursor));
+        } else if (ch === 'x' || ch === 'X') {
+            do {
+                ch = input[this.cursor++];
+            } while ((ch >= '0' && ch <= '9') || (ch >= 'a' && ch <= 'f') ||
+                     (ch >= 'A' && ch <= 'F'));
+            this.cursor--;
 
-            var str = input.substring(token.start, this.cursor);
-            token.value = floating ? parseFloat(str) : parseInt(str);
-        },
+            token.value = parseInt(input.substring(token.start, this.cursor));
+        } else if (ch >= '0' && ch <= '7') {
+            do {
+                ch = input[this.cursor++];
+            } while (ch >= '0' && ch <= '7');
+            this.cursor--;
 
-        lexDot: function (ch) {
-            var token = this.token, input = this.source;
-            var next = input[this.cursor];
-            if (next >= '0' && next <= '9') {
-                do {
-                    ch = input[this.cursor++];
-                } while (ch >= '0' && ch <= '9');
-                this.cursor--;
+            token.value = parseInt(input.substring(token.start, this.cursor));
+        } else {
+            this.cursor--;
+            this.lexExponent();     // 0E1, &c.
+            token.value = 0;
+        }
+    },
 
-                this.lexExponent();
+    lexNumber: function (ch) {
+        var token = this.token, input = this.source;
+        token.type = NUMBER;
 
-                token.type = NUMBER;
-                token.value = parseFloat(token.start, this.cursor);
-            } else {
-                token.type = DOT;
-                token.assignOp = null;
-                token.value = '.';
+        var floating = false;
+        do {
+            ch = input[this.cursor++];
+            if (ch === '.' && !floating) {
+                floating = true;
+                ch = input[this.cursor++];
             }
-        },
+        } while (ch >= '0' && ch <= '9');
+
+        this.cursor--;
+
+        var exponent = this.lexExponent();
+        floating = floating || exponent;
+
+        var str = input.substring(token.start, this.cursor);
+        token.value = floating ? parseFloat(str) : parseInt(str);
+    },
+
+    lexDot: function (ch) {
+        var token = this.token, input = this.source;
+        var next = input[this.cursor];
+        if (next >= '0' && next <= '9') {
+            do {
+                ch = input[this.cursor++];
+            } while (ch >= '0' && ch <= '9');
+            this.cursor--;
 
-        lexString: function (ch) {
-            var token = this.token, input = this.source;
-            token.type = STRING;
+            this.lexExponent();
 
-            var hasEscapes = false;
-            var delim = ch;
-            if (input.length <= this.cursor)
+            token.type = NUMBER;
+            token.value = parseFloat(
+                input.substring(token.start, this.cursor));
+        } else {
+            token.type = DOT;
+            token.assignOp = null;
+            token.value = '.';
+        }
+    },
+
+    lexString: function (ch) {
+        var token = this.token, input = this.source;
+        token.type = STRING;
+
+        var hasEscapes = false;
+        var delim = ch;
+        if (input.length <= this.cursor)
+            throw this.newSyntaxError("Unterminated string literal");
+        while ((ch = input[this.cursor++]) !== delim) {
+            if (ch == '\n' || ch == '\r')
+                throw this.newSyntaxError("Unterminated string literal");
+            if (this.cursor == input.length)
                 throw this.newSyntaxError("Unterminated string literal");
-            while ((ch = input[this.cursor++]) !== delim) {
-                if (this.cursor == input.length)
+            if (ch === '\\') {
+                hasEscapes = true;
+                if (++this.cursor == input.length)
                     throw this.newSyntaxError("Unterminated string literal");
-                if (ch === '\\') {
-                    hasEscapes = true;
-                    if (++this.cursor == input.length)
-                        throw this.newSyntaxError("Unterminated string literal");
-                }
             }
+        }
 
-            token.value = hasEscapes
-                          ? eval(input.substring(token.start, this.cursor))
-                          : input.substring(token.start + 1, this.cursor - 1);
-        },
+        token.value = hasEscapes
+            ? eval(input.substring(token.start, this.cursor))
+            : input.substring(token.start + 1, this.cursor - 1);
+    },
 
-        lexRegExp: function (ch) {
-            var token = this.token, input = this.source;
-            token.type = REGEXP;
+    lexRegExp: function (ch) {
+        var token = this.token, input = this.source;
+        token.type = REGEXP;
 
-            do {
-                ch = input[this.cursor++];
-                if (ch === '\\') {
-                    this.cursor++;
-                } else if (ch === '[') {
-                    do {
-                        if (ch === undefined)
-                            throw this.newSyntaxError("Unterminated character class");
+        do {
+            ch = input[this.cursor++];
+            if (ch === '\\') {
+                this.cursor++;
+            } else if (ch === '[') {
+                do {
+                    if (ch === undefined)
+                        throw this.newSyntaxError("Unterminated character class");
 
-                        if (ch === '\\')
-                            this.cursor++;
+                    if (ch === '\\')
+                        this.cursor++;
 
-                        ch = input[this.cursor++];
-                    } while (ch !== ']');
-                } else if (ch === undefined) {
-                    throw this.newSyntaxError("Unterminated regex");
-                }
-            } while (ch !== '/');
+                    ch = input[this.cursor++];
+                } while (ch !== ']');
+            } else if (ch === undefined) {
+                throw this.newSyntaxError("Unterminated regex");
+            }
+        } while (ch !== '/');
 
-            do {
-                ch = input[this.cursor++];
-            } while (ch >= 'a' && ch <= 'z');
+        do {
+            ch = input[this.cursor++];
+        } while (ch >= 'a' && ch <= 'z');
 
-            this.cursor--;
+        this.cursor--;
 
-            token.value = eval(input.substring(token.start, this.cursor));
-        },
+        token.value = eval(input.substring(token.start, this.cursor));
+    },
 
-        lexOp: function (ch) {
-            var token = this.token, input = this.source;
+    lexOp: function (ch) {
+        var token = this.token, input = this.source;
 
-            // A bit ugly, but it seems wasteful to write a trie lookup routine
-            // for only 3 characters...
-            var node = opTokens[ch];
-            var next = input[this.cursor];
+        // A bit ugly, but it seems wasteful to write a trie lookup routine
+        // for only 3 characters...
+        var node = opTokens[ch];
+        var next = input[this.cursor];
+        if (next in node) {
+            node = node[next];
+            this.cursor++;
+            next = input[this.cursor];
             if (next in node) {
                 node = node[next];
                 this.cursor++;
                 next = input[this.cursor];
-                if (next in node) {
-                    node = node[next];
-                    this.cursor++;
-                    next = input[this.cursor];
-                }
             }
+        }
 
-            var op = node.op;
-            if (definitions.assignOps[op] && input[this.cursor] === '=') {
-                this.cursor++;
-                token.type = ASSIGN;
-                token.assignOp = definitions.tokenIds[definitions.opTypeNames[op]];
-                op += '=';
-            } else {
-                token.type = definitions.tokenIds[definitions.opTypeNames[op]];
-                token.assignOp = null;
-            }
+        var op = node.op;
+        if (definitions.assignOps[op] && input[this.cursor] === '=') {
+            this.cursor++;
+            token.type = ASSIGN;
+            token.assignOp = definitions.tokenIds[definitions.opTypeNames[op]];
+            op += '=';
+        } else {
+            token.type = definitions.tokenIds[definitions.opTypeNames[op]];
+            token.assignOp = null;
+        }
 
-            token.value = op;
-        },
+        token.value = op;
+    },
 
-        // FIXME: Unicode escape sequences
-        lexIdent: function (ch) {
-            var token = this.token;
-            var id = ch;
+    // FIXME: Unicode escape sequences
+    lexIdent: function (ch, keywordIsName) {
+        var token = this.token;
+        var id = ch;
 
-            while ((ch = this.getValidIdentifierChar(false)) !== null) {
-                id += ch;
-            }
+        while ((ch = this.getValidIdentifierChar(false)) !== null) {
+            id += ch;
+        }
+
+        token.type = IDENTIFIER;
+        token.value = id;
+
+        if (keywordIsName)
+            return;
+
+        var kw;
 
-            token.type = definitions.keywords[id] || IDENTIFIER;
-            if (token.type in this.blackList) {
-                // banned keyword, this is an identifier
-                token.type = IDENTIFIER;
+        if (this.parser.mozillaMode) {
+            kw = definitions.mozillaKeywords[id];
+            if (kw) {
+                token.type = kw;
+                return;
             }
-            token.value = id;
-        },
+        }
 
-        /*
-         * Tokenizer.get :: void -> token type
-         *
-         * Consume input *only* if there is no lookahead.
-         * Dispatch to the appropriate lexing function depending on the input.
-         */
-        get: function (scanOperand) {
-            var token;
-            while (this.lookahead) {
-                --this.lookahead;
-                this.tokenIndex = (this.tokenIndex + 1) & 3;
-                token = this.tokens[this.tokenIndex];
-                if (token.type !== NEWLINE || this.scanNewlines)
-                    return token.type;
+        if (this.parser.x.strictMode) {
+            kw = definitions.strictKeywords[id];
+            if (kw) {
+                token.type = kw;
+                return;
             }
+        }
 
-            this.skip();
+        kw = definitions.keywords[id];
+        if (kw)
+            token.type = kw;
+    },
 
+    /*
+     * Tokenizer.get :: ([boolean[, boolean]]) -> token type
+     *
+     * Consume input *only* if there is no lookahead.
+     * Dispatch to the appropriate lexing function depending on the input.
+     */
+    get: function (scanOperand, keywordIsName) {
+        var token;
+        while (this.lookahead) {
+            --this.lookahead;
             this.tokenIndex = (this.tokenIndex + 1) & 3;
             token = this.tokens[this.tokenIndex];
-            if (!token)
-                this.tokens[this.tokenIndex] = token = {};
-
-            var input = this.source;
-            if (this.cursor >= input.length)
-                return token.type = END;
-
-            token.start = this.cursor;
-            token.lineno = this.lineno;
-
-            var ich = this.getValidIdentifierChar(true);
-            var ch = (ich === null) ? input[this.cursor++] : null;
-            if (ich !== null) {
-                this.lexIdent(ich);
-            } else if (scanOperand && ch === '/') {
-                this.lexRegExp(ch);
-            } else if (ch in opTokens) {
-                this.lexOp(ch);
-            } else if (ch === '.') {
-                this.lexDot(ch);
-            } else if (ch >= '1' && ch <= '9') {
-                this.lexNumber(ch);
-            } else if (ch === '0') {
-                this.lexZeroNumber(ch);
-            } else if (ch === '"' || ch === "'") {
-                this.lexString(ch);
-            } else if (this.scanNewlines && (ch === '\n' || ch === '\r')) {
-                // if this was a \r, look for \r\n
-                if (ch === '\r' && input[this.cursor] === '\n') this.cursor++;
-                token.type = NEWLINE;
-                token.value = '\n';
-                this.lineno++;
-            } else {
-                throw this.newSyntaxError("Illegal token");
-            }
-
-            token.end = this.cursor;
-            return token.type;
-        },
-
-        /*
-         * Tokenizer.unget :: void -> undefined
-         *
-         * Match depends on unget returning undefined.
-         */
-        unget: function () {
-            if (++this.lookahead === 4) throw "PANIC: too much lookahead!";
-            this.tokenIndex = (this.tokenIndex - 1) & 3;
-        },
-
-        newSyntaxError: function (m) {
-            m = (this.filename ? this.filename + ":" : "") + this.lineno + ": " + m;
-            var e = new SyntaxError(m, this.filename, this.lineno);
-            e.source = this.source;
-            e.cursor = this.lookahead
-                       ? this.tokens[(this.tokenIndex + this.lookahead) & 3].start
-                       : this.cursor;
-            return e;
-        },
+            if (token.type !== NEWLINE || this.scanNewlines)
+                return token.type;
+        }
+
+        this.skip();
+
+        this.tokenIndex = (this.tokenIndex + 1) & 3;
+        token = this.tokens[this.tokenIndex];
+        if (!token)
+            this.tokens[this.tokenIndex] = token = {};
+
+        var input = this.source;
+        if (this.cursor >= input.length)
+            return token.type = END;
+
+        token.start = this.cursor;
+        token.lineno = this.lineno;
+
+        var ich = this.getValidIdentifierChar(true);
+        var ch = (ich === null) ? input[this.cursor++] : null;
+        if (ich !== null) {
+            this.lexIdent(ich, keywordIsName);
+        } else if (scanOperand && ch === '/') {
+            this.lexRegExp(ch);
+        } else if (ch in opTokens) {
+            this.lexOp(ch);
+        } else if (ch === '.') {
+            this.lexDot(ch);
+        } else if (ch >= '1' && ch <= '9') {
+            this.lexNumber(ch);
+        } else if (ch === '0') {
+            this.lexZeroNumber(ch);
+        } else if (ch === '"' || ch === "'") {
+            this.lexString(ch);
+        } else if (this.scanNewlines && (ch === '\n' || ch === '\r')) {
+            // if this was a \r, look for \r\n
+            if (ch === '\r' && input[this.cursor] === '\n') this.cursor++;
+            token.type = NEWLINE;
+            token.value = '\n';
+            this.lineno++;
+        } else {
+            throw this.newSyntaxError("Illegal token");
+        }
 
-        /* Gets a single valid identifier char from the input stream, or null
-         * if there is none.
-         * Since JavaScript provides no convenient way to determine if a
-         * character is in a particular Unicode category, we use
-         * metacircularity to accomplish this (oh yeaaaah!) */
-        getValidIdentifierChar: function(first) {
-            var input = this.source;
-            if (this.cursor >= input.length) return null;
-            var ch = input[this.cursor];
-
-            // first check for \u escapes
-            if (ch === '\\' && input[this.cursor+1] === 'u') {
-                // get the character value
-                try {
-                    ch = String.fromCharCode(parseInt(
-                        input.substring(this.cursor + 2, this.cursor + 6),
-                        16));
-                } catch (ex) {
-                    return null;
-                }
-                this.cursor += 5;
-            }
+        token.end = this.cursor;
+        return token.type;
+    },
 
-            // check directly for ASCII
-            if (ch <= "\u007F") {
-                if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || ch === '$' || ch === '_' ||
-                    (!first && (ch >= '0' && ch <= '9'))) {
-                    this.cursor++;
-                    return ch;
-                }
+    /*
+     * Tokenizer.unget :: void -> undefined
+     *
+     * Match depends on unget returning undefined.
+     */
+    unget: function () {
+        if (++this.lookahead === 4) throw "PANIC: too much lookahead!";
+        this.tokenIndex = (this.tokenIndex - 1) & 3;
+    },
+
+    newSyntaxError: function (m) {
+        m = (this.filename ? this.filename + ":" : "") + this.lineno + ": " + m;
+        var e = new SyntaxError(m, this.filename, this.lineno);
+        e.source = this.source;
+        e.cursor = this.lookahead
+            ? this.tokens[(this.tokenIndex + this.lookahead) & 3].start
+            : this.cursor;
+        return e;
+    },
+
+
+    /* Gets a single valid identifier char from the input stream, or null
+     * if there is none.
+     */
+    getValidIdentifierChar: function(first) {
+        var input = this.source;
+        if (this.cursor >= input.length) return null;
+        var ch = input[this.cursor];
+
+        // first check for \u escapes
+        if (ch === '\\' && input[this.cursor+1] === 'u') {
+            // get the character value
+            try {
+                ch = String.fromCharCode(parseInt(
+                    input.substring(this.cursor + 2, this.cursor + 6),
+                    16));
+            } catch (ex) {
                 return null;
             }
-    
-            // create an object to test this in
-            var x = {};
-            x["x"+ch] = true;
-            x[ch] = true;
-    
-            // then use eval to determine if it's a valid character
-            var valid = false;
-            try {
-                valid = (Function("x", "return (x." + (first?"":"x") + ch + ");")(x) === true);
-            } catch (ex) {}
-            if (valid) this.cursor++;
-            return (valid ? ch : null);
-        },
-    };
+            this.cursor += 5;
+        }
+
+        var valid = isValidIdentifierChar(ch, first);
+        if (valid) this.cursor++;
+        return (valid ? ch : null);
+    },
+};
 
 
-    module.exports = { Tokenizer: Tokenizer };
+exports.isIdentifier = isIdentifier;
+exports.Tokenizer = Tokenizer;
 
-});
-/* vim: set sw=4 ts=4 et tw=78: */
+});/* vim: set sw=4 ts=4 et tw=78: */
 /* ***** BEGIN LICENSE BLOCK *****
  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  *
@@ -9123,507 +9908,533 @@ define('ace/narcissus/jsparse', ['require', 'exports', 'module' , 'ace/narcissus
  * done by SpiderMonkey.
  */
 
-define('ace/narcissus/jsdefs', ['require', 'exports', 'module' ], function(require, exports, module) {
-
-    var narcissus = {
-        options: {
-            version: 185,
-            // Global variables to hide from the interpreter
-            hiddenHostGlobals: { Narcissus: true },
-            // Desugar SpiderMonkey language extensions?
-            desugarExtensions: false
-        },
-        hostSupportsEvalConst: (function() {
-            try {
-                return eval("(function(s) { eval(s); return x })('const x = true;')");
-            } catch (e) {
-                return false;
-            }
-        })(),
-        hostGlobal: this
-    };
-    Narcissus = narcissus;
-
-    var tokens = [
-        // End of source.
-        "END",
-
-        // Operators and punctuators.  Some pair-wise order matters, e.g. (+, -)
-        // and (UNARY_PLUS, UNARY_MINUS).
-        "\n", ";",
-        ",",
-        "=",
-        "?", ":", "CONDITIONAL",
-        "||",
-        "&&",
-        "|",
-        "^",
-        "&",
-        "==", "!=", "===", "!==",
-        "<", "<=", ">=", ">",
-        "<<", ">>", ">>>",
-        "+", "-",
-        "*", "/", "%",
-        "!", "~", "UNARY_PLUS", "UNARY_MINUS",
-        "++", "--",
-        ".",
-        "[", "]",
-        "{", "}",
-        "(", ")",
-
-        // Nonterminal tree node type codes.
-        "SCRIPT", "BLOCK", "LABEL", "FOR_IN", "CALL", "NEW_WITH_ARGS", "INDEX",
-        "ARRAY_INIT", "OBJECT_INIT", "PROPERTY_INIT", "GETTER", "SETTER",
-        "GROUP", "LIST", "LET_BLOCK", "ARRAY_COMP", "GENERATOR", "COMP_TAIL",
-
-        // Terminals.
-        "IDENTIFIER", "NUMBER", "STRING", "REGEXP",
-
-        // Keywords.
-        "break",
-        "case", "catch", "const", "continue",
-        "debugger", "default", "delete", "do",
-        "else", "export",
-        "false", "finally", "for", "function",
-        "if", "import", "in", "instanceof",
-        "let", "module",
-        "new", "null",
-        "return",
-        "switch",
-        "this", "throw", "true", "try", "typeof",
-        "var", "void",
-        "yield",
-        "while", "with",
-    ];
-
-    var statementStartTokens = [
-        "break",
-        "const", "continue",
-        "debugger", "do",
-        "for",
-        "if",
-        "return",
-        "switch",
-        "throw", "try",
-        "var",
-        "yield",
-        "while", "with",
-    ];
-
-    // Whitespace characters (see ECMA-262 7.2)
-    var whitespaceChars = [
-        // normal whitespace:
-        "\u0009", "\u000B", "\u000C", "\u0020", "\u00A0", "\uFEFF", 
-
-        // high-Unicode whitespace:
-        "\u1680", "\u180E",
-        "\u2000", "\u2001", "\u2002", "\u2003", "\u2004", "\u2005", "\u2006",
-        "\u2007", "\u2008", "\u2009", "\u200A",
-        "\u202F", "\u205F", "\u3000"
-    ];
-
-    var whitespace = {};
-    for (var i = 0; i < whitespaceChars.length; i++) {
-        whitespace[whitespaceChars[i]] = true;
-    }
-
-    // Operator and punctuator mapping from token to tree node type name.
-    // NB: because the lexer doesn't backtrack, all token prefixes must themselves
-    // be valid tokens (e.g. !== is acceptable because its prefixes are the valid
-    // tokens != and !).
-    var opTypeNames = {
-        '\n':   "NEWLINE",
-        ';':    "SEMICOLON",
-        ',':    "COMMA",
-        '?':    "HOOK",
-        ':':    "COLON",
-        '||':   "OR",
-        '&&':   "AND",
-        '|':    "BITWISE_OR",
-        '^':    "BITWISE_XOR",
-        '&':    "BITWISE_AND",
-        '===':  "STRICT_EQ",
-        '==':   "EQ",
-        '=':    "ASSIGN",
-        '!==':  "STRICT_NE",
-        '!=':   "NE",
-        '<<':   "LSH",
-        '<=':   "LE",
-        '<':    "LT",
-        '>>>':  "URSH",
-        '>>':   "RSH",
-        '>=':   "GE",
-        '>':    "GT",
-        '++':   "INCREMENT",
-        '--':   "DECREMENT",
-        '+':    "PLUS",
-        '-':    "MINUS",
-        '*':    "MUL",
-        '/':    "DIV",
-        '%':    "MOD",
-        '!':    "NOT",
-        '~':    "BITWISE_NOT",
-        '.':    "DOT",
-        '[':    "LEFT_BRACKET",
-        ']':    "RIGHT_BRACKET",
-        '{':    "LEFT_CURLY",
-        '}':    "RIGHT_CURLY",
-        '(':    "LEFT_PAREN",
-        ')':    "RIGHT_PAREN"
-    };
-
-    // Hash of keyword identifier to tokens index.  NB: we must null __proto__ to
-    // avoid toString, etc. namespace pollution.
-    var keywords = {__proto__: null};
-
-    // Define const END, etc., based on the token names.  Also map name to index.
-    var tokenIds = {};
-
-    // Building up a string to be eval'd in different contexts.
-    var consts = Narcissus.hostSupportsEvalConst ? "const " : "var ";
-    for (var i = 0, j = tokens.length; i < j; i++) {
-        if (i > 0)
-            consts += ", ";
-        var t = tokens[i];
-        var name;
-        if (/^[a-z]/.test(t)) {
-            name = t.toUpperCase();
-            keywords[t] = i;
-        } else {
-            name = (/^\W/.test(t) ? opTypeNames[t] : t);
-        }
-        consts += name + " = " + i;
-        tokenIds[name] = i;
-        tokens[t] = i;
-    }
-    consts += ";";
-
-    var isStatementStartCode = {__proto__: null};
-    for (i = 0, j = statementStartTokens.length; i < j; i++)
-        isStatementStartCode[keywords[statementStartTokens[i]]] = true;
-
-    // Map assignment operators to their indexes in the tokens array.
-    var assignOps = ['|', '^', '&', '<<', '>>', '>>>', '+', '-', '*', '/', '%'];
-
-    for (i = 0, j = assignOps.length; i < j; i++) {
-        t = assignOps[i];
-        assignOps[t] = tokens[t];
-    }
-
-    function defineGetter(obj, prop, fn, dontDelete, dontEnum) {
-        Object.defineProperty(obj, prop,
-                              { get: fn, configurable: !dontDelete, enumerable: !dontEnum });
-    }
+define('ace/narcissus/definitions', ['require', 'exports', 'module' ], function(require, exports, module) {
+
+var tokens = [
+    // End of source.
+    "END",
+
+    // Operators and punctuators.  Some pair-wise order matters, e.g. (+, -)
+    // and (UNARY_PLUS, UNARY_MINUS).
+    "\n", ";",
+    ",",
+    "=",
+    "?", ":", "CONDITIONAL",
+    "||",
+    "&&",
+    "|",
+    "^",
+    "&",
+    "==", "!=", "===", "!==",
+    "<", "<=", ">=", ">",
+    "<<", ">>", ">>>",
+    "+", "-",
+    "*", "/", "%",
+    "!", "~", "UNARY_PLUS", "UNARY_MINUS",
+    "++", "--",
+    ".",
+    "[", "]",
+    "{", "}",
+    "(", ")",
+
+    // Nonterminal tree node type codes.
+    "SCRIPT", "BLOCK", "LABEL", "FOR_IN", "CALL", "NEW_WITH_ARGS", "INDEX",
+    "ARRAY_INIT", "OBJECT_INIT", "PROPERTY_INIT", "GETTER", "SETTER",
+    "GROUP", "LIST", "LET_BLOCK", "ARRAY_COMP", "GENERATOR", "COMP_TAIL",
+
+    // Contextual keywords.
+    "IMPLEMENTS", "INTERFACE", "LET", "MODULE", "PACKAGE", "PRIVATE",
+    "PROTECTED", "PUBLIC", "STATIC", "USE", "YIELD",
+
+    // Terminals.
+    "IDENTIFIER", "NUMBER", "STRING", "REGEXP",
+
+    // Keywords.
+    "break",
+    "case", "catch", "const", "continue",
+    "debugger", "default", "delete", "do",
+    "else", "export",
+    "false", "finally", "for", "function",
+    "if", "import", "in", "instanceof",
+    "new", "null",
+    "return",
+    "switch",
+    "this", "throw", "true", "try", "typeof",
+    "var", "void",
+    "while", "with",
+];
+
+var strictKeywords = {
+    __proto__: null,
+    "implements": true,
+    "interface": true,
+    "let": true,
+    //"module": true,
+    "package": true,
+    "private": true,
+    "protected": true,
+    "public": true,
+    "static": true,
+    "use": true,
+    "yield": true
+};
 
-    function defineGetterSetter(obj, prop, getter, setter, dontDelete, dontEnum) {
-        Object.defineProperty(obj, prop, {
-            get: getter,
-            set: setter,
-            configurable: !dontDelete,
-            enumerable: !dontEnum
-        });
-    }
+var statementStartTokens = [
+    "break",
+    "const", "continue",
+    "debugger", "do",
+    "for",
+    "if",
+    "let",
+    "return",
+    "switch",
+    "throw", "try",
+    "var",
+    "yield",
+    "while", "with",
+];
+
+// Whitespace characters (see ECMA-262 7.2)
+var whitespaceChars = [
+    // normal whitespace:
+    "\u0009", "\u000B", "\u000C", "\u0020", "\u00A0", "\uFEFF",
+
+    // high-Unicode whitespace:
+    "\u1680", "\u180E",
+    "\u2000", "\u2001", "\u2002", "\u2003", "\u2004", "\u2005", "\u2006",
+    "\u2007", "\u2008", "\u2009", "\u200A",
+    "\u202F", "\u205F", "\u3000"
+];
+
+var whitespace = {};
+for (var i = 0; i < whitespaceChars.length; i++) {
+    whitespace[whitespaceChars[i]] = true;
+}
 
-    function defineMemoGetter(obj, prop, fn, dontDelete, dontEnum) {
-        Object.defineProperty(obj, prop, {
-            get: function() {
-                var val = fn();
-                defineProperty(obj, prop, val, dontDelete, true, dontEnum);
-                return val;
-            },
-            configurable: true,
-            enumerable: !dontEnum
-        });
-    }
+// Operator and punctuator mapping from token to tree node type name.
+// NB: because the lexer doesn't backtrack, all token prefixes must themselves
+// be valid tokens (e.g. !== is acceptable because its prefixes are the valid
+// tokens != and !).
+var opTypeNames = {
+    '\n':   "NEWLINE",
+    ';':    "SEMICOLON",
+    ',':    "COMMA",
+    '?':    "HOOK",
+    ':':    "COLON",
+    '||':   "OR",
+    '&&':   "AND",
+    '|':    "BITWISE_OR",
+    '^':    "BITWISE_XOR",
+    '&':    "BITWISE_AND",
+    '===':  "STRICT_EQ",
+    '==':   "EQ",
+    '=':    "ASSIGN",
+    '!==':  "STRICT_NE",
+    '!=':   "NE",
+    '<<':   "LSH",
+    '<=':   "LE",
+    '<':    "LT",
+    '>>>':  "URSH",
+    '>>':   "RSH",
+    '>=':   "GE",
+    '>':    "GT",
+    '++':   "INCREMENT",
+    '--':   "DECREMENT",
+    '+':    "PLUS",
+    '-':    "MINUS",
+    '*':    "MUL",
+    '/':    "DIV",
+    '%':    "MOD",
+    '!':    "NOT",
+    '~':    "BITWISE_NOT",
+    '.':    "DOT",
+    '[':    "LEFT_BRACKET",
+    ']':    "RIGHT_BRACKET",
+    '{':    "LEFT_CURLY",
+    '}':    "RIGHT_CURLY",
+    '(':    "LEFT_PAREN",
+    ')':    "RIGHT_PAREN"
+};
 
-    function defineProperty(obj, prop, val, dontDelete, readOnly, dontEnum) {
-        Object.defineProperty(obj, prop,
-                              { value: val, writable: !readOnly, configurable: !dontDelete,
-                                enumerable: !dontEnum });
-    }
+// Hash of keyword identifier to tokens index.  NB: we must null __proto__ to
+// avoid toString, etc. namespace pollution.
+var keywords = {__proto__: null};
+var mozillaKeywords = {__proto__: null};
 
-    // Returns true if fn is a native function.  (Note: SpiderMonkey specific.)
-    function isNativeCode(fn) {
-        // Relies on the toString method to identify native code.
-        return ((typeof fn) === "function") && fn.toString().match(/\[native code\]/);
-    }
+// Define const END, etc., based on the token names.  Also map name to index.
+var tokenIds = {};
 
-    function getPropertyDescriptor(obj, name) {
-        while (obj) {
-            if (({}).hasOwnProperty.call(obj, name))
-                return Object.getOwnPropertyDescriptor(obj, name);
-            obj = Object.getPrototypeOf(obj);
-        }
+var hostSupportsEvalConst = (function() {
+    try {
+        return eval("(function(s) { eval(s); return x })('const x = true;')");
+    } catch (e) {
+        return false;
     }
-
-    function getPropertyNames(obj) {
-        var table = Object.create(null, {});
-        while (obj) {
-            var names = Object.getOwnPropertyNames(obj);
-            for (var i = 0, n = names.length; i < n; i++)
-                table[names[i]] = true;
-            obj = Object.getPrototypeOf(obj);
-        }
-        return Object.keys(table);
+})();
+
+// Building up a string to be eval'd in different contexts.
+var consts = hostSupportsEvalConst ? "const " : "var ";
+for (var i = 0, j = tokens.length; i < j; i++) {
+    if (i > 0)
+        consts += ", ";
+    var t = tokens[i];
+    var name;
+    if (/^[a-z]/.test(t)) {
+        name = t.toUpperCase();
+        if (name === "LET" || name === "YIELD")
+            mozillaKeywords[name] = i;
+        if (strictKeywords[name])
+            strictKeywords[name] = i;
+        keywords[t] = i;
+    } else {
+        name = (/^\W/.test(t) ? opTypeNames[t] : t);
     }
+    consts += name + " = " + i;
+    tokenIds[name] = i;
+    tokens[t] = i;
+}
+consts += ";";
 
-    function getOwnProperties(obj) {
-        var map = {};
-        for (var name in Object.getOwnPropertyNames(obj))
-            map[name] = Object.getOwnPropertyDescriptor(obj, name);
-        return map;
-    }
+var isStatementStartCode = {__proto__: null};
+for (i = 0, j = statementStartTokens.length; i < j; i++)
+    isStatementStartCode[keywords[statementStartTokens[i]]] = true;
 
-    function blacklistHandler(target, blacklist) {
-        var mask = Object.create(null, {});
-        var redirect = StringMap.create(blacklist).mapObject(function(name) { return mask; });
-        return mixinHandler(redirect, target);
-    }
+// Map assignment operators to their indexes in the tokens array.
+var assignOps = ['|', '^', '&', '<<', '>>', '>>>', '+', '-', '*', '/', '%'];
 
-    function whitelistHandler(target, whitelist) {
-        var catchall = Object.create(null, {});
-        var redirect = StringMap.create(whitelist).mapObject(function(name) { return target; });
-        return mixinHandler(redirect, catchall);
-    }
+for (i = 0, j = assignOps.length; i < j; i++) {
+    t = assignOps[i];
+    assignOps[t] = tokens[t];
+}
 
-    function mirrorHandler(target, writable) {
-        var handler = makePassthruHandler(target);
+function defineGetter(obj, prop, fn, dontDelete, dontEnum) {
+    Object.defineProperty(obj, prop,
+                          { get: fn, configurable: !dontDelete, enumerable: !dontEnum });
+}
 
-        var defineProperty = handler.defineProperty;
-        handler.defineProperty = function(name, desc) {
-            if (!desc.enumerable)
-                throw new Error("mirror property must be enumerable");
-            if (!desc.configurable)
-                throw new Error("mirror property must be configurable");
-            if (desc.writable !== writable)
-                throw new Error("mirror property must " + (writable ? "" : "not ") + "be writable");
-            defineProperty(name, desc);
-        };
+function defineGetterSetter(obj, prop, getter, setter, dontDelete, dontEnum) {
+    Object.defineProperty(obj, prop, {
+        get: getter,
+        set: setter,
+        configurable: !dontDelete,
+        enumerable: !dontEnum
+    });
+}
 
-        handler.fix = function() { };
-        handler.getOwnPropertyDescriptor = handler.getPropertyDescriptor;
-        handler.getOwnPropertyNames = getPropertyNames.bind(handler, target);
-        handler.keys = handler.enumerate;
-        handler["delete"] = function() { return false; };
-        handler.hasOwn = handler.has;
-        return handler;
-    }
+function defineMemoGetter(obj, prop, fn, dontDelete, dontEnum) {
+    Object.defineProperty(obj, prop, {
+        get: function() {
+            var val = fn();
+            defineProperty(obj, prop, val, dontDelete, true, dontEnum);
+            return val;
+        },
+        configurable: true,
+        enumerable: !dontEnum
+    });
+}
 
-    /*
-     * Mixin proxies break the single-inheritance model of prototypes, so
-     * the handler treats all properties as own-properties:
-     *
-     *                  X
-     *                  |
-     *     +------------+------------+
-     *     |                 O       |
-     *     |                 |       |
-     *     |  O         O    O       |
-     *     |  |         |    |       |
-     *     |  O    O    O    O       |
-     *     |  |    |    |    |       |
-     *     |  O    O    O    O    O  |
-     *     |  |    |    |    |    |  |
-     *     +-(*)--(w)--(x)--(y)--(z)-+
-     */
+function defineProperty(obj, prop, val, dontDelete, readOnly, dontEnum) {
+    Object.defineProperty(obj, prop,
+                          { value: val, writable: !readOnly, configurable: !dontDelete,
+                            enumerable: !dontEnum });
+}
 
-    function mixinHandler(redirect, catchall) {
-        function targetFor(name) {
-            return hasOwn(redirect, name) ? redirect[name] : catchall;
-        }
+// Returns true if fn is a native function.  (Note: SpiderMonkey specific.)
+function isNativeCode(fn) {
+    // Relies on the toString method to identify native code.
+    return ((typeof fn) === "function") && fn.toString().match(/\[native code\]/);
+}
 
-        function getMuxPropertyDescriptor(name) {
-            var desc = getPropertyDescriptor(targetFor(name), name);
-            if (desc)
-                desc.configurable = true;
-            return desc;
-        }
+var Fpapply = Function.prototype.apply;
 
-        function getMuxPropertyNames() {
-            var names1 = Object.getOwnPropertyNames(redirect).filter(function(name) {
-                return name in redirect[name];
-            });
-            var names2 = getPropertyNames(catchall).filter(function(name) {
-                return !hasOwn(redirect, name);
-            });
-            return names1.concat(names2);
-        }
+function apply(f, o, a) {
+    return Fpapply.call(f, [o].concat(a));
+}
 
-        function enumerateMux() {
-            var result = Object.getOwnPropertyNames(redirect).filter(function(name) {
-                return name in redirect[name];
-            });
-            for (name in catchall) {
-                if (!hasOwn(redirect, name))
-                    result.push(name);
-            };
-            return result;
-        }
+var applyNew;
 
-        function hasMux(name) {
-            return name in targetFor(name);
+// ES5's bind is a simpler way to implement applyNew
+if (Function.prototype.bind) {
+    applyNew = function applyNew(f, a) {
+        return new (f.bind.apply(f, [,].concat(Array.prototype.slice.call(a))))();
+    };
+} else {
+    applyNew = function applyNew(f, a) {
+        switch (a.length) {
+          case 0:
+            return new f();
+          case 1:
+            return new f(a[0]);
+          case 2:
+            return new f(a[0], a[1]);
+          case 3:
+            return new f(a[0], a[1], a[2]);
+          default:
+            var argStr = "a[0]";
+            for (var i = 1, n = a.length; i < n; i++)
+                argStr += ",a[" + i + "]";
+            return eval("new f(" + argStr + ")");
         }
+    };
+}
 
-        return {
-            getOwnPropertyDescriptor: getMuxPropertyDescriptor,
-            getPropertyDescriptor: getMuxPropertyDescriptor,
-            getOwnPropertyNames: getMuxPropertyNames,
-            defineProperty: function(name, desc) {
-                Object.defineProperty(targetFor(name), name, desc);
-            },
-            "delete": function(name) {
-                var target = targetFor(name);
-                return delete target[name];
-            },
-            // FIXME: ha ha ha
-            fix: function() { },
-            has: hasMux,
-            hasOwn: hasMux,
-            get: function(receiver, name) {
-                var target = targetFor(name);
-                return target[name];
-            },
-            set: function(receiver, name, val) {
-                var target = targetFor(name);
-                target[name] = val;
-                return true;
-            },
-            enumerate: enumerateMux,
-            keys: enumerateMux
-        };
+function getPropertyDescriptor(obj, name) {
+    while (obj) {
+        if (({}).hasOwnProperty.call(obj, name))
+            return Object.getOwnPropertyDescriptor(obj, name);
+        obj = Object.getPrototypeOf(obj);
     }
+}
 
-    function makePassthruHandler(obj) {
-        // Handler copied from
-        // http://wiki.ecmascript.org/doku.php?id=harmony:proxies&s=proxy%20object#examplea_no-op_forwarding_proxy
-        return {
-            getOwnPropertyDescriptor: function(name) {
-                var desc = Object.getOwnPropertyDescriptor(obj, name);
+function getPropertyNames(obj) {
+    var table = Object.create(null, {});
+    while (obj) {
+        var names = Object.getOwnPropertyNames(obj);
+        for (var i = 0, n = names.length; i < n; i++)
+            table[names[i]] = true;
+        obj = Object.getPrototypeOf(obj);
+    }
+    return Object.keys(table);
+}
 
-                // a trapping proxy's properties must always be configurable
-                desc.configurable = true;
-                return desc;
-            },
-            getPropertyDescriptor: function(name) {
-                var desc = getPropertyDescriptor(obj, name);
+function getOwnProperties(obj) {
+    var map = {};
+    for (var name in Object.getOwnPropertyNames(obj))
+        map[name] = Object.getOwnPropertyDescriptor(obj, name);
+    return map;
+}
 
-                // a trapping proxy's properties must always be configurable
-                desc.configurable = true;
-                return desc;
-            },
-            getOwnPropertyNames: function() {
-                return Object.getOwnPropertyNames(obj);
-            },
-            defineProperty: function(name, desc) {
-                Object.defineProperty(obj, name, desc);
-            },
-            "delete": function(name) { return delete obj[name]; },
-            fix: function() {
-                if (Object.isFrozen(obj)) {
-                    return getOwnProperties(obj);
-                }
+function blacklistHandler(target, blacklist) {
+    var mask = Object.create(null, {});
+    var redirect = Dict.create(blacklist).mapObject(function(name) { return mask; });
+    return mixinHandler(redirect, target);
+}
 
-                // As long as obj is not frozen, the proxy won't allow itself to be fixed.
-                return undefined; // will cause a TypeError to be thrown
-            },
+function whitelistHandler(target, whitelist) {
+    var catchall = Object.create(null, {});
+    var redirect = Dict.create(whitelist).mapObject(function(name) { return target; });
+    return mixinHandler(redirect, catchall);
+}
 
-            has: function(name) { return name in obj; },
-            hasOwn: function(name) { return ({}).hasOwnProperty.call(obj, name); },
-            get: function(receiver, name) { return obj[name]; },
+/*
+ * Mixin proxies break the single-inheritance model of prototypes, so
+ * the handler treats all properties as own-properties:
+ *
+ *                  X
+ *                  |
+ *     +------------+------------+
+ *     |                 O       |
+ *     |                 |       |
+ *     |  O         O    O       |
+ *     |  |         |    |       |
+ *     |  O    O    O    O       |
+ *     |  |    |    |    |       |
+ *     |  O    O    O    O    O  |
+ *     |  |    |    |    |    |  |
+ *     +-(*)--(w)--(x)--(y)--(z)-+
+ */
 
-            // bad behavior when set fails in non-strict mode
-            set: function(receiver, name, val) { obj[name] = val; return true; },
-            enumerate: function() {
-                var result = [];
-                for (name in obj) { result.push(name); };
-                return result;
-            },
-            keys: function() { return Object.keys(obj); }
-        };
+function mixinHandler(redirect, catchall) {
+    function targetFor(name) {
+        return hasOwn(redirect, name) ? redirect[name] : catchall;
     }
 
-    var hasOwnProperty = ({}).hasOwnProperty;
+    function getMuxPropertyDescriptor(name) {
+        var desc = getPropertyDescriptor(targetFor(name), name);
+        if (desc)
+            desc.configurable = true;
+        return desc;
+    }
 
-    function hasOwn(obj, name) {
-        return hasOwnProperty.call(obj, name);
+    function getMuxPropertyNames() {
+        var names1 = Object.getOwnPropertyNames(redirect).filter(function(name) {
+            return name in redirect[name];
+        });
+        var names2 = getPropertyNames(catchall).filter(function(name) {
+            return !hasOwn(redirect, name);
+        });
+        return names1.concat(names2);
     }
 
-    function StringMap(table, size) {
-        this.table = table || Object.create(null, {});
-        this.size = size || 0;
+    function enumerateMux() {
+        var result = Object.getOwnPropertyNames(redirect).filter(function(name) {
+            return name in redirect[name];
+        });
+        for (name in catchall) {
+            if (!hasOwn(redirect, name))
+                result.push(name);
+        };
+        return result;
     }
 
-    StringMap.create = function(table) {
-        var init = Object.create(null, {});
-        var size = 0;
-        var names = Object.getOwnPropertyNames(table);
-        for (var i = 0, n = names.length; i < n; i++) {
-            var name = names[i];
-            init[name] = table[name];
-            size++;
-        }
-        return new StringMap(init, size);
-    };
+    function hasMux(name) {
+        return name in targetFor(name);
+    }
 
-    StringMap.prototype = {
-        has: function(x) { return hasOwnProperty.call(this.table, x); },
-        set: function(x, v) {
-            if (!hasOwnProperty.call(this.table, x))
-                this.size++;
-            this.table[x] = v;
+    return {
+        getOwnPropertyDescriptor: getMuxPropertyDescriptor,
+        getPropertyDescriptor: getMuxPropertyDescriptor,
+        getOwnPropertyNames: getMuxPropertyNames,
+        defineProperty: function(name, desc) {
+            Object.defineProperty(targetFor(name), name, desc);
         },
-        get: function(x) { return this.table[x]; },
-        getDef: function(x, thunk) {
-            if (!hasOwnProperty.call(this.table, x)) {
-                this.size++;
-                this.table[x] = thunk();
-            }
-            return this.table[x];
+        "delete": function(name) {
+            var target = targetFor(name);
+            return delete target[name];
         },
-        forEach: function(f) {
-            var table = this.table;
-            for (var key in table)
-                f.call(this, key, table[key]);
+        // FIXME: ha ha ha
+        fix: function() { },
+        has: hasMux,
+        hasOwn: hasMux,
+        get: function(receiver, name) {
+            var target = targetFor(name);
+            return target[name];
         },
-        map: function(f) {
-            var table1 = this.table;
-            var table2 = Object.create(null, {});
-            this.forEach(function(key, val) {
-                table2[key] = f.call(this, val, key);
-            });
-            return new StringMap(table2, this.size);
+        set: function(receiver, name, val) {
+            var target = targetFor(name);
+            target[name] = val;
+            return true;
         },
-        mapObject: function(f) {
-            var table1 = this.table;
-            var table2 = Object.create(null, {});
-            this.forEach(function(key, val) {
-                table2[key] = f.call(this, val, key);
-            });
-            return table2;
+        enumerate: enumerateMux,
+        keys: enumerateMux
+    };
+}
+
+function makePassthruHandler(obj) {
+    // Handler copied from
+    // http://wiki.ecmascript.org/doku.php?id=harmony:proxies&s=proxy%20object#examplea_no-op_forwarding_proxy
+    return {
+        getOwnPropertyDescriptor: function(name) {
+            var desc = Object.getOwnPropertyDescriptor(obj, name);
+
+            // a trapping proxy's properties must always be configurable
+            desc.configurable = true;
+            return desc;
+        },
+        getPropertyDescriptor: function(name) {
+            var desc = getPropertyDescriptor(obj, name);
+
+            // a trapping proxy's properties must always be configurable
+            desc.configurable = true;
+            return desc;
         },
-        toObject: function() {
-            return this.mapObject(function(val) { return val; });
+        getOwnPropertyNames: function() {
+            return Object.getOwnPropertyNames(obj);
         },
-        choose: function() {
-            return Object.getOwnPropertyNames(this.table)[0];
+        defineProperty: function(name, desc) {
+            Object.defineProperty(obj, name, desc);
         },
-        remove: function(x) {
-            if (hasOwnProperty.call(this.table, x)) {
-                this.size--;
-                delete this.table[x];
+        "delete": function(name) { return delete obj[name]; },
+        fix: function() {
+            if (Object.isFrozen(obj)) {
+                return getOwnProperties(obj);
             }
+
+            // As long as obj is not frozen, the proxy won't allow itself to be fixed.
+            return undefined; // will cause a TypeError to be thrown
         },
-        copy: function() {
-            var table = Object.create(null, {});
-            for (var key in this.table)
-                table[key] = this.table[key];
-            return new StringMap(table, this.size);
+
+        has: function(name) { return name in obj; },
+        hasOwn: function(name) { return ({}).hasOwnProperty.call(obj, name); },
+        get: function(receiver, name) { return obj[name]; },
+
+        // bad behavior when set fails in non-strict mode
+        set: function(receiver, name, val) { obj[name] = val; return true; },
+        enumerate: function() {
+            var result = [];
+            for (name in obj) { result.push(name); };
+            return result;
         },
-        toString: function() { return "[object StringMap]" }
+        keys: function() { return Object.keys(obj); }
     };
+}
+
+var hasOwnProperty = ({}).hasOwnProperty;
+
+function hasOwn(obj, name) {
+    return hasOwnProperty.call(obj, name);
+}
+
+function Dict(table, size) {
+    this.table = table || Object.create(null, {});
+    this.size = size || 0;
+}
+
+Dict.create = function(table) {
+    var init = Object.create(null, {});
+    var size = 0;
+    var names = Object.getOwnPropertyNames(table);
+    for (var i = 0, n = names.length; i < n; i++) {
+        var name = names[i];
+        init[name] = table[name];
+        size++;
+    }
+    return new Dict(init, size);
+};
+
+Dict.prototype = {
+    has: function(x) { return hasOwnProperty.call(this.table, x); },
+    set: function(x, v) {
+        if (!hasOwnProperty.call(this.table, x))
+            this.size++;
+        this.table[x] = v;
+    },
+    get: function(x) { return this.table[x]; },
+    getDef: function(x, thunk) {
+        if (!hasOwnProperty.call(this.table, x)) {
+            this.size++;
+            this.table[x] = thunk();
+        }
+        return this.table[x];
+    },
+    forEach: function(f) {
+        var table = this.table;
+        for (var key in table)
+            f.call(this, key, table[key]);
+    },
+    map: function(f) {
+        var table1 = this.table;
+        var table2 = Object.create(null, {});
+        this.forEach(function(key, val) {
+            table2[key] = f.call(this, val, key);
+        });
+        return new Dict(table2, this.size);
+    },
+    mapObject: function(f) {
+        var table1 = this.table;
+        var table2 = Object.create(null, {});
+        this.forEach(function(key, val) {
+            table2[key] = f.call(this, val, key);
+        });
+        return table2;
+    },
+    toObject: function() {
+        return this.mapObject(function(val) { return val; });
+    },
+    choose: function() {
+        return Object.getOwnPropertyNames(this.table)[0];
+    },
+    remove: function(x) {
+        if (hasOwnProperty.call(this.table, x)) {
+            this.size--;
+            delete this.table[x];
+        }
+    },
+    copy: function() {
+        var table = Object.create(null, {});
+        for (var key in this.table)
+            table[key] = this.table[key];
+        return new Dict(table, this.size);
+    },
+    keys: function() {
+        return Object.keys(this.table);
+    },
+    toString: function() { return "[object Dict]" }
+};
 
-    // an object-key table with poor asymptotics (replace with WeakMap when possible)
-    function ObjectMap(array) {
+var _WeakMap = typeof WeakMap === "function" ? WeakMap : (function() {
+    // shim for ES6 WeakMap with poor asymptotics
+    function WeakMap(array) {
         this.array = array || [];
     }
 
@@ -9637,7 +10448,7 @@ define('ace/narcissus/jsdefs', ['require', 'exports', 'module' ], function(requi
         return notFound();
     }
 
-    ObjectMap.prototype = {
+    WeakMap.prototype = {
         has: function(x) {
             return searchMap(this, x, function() { return true }, function() { return false });
         },
@@ -9652,101 +10463,152 @@ define('ace/narcissus/jsdefs', ['require', 'exports', 'module' ], function(requi
                              function(pair) { return pair.value },
                              function() { return null });
         },
-        getDef: function(x, thunk) {
-            var a = this.array;
-            return searchMap(this, x,
-                             function(pair) { return pair.value },
-                             function() {
-                                 var v = thunk();
-                                 a.push({ key: x, value: v });
-                                 return v;
-                             });
-        },
-        forEach: function(f) {
-            var a = this.array;
-            for (var i = 0, n = a.length; i < n; i++) {
-                var pair = a[i];
-                f.call(this, pair.key, pair.value);
-            }
-        },
-        choose: function() {
-            return this.array[0].key;
-        },
-        get size() {
-            return this.array.length;
-        },
-        remove: function(x) {
+        "delete": function(x) {
             var a = this.array;
             searchMap(this, x,
                       function(pair, i) { a.splice(i, 1) },
                       function() { });
         },
-        copy: function() {
-            return new ObjectMap(this.array.map(function(pair) {
-                return { key: pair.key, value: pair.value }
-            }));
-        },
-        clear: function() {
-            this.array = [];
-        },
-        toString: function() { return "[object ObjectMap]" }
+        toString: function() { return "[object WeakMap]" }
     };
 
-    // non-destructive stack
-    function Stack(elts) {
-        this.elts = elts || null;
-    }
+    return WeakMap;
+})();
 
-    Stack.prototype = {
-        push: function(x) {
-            return new Stack({ top: x, rest: this.elts });
-        },
-        top: function() {
-            if (!this.elts)
-                throw new Error("empty stack");
-            return this.elts.top;
-        },
-        isEmpty: function() {
-            return this.top === null;
-        },
-        find: function(test) {
-            for (var elts = this.elts; elts; elts = elts.rest) {
-                if (test(elts.top))
-                    return elts.top;
-            }
-            return null;
-        },
-        has: function(x) {
-            return Boolean(this.find(function(elt) { return elt === x }));
-        },
-        forEach: function(f) {
-            for (var elts = this.elts; elts; elts = elts.rest) {
-                f(elts.top);
-            }
+// non-destructive stack
+function Stack(elts) {
+    this.elts = elts || null;
+}
+
+Stack.prototype = {
+    push: function(x) {
+        return new Stack({ top: x, rest: this.elts });
+    },
+    top: function() {
+        if (!this.elts)
+            throw new Error("empty stack");
+        return this.elts.top;
+    },
+    isEmpty: function() {
+        return this.top === null;
+    },
+    find: function(test) {
+        for (var elts = this.elts; elts; elts = elts.rest) {
+            if (test(elts.top))
+                return elts.top;
+        }
+        return null;
+    },
+    has: function(x) {
+        return Boolean(this.find(function(elt) { return elt === x }));
+    },
+    forEach: function(f) {
+        for (var elts = this.elts; elts; elts = elts.rest) {
+            f(elts.top);
         }
-    };
+    }
+};
+
+if (!Array.prototype.copy) {
+    defineProperty(Array.prototype, "copy",
+                   function() {
+                       var result = [];
+                       for (var i = 0, n = this.length; i < n; i++)
+                           result[i] = this[i];
+                       return result;
+                   }, false, false, true);
+}
+
+if (!Array.prototype.top) {
+    defineProperty(Array.prototype, "top",
+                   function() {
+                       return this.length && this[this.length-1];
+                   }, false, false, true);
+}
+
+exports.tokens = tokens;
+exports.whitespace = whitespace;
+exports.opTypeNames = opTypeNames;
+exports.keywords = keywords;
+exports.mozillaKeywords = mozillaKeywords;
+exports.strictKeywords = strictKeywords;
+exports.isStatementStartCode = isStatementStartCode;
+exports.tokenIds = tokenIds;
+exports.consts = consts;
+exports.assignOps = assignOps;
+exports.defineGetter = defineGetter;
+exports.defineGetterSetter = defineGetterSetter;
+exports.defineMemoGetter = defineMemoGetter;
+exports.defineProperty = defineProperty;
+exports.isNativeCode = isNativeCode;
+exports.apply = apply;
+exports.applyNew = applyNew;
+exports.mixinHandler = mixinHandler;
+exports.whitelistHandler = whitelistHandler;
+exports.blacklistHandler = blacklistHandler;
+exports.makePassthruHandler = makePassthruHandler;
+exports.Dict = Dict;
+exports.WeakMap = _WeakMap;
+exports.Stack = Stack;
+
+});/* vim: set sw=4 ts=4 et tw=78: */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Narcissus JavaScript engine.
+ *
+ * The Initial Developer of the Original Code is
+ * Brendan Eich <brendan@mozilla.org>.
+ * Portions created by the Initial Developer are Copyright (C) 2004
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Tom Austin <taustin@ucsc.edu>
+ *   Brendan Eich <brendan@mozilla.org>
+ *   Shu-Yu Guo <shu@rfrn.org>
+ *   Dave Herman <dherman@mozilla.com>
+ *   Dimitris Vardoulakis <dimvar@ccs.neu.edu>
+ *   Patrick Walton <pcwalton@mozilla.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+define('ace/narcissus/options', ['require', 'exports', 'module' ], function(require, exports, module) {
+
+// Global variables to hide from the interpreter
+exports.hiddenHostGlobals = { Narcissus: true };
+
+// Desugar SpiderMonkey language extensions?
+exports.desugarExtensions = false;
+
+// Allow HTML comments?
+exports.allowHTMLComments = false;
+
+// Allow non-standard Mozilla extensions?
+exports.mozillaMode = true;
+
+// Allow experimental paren-free mode?
+exports.parenFreeMode = false;
 
-    module.exports = {
-        tokens: tokens,
-        whitespace: whitespace,
-        opTypeNames: opTypeNames,
-        keywords: keywords,
-        isStatementStartCode: isStatementStartCode,
-        tokenIds: tokenIds,
-        consts: consts,
-        assignOps: assignOps,
-        defineGetter: defineGetter,
-        defineGetterSetter: defineGetterSetter,
-        defineMemoGetter: defineMemoGetter,
-        defineProperty: defineProperty,
-        isNativeCode: isNativeCode,
-        mirrorHandler: mirrorHandler,
-        mixinHandler: mixinHandler,
-        whitelistHandler: whitelistHandler,
-        blacklistHandler: blacklistHandler,
-        makePassthruHandler: makePassthruHandler,
-        StringMap: StringMap,
-        ObjectMap: ObjectMap,
-        Stack: Stack
-    };
 });
\ No newline at end of file
diff --git a/apps/files_texteditor/js/aceeditor/worker-json.js b/apps/files_texteditor/js/aceeditor/worker-json.js
new file mode 100644
index 0000000000000000000000000000000000000000..80757ef64b1a59047bc9240284960d804bccd469
--- /dev/null
+++ b/apps/files_texteditor/js/aceeditor/worker-json.js
@@ -0,0 +1,3083 @@
+"no use strict";
+
+var console = {
+    log: function(msg) {
+        postMessage({type: "log", data: msg});
+    }
+};
+var window = {
+    console: console
+};
+
+var normalizeModule = function(parentId, moduleName) {
+    // normalize plugin requires
+    if (moduleName.indexOf("!") !== -1) {
+        var chunks = moduleName.split("!");
+        return normalizeModule(parentId, chunks[0]) + "!" + normalizeModule(parentId, chunks[1]);
+    }
+    // normalize relative requires
+    if (moduleName.charAt(0) == ".") {
+        var base = parentId.split("/").slice(0, -1).join("/");
+        var moduleName = base + "/" + moduleName;
+        
+        while(moduleName.indexOf(".") !== -1 && previous != moduleName) {
+            var previous = moduleName;
+            var moduleName = moduleName.replace(/\/\.\//, "/").replace(/[^\/]+\/\.\.\//, "");
+        }
+    }
+    
+    return moduleName;
+};
+
+var require = function(parentId, id) {
+    var id = normalizeModule(parentId, id);
+    
+    var module = require.modules[id];
+    if (module) {
+        if (!module.initialized) {
+            module.exports = module.factory().exports;
+            module.initialized = true;
+        }
+        return module.exports;
+    }
+    
+    var chunks = id.split("/");
+    chunks[0] = require.tlns[chunks[0]] || chunks[0];
+    var path = chunks.join("/") + ".js";
+    
+    require.id = id;
+    importScripts(path);
+    return require(parentId, id);    
+};
+
+require.modules = {};
+require.tlns = {};
+
+var define = function(id, deps, factory) {
+    if (arguments.length == 2) {
+        factory = deps;
+    } else if (arguments.length == 1) {
+        factory = id;
+        id = require.id;
+    }
+
+    if (id.indexOf("text!") === 0) 
+        return;
+    
+    var req = function(deps, factory) {
+        return require(id, deps, factory);
+    };
+
+    require.modules[id] = {
+        factory: function() {
+            var module = {
+                exports: {}
+            };
+            var returnExports = factory(req, module.exports, module);
+            if (returnExports)
+                module.exports = returnExports;
+            return module;
+        }
+    };
+};
+
+function initBaseUrls(topLevelNamespaces) {
+    require.tlns = topLevelNamespaces;
+}
+
+function initSender() {
+
+    var EventEmitter = require(null, "ace/lib/event_emitter").EventEmitter;
+    var oop = require(null, "ace/lib/oop");
+    
+    var Sender = function() {};
+    
+    (function() {
+        
+        oop.implement(this, EventEmitter);
+                
+        this.callback = function(data, callbackId) {
+            postMessage({
+                type: "call",
+                id: callbackId,
+                data: data
+            });
+        };
+    
+        this.emit = function(name, data) {
+            postMessage({
+                type: "event",
+                name: name,
+                data: data
+            });
+        };
+        
+    }).call(Sender.prototype);
+    
+    return new Sender();
+}
+
+var main;
+var sender;
+
+onmessage = function(e) {
+    var msg = e.data;
+    if (msg.command) {
+        main[msg.command].apply(main, msg.args);
+    }
+    else if (msg.init) {        
+        initBaseUrls(msg.tlns);
+        require(null, "ace/lib/fixoldbrowsers");
+        sender = initSender();
+        var clazz = require(null, msg.module)[msg.classname];
+        main = new clazz(sender);
+    } 
+    else if (msg.event && sender) {
+        sender._emit(msg.event, msg.data);
+    }
+};
+// vim:set ts=4 sts=4 sw=4 st:
+// -- kriskowal Kris Kowal Copyright (C) 2009-2010 MIT License
+// -- tlrobinson Tom Robinson Copyright (C) 2009-2010 MIT License (Narwhal Project)
+// -- dantman Daniel Friesen Copyright(C) 2010 XXX No License Specified
+// -- fschaefer Florian Schäfer Copyright (C) 2010 MIT License
+// -- Irakli Gozalishvili Copyright (C) 2010 MIT License
+
+/*!
+    Copyright (c) 2009, 280 North Inc. http://280north.com/
+    MIT License. http://github.com/280north/narwhal/blob/master/README.md
+*/
+
+define('ace/lib/fixoldbrowsers', ['require', 'exports', 'module' , 'ace/lib/regexp', 'ace/lib/es5-shim'], function(require, exports, module) {
+"use strict";
+
+require("./regexp");
+require("./es5-shim");
+
+});/**
+ *  Based on code from:
+ *
+ * XRegExp 1.5.0
+ * (c) 2007-2010 Steven Levithan
+ * MIT License
+ * <http://xregexp.com>
+ * Provides an augmented, extensible, cross-browser implementation of regular expressions,
+ * including support for additional syntax, flags, and methods
+ */
+ 
+define('ace/lib/regexp', ['require', 'exports', 'module' ], function(require, exports, module) {
+"use strict";
+
+    //---------------------------------
+    //  Private variables
+    //---------------------------------
+
+    var real = {
+            exec: RegExp.prototype.exec,
+            test: RegExp.prototype.test,
+            match: String.prototype.match,
+            replace: String.prototype.replace,
+            split: String.prototype.split
+        },
+        compliantExecNpcg = real.exec.call(/()??/, "")[1] === undefined, // check `exec` handling of nonparticipating capturing groups
+        compliantLastIndexIncrement = function () {
+            var x = /^/g;
+            real.test.call(x, "");
+            return !x.lastIndex;
+        }();
+
+    //---------------------------------
+    //  Overriden native methods
+    //---------------------------------
+
+    // Adds named capture support (with backreferences returned as `result.name`), and fixes two
+    // cross-browser issues per ES3:
+    // - Captured values for nonparticipating capturing groups should be returned as `undefined`,
+    //   rather than the empty string.
+    // - `lastIndex` should not be incremented after zero-length matches.
+    RegExp.prototype.exec = function (str) {
+        var match = real.exec.apply(this, arguments),
+            name, r2;
+        if ( typeof(str) == 'string' && match) {
+            // Fix browsers whose `exec` methods don't consistently return `undefined` for
+            // nonparticipating capturing groups
+            if (!compliantExecNpcg && match.length > 1 && indexOf(match, "") > -1) {
+                r2 = RegExp(this.source, real.replace.call(getNativeFlags(this), "g", ""));
+                // Using `str.slice(match.index)` rather than `match[0]` in case lookahead allowed
+                // matching due to characters outside the match
+                real.replace.call(str.slice(match.index), r2, function () {
+                    for (var i = 1; i < arguments.length - 2; i++) {
+                        if (arguments[i] === undefined)
+                            match[i] = undefined;
+                    }
+                });
+            }
+            // Attach named capture properties
+            if (this._xregexp && this._xregexp.captureNames) {
+                for (var i = 1; i < match.length; i++) {
+                    name = this._xregexp.captureNames[i - 1];
+                    if (name)
+                       match[name] = match[i];
+                }
+            }
+            // Fix browsers that increment `lastIndex` after zero-length matches
+            if (!compliantLastIndexIncrement && this.global && !match[0].length && (this.lastIndex > match.index))
+                this.lastIndex--;
+        }
+        return match;
+    };
+
+    // Don't override `test` if it won't change anything
+    if (!compliantLastIndexIncrement) {
+        // Fix browser bug in native method
+        RegExp.prototype.test = function (str) {
+            // Use the native `exec` to skip some processing overhead, even though the overriden
+            // `exec` would take care of the `lastIndex` fix
+            var match = real.exec.call(this, str);
+            // Fix browsers that increment `lastIndex` after zero-length matches
+            if (match && this.global && !match[0].length && (this.lastIndex > match.index))
+                this.lastIndex--;
+            return !!match;
+        };
+    }
+
+    //---------------------------------
+    //  Private helper functions
+    //---------------------------------
+
+    function getNativeFlags (regex) {
+        return (regex.global     ? "g" : "") +
+               (regex.ignoreCase ? "i" : "") +
+               (regex.multiline  ? "m" : "") +
+               (regex.extended   ? "x" : "") + // Proposed for ES4; included in AS3
+               (regex.sticky     ? "y" : "");
+    };
+
+    function indexOf (array, item, from) {
+        if (Array.prototype.indexOf) // Use the native array method if available
+            return array.indexOf(item, from);
+        for (var i = from || 0; i < array.length; i++) {
+            if (array[i] === item)
+                return i;
+        }
+        return -1;
+    };
+
+});
+// vim: ts=4 sts=4 sw=4 expandtab
+// -- kriskowal Kris Kowal Copyright (C) 2009-2011 MIT License
+// -- tlrobinson Tom Robinson Copyright (C) 2009-2010 MIT License (Narwhal Project)
+// -- dantman Daniel Friesen Copyright (C) 2010 XXX TODO License or CLA
+// -- fschaefer Florian Schäfer Copyright (C) 2010 MIT License
+// -- Gozala Irakli Gozalishvili Copyright (C) 2010 MIT License
+// -- kitcambridge Kit Cambridge Copyright (C) 2011 MIT License
+// -- kossnocorp Sasha Koss XXX TODO License or CLA
+// -- bryanforbes Bryan Forbes XXX TODO License or CLA
+// -- killdream Quildreen Motta Copyright (C) 2011 MIT Licence
+// -- michaelficarra Michael Ficarra Copyright (C) 2011 3-clause BSD License
+// -- sharkbrainguy Gerard Paapu Copyright (C) 2011 MIT License
+// -- bbqsrc Brendan Molloy (C) 2011 Creative Commons Zero (public domain)
+// -- iwyg XXX TODO License or CLA
+// -- DomenicDenicola Domenic Denicola Copyright (C) 2011 MIT License
+// -- xavierm02 Montillet Xavier XXX TODO License or CLA
+// -- Raynos Raynos XXX TODO License or CLA
+// -- samsonjs Sami Samhuri Copyright (C) 2010 MIT License
+// -- rwldrn Rick Waldron Copyright (C) 2011 MIT License
+// -- lexer Alexey Zakharov XXX TODO License or CLA
+
+/*!
+    Copyright (c) 2009, 280 North Inc. http://280north.com/
+    MIT License. http://github.com/280north/narwhal/blob/master/README.md
+*/
+
+define('ace/lib/es5-shim', ['require', 'exports', 'module' ], function(require, exports, module) {
+
+/**
+ * Brings an environment as close to ECMAScript 5 compliance
+ * as is possible with the facilities of erstwhile engines.
+ *
+ * Annotated ES5: http://es5.github.com/ (specific links below)
+ * ES5 Spec: http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf
+ *
+ * @module
+ */
+
+/*whatsupdoc*/
+
+//
+// Function
+// ========
+//
+
+// ES-5 15.3.4.5
+// http://es5.github.com/#x15.3.4.5
+
+if (!Function.prototype.bind) {
+    Function.prototype.bind = function bind(that) { // .length is 1
+        // 1. Let Target be the this value.
+        var target = this;
+        // 2. If IsCallable(Target) is false, throw a TypeError exception.
+        if (typeof target != "function")
+            throw new TypeError(); // TODO message
+        // 3. Let A be a new (possibly empty) internal list of all of the
+        //   argument values provided after thisArg (arg1, arg2 etc), in order.
+        // XXX slicedArgs will stand in for "A" if used
+        var args = slice.call(arguments, 1); // for normal call
+        // 4. Let F be a new native ECMAScript object.
+        // 11. Set the [[Prototype]] internal property of F to the standard
+        //   built-in Function prototype object as specified in 15.3.3.1.
+        // 12. Set the [[Call]] internal property of F as described in
+        //   15.3.4.5.1.
+        // 13. Set the [[Construct]] internal property of F as described in
+        //   15.3.4.5.2.
+        // 14. Set the [[HasInstance]] internal property of F as described in
+        //   15.3.4.5.3.
+        var bound = function () {
+
+            if (this instanceof bound) {
+                // 15.3.4.5.2 [[Construct]]
+                // When the [[Construct]] internal method of a function object,
+                // F that was created using the bind function is called with a
+                // list of arguments ExtraArgs, the following steps are taken:
+                // 1. Let target be the value of F's [[TargetFunction]]
+                //   internal property.
+                // 2. If target has no [[Construct]] internal method, a
+                //   TypeError exception is thrown.
+                // 3. Let boundArgs be the value of F's [[BoundArgs]] internal
+                //   property.
+                // 4. Let args be a new list containing the same values as the
+                //   list boundArgs in the same order followed by the same
+                //   values as the list ExtraArgs in the same order.
+                // 5. Return the result of calling the [[Construct]] internal 
+                //   method of target providing args as the arguments.
+
+                var F = function(){};
+                F.prototype = target.prototype;
+                var self = new F;
+
+                var result = target.apply(
+                    self,
+                    args.concat(slice.call(arguments))
+                );
+                if (result !== null && Object(result) === result)
+                    return result;
+                return self;
+
+            } else {
+                // 15.3.4.5.1 [[Call]]
+                // When the [[Call]] internal method of a function object, F,
+                // which was created using the bind function is called with a
+                // this value and a list of arguments ExtraArgs, the following
+                // steps are taken:
+                // 1. Let boundArgs be the value of F's [[BoundArgs]] internal
+                //   property.
+                // 2. Let boundThis be the value of F's [[BoundThis]] internal
+                //   property.
+                // 3. Let target be the value of F's [[TargetFunction]] internal
+                //   property.
+                // 4. Let args be a new list containing the same values as the 
+                //   list boundArgs in the same order followed by the same 
+                //   values as the list ExtraArgs in the same order.
+                // 5. Return the result of calling the [[Call]] internal method 
+                //   of target providing boundThis as the this value and 
+                //   providing args as the arguments.
+
+                // equiv: target.call(this, ...boundArgs, ...args)
+                return target.apply(
+                    that,
+                    args.concat(slice.call(arguments))
+                );
+
+            }
+
+        };
+        // XXX bound.length is never writable, so don't even try
+        //
+        // 15. If the [[Class]] internal property of Target is "Function", then
+        //     a. Let L be the length property of Target minus the length of A.
+        //     b. Set the length own property of F to either 0 or L, whichever is 
+        //       larger.
+        // 16. Else set the length own property of F to 0.
+        // 17. Set the attributes of the length own property of F to the values
+        //   specified in 15.3.5.1.
+
+        // TODO
+        // 18. Set the [[Extensible]] internal property of F to true.
+        
+        // TODO
+        // 19. Let thrower be the [[ThrowTypeError]] function Object (13.2.3).
+        // 20. Call the [[DefineOwnProperty]] internal method of F with 
+        //   arguments "caller", PropertyDescriptor {[[Get]]: thrower, [[Set]]:
+        //   thrower, [[Enumerable]]: false, [[Configurable]]: false}, and 
+        //   false.
+        // 21. Call the [[DefineOwnProperty]] internal method of F with 
+        //   arguments "arguments", PropertyDescriptor {[[Get]]: thrower, 
+        //   [[Set]]: thrower, [[Enumerable]]: false, [[Configurable]]: false},
+        //   and false.
+
+        // TODO
+        // NOTE Function objects created using Function.prototype.bind do not 
+        // have a prototype property or the [[Code]], [[FormalParameters]], and
+        // [[Scope]] internal properties.
+        // XXX can't delete prototype in pure-js.
+
+        // 22. Return F.
+        return bound;
+    };
+}
+
+// Shortcut to an often accessed properties, in order to avoid multiple
+// dereference that costs universally.
+// _Please note: Shortcuts are defined after `Function.prototype.bind` as we
+// us it in defining shortcuts.
+var call = Function.prototype.call;
+var prototypeOfArray = Array.prototype;
+var prototypeOfObject = Object.prototype;
+var slice = prototypeOfArray.slice;
+var toString = call.bind(prototypeOfObject.toString);
+var owns = call.bind(prototypeOfObject.hasOwnProperty);
+
+// If JS engine supports accessors creating shortcuts.
+var defineGetter;
+var defineSetter;
+var lookupGetter;
+var lookupSetter;
+var supportsAccessors;
+if ((supportsAccessors = owns(prototypeOfObject, "__defineGetter__"))) {
+    defineGetter = call.bind(prototypeOfObject.__defineGetter__);
+    defineSetter = call.bind(prototypeOfObject.__defineSetter__);
+    lookupGetter = call.bind(prototypeOfObject.__lookupGetter__);
+    lookupSetter = call.bind(prototypeOfObject.__lookupSetter__);
+}
+
+//
+// Array
+// =====
+//
+
+// ES5 15.4.3.2
+// http://es5.github.com/#x15.4.3.2
+// https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/isArray
+if (!Array.isArray) {
+    Array.isArray = function isArray(obj) {
+        return toString(obj) == "[object Array]";
+    };
+}
+
+// The IsCallable() check in the Array functions
+// has been replaced with a strict check on the
+// internal class of the object to trap cases where
+// the provided function was actually a regular
+// expression literal, which in V8 and
+// JavaScriptCore is a typeof "function".  Only in
+// V8 are regular expression literals permitted as
+// reduce parameters, so it is desirable in the
+// general case for the shim to match the more
+// strict and common behavior of rejecting regular
+// expressions.
+
+// ES5 15.4.4.18
+// http://es5.github.com/#x15.4.4.18
+// https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/array/forEach
+if (!Array.prototype.forEach) {
+    Array.prototype.forEach = function forEach(fun /*, thisp*/) {
+        var self = toObject(this),
+            thisp = arguments[1],
+            i = 0,
+            length = self.length >>> 0;
+
+        // If no callback function or if callback is not a callable function
+        if (toString(fun) != "[object Function]") {
+            throw new TypeError(); // TODO message
+        }
+
+        while (i < length) {
+            if (i in self) {
+                // Invoke the callback function with call, passing arguments:
+                // context, property value, property key, thisArg object context
+                fun.call(thisp, self[i], i, self);
+            }
+            i++;
+        }
+    };
+}
+
+// ES5 15.4.4.19
+// http://es5.github.com/#x15.4.4.19
+// https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/map
+if (!Array.prototype.map) {
+    Array.prototype.map = function map(fun /*, thisp*/) {
+        var self = toObject(this),
+            length = self.length >>> 0,
+            result = Array(length),
+            thisp = arguments[1];
+
+        // If no callback function or if callback is not a callable function
+        if (toString(fun) != "[object Function]") {
+            throw new TypeError(); // TODO message
+        }
+
+        for (var i = 0; i < length; i++) {
+            if (i in self)
+                result[i] = fun.call(thisp, self[i], i, self);
+        }
+        return result;
+    };
+}
+
+// ES5 15.4.4.20
+// http://es5.github.com/#x15.4.4.20
+// https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/filter
+if (!Array.prototype.filter) {
+    Array.prototype.filter = function filter(fun /*, thisp */) {
+        var self = toObject(this),
+            length = self.length >>> 0,
+            result = [],
+            thisp = arguments[1];
+
+        // If no callback function or if callback is not a callable function
+        if (toString(fun) != "[object Function]") {
+            throw new TypeError(); // TODO message
+        }
+
+        for (var i = 0; i < length; i++) {
+            if (i in self && fun.call(thisp, self[i], i, self))
+                result.push(self[i]);
+        }
+        return result;
+    };
+}
+
+// ES5 15.4.4.16
+// http://es5.github.com/#x15.4.4.16
+// https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/every
+if (!Array.prototype.every) {
+    Array.prototype.every = function every(fun /*, thisp */) {
+        var self = toObject(this),
+            length = self.length >>> 0,
+            thisp = arguments[1];
+
+        // If no callback function or if callback is not a callable function
+        if (toString(fun) != "[object Function]") {
+            throw new TypeError(); // TODO message
+        }
+
+        for (var i = 0; i < length; i++) {
+            if (i in self && !fun.call(thisp, self[i], i, self))
+                return false;
+        }
+        return true;
+    };
+}
+
+// ES5 15.4.4.17
+// http://es5.github.com/#x15.4.4.17
+// https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/some
+if (!Array.prototype.some) {
+    Array.prototype.some = function some(fun /*, thisp */) {
+        var self = toObject(this),
+            length = self.length >>> 0,
+            thisp = arguments[1];
+
+        // If no callback function or if callback is not a callable function
+        if (toString(fun) != "[object Function]") {
+            throw new TypeError(); // TODO message
+        }
+
+        for (var i = 0; i < length; i++) {
+            if (i in self && fun.call(thisp, self[i], i, self))
+                return true;
+        }
+        return false;
+    };
+}
+
+// ES5 15.4.4.21
+// http://es5.github.com/#x15.4.4.21
+// https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/reduce
+if (!Array.prototype.reduce) {
+    Array.prototype.reduce = function reduce(fun /*, initial*/) {
+        var self = toObject(this),
+            length = self.length >>> 0;
+
+        // If no callback function or if callback is not a callable function
+        if (toString(fun) != "[object Function]") {
+            throw new TypeError(); // TODO message
+        }
+
+        // no value to return if no initial value and an empty array
+        if (!length && arguments.length == 1)
+            throw new TypeError(); // TODO message
+
+        var i = 0;
+        var result;
+        if (arguments.length >= 2) {
+            result = arguments[1];
+        } else {
+            do {
+                if (i in self) {
+                    result = self[i++];
+                    break;
+                }
+
+                // if array contains no values, no initial value to return
+                if (++i >= length)
+                    throw new TypeError(); // TODO message
+            } while (true);
+        }
+
+        for (; i < length; i++) {
+            if (i in self)
+                result = fun.call(void 0, result, self[i], i, self);
+        }
+
+        return result;
+    };
+}
+
+// ES5 15.4.4.22
+// http://es5.github.com/#x15.4.4.22
+// https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/reduceRight
+if (!Array.prototype.reduceRight) {
+    Array.prototype.reduceRight = function reduceRight(fun /*, initial*/) {
+        var self = toObject(this),
+            length = self.length >>> 0;
+
+        // If no callback function or if callback is not a callable function
+        if (toString(fun) != "[object Function]") {
+            throw new TypeError(); // TODO message
+        }
+
+        // no value to return if no initial value, empty array
+        if (!length && arguments.length == 1)
+            throw new TypeError(); // TODO message
+
+        var result, i = length - 1;
+        if (arguments.length >= 2) {
+            result = arguments[1];
+        } else {
+            do {
+                if (i in self) {
+                    result = self[i--];
+                    break;
+                }
+
+                // if array contains no values, no initial value to return
+                if (--i < 0)
+                    throw new TypeError(); // TODO message
+            } while (true);
+        }
+
+        do {
+            if (i in this)
+                result = fun.call(void 0, result, self[i], i, self);
+        } while (i--);
+
+        return result;
+    };
+}
+
+// ES5 15.4.4.14
+// http://es5.github.com/#x15.4.4.14
+// https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/indexOf
+if (!Array.prototype.indexOf) {
+    Array.prototype.indexOf = function indexOf(sought /*, fromIndex */ ) {
+        var self = toObject(this),
+            length = self.length >>> 0;
+
+        if (!length)
+            return -1;
+
+        var i = 0;
+        if (arguments.length > 1)
+            i = toInteger(arguments[1]);
+
+        // handle negative indices
+        i = i >= 0 ? i : Math.max(0, length + i);
+        for (; i < length; i++) {
+            if (i in self && self[i] === sought) {
+                return i;
+            }
+        }
+        return -1;
+    };
+}
+
+// ES5 15.4.4.15
+// http://es5.github.com/#x15.4.4.15
+// https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/lastIndexOf
+if (!Array.prototype.lastIndexOf) {
+    Array.prototype.lastIndexOf = function lastIndexOf(sought /*, fromIndex */) {
+        var self = toObject(this),
+            length = self.length >>> 0;
+
+        if (!length)
+            return -1;
+        var i = length - 1;
+        if (arguments.length > 1)
+            i = Math.min(i, toInteger(arguments[1]));
+        // handle negative indices
+        i = i >= 0 ? i : length - Math.abs(i);
+        for (; i >= 0; i--) {
+            if (i in self && sought === self[i])
+                return i;
+        }
+        return -1;
+    };
+}
+
+//
+// Object
+// ======
+//
+
+// ES5 15.2.3.2
+// http://es5.github.com/#x15.2.3.2
+if (!Object.getPrototypeOf) {
+    // https://github.com/kriskowal/es5-shim/issues#issue/2
+    // http://ejohn.org/blog/objectgetprototypeof/
+    // recommended by fschaefer on github
+    Object.getPrototypeOf = function getPrototypeOf(object) {
+        return object.__proto__ || (
+            object.constructor ?
+            object.constructor.prototype :
+            prototypeOfObject
+        );
+    };
+}
+
+// ES5 15.2.3.3
+// http://es5.github.com/#x15.2.3.3
+if (!Object.getOwnPropertyDescriptor) {
+    var ERR_NON_OBJECT = "Object.getOwnPropertyDescriptor called on a " +
+                         "non-object: ";
+    Object.getOwnPropertyDescriptor = function getOwnPropertyDescriptor(object, property) {
+        if ((typeof object != "object" && typeof object != "function") || object === null)
+            throw new TypeError(ERR_NON_OBJECT + object);
+        // If object does not owns property return undefined immediately.
+        if (!owns(object, property))
+            return;
+
+        var descriptor, getter, setter;
+
+        // If object has a property then it's for sure both `enumerable` and
+        // `configurable`.
+        descriptor =  { enumerable: true, configurable: true };
+
+        // If JS engine supports accessor properties then property may be a
+        // getter or setter.
+        if (supportsAccessors) {
+            // Unfortunately `__lookupGetter__` will return a getter even
+            // if object has own non getter property along with a same named
+            // inherited getter. To avoid misbehavior we temporary remove
+            // `__proto__` so that `__lookupGetter__` will return getter only
+            // if it's owned by an object.
+            var prototype = object.__proto__;
+            object.__proto__ = prototypeOfObject;
+
+            var getter = lookupGetter(object, property);
+            var setter = lookupSetter(object, property);
+
+            // Once we have getter and setter we can put values back.
+            object.__proto__ = prototype;
+
+            if (getter || setter) {
+                if (getter) descriptor.get = getter;
+                if (setter) descriptor.set = setter;
+
+                // If it was accessor property we're done and return here
+                // in order to avoid adding `value` to the descriptor.
+                return descriptor;
+            }
+        }
+
+        // If we got this far we know that object has an own property that is
+        // not an accessor so we set it as a value and return descriptor.
+        descriptor.value = object[property];
+        return descriptor;
+    };
+}
+
+// ES5 15.2.3.4
+// http://es5.github.com/#x15.2.3.4
+if (!Object.getOwnPropertyNames) {
+    Object.getOwnPropertyNames = function getOwnPropertyNames(object) {
+        return Object.keys(object);
+    };
+}
+
+// ES5 15.2.3.5
+// http://es5.github.com/#x15.2.3.5
+if (!Object.create) {
+    Object.create = function create(prototype, properties) {
+        var object;
+        if (prototype === null) {
+            object = { "__proto__": null };
+        } else {
+            if (typeof prototype != "object")
+                throw new TypeError("typeof prototype["+(typeof prototype)+"] != 'object'");
+            var Type = function () {};
+            Type.prototype = prototype;
+            object = new Type();
+            // IE has no built-in implementation of `Object.getPrototypeOf`
+            // neither `__proto__`, but this manually setting `__proto__` will
+            // guarantee that `Object.getPrototypeOf` will work as expected with
+            // objects created using `Object.create`
+            object.__proto__ = prototype;
+        }
+        if (properties !== void 0)
+            Object.defineProperties(object, properties);
+        return object;
+    };
+}
+
+// ES5 15.2.3.6
+// http://es5.github.com/#x15.2.3.6
+
+// Patch for WebKit and IE8 standard mode
+// Designed by hax <hax.github.com>
+// related issue: https://github.com/kriskowal/es5-shim/issues#issue/5
+// IE8 Reference:
+//     http://msdn.microsoft.com/en-us/library/dd282900.aspx
+//     http://msdn.microsoft.com/en-us/library/dd229916.aspx
+// WebKit Bugs:
+//     https://bugs.webkit.org/show_bug.cgi?id=36423
+
+function doesDefinePropertyWork(object) {
+    try {
+        Object.defineProperty(object, "sentinel", {});
+        return "sentinel" in object;
+    } catch (exception) {
+        // returns falsy
+    }
+}
+
+// check whether defineProperty works if it's given. Otherwise,
+// shim partially.
+if (Object.defineProperty) {
+    var definePropertyWorksOnObject = doesDefinePropertyWork({});
+    var definePropertyWorksOnDom = typeof document == "undefined" ||
+        doesDefinePropertyWork(document.createElement("div"));
+    if (!definePropertyWorksOnObject || !definePropertyWorksOnDom) {
+        var definePropertyFallback = Object.defineProperty;
+    }
+}
+
+if (!Object.defineProperty || definePropertyFallback) {
+    var ERR_NON_OBJECT_DESCRIPTOR = "Property description must be an object: ";
+    var ERR_NON_OBJECT_TARGET = "Object.defineProperty called on non-object: "
+    var ERR_ACCESSORS_NOT_SUPPORTED = "getters & setters can not be defined " +
+                                      "on this javascript engine";
+
+    Object.defineProperty = function defineProperty(object, property, descriptor) {
+        if ((typeof object != "object" && typeof object != "function") || object === null)
+            throw new TypeError(ERR_NON_OBJECT_TARGET + object);
+        if ((typeof descriptor != "object" && typeof descriptor != "function") || descriptor === null)
+            throw new TypeError(ERR_NON_OBJECT_DESCRIPTOR + descriptor);
+
+        // make a valiant attempt to use the real defineProperty
+        // for I8's DOM elements.
+        if (definePropertyFallback) {
+            try {
+                return definePropertyFallback.call(Object, object, property, descriptor);
+            } catch (exception) {
+                // try the shim if the real one doesn't work
+            }
+        }
+
+        // If it's a data property.
+        if (owns(descriptor, "value")) {
+            // fail silently if "writable", "enumerable", or "configurable"
+            // are requested but not supported
+            /*
+            // alternate approach:
+            if ( // can't implement these features; allow false but not true
+                !(owns(descriptor, "writable") ? descriptor.writable : true) ||
+                !(owns(descriptor, "enumerable") ? descriptor.enumerable : true) ||
+                !(owns(descriptor, "configurable") ? descriptor.configurable : true)
+            )
+                throw new RangeError(
+                    "This implementation of Object.defineProperty does not " +
+                    "support configurable, enumerable, or writable."
+                );
+            */
+
+            if (supportsAccessors && (lookupGetter(object, property) ||
+                                      lookupSetter(object, property)))
+            {
+                // As accessors are supported only on engines implementing
+                // `__proto__` we can safely override `__proto__` while defining
+                // a property to make sure that we don't hit an inherited
+                // accessor.
+                var prototype = object.__proto__;
+                object.__proto__ = prototypeOfObject;
+                // Deleting a property anyway since getter / setter may be
+                // defined on object itself.
+                delete object[property];
+                object[property] = descriptor.value;
+                // Setting original `__proto__` back now.
+                object.__proto__ = prototype;
+            } else {
+                object[property] = descriptor.value;
+            }
+        } else {
+            if (!supportsAccessors)
+                throw new TypeError(ERR_ACCESSORS_NOT_SUPPORTED);
+            // If we got that far then getters and setters can be defined !!
+            if (owns(descriptor, "get"))
+                defineGetter(object, property, descriptor.get);
+            if (owns(descriptor, "set"))
+                defineSetter(object, property, descriptor.set);
+        }
+
+        return object;
+    };
+}
+
+// ES5 15.2.3.7
+// http://es5.github.com/#x15.2.3.7
+if (!Object.defineProperties) {
+    Object.defineProperties = function defineProperties(object, properties) {
+        for (var property in properties) {
+            if (owns(properties, property))
+                Object.defineProperty(object, property, properties[property]);
+        }
+        return object;
+    };
+}
+
+// ES5 15.2.3.8
+// http://es5.github.com/#x15.2.3.8
+if (!Object.seal) {
+    Object.seal = function seal(object) {
+        // this is misleading and breaks feature-detection, but
+        // allows "securable" code to "gracefully" degrade to working
+        // but insecure code.
+        return object;
+    };
+}
+
+// ES5 15.2.3.9
+// http://es5.github.com/#x15.2.3.9
+if (!Object.freeze) {
+    Object.freeze = function freeze(object) {
+        // this is misleading and breaks feature-detection, but
+        // allows "securable" code to "gracefully" degrade to working
+        // but insecure code.
+        return object;
+    };
+}
+
+// detect a Rhino bug and patch it
+try {
+    Object.freeze(function () {});
+} catch (exception) {
+    Object.freeze = (function freeze(freezeObject) {
+        return function freeze(object) {
+            if (typeof object == "function") {
+                return object;
+            } else {
+                return freezeObject(object);
+            }
+        };
+    })(Object.freeze);
+}
+
+// ES5 15.2.3.10
+// http://es5.github.com/#x15.2.3.10
+if (!Object.preventExtensions) {
+    Object.preventExtensions = function preventExtensions(object) {
+        // this is misleading and breaks feature-detection, but
+        // allows "securable" code to "gracefully" degrade to working
+        // but insecure code.
+        return object;
+    };
+}
+
+// ES5 15.2.3.11
+// http://es5.github.com/#x15.2.3.11
+if (!Object.isSealed) {
+    Object.isSealed = function isSealed(object) {
+        return false;
+    };
+}
+
+// ES5 15.2.3.12
+// http://es5.github.com/#x15.2.3.12
+if (!Object.isFrozen) {
+    Object.isFrozen = function isFrozen(object) {
+        return false;
+    };
+}
+
+// ES5 15.2.3.13
+// http://es5.github.com/#x15.2.3.13
+if (!Object.isExtensible) {
+    Object.isExtensible = function isExtensible(object) {
+        // 1. If Type(O) is not Object throw a TypeError exception.
+        if (Object(object) === object) {
+            throw new TypeError(); // TODO message
+        }
+        // 2. Return the Boolean value of the [[Extensible]] internal property of O.
+        var name = '';
+        while (owns(object, name)) {
+            name += '?';
+        }
+        object[name] = true;
+        var returnValue = owns(object, name);
+        delete object[name];
+        return returnValue;
+    };
+}
+
+// ES5 15.2.3.14
+// http://es5.github.com/#x15.2.3.14
+if (!Object.keys) {
+    // http://whattheheadsaid.com/2010/10/a-safer-object-keys-compatibility-implementation
+    var hasDontEnumBug = true,
+        dontEnums = [
+            "toString",
+            "toLocaleString",
+            "valueOf",
+            "hasOwnProperty",
+            "isPrototypeOf",
+            "propertyIsEnumerable",
+            "constructor"
+        ],
+        dontEnumsLength = dontEnums.length;
+
+    for (var key in {"toString": null})
+        hasDontEnumBug = false;
+
+    Object.keys = function keys(object) {
+
+        if ((typeof object != "object" && typeof object != "function") || object === null)
+            throw new TypeError("Object.keys called on a non-object");
+
+        var keys = [];
+        for (var name in object) {
+            if (owns(object, name)) {
+                keys.push(name);
+            }
+        }
+
+        if (hasDontEnumBug) {
+            for (var i = 0, ii = dontEnumsLength; i < ii; i++) {
+                var dontEnum = dontEnums[i];
+                if (owns(object, dontEnum)) {
+                    keys.push(dontEnum);
+                }
+            }
+        }
+
+        return keys;
+    };
+
+}
+
+//
+// Date
+// ====
+//
+
+// ES5 15.9.5.43
+// http://es5.github.com/#x15.9.5.43
+// This function returns a String value represent the instance in time 
+// represented by this Date object. The format of the String is the Date Time 
+// string format defined in 15.9.1.15. All fields are present in the String. 
+// The time zone is always UTC, denoted by the suffix Z. If the time value of 
+// this object is not a finite Number a RangeError exception is thrown.
+if (!Date.prototype.toISOString || (new Date(-62198755200000).toISOString().indexOf('-000001') === -1)) {
+    Date.prototype.toISOString = function toISOString() {
+        var result, length, value, year;
+        if (!isFinite(this))
+            throw new RangeError;
+
+        // the date time string format is specified in 15.9.1.15.
+        result = [this.getUTCMonth() + 1, this.getUTCDate(),
+            this.getUTCHours(), this.getUTCMinutes(), this.getUTCSeconds()];
+        year = this.getUTCFullYear();
+        year = (year < 0 ? '-' : (year > 9999 ? '+' : '')) + ('00000' + Math.abs(year)).slice(0 <= year && year <= 9999 ? -4 : -6);
+
+        length = result.length;
+        while (length--) {
+            value = result[length];
+            // pad months, days, hours, minutes, and seconds to have two digits.
+            if (value < 10)
+                result[length] = "0" + value;
+        }
+        // pad milliseconds to have three digits.
+        return year + "-" + result.slice(0, 2).join("-") + "T" + result.slice(2).join(":") + "." +
+            ("000" + this.getUTCMilliseconds()).slice(-3) + "Z";
+    }
+}
+
+// ES5 15.9.4.4
+// http://es5.github.com/#x15.9.4.4
+if (!Date.now) {
+    Date.now = function now() {
+        return new Date().getTime();
+    };
+}
+
+// ES5 15.9.5.44
+// http://es5.github.com/#x15.9.5.44
+// This function provides a String representation of a Date object for use by 
+// JSON.stringify (15.12.3).
+if (!Date.prototype.toJSON) {
+    Date.prototype.toJSON = function toJSON(key) {
+        // When the toJSON method is called with argument key, the following 
+        // steps are taken:
+
+        // 1.  Let O be the result of calling ToObject, giving it the this
+        // value as its argument.
+        // 2. Let tv be ToPrimitive(O, hint Number).
+        // 3. If tv is a Number and is not finite, return null.
+        // XXX
+        // 4. Let toISO be the result of calling the [[Get]] internal method of
+        // O with argument "toISOString".
+        // 5. If IsCallable(toISO) is false, throw a TypeError exception.
+        if (typeof this.toISOString != "function")
+            throw new TypeError(); // TODO message
+        // 6. Return the result of calling the [[Call]] internal method of
+        //  toISO with O as the this value and an empty argument list.
+        return this.toISOString();
+
+        // NOTE 1 The argument is ignored.
+
+        // NOTE 2 The toJSON function is intentionally generic; it does not
+        // require that its this value be a Date object. Therefore, it can be
+        // transferred to other kinds of objects for use as a method. However,
+        // it does require that any such object have a toISOString method. An
+        // object is free to use the argument key to filter its
+        // stringification.
+    };
+}
+
+// ES5 15.9.4.2
+// http://es5.github.com/#x15.9.4.2
+// based on work shared by Daniel Friesen (dantman)
+// http://gist.github.com/303249
+if (Date.parse("+275760-09-13T00:00:00.000Z") !== 8.64e15) {
+    // XXX global assignment won't work in embeddings that use
+    // an alternate object for the context.
+    Date = (function(NativeDate) {
+
+        // Date.length === 7
+        var Date = function Date(Y, M, D, h, m, s, ms) {
+            var length = arguments.length;
+            if (this instanceof NativeDate) {
+                var date = length == 1 && String(Y) === Y ? // isString(Y)
+                    // We explicitly pass it through parse:
+                    new NativeDate(Date.parse(Y)) :
+                    // We have to manually make calls depending on argument
+                    // length here
+                    length >= 7 ? new NativeDate(Y, M, D, h, m, s, ms) :
+                    length >= 6 ? new NativeDate(Y, M, D, h, m, s) :
+                    length >= 5 ? new NativeDate(Y, M, D, h, m) :
+                    length >= 4 ? new NativeDate(Y, M, D, h) :
+                    length >= 3 ? new NativeDate(Y, M, D) :
+                    length >= 2 ? new NativeDate(Y, M) :
+                    length >= 1 ? new NativeDate(Y) :
+                                  new NativeDate();
+                // Prevent mixups with unfixed Date object
+                date.constructor = Date;
+                return date;
+            }
+            return NativeDate.apply(this, arguments);
+        };
+
+        // 15.9.1.15 Date Time String Format.
+        var isoDateExpression = new RegExp("^" +
+            "(\\d{4}|[\+\-]\\d{6})" + // four-digit year capture or sign + 6-digit extended year
+            "(?:-(\\d{2})" + // optional month capture
+            "(?:-(\\d{2})" + // optional day capture
+            "(?:" + // capture hours:minutes:seconds.milliseconds
+                "T(\\d{2})" + // hours capture
+                ":(\\d{2})" + // minutes capture
+                "(?:" + // optional :seconds.milliseconds
+                    ":(\\d{2})" + // seconds capture
+                    "(?:\\.(\\d{3}))?" + // milliseconds capture
+                ")?" +
+            "(?:" + // capture UTC offset component
+                "Z|" + // UTC capture
+                "(?:" + // offset specifier +/-hours:minutes
+                    "([-+])" + // sign capture
+                    "(\\d{2})" + // hours offset capture
+                    ":(\\d{2})" + // minutes offset capture
+                ")" +
+            ")?)?)?)?" +
+        "$");
+
+        // Copy any custom methods a 3rd party library may have added
+        for (var key in NativeDate)
+            Date[key] = NativeDate[key];
+
+        // Copy "native" methods explicitly; they may be non-enumerable
+        Date.now = NativeDate.now;
+        Date.UTC = NativeDate.UTC;
+        Date.prototype = NativeDate.prototype;
+        Date.prototype.constructor = Date;
+
+        // Upgrade Date.parse to handle simplified ISO 8601 strings
+        Date.parse = function parse(string) {
+            var match = isoDateExpression.exec(string);
+            if (match) {
+                match.shift(); // kill match[0], the full match
+                // parse months, days, hours, minutes, seconds, and milliseconds
+                for (var i = 1; i < 7; i++) {
+                    // provide default values if necessary
+                    match[i] = +(match[i] || (i < 3 ? 1 : 0));
+                    // match[1] is the month. Months are 0-11 in JavaScript
+                    // `Date` objects, but 1-12 in ISO notation, so we
+                    // decrement.
+                    if (i == 1)
+                        match[i]--;
+                }
+
+                // parse the UTC offset component
+                var minuteOffset = +match.pop(), hourOffset = +match.pop(), sign = match.pop();
+
+                // compute the explicit time zone offset if specified
+                var offset = 0;
+                if (sign) {
+                    // detect invalid offsets and return early
+                    if (hourOffset > 23 || minuteOffset > 59)
+                        return NaN;
+
+                    // express the provided time zone offset in minutes. The offset is
+                    // negative for time zones west of UTC; positive otherwise.
+                    offset = (hourOffset * 60 + minuteOffset) * 6e4 * (sign == "+" ? -1 : 1);
+                }
+
+                // Date.UTC for years between 0 and 99 converts year to 1900 + year
+                // The Gregorian calendar has a 400-year cycle, so 
+                // to Date.UTC(year + 400, .... ) - 12622780800000 == Date.UTC(year, ...),
+                // where 12622780800000 - number of milliseconds in Gregorian calendar 400 years
+                var year = +match[0];
+                if (0 <= year && year <= 99) {
+                    match[0] = year + 400;
+                    return NativeDate.UTC.apply(this, match) + offset - 12622780800000;
+                }
+
+                // compute a new UTC date value, accounting for the optional offset
+                return NativeDate.UTC.apply(this, match) + offset;
+            }
+            return NativeDate.parse.apply(this, arguments);
+        };
+
+        return Date;
+    })(Date);
+}
+
+//
+// String
+// ======
+//
+
+// ES5 15.5.4.20
+// http://es5.github.com/#x15.5.4.20
+var ws = "\x09\x0A\x0B\x0C\x0D\x20\xA0\u1680\u180E\u2000\u2001\u2002\u2003" +
+    "\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u3000\u2028" +
+    "\u2029\uFEFF";
+if (!String.prototype.trim || ws.trim()) {
+    // http://blog.stevenlevithan.com/archives/faster-trim-javascript
+    // http://perfectionkills.com/whitespace-deviations/
+    ws = "[" + ws + "]";
+    var trimBeginRegexp = new RegExp("^" + ws + ws + "*"),
+        trimEndRegexp = new RegExp(ws + ws + "*$");
+    String.prototype.trim = function trim() {
+        return String(this).replace(trimBeginRegexp, "").replace(trimEndRegexp, "");
+    };
+}
+
+//
+// Util
+// ======
+//
+
+// ES5 9.4
+// http://es5.github.com/#x9.4
+// http://jsperf.com/to-integer
+var toInteger = function (n) {
+    n = +n;
+    if (n !== n) // isNaN
+        n = 0;
+    else if (n !== 0 && n !== (1/0) && n !== -(1/0))
+        n = (n > 0 || -1) * Math.floor(Math.abs(n));
+    return n;
+};
+
+var prepareString = "a"[0] != "a",
+    // ES5 9.9
+    // http://es5.github.com/#x9.9
+    toObject = function (o) {
+        if (o == null) { // this matches both null and undefined
+            throw new TypeError(); // TODO message
+        }
+        // If the implementation doesn't support by-index access of
+        // string characters (ex. IE < 7), split the string
+        if (prepareString && typeof o == "string" && o) {
+            return o.split("");
+        }
+        return Object(o);
+    };
+});/* vim:ts=4:sts=4:sw=4:
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Ajax.org Code Editor (ACE).
+ *
+ * The Initial Developer of the Original Code is
+ * Ajax.org B.V.
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *      Fabian Jakobs <fabian AT ajax DOT org>
+ *      Irakli Gozalishvili <rfobic@gmail.com> (http://jeditoolkit.com)
+ *      Mike de Boer <mike AT ajax DOT org>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+define('ace/lib/event_emitter', ['require', 'exports', 'module' ], function(require, exports, module) {
+"use strict";
+
+var EventEmitter = {};
+
+EventEmitter._emit =
+EventEmitter._dispatchEvent = function(eventName, e) {
+    this._eventRegistry = this._eventRegistry || {};
+    this._defaultHandlers = this._defaultHandlers || {};
+
+    var listeners = this._eventRegistry[eventName] || [];
+    var defaultHandler = this._defaultHandlers[eventName];
+    if (!listeners.length && !defaultHandler)
+        return;
+
+    e = e || {};
+    e.type = eventName;
+    
+    if (!e.stopPropagation) {
+        e.stopPropagation = function() {
+            this.propagationStopped = true;
+        };
+    }
+    
+    if (!e.preventDefault) {
+        e.preventDefault = function() {
+            this.defaultPrevented = true;
+        };
+    }
+
+    for (var i=0; i<listeners.length; i++) {
+        listeners[i](e);
+        if (e.propagationStopped)
+            break;
+    }
+    
+    if (defaultHandler && !e.defaultPrevented)
+        defaultHandler(e);
+};
+
+EventEmitter.setDefaultHandler = function(eventName, callback) {
+    this._defaultHandlers = this._defaultHandlers || {};
+    
+    if (this._defaultHandlers[eventName])
+        throw new Error("The default handler for '" + eventName + "' is already set");
+        
+    this._defaultHandlers[eventName] = callback;
+};
+
+EventEmitter.on =
+EventEmitter.addEventListener = function(eventName, callback) {
+    this._eventRegistry = this._eventRegistry || {};
+
+    var listeners = this._eventRegistry[eventName];
+    if (!listeners)
+        var listeners = this._eventRegistry[eventName] = [];
+
+    if (listeners.indexOf(callback) == -1)
+        listeners.push(callback);
+};
+
+EventEmitter.removeListener =
+EventEmitter.removeEventListener = function(eventName, callback) {
+    this._eventRegistry = this._eventRegistry || {};
+
+    var listeners = this._eventRegistry[eventName];
+    if (!listeners)
+        return;
+
+    var index = listeners.indexOf(callback);
+    if (index !== -1)
+        listeners.splice(index, 1);
+};
+
+EventEmitter.removeAllListeners = function(eventName) {
+    if (this._eventRegistry) this._eventRegistry[eventName] = [];
+};
+
+exports.EventEmitter = EventEmitter;
+
+});/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Ajax.org Code Editor (ACE).
+ *
+ * The Initial Developer of the Original Code is
+ * Ajax.org B.V.
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *      Fabian Jakobs <fabian AT ajax DOT org>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+define('ace/lib/oop', ['require', 'exports', 'module' ], function(require, exports, module) {
+"use strict";
+
+exports.inherits = (function() {
+    var tempCtor = function() {};
+    return function(ctor, superCtor) {
+        tempCtor.prototype = superCtor.prototype;
+        ctor.super_ = superCtor.prototype;
+        ctor.prototype = new tempCtor();
+        ctor.prototype.constructor = ctor;
+    };
+}());
+
+exports.mixin = function(obj, mixin) {
+    for (var key in mixin) {
+        obj[key] = mixin[key];
+    }
+};
+
+exports.implement = function(proto, mixin) {
+    exports.mixin(proto, mixin);
+};
+
+});
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Ajax.org Code Editor (ACE).
+ *
+ * The Initial Developer of the Original Code is
+ * Ajax.org B.V.
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *      Fabian Jakobs <fabian AT ajax DOT org>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+define('ace/mode/json_worker', ['require', 'exports', 'module' , 'ace/lib/oop', 'ace/worker/mirror', 'ace/mode/json/json_parse'], function(require, exports, module) {
+"use strict";
+
+var oop = require("../lib/oop");
+var Mirror = require("../worker/mirror").Mirror;
+var parse = require("./json/json_parse");
+
+var JsonWorker = exports.JsonWorker = function(sender) {
+    Mirror.call(this, sender);
+    this.setTimeout(200);
+};
+
+oop.inherits(JsonWorker, Mirror);
+
+(function() {
+
+    this.onUpdate = function() {
+        var value = this.doc.getValue();
+
+        try {
+            var result = parse(value);
+        } catch (e) {
+            var pos = this.charToDocumentPosition(e.at-1);
+            this.sender.emit("error", {
+                row: pos.row,
+                column: pos.column,
+                text: e.message,
+                type: "error"
+            });
+            return;
+        }
+        this.sender.emit("ok");
+    };
+
+    this.charToDocumentPosition = function(charPos) {
+        var i = 0;
+        var len = this.doc.getLength();
+        var nl = this.doc.getNewLineCharacter().length;
+
+        if (!len) {
+            return { row: 0, column: 0};
+        }
+
+        var lineStart = 0;
+        while (i < len) {
+            var line = this.doc.getLine(i);
+            var lineLength = line.length + nl;
+            if (lineStart + lineLength > charPos)
+                return {
+                    row: i,
+                    column: charPos - lineStart
+                };
+
+            lineStart += lineLength;
+            i += 1;
+        }
+
+        return {
+            row: i-1,
+            column: line.length
+        };
+    };
+
+}).call(JsonWorker.prototype);
+
+});define('ace/worker/mirror', ['require', 'exports', 'module' , 'ace/document', 'ace/lib/lang'], function(require, exports, module) {
+"use strict";
+
+var Document = require("../document").Document;
+var lang = require("../lib/lang");
+    
+var Mirror = exports.Mirror = function(sender) {
+    this.sender = sender;
+    var doc = this.doc = new Document("");
+    
+    var deferredUpdate = this.deferredUpdate = lang.deferredCall(this.onUpdate.bind(this));
+    
+    var _self = this;
+    sender.on("change", function(e) {
+        doc.applyDeltas([e.data]);        
+        deferredUpdate.schedule(_self.$timeout);
+    });
+};
+
+(function() {
+    
+    this.$timeout = 500;
+    
+    this.setTimeout = function(timeout) {
+        this.$timeout = timeout;
+    };
+    
+    this.setValue = function(value) {
+        this.doc.setValue(value);
+        this.deferredUpdate.schedule(this.$timeout);
+    };
+    
+    this.getValue = function(callbackId) {
+        this.sender.callback(this.doc.getValue(), callbackId);
+    };
+    
+    this.onUpdate = function() {
+        // abstract method
+    };
+    
+}).call(Mirror.prototype);
+
+});/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Ajax.org Code Editor (ACE).
+ *
+ * The Initial Developer of the Original Code is
+ * Ajax.org B.V.
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *      Fabian Jakobs <fabian AT ajax DOT org>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+define('ace/document', ['require', 'exports', 'module' , 'ace/lib/oop', 'ace/lib/event_emitter', 'ace/range', 'ace/anchor'], function(require, exports, module) {
+"use strict";
+
+var oop = require("./lib/oop");
+var EventEmitter = require("./lib/event_emitter").EventEmitter;
+var Range = require("./range").Range;
+var Anchor = require("./anchor").Anchor;
+
+var Document = function(text) {
+    this.$lines = [];
+
+    if (Array.isArray(text)) {
+        this.insertLines(0, text);
+    }
+    // There has to be one line at least in the document. If you pass an empty
+    // string to the insert function, nothing will happen. Workaround.
+    else if (text.length == 0) {
+        this.$lines = [""];
+    } else {
+        this.insert({row: 0, column:0}, text);
+    }
+};
+
+(function() {
+
+    oop.implement(this, EventEmitter);
+
+    this.setValue = function(text) {
+        var len = this.getLength();
+        this.remove(new Range(0, 0, len, this.getLine(len-1).length));
+        this.insert({row: 0, column:0}, text);
+    };
+
+    this.getValue = function() {
+        return this.getAllLines().join(this.getNewLineCharacter());
+    };
+
+    this.createAnchor = function(row, column) {
+        return new Anchor(this, row, column);
+    };
+
+    // check for IE split bug
+    if ("aaa".split(/a/).length == 0)
+        this.$split = function(text) {
+            return text.replace(/\r\n|\r/g, "\n").split("\n");
+        }
+    else
+        this.$split = function(text) {
+            return text.split(/\r\n|\r|\n/);
+        };
+
+
+    this.$detectNewLine = function(text) {
+        var match = text.match(/^.*?(\r\n|\r|\n)/m);
+        if (match) {
+            this.$autoNewLine = match[1];
+        } else {
+            this.$autoNewLine = "\n";
+        }
+    };
+
+    this.getNewLineCharacter = function() {
+      switch (this.$newLineMode) {
+          case "windows":
+              return "\r\n";
+
+          case "unix":
+              return "\n";
+
+          case "auto":
+              return this.$autoNewLine;
+      }
+    };
+
+    this.$autoNewLine = "\n";
+    this.$newLineMode = "auto";
+    this.setNewLineMode = function(newLineMode) {
+        if (this.$newLineMode === newLineMode)
+            return;
+
+        this.$newLineMode = newLineMode;
+    };
+
+    this.getNewLineMode = function() {
+        return this.$newLineMode;
+    };
+
+    this.isNewLine = function(text) {
+        return (text == "\r\n" || text == "\r" || text == "\n");
+    };
+
+    /**
+     * Get a verbatim copy of the given line as it is in the document
+     */
+    this.getLine = function(row) {
+        return this.$lines[row] || "";
+    };
+
+    this.getLines = function(firstRow, lastRow) {
+        return this.$lines.slice(firstRow, lastRow + 1);
+    };
+
+    /**
+     * Returns all lines in the document as string array. Warning: The caller
+     * should not modify this array!
+     */
+    this.getAllLines = function() {
+        return this.getLines(0, this.getLength());
+    };
+
+    this.getLength = function() {
+        return this.$lines.length;
+    };
+
+    this.getTextRange = function(range) {
+        if (range.start.row == range.end.row) {
+            return this.$lines[range.start.row].substring(range.start.column,
+                                                         range.end.column);
+        }
+        else {
+            var lines = [];
+            lines.push(this.$lines[range.start.row].substring(range.start.column));
+            lines.push.apply(lines, this.getLines(range.start.row+1, range.end.row-1));
+            lines.push(this.$lines[range.end.row].substring(0, range.end.column));
+            return lines.join(this.getNewLineCharacter());
+        }
+    };
+
+    this.$clipPosition = function(position) {
+        var length = this.getLength();
+        if (position.row >= length) {
+            position.row = Math.max(0, length - 1);
+            position.column = this.getLine(length-1).length;
+        }
+        return position;
+    };
+
+    this.insert = function(position, text) {
+        if (!text || text.length === 0)
+            return position;
+
+        position = this.$clipPosition(position);
+
+        // only detect new lines if the document has no line break yet
+        if (this.getLength() <= 1)
+            this.$detectNewLine(text);
+
+        var lines = this.$split(text);
+        var firstLine = lines.splice(0, 1)[0];
+        var lastLine = lines.length == 0 ? null : lines.splice(lines.length - 1, 1)[0];
+
+        position = this.insertInLine(position, firstLine);
+        if (lastLine !== null) {
+            position = this.insertNewLine(position); // terminate first line
+            position = this.insertLines(position.row, lines);
+            position = this.insertInLine(position, lastLine || "");
+        }
+        return position;
+    };
+
+    this.insertLines = function(row, lines) {
+        if (lines.length == 0)
+            return {row: row, column: 0};
+
+        var args = [row, 0];
+        args.push.apply(args, lines);
+        this.$lines.splice.apply(this.$lines, args);
+
+        var range = new Range(row, 0, row + lines.length, 0);
+        var delta = {
+            action: "insertLines",
+            range: range,
+            lines: lines
+        };
+        this._emit("change", { data: delta });
+        return range.end;
+    };
+
+    this.insertNewLine = function(position) {
+        position = this.$clipPosition(position);
+        var line = this.$lines[position.row] || "";
+
+        this.$lines[position.row] = line.substring(0, position.column);
+        this.$lines.splice(position.row + 1, 0, line.substring(position.column, line.length));
+
+        var end = {
+            row : position.row + 1,
+            column : 0
+        };
+
+        var delta = {
+            action: "insertText",
+            range: Range.fromPoints(position, end),
+            text: this.getNewLineCharacter()
+        };
+        this._emit("change", { data: delta });
+
+        return end;
+    };
+
+    this.insertInLine = function(position, text) {
+        if (text.length == 0)
+            return position;
+
+        var line = this.$lines[position.row] || "";
+
+        this.$lines[position.row] = line.substring(0, position.column) + text
+                + line.substring(position.column);
+
+        var end = {
+            row : position.row,
+            column : position.column + text.length
+        };
+
+        var delta = {
+            action: "insertText",
+            range: Range.fromPoints(position, end),
+            text: text
+        };
+        this._emit("change", { data: delta });
+
+        return end;
+    };
+
+    this.remove = function(range) {
+        // clip to document
+        range.start = this.$clipPosition(range.start);
+        range.end = this.$clipPosition(range.end);
+
+        if (range.isEmpty())
+            return range.start;
+
+        var firstRow = range.start.row;
+        var lastRow = range.end.row;
+
+        if (range.isMultiLine()) {
+            var firstFullRow = range.start.column == 0 ? firstRow : firstRow + 1;
+            var lastFullRow = lastRow - 1;
+
+            if (range.end.column > 0)
+                this.removeInLine(lastRow, 0, range.end.column);
+
+            if (lastFullRow >= firstFullRow)
+                this.removeLines(firstFullRow, lastFullRow);
+
+            if (firstFullRow != firstRow) {
+                this.removeInLine(firstRow, range.start.column, this.getLine(firstRow).length);
+                this.removeNewLine(range.start.row);
+            }
+        }
+        else {
+            this.removeInLine(firstRow, range.start.column, range.end.column);
+        }
+        return range.start;
+    };
+
+    this.removeInLine = function(row, startColumn, endColumn) {
+        if (startColumn == endColumn)
+            return;
+
+        var range = new Range(row, startColumn, row, endColumn);
+        var line = this.getLine(row);
+        var removed = line.substring(startColumn, endColumn);
+        var newLine = line.substring(0, startColumn) + line.substring(endColumn, line.length);
+        this.$lines.splice(row, 1, newLine);
+
+        var delta = {
+            action: "removeText",
+            range: range,
+            text: removed
+        };
+        this._emit("change", { data: delta });
+        return range.start;
+    };
+
+    /**
+     * Removes a range of full lines
+     *
+     * @param firstRow {Integer} The first row to be removed
+     * @param lastRow {Integer} The last row to be removed
+     * @return {String[]} The removed lines
+     */
+    this.removeLines = function(firstRow, lastRow) {
+        var range = new Range(firstRow, 0, lastRow + 1, 0);
+        var removed = this.$lines.splice(firstRow, lastRow - firstRow + 1);
+
+        var delta = {
+            action: "removeLines",
+            range: range,
+            nl: this.getNewLineCharacter(),
+            lines: removed
+        };
+        this._emit("change", { data: delta });
+        return removed;
+    };
+
+    this.removeNewLine = function(row) {
+        var firstLine = this.getLine(row);
+        var secondLine = this.getLine(row+1);
+
+        var range = new Range(row, firstLine.length, row+1, 0);
+        var line = firstLine + secondLine;
+
+        this.$lines.splice(row, 2, line);
+
+        var delta = {
+            action: "removeText",
+            range: range,
+            text: this.getNewLineCharacter()
+        };
+        this._emit("change", { data: delta });
+    };
+
+    this.replace = function(range, text) {
+        if (text.length == 0 && range.isEmpty())
+            return range.start;
+
+        // Shortcut: If the text we want to insert is the same as it is already
+        // in the document, we don't have to replace anything.
+        if (text == this.getTextRange(range))
+            return range.end;
+
+        this.remove(range);
+        if (text) {
+            var end = this.insert(range.start, text);
+        }
+        else {
+            end = range.start;
+        }
+
+        return end;
+    };
+
+    this.applyDeltas = function(deltas) {
+        for (var i=0; i<deltas.length; i++) {
+            var delta = deltas[i];
+            var range = Range.fromPoints(delta.range.start, delta.range.end);
+
+            if (delta.action == "insertLines")
+                this.insertLines(range.start.row, delta.lines);
+            else if (delta.action == "insertText")
+                this.insert(range.start, delta.text);
+            else if (delta.action == "removeLines")
+                this.removeLines(range.start.row, range.end.row - 1);
+            else if (delta.action == "removeText")
+                this.remove(range);
+        }
+    };
+
+    this.revertDeltas = function(deltas) {
+        for (var i=deltas.length-1; i>=0; i--) {
+            var delta = deltas[i];
+
+            var range = Range.fromPoints(delta.range.start, delta.range.end);
+
+            if (delta.action == "insertLines")
+                this.removeLines(range.start.row, range.end.row - 1);
+            else if (delta.action == "insertText")
+                this.remove(range);
+            else if (delta.action == "removeLines")
+                this.insertLines(range.start.row, delta.lines);
+            else if (delta.action == "removeText")
+                this.insert(range.start, delta.text);
+        }
+    };
+
+}).call(Document.prototype);
+
+exports.Document = Document;
+});
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Ajax.org Code Editor (ACE).
+ *
+ * The Initial Developer of the Original Code is
+ * Ajax.org B.V.
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *      Fabian Jakobs <fabian AT ajax DOT org>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+define('ace/range', ['require', 'exports', 'module' ], function(require, exports, module) {
+"use strict";
+
+var Range = function(startRow, startColumn, endRow, endColumn) {
+    this.start = {
+        row: startRow,
+        column: startColumn
+    };
+
+    this.end = {
+        row: endRow,
+        column: endColumn
+    };
+};
+
+(function() {
+    this.isEqual = function(range) {
+        return this.start.row == range.start.row &&
+            this.end.row == range.end.row &&
+            this.start.column == range.start.column &&
+            this.end.column == range.end.column
+    };
+
+    this.toString = function() {
+        return ("Range: [" + this.start.row + "/" + this.start.column +
+            "] -> [" + this.end.row + "/" + this.end.column + "]");
+    };
+
+    this.contains = function(row, column) {
+        return this.compare(row, column) == 0;
+    };
+
+    /**
+     * Compares this range (A) with another range (B), where B is the passed in
+     * range.
+     *
+     * Return values:
+     *  -2: (B) is infront of (A) and doesn't intersect with (A)
+     *  -1: (B) begins before (A) but ends inside of (A)
+     *   0: (B) is completly inside of (A) OR (A) is complety inside of (B)
+     *  +1: (B) begins inside of (A) but ends outside of (A)
+     *  +2: (B) is after (A) and doesn't intersect with (A)
+     *
+     *  42: FTW state: (B) ends in (A) but starts outside of (A)
+     */
+    this.compareRange = function(range) {
+        var cmp,
+            end = range.end,
+            start = range.start;
+
+        cmp = this.compare(end.row, end.column);
+        if (cmp == 1) {
+            cmp = this.compare(start.row, start.column);
+            if (cmp == 1) {
+                return 2;
+            } else if (cmp == 0) {
+                return 1;
+            } else {
+                return 0;
+            }
+        } else if (cmp == -1) {
+            return -2;
+        } else {
+            cmp = this.compare(start.row, start.column);
+            if (cmp == -1) {
+                return -1;
+            } else if (cmp == 1) {
+                return 42;
+            } else {
+                return 0;
+            }
+        }
+    }
+
+    this.comparePoint = function(p) {
+        return this.compare(p.row, p.column);
+    }
+
+    this.containsRange = function(range) {
+        return this.comparePoint(range.start) == 0 && this.comparePoint(range.end) == 0;
+    }
+
+    this.intersectsRange = function(range) {
+        var cmp = this.compareRange(range);
+        return (cmp == -1 || cmp == 0 || cmp == 1);
+    }
+
+    this.isEnd = function(row, column) {
+        return this.end.row == row && this.end.column == column;
+    }
+
+    this.isStart = function(row, column) {
+        return this.start.row == row && this.start.column == column;
+    }
+
+    this.setStart = function(row, column) {
+        if (typeof row == "object") {
+            this.start.column = row.column;
+            this.start.row = row.row;
+        } else {
+            this.start.row = row;
+            this.start.column = column;
+        }
+    }
+
+    this.setEnd = function(row, column) {
+        if (typeof row == "object") {
+            this.end.column = row.column;
+            this.end.row = row.row;
+        } else {
+            this.end.row = row;
+            this.end.column = column;
+        }
+    }
+
+    this.inside = function(row, column) {
+        if (this.compare(row, column) == 0) {
+            if (this.isEnd(row, column) || this.isStart(row, column)) {
+                return false;
+            } else {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    this.insideStart = function(row, column) {
+        if (this.compare(row, column) == 0) {
+            if (this.isEnd(row, column)) {
+                return false;
+            } else {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    this.insideEnd = function(row, column) {
+        if (this.compare(row, column) == 0) {
+            if (this.isStart(row, column)) {
+                return false;
+            } else {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    this.compare = function(row, column) {
+        if (!this.isMultiLine()) {
+            if (row === this.start.row) {
+                return column < this.start.column ? -1 : (column > this.end.column ? 1 : 0);
+            };
+        }
+
+        if (row < this.start.row)
+            return -1;
+
+        if (row > this.end.row)
+            return 1;
+
+        if (this.start.row === row)
+            return column >= this.start.column ? 0 : -1;
+
+        if (this.end.row === row)
+            return column <= this.end.column ? 0 : 1;
+
+        return 0;
+    };
+
+    /**
+     * Like .compare(), but if isStart is true, return -1;
+     */
+    this.compareStart = function(row, column) {
+        if (this.start.row == row && this.start.column == column) {
+            return -1;
+        } else {
+            return this.compare(row, column);
+        }
+    }
+
+    /**
+     * Like .compare(), but if isEnd is true, return 1;
+     */
+    this.compareEnd = function(row, column) {
+        if (this.end.row == row && this.end.column == column) {
+            return 1;
+        } else {
+            return this.compare(row, column);
+        }
+    }
+
+    this.compareInside = function(row, column) {
+        if (this.end.row == row && this.end.column == column) {
+            return 1;
+        } else if (this.start.row == row && this.start.column == column) {
+            return -1;
+        } else {
+            return this.compare(row, column);
+        }
+    }
+
+    this.clipRows = function(firstRow, lastRow) {
+        if (this.end.row > lastRow) {
+            var end = {
+                row: lastRow+1,
+                column: 0
+            };
+        }
+
+        if (this.start.row > lastRow) {
+            var start = {
+                row: lastRow+1,
+                column: 0
+            };
+        }
+
+        if (this.start.row < firstRow) {
+            var start = {
+                row: firstRow,
+                column: 0
+            };
+        }
+
+        if (this.end.row < firstRow) {
+            var end = {
+                row: firstRow,
+                column: 0
+            };
+        }
+        return Range.fromPoints(start || this.start, end || this.end);
+    };
+
+    this.extend = function(row, column) {
+        var cmp = this.compare(row, column);
+
+        if (cmp == 0)
+            return this;
+        else if (cmp == -1)
+            var start = {row: row, column: column};
+        else
+            var end = {row: row, column: column};
+
+        return Range.fromPoints(start || this.start, end || this.end);
+    };
+
+    this.fixOrientation = function() {
+        if (
+            this.start.row < this.end.row 
+            || (this.start.row == this.end.row && this.start.column < this.end.column)
+        ) {
+            return false;
+        }
+        
+        var temp = this.start;
+        this.end = this.start;
+        this.start = temp;
+        return true;
+    };
+
+
+    this.isEmpty = function() {
+        return (this.start.row == this.end.row && this.start.column == this.end.column);
+    };
+
+    this.isMultiLine = function() {
+        return (this.start.row !== this.end.row);
+    };
+
+    this.clone = function() {
+        return Range.fromPoints(this.start, this.end);
+    };
+
+    this.collapseRows = function() {
+        if (this.end.column == 0)
+            return new Range(this.start.row, 0, Math.max(this.start.row, this.end.row-1), 0)
+        else
+            return new Range(this.start.row, 0, this.end.row, 0)
+    };
+
+    this.toScreenRange = function(session) {
+        var screenPosStart =
+            session.documentToScreenPosition(this.start);
+        var screenPosEnd =
+            session.documentToScreenPosition(this.end);
+
+        return new Range(
+            screenPosStart.row, screenPosStart.column,
+            screenPosEnd.row, screenPosEnd.column
+        );
+    };
+
+}).call(Range.prototype);
+
+
+Range.fromPoints = function(start, end) {
+    return new Range(start.row, start.column, end.row, end.column);
+};
+
+exports.Range = Range;
+});
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Ajax.org Code Editor (ACE).
+ *
+ * The Initial Developer of the Original Code is
+ * Ajax.org B.V.
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *      Fabian Jakobs <fabian AT ajax DOT org>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+define('ace/anchor', ['require', 'exports', 'module' , 'ace/lib/oop', 'ace/lib/event_emitter'], function(require, exports, module) {
+"use strict";
+
+var oop = require("./lib/oop");
+var EventEmitter = require("./lib/event_emitter").EventEmitter;
+
+/**
+ * An Anchor is a floating pointer in the document. Whenever text is inserted or
+ * deleted before the cursor, the position of the cursor is updated
+ */
+var Anchor = exports.Anchor = function(doc, row, column) {
+    this.document = doc;
+    
+    if (typeof column == "undefined")
+        this.setPosition(row.row, row.column);
+    else
+        this.setPosition(row, column);
+
+    this.$onChange = this.onChange.bind(this);
+    doc.on("change", this.$onChange);
+};
+
+(function() {
+
+    oop.implement(this, EventEmitter);
+    
+    this.getPosition = function() {
+        return this.$clipPositionToDocument(this.row, this.column);
+    };
+    
+    this.getDocument = function() {
+        return this.document;
+    };
+    
+    this.onChange = function(e) {
+        var delta = e.data;
+        var range = delta.range;
+            
+        if (range.start.row == range.end.row && range.start.row != this.row)
+            return;
+            
+        if (range.start.row > this.row)
+            return;
+            
+        if (range.start.row == this.row && range.start.column > this.column)
+            return;
+    
+        var row = this.row;
+        var column = this.column;
+        
+        if (delta.action === "insertText") {
+            if (range.start.row === row && range.start.column <= column) {
+                if (range.start.row === range.end.row) {
+                    column += range.end.column - range.start.column;
+                }
+                else {
+                    column -= range.start.column;
+                    row += range.end.row - range.start.row;
+                }
+            }
+            else if (range.start.row !== range.end.row && range.start.row < row) {
+                row += range.end.row - range.start.row;
+            }
+        } else if (delta.action === "insertLines") {
+            if (range.start.row <= row) {
+                row += range.end.row - range.start.row;
+            }
+        }
+        else if (delta.action == "removeText") {
+            if (range.start.row == row && range.start.column < column) {
+                if (range.end.column >= column)
+                    column = range.start.column;
+                else
+                    column = Math.max(0, column - (range.end.column - range.start.column));
+                
+            } else if (range.start.row !== range.end.row && range.start.row < row) {
+                if (range.end.row == row) {
+                    column = Math.max(0, column - range.end.column) + range.start.column;
+                }
+                row -= (range.end.row - range.start.row);
+            }
+            else if (range.end.row == row) {
+                row -= range.end.row - range.start.row;
+                column = Math.max(0, column - range.end.column) + range.start.column;
+            }
+        } else if (delta.action == "removeLines") {
+            if (range.start.row <= row) {
+                if (range.end.row <= row)
+                    row -= range.end.row - range.start.row;
+                else {
+                    row = range.start.row;
+                    column = 0;
+                }
+            }
+        }
+
+        this.setPosition(row, column, true);
+    };
+
+    this.setPosition = function(row, column, noClip) {
+        var pos;
+        if (noClip) {
+            pos = {
+                row: row,
+                column: column
+            };
+        }
+        else {
+            pos = this.$clipPositionToDocument(row, column);
+        }
+        
+        if (this.row == pos.row && this.column == pos.column)
+            return;
+            
+        var old = {
+            row: this.row,
+            column: this.column
+        };
+        
+        this.row = pos.row;
+        this.column = pos.column;
+        this._emit("change", {
+            old: old,
+            value: pos
+        });
+    };
+    
+    this.detach = function() {
+        this.document.removeEventListener("change", this.$onChange);
+    };
+    
+    this.$clipPositionToDocument = function(row, column) {
+        var pos = {};
+    
+        if (row >= this.document.getLength()) {
+            pos.row = Math.max(0, this.document.getLength() - 1);
+            pos.column = this.document.getLine(pos.row).length;
+        }
+        else if (row < 0) {
+            pos.row = 0;
+            pos.column = 0;
+        }
+        else {
+            pos.row = row;
+            pos.column = Math.min(this.document.getLine(pos.row).length, Math.max(0, column));
+        }
+        
+        if (column < 0)
+            pos.column = 0;
+            
+        return pos;
+    };
+    
+}).call(Anchor.prototype);
+
+});
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Ajax.org Code Editor (ACE).
+ *
+ * The Initial Developer of the Original Code is
+ * Ajax.org B.V.
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *      Fabian Jakobs <fabian AT ajax DOT org>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+define('ace/lib/lang', ['require', 'exports', 'module' ], function(require, exports, module) {
+"use strict";
+
+exports.stringReverse = function(string) {
+    return string.split("").reverse().join("");
+};
+
+exports.stringRepeat = function (string, count) {
+     return new Array(count + 1).join(string);
+};
+
+var trimBeginRegexp = /^\s\s*/;
+var trimEndRegexp = /\s\s*$/;
+
+exports.stringTrimLeft = function (string) {
+    return string.replace(trimBeginRegexp, '');
+};
+
+exports.stringTrimRight = function (string) {
+    return string.replace(trimEndRegexp, '');
+};
+
+exports.copyObject = function(obj) {
+    var copy = {};
+    for (var key in obj) {
+        copy[key] = obj[key];
+    }
+    return copy;
+};
+
+exports.copyArray = function(array){
+    var copy = [];
+    for (var i=0, l=array.length; i<l; i++) {
+        if (array[i] && typeof array[i] == "object")
+            copy[i] = this.copyObject( array[i] );
+        else 
+            copy[i] = array[i];
+    }
+    return copy;
+};
+
+exports.deepCopy = function (obj) {
+    if (typeof obj != "object") {
+        return obj;
+    }
+    
+    var copy = obj.constructor();
+    for (var key in obj) {
+        if (typeof obj[key] == "object") {
+            copy[key] = this.deepCopy(obj[key]);
+        } else {
+            copy[key] = obj[key];
+        }
+    }
+    return copy;
+};
+
+exports.arrayToMap = function(arr) {
+    var map = {};
+    for (var i=0; i<arr.length; i++) {
+        map[arr[i]] = 1;
+    }
+    return map;
+
+};
+
+/**
+ * splice out of 'array' anything that === 'value'
+ */
+exports.arrayRemove = function(array, value) {
+  for (var i = 0; i <= array.length; i++) {
+    if (value === array[i]) {
+      array.splice(i, 1);
+    }
+  }
+};
+
+exports.escapeRegExp = function(str) {
+    return str.replace(/([.*+?^${}()|[\]\/\\])/g, '\\$1');
+};
+
+exports.deferredCall = function(fcn) {
+
+    var timer = null;
+    var callback = function() {
+        timer = null;
+        fcn();
+    };
+
+    var deferred = function(timeout) {
+        deferred.cancel();
+        timer = setTimeout(callback, timeout || 0);
+        return deferred;
+    };
+
+    deferred.schedule = deferred;
+
+    deferred.call = function() {
+        this.cancel();
+        fcn();
+        return deferred;
+    };
+
+    deferred.cancel = function() {
+        clearTimeout(timer);
+        timer = null;
+        return deferred;
+    };
+
+    return deferred;
+};
+
+});
+/*
+    http://www.JSON.org/json_parse.js
+    2008-09-18
+
+    Public Domain.
+
+    NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
+
+    This file creates a json_parse function.
+
+        json_parse(text, reviver)
+            This method parses a JSON text to produce an object or array.
+            It can throw a SyntaxError exception.
+
+            The optional reviver parameter is a function that can filter and
+            transform the results. It receives each of the keys and values,
+            and its return value is used instead of the original value.
+            If it returns what it received, then the structure is not modified.
+            If it returns undefined then the member is deleted.
+
+            Example:
+
+            // Parse the text. Values that look like ISO date strings will
+            // be converted to Date objects.
+
+            myData = json_parse(text, function (key, value) {
+                var a;
+                if (typeof value === 'string') {
+                    a =
+/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(value);
+                    if (a) {
+                        return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4],
+                            +a[5], +a[6]));
+                    }
+                }
+                return value;
+            });
+
+    This is a reference implementation. You are free to copy, modify, or
+    redistribute.
+
+    This code should be minified before deployment.
+    See http://javascript.crockford.com/jsmin.html
+
+    USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO
+    NOT CONTROL.
+*/
+
+/*members "", "\"", "\/", "\\", at, b, call, charAt, f, fromCharCode,
+    hasOwnProperty, message, n, name, push, r, t, text
+*/
+
+define('ace/mode/json/json_parse', ['require', 'exports', 'module' ], function(require, exports, module) {
+"use strict";
+
+// This is a function that can parse a JSON text, producing a JavaScript
+// data structure. It is a simple, recursive descent parser. It does not use
+// eval or regular expressions, so it can be used as a model for implementing
+// a JSON parser in other languages.
+
+// We are defining the function inside of another function to avoid creating
+// global variables.
+
+    var at,     // The index of the current character
+        ch,     // The current character
+        escapee = {
+            '"':  '"',
+            '\\': '\\',
+            '/':  '/',
+            b:    '\b',
+            f:    '\f',
+            n:    '\n',
+            r:    '\r',
+            t:    '\t'
+        },
+        text,
+
+        error = function (m) {
+
+// Call error when something is wrong.
+
+            throw {
+                name:    'SyntaxError',
+                message: m,
+                at:      at,
+                text:    text
+            };
+        },
+
+        next = function (c) {
+
+// If a c parameter is provided, verify that it matches the current character.
+
+            if (c && c !== ch) {
+                error("Expected '" + c + "' instead of '" + ch + "'");
+            }
+
+// Get the next character. When there are no more characters,
+// return the empty string.
+
+            ch = text.charAt(at);
+            at += 1;
+            return ch;
+        },
+
+        number = function () {
+
+// Parse a number value.
+
+            var number,
+                string = '';
+
+            if (ch === '-') {
+                string = '-';
+                next('-');
+            }
+            while (ch >= '0' && ch <= '9') {
+                string += ch;
+                next();
+            }
+            if (ch === '.') {
+                string += '.';
+                while (next() && ch >= '0' && ch <= '9') {
+                    string += ch;
+                }
+            }
+            if (ch === 'e' || ch === 'E') {
+                string += ch;
+                next();
+                if (ch === '-' || ch === '+') {
+                    string += ch;
+                    next();
+                }
+                while (ch >= '0' && ch <= '9') {
+                    string += ch;
+                    next();
+                }
+            }
+            number = +string;
+            if (isNaN(number)) {
+                error("Bad number");
+            } else {
+                return number;
+            }
+        },
+
+        string = function () {
+
+// Parse a string value.
+
+            var hex,
+                i,
+                string = '',
+                uffff;
+
+// When parsing for string values, we must look for " and \ characters.
+
+            if (ch === '"') {
+                while (next()) {
+                    if (ch === '"') {
+                        next();
+                        return string;
+                    } else if (ch === '\\') {
+                        next();
+                        if (ch === 'u') {
+                            uffff = 0;
+                            for (i = 0; i < 4; i += 1) {
+                                hex = parseInt(next(), 16);
+                                if (!isFinite(hex)) {
+                                    break;
+                                }
+                                uffff = uffff * 16 + hex;
+                            }
+                            string += String.fromCharCode(uffff);
+                        } else if (typeof escapee[ch] === 'string') {
+                            string += escapee[ch];
+                        } else {
+                            break;
+                        }
+                    } else {
+                        string += ch;
+                    }
+                }
+            }
+            error("Bad string");
+        },
+
+        white = function () {
+
+// Skip whitespace.
+
+            while (ch && ch <= ' ') {
+                next();
+            }
+        },
+
+        word = function () {
+
+// true, false, or null.
+
+            switch (ch) {
+            case 't':
+                next('t');
+                next('r');
+                next('u');
+                next('e');
+                return true;
+            case 'f':
+                next('f');
+                next('a');
+                next('l');
+                next('s');
+                next('e');
+                return false;
+            case 'n':
+                next('n');
+                next('u');
+                next('l');
+                next('l');
+                return null;
+            }
+            error("Unexpected '" + ch + "'");
+        },
+
+        value,  // Place holder for the value function.
+
+        array = function () {
+
+// Parse an array value.
+
+            var array = [];
+
+            if (ch === '[') {
+                next('[');
+                white();
+                if (ch === ']') {
+                    next(']');
+                    return array;   // empty array
+                }
+                while (ch) {
+                    array.push(value());
+                    white();
+                    if (ch === ']') {
+                        next(']');
+                        return array;
+                    }
+                    next(',');
+                    white();
+                }
+            }
+            error("Bad array");
+        },
+
+        object = function () {
+
+// Parse an object value.
+
+            var key,
+                object = {};
+
+            if (ch === '{') {
+                next('{');
+                white();
+                if (ch === '}') {
+                    next('}');
+                    return object;   // empty object
+                }
+                while (ch) {
+                    key = string();
+                    white();
+                    next(':');
+                    if (Object.hasOwnProperty.call(object, key)) {
+                        error('Duplicate key "' + key + '"');
+                    }
+                    object[key] = value();
+                    white();
+                    if (ch === '}') {
+                        next('}');
+                        return object;
+                    }
+                    next(',');
+                    white();
+                }
+            }
+            error("Bad object");
+        };
+
+    value = function () {
+
+// Parse a JSON value. It could be an object, an array, a string, a number,
+// or a word.
+
+        white();
+        switch (ch) {
+        case '{':
+            return object();
+        case '[':
+            return array();
+        case '"':
+            return string();
+        case '-':
+            return number();
+        default:
+            return ch >= '0' && ch <= '9' ? number() : word();
+        }
+    };
+
+// Return the json_parse function. It will have access to all of the above
+// functions and variables.
+
+    return function (source, reviver) {
+        var result;
+
+        text = source;
+        at = 0;
+        ch = ' ';
+        result = value();
+        white();
+        if (ch) {
+            error("Syntax error");
+        }
+
+// If there is a reviver function, we recursively walk the new structure,
+// passing each name/value pair to the reviver function for possible
+// transformation, starting with a temporary root object that holds the result
+// in an empty key. If there is not a reviver function, we simply return the
+// result.
+
+        return typeof reviver === 'function' ? function walk(holder, key) {
+            var k, v, value = holder[key];
+            if (value && typeof value === 'object') {
+                for (k in value) {
+                    if (Object.hasOwnProperty.call(value, k)) {
+                        v = walk(value, k);
+                        if (v !== undefined) {
+                            value[k] = v;
+                        } else {
+                            delete value[k];
+                        }
+                    }
+                }
+            }
+            return reviver.call(holder, key, value);
+        }({'': result}, '') : result;
+    };
+});
\ No newline at end of file
diff --git a/apps/files_texteditor/js/editor.js b/apps/files_texteditor/js/editor.js
index bc8a20408c2db863b212f5f652bde9d2baf25c29..b891ef29b96add27cc3452280e0ebad229ce96bf 100644
--- a/apps/files_texteditor/js/editor.js
+++ b/apps/files_texteditor/js/editor.js
@@ -29,6 +29,7 @@ function setSyntaxMode(ext){
 	filetype["jsm"] = "javascript";
 	filetype["json"] = "json";
 	filetype["latex"] = "latex";
+        filetype["less"] = "less";
 	filetype["ly"] = "latex";
 	filetype["ily"] = "latex";
 	filetype["lua"] = "lua";
@@ -47,6 +48,7 @@ function setSyntaxMode(ext){
 	filetype["scad"] = "scad"; // seems to be something like 3d model files printed with e.g. reprap
 	filetype["scala"] = "scala";
 	filetype["scss"] = "scss"; // "sassy css"
+        filetype["sh"] = "sh";
 	filetype["sql"] = "sql";
 	filetype["svg"] = "svg";
 	filetype["textile"] = "textile"; // related to markdown
@@ -59,7 +61,7 @@ function setSyntaxMode(ext){
 			var SyntaxMode = require("ace/mode/"+filetype[ext]).Mode;
 			window.aceEditor.getSession().setMode(new SyntaxMode());
 		});
-	}	
+	}
 }
 
 function showControls(filename,writeperms){
@@ -69,17 +71,16 @@ function showControls(filename,writeperms){
 	if(writeperms=="true"){
 		editorbarhtml += '<button id="editor_save">'+t('files_texteditor','Save')+'</button><div class="separator"></div>';
 	}
-	editorbarhtml += '<label for="gotolineval">Go to line:</label><input stype="text" id="gotolineval"><label for="editorseachval">Search:</label><input type="text" name="editorsearchval" id="editorsearchval"><div class="separator"></div><button id="editor_close">'+t('files_texteditor','Close')+'</button></div>';
+	editorbarhtml += '<label for="editorseachval">Search:</label><input type="text" name="editorsearchval" id="editorsearchval"><div class="separator"></div><button id="editor_close">'+t('files_texteditor','Close')+'</button></div>';
 	// Change breadcrumb classes
 	$('#controls .last').removeClass('last');
 	$('#controls').append(editorbarhtml);
 	$('#editorcontrols').fadeIn('slow');
 }
- 
+
 function bindControlEvents(){
-	$("#editor_save").die('click',doFileSave).live('click',doFileSave);	
+	$("#editor_save").die('click',doFileSave).live('click',doFileSave);
 	$('#editor_close').die('click',hideFileEditor).live('click',hideFileEditor);
-	$('#gotolineval').die('keyup', goToLine).live('keyup', goToLine);
 	$('#editorsearchval').die('keyup', doSearch).live('keyup', doSearch);
 	$('#clearsearchbtn').die('click', resetSearch).live('click', resetSearch);
 	$('#nextsearchbtn').die('click', nextSearchResult).live('click', nextSearchResult);
@@ -91,19 +92,12 @@ function editorIsShown(){
 	return is_editor_shown;
 }
 
-// Moves the editor view to the line number speificed in #gotolineval
-function goToLine(){
-	// Go to the line specified
-	window.aceEditor.gotoLine($('#gotolineval').val());
-	
-}
-
 //resets the search
 function resetSearch(){
 	$('#editorsearchval').val('');
 	$('#nextsearchbtn').remove();
 	$('#clearsearchbtn').remove();
-	window.aceEditor.gotoLine(0);	
+	window.aceEditor.gotoLine(0);
 }
 
 // moves the cursor to the next search resukt
@@ -111,10 +105,10 @@ function nextSearchResult(){
 	window.aceEditor.findNext();
 }
 // Performs the initial search
-function doSearch(){	
+function doSearch(){
 	// check if search box empty?
 	if($('#editorsearchval').val()==''){
-		// Hide clear button	
+		// Hide clear button
 		window.aceEditor.gotoLine(0);
 		$('#nextsearchbtn').remove();
 		$('#clearsearchbtn').remove();
@@ -129,7 +123,7 @@ function doSearch(){
 			caseSensitive: false,
 			wholeWord: false,
 			regExp: false
-		});	
+		});
 		// Show next and clear buttons
 		// check if already there
 		if($('#nextsearchbtn').length==0){
@@ -161,16 +155,16 @@ function doFileSave(){
 					// Save failed
 					$('#editor_save').text(t('files_texteditor','Save'));
 					$('#editor_save').after('<p id="save_result" style="float: left">Failed to save file</p>');
-					$("#editor_save").live('click',doFileSave); 
+					$("#editor_save").live('click',doFileSave);
 				} else {
-					// Save OK	
+					// Save OK
 					// Update mtime
 					$('#editor').attr('data-mtime',jsondata.data.mtime);
-					$('#editor_save').text(t('files_texteditor','Save'));     
+					$('#editor_save').text(t('files_texteditor','Save'));
 					$("#editor_save").live('click',doFileSave);
 					// Update titles
 					$('#editor').attr('data-edited', 'false');
-					$('#breadcrumb_file').text($('#editor').attr('data-filename'));	
+					$('#breadcrumb_file').text($('#editor').attr('data-filename'));
 					document.title = $('#editor').attr('data-filename')+' - ownCloud';
 				}
 			},'json');
@@ -223,7 +217,7 @@ function showFileEditor(dir,filename){
 						window.aceEditor.getSession().on('change', function(){
 							if($('#editor').attr('data-edited')!='true'){
 								$('#editor').attr('data-edited', 'true');
-								$('#breadcrumb_file').text($('#breadcrumb_file').text()+' *');	
+								$('#breadcrumb_file').text($('#breadcrumb_file').text()+' *');
 								document.title = $('#editor').attr('data-filename')+' * - ownCloud';
 							}
 						});
@@ -243,7 +237,7 @@ function showFileEditor(dir,filename){
 // Fades out the editor.
 function hideFileEditor(){
 	if($('#editor').attr('data-edited') == 'true'){
-		// Hide, not remove	
+		// Hide, not remove
 		$('#editorcontrols').fadeOut('slow',function(){
 			// Check if there is a folder in the breadcrumb
 			if($('.crumb.ui-droppable').length){
@@ -255,7 +249,7 @@ function hideFileEditor(){
 			// Reset document title
 			document.title = "ownCloud";
 			$('.actions,#file_access_panel').fadeIn('slow');
-			$('table').fadeIn('slow');			
+			$('table').fadeIn('slow');
 		});
 		$('#notification').text(t('files_texteditor','There were unsaved changes, click here to go back'));
 		$('#notification').data('reopeneditor',true);
@@ -273,7 +267,7 @@ function hideFileEditor(){
 			// Reset document title
 			document.title = "ownCloud";
 			$('.actions,#file_access_panel').fadeIn('slow');
-			$('table').fadeIn('slow');			
+			$('table').fadeIn('slow');
 		});
 		is_editor_shown = false;
 	}
@@ -287,7 +281,7 @@ function reopenEditor(){
 		$('#editor').fadeIn('fast');
 		$('#editorcontrols').fadeIn('fast', function(){
 
-		});	
+		});
 	});
 	is_editor_shown  = true;
 }
diff --git a/apps/files_versioning/ajax/gethead.php b/apps/files_versioning/ajax/gethead.php
deleted file mode 100644
index cc93b7a1d17aa0ac33ab6410caa74c219269bf02..0000000000000000000000000000000000000000
--- a/apps/files_versioning/ajax/gethead.php
+++ /dev/null
@@ -1,12 +0,0 @@
-<?php
-/**
- * Copyright (c) 2011 Craig Roberts craig0990@googlemail.com
- * This file is licensed under the Affero General Public License version 3 or
- * later.
- */
-require_once('../../../lib/base.php');
-
-OC_JSON::checkLoggedIn();
-// Fetch current commit (or HEAD if not yet set)
-$head = OC_Preferences::getValue(OC_User::getUser(), 'files_versioning', 'head', 'HEAD');
-OC_JSON::encodedPrint(array("head" => $head));
diff --git a/apps/files_versioning/ajax/sethead.php b/apps/files_versioning/ajax/sethead.php
deleted file mode 100644
index d1b2df9b00ff1fae2236b2ef075111013027f74b..0000000000000000000000000000000000000000
--- a/apps/files_versioning/ajax/sethead.php
+++ /dev/null
@@ -1,14 +0,0 @@
-<?php
-/**
- * Copyright (c) 2011 Craig Roberts craig0990@googlemail.com
- * This file is licensed under the Affero General Public License version 3 or
- * later.
- */
-require_once('../../../lib/base.php');
-OC_JSON::checkLoggedIn();
-if(isset($_POST["file_versioning_head"])){
-	OC_Preferences::setValue(OC_User::getUser(), 'files_versioning', 'head', $_POST["file_versioning_head"]);
-	OC_JSON::success();
-}else{
-	OC_JSON::error();
-}
diff --git a/apps/files_versioning/appinfo/app.php b/apps/files_versioning/appinfo/app.php
deleted file mode 100644
index 24a8701dbb0f69c367d71f1c3657352f5a72251f..0000000000000000000000000000000000000000
--- a/apps/files_versioning/appinfo/app.php
+++ /dev/null
@@ -1,20 +0,0 @@
-<?php
-
-// Include required files
-require_once('apps/files_versioning/versionstorage.php');
-require_once('apps/files_versioning/versionwrapper.php');
-// Register streamwrapper for versioned:// paths
-stream_wrapper_register('versioned', 'OC_VersionStreamWrapper');
-
-// Add an entry in the app list for versioning and backup
-OC_App::register( array(
-  'order' => 10,
-  'id' => 'files_versioning',
-  'name' => 'Versioning and Backup' ));
-
-// Include stylesheets for the settings page
-OC_Util::addStyle( 'files_versioning', 'settings' );
-OC_Util::addScript('files_versioning','settings');
-
-// Register a settings section in the Admin > Personal page
-OC_APP::registerPersonal('files_versioning','settings');
diff --git a/apps/files_versioning/appinfo/info.xml b/apps/files_versioning/appinfo/info.xml
deleted file mode 100644
index 4c67894f9f91a6fddb207e30c115231446bf34fa..0000000000000000000000000000000000000000
--- a/apps/files_versioning/appinfo/info.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-<?xml version="1.0"?>
-<info>
-    <id>files_versioning</id>
-    <name>Versioning and Backup</name>
-    <version>1.0.0</version>
-    <licence>GPLv2</licence>
-    <author>Craig Roberts</author>
-    <require>3</require>
-    <description>Versions files using Git repositories, providing a simple backup facility. Currently in *beta* and explicitly without warranty of any kind.</description>
-	<types>
-		<filesystem/>
-	</types>
-</info>
diff --git a/apps/files_versioning/css/settings.css b/apps/files_versioning/css/settings.css
deleted file mode 100644
index afe2cd5508ffd320a7706239a9bd20484239eae2..0000000000000000000000000000000000000000
--- a/apps/files_versioning/css/settings.css
+++ /dev/null
@@ -1,3 +0,0 @@
-#file_versioning_commit_chzn {
-    width: 15em;
-}
diff --git a/apps/files_versioning/js/settings.js b/apps/files_versioning/js/settings.js
deleted file mode 100644
index 8dd13bac033529ff130c413d9f6f9efde96d9f90..0000000000000000000000000000000000000000
--- a/apps/files_versioning/js/settings.js
+++ /dev/null
@@ -1,25 +0,0 @@
-$(document).ready(function(){
-    $('#file_versioning_head').chosen();
-
-    $.getJSON(OC.filePath('files_versioning', 'ajax', 'gethead.php'), function(jsondata, status) {
-
-        if (jsondata.head == 'HEAD') {
-            // Most recent commit, do nothing
-        } else {
-            $("#file_versioning_head").val(jsondata.head);
-            // Trigger the chosen update call
-            // See http://harvesthq.github.com/chosen/
-            $("#file_versioning_head").trigger("liszt:updated");
-        }
-    });
-
-    $('#file_versioning_head').change(function() {
-
-        var data = $(this).serialize();
-        $.post( OC.filePath('files_versioning', 'ajax', 'sethead.php'), data, function(data){
-	        if(data == 'error'){
-		        console.log('Saving new HEAD failed');
-	        }
-        });
-    });
-});
diff --git a/apps/files_versioning/lib_granite.php b/apps/files_versioning/lib_granite.php
deleted file mode 100644
index 571e5cea63720d7b690ceb92c4959f2f8c7d232f..0000000000000000000000000000000000000000
--- a/apps/files_versioning/lib_granite.php
+++ /dev/null
@@ -1,12 +0,0 @@
-<?php
-
-require_once('granite/git/blob.php');
-require_once('granite/git/commit.php');
-require_once('granite/git/repository.php');
-require_once('granite/git/tag.php');
-require_once('granite/git/tree.php');
-require_once('granite/git/tree/node.php');
-require_once('granite/git/object/index.php');
-require_once('granite/git/object/raw.php');
-require_once('granite/git/object/loose.php');
-require_once('granite/git/object/packed.php');
diff --git a/apps/files_versioning/settings.php b/apps/files_versioning/settings.php
deleted file mode 100644
index 94af587a2158f74f1e1a65273115fa1118c540a8..0000000000000000000000000000000000000000
--- a/apps/files_versioning/settings.php
+++ /dev/null
@@ -1,34 +0,0 @@
-<?php
-
-// Get the full path to the repository folder (FIXME: hard-coded to 'Backup')
-$path = OC_Config::getValue('datadirectory', OC::$SERVERROOT.'/data')
-        . DIRECTORY_SEPARATOR
-        . OC_User::getUser()
-        . DIRECTORY_SEPARATOR
-        . 'files'
-        . DIRECTORY_SEPARATOR
-        . 'Backup'
-        . DIRECTORY_SEPARATOR
-        . '.git'
-        . DIRECTORY_SEPARATOR;
-
-$repository = new Granite\Git\Repository($path);
-
-$commits = array();
-// Fetch most recent 50 commits (FIXME - haven't tested this much)
-$commit = $repository->head();
-for ($i = 0; $i < 50; $i++) {
-    $commits[] = $commit;
-    $parents = $commit->parents();
-    if (count($parents) > 0) {
-        $parent = $parents[0];
-    } else {
-        break;
-    }
-
-    $commit = $repository->factory('commit', $parent);
-}
-
-$tmpl = new OC_Template( 'files_versioning', 'settings');
-$tmpl->assign('commits', $commits);
-return $tmpl->fetchPage();
diff --git a/apps/files_versioning/templates/settings.php b/apps/files_versioning/templates/settings.php
deleted file mode 100644
index 17f4cc7f77f677997372998fb5887753d1b7d3e4..0000000000000000000000000000000000000000
--- a/apps/files_versioning/templates/settings.php
+++ /dev/null
@@ -1,12 +0,0 @@
-<fieldset id="status_list" class="personalblock">
-	<strong>Versioning and Backup</strong><br>
-	<p><em>Please note: Backing up large files (around 16MB+) will cause your backup history to grow very large, very quickly.</em></p>
-	<label class="bold">Backup Folder</label>
-	<select name="file_versioning_head" id="file_versioning_head">
-	<?php
-        foreach ($_['commits'] as $commit):
-            echo '<option value="' . $commit->sha() . '">' . $commit->message() . '</option>';
-        endforeach;
-	?>
-	</select>
-</fieldset>
diff --git a/apps/files_versioning/versionstorage.php b/apps/files_versioning/versionstorage.php
deleted file mode 100644
index d083e623df94ebf9c72cf4503cb1449cd7358d27..0000000000000000000000000000000000000000
--- a/apps/files_versioning/versionstorage.php
+++ /dev/null
@@ -1,386 +0,0 @@
-<?php
-/**
- * ownCloud file storage implementation for Git repositories
- * @author Craig Roberts
- * @copyright 2012 Craig Roberts craig0990@googlemail.com
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or any later version.
- *
- * This library 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 AFFERO GENERAL PUBLIC LICENSE for more details.
- *
- * You should have received a copy of the GNU Affero General Public
- * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-// Include Granite
-require_once('lib_granite.php');
-
-// Create a top-level 'Backup' directory if it does not already exist
-$user = OC_User::getUser();
-if (OC_Filesystem::$loaded and !OC_Filesystem::is_dir('/Backup')) {
-    OC_Filesystem::mkdir('/Backup');
-    OC_Preferences::setValue(OC_User::getUser(), 'files_versioning', 'head', 'HEAD');
-}
-
-// Generate the repository path (currently using 'full' repositories, as opposed to bare ones)
-$repo_path = DIRECTORY_SEPARATOR
-    . OC_User::getUser()
-    . DIRECTORY_SEPARATOR
-    . 'files'
-    . DIRECTORY_SEPARATOR
-    . 'Backup';
-
-// Mount the 'Backup' folder using the versioned storage provider below
-OC_Filesystem::mount('OC_Filestorage_Versioned', array('repo'=>$repo_path), $repo_path . DIRECTORY_SEPARATOR);
-
-class OC_Filestorage_Versioned extends OC_Filestorage {
-
-    /**
-     * Holds an instance of Granite\Git\Repository
-     */
-    protected $repo;
-
-    /**
-     * Constructs a new OC_Filestorage_Versioned instance, expects an associative
-     * array with a `repo` key set to the path of the repository's `.git` folder
-     *
-     * @param array $parameters An array containing the key `repo` pointing to the
-     *                             repository path.
-     */
-    public function __construct($parameters) {
-        // Get the full path to the repository folder
-        $path = OC_Config::getValue('datadirectory', OC::$SERVERROOT.'/data')
-                . $parameters['repo']
-                . DIRECTORY_SEPARATOR
-                . '.git'
-                . DIRECTORY_SEPARATOR;
-
-        try {
-            // Attempt to load the repository
-            $this->repo = new Granite\Git\Repository($path);
-        } catch (InvalidArgumentException $e) {
-            // $path is not a valid Git repository, we must create one
-            Granite\Git\Repository::init($path);
-
-            // Load the newly-initialised repository
-            $this->repo = new Granite\Git\Repository($path);
-
-            /**
-             * Create an initial commit with a README file
-             * FIXME: This functionality should be transferred to the Granite library
-             */
-            $blob = new Granite\Git\Blob($this->repo->path());
-            $blob->content('Your Backup directory is now ready for use.');
-
-            // Create a new tree to hold the README file
-            $tree = $this->repo->factory('tree');
-            // Create a tree node to represent the README blob
-            $tree_node = new Granite\Git\Tree\Node('README', '100644', $blob->sha());
-            $tree->nodes(array($tree_node->name() => $tree_node));
-
-            // Create an initial commit
-            $commit = new Granite\Git\Commit($this->repo->path());
-            $user_string = OC_User::getUser() . ' ' . time() . ' +0000';
-            $commit->author($user_string);
-            $commit->committer($user_string);
-            $commit->message('Initial commit');
-            $commit->tree($tree);
-
-            // Write it all to disk
-            $blob->write();
-            $tree->write();
-            $commit->write();
-
-            // Update the HEAD for the 'master' branch
-            $this->repo->head('master', $commit->sha());
-        }
-
-        // Update the class pointer to the HEAD
-        $head = OC_Preferences::getValue(OC_User::getUser(), 'files_versioning', 'head', 'HEAD');
-
-        // Load the most recent commit if the preference is not set
-        if ($head == 'HEAD') {
-            $this->head = $this->repo->head()->sha();
-        } else {
-            $this->head = $head;
-        }
-    }
-
-    public function mkdir($path) {
-        if (mkdir("versioned:/{$this->repo->path()}$path#{$this->head}")) {
-            $this->head = $this->repo->head()->sha();
-            OC_Preferences::setValue(OC_User::getUser(), 'files_versioning', 'head', $head);
-            return true;
-        }
-
-        return false;
-    }
-
-    public function rmdir($path) {
-
-    }
-
-    /**
-     * Returns a directory handle to the requested path, or FALSE on failure
-     *
-     * @param string $path The directory path to open
-     *
-     * @return boolean|resource A directory handle, or FALSE on failure
-     */
-    public function opendir($path) {
-        return opendir("versioned:/{$this->repo->path()}$path#{$this->head}");
-    }
-
-    /**
-     * Returns TRUE if $path is a directory, or FALSE if not
-     *
-     * @param string $path The path to check
-     *
-     * @return boolean
-     */
-    public function is_dir($path) {
-        return $this->filetype($path) == 'dir';
-    }
-
-    /**
-     * Returns TRUE if $path is a file, or FALSE if not
-     *
-     * @param string $path The path to check
-     *
-     * @return boolean
-     */
-    public function is_file($path) {
-        return $this->filetype($path) == 'file';
-    }
-
-    public function stat($path)
-	{
-	    return stat("versioned:/{$this->repo->path()}$path#{$this->head}");
-    }
-
-    /**
-     * Returns the strings 'dir' or 'file', depending on the type of $path
-     *
-     * @param string $path The path to check
-     *
-     * @return string Returns 'dir' if a directory, 'file' otherwise
-     */
-    public function filetype($path) {
-	    if ($path == "" || $path == "/") {
-	        return 'dir';
-        } else {
-            if (substr($path, -1) == '/') {
-                $path = substr($path, 0, -1);
-            }
-
-            $node = $this->tree_search($this->repo, $this->repo->factory('commit', $this->head)->tree(), $path);
-
-            // Does it exist, or is it new?
-            if ($node == null) {
-                // New file
-                return 'file';
-            } else {
-                // Is it a tree?
-                try {
-                    $this->repo->factory('tree', $node);
-                    return 'dir';
-                } catch (InvalidArgumentException $e) {
-                    // Nope, must be a blob
-                    return 'file';
-                }
-            }
-        }
-    }
-
-    public function filesize($path) {
-        return filesize("versioned:/{$this->repo->path()}$path#{$this->head}");
-    }
-
-    /**
-     * Returns a boolean value representing whether $path is readable
-     *
-     * @param string $path The path to check
-     *(
-     * @return boolean Whether or not the path is readable
-     */
-    public function is_readable($path) {
-        return true;
-    }
-
-    /**
-     * Returns a boolean value representing whether $path is writable
-     *
-     * @param string $path The path to check
-     *(
-     * @return boolean Whether or not the path is writable
-     */
-    public function is_writable($path) {
-
-        $head = OC_Preferences::getValue(OC_User::getUser(), 'files_versioning', 'head', 'HEAD');
-        if ($head !== 'HEAD' && $head !== $this->repo->head()->sha()) {
-            // Cannot modify previous commits
-            return false;
-        }
-        return true;
-    }
-
-    /**
-     * Returns a boolean value representing whether $path exists
-     *
-     * @param string $path The path to check
-     *(
-     * @return boolean Whether or not the path exists
-     */
-    public function file_exists($path) {
-        return file_exists("versioned:/{$this->repo->path()}$path#{$this->head}");
-    }
-
-    /**
-     * Returns an integer value representing the inode change time
-     * (NOT IMPLEMENTED)
-     *
-     * @param string $path The path to check
-     *(
-     * @return int Timestamp of the last inode change
-     */
-    public function filectime($path) {
-        return -1;
-    }
-
-    /**
-     * Returns an integer value representing the file modification time
-     *
-     * @param string $path The path to check
-     *(
-     * @return int Timestamp of the last file modification
-     */
-    public function filemtime($path) {
-        return filemtime("versioned:/{$this->repo->path()}$path#{$this->head}");
-    }
-
-    public function file_get_contents($path) {
-        return file_get_contents("versioned:/{$this->repo->path()}$path#{$this->head}");
-    }
-
-    public function file_put_contents($path, $data) {
-        $success = file_put_contents("versioned:/{$this->repo->path()}$path#{$this->head}", $data);
-        if ($success !== false) {
-            // Update the HEAD in the preferences
-            OC_Preferences::setValue(OC_User::getUser(), 'files_versioning', 'head', $this->repo->head()->sha());
-            return $success;
-        }
-
-        return false;
-    }
-
-    public function unlink($path) {
-
-    }
-
-    public function rename($path1, $path2) {
-
-    }
-
-    public function copy($path1, $path2) {
-
-    }
-
-    public function fopen($path, $mode) {
-	    return fopen("versioned:/{$this->repo->path()}$path#{$this->head}", $mode);
-    }
-
-    public function getMimeType($path) {
-        if ($this->filetype($path) == 'dir') {
-	        return 'httpd/unix-directory';
-	    } elseif ($this->filesize($path) == 0) {
-	        // File's empty, returning text/plain allows opening in the web editor
-	        return 'text/plain';
-	    } else {
-            $finfo = new finfo(FILEINFO_MIME_TYPE);
-            /**
-             * We need to represent the repository path, the file path, and the
-             * revision, which can be simply achieved with a convention of using
-             * `.git` in the repository directory (bare or not) and the '#part'
-             * segment of a URL to specify the revision. For example
-             *
-             * versioned://var/www/myrepo.git/docs/README.md#HEAD ('bare' repo)
-             * versioned://var/www/myrepo/.git/docs/README.md#HEAD ('full' repo)
-             * versioned://var/www/myrepo/.git/docs/README.md#6a8f...8a54 ('full' repo and SHA-1 commit ID)
-             */
-            $mime = $finfo->buffer(file_get_contents("versioned:/{$this->repo->path()}$path#{$this->head}"));
-            return $mime;
-	    }
-    }
-
-    /**
-     * Generates a hash based on the file contents
-     *
-     * @param string $type The hashing algorithm to use (e.g. 'md5', 'sha256', etc.)
-     * @param string $path The file to be hashed
-     * @param boolean $raw Outputs binary data if true, lowercase hex digits otherwise
-     *
-     * @return string Hashed string representing the file contents
-     */
-    public function hash($type, $path, $raw) {
-        return hash($type, file_get_contents($path), $raw);
-    }
-
-    public function free_space($path) {
-    }
-
-    public function search($query) {
-
-    }
-
-    public function touch($path, $mtime=null) {
-
-    }
-
-
-    public function getLocalFile($path) {
-    }
-
-    /**
-     * Recursively searches a tree for a path, returning FALSE if is not found
-     * or an SHA-1 id if it is found.
-     *
-     * @param string  $repo  The repository containing the tree object
-     * @param string  $tree  The tree object to search
-     * @param string  $path  The path to search for (relative to the tree)
-     * @param int     $depth The depth of the current search (for recursion)
-     *
-     * @return string|boolean The SHA-1 id of the sub-tree
-     */
-    private function tree_search($repo, $tree, $path, $depth = 0)
-    {
-        $paths = array_values(explode(DIRECTORY_SEPARATOR, $path));
-
-        $current_path = $paths[$depth];
-
-        $nodes = $tree->nodes();
-        foreach ($nodes as $node) {
-            if ($node->name() == $current_path) {
-
-                if (count($paths)-1 == $depth) {
-                    // Stop, found it
-                    return $node->sha();
-                }
-
-                // Recurse if necessary
-                if ($node->isDirectory()) {
-                    $tree = $this->repo->factory('tree', $node->sha());
-                    return $this->tree_search($repo, $tree, $path, $depth + 1);
-                }
-            }
-        }
-
-        return false;
-    }
-
-}
diff --git a/apps/files_versioning/versionwrapper.php b/apps/files_versioning/versionwrapper.php
deleted file mode 100644
index b83a4fd3b2246293767b908005adcba837aebe6e..0000000000000000000000000000000000000000
--- a/apps/files_versioning/versionwrapper.php
+++ /dev/null
@@ -1,686 +0,0 @@
-<?php
-
-final class OC_VersionStreamWrapper {
-
-    /**
-     * Determines whether or not to log debug messages with `OC_Log::write()`
-     */
-    private $debug = true;
-
-    /**
-     * The name of the ".empty" files created in new directories
-     */
-    const EMPTYFILE = '.empty';
-
-    /**
-     * Stores the current position for `readdir()` etc. calls
-     */
-    private $dir_position = 0;
-
-    /**
-     * Stores the current position for `fread()`, `fseek()` etc. calls
-     */
-    private $file_position = 0;
-
-    /**
-     * Stores the current directory tree for `readdir()` etc. directory traversal
-     */
-    private $tree;
-
-    /**
-     * Stores the current file for `fread()`, `fseek()`, etc. calls
-     */
-    private $blob;
-
-    /**
-     * Stores the current commit for `fstat()`, `stat()`, etc. calls
-     */
-    private $commit;
-
-    /**
-     * Stores the current path for `fwrite()`, `file_put_contents()` etc. calls
-     */
-    private $path;
-
-    /**
-     * Close directory handle
-     */
-    public function dir_closedir() {
-        unset($this->tree);
-        return true;
-    }
-
-    /**
-     * Open directory handle
-     */
-    public function dir_opendir($path, $options) {
-        // Parse the URL into a repository directory, file path and commit ID
-        list($this->repo, $repo_file, $this->commit) = $this->parse_url($path);
-
-        if ($repo_file == '' || $repo_file == '/') {
-            // Set the tree property for the future `readdir()` etc. calls
-            $this->tree = array_values($this->commit->tree()->nodes());
-            return true;
-        } elseif ($this->tree_search($this->repo, $this->commit->tree(), $repo_file) !== false) {
-            // Something exists at this path, is it a directory though?
-            try {
-                $tree = $this->repo->factory(
-                    'tree',
-                    $this->tree_search($this->repo, $this->commit->tree(), $repo_file)
-                );
-                $this->tree = array_values($tree->nodes());
-                return true;
-            } catch (InvalidArgumentException $e) {
-                // Trying to call `opendir()` on a file, return false below
-            }
-        }
-
-        // Unable to find the directory, return false
-        return false;
-    }
-
-    /**
-     * Read entry from directory handle
-     */
-    public function dir_readdir() {
-        return isset($this->tree[$this->dir_position])
-               ? $this->tree[$this->dir_position++]->name()
-               : false;
-    }
-
-    /**
-     * Rewind directory handle
-     */
-    public function dir_rewinddir() {
-        $this->dir_position = 0;
-    }
-
-    /**
-     * Create a directory
-     * Git doesn't track empty directories, so a ".empty" file is added instead
-     */
-    public function mkdir($path, $mode, $options) {
-        // Parse the URL into a repository directory, file path and commit ID
-        list($this->repo, $repo_file, $this->commit) = $this->parse_url($path);
-
-        // Create an empty file for Git
-        $empty = new Granite\Git\Blob($this->repo->path());
-        $empty->content('');
-        $empty->write();
-
-        if (dirname($repo_file) == '.') {
-            // Adding a new directory to the root tree
-            $tree = $this->repo->head()->tree();
-        } else {
-            $tree = $this->repo->factory('tree', $this->tree_search(
-                    $this->repo, $this->repo->head()->tree(), dirname($repo_file)
-                )
-            );
-        }
-
-        // Create our new tree, with our empty file
-        $dir = $this->repo->factory('tree');
-        $nodes = array();
-        $nodes[self::EMPTYFILE] = new Granite\Git\Tree\Node(self::EMPTYFILE, '100644', $empty->sha());
-        $dir->nodes($nodes);
-        $dir->write();
-
-        // Add our new tree to its parent
-        $nodes = $tree->nodes();
-        $nodes[basename($repo_file)] = new Granite\Git\Tree\Node(basename($repo_file), '040000', $dir->sha());
-        $tree->nodes($nodes);
-        $tree->write();
-
-        // We need to recursively update each parent tree, since they are all
-        // hashed and the changes will cascade back up the chain
-
-        // So, we're currently at the bottom-most directory
-        $current_dir = dirname($repo_file);
-        $previous_tree = $tree;
-
-        if ($current_dir !== '.') {
-            do {
-                // Determine the parent directory
-                $previous_dir = $current_dir;
-                $current_dir = dirname($current_dir);
-
-                $current_tree = $current_dir !== '.'
-                                ? $this->repo->factory(
-                                      'tree', $this->tree_search(
-                                          $this->repo,
-                                          $this->repo->head()->tree(),
-                                          $current_dir
-                                      )
-                                  )
-                                : $this->repo->head()->tree();
-
-                $current_nodes = $current_tree->nodes();
-                $current_nodes[basename($previous_dir)] = new Granite\Git\Tree\Node(
-                    basename($previous_dir), '040000', $previous_tree->sha()
-                );
-                $current_tree->nodes($current_nodes);
-                $current_tree->write();
-
-                $previous_tree = $current_tree;
-            } while ($current_dir !== '.');
-
-            $tree = $previous_tree;
-        }
-
-        // Create a new commit to represent this write
-        $commit = $this->repo->factory('commit');
-        $username = OC_User::getUser();
-        $user_string = $username . ' ' . time() . ' +0000';
-        $commit->author($user_string);
-        $commit->committer($user_string);
-        $commit->message("$username created the `$repo_file` directory, " . date('d F Y H:i', time()) . '.');
-        $commit->parents(array($this->repo->head()->sha()));
-        $commit->tree($tree);
-
-        // Write it to disk
-        $commit->write();
-
-        // Update the HEAD for the 'master' branch
-        $this->repo->head('master', $commit->sha());
-
-        return true;
-    }
-
-    /**
-     * Renames a file or directory
-     */
-    public function rename($path_from, $path_to) {
-
-    }
-
-    /**
-     * Removes a directory
-     */
-    public function rmdir($path, $options) {
-
-    }
-
-    /**
-     * Retrieve the underlaying resource (NOT IMPLEMENTED)
-     */
-    public function stream_cast($cast_as) {
-        return false;
-    }
-
-    /**
-     * Close a resource
-     */
-    public function stream_close() {
-        unset($this->blob);
-        return true;
-    }
-
-    /**
-     * Tests for end-of-file on a file pointer
-     */
-    public function stream_eof() {
-        return !($this->file_position < strlen($this->blob));
-    }
-
-    /**
-     * Flushes the output (NOT IMPLEMENTED)
-     */
-    public function stream_flush() {
-        return false;
-    }
-
-    /**
-     * Advisory file locking (NOT IMPLEMENTED)
-     */
-    public function stream_lock($operation) {
-        return false;
-    }
-
-    /**
-     * Change stream options (NOT IMPLEMENTED)
-     * Called in response to `chgrp()`, `chown()`, `chmod()` and `touch()`
-     */
-    public function stream_metadata($path, $option, $var) {
-        return false;
-    }
-
-    /**
-     * Opens file or URL
-     */
-    public function stream_open($path, $mode, $options, &$opened_path) {
-        // Store the path, so we can use it later in `stream_write()` if necessary
-        $this->path = $path;
-        // Parse the URL into a repository directory, file path and commit ID
-        list($this->repo, $repo_file, $this->commit) = $this->parse_url($path);
-
-        $file = $this->tree_search($this->repo, $this->commit->tree(), $repo_file);
-        if ($file !== false) {
-            try {
-                $this->blob = $this->repo->factory('blob', $file)->content();
-                return true;
-            } catch (InvalidArgumentException $e) {
-                // Trying to open a directory, return false below
-            }
-        } elseif ($mode !== 'r') {
-            // All other modes allow opening for reading and writing, clearly
-            // some 'write' files may not exist yet...
-            return true;
-        }
-
-        // File could not be found or is not actually a file
-        return false;
-    }
-
-    /**
-     * Read from stream
-     */
-    public function stream_read($count) {
-        // Fetch the remaining set of bytes
-        $bytes = substr($this->blob, $this->file_position, $count);
-
-        // If EOF or empty string, return false
-        if ($bytes == '' || $bytes == false) {
-            return false;
-        }
-
-        // If $count does not extend past EOF, add $count to stream offset
-        if ($this->file_position + $count < strlen($this->blob)) {
-            $this->file_position += $count;
-        } else {
-            // Otherwise return all remaining bytes
-            $this->file_position = strlen($this->blob);
-        }
-
-        return $bytes;
-    }
-
-    /**
-     * Seeks to specific location in a stream
-     */
-    public function stream_seek($offset, $whence = SEEK_SET) {
-        $new_offset = false;
-
-        switch ($whence)
-        {
-            case SEEK_SET:
-                $new_offset = $offset;
-            break;
-            case SEEK_CUR:
-                $new_offset = $this->file_position += $offset;
-            break;
-            case SEEK_END:
-                $new_offset = strlen($this->blob) + $offset;
-            break;
-        }
-
-        $this->file_position = $offset;
-
-        return ($new_offset !== false);
-    }
-
-    /**
-     * Change stream options (NOT IMPLEMENTED)
-     */
-    public function stream_set_option($option, $arg1, $arg2) {
-        return false;
-    }
-
-    /**
-     * Retrieve information about a file resource (NOT IMPLEMENTED)
-     */
-    public function stream_stat() {
-
-    }
-
-    /**
-     * Retrieve the current position of a stream
-     */
-    public function stream_tell() {
-        return $this->file_position;
-    }
-
-    /**
-     * Truncate stream
-     */
-    public function stream_truncate($new_size) {
-
-    }
-
-    /**
-     * Write to stream
-     * FIXME: Could use heavy refactoring
-     */
-    public function stream_write($data) {
-        /**
-         * FIXME: This also needs to be added to Granite, in the form of `add()`,
-         * `rm()` and `commit()` calls
-         */
-
-        // Parse the URL into a repository directory, file path and commit ID
-        list($this->repo, $repo_file, $this->commit) = $this->parse_url($this->path);
-
-        $node = $this->tree_search($this->repo, $this->commit->tree(), $repo_file);
-
-        if ($node !== false) {
-            // File already exists, attempting modification of existing tree
-            try {
-                $this->repo->factory('blob', $node);
-
-                // Create our new blob with the provided $data
-                $blob = $this->repo->factory('blob');
-                $blob->content($data);
-                $blob->write();
-
-                // We know the tree exists, so strip the filename from the path and
-                // find it...
-
-                if (dirname($repo_file) == '.' || dirname($repo_file) == '') {
-                    // Root directory
-                    $tree = $this->repo->head()->tree();
-                } else {
-                    // Sub-directory
-                    $tree = $this->repo->factory('tree', $this->tree_search(
-                            $this->repo,
-                            $this->repo->head()->tree(),
-                            dirname($repo_file)
-                        )
-                    );
-                }
-
-                // Replace the old blob with our newly modified one
-                $tree_nodes = $tree->nodes();
-                $tree_nodes[basename($repo_file)] = new Granite\Git\Tree\Node(
-                    basename($repo_file), '100644', $blob->sha()
-                );
-                $tree->nodes($tree_nodes);
-                $tree->write();
-
-                // We need to recursively update each parent tree, since they are all
-                // hashed and the changes will cascade back up the chain
-
-                // So, we're currently at the bottom-most directory
-                $current_dir = dirname($repo_file);
-                $previous_tree = $tree;
-
-                if ($current_dir !== '.') {
-                    do {
-                        // Determine the parent directory
-                        $previous_dir = $current_dir;
-                        $current_dir = dirname($current_dir);
-
-                        $current_tree = $current_dir !== '.'
-                                        ? $this->repo->factory(
-                                              'tree', $this->tree_search(
-                                                  $this->repo,
-                                                  $this->repo->head()->tree(),
-                                                  $current_dir
-                                              )
-                                          )
-                                        : $this->repo->head()->tree();
-
-                        $current_nodes = $current_tree->nodes();
-                        $current_nodes[basename($previous_dir)] = new Granite\Git\Tree\Node(
-                            basename($previous_dir), '040000', $previous_tree->sha()
-                        );
-                        $current_tree->nodes($current_nodes);
-                        $current_tree->write();
-
-                        $previous_tree = $current_tree;
-                    } while ($current_dir !== '.');
-                }
-
-                // Create a new commit to represent this write
-                $commit = $this->repo->factory('commit');
-                $username = OC_User::getUser();
-                $user_string = $username . ' ' . time() . ' +0000';
-                $commit->author($user_string);
-                $commit->committer($user_string);
-                $commit->message("$username modified the `$repo_file` file, " . date('d F Y H:i', time()) . '.');
-                $commit->parents(array($this->repo->head()->sha()));
-                $commit->tree($previous_tree);
-
-                // Write it to disk
-                $commit->write();
-
-                // Update the HEAD for the 'master' branch
-                $this->repo->head('master', $commit->sha());
-
-                // If we made it this far, write was successful - update the stream
-                // position and return the number of bytes written
-                $this->file_position += strlen($data);
-                return strlen($data);
-
-            } catch (InvalidArgumentException $e) {
-                // Attempting to write to a directory or other error, fail
-                return 0;
-            }
-        } else {
-            // File does not exist, needs to be created
-
-            // Create our new blob with the provided $data
-            $blob = $this->repo->factory('blob');
-            $blob->content($data);
-            $blob->write();
-
-            if (dirname($repo_file) == '.') {
-                // Trying to add a new file to the root tree, nice and easy
-                $tree = $this->repo->head()->tree();
-                $tree_nodes = $tree->nodes();
-                $tree_nodes[basename($repo_file)] = new Granite\Git\Tree\Node(
-                    basename($repo_file), '100644', $blob->sha()
-                );
-                $tree->nodes($tree_nodes);
-                $tree->write();
-            } else {
-                // Trying to add a new file to a subdirectory, try and find it
-                $tree = $this->repo->factory('tree', $this->tree_search(
-                        $this->repo, $this->repo->head()->tree(), dirname($repo_file)
-                    )
-                );
-
-                // Add the blob to the tree
-                $nodes = $tree->nodes();
-                $nodes[basename($repo_file)] =  new Granite\Git\Tree\Node(
-                    basename($repo_file), '100644', $blob->sha()
-                );
-                $tree->nodes($nodes);
-                $tree->write();
-
-                // We need to recursively update each parent tree, since they are all
-                // hashed and the changes will cascade back up the chain
-
-                // So, we're currently at the bottom-most directory
-                $current_dir = dirname($repo_file);
-                $previous_tree = $tree;
-
-                if ($current_dir !== '.') {
-                    do {
-                        // Determine the parent directory
-                        $previous_dir = $current_dir;
-                        $current_dir = dirname($current_dir);
-
-                        $current_tree = $current_dir !== '.'
-                                        ? $this->repo->factory(
-                                              'tree', $this->tree_search(
-                                                  $this->repo,
-                                                  $this->repo->head()->tree(),
-                                                  $current_dir
-                                              )
-                                          )
-                                        : $this->repo->head()->tree();
-
-                        $current_nodes = $current_tree->nodes();
-                        $current_nodes[basename($previous_dir)] = new Granite\Git\Tree\Node(
-                            basename($previous_dir), '040000', $previous_tree->sha()
-                        );
-                        $current_tree->nodes($current_nodes);
-                        $current_tree->write();
-
-                        $previous_tree = $current_tree;
-                    } while ($current_dir !== '.');
-
-                    $tree = $previous_tree;
-                }
-            }
-
-            // Create a new commit to represent this write
-            $commit = $this->repo->factory('commit');
-            $username = OC_User::getUser();
-            $user_string = $username . ' ' . time() . ' +0000';
-            $commit->author($user_string);
-            $commit->committer($user_string);
-            $commit->message("$username created the `$repo_file` file, " . date('d F Y H:i', time()) . '.');
-            $commit->parents(array($this->repo->head()->sha()));
-            $commit->tree($tree); // Top-level tree (NOT the newly modified tree)
-
-            // Write it to disk
-            $commit->write();
-
-            // Update the HEAD for the 'master' branch
-            $this->repo->head('master', $commit->sha());
-
-            // If we made it this far, write was successful - update the stream
-            // position and return the number of bytes written
-            $this->file_position += strlen($data);
-            return strlen($data);
-        }
-
-        // Write failed
-        return 0;
-    }
-
-    /**
-     * Delete a file
-     */
-    public function unlink($path) {
-
-    }
-
-    /**
-     * Retrieve information about a file
-     */
-    public function url_stat($path, $flags) {
-        // Parse the URL into a repository directory, file path and commit ID
-        list($this->repo, $repo_file, $this->commit) = $this->parse_url($path);
-
-        $node = $this->tree_search($this->repo, $this->commit->tree(), $repo_file);
-
-        if ($node == false && $this->commit->sha() == $this->repo->head()->sha()) {
-            // A new file - no information available
-            $size = 0;
-            $mtime = -1;
-        } else {
-
-            // Is it a directory?
-            try {
-                $this->repo->factory('tree', $node);
-                $size = 4096; // FIXME
-            } catch (InvalidArgumentException $e) {
-                // Must be a file
-                $size = strlen(file_get_contents($path));
-            }
-
-            // Parse the timestamp from the commit message
-	        preg_match('/[0-9]{10}+/', $this->commit->committer(), $matches);
-	        $mtime = $matches[0];
-        }
-
-	    $stat["dev"] = "";
-	    $stat["ino"] = "";
-	    $stat["mode"] = "";
-	    $stat["nlink"] = "";
-	    $stat["uid"] = "";
-	    $stat["gid"] = "";
-	    $stat["rdev"] = "";
-	    $stat["size"] = $size;
-	    $stat["atime"] = $mtime;
-	    $stat["mtime"] = $mtime;
-	    $stat["ctime"] = $mtime;
-	    $stat["blksize"] = "";
-	    $stat["blocks"] = "";
-
-	    return $stat;
-    }
-
-    /**
-     * Debug function for development purposes
-     */
-    private function debug($message, $level = OC_Log::DEBUG)
-    {
-        if ($this->debug) {
-            OC_Log::write('files_versioning', $message, $level);
-        }
-    }
-
-    /**
-     * Parses a URL of the form:
-     * `versioned://path/to/git/repository/.git/path/to/file#SHA-1-commit-id`
-     * FIXME: Will throw an InvalidArgumentException if $path is invaid
-     *
-     * @param string $path The path to parse
-     *
-     * @return array An array containing an instance of Granite\Git\Repository,
-     *               the file path, and an instance of Granite\Git\Commit
-     * @throws InvalidArgumentException If the repository cannot be loaded
-     */
-    private function parse_url($path)
-    {
-        preg_match('/\/([A-Za-z0-9\/]+\.git\/)([A-Za-z0-9\/\.\/]*)(#([A-Fa-f0-9]+))*/', $path, $matches);
-
-        // Load up the repo
-        $repo = new \Granite\Git\Repository($matches[1]);
-        // Parse the filename (stripping any trailing slashes)
-        $repo_file = $matches[2];
-        if (substr($repo_file, -1) == '/') {
-            $repo_file = substr($repo_file, 0, -1);
-        }
-
-        // Default to HEAD if no commit is provided
-        $repo_commit = isset($matches[4])
-                       ? $matches[4]
-                       : $repo->head()->sha();
-
-        // Load the relevant commit
-        $commit = $repo->factory('commit', $repo_commit);
-
-        return array($repo, $repo_file, $commit);
-    }
-
-    /**
-     * Recursively searches a tree for a path, returning FALSE if is not found
-     * or an SHA-1 id if it is found.
-     *
-     * @param string  $repo  The repository containing the tree object
-     * @param string  $tree  The tree object to search
-     * @param string  $path  The path to search for (relative to the tree)
-     * @param int     $depth The depth of the current search (for recursion)
-     *
-     * @return string|boolean The SHA-1 id of the sub-tree
-     */
-    private function tree_search($repo, $tree, $path, $depth = 0)
-    {
-        $paths = array_values(explode(DIRECTORY_SEPARATOR, $path));
-
-        $current_path = $paths[$depth];
-
-        $nodes = $tree->nodes();
-        foreach ($nodes as $node) {
-            if ($node->name() == $current_path) {
-
-                if (count($paths)-1 == $depth) {
-                    // Stop, found it
-                    return $node->sha();
-                }
-
-                // Recurse if necessary
-                if ($node->isDirectory()) {
-                    $tree = $this->repo->factory('tree', $node->sha());
-                    return $this->tree_search($repo, $tree, $path, $depth + 1);
-                }
-            }
-        }
-
-        return false;
-    }
-
-}
diff --git a/apps/files_versions/ajax/getVersions.php b/apps/files_versions/ajax/getVersions.php
new file mode 100755
index 0000000000000000000000000000000000000000..5949c32ed16746b38cceef218508e5c540d003b1
--- /dev/null
+++ b/apps/files_versions/ajax/getVersions.php
@@ -0,0 +1,61 @@
+<?php
+
+require_once('../../../lib/base.php');
+OCP\JSON::checkAppEnabled('files_versions');
+require_once('../versions.php');
+
+$userDirectory = "/".OCP\USER::getUser()."/files";
+$source = $_GET['source'];
+$source = strip_tags( $source );
+
+if( OCA_Versions\Storage::isversioned( $source ) ) {
+
+	$count=5; //show the newest revisions
+	$versions = OCA_Versions\Storage::getversions( $source, $count);
+	$versionsFormatted = array();
+	
+	foreach ( $versions AS $version ) {
+	
+		$versionsFormatted[] = OCP\Util::formatDate( $version );
+		
+	}
+
+	$versionsSorted = array_reverse( $versionsFormatted );
+	
+	if ( !empty( $versionsSorted ) ) {
+		OCP\JSON::encodedPrint($versionsSorted);
+	}
+	
+}else{
+
+	return;
+	
+}
+
+// $path = $source;
+// $users = array();
+// if ($users = OC_Share::getMySharedItem($source)) {
+// 	for ($i = 0; $i < count($users); $i++) {
+// 		if ($users[$i]['uid_shared_with'] == OC_Share::PUBLICLINK) {
+// 			$users[$i]['token'] = OC_Share::getTokenFromSource($source);
+// 		}
+// 	}
+// }
+// $source = dirname($source);
+// while ($source != "" && $source != "/" && $source != "." && $source != $userDirectory) {
+// 	if ($values = OC_Share::getMySharedItem($source)) {
+// 		$values = array_values($values);
+// 		$parentUsers = array();
+// 		for ($i = 0; $i < count($values); $i++) {
+// 			if ($values[$i]['uid_shared_with'] == OC_Share::PUBLICLINK) {
+// 				$values[$i]['token'] = OC_Share::getTokenFromSource($source)."&path=".substr($path, strlen($source));
+// 			}
+// 			$parentUsers[basename($source)."-".$i] = $values[$i];
+// 		}
+// 		$users = array_merge($users, $parentUsers);
+// 	}
+// 	$source = dirname($source);
+// }
+// if (!empty($users)) {
+// 	OCP\JSON::encodedPrint($users);
+// }
diff --git a/apps/files_versions/ajax/rollbackVersion.php b/apps/files_versions/ajax/rollbackVersion.php
new file mode 100755
index 0000000000000000000000000000000000000000..3faaafe935daf2a9d82134e48cbff20e7baee59f
--- /dev/null
+++ b/apps/files_versions/ajax/rollbackVersion.php
@@ -0,0 +1,26 @@
+<?php
+
+require_once('../../../lib/base.php');
+OCP\JSON::checkAppEnabled('files_versions');
+require_once('../versions.php');
+
+$userDirectory = "/".OCP\USER::getUser()."/files";
+
+$source = $_GET['source'];
+
+$source = strip_tags( $source );
+
+echo "\n\n$source\n\n";
+
+$revision = strtotime( $source );
+
+echo "\n\n$revision\n\n";
+
+if( OCA_Versions\Storage::isversioned( $source ) ) {
+
+
+        #\OCA_Versions\Storage::rollback( $source, $revision );
+	
+}
+
+?>
\ No newline at end of file
diff --git a/apps/files_versions/ajax/togglesettings.php b/apps/files_versions/ajax/togglesettings.php
new file mode 100755
index 0000000000000000000000000000000000000000..d513d12dd6c044a89e8b6e4b9bcdbae42bdda8c9
--- /dev/null
+++ b/apps/files_versions/ajax/togglesettings.php
@@ -0,0 +1,11 @@
+<?php
+
+OCP\JSON::checkAppEnabled('files_versions');
+OCP\JSON::checkAdminUser();
+if (OCP\Config::getSystemValue('versions', 'true')=='true') {
+	OCP\Config::setSystemValue('versions', 'false');
+} else {
+	OCP\Config::setSystemValue('versions', 'true');
+}
+
+?>
diff --git a/apps/files_versions/appinfo/app.php b/apps/files_versions/appinfo/app.php
new file mode 100755
index 0000000000000000000000000000000000000000..ebaa7ee0e7e70cfb35bfc303d473d8cbfccf8dfc
--- /dev/null
+++ b/apps/files_versions/appinfo/app.php
@@ -0,0 +1,20 @@
+<?php
+
+require_once('apps/files_versions/versions.php');
+
+// Add an entry in the app list
+OCP\App::register( array(
+  'order' => 10,
+  'id' => 'files_versions',
+  'name' => 'Versioning' ));
+
+OCP\App::registerAdmin('files_versions', 'settings');
+OCP\Util::addscript('files_versions', 'versions');
+
+// Listen to write signals
+OC_Hook::connect(OC_Filesystem::CLASSNAME, OC_Filesystem::signal_post_write, "OCA_Versions\Storage", "write_hook");
+
+
+
+
+?>
diff --git a/apps/files_versions/appinfo/info.xml b/apps/files_versions/appinfo/info.xml
new file mode 100644
index 0000000000000000000000000000000000000000..913be0d93ca5e0b53eb9124dce69a8cc5da49b1a
--- /dev/null
+++ b/apps/files_versions/appinfo/info.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0"?>
+<info>
+    <id>files_versions</id>
+    <name>Versions</name>
+    <licence>AGPL</licence>
+    <author>Frank Karlitschek</author>
+    <require>3</require>
+    <description>Versioning of files</description>
+	<types>
+		<filesystem/>
+	</types>
+	<default_enable/>
+</info>
diff --git a/apps/files_versions/appinfo/version b/apps/files_versions/appinfo/version
new file mode 100644
index 0000000000000000000000000000000000000000..afaf360d37fb71bcfa8cc082882f910ac2628bda
--- /dev/null
+++ b/apps/files_versions/appinfo/version
@@ -0,0 +1 @@
+1.0.0
\ No newline at end of file
diff --git a/apps/files_versions/css/versions.css b/apps/files_versions/css/versions.css
new file mode 100644
index 0000000000000000000000000000000000000000..a9b259ce1405ac7da4393a9baee111186f08c710
--- /dev/null
+++ b/apps/files_versions/css/versions.css
@@ -0,0 +1,16 @@
+#history {
+	margin: 2em 2em 0;
+}
+
+#feedback-messages h3 {
+	font-size: 1.3em;
+	font-style: italic;
+}
+
+.success {
+	color: green;
+}
+
+.failure {
+	color: red;
+}
\ No newline at end of file
diff --git a/apps/files_versions/history.php b/apps/files_versions/history.php
new file mode 100755
index 0000000000000000000000000000000000000000..eb8886239d31717f0365ac138ee4224f7422d37a
--- /dev/null
+++ b/apps/files_versions/history.php
@@ -0,0 +1,75 @@
+<?php
+
+/**
+ * ownCloud - History page of the Versions App
+ *
+ * @author Frank Karlitschek
+ * @copyright 2011 Frank Karlitschek karlitschek@kde.org
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * License as published by the Free Software Foundation; either 
+ * version 3 of the License, or any later version.
+ * 
+ * This library 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 AFFERO GENERAL PUBLIC LICENSE for more details.
+ *  
+ * You should have received a copy of the GNU Lesser General Public 
+ * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
+ * 
+ */
+require_once( '../../lib/base.php' );
+
+OCP\User::checkLoggedIn( );
+OCP\Util::addStyle('files_versions','versions');
+$tmpl = new OC_Template( 'files_versions', 'history', 'user' );
+
+if ( isset( $_GET['path'] ) ) {
+
+	$path = $_GET['path'];
+	$path = strip_tags( $path );
+	$tmpl->assign( 'path', $path );
+
+	// roll back to old version if button clicked
+        if( isset( $_GET['revert'] ) ) {
+        	
+        	if( \OCA_Versions\Storage::rollback( $path, $_GET['revert'] ) ) {
+			
+			$tmpl->assign( 'outcome_stat', 'success' );
+			
+			$tmpl->assign( 'outcome_msg', "File {$_GET['path']} was reverted to version ".OCP\Util::formatDate( $_GET['revert'] ) );
+			
+		} else {
+		
+			$tmpl->assign( 'outcome_stat', 'failure' );
+		
+			$tmpl->assign( 'outcome_msg', "File {$_GET['path']} could not be reverted to version ".OCP\Util::formatDate( $_GET['revert'] ) );
+			
+		}
+		
+	}
+
+	// show the history only if there is something to show
+        if( OCA_Versions\Storage::isversioned( $path ) ) {
+	
+		$count=999; //show the newest revisions
+	        $versions=OCA_Versions\Storage::getversions( $path, $count);
+
+		$tmpl->assign( 'versions', array_reverse( $versions ) );
+		
+	}else{
+		
+		$tmpl->assign( 'message', 'No old versions available' );
+		
+	}
+}else{
+	
+	$tmpl->assign( 'message', 'No path specified' );
+	
+}
+
+$tmpl->printPage( );
+
+?>
diff --git a/apps/files_versions/js/versions.js b/apps/files_versions/js/versions.js
new file mode 100644
index 0000000000000000000000000000000000000000..0508ab4cdec2944ac59aaf7bf2205c0d86fb3a59
Binary files /dev/null and b/apps/files_versions/js/versions.js differ
diff --git a/apps/files_versions/settings.php b/apps/files_versions/settings.php
new file mode 100755
index 0000000000000000000000000000000000000000..59609de15b4e8c3e37542326c0ea40c95cae9510
--- /dev/null
+++ b/apps/files_versions/settings.php
@@ -0,0 +1,10 @@
+<?php
+
+OCP\User::checkAdminUser();
+
+OCP\Util::addscript( 'files_versions', 'versions' );
+
+$tmpl = new OC_Template( 'files_versions', 'settings');
+
+return $tmpl->fetchPage();
+?>
diff --git a/apps/files_versions/templates/history.php b/apps/files_versions/templates/history.php
new file mode 100755
index 0000000000000000000000000000000000000000..3b29625b3b085be997cadc214ad1e540c3afab19
--- /dev/null
+++ b/apps/files_versions/templates/history.php
@@ -0,0 +1,33 @@
+<div id="history">
+
+<?php
+
+if( isset( $_['message'] ) ) {
+
+
+	if( isset($_['path'] ) ) echo('<strong>File: '.$_['path'] ).'</strong><br>';
+	echo('<strong>'.$_['message'] ).'</strong><br>';
+
+}else{
+
+	if( isset( $_['outcome_stat'] ) ) {
+		
+		echo( '<div id="feedback-messages" class="'.$_['outcome_stat'].'"><h3>'.$_['outcome_msg'] ).'</h3></div><br>';
+
+	}
+
+	echo( '<strong>Versions of '.$_['path'] ).'</strong><br>';
+	echo('<p><em>You can click on the revert button to revert to the specific verson.</em></p><br />');
+	
+	foreach ( $_['versions'] as $v ) {
+	
+		echo ' ';
+		echo OCP\Util::formatDate( $v );
+		echo ' <a href="history.php?path='.urlencode( $_['path'] ).'&revert='. $v .'" class="button">Revert</a><br /><br />';
+		
+	}
+
+}
+
+?>
+</div>
diff --git a/apps/files_versions/templates/settings.php b/apps/files_versions/templates/settings.php
new file mode 100755
index 0000000000000000000000000000000000000000..c3a856bc196e6951a231a49c72e446a41046ba40
--- /dev/null
+++ b/apps/files_versions/templates/settings.php
@@ -0,0 +1,5 @@
+<form id="versions">
+        <fieldset class="personalblock">
+	        <input type="checkbox" name="versions" id="versions" value="1" <?php if (OCP\Config::getSystemValue('versions', 'true')=='true') echo ' checked="checked"'; ?> /> <label for="versions"><?php echo $l->t('Enable Files Versioning'); ?></label> <br/>
+        </fieldset>
+</form>
diff --git a/apps/files_versions/versions.php b/apps/files_versions/versions.php
new file mode 100755
index 0000000000000000000000000000000000000000..082dfbf7fd07b4dbc5dd25a37395444bca1b24b2
--- /dev/null
+++ b/apps/files_versions/versions.php
@@ -0,0 +1,229 @@
+<?php
+/**
+ * Copyright (c) 2012 Frank Karlitschek <frank@owncloud.org>
+ * This file is licensed under the Affero General Public License version 3 or
+ * later.
+ * See the COPYING-README file.
+ */
+
+/**
+ * Versions
+ *
+ * A class to handle the versioning of files.
+ */
+
+namespace OCA_Versions;
+
+class Storage {
+
+
+	// config.php configuration:
+	//   - files_versions
+	//   - files_versionsfolder
+	//   - files_versionsblacklist
+	//   - files_versionsmaxfilesize
+	//   - files_versionsinterval 
+	//   - files_versionmaxversions 
+	//
+	// todo:
+	//   - port to oc_filesystem to enable network transparency
+	//   - check if it works well together with encryption
+	//   - implement expire all function. And find a place to call it ;-)
+	//   - add transparent compression. first test if it´s worth it.
+
+	const DEFAULTENABLED=true; 
+	const DEFAULTFOLDER='versions'; 
+	const DEFAULTBLACKLIST='avi mp3 mpg mp4'; 
+	const DEFAULTMAXFILESIZE=1048576; // 10MB 
+	const DEFAULTMININTERVAL=120; // 2 min
+	const DEFAULTMAXVERSIONS=50; 
+
+	/**
+	 * init the versioning and create the versions folder.
+	 */
+	public static function init() {
+		if(\OCP\Config::getSystemValue('files_versions', Storage::DEFAULTENABLED)=='true') {
+			// create versions folder
+			$foldername=\OCP\Config::getSystemValue('datadirectory').'/'. \OCP\USER::getUser() .'/'.\OCP\Config::getSystemValue('files_versionsfolder', Storage::DEFAULTFOLDER);
+			if(!is_dir($foldername)){
+				mkdir($foldername);
+			}
+		}
+	}
+
+
+	/**
+	 * listen to write event.
+	 */
+	public static function write_hook($params) {
+		if(\OCP\Config::getSystemValue('files_versions', Storage::DEFAULTENABLED)=='true') {
+			$path = $params[\OC_Filesystem::signal_param_path];
+			if($path<>'') Storage::store($path);
+		}
+	}
+
+
+
+	/**
+	 * store a new version of a file.
+	 */
+	public static function store($filename) {
+		if(\OCP\Config::getSystemValue('files_versions', Storage::DEFAULTENABLED)=='true') {
+			$versionsfoldername=\OCP\Config::getSystemValue('datadirectory').'/'. \OCP\USER::getUser() .'/'.\OCP\Config::getSystemValue('files_versionsfolder', Storage::DEFAULTFOLDER);
+			$filesfoldername=\OCP\Config::getSystemValue('datadirectory').'/'. \OCP\USER::getUser() .'/files';
+			Storage::init();
+
+			// check if filename is a directory
+			if(is_dir($filesfoldername.$filename)){
+				return false;
+			}
+
+			// check filetype blacklist
+			$blacklist=explode(' ',\OCP\Config::getSystemValue('files_versionsblacklist', Storage::DEFAULTBLACKLIST));
+			foreach($blacklist as $bl) {
+				$parts=explode('.', $filename);
+				$ext=end($parts);
+				if(strtolower($ext)==$bl) {
+					return false;
+				}
+			}
+			
+			// check filesize
+			if(filesize($filesfoldername.$filename)>\OCP\Config::getSystemValue('files_versionsmaxfilesize', Storage::DEFAULTMAXFILESIZE)){
+				return false;
+			}
+
+
+			// check mininterval
+			$matches=glob($versionsfoldername.$filename.'.v*');
+			sort($matches);
+			$parts=explode('.v',end($matches));
+			if((end($parts)+Storage::DEFAULTMININTERVAL)>time()){
+				return false;
+			}
+			
+
+			// create all parent folders
+			$info=pathinfo($filename);	
+			@mkdir($versionsfoldername.$info['dirname'],0700,true);	
+
+
+			// store a new version of a file
+			copy($filesfoldername.$filename,$versionsfoldername.$filename.'.v'.time());
+        
+			// expire old revisions
+			Storage::expire($filename);
+		}
+	}
+
+
+	/**
+	 * rollback to an old version of a file.
+	 */
+	public static function rollback($filename,$revision) {
+	
+		if(\OCP\Config::getSystemValue('files_versions', Storage::DEFAULTENABLED)=='true') {
+		
+			$versionsfoldername=\OCP\Config::getSystemValue('datadirectory').'/'. \OCP\USER::getUser() .'/'.\OCP\Config::getSystemValue('files_versionsfolder', Storage::DEFAULTFOLDER);
+			
+			$filesfoldername=\OCP\Config::getSystemValue('datadirectory').'/'. \OCP\USER::getUser() .'/files';
+			
+			// rollback
+			if ( @copy($versionsfoldername.$filename.'.v'.$revision,$filesfoldername.$filename) ) {
+			
+				return true;
+				
+			}else{
+			
+				return false;
+				
+			}
+			
+		}
+		
+	}
+
+	/**
+	 * check if old versions of a file exist.
+	 */
+	public static function isversioned($filename) {
+		if(\OCP\Config::getSystemValue('files_versions', Storage::DEFAULTENABLED)=='true') {
+			$versionsfoldername=\OCP\Config::getSystemValue('datadirectory').'/'. \OCP\USER::getUser() .'/'.\OCP\Config::getSystemValue('files_versionsfolder', Storage::DEFAULTFOLDER);
+
+			// check for old versions
+			$matches=glob($versionsfoldername.$filename.'.v*');
+			if(count($matches)>1){
+				return true;
+			}else{
+				return false;
+			}
+		}else{
+			return(false);
+		}
+	}
+
+
+        
+        /**
+         * get a list of old versions of a file.
+         */
+        public static function getversions($filename,$count=0) {
+                if(\OCP\Config::getSystemValue('files_versions', Storage::DEFAULTENABLED)=='true') {
+			$versionsfoldername=\OCP\Config::getSystemValue('datadirectory').'/'. \OCP\USER::getUser() .'/'.\OCP\Config::getSystemValue('files_versionsfolder', Storage::DEFAULTFOLDER);
+			$versions=array();         
+ 
+	              // fetch for old versions
+			$matches=glob($versionsfoldername.$filename.'.v*');
+			sort($matches);
+			foreach($matches as $ma) {
+				$parts=explode('.v',$ma);
+				$versions[]=(end($parts));
+			}
+			
+			// only show the newest commits
+			if($count<>0 and (count($versions)>$count)) {
+				$versions=array_slice($versions,count($versions)-$count);
+			}
+	
+			return($versions);
+
+
+                }else{
+                        return(array());
+                }
+        }	
+
+
+        
+        /**
+         * expire old versions of a file.
+         */
+        public static function expire($filename) {
+                if(\OCP\Config::getSystemValue('files_versions', Storage::DEFAULTENABLED)=='true') {
+
+			$versionsfoldername=\OCP\Config::getSystemValue('datadirectory').'/'. \OCP\USER::getUser() .'/'.\OCP\Config::getSystemValue('files_versionsfolder', Storage::DEFAULTFOLDER);
+
+			// check for old versions
+			$matches=glob($versionsfoldername.$filename.'.v*');
+			if(count($matches)>\OCP\Config::getSystemValue('files_versionmaxversions', Storage::DEFAULTMAXVERSIONS)){
+				$numbertodelete=count($matches-\OCP\Config::getSystemValue('files_versionmaxversions', Storage::DEFAULTMAXVERSIONS));
+
+				// delete old versions of a file
+				$deleteitems=array_slice($matches,0,$numbertodelete);
+				foreach($deleteitems as $de){
+					unlink($versionsfoldername.$filename.'.v'.$de);
+				}
+			}
+                }
+        }
+
+        /**
+         * expire all old versions.
+         */
+        public static function expireall($filename) {
+		// todo this should go through all the versions directories and delete all the not needed files and not needed directories.
+		// useful to be included in a cleanup cronjob.
+        }
+
+
+}
diff --git a/apps/gallery/ajax/createAlbum.php b/apps/gallery/ajax/createAlbum.php
old mode 100644
new mode 100755
index 152f5834bcb4130d7f0f1db203c13f0aa521bbf0..61e2e9ae2e9928b90b4899a833e0495959f78750
--- a/apps/gallery/ajax/createAlbum.php
+++ b/apps/gallery/ajax/createAlbum.php
@@ -21,12 +21,12 @@
 * 
 */
 
-require_once('../../../lib/base.php');
-OC_JSON::checkLoggedIn();
-OC_JSON::checkAppEnabled('gallery');
+ 
+OCP\JSON::checkLoggedIn();
+OCP\JSON::checkAppEnabled('gallery');
 
-OC_Gallery_Album::create(OC_User::getUser(), $_GET['album_name']);
+OC_Gallery_Album::create(OCP\USER::getUser(), $_GET['album_name']);
 
-OC_JSON::success(array('name' => $_GET['album_name']));
+OCP\JSON::success(array('name' => $_GET['album_name']));
 
 ?>
diff --git a/apps/gallery/ajax/galleryOp.php b/apps/gallery/ajax/galleryOp.php
old mode 100644
new mode 100755
index 1b3ad48f561046574d6f3c7ffadcf5580196a8c5..0cd825f3e50d938cc0b11a2cbe78ba4aafa33231
--- a/apps/gallery/ajax/galleryOp.php
+++ b/apps/gallery/ajax/galleryOp.php
@@ -22,77 +22,77 @@
 */
 
 header('Content-type: text/html; charset=UTF-8') ;
-require_once('../../../lib/base.php');
+ 
 
-OC_JSON::checkLoggedIn();
-OC_JSON::checkAppEnabled('gallery');
+OCP\JSON::checkLoggedIn();
+OCP\JSON::checkAppEnabled('gallery');
 
 function handleRename($oldname, $newname) {
-  OC_Gallery_Album::rename($oldname, $newname, OC_User::getUser());
+  OC_Gallery_Album::rename($oldname, $newname, OCP\USER::getUser());
   OC_Gallery_Album::changeThumbnailPath($oldname, $newname);
 }
 
 function handleRemove($name) {
-  $album_id = OC_Gallery_Album::find(OC_User::getUser(), $name);
+  $album_id = OC_Gallery_Album::find(OCP\USER::getUser(), $name);
   $album_id = $album_id->fetchRow();
   $album_id = $album_id['album_id'];
-  OC_Gallery_Album::remove(OC_User::getUser(), $name);
+  OC_Gallery_Album::remove(OCP\USER::getUser(), $name);
   OC_Gallery_Photo::removeByAlbumId($album_id);
 }
 
 function handleGetThumbnails($albumname) {
-  OC_Response::enableCaching(3600 * 24); // 24 hour
+  OCP\Response::enableCaching(3600 * 24); // 24 hour
   $thumbnail = OC::$CONFIG_DATADIRECTORY.'/../gallery/'.urldecode($albumname).'.png';
   header('Content-Type: '.OC_Image::getMimeTypeForFile($thumbnail));
-  OC_Response::sendFile($thumbnail);
+  OCP\Response::sendFile($thumbnail);
 }
 
 function handleGalleryScanning() {
-  OC_DB::beginTransaction();
+  OCP\DB::beginTransaction();
   set_time_limit(0);
   OC_Gallery_Album::cleanup();
   $eventSource = new OC_EventSource();
   OC_Gallery_Scanner::scan($eventSource);
   $eventSource->close();
-  OC_DB::commit();
+  OCP\DB::commit();
 }
 
 function handleFilescan($cleanup) {
   if ($cleanup) OC_Gallery_Album::cleanup();
   $pathlist = OC_Gallery_Scanner::find_paths();
   sort($pathlist);
-  OC_JSON::success(array('paths' => $pathlist));
+  OCP\JSON::success(array('paths' => $pathlist));
 }
 
 function handleStoreSettings($root, $order) {
   if (!OC_Filesystem::file_exists($root)) {
-    OC_JSON::error(array('cause' => 'No such file or directory'));
+    OCP\JSON::error(array('cause' => 'No such file or directory'));
     return;
   }
   if (!OC_Filesystem::is_dir($root)) {
-    OC_JSON::error(array('cause' => $root . ' is not a directory'));
+    OCP\JSON::error(array('cause' => $root . ' is not a directory'));
     return;
   }
 
-  $current_root = OC_Preferences::getValue(OC_User::getUser(),'gallery', 'root', '/');
+  $current_root = OCP\Config::getUserValue(OCP\USER::getUser(),'gallery', 'root', '/');
   $root = trim($root);
   $root = rtrim($root, '/').'/';
   $rescan = $current_root==$root?'no':'yes';
-  OC_Preferences::setValue(OC_User::getUser(), 'gallery', 'root', $root);
-  OC_Preferences::setValue(OC_User::getUser(), 'gallery', 'order', $order);
-  OC_JSON::success(array('rescan' => $rescan));
+  OCP\Config::setUserValue(OCP\USER::getUser(), 'gallery', 'root', $root);
+  OCP\Config::setUserValue(OCP\USER::getUser(), 'gallery', 'order', $order);
+  OCP\JSON::success(array('rescan' => $rescan));
 }
 
 function handleGetGallery($path) {
   $a = array();
-  $root = OC_Preferences::getValue(OC_User::getUser(),'gallery', 'root', '/');
+  $root = OCP\Config::getUserValue(OCP\USER::getUser(),'gallery', 'root', '/');
   $path = utf8_decode(rtrim($root.$path,'/'));
   if($path == '') $path = '/';
   $pathLen = strlen($path);
-  $result = OC_Gallery_Album::find(OC_User::getUser(), null, $path);
+  $result = OC_Gallery_Album::find(OCP\USER::getUser(), null, $path);
   $album_details = $result->fetchRow();
 
-  $result = OC_Gallery_Album::find(OC_User::getUser(), null, null, $path);
+  $result = OC_Gallery_Album::find(OCP\USER::getUser(), null, null, $path);
 
   while ($r = $result->fetchRow()) {
     $album_name = $r['album_name'];
@@ -121,36 +121,36 @@ function handleGetGallery($path) {
     $token = $row['token'];
   }
 
-  OC_JSON::success(array('albums'=>$a, 'photos'=>$p, 'shared' => $shared, 'recursive' => $recursive, 'token' => $token));
+  OCP\JSON::success(array('albums'=>$a, 'photos'=>$p, 'shared' => $shared, 'recursive' => $recursive, 'token' => $token));
 }
 
 function handleShare($path, $share, $recursive) {
   $recursive = $recursive == 'true' ? 1 : 0;
-  $owner = OC_User::getUser();
-  $root = OC_Preferences::getValue(OC_User::getUser(),'gallery', 'root', '/');
+  $owner = OCP\USER::getUser();
+  $root = OCP\Config::getUserValue(OCP\USER::getUser(),'gallery', 'root', '/');
   $path = utf8_decode(rtrim($root.$path,'/'));
   if($path == '') $path = '/';
   $r = OC_Gallery_Album::find($owner, null, $path);
   if ($row = $r->fetchRow()) {
     $albumId = $row['album_id'];
   } else {
-    OC_JSON::error(array('cause' => 'Couldn\'t find requested gallery'));
+    OCP\JSON::error(array('cause' => 'Couldn\'t find requested gallery'));
     exit;
   }
     
   if ($share == false) {
       OC_Gallery_Sharing::remove($albumId);
-      OC_JSON::success(array('sharing' => false));
+      OCP\JSON::success(array('sharing' => false));
   } else { // share, yeah \o/
     $r = OC_Gallery_Sharing::getEntryByAlbumId($albumId);
     if (($row = $r->fetchRow())) { // update entry
       OC_Gallery_Sharing::updateSharingByToken($row['token'], $recursive);
-      OC_JSON::success(array('sharing' => true, 'token' => $row['token'], 'recursive' => $recursive == 1 ? true : false ));
+      OCP\JSON::success(array('sharing' => true, 'token' => $row['token'], 'recursive' => $recursive == 1 ? true : false ));
     } else { // and new sharing entry
       $date = new DateTime();
       $token = md5($owner . $date->getTimestamp());
       OC_Gallery_Sharing::addShared($token, intval($albumId), $recursive);
-      OC_JSON::success(array('sharing' => true, 'token' => $token, 'recursive' => $recursive == 1 ? true : false ));
+      OCP\JSON::success(array('sharing' => true, 'token' => $token, 'recursive' => $recursive == 1 ? true : false ));
     }
   }
 }
@@ -160,11 +160,11 @@ if ($_GET['operation']) {
   switch($_GET['operation']) {
   case 'rename':
 	  handleRename($_GET['oldname'], $_GET['newname']);
-	  OC_JSON::success(array('newname' => $_GET['newname']));
+	  OCP\JSON::success(array('newname' => $_GET['newname']));
 	break;
   case 'remove':
 	  handleRemove($_GET['name']);
-	  OC_JSON::success();
+	  OCP\JSON::success();
     break;
   case 'get_covers':
     handleGetThumbnails(urldecode($_GET['albumname']));
@@ -182,7 +182,7 @@ if ($_GET['operation']) {
     handleShare($_GET['path'], $_GET['share'] == 'true' ? true : false, $_GET['recursive']);
     break;
   default:
-    OC_JSON::error(array('cause' => 'Unknown operation'));
+    OCP\JSON::error(array('cause' => 'Unknown operation'));
   }
 }
 ?>
diff --git a/apps/gallery/ajax/sharing.php b/apps/gallery/ajax/sharing.php
old mode 100644
new mode 100755
index fba85fa34ee8589336b45e172311d846aad3a866..1223320120b4aa7a41150542a9afea658974ba16
--- a/apps/gallery/ajax/sharing.php
+++ b/apps/gallery/ajax/sharing.php
@@ -21,10 +21,10 @@
 * 
 */
 
-require_once('../../../lib/base.php');
+ 
 
 if (!isset($_GET['token']) || !isset($_GET['operation'])) {
-  OC_JSON::error(array('cause' => 'Not enought arguments'));
+  OCP\JSON::error(array('cause' => 'Not enought arguments'));
   exit;
 }
 
@@ -32,7 +32,7 @@ $operation = $_GET['operation'];
 $token = $_GET['token'];
 
 if (!OC_Gallery_Sharing::isTokenValid($token)) {
-  OC_JSON::error(array('cause' => 'Given token is not valid'));
+  OCP\JSON::error(array('cause' => 'Given token is not valid'));
   exit;
 }
 
@@ -65,14 +65,14 @@ function handleGetGallery($token, $path) {
       $photos[] = $row['file_path'];
   }
 
-  OC_JSON::success(array('albums' => $albums, 'photos' => $photos));
+  OCP\JSON::success(array('albums' => $albums, 'photos' => $photos));
 }
 
 function handleGetThumbnail($token, $imgpath) {
   $owner = OC_Gallery_Sharing::getTokenOwner($token);
   $image = OC_Gallery_Photo::getThumbnail($imgpath, $owner);
   if ($image) {
-    OC_Response::enableCaching(3600 * 24); // 24 hour
+    OCP\Response::enableCaching(3600 * 24); // 24 hour
     $image->show();
   }
 }
@@ -80,22 +80,22 @@ function handleGetThumbnail($token, $imgpath) {
 function handleGetAlbumThumbnail($token, $albumname)
 {
   $owner = OC_Gallery_Sharing::getTokenOwner($token);
-  $file = OC_Config::getValue("datadirectory").'/'. $owner .'/gallery/'.$albumname.'.png';
+  $file = OCP\Config::getSystemValue("datadirectory").'/'. $owner .'/gallery/'.$albumname.'.png';
   $image = new OC_Image($file);
   if ($image->valid()) {
     $image->centerCrop();
     $image->resize(200);
     $image->fixOrientation();
-    OC_Response::enableCaching(3600 * 24); // 24 hour
+    OCP\Response::enableCaching(3600 * 24); // 24 hour
     $image->show();
   }
 }
 
 function handleGetPhoto($token, $photo) {
   $owner = OC_Gallery_Sharing::getTokenOwner($token);
-  $file = OC_Config::getValue( "datadirectory", OC::$SERVERROOT."/data" ).'/'.$owner.'/files'.urldecode($photo);
+  $file = OCP\Config::getSystemValue( "datadirectory", OC::$SERVERROOT."/data" ).'/'.$owner.'/files'.urldecode($photo);
   header('Content-Type: '.OC_Image::getMimeTypeForFile($file));
-  OC_Response::sendFile($file);
+  OCP\Response::sendFile($file);
 }
 
 switch ($operation) {
diff --git a/apps/gallery/ajax/thumbnail.php b/apps/gallery/ajax/thumbnail.php
old mode 100644
new mode 100755
index 184171f8fcadaad7eb5400aa575b6bf79fddd9bf..ff0cb44022ceedd403790df7c32ef6fe4c8e3ce2
--- a/apps/gallery/ajax/thumbnail.php
+++ b/apps/gallery/ajax/thumbnail.php
@@ -21,14 +21,14 @@
 * 
 */
 
-require_once('../../../lib/base.php');
-OC_JSON::checkLoggedIn();
-OC_JSON::checkAppEnabled('gallery');
+ 
+OCP\JSON::checkLoggedIn();
+OCP\JSON::checkAppEnabled('gallery');
 
 $img = $_GET['img'];
 
 $image = OC_Gallery_Photo::getThumbnail($img);
 if ($image) {
-	OC_Response::enableCaching(3600 * 24); // 24 hour
+	OCP\Response::enableCaching(3600 * 24); // 24 hour
 	$image->show();
 }
diff --git a/apps/gallery/appinfo/app.php b/apps/gallery/appinfo/app.php
old mode 100644
new mode 100755
index 325c2acf2491b432ca626adfc691f25c5843018d..2501ae7bbd520131da62945c30fa326af446d3af
--- a/apps/gallery/appinfo/app.php
+++ b/apps/gallery/appinfo/app.php
@@ -27,27 +27,27 @@ OC::$CLASSPATH['OC_Gallery_Scanner'] = 'apps/gallery/lib/scanner.php';
 OC::$CLASSPATH['OC_Gallery_Sharing'] = 'apps/gallery/lib/sharing.php';
 OC::$CLASSPATH['OC_Gallery_Hooks_Handlers'] = 'apps/gallery/lib/hooks_handlers.php';
 
-$l = new OC_L10N('gallery');
+$l = OC_L10N::get('gallery');
 
-OC_App::register(array(
+OCP\App::register(array(
   'order' => 20,
   'id' => 'gallery',
   'name' => 'Pictures'));
 
-OC_App::addNavigationEntry( array(
+OCP\App::addNavigationEntry( array(
  'id' => 'gallery_index',
  'order' => 20,
- 'href' => OC_Helper::linkTo('gallery', 'index.php'),
- 'icon' => OC_Helper::imagePath('core', 'places/picture.svg'),
+ 'href' => OCP\Util::linkTo('gallery', 'index.php'),
+ 'icon' => OCP\Util::imagePath('core', 'places/picture.svg'),
  'name' => $l->t('Pictures')));
 
 class OC_GallerySearchProvider extends OC_Search_Provider{
 	function search($query){
-		$stmt = OC_DB::prepare('SELECT * FROM *PREFIX*gallery_albums WHERE uid_owner = ? AND album_name LIKE ?');
-		$result = $stmt->execute(array(OC_User::getUser(),'%'.$query.'%'));
+		$stmt = OCP\DB::prepare('SELECT * FROM *PREFIX*gallery_albums WHERE uid_owner = ? AND album_name LIKE ?');
+		$result = $stmt->execute(array(OCP\USER::getUser(),'%'.$query.'%'));
 		$results=array();
 		while($row=$result->fetchRow()){
-			$results[]=new OC_Search_Result($row['album_name'],'',OC_Helper::linkTo('gallery', 'index.php').'?view='.$row['album_name'],'Galleries');
+			$results[]=new OC_Search_Result($row['album_name'],'',OCP\Util::linkTo('gallery', 'index.php').'?view='.$row['album_name'],'Galleries');
 		}
 		return $results;
 	}
diff --git a/apps/gallery/appinfo/info.xml b/apps/gallery/appinfo/info.xml
index 4c8c1cee24257d05c429d4de5267dbee0caae51f..7dc85374b0bd582d6147fb6e9a35ae41ed65b151 100644
--- a/apps/gallery/appinfo/info.xml
+++ b/apps/gallery/appinfo/info.xml
@@ -2,7 +2,6 @@
 <info>
 	<id>gallery</id>
 	<name>Pictures</name>
-	<version>0.4</version>
 	<licence>AGPL</licence>
 	<author>Bartek Przybylski</author>
 	<require>2</require>
diff --git a/apps/gallery/appinfo/version b/apps/gallery/appinfo/version
new file mode 100644
index 0000000000000000000000000000000000000000..267577d47e497a0630bc454b3f74c4fd9a10ced4
--- /dev/null
+++ b/apps/gallery/appinfo/version
@@ -0,0 +1 @@
+0.4.1
diff --git a/apps/gallery/css/sharing.css b/apps/gallery/css/sharing.css
index eaac82ebd605cf2a6429210640188fae42865ee1..d061fc3e6c1436db68dd7cbd0a18b06fa2ac2fc1 100644
--- a/apps/gallery/css/sharing.css
+++ b/apps/gallery/css/sharing.css
@@ -5,4 +5,4 @@ div.gallery_box:hover { color: black; }
 div.gallery_box h1 {font-size: 17px; font-weight: normal;}
 div#breadcrumb { border: 0; width: 70%; margin: 0 auto; padding: 25px 0; font-family: Verdana; text-align: center;}
 span.breadcrumbelement { margin: 10px; margin-right: 0; cursor: pointer;}
-span.inside { background-image: url('../img/breadcrumb.png'); padding-left: 20px; background-position: left; background-repeat: no-repeat;}
+span.inside { background-image: url('%appswebroot%/apps/gallery/img/breadcrumb.png'); padding-left: 20px; background-position: left; background-repeat: no-repeat;}
diff --git a/apps/gallery/index.php b/apps/gallery/index.php
old mode 100644
new mode 100755
index 7de7c0941429aa0c0f922a51f112aa3d2cda97a0..cf8bea142164d307c11123ee92e18f36dfbe5117
--- a/apps/gallery/index.php
+++ b/apps/gallery/index.php
@@ -21,18 +21,18 @@
 * 
 */
 
-require_once('../../lib/base.php');
 
-OC_Util::checkLoggedIn();
-OC_Util::checkAppEnabled('gallery');
-OC_App::setActiveNavigationEntry( 'gallery_index' );
 
-if (!file_exists(OC_Config::getValue("datadirectory").'/'. OC_User::getUser() .'/gallery')) {
-  mkdir(OC_Config::getValue("datadirectory").'/'. OC_User::getUser() .'/gallery');
+OCP\User::checkLoggedIn();
+OCP\App::checkAppEnabled('gallery');
+OCP\App::setActiveNavigationEntry( 'gallery_index' );
+
+if (!file_exists(OCP\Config::getSystemValue("datadirectory").'/'. OCP\USER::getUser() .'/gallery')) {
+  mkdir(OCP\Config::getSystemValue("datadirectory").'/'. OCP\USER::getUser() .'/gallery');
 }
 
 if (!isset($_GET['view'])) {
-  $result = OC_Gallery_Album::find(OC_User::getUser());
+  $result = OC_Gallery_Album::find(OCP\USER::getUser());
 
   $r = array();
   while ($row = $result->fetchRow())
@@ -42,7 +42,7 @@ if (!isset($_GET['view'])) {
   $tmpl->assign('r', $r);
   $tmpl->printPage();
 } else {
-  $result = OC_Gallery_Photo::findForAlbum(OC_User::getUser(), $_GET['view']);
+  $result = OC_Gallery_Photo::findForAlbum(OCP\USER::getUser(), $_GET['view']);
 
   $photos = array();
   while ($p = $result->fetchRow())
diff --git a/apps/gallery/lib/album.php b/apps/gallery/lib/album.php
old mode 100644
new mode 100755
index ef361a3791319e0661c1e44b11754e4843d11541..27d40cdb91f8519351810d3e279d221198e4ea09
--- a/apps/gallery/lib/album.php
+++ b/apps/gallery/lib/album.php
@@ -25,15 +25,15 @@ require_once('base.php');
 
 class OC_Gallery_Album {
 	public static function create($owner, $name, $path){
-		$stmt = OC_DB::prepare('INSERT INTO *PREFIX*gallery_albums (uid_owner, album_name, album_path, parent_path) VALUES (?, ?, ?, ?)');
+		$stmt = OCP\DB::prepare('INSERT INTO *PREFIX*gallery_albums (uid_owner, album_name, album_path, parent_path) VALUES (?, ?, ?, ?)');
 		$stmt->execute(array($owner, $name, $path, self::getParentPath($path)));
 	}
 
 	public static function cleanup() {
-		$albums = self::find(OC_User::getUser());
+		$albums = self::find(OCP\USER::getUser());
 		while ($r = $albums->fetchRow()) {
 			OC_Gallery_Photo::removeByAlbumId($r['album_id']);
-			self::remove(OC_User::getUser(), $r['album_name']);
+			self::remove(OCP\USER::getUser(), $r['album_name']);
 		}
 	}
 
@@ -56,7 +56,7 @@ class OC_Gallery_Album {
 			$sql .= ' AND parent_path LIKE ?';
 			$args[] = $parent;
 		}
-		$stmt = OC_DB::prepare($sql);
+		$stmt = OCP\DB::prepare($sql);
 		return $stmt->execute($args);
 	}
 
@@ -79,27 +79,27 @@ class OC_Gallery_Album {
 			$sql .= ' AND parent_path = ?';
 			$args[] = $parent;
 		}
-    $order = OC_Preferences::getValue($owner, 'gallery', 'order', 'ASC');
+    $order = OCP\Config::getUserValue($owner, 'gallery', 'order', 'ASC');
 		$sql .= ' ORDER BY album_name ' . $order;
 
-		$stmt = OC_DB::prepare($sql);
+		$stmt = OCP\DB::prepare($sql);
 		return $stmt->execute($args);
 	}
 
 	public static function changePath($oldname, $newname, $owner) {
-		$stmt = OC_DB::prepare('UPDATE *PREFIX*gallery_albums SET album_path=? WHERE uid_owner=? AND album_path=?');
+		$stmt = OCP\DB::prepare('UPDATE *PREFIX*gallery_albums SET album_path=? WHERE uid_owner=? AND album_path=?');
 		$stmt->execute(array($newname, $owner, $oldname));
 	}
 
 	public static function changeThumbnailPath($oldname, $newname) {
-		require_once('../../../lib/base.php');
+		 
 		$thumbpath = OC::$CONFIG_DATADIRECTORY.'/../gallery/';
 		rename($thumbpath.$oldname.'.png', $thumbpath.$newname.'.png');
 	}
 
 	public static function getAlbumSize($id){
     $sql = 'SELECT COUNT(*) as size FROM *PREFIX*gallery_photos WHERE album_id = ?';
-    $stmt = OC_DB::prepare($sql);
+    $stmt = OCP\DB::prepare($sql);
     $result=$stmt->execute(array($id))->fetchRow();
     return $result['size'];
 	}
@@ -107,8 +107,8 @@ class OC_Gallery_Album {
   public static function getIntermediateGallerySize($path) {
     $path .= '%';
     $sql = 'SELECT COUNT(*) as size FROM *PREFIX*gallery_photos photos, *PREFIX*gallery_albums albums WHERE photos.album_id = albums.album_id AND uid_owner = ? AND file_path LIKE ?';
-    $stmt = OC_DB::prepare($sql);
-    $result = $stmt->execute(array(OC_User::getUser(), $path))->fetchRow();
+    $stmt = OCP\DB::prepare($sql);
+    $result = $stmt->execute(array(OCP\USER::getUser(), $path))->fetchRow();
     return $result['size'];
   }
 }
diff --git a/apps/gallery/lib/hooks_handlers.php b/apps/gallery/lib/hooks_handlers.php
old mode 100644
new mode 100755
index 2788337bbe84a657a920fe7372d17a54d7f83ce1..678d3fe7531920c23396f97e374bdfeeaa3afb01
--- a/apps/gallery/lib/hooks_handlers.php
+++ b/apps/gallery/lib/hooks_handlers.php
@@ -21,8 +21,8 @@
 * 
 */
 
-//OC_Hook::connect(OC_Filesystem::CLASSNAME, OC_Filesystem::signal_post_write, "OC_Gallery_Hooks_Handlers", "addPhotoFromPath");
-//OC_Hook::connect(OC_Filesystem::CLASSNAME, OC_Filesystem::signal_delete, "OC_Gallery_Hooks_Handlers", "removePhoto");
+OC_Hook::connect(OC_Filesystem::CLASSNAME, OC_Filesystem::signal_post_write, "OC_Gallery_Hooks_Handlers", "addPhotoFromPath");
+OC_Hook::connect(OC_Filesystem::CLASSNAME, OC_Filesystem::signal_delete, "OC_Gallery_Hooks_Handlers", "removePhoto");
 //OC_Hook::connect(OC_Filesystem::CLASSNAME, OC_Filesystem::signal_post_rename, "OC_Gallery_Hooks_Handlers", "renamePhoto");
 
 require_once(OC::$CLASSPATH['OC_Gallery_Album']);
@@ -52,35 +52,50 @@ class OC_Gallery_Hooks_Handlers {
     if ($new_album_name == '')
       $new_album_name = 'main';
 
-    OC_Log::write(self::$APP_TAG, 'Creating new album '.$new_album_name, OC_Log::DEBUG);
-    OC_Gallery_Album::create(OC_User::getUser(), $new_album_name, $path);
+    OCP\Util::writeLog(self::$APP_TAG, 'Creating new album '.$new_album_name, OCP\Util::DEBUG);
+    OC_Gallery_Album::create(OCP\USER::getUser(), $new_album_name, $path);
 
-    return OC_Gallery_Album::find(OC_User::getUser(), null, $path);
+    return OC_Gallery_Album::find(OCP\USER::getUser(), null, $path);
   }
 
   public static function pathInRoot($path) {
-    $root = OC_Preferences::getValue(OC_User::getUser(), 'gallery', 'root', '/');
+    $root = OCP\Config::getUserValue(OCP\USER::getUser(), 'gallery', 'root', '/');
     return substr($path, 0, strlen($path)>strlen($root)?strlen($root):strlen($path)) == $root;
   }
 
   public static function addPhotoFromPath($params) {
     $fullpath = $params[OC_Filesystem::signal_param_path];
+    $fullpath = rtrim(dirname($fullpath),'/').'/'.basename($fullpath);
 
     if (!self::isPhoto($fullpath)) return;
 
-    $path = dirname($fullpath);
-    if (!self::pathInRoot($path)) return;
-    OC_Gallery_Scanner::scanDir($path, $albums);
-
+    $a = OC_Gallery_Album::find(OCP\USER::getUser(), null, dirname($fullpath));
+    if (!($r = $a->fetchRow())) {
+      OC_Gallery_Album::create(OCP\USER::getUser(), basename(dirname($fullpath)), dirname($fullpath));
+      $a = OC_Gallery_Album::find(OCP\USER::getUser(), null, dirname($fullpath));
+      $r = $a->fetchRow();
+    }
+    $albumId = $r['album_id'];
+    $p = OC_Gallery_Album::find($albumId, $fullpath);
+    if (!($p->fetchRow()))
+      OC_Gallery_Photo::create($albumId, $fullpath);
   }
 
   public static function removePhoto($params) {
-    $path = $params[OC_Filesystem::signal_param_path];
-    if (OC_Filesystem::is_dir($path.'/') && self::directoryContainsPhotos($path)) {
-      if(!self::pathInRoot($path)) return;
-      OC_Gallery_Album::removeByPath($path, OC_User::getUser());
-    } elseif (self::isPhoto($path)) {
-      OC_Gallery_Photo::removeByPath($path);
+    $fullpath = $params[OC_Filesystem::signal_param_path];
+    $fullpath = rtrim(dirname($fullpath),'/').'/'.basename($fullpath);
+
+    if (OC_Filesystem::is_dir($fullpath)) {
+      OC_Gallery_Album::remove(OCP\USER::getUser(), null, $fullpath);
+    } elseif (self::isPhoto($fullpath)) {
+      $a = OC_Gallery_Album::find(OCP\USER::getUser(), null, rtrim(dirname($fullpath),'/'));
+      if (($r = $a->fetchRow())) {
+        OC_Gallery_Photo::removeByPath($fullpath, $r['album_id']);
+        $p = OC_Gallery_Photo::findForAlbum(OCP\USER::getUser(), $r['album_name']);
+        if (!($p->fetchRow())) {
+          OC_Gallery_Album::remove(OCP\USER::getUser(), null, dirname($fullpath));
+        }
+      }
     }
   }
 
@@ -88,20 +103,20 @@ class OC_Gallery_Hooks_Handlers {
     $oldpath = $params[OC_Filesystem::signal_param_oldpath];
     $newpath = $params[OC_Filesystem::signal_param_newpath];
     if (OC_Filesystem::is_dir($newpath.'/') && self::directoryContainsPhotos($newpath)) {
-      OC_Gallery_Album::changePath($oldpath, $newpath, OC_User::getUser());
+      OC_Gallery_Album::changePath($oldpath, $newpath, OCP\USER::getUser());
     } elseif (self::isPhoto($newpath)) {
       $olddir = dirname($oldpath);
       $newdir = dirname($newpath);
       if ($olddir == '') $olddir = '/';
       if ($newdir == '') $newdir = '/';
       if (!self::isPhoto($newpath)) return;
-      OC_Log::write(self::$APP_TAG, 'Moving photo from '.$oldpath.' to '.$newpath, OC_Log::DEBUG);
+      OCP\Util::writeLog(self::$APP_TAG, 'Moving photo from '.$oldpath.' to '.$newpath, OCP\Util::DEBUG);
       $album;
       $newAlbumId;
       $oldAlbumId;
       if ($olddir == $newdir) {
         // album changing is not needed
-        $albums = OC_Gallery_Album::find(OC_User::getUser(), null, $olddir);
+        $albums = OC_Gallery_Album::find(OCP\USER::getUser(), null, $olddir);
         $album = $albums->fetchRow();
         if (!$album) {
           $albums = self::createAlbum($newdir);
@@ -109,8 +124,8 @@ class OC_Gallery_Hooks_Handlers {
         }
         $newAlbumId = $oldAlbumId = $album['album_id'];
       } else {
-        $newalbum = OC_Gallery_Album::find(OC_User::getUser(), null, $newdir);
-        $oldalbum = OC_Gallery_Album::find(OC_User::getUser(), null, $olddir);
+        $newalbum = OC_Gallery_Album::find(OCP\USER::getUser(), null, $newdir);
+        $oldalbum = OC_Gallery_Album::find(OCP\USER::getUser(), null, $olddir);
 
         if (!($newalbum = $newalbum->fetchRow())) {
           $newalbum = self::createAlbum($newdir);
diff --git a/apps/gallery/lib/images_utils.php b/apps/gallery/lib/images_utils.php
old mode 100644
new mode 100755
index 126298913be10ce71e93ce5bfbdda8c2b8f70d71..ac3a383c97748985a0a44540510556882f86607e
--- a/apps/gallery/lib/images_utils.php
+++ b/apps/gallery/lib/images_utils.php
@@ -21,13 +21,8 @@
 * 
 */
 
-if (file_exists('../../../lib/base.php'))
-  require_once('../../../lib/base.php');
-elseif (file_exists('lib/base.php'))
-  require_once('lib/base.php');
-
-OC_JSON::checkLoggedIn();
-OC_JSON::checkAppEnabled('gallery');
+OCP\JSON::checkLoggedIn();
+OCP\JSON::checkAppEnabled('gallery');
 
 function CroppedThumbnail($imgSrc,$thumbnail_width,$thumbnail_height, $tgtImg, $shift) { 
     //getting the image dimensions
diff --git a/apps/gallery/lib/photo.php b/apps/gallery/lib/photo.php
old mode 100644
new mode 100755
index 3bb6f9129fa51184b930e167b4e8d5edacc2d885..99384af621ac513ed384a42cb4cd5e3b545aeada
--- a/apps/gallery/lib/photo.php
+++ b/apps/gallery/lib/photo.php
@@ -23,7 +23,7 @@
 
 class OC_Gallery_Photo {
 	public static function create($albumId, $img){
-		$stmt = OC_DB::prepare('INSERT INTO *PREFIX*gallery_photos (album_id, file_path) VALUES (?, ?)');
+		$stmt = OCP\DB::prepare('INSERT INTO *PREFIX*gallery_photos (album_id, file_path) VALUES (?, ?)');
 		$stmt->execute(array($albumId, $img));
 	}
 	public static function find($albumId, $img=null){
@@ -33,11 +33,11 @@ class OC_Gallery_Photo {
 			$sql .= ' AND file_path = ?';
 			$args[] = $img;
 		}
-		$stmt = OC_DB::prepare($sql);
+		$stmt = OCP\DB::prepare($sql);
 		return $stmt->execute($args);
 	}
 	public static function findForAlbum($owner, $album_name){
-		$stmt = OC_DB::prepare('SELECT *'
+		$stmt = OCP\DB::prepare('SELECT *'
 			.' FROM *PREFIX*gallery_photos photos,'
 				.' *PREFIX*gallery_albums albums'
 			.' WHERE albums.uid_owner = ?'
@@ -46,29 +46,29 @@ class OC_Gallery_Photo {
 		return $stmt->execute(array($owner, $album_name));
 	}
 
-	public static function removeByPath($path) {
-		$stmt = OC_DB::prepare('DELETE FROM *PREFIX*gallery_photos WHERE file_path LIKE ?');
-		$stmt->execute(array($path));
+  public static function removeByPath($path, $album_id) {
+    $stmt = OCP\DB::prepare('DELETE FROM *PREFIX*gallery_photos WHERE file_path LIKE ? and album_id = ?');
+		$stmt->execute(array($path, $album_id));
 	}
 
 	public static function removeById($id) {
-		$stmt = OC_DB::prepare('DELETE FROM *PREFIX*gallery_photos WHERE photo_id = ?');
+		$stmt = OCP\DB::prepare('DELETE FROM *PREFIX*gallery_photos WHERE photo_id = ?');
 		$stmt->execute(array($id));
 	}
 
 	public static function removeByAlbumId($albumid) {
-		$stmt = OC_DB::prepare('DELETE FROM *PREFIX*gallery_photos WHERE album_id = ?');
+		$stmt = OCP\DB::prepare('DELETE FROM *PREFIX*gallery_photos WHERE album_id = ?');
 		$stmt->execute(array($albumid));
 	}
 
 	public static function changePath($oldAlbumId, $newAlbumId, $oldpath, $newpath) {
-		$stmt = OC_DB::prepare("UPDATE *PREFIX*gallery_photos SET file_path = ?, album_id = ? WHERE album_id = ? and file_path = ?");
+		$stmt = OCP\DB::prepare("UPDATE *PREFIX*gallery_photos SET file_path = ?, album_id = ? WHERE album_id = ? and file_path = ?");
 		$stmt->execute(array($newpath, $newAlbumId, $oldAlbumId, $oldpath));
 	}
 
 	public static function getThumbnail($image_name, $owner = null) {
-		if (!$owner) $owner = OC_User::getUser();
-		$save_dir = OC_Config::getValue("datadirectory").'/'. $owner .'/gallery/';
+		if (!$owner) $owner = OCP\USER::getUser();
+		$save_dir = OCP\Config::getSystemValue("datadirectory").'/'. $owner .'/gallery/';
 		$save_dir .= dirname($image_name). '/';
 		$image_path = $image_name;
 		$thumb_file = $save_dir . basename($image_name);
@@ -98,6 +98,6 @@ class OC_Gallery_Photo {
 	}
 
 	public static function getGalleryRoot() {
-		return OC_Preferences::getValue(OC_User::getUser(), 'gallery', 'root', '');
+		return OCP\Config::getUserValue(OCP\USER::getUser(), 'gallery', 'root', '');
 	}
 }
diff --git a/apps/gallery/lib/scanner.php b/apps/gallery/lib/scanner.php
old mode 100644
new mode 100755
index 0317f943e5d0ce88bbc606b974643f5bf4b802ae..7a137cb3f508eeffdb2856e81d1df1635d43e041
--- a/apps/gallery/lib/scanner.php
+++ b/apps/gallery/lib/scanner.php
@@ -24,7 +24,7 @@
 class OC_Gallery_Scanner {
 
 	public static function getGalleryRoot() {
-		return OC_Preferences::getValue(OC_User::getUser(), 'gallery', 'root', '/');
+		return OCP\Config::getUserValue(OCP\USER::getUser(), 'gallery', 'root', '/');
 	}
 	public static function getScanningRoot() {
 		return OC_Filesystem::getRoot().self::getGalleryRoot();
@@ -43,7 +43,7 @@ class OC_Gallery_Scanner {
 	public static function scan($eventSource) {
 		$paths = self::findPaths();
 		$eventSource->send('count', count($paths)+1);
-		$owner = OC_User::getUser();
+		$owner = OCP\USER::getUser();
 		foreach ($paths as $path) {
 			$name = self::createName($path);
 			$images = self::findFiles($path);
@@ -81,7 +81,7 @@ class OC_Gallery_Scanner {
 				$image->destroy();
 			}
 		}
-		imagepng($thumbnail, OC_Config::getValue("datadirectory").'/'. OC_User::getUser() .'/gallery/' . $albumName.'.png');
+		imagepng($thumbnail, OCP\Config::getSystemValue("datadirectory").'/'. OCP\USER::getUser() .'/gallery/' . $albumName.'.png');
 		imagedestroy($thumbnail);
 	}
 
@@ -96,7 +96,7 @@ class OC_Gallery_Scanner {
 					$p = $paths[$i-1];
 					foreach ($a as $e) {
 						$p .= ($p == '/'?'':'/').$e;
-						OC_Gallery_Album::create(OC_User::getUser(), $e, $p);
+						OC_Gallery_Album::create(OCP\USER::getUser(), $e, $p);
             $arr = OC_FileCache::searchByMime('image','', OC_Filesystem::getRoot().$p);
             $step = floor(count($arr)/10);
             if ($step == 0) $step = 1;
diff --git a/apps/gallery/lib/sharing.php b/apps/gallery/lib/sharing.php
old mode 100644
new mode 100755
index 60f108bd6c6cbc5efea6103c3b623e9243c3037a..fffeca032a39209522303715c8482a4eca80fd08
--- a/apps/gallery/lib/sharing.php
+++ b/apps/gallery/lib/sharing.php
@@ -24,7 +24,7 @@
 class OC_Gallery_Sharing {
   private static function getEntries($token) {
     $sql = 'SELECT * FROM *PREFIX*gallery_sharing WHERE token = ?';
-    $stmt = OC_DB::prepare($sql);
+    $stmt = OCP\DB::prepare($sql);
     return $stmt->execute(array($token));
   }
 
@@ -45,7 +45,7 @@ class OC_Gallery_Sharing {
     if ($row = $r->fetchRow()) {
       $galleryId = $row['gallery_id'];
       $sql = 'SELECT * FROM *PREFIX*gallery_albums WHERE album_id = ?';
-      $stmt = OC_DB::prepare($sql);
+      $stmt = OCP\DB::prepare($sql);
       $r = $stmt->execute(array($galleryId));
       if ($row = $r->fetchRow())
        return $row['uid_owner'];
@@ -58,7 +58,7 @@ class OC_Gallery_Sharing {
     if ($row = $r->fetchRow()) {
       $galleryId = $row['gallery_id'];
       $sql = 'SELECT * FROM *PREFIX*gallery_albums WHERE album_id = ?';
-      $stmt = OC_DB::prepare($sql);
+      $stmt = OCP\DB::prepare($sql);
       $r = $stmt->execute(array($galleryId));
       if ($row = $r->fetchRow())
         return $row['album_path'];
@@ -66,23 +66,23 @@ class OC_Gallery_Sharing {
   }
 
   public static function updateSharingByToken($token, $recursive) {
-    $stmt = OC_DB::prepare('UPDATE *PREFIX*gallery_sharing SET recursive = ? WHERE token = ?');
+    $stmt = OCP\DB::prepare('UPDATE *PREFIX*gallery_sharing SET recursive = ? WHERE token = ?');
     $stmt->execute(array($recursive, $token));
   }
 
   public static function getEntryByAlbumId($album_id) {
-    $stmt = OC_DB::prepare('SELECT * FROM *PREFIX*gallery_sharing WHERE gallery_id = ?');
+    $stmt = OCP\DB::prepare('SELECT * FROM *PREFIX*gallery_sharing WHERE gallery_id = ?');
     return $stmt->execute(array($album_id));
   }
 
   public static function addShared($token, $albumId, $recursive) {
     $sql = 'INSERT INTO *PREFIX*gallery_sharing (token, gallery_id, recursive) VALUES (?, ?, ?)';
-    $stmt = OC_DB::prepare($sql);
+    $stmt = OCP\DB::prepare($sql);
     $stmt->execute(array($token, $albumId, $recursive));
   }
 
   public static function remove($albumId) {
-    $stmt = OC_DB::prepare('DELETE FROM *PREFIX*gallery_sharing WHERE gallery_id = ?');
+    $stmt = OCP\DB::prepare('DELETE FROM *PREFIX*gallery_sharing WHERE gallery_id = ?');
     $stmt->execute(array($albumId));
   }
 }
diff --git a/apps/gallery/sharing.php b/apps/gallery/sharing.php
old mode 100644
new mode 100755
index d7430becf4329b4c8c8efd87976f932520b0a7a1..44fcd9c864b35337a3544fcb9c5a5d53bbd5903b
--- a/apps/gallery/sharing.php
+++ b/apps/gallery/sharing.php
@@ -25,9 +25,9 @@ if (!isset($_GET['token']) || empty($_GET['token'])) {
   exit;
 }
 
-require_once('../../lib/base.php');
 
-OC_Util::checkAppEnabled('gallery');
+
+OCP\App::checkAppEnabled('gallery');
 
 ?>
 <!doctype html>
diff --git a/apps/gallery/templates/index.php b/apps/gallery/templates/index.php
old mode 100644
new mode 100755
index 9bec5db1b9131da268db2ba004e69f896d1f625a..854e4480bcf6177baa93999cc565f53878773e40
--- a/apps/gallery/templates/index.php
+++ b/apps/gallery/templates/index.php
@@ -1,15 +1,15 @@
 <?php
-OC_Util::addStyle('gallery', 'styles');
-OC_Util::addScript('gallery', 'albums');
-OC_Util::addScript('gallery', 'scanner');
-OC_Util::addScript('gallery', 'album_cover');
-OC_Util::addStyle('files', 'files');
-OC_Util::addScript('files_imageviewer', 'jquery.mousewheel-3.0.4.pack');
-OC_Util::addScript('files_imageviewer', 'jquery.fancybox-1.3.4.pack');
-OC_Util::addStyle( 'files_imageviewer', 'jquery.fancybox-1.3.4' );
-$l = new OC_L10N('gallery');
+OCP\Util::addStyle('gallery', 'styles');
+OCP\Util::addscript('gallery', 'albums');
+OCP\Util::addscript('gallery', 'scanner');
+OCP\Util::addscript('gallery', 'album_cover');
+OCP\Util::addStyle('files', 'files');
+OCP\Util::addscript('files_imageviewer', 'jquery.mousewheel-3.0.4.pack');
+OCP\Util::addscript('files_imageviewer', 'jquery.fancybox-1.3.4.pack');
+OCP\Util::addStyle( 'files_imageviewer', 'jquery.fancybox-1.3.4' );
+$l = OC_L10N::get('gallery');
 ?>
-<script type="text/javascript">var gallery_scanning_root='<? echo OC_Preferences::getValue(OC_User::getUser(), 'gallery', 'root', '/'); ?>'; var gallery_default_order = '<? echo OC_Preferences::getValue(OC_User::getUser(), 'gallery', 'order', 'ASC'); ?>';</script>
+<script type="text/javascript">var gallery_scanning_root='<? echo OCP\Config::getUserValue(OCP\USER::getUser(), 'gallery', 'root', '/'); ?>'; var gallery_default_order = '<? echo OCP\Config::getUserValue(OCP\USER::getUser(), 'gallery', 'order', 'ASC'); ?>';</script>
 <div id="controls">
 	<div id="scan">
 		<div id="scanprogressbar"></div>
@@ -24,7 +24,7 @@ $l = new OC_L10N('gallery');
 		</div>
 	</div>
 	<div id="g-album-loading" class="crumb" style="display:none">
-		<img src="img/loading.gif">
+		<img src="<?php echo OCP\Util::linkTo('gallery', 'img/loading.gif'); ?>">
 	</div>
 </div>
 <div id="gallery_list">
diff --git a/apps/gallery/templates/view_album.php b/apps/gallery/templates/view_album.php
old mode 100644
new mode 100755
index 6b513a672d5a569bbab8d559fee06962d88f86a3..c16ed69c0658015fb95fc590121f8c115fb715f6
--- a/apps/gallery/templates/view_album.php
+++ b/apps/gallery/templates/view_album.php
@@ -1,11 +1,11 @@
 <?php
-OC_Util::addStyle('gallery', 'styles');
-OC_Util::addScript('gallery', 'albums');
-OC_Util::addScript('gallery', 'album_cover');
-OC_Util::addScript('files_imageviewer', 'jquery.mousewheel-3.0.4.pack');
-OC_Util::addScript('files_imageviewer', 'jquery.fancybox-1.3.4.pack');
-OC_Util::addStyle( 'files_imageviewer', 'jquery.fancybox-1.3.4' );
-$l = new OC_L10N('gallery');
+OCP\Util::addStyle('gallery', 'styles');
+OCP\Util::addscript('gallery', 'albums');
+OCP\Util::addscript('gallery', 'album_cover');
+OCP\Util::addscript('files_imageviewer', 'jquery.mousewheel-3.0.4.pack');
+OCP\Util::addscript('files_imageviewer', 'jquery.fancybox-1.3.4.pack');
+OCP\Util::addStyle( 'files_imageviewer', 'jquery.fancybox-1.3.4' );
+$l = OC_L10N::get('gallery');
 ?>
 <script type="text/javascript">
   $(document).ready(function() {
diff --git a/apps/media/ajax/api.php b/apps/media/ajax/api.php
old mode 100644
new mode 100755
index 9d9c14deb1705d02977e0b92d9f04a3314fba2ca..37dc638019875a2d6358e603f8cff4fa46e5d14f
--- a/apps/media/ajax/api.php
+++ b/apps/media/ajax/api.php
@@ -23,10 +23,9 @@
 
 header('Content-type: text/html; charset=UTF-8') ;
 
-require_once('../../../lib/base.php');
-OC_JSON::checkAppEnabled('media');
-require_once('../lib_collection.php');
-require_once('../lib_scanner.php');
+OCP\JSON::checkAppEnabled('media');
+require_once(OC::$APPSROOT . '/apps/media/lib_collection.php');
+require_once(OC::$APPSROOT . '/apps/media/lib_scanner.php');
 
 error_reporting(E_ALL); //no script error reporting because of getID3
 
@@ -49,43 +48,43 @@ if(!isset($arguments['album'])){
 if(!isset($arguments['search'])){
 	$arguments['search']='';
 }
-OC_MEDIA_COLLECTION::$uid=OC_User::getUser();
+OC_MEDIA_COLLECTION::$uid=OCP\USER::getUser();
 if($arguments['action']){
 	switch($arguments['action']){
 		case 'delete':
 			$path=$arguments['path'];
 			OC_MEDIA_COLLECTION::deleteSongByPath($path);
-			$paths=explode(PATH_SEPARATOR,OC_Preferences::getValue(OC_User::getUser(),'media','paths',''));
+			$paths=explode(PATH_SEPARATOR,OCP\Config::getUserValue(OCP\USER::getUser(),'media','paths',''));
 			if(array_search($path,$paths)!==false){
 				unset($paths[array_search($path,$paths)]);
-				OC_Preferences::setValue(OC_User::getUser(),'media','paths',implode(PATH_SEPARATOR,$paths));
+				OCP\Config::setUserValue(OCP\USER::getUser(),'media','paths',implode(PATH_SEPARATOR,$paths));
 			}
 		case 'get_collection':
 			$data=array();
 			$data['artists']=OC_MEDIA_COLLECTION::getArtists();
 			$data['albums']=OC_MEDIA_COLLECTION::getAlbums();
 			$data['songs']=OC_MEDIA_COLLECTION::getSongs();
-			OC_JSON::encodedPrint($data);
+			OCP\JSON::encodedPrint($data);
 			break;
 		case 'scan':
-			OC_DB::beginTransaction();
+			OCP\DB::beginTransaction();
 			set_time_limit(0); //recursive scan can take a while
 			$eventSource=new OC_EventSource();
 			OC_MEDIA_SCANNER::scanCollection($eventSource);
 			$eventSource->close();
-			OC_DB::commit();
+			OCP\DB::commit();
 			break;
 		case 'scanFile':
 			echo (OC_MEDIA_SCANNER::scanFile($arguments['path']))?'true':'false';
 			break;
 		case 'get_artists':
-			OC_JSON::encodedPrint(OC_MEDIA_COLLECTION::getArtists($arguments['search']));
+			OCP\JSON::encodedPrint(OC_MEDIA_COLLECTION::getArtists($arguments['search']));
 			break;
 		case 'get_albums':
-			OC_JSON::encodedPrint(OC_MEDIA_COLLECTION::getAlbums($arguments['artist'],$arguments['search']));
+			OCP\JSON::encodedPrint(OC_MEDIA_COLLECTION::getAlbums($arguments['artist'],$arguments['search']));
 			break;
 		case 'get_songs':
-			OC_JSON::encodedPrint(OC_MEDIA_COLLECTION::getSongs($arguments['artist'],$arguments['album'],$arguments['search']));
+			OCP\JSON::encodedPrint(OC_MEDIA_COLLECTION::getSongs($arguments['artist'],$arguments['album'],$arguments['search']));
 			break;
 		case 'get_path_info':
 			if(OC_Filesystem::file_exists($arguments['path'])){
@@ -98,7 +97,7 @@ if($arguments['action']){
 					$song=OC_MEDIA_COLLECTION::getSong($songId);
 					$song['artist']=OC_MEDIA_COLLECTION::getArtistName($song['song_artist']);
 					$song['album']=OC_MEDIA_COLLECTION::getAlbumName($song['song_album']);
-					OC_JSON::encodedPrint($song);
+					OCP\JSON::encodedPrint($song);
 				}
 			}
 			break;
@@ -111,11 +110,11 @@ if($arguments['action']){
 			OC_MEDIA_COLLECTION::registerPlay($songId);
 			
 			header('Content-Type:'.$ftype);
-			OC_Response::enableCaching(3600 * 24); // 24 hour
+			OCP\Response::enableCaching(3600 * 24); // 24 hour
 			header('Accept-Ranges: bytes');
 			header('Content-Length: '.OC_Filesystem::filesize($arguments['path']));
 			$mtime = OC_Filesystem::filemtime($arguments['path']);
-			OC_Response::setLastModifiedHeader($mtime);
+			OCP\Response::setLastModifiedHeader($mtime);
 			
 			OC_Filesystem::readfile($arguments['path']);
 			exit;
@@ -123,9 +122,8 @@ if($arguments['action']){
 			$music=OC_FileCache::searchByMime('audio');
 			$ogg=OC_FileCache::searchByMime('application','ogg');
 			$music=array_merge($music,$ogg);
-			OC_JSON::encodedPrint($music);
+			OCP\JSON::encodedPrint($music);
 			exit;
 	}
 }
-
-?>
+?>
\ No newline at end of file
diff --git a/apps/media/ajax/autoupdate.php b/apps/media/ajax/autoupdate.php
old mode 100644
new mode 100755
index a78b5e25dd1290f83b4d45506e1991130ae0b5ab..3122c7e6754193310f626343f3d9c226b714f284
--- a/apps/media/ajax/autoupdate.php
+++ b/apps/media/ajax/autoupdate.php
@@ -27,12 +27,12 @@ header('Content-type: text/html; charset=UTF-8') ;
 $RUNTIME_NOAPPS=true;
 $RUNTIME_NOSETUPFS=true;
 
-require_once('../../../lib/base.php');
-OC_JSON::checkAppEnabled('media');
+ 
+OCP\JSON::checkAppEnabled('media');
 
 $autoUpdate=(isset($_GET['autoupdate']) and $_GET['autoupdate']=='true');
 
-OC_Preferences::setValue(OC_User::getUser(),'media','autoupdate',(integer)$autoUpdate);
+OCP\Config::setUserValue(OCP\USER::getUser(),'media','autoupdate',(integer)$autoUpdate);
 
-OC_JSON::success(array('data' => $autoUpdate));
+OCP\JSON::success(array('data' => $autoUpdate));
 ?>
diff --git a/apps/media/appinfo/app.php b/apps/media/appinfo/app.php
old mode 100644
new mode 100755
index 651067fbbe1139cf7504fb6dd37c8f426b38a2ad..26cb2045549882e6dd630f2d36390d462950dfd2
--- a/apps/media/appinfo/app.php
+++ b/apps/media/appinfo/app.php
@@ -20,15 +20,15 @@
  *
  */
 
-$l=new OC_L10N('media');
+$l=OC_L10N::get('media');
 
 require_once('apps/media/lib_media.php');
 
-OC_Util::addScript('media','loader');
-OC_APP::registerPersonal('media','settings');
+OCP\Util::addscript('media','loader');
+OCP\App::registerPersonal('media','settings');
 
-OC_App::register( array( 'order' => 3, 'id' => 'media', 'name' => 'Media' ));
+OCP\App::register( array( 'order' => 3, 'id' => 'media', 'name' => 'Media' ));
 
-OC_App::addNavigationEntry(array('id' => 'media_index', 'order' => 2, 'href' => OC_Helper::linkTo('media', 'index.php'), 'icon' => OC_Helper::imagePath('core', 'places/music.svg'), 'name' => $l->t('Music')));
+OCP\App::addNavigationEntry(array('id' => 'media_index', 'order' => 2, 'href' => OCP\Util::linkTo('media', 'index.php'), 'icon' => OCP\Util::imagePath('core', 'places/music.svg'), 'name' => $l->t('Music')));
 
 OC_Search::registerProvider('OC_MediaSearchProvider');
diff --git a/apps/media/appinfo/info.xml b/apps/media/appinfo/info.xml
index 4a642bf889de2b0ef573553f9223034a2efe3037..01145d4a944f781a49e89a3b5f0bb07214645666 100644
--- a/apps/media/appinfo/info.xml
+++ b/apps/media/appinfo/info.xml
@@ -3,7 +3,6 @@
 	<id>media</id>
 	<name>Media</name>
 	<description>Media player and server for ownCloud</description>
-	<version>0.3</version>
 	<licence>AGPL</licence>
 	<author>Robin Appelman</author>
 	<require>2</require>
diff --git a/apps/media/appinfo/version b/apps/media/appinfo/version
new file mode 100644
index 0000000000000000000000000000000000000000..1d71ef97443918d538e8188167c94d7bbafaf753
--- /dev/null
+++ b/apps/media/appinfo/version
@@ -0,0 +1 @@
+0.3
\ No newline at end of file
diff --git a/apps/media/css/music.css b/apps/media/css/music.css
index 164a6c62ae6f0d0ee5e4840d1489772a1b3e99e7..c782e8afeeb2c87ea0afcb6f152b7503cc5d05fb 100644
--- a/apps/media/css/music.css
+++ b/apps/media/css/music.css
@@ -1,3 +1,7 @@
+/* Copyright (c) 2011, Jan-Christoph Borchardt, http://jancborchardt.net
+ This file is licensed under the Affero General Public License version 3 or later.
+ See the COPYING-README file. */
+
 #controls ul.jp-controls { padding:0; }
 #controls ul.jp-controls li { display:inline; }
 #controls ul.jp-controls li a { position:absolute; padding:.8em 1em .8em 0; }
diff --git a/apps/media/index.php b/apps/media/index.php
old mode 100644
new mode 100755
index 419d4ae0bde1bbc70ef0be4232201132236fc23f..e2911361ea2065110c9a61eb5b6321d9d3b09163
--- a/apps/media/index.php
+++ b/apps/media/index.php
@@ -22,24 +22,24 @@
 */
 
 
-require_once('../../lib/base.php');
+
 
 // Check if we are a user
-OC_Util::checkLoggedIn();
-OC_Util::checkAppEnabled('media');
+OCP\User::checkLoggedIn();
+OCP\App::checkAppEnabled('media');
 
-require_once('lib_collection.php');
-require_once('lib_scanner.php');
+require_once(OC::$APPSROOT . '/apps/media/lib_collection.php');
+require_once(OC::$APPSROOT . '/apps/media/lib_scanner.php');
 
-OC_Util::addScript('media','player');
-OC_Util::addScript('media','music');
-OC_Util::addScript('media','playlist');
-OC_Util::addScript('media','collection');
-OC_Util::addScript('media','scanner');
-OC_Util::addScript('media','jquery.jplayer.min');
-OC_Util::addStyle('media','music');
+OCP\Util::addscript('media','player');
+OCP\Util::addscript('media','music');
+OCP\Util::addscript('media','playlist');
+OCP\Util::addscript('media','collection');
+OCP\Util::addscript('media','scanner');
+OCP\Util::addscript('media','jquery.jplayer.min');
+OCP\Util::addStyle('media','music');
 
-OC_App::setActiveNavigationEntry( 'media_index' );
+OCP\App::setActiveNavigationEntry( 'media_index' );
 
 $tmpl = new OC_Template( 'media', 'music', 'user' );
 $tmpl->printPage();
diff --git a/apps/media/js/collection.js b/apps/media/js/collection.js
index 753785f77b0b0d2933f04a7fc4a8e597360a6a55..0b5a9ef9a47446cce4c24bff2bf7fe7ec181f91b 100644
--- a/apps/media/js/collection.js
+++ b/apps/media/js/collection.js
@@ -15,6 +15,11 @@ Collection={
 		}
 		if(!Collection.loading){
 			Collection.loading=true;
+			Collection.artists=[];
+			Collection.albums=[];
+			Collection.songs=[];
+			Collection.artistsById={};
+			Collection.albumsById={};
 			$.ajax({
 				url: OC.linkTo('media','ajax/api.php')+'?action=get_collection',
 				dataType: 'json',
@@ -107,6 +112,7 @@ Collection={
 							Collection.parent.find('tr').removeClass('active');
 							$('tr[data-artist="'+artist.name+'"]').addClass('active');
 						});
+						expander='';
 						if(artist.songs.length>1){
 							expander=$('<a class="expander">&gt;</a>');
 							expander.data('expanded',false);
diff --git a/apps/media/js/loader.js b/apps/media/js/loader.js
index 514965666fa3bbab05897c306806d37de6c04855..393f8ba914ed41ab0916c7a0f45fc1c8b6ebf38e 100644
--- a/apps/media/js/loader.js
+++ b/apps/media/js/loader.js
@@ -1,10 +1,10 @@
 function musicTypeFromFile(file){
-	var extention=file.substr(file.indexOf('.')+1).toLowerCase();
-	if(extention=='ogg'){
+	var extension=file.substr(file.indexOf('.')+1).toLowerCase();
+	if(extension=='ogg'){
 		return 'oga';
 	}
 	//TODO check for more specific cases
-	return extention;
+	return extension;
 }
 
 function playAudio(filename){
diff --git a/apps/media/js/music.js b/apps/media/js/music.js
index f93f0fded6248be495e65ec6a4985ebf2bdf54e9..db12922762653fbbe86829b8159a80f53ed1f946 100644
--- a/apps/media/js/music.js
+++ b/apps/media/js/music.js
@@ -48,10 +48,10 @@ function getUrlVars(){
 }
 
 function musicTypeFromFile(file){
-	var extention=file.split('.').pop().toLowerCase();
-	if(extention=='ogg'){
+	var extension=file.split('.').pop().toLowerCase();
+	if(extension=='ogg'){
 		return 'oga';
 	}
 	//TODO check for more specific cases
-	return extention;
+	return extension;
 }
diff --git a/apps/media/lib_ampache.php b/apps/media/lib_ampache.php
old mode 100644
new mode 100755
index 97c0930860726873503e8a9b71da6802616e5e27..d658605611c41c4447812bdd865d494d9674426f
--- a/apps/media/lib_ampache.php
+++ b/apps/media/lib_ampache.php
@@ -65,7 +65,7 @@ class OC_MEDIA_AMPACHE{
 </root>");
 		}
 		if($auth and $user and $time){
-			$query=OC_DB::prepare("SELECT user_id, user_password_sha256 from *PREFIX*media_users WHERE user_id=?");
+			$query=OCP\DB::prepare("SELECT user_id, user_password_sha256 from *PREFIX*media_users WHERE user_id=?");
 			$users=$query->execute(array($user))->fetchAll();
 			if(count($users)>0){
 				$pass=$users[0]['user_password_sha256'];
@@ -77,7 +77,7 @@ class OC_MEDIA_AMPACHE{
 					$songs=OC_MEDIA_COLLECTION::getSongCount();
 					$artists=OC_MEDIA_COLLECTION::getArtistCount();
 					$albums=OC_MEDIA_COLLECTION::getAlbumCount();
-					$query=OC_DB::prepare("INSERT INTO *PREFIX*media_sessions (`session_id`, `token`, `user_id`, `start`) VALUES (NULL, ?, ?, now());");
+					$query=OCP\DB::prepare("INSERT INTO *PREFIX*media_sessions (`session_id`, `token`, `user_id`, `start`) VALUES (NULL, ?, ?, now());");
 					$query->execute(array($token,$user));
 					$expire=date('c',time()+600);
 					echo('<?xml version="1.0" encoding="UTF-8"?>');
@@ -137,10 +137,10 @@ class OC_MEDIA_AMPACHE{
 			}
 		}
 		//remove old sessions
-		$query=OC_DB::prepare("DELETE from *PREFIX*media_sessions WHERE start<(NOW()-600)");
+		$query=OCP\DB::prepare("DELETE from *PREFIX*media_sessions WHERE start<(NOW()-600)");
 		$query->execute();
 		
-		$query=OC_DB::prepare("SELECT user_id from *PREFIX*media_sessions WHERE token=?");
+		$query=OCP\DB::prepare("SELECT user_id from *PREFIX*media_sessions WHERE token=?");
 		$users=$query->execute(array($auth))->fetchAll();
 		if(count($users)>0){
 			OC_MEDIA_COLLECTION::$uid=$users[0]['user_id'];
@@ -151,7 +151,7 @@ class OC_MEDIA_AMPACHE{
 	}
 	
 	public static function updateAuth($auth){
-		$query=OC_DB::prepare("UPDATE *PREFIX*media_sessions SET start=CURRENT_TIMESTAMP WHERE token=?");
+		$query=OCP\DB::prepare("UPDATE *PREFIX*media_sessions SET start=CURRENT_TIMESTAMP WHERE token=?");
 		$query->execute(array($auth));
 	}
 	
@@ -207,7 +207,7 @@ class OC_MEDIA_AMPACHE{
 		echo("\t\t<title>$name</title>\n");
 		echo("\t\t<artist id='$artist'>$artistName</artist>\n");
 		echo("\t\t<album id='$album'>$albumName</album>\n");
-		$url=OC_Helper::linkToAbsolute('media', 'server/xml.server.php')."?action=play&song=$id&auth={$_GET['auth']}";
+		$url=OCP\Util::linkToAbsolute('media', 'server/xml.server.php')."?action=play&song=$id&auth={$_GET['auth']}";
 		$url=self::fixXmlString($url);
 		echo("\t\t<url>$url</url>\n");
 		echo("\t\t<time>{$song['song_length']}</time>\n");
diff --git a/apps/media/lib_collection.php b/apps/media/lib_collection.php
old mode 100644
new mode 100755
index 411acd975060f0566794b33bfd31119af96c19ef..a32a50534ed119d8a02fa620fa324fc6646e3988
--- a/apps/media/lib_collection.php
+++ b/apps/media/lib_collection.php
@@ -43,7 +43,7 @@ class OC_MEDIA_COLLECTION{
 		if(isset(self::$artistIdCache[$name])){
 			return self::$artistIdCache[$name];
 		}else{
-			$query=OC_DB::prepare("SELECT artist_id FROM *PREFIX*media_artists WHERE lower(artist_name) LIKE ?");
+			$query=OCP\DB::prepare("SELECT artist_id FROM *PREFIX*media_artists WHERE lower(artist_name) LIKE ?");
 			$artists=$query->execute(array($name))->fetchAll();
 			if(is_array($artists) and isset($artists[0])){
 				self::$artistIdCache[$name]=$artists[0]['artist_id'];
@@ -71,7 +71,7 @@ class OC_MEDIA_COLLECTION{
 		if(isset(self::$albumIdCache[$artistId][$name])){
 			return self::$albumIdCache[$artistId][$name];
 		}else{
-			$query=OC_DB::prepare("SELECT album_id FROM *PREFIX*media_albums WHERE lower(album_name) LIKE ? AND album_artist=?");
+			$query=OCP\DB::prepare("SELECT album_id FROM *PREFIX*media_albums WHERE lower(album_name) LIKE ? AND album_artist=?");
 			$albums=$query->execute(array($name,$artistId))->fetchAll();
 			if(is_array($albums) and isset($albums[0])){
 				self::$albumIdCache[$artistId][$name]=$albums[0]['album_id'];
@@ -104,7 +104,7 @@ class OC_MEDIA_COLLECTION{
 			return self::$albumIdCache[$artistId][$albumId][$name];
 		}else{
 			$uid=$_SESSION['user_id'];
-			$query=OC_DB::prepare("SELECT song_id FROM *PREFIX*media_songs WHERE song_user=? AND song_name LIKE ? AND song_artist=? AND song_album=?");
+			$query=OCP\DB::prepare("SELECT song_id FROM *PREFIX*media_songs WHERE song_user=? AND song_name LIKE ? AND song_artist=? AND song_album=?");
 			$songs=$query->execute(array($uid,$name,$artistId,$albumId))->fetchAll();
 			if(is_array($songs) and isset($songs[0])){
 				self::$albumIdCache[$artistId][$albumId][$name]=$songs[0]['song_id'];
@@ -130,7 +130,7 @@ class OC_MEDIA_COLLECTION{
 		}elseif($search==''){
 			$search='%';
 		}
-		$query=OC_DB::prepare("SELECT DISTINCT artist_name, artist_id FROM *PREFIX*media_artists
+		$query=OCP\DB::prepare("SELECT DISTINCT artist_name, artist_id FROM *PREFIX*media_artists
 			INNER JOIN *PREFIX*media_songs ON artist_id=song_artist WHERE artist_name LIKE ? AND song_user=? ORDER BY artist_name");
 		$result=$query->execute(array($search,self::$uid));
 		return $result->fetchAll();
@@ -151,7 +151,7 @@ class OC_MEDIA_COLLECTION{
 		if($artistId!=0){
 			return $artistId;
 		}else{
-			$query=OC_DB::prepare("INSERT INTO `*PREFIX*media_artists` (`artist_name`) VALUES (?)");
+			$query=OCP\DB::prepare("INSERT INTO `*PREFIX*media_artists` (`artist_name`) VALUES (?)");
 			$result=$query->execute(array($name));
 			return self::getArtistId($name);;
 		}
@@ -183,7 +183,7 @@ class OC_MEDIA_COLLECTION{
 			array_push($params,$search);
 		}
 		$cmd.=' ORDER BY album_name';
-		$query=OC_DB::prepare($cmd);
+		$query=OCP\DB::prepare($cmd);
 		return $query->execute($params)->fetchAll();
 	}
 	
@@ -203,7 +203,7 @@ class OC_MEDIA_COLLECTION{
 		if($albumId!=0){
 			return $albumId;
 		}else{
-			$query=OC_DB::prepare("INSERT INTO  `*PREFIX*media_albums` (`album_name` ,`album_artist`) VALUES ( ?, ?)");
+			$query=OCP\DB::prepare("INSERT INTO  `*PREFIX*media_albums` (`album_name` ,`album_artist`) VALUES ( ?, ?)");
 			$query->execute(array($name,$artist));
 			return self::getAlbumId($name,$artist);
 		}
@@ -243,7 +243,7 @@ class OC_MEDIA_COLLECTION{
 		}else{
 			$searchString='';
 		}
-		$query=OC_DB::prepare("SELECT * FROM *PREFIX*media_songs WHERE song_user=? $artistString $albumString $searchString ORDER BY song_track, song_name, song_path");
+		$query=OCP\DB::prepare("SELECT * FROM *PREFIX*media_songs WHERE song_user=? $artistString $albumString $searchString ORDER BY song_track, song_name, song_path");
 		return $query->execute($params)->fetchAll();
 	}
 	
@@ -261,7 +261,7 @@ class OC_MEDIA_COLLECTION{
 		if($name=='' or $path==''){
 			return 0;
 		}
-		$uid=OC_User::getUser();
+		$uid=OCP\USER::getUser();
 		//check if the song is already in the database
 		$songId=self::getSongId($name,$artist,$album);
 		if($songId!=0){
@@ -270,39 +270,39 @@ class OC_MEDIA_COLLECTION{
 			return $songId;
 		}else{
 			if(!isset(self::$queries['addsong'])){
-				$query=OC_DB::prepare("INSERT INTO  `*PREFIX*media_songs` (`song_name` ,`song_artist` ,`song_album` ,`song_path` ,`song_user`,`song_length`,`song_track`,`song_size`,`song_playcount`,`song_lastplayed`)
+				$query=OCP\DB::prepare("INSERT INTO  `*PREFIX*media_songs` (`song_name` ,`song_artist` ,`song_album` ,`song_path` ,`song_user`,`song_length`,`song_track`,`song_size`,`song_playcount`,`song_lastplayed`)
 				VALUES (?, ?, ?, ?,?,?,?,?,0,0)");
 				self::$queries['addsong']=$query;
 			}else{
 				$query=self::$queries['addsong'];
 			}
 			$query->execute(array($name,$artist,$album,$path,$uid,$length,$track,$size));
-			$songId=OC_DB::insertid('*PREFIX*media_songs');
+			$songId=OCP\DB::insertid('*PREFIX*media_songs');
 // 			self::setLastUpdated();
 			return self::getSongId($name,$artist,$album);
 		}
 	}
 	
 	public static function getSongCount(){
-		$query=OC_DB::prepare("SELECT COUNT(song_id) AS count FROM *PREFIX*media_songs");
+		$query=OCP\DB::prepare("SELECT COUNT(song_id) AS count FROM *PREFIX*media_songs");
 		$result=$query->execute()->fetchAll();
 		return $result[0]['count'];
 	}
 	
 	public static function getArtistCount(){
-		$query=OC_DB::prepare("SELECT COUNT(artist_id) AS count FROM *PREFIX*media_artists");
+		$query=OCP\DB::prepare("SELECT COUNT(artist_id) AS count FROM *PREFIX*media_artists");
 		$result=$query->execute()->fetchAll();
 		return $result[0]['count'];
 	}
 	
 	public static function getAlbumCount(){
-		$query=OC_DB::prepare("SELECT COUNT(album_id) AS count FROM *PREFIX*media_albums");
+		$query=OCP\DB::prepare("SELECT COUNT(album_id) AS count FROM *PREFIX*media_albums");
 		$result=$query->execute()->fetchAll();
 		return $result[0]['count'];
 	}
 	
 	public static function getArtistName($artistId){
-		$query=OC_DB::prepare("SELECT artist_name FROM *PREFIX*media_artists WHERE artist_id=?");
+		$query=OCP\DB::prepare("SELECT artist_name FROM *PREFIX*media_artists WHERE artist_id=?");
 		$artist=$query->execute(array($artistId))->fetchAll();
 		if(count($artist)>0){
 			return $artist[0]['artist_name'];
@@ -312,7 +312,7 @@ class OC_MEDIA_COLLECTION{
 	}
 	
 	public static function getAlbumName($albumId){
-		$query=OC_DB::prepare("SELECT album_name FROM *PREFIX*media_albums WHERE album_id=?");
+		$query=OCP\DB::prepare("SELECT album_name FROM *PREFIX*media_albums WHERE album_id=?");
 		$album=$query->execute(array($albumId))->fetchAll();
 		if(count($album)>0){
 			return $album[0]['album_name'];
@@ -322,7 +322,7 @@ class OC_MEDIA_COLLECTION{
 	}
 	
 	public static function getSong($id){
-		$query=OC_DB::prepare("SELECT * FROM *PREFIX*media_songs WHERE song_id=?");
+		$query=OCP\DB::prepare("SELECT * FROM *PREFIX*media_songs WHERE song_id=?");
 		$song=$query->execute(array($id))->fetchAll();
 		if(count($song)>0){
 			return $song[0];
@@ -336,7 +336,7 @@ class OC_MEDIA_COLLECTION{
 	 * @param string $path
 	 */
 	public static function getSongCountByPath($path){
-		$query=OC_DB::prepare("SELECT COUNT(song_id) AS count FROM *PREFIX*media_songs WHERE song_path LIKE ?");
+		$query=OCP\DB::prepare("SELECT COUNT(song_id) AS count FROM *PREFIX*media_songs WHERE song_path LIKE ?");
 		$result=$query->execute(array("$path%"))->fetchAll();
 		return $result[0]['count'];
 	}
@@ -348,7 +348,7 @@ class OC_MEDIA_COLLECTION{
 	 * if a path of a folder is passed, all songs stored in the folder will be removed from the database
 	 */
 	public static function deleteSongByPath($path){
-		$query=OC_DB::prepare("DELETE FROM *PREFIX*media_songs WHERE song_path LIKE ?");
+		$query=OCP\DB::prepare("DELETE FROM *PREFIX*media_songs WHERE song_path LIKE ?");
 		$query->execute(array("$path%"));
 	}
 
@@ -358,7 +358,7 @@ class OC_MEDIA_COLLECTION{
 	 */
 	public static function registerPlay($songId){
 		$now=time();
-		$query=OC_DB::prepare('UPDATE *PREFIX*media_songs SET song_playcount=song_playcount+1, song_lastplayed=? WHERE song_id=? AND song_lastplayed<?');
+		$query=OCP\DB::prepare('UPDATE *PREFIX*media_songs SET song_playcount=song_playcount+1, song_lastplayed=? WHERE song_id=? AND song_lastplayed<?');
 		$query->execute(array($now,$songId,$now-60));
 	}
 
@@ -368,7 +368,7 @@ class OC_MEDIA_COLLECTION{
 	 * @return int
 	 */
 	public static function getSongByPath($path){
-		$query=OC_DB::prepare("SELECT song_id FROM *PREFIX*media_songs WHERE song_path = ?");
+		$query=OCP\DB::prepare("SELECT song_id FROM *PREFIX*media_songs WHERE song_path = ?");
 		$result=$query->execute(array($path));
 		if($row=$result->fetchRow()){
 			return $row['song_id'];
@@ -383,7 +383,7 @@ class OC_MEDIA_COLLECTION{
 	 * @param string $newPath
 	 */
 	public static function moveSong($oldPath,$newPath){
-		$query=OC_DB::prepare("UPDATE *PREFIX*media_songs SET song_path = ? WHERE song_path = ?");
+		$query=OCP\DB::prepare("UPDATE *PREFIX*media_songs SET song_path = ? WHERE song_path = ?");
 		$query->execute(array($newPath,$oldPath));
 	}
 }
diff --git a/apps/media/lib_media.php b/apps/media/lib_media.php
old mode 100644
new mode 100755
index a4e5a5dfebc35d3c6dd2855448e1d3eb6353cdb1..94c3fabe8a06c529e18cf58ac10f503e66c69f18
--- a/apps/media/lib_media.php
+++ b/apps/media/lib_media.php
@@ -41,11 +41,11 @@ class OC_MEDIA{
 	public static function loginListener($params){
 		if(isset($_POST['user']) and $_POST['password']){
 			$name=$_POST['user'];
-			$query=OC_DB::prepare("SELECT user_id from *PREFIX*media_users WHERE user_id LIKE ?");
+			$query=OCP\DB::prepare("SELECT user_id from *PREFIX*media_users WHERE user_id LIKE ?");
 			$uid=$query->execute(array($name))->fetchAll();
 			if(count($uid)==0){
 				$password=hash('sha256',$_POST['password']);
-				$query=OC_DB::prepare("INSERT INTO *PREFIX*media_users (user_id, user_password_sha256) VALUES (?, ?);");
+				$query=OCP\DB::prepare("INSERT INTO *PREFIX*media_users (user_id, user_password_sha256) VALUES (?, ?);");
 				$query->execute(array($name,$password));
 			}
 		}
@@ -90,18 +90,18 @@ class OC_MediaSearchProvider extends OC_Search_Provider{
 		$songs=OC_MEDIA_COLLECTION::getSongs(0,0,$query);
 		$results=array();
 		foreach($artists as $artist){
-			$results[]=new OC_Search_Result($artist['artist_name'],'',OC_Helper::linkTo( 'media', 'index.php').'#artist='.urlencode($artist['artist_name']),'Music');
+			$results[]=new OC_Search_Result($artist['artist_name'],'',OCP\Util::linkTo( 'media', 'index.php').'#artist='.urlencode($artist['artist_name']),'Music');
 		}
 		foreach($albums as $album){
 			$artist=OC_MEDIA_COLLECTION::getArtistName($album['album_artist']);
-			$results[]=new OC_Search_Result($album['album_name'],'by '.$artist,OC_Helper::linkTo( 'media', 'index.php').'#artist='.urlencode($artist).'&album='.urlencode($album['album_name']),'Music');
+			$results[]=new OC_Search_Result($album['album_name'],'by '.$artist,OCP\Util::linkTo( 'media', 'index.php').'#artist='.urlencode($artist).'&album='.urlencode($album['album_name']),'Music');
 		}
 		foreach($songs as $song){
 			$minutes=floor($song['song_length']/60);
 			$secconds=$song['song_length']%60;
 			$artist=OC_MEDIA_COLLECTION::getArtistName($song['song_artist']);
 			$album=OC_MEDIA_COLLECTION::getalbumName($song['song_album']);
-			$results[]=new OC_Search_Result($song['song_name'],"by $artist, in $album $minutes:$secconds",OC_Helper::linkTo( 'media', 'index.php').'#artist='.urlencode($artist).'&album='.urlencode($album).'&song='.urlencode($song['song_name']),'Music');
+			$results[]=new OC_Search_Result($song['song_name'],"by $artist, in $album $minutes:$secconds",OCP\Util::linkTo( 'media', 'index.php').'#artist='.urlencode($artist).'&album='.urlencode($album).'&song='.urlencode($song['song_name']),'Music');
 		}
 		return $results;
 	}
diff --git a/apps/media/lib_scanner.php b/apps/media/lib_scanner.php
old mode 100644
new mode 100755
index 341f411bdb81edfb770ccbd044ad96795de1c254..dc2a8a9beb4a1eef53e34feb747c0f9163529be7
--- a/apps/media/lib_scanner.php
+++ b/apps/media/lib_scanner.php
@@ -72,23 +72,23 @@ class OC_MEDIA_SCANNER{
 		$data=@self::$getID3->analyze($file);
 		getid3_lib::CopyTagsToComments($data);
 		if(!isset($data['comments'])){
-			OC_Log::write('media',"error reading id3 tags in '$file'",OC_Log::WARN);
+			OCP\Util::writeLog('media',"error reading id3 tags in '$file'",OCP\Util::WARN);
 			return;
 		}
 		if(!isset($data['comments']['artist'])){
-			OC_Log::write('media',"error reading artist tag in '$file'",OC_Log::WARN);
+			OCP\Util::writeLog('media',"error reading artist tag in '$file'",OCP\Util::WARN);
 			$artist='unknown';
 		}else{
 			$artist=stripslashes($data['comments']['artist'][0]);
 		}
 		if(!isset($data['comments']['album'])){
-			OC_Log::write('media',"error reading album tag in '$file'",OC_Log::WARN);
+			OCP\Util::writeLog('media',"error reading album tag in '$file'",OCP\Util::WARN);
 			$album='unknown';
 		}else{
 			$album=stripslashes($data['comments']['album'][0]);
 		}
 		if(!isset($data['comments']['title'])){
-			OC_Log::write('media',"error reading title tag in '$file'",OC_Log::WARN);
+			OCP\Util::writeLog('media',"error reading title tag in '$file'",OCP\Util::WARN);
 			$title='unknown';
 		}else{
 			$title=stripslashes($data['comments']['title'][0]);
@@ -127,7 +127,7 @@ class OC_MEDIA_SCANNER{
 	}
 
 	/**
-	 * quick check if a song is a music file by checking the extention, not as good as a proper mimetype check but way faster
+	 * quick check if a song is a music file by checking the extension, not as good as a proper mimetype check but way faster
 	 * @param string $filename
 	 * @return bool
 	 */
diff --git a/apps/media/server/xml.server.php b/apps/media/server/xml.server.php
old mode 100644
new mode 100755
index cb9b68fc4224462444248e5e380c52c258492e6c..63f2a51dcb51dbc6562261fd460ac975d1f3b79a
--- a/apps/media/server/xml.server.php
+++ b/apps/media/server/xml.server.php
@@ -21,11 +21,11 @@
 * 
 */
 
+require_once('../../inc.php');
 
-require_once('../../../lib/base.php');
-OC_Util::checkAppEnabled('media');
-require_once('../lib_collection.php');
-require_once('../lib_ampache.php');
+OCP\App::checkAppEnabled('media');
+ require_once(OC::$APPSROOT . '/apps/media/lib_collection.php');
+ require_once(OC::$APPSROOT . '/apps/media/lib_ampache.php');
 
 $arguments=$_POST;
 if(!isset($_POST['action']) and isset($_GET['action'])){
@@ -37,8 +37,11 @@ foreach($arguments as &$argument){
 }
 @ob_clean();
 if(isset($arguments['action'])){
-	OC_Log::write('media','ampache '.$arguments['action'].' request', OC_Log::DEBUG);
+	OCP\Util::writeLog('media','ampache '.$arguments['action'].' request', OCP\Util::DEBUG);
 	switch($arguments['action']){
+		case 'songs':
+			OC_MEDIA_AMPACHE::songs($arguments);
+			break;
 		case 'url_to_song':
 			OC_MEDIA_AMPACHE::url_to_song($arguments);
 			break;
diff --git a/apps/media/templates/settings.php b/apps/media/templates/settings.php
old mode 100644
new mode 100755
index 2907c616cf6830269f4024a9858d522d584d1e1a..2fe0b945a63d248a32fe9c0e990b28694aea1109
--- a/apps/media/templates/settings.php
+++ b/apps/media/templates/settings.php
@@ -2,6 +2,6 @@
 	<fieldset class="personalblock">
 		<strong>Media</strong><br />
 		Ampache address: 
-		<?php echo OC_Helper::linkToAbsolute('media', ''); ?><br />
+		<code><?php echo OCP\Util::linkToAbsolute('media', ''); ?></code><br />
 	</fieldset>
 </form>
diff --git a/apps/media/tomahawk.php b/apps/media/tomahawk.php
old mode 100644
new mode 100755
index 6dd41233f12929f8c5deb6a67ae747e7a02ebe5c..700a75bf41e87fd32f4d131b024943a99489324f
--- a/apps/media/tomahawk.php
+++ b/apps/media/tomahawk.php
@@ -22,14 +22,14 @@
 */
 
 $_POST=$_GET; //debug
+require_once('../inc.php');
 
-require_once('../../lib/base.php');
-OC_JSON::checkAppEnabled('media');
-require_once('lib_collection.php');
+OCP\JSON::checkAppEnabled('media');
+require_once(OC::$APPSROOT . '/apps/media/lib_collection.php');
 
 $user=isset($_POST['user'])?$_POST['user']:'';
 $pass=isset($_POST['pass'])?$_POST['pass']:'';
-if(OC_User::checkPassword($user,$pass)){
+if(OCP\User::checkPassword($user,$pass)){
 	OC_Util::setupFS($user);
 	OC_MEDIA_COLLECTION::$uid=$user;
 }else{
@@ -43,7 +43,7 @@ if(isset($_POST['play']) and $_POST['play']=='true'){
 	$song=OC_MEDIA_COLLECTION::getSong($_POST['song']);
 	$ftype=OC_Filesystem::getMimeType( $song['song_path'] );
 	header('Content-Type:'.$ftype);
-	OC_Response::disableCaching();
+	OCP\Response::disableCaching();
 	header('Content-Length: '.OC_Filesystem::filesize($song['song_path']));
 
 	OC_Filesystem::readfile($song['song_path']);
@@ -58,7 +58,7 @@ $album=OC_MEDIA_COLLECTION::getAlbumId($album,$artist);
 
 $songs=OC_MEDIA_COLLECTION::getSongs($artist,$album,$song);
 
-$baseUrl=OC_Util::getServerURL().OC_Helper::linkTo('media','tomahawk.php');
+$baseUrl=OC_Util::getServerURL().OCP\Util::linkTo('media','tomahawk.php');
 
 $results=array();
 foreach($songs as $song) {
@@ -76,5 +76,5 @@ foreach($songs as $song) {
 		'score' => (float)1.0
 	);
 }
-OC_JSON::encodedPrint($results);
+OCP\JSON::encodedPrint($results);
 ?>
diff --git a/apps/remoteStorage/WebDAV.php b/apps/remoteStorage/WebDAV.php
old mode 100644
new mode 100755
index cad465181a985488f5a70369f673e06c39b3988b..45f6cac31668b79897ed7ef7c22742d69edacb1e
--- a/apps/remoteStorage/WebDAV.php
+++ b/apps/remoteStorage/WebDAV.php
@@ -29,8 +29,8 @@
 // Do not load FS ...
 $RUNTIME_NOSETUPFS = true;
 
-require_once('../../lib/base.php');
-OC_Util::checkAppEnabled('remoteStorage');
+
+OCP\App::checkAppEnabled('remoteStorage');
 require_once('Sabre/autoload.php');
 require_once('lib_remoteStorage.php');
 require_once('BearerAuth.php');
diff --git a/apps/remoteStorage/ajax/revokeToken.php b/apps/remoteStorage/ajax/revokeToken.php
old mode 100644
new mode 100755
index ca56cf560ecdc868ee3f2e21a09d92673298b255..235a02107e6c8b570edabda8e0fb987a1b1e06c8
--- a/apps/remoteStorage/ajax/revokeToken.php
+++ b/apps/remoteStorage/ajax/revokeToken.php
@@ -29,8 +29,8 @@
 // Do not load FS ...
 $RUNTIME_NOSETUPFS = true;
 
-require_once('../../../lib/base.php');
-OC_Util::checkAppEnabled('remoteStorage');
+ 
+OCP\App::checkAppEnabled('remoteStorage');
 require_once('Sabre/autoload.php');
 require_once('../lib_remoteStorage.php');
 
diff --git a/apps/remoteStorage/appinfo/app.php b/apps/remoteStorage/appinfo/app.php
old mode 100644
new mode 100755
index a1fbebc42f57c424cb8d241930032d8ccff12e02..14b8a3d11dfdb3fe8660c26c0381e714e615aa88
--- a/apps/remoteStorage/appinfo/app.php
+++ b/apps/remoteStorage/appinfo/app.php
@@ -1,6 +1,6 @@
 <?php
-OC_App::register( array( 
+OCP\App::register( array( 
   'order' => 10,
   'id' => 'remoteStorage',
   'name' => 'remoteStorage compatibility' ));
-OC_APP::registerPersonal('remoteStorage','settings');
+OCP\App::registerPersonal('remoteStorage','settings');
diff --git a/apps/remoteStorage/appinfo/info.xml b/apps/remoteStorage/appinfo/info.xml
index 1f9618a3334a8911d850ec3c29a239cd73124848..1875e70a300c6e7cd62362d620da08c594f65c38 100644
--- a/apps/remoteStorage/appinfo/info.xml
+++ b/apps/remoteStorage/appinfo/info.xml
@@ -3,7 +3,6 @@
 	<id>remoteStorage</id>
 	<name>remoteStorage compatibility</name>
 	<description>Enables you to use ownCloud as their remote storage for unhosted applications. This app requires the Webfinger app to be installed and enabled correctly. More info on <a href="http://unhosted.org">the website of the unhosted movement</a>.</description>
-	<version>0.6</version>
 	<licence>AGPL or MIT</licence>
 	<author>Michiel de Jong</author>
 	<require>2</require>
diff --git a/apps/remoteStorage/appinfo/version b/apps/remoteStorage/appinfo/version
new file mode 100644
index 0000000000000000000000000000000000000000..490f510fc27c164443c2334282f67bd7034c1698
--- /dev/null
+++ b/apps/remoteStorage/appinfo/version
@@ -0,0 +1 @@
+0.6
\ No newline at end of file
diff --git a/apps/remoteStorage/auth.php b/apps/remoteStorage/auth.php
old mode 100644
new mode 100755
index c00f9d5555cbe8c4f25a2697cca2ab17d4a5c496..a5cbd6aca02b6287f47b0a7ddc91e6eec35d0ab9
--- a/apps/remoteStorage/auth.php
+++ b/apps/remoteStorage/auth.php
@@ -29,8 +29,8 @@
 // Do not load FS ...
 $RUNTIME_NOSETUPFS = true;
 
-require_once('../../lib/base.php');
-OC_Util::checkAppEnabled('remoteStorage');
+
+OCP\App::checkAppEnabled('remoteStorage');
 require_once('Sabre/autoload.php');
 require_once('lib_remoteStorage.php');
 require_once('oauth_ro_auth.php');
@@ -56,7 +56,7 @@ if(count($pathParts) == 2 && $pathParts[0] == '') {
 			$categories=$v;
 		}
 	}
-	$currUser = OC_User::getUser();
+	$currUser = OCP\USER::getUser();
 	if($currUser == $ownCloudUser) {
 		if(isset($_POST['allow'])) {
 			//TODO: check if this can be faked by editing the cookie in firebug!
@@ -77,7 +77,7 @@ if(count($pathParts) == 2 && $pathParts[0] == '') {
 	<div id="login">
 		<header>
 		<div id="header">
-			<img src="../../../core/img/owncloud-logo-medium-white.png" alt="ownCloud" />
+			<img src="../../../core/img/logo.png" alt="ownCloud" />
 		</div>
 		</header>
 		<section id="main">
diff --git a/apps/remoteStorage/lib_remoteStorage.php b/apps/remoteStorage/lib_remoteStorage.php
old mode 100644
new mode 100755
index 6e6a19c739f8fc8ef1b7086bcc861e1ca1436bb5..b6a7a43b7b29c0f3d685d154cff65210ed30985f
--- a/apps/remoteStorage/lib_remoteStorage.php
+++ b/apps/remoteStorage/lib_remoteStorage.php
@@ -2,7 +2,7 @@
 
 class OC_remoteStorage {
 	public static function getValidTokens($ownCloudUser, $category) {
-		$query=OC_DB::prepare("SELECT token,appUrl,category FROM *PREFIX*authtoken WHERE user=? LIMIT 100");
+		$query=OCP\DB::prepare("SELECT token,appUrl,category FROM *PREFIX*authtoken WHERE user=? LIMIT 100");
 		$result=$query->execute(array($ownCloudUser));
 		$ret = array();
 		while($row=$result->fetchRow()){
@@ -14,8 +14,8 @@ class OC_remoteStorage {
 	}
 
 	public static function getAllTokens() {
-		$user=OC_User::getUser();
-		$query=OC_DB::prepare("SELECT token,appUrl,category FROM *PREFIX*authtoken WHERE user=? LIMIT 100");
+		$user=OCP\USER::getUser();
+		$query=OCP\DB::prepare("SELECT token,appUrl,category FROM *PREFIX*authtoken WHERE user=? LIMIT 100");
 		$result=$query->execute(array($user));
 		$ret = array();
 		while($row=$result->fetchRow()){
@@ -28,19 +28,19 @@ class OC_remoteStorage {
 	}
 
 	public static function deleteToken($token) {
-		$user=OC_User::getUser();
-		$query=OC_DB::prepare("DELETE FROM *PREFIX*authtoken WHERE token=? AND user=?");
+		$user=OCP\USER::getUser();
+		$query=OCP\DB::prepare("DELETE FROM *PREFIX*authtoken WHERE token=? AND user=?");
 		$result=$query->execute(array($token,$user));
 		return 'unknown';//how can we see if any rows were affected?
 	}
 	private static function addToken($token, $appUrl, $categories){
-		$user=OC_User::getUser();
-		$query=OC_DB::prepare("INSERT INTO *PREFIX*authtoken (`token`,`appUrl`,`user`,`category`) VALUES(?,?,?,?)");
+		$user=OCP\USER::getUser();
+		$query=OCP\DB::prepare("INSERT INTO *PREFIX*authtoken (`token`,`appUrl`,`user`,`category`) VALUES(?,?,?,?)");
 		$result=$query->execute(array($token,$appUrl,$user,$categories));
 	}
 	public static function createCategories($appUrl, $categories) {
 		$token=uniqid();
-		OC_Util::setupFS(OC_User::getUser());
+		OC_Util::setupFS(OCP\USER::getUser());
 		self::addToken($token, $appUrl, $categories);
 		foreach(explode(',', $categories) as $category) {
 			//TODO: input checking on $category
diff --git a/apps/remoteStorage/templates/settings.php b/apps/remoteStorage/templates/settings.php
old mode 100644
new mode 100755
index 9b5c3b6229c2eda37a518ec6e61cddc075648c15..147378dda39efc32370ca7ac4a89fa223e2a330d
--- a/apps/remoteStorage/templates/settings.php
+++ b/apps/remoteStorage/templates/settings.php
@@ -1,8 +1,8 @@
 	<fieldset class="personalblock">
 		<?php
-			echo '<img src="/apps/remoteStorage/remoteStorage.png" style="width:16px"> '
+			echo '<img src="../apps/remoteStorage/remoteStorage.png" style="width:16px"> '
 				.'<strong>'.$l->t('remoteStorage').'</strong> user address: '
-				.OC_User::getUser().'@'.$_SERVER['SERVER_NAME']
+				.OCP\USER::getUser().'@'.$_SERVER['SERVER_NAME']
 				.' (<a href="http://unhosted.org/">more info</a>)';
 		?>
 		<p><em>Apps that currently have access to your ownCloud:</em></p>
diff --git a/apps/user_ldap/appinfo/app.php b/apps/user_ldap/appinfo/app.php
old mode 100644
new mode 100755
index 5c56ca8191e9988afaeef3af2fff1b133814dd2c..79675f940bcc7f2da47e3d06da5d4df92916287a
--- a/apps/user_ldap/appinfo/app.php
+++ b/apps/user_ldap/appinfo/app.php
@@ -21,9 +21,11 @@
 *
 */
 
+require_once('apps/user_ldap/lib_ldap.php');
 require_once('apps/user_ldap/user_ldap.php');
+require_once('apps/user_ldap/group_ldap.php');
 
-OC_APP::registerAdmin('user_ldap','settings');
+OCP\App::registerAdmin('user_ldap','settings');
 
 // define LDAP_DEFAULT_PORT
 define('OC_USER_BACKEND_LDAP_DEFAULT_PORT', 389);
@@ -33,12 +35,12 @@ define('OC_USER_BACKEND_LDAP_DEFAULT_DISPLAY_NAME', 'uid');
 
 // register user backend
 OC_User::useBackend( 'LDAP' );
+OC_Group::useBackend( new OC_GROUP_LDAP() );
 
 // add settings page to navigation
 $entry = array(
 	'id' => 'user_ldap_settings',
 	'order'=>1,
-	'href' => OC_Helper::linkTo( 'user_ldap', 'settings.php' ),
+	'href' => OCP\Util::linkTo( 'user_ldap', 'settings.php' ),
 	'name' => 'LDAP'
 );
-// OC_App::addNavigationSubEntry( "core_users", $entry);
diff --git a/apps/user_ldap/appinfo/database.xml b/apps/user_ldap/appinfo/database.xml
new file mode 100644
index 0000000000000000000000000000000000000000..74c56fcf7435952fd189ffaefa4e5fab0a881f73
--- /dev/null
+++ b/apps/user_ldap/appinfo/database.xml
@@ -0,0 +1,95 @@
+<?xml version="1.0" encoding="ISO-8859-1" ?>
+<database>
+
+ <name>*dbname*</name>
+ <create>true</create>
+ <overwrite>false</overwrite>
+ <charset>utf8</charset>
+
+ <table>
+
+  <name>*dbprefix*ldap_user_mapping</name>
+
+  <declaration>
+
+   <field>
+    <name>ldap_dn</name>
+    <type>text</type>
+    <notnull>true</notnull>
+	<length>255</length>
+	<default></default>
+   </field>
+
+   <field>
+    <name>owncloud_name</name>
+    <type>text</type>
+    <notnull>true</notnull>
+    <length>255</length>
+	<default></default>
+   </field>
+
+   <index>
+    <name>ldap_dn</name>
+    <unique>true</unique>
+    <field>
+     <name>ldap_dn</name>
+    </field>
+   </index>
+
+   <index>
+    <name>owncloud_name</name>
+    <unique>true</unique>
+    <field>
+     <name>owncloud_name</name>
+	 <sorting>ascending</sorting>
+    </field>
+   </index>
+
+  </declaration>
+
+ </table>
+
+ <table>
+
+  <name>*dbprefix*ldap_group_mapping</name>
+
+  <declaration>
+
+   <field>
+    <name>ldap_dn</name>
+    <type>text</type>
+    <notnull>true</notnull>
+    <length>255</length>
+    <default></default>
+   </field>
+
+   <field>
+    <name>owncloud_name</name>
+    <type>text</type>
+    <notnull>true</notnull>
+    <length>255</length>
+    <default></default>
+   </field>
+
+   <index>
+    <name>ldap_dn</name>
+    <unique>true</unique>
+    <field>
+     <name>ldap_dn</name>
+    </field>
+   </index>
+
+   <index>
+    <name>owncloud_name</name>
+    <unique>true</unique>
+    <field>
+     <name>owncloud_name</name>
+     <sorting>ascending</sorting>
+    </field>
+   </index>
+
+  </declaration>
+
+ </table>
+
+</database>
\ No newline at end of file
diff --git a/apps/user_ldap/appinfo/info.xml b/apps/user_ldap/appinfo/info.xml
index 99830dd1ffdc2cdecfd8e4c3e4f1b946799cc86f..fe7e61fb5c3a3762dc933fc5d7828e670e151fe3 100644
--- a/apps/user_ldap/appinfo/info.xml
+++ b/apps/user_ldap/appinfo/info.xml
@@ -3,7 +3,6 @@
 	<id>user_ldap</id>
 	<name>LDAP user backend</name>
 	<description>Authenticate Users by LDAP</description>
-	<version>0.1</version>
 	<licence>AGPL</licence>
 	<author>Dominik Schmidt</author>
 	<require>2</require>
diff --git a/apps/user_ldap/appinfo/version b/apps/user_ldap/appinfo/version
new file mode 100644
index 0000000000000000000000000000000000000000..a0d78bd347e089e143f3ded0ecfb6dd6ba382545
--- /dev/null
+++ b/apps/user_ldap/appinfo/version
@@ -0,0 +1 @@
+0.1.90
\ No newline at end of file
diff --git a/apps/user_ldap/group_ldap.php b/apps/user_ldap/group_ldap.php
new file mode 100755
index 0000000000000000000000000000000000000000..a38c1b9b78bb05dba70982455a66116e8cf2ea51
--- /dev/null
+++ b/apps/user_ldap/group_ldap.php
@@ -0,0 +1,137 @@
+<?php
+
+/**
+ * ownCloud – LDAP group backend
+ *
+ * @author Arthur Schiwon
+ * @copyright 2012 Arthur Schiwon blizzz@owncloud.com
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or any later version.
+ *
+ * This library 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 AFFERO GENERAL PUBLIC LICENSE for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public
+ * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+class OC_GROUP_LDAP extends OC_Group_Backend {
+// 	//group specific settings
+	protected $ldapGroupFilter;
+
+	public function __construct() {
+		$this->ldapGroupFilter      = OCP\Config::getAppValue('user_ldap', 'ldap_group_filter', '(objectClass=posixGroup)');
+	}
+
+	/**
+	 * @brief is user in group?
+	 * @param $uid uid of the user
+	 * @param $gid gid of the group
+	 * @returns true/false
+	 *
+	 * Checks whether the user is member of a group or not.
+	 */
+	public function inGroup($uid, $gid) {
+		$dn_user = OC_LDAP::username2dn($uid);
+		$dn_group = OC_LDAP::groupname2dn($gid);
+// 	if($dn_group == 'c')	{echo('#sdfsdgfds');die($gid);}
+		// just in case
+		if(!$dn_group || !$dn_user) {
+			return false;
+		}
+// 		var_dump($dn_group);
+		$members = OC_LDAP::readAttribute($dn_group, LDAP_GROUP_MEMBER_ASSOC_ATTR);
+
+		return in_array($dn_user, $members);
+	}
+
+	/**
+	 * @brief Get all groups a user belongs to
+	 * @param $uid Name of the user
+	 * @returns array with group names
+	 *
+	 * This function fetches all groups a user belongs to. It does not check
+	 * if the user exists at all.
+	 */
+	public function getUserGroups($uid) {
+		$userDN = OC_LDAP::username2dn($uid);
+		if(!$userDN) {
+			return array();
+		}
+
+		$filter = OC_LDAP::combineFilterWithAnd(array(
+			$this->ldapGroupFilter,
+			LDAP_GROUP_MEMBER_ASSOC_ATTR.'='.$userDN
+		));
+		$groups = $this->retrieveList($filter, array(OC_LDAP::conf('ldapGroupDisplayName'),'dn'));
+		$userGroups = OC_LDAP::ownCloudGroupNames($groups);
+
+		return array_unique($userGroups, SORT_LOCALE_STRING);
+	}
+
+	/**
+	 * @brief get a list of all users in a group
+	 * @returns array with user ids
+	 */
+	public function usersInGroup($gid) {
+		$groupDN = OC_LDAP::groupname2dn($gid);
+		if(!$groupDN) {
+			return array();
+		}
+		$members = OC_LDAP::readAttribute($groupDN, LDAP_GROUP_MEMBER_ASSOC_ATTR);
+		$result = array();
+		foreach($members as $member) {
+		    $result[] = OC_LDAP::dn2username($member);
+		}
+		return array_unique($result, SORT_LOCALE_STRING);
+	}
+
+	/**
+	 * @brief get a list of all groups
+	 * @returns array with group names
+	 *
+	 * Returns a list with all groups
+	 */
+	public function getGroups() {
+		$ldap_groups = $this->retrieveList($this->ldapGroupFilter, array(OC_LDAP::conf('ldapGroupDisplayName'), 'dn'));
+		$groups = OC_LDAP::ownCloudGroupNames($ldap_groups);
+		return $groups;
+	}
+
+	/**
+	 * check if a group exists
+	 * @param string $gid
+	 * @return bool
+	 */
+	public function groupExists($gid){
+		return in_array($gid, $this->getGroups());
+	}
+
+	private function retrieveList($filter, $attr, $searchForGroups = true) {
+		if($searchForGroups) {
+			$list = OC_LDAP::searchGroups($filter, $attr);
+		} else {
+			$list = OC_LDAP::searchUsers($filter, $attr);
+		}
+
+		if(is_array($list)) {
+			if(count($attr) > 1){
+				return $list;
+			} else {
+				return array_unique($list, SORT_LOCALE_STRING);
+			}
+		}
+
+		//error cause actually, maybe throw an exception in future.
+		return array();
+	}
+
+
+
+}
\ No newline at end of file
diff --git a/apps/user_ldap/js/settings.js b/apps/user_ldap/js/settings.js
new file mode 100644
index 0000000000000000000000000000000000000000..cae9655e3df5354529c5514ae105808bb8bf505e
--- /dev/null
+++ b/apps/user_ldap/js/settings.js
@@ -0,0 +1,3 @@
+$(document).ready(function() {
+	$('#ldapSettings').tabs();
+});
\ No newline at end of file
diff --git a/apps/user_ldap/lib_ldap.php b/apps/user_ldap/lib_ldap.php
new file mode 100755
index 0000000000000000000000000000000000000000..2571ff8d76f513fb677ef6ef4a16fa42caa5f50e
--- /dev/null
+++ b/apps/user_ldap/lib_ldap.php
@@ -0,0 +1,616 @@
+<?php
+
+/**
+ * ownCloud – LDAP lib
+ *
+ * @author Arthur Schiwon
+ * @copyright 2012 Arthur Schiwon blizzz@owncloud.com
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or any later version.
+ *
+ * This library 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 AFFERO GENERAL PUBLIC LICENSE for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public
+ * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+define('LDAP_GROUP_MEMBER_ASSOC_ATTR','uniqueMember');
+define('LDAP_GROUP_DISPLAY_NAME_ATTR','cn');
+
+//needed to unbind, because we use OC_LDAP only statically
+class OC_LDAP_DESTRUCTOR {
+	public function __destruct() {
+		OC_LDAP::destruct();
+	}
+}
+
+class OC_LDAP {
+	static protected $ldapConnectionRes = false;
+	static protected $configured = false;
+
+	//cached settings
+	static protected $ldapHost;
+	static protected $ldapPort;
+	static protected $ldapBase;
+	static protected $ldapBaseUsers;
+	static protected $ldapBaseGroups;
+	static protected $ldapAgentName;
+	static protected $ldapAgentPassword;
+	static protected $ldapTLS;
+	static protected $ldapNoCase;
+	// user and group settings, that are needed in both backends
+	static protected $ldapUserDisplayName;
+	static protected $ldapUserFilter;
+	static protected $ldapGroupDisplayName;
+
+	static public function init() {
+		self::readConfiguration();
+		self::establishConnection();
+	}
+
+	static public function destruct() {
+		@ldap_unbind(self::$ldapConnectionRes);
+	}
+
+	/**
+	 * @brief returns a read-only configuration value
+	 * @param $key the name of the configuration value
+	 * @returns the value on success, otherwise null
+	 *
+	 * returns a read-only configuration values
+	 *
+	 * we cannot work with getters, because it is a static class
+	 */
+	static public function conf($key) {
+		if(!self::$configured) {
+			self::init();
+		}
+
+		$availableProperties = array(
+			'ldapUserDisplayName',
+			'ldapGroupDisplayName',
+		);
+
+		if(in_array($key, $availableProperties)) {
+			return self::$$key;
+		}
+
+		return null;
+	}
+
+	/**
+	 * gives back the database table for the query
+	 */
+	static private function getMapTable($isUser) {
+		if($isUser) {
+			return '*PREFIX*ldap_user_mapping';
+		} else {
+			return '*PREFIX*ldap_group_mapping';
+		}
+	}
+
+	/**
+	 * @brief returns the LDAP DN for the given internal ownCloud name of the group
+	 * @param $name the ownCloud name in question
+	 * @returns string with the LDAP DN on success, otherwise false
+	 *
+	 * returns the LDAP DN for the given internal ownCloud name of the group
+	 */
+	static public function groupname2dn($name) {
+		return self::ocname2dn($name, false);
+	}
+
+	/**
+	 * @brief returns the LDAP DN for the given internal ownCloud name of the user
+	 * @param $name the ownCloud name in question
+	 * @returns string with the LDAP DN on success, otherwise false
+	 *
+	 * returns the LDAP DN for the given internal ownCloud name of the user
+	 */
+	static public function username2dn($name) {
+		$dn = self::ocname2dn($name, true);
+		if($dn) {
+			return $dn;
+		} else {
+			//fallback: user is not mapped
+			$filter = self::combineFilterWithAnd(array(
+				self::$ldapUserFilter,
+				self::$ldapUserDisplayName . '=' . $name,
+			));
+			$result = self::searchUsers($filter, 'dn');
+			if(isset($result[0]['dn'])) {
+				self::mapUser($result[0], $name);
+				return $result[0];
+			}
+		}
+
+		return false;
+	}
+
+	static private function ocname2dn($name, $isUser) {
+		$table = self::getMapTable($isUser);
+
+		$query = OCP\DB::prepare('
+			SELECT ldap_dn
+			FROM '.$table.'
+			WHERE owncloud_name = ?
+		');
+
+		$record = $query->execute(array($name))->fetchOne();
+		return $record;
+		if($name=='Coyotes') {
+			echo("adsfasdf ");
+			var_dump($record);
+			die();
+		}
+		if(isset($record['ldap_dn'])) {
+			return $record['ldap_dn'];
+		}
+
+		return false;
+	}
+
+	/**
+	 * @brief returns the internal ownCloud name for the given LDAP DN of the group
+	 * @param $dn the dn of the group object
+	 * @param $ldapname optional, the display name of the object
+	 * @returns string with with the name to use in ownCloud
+	 *
+	 * returns the internal ownCloud name for the given LDAP DN of the group
+	 */
+	static public function dn2groupname($dn, $ldapname = null) {
+		return self::dn2ocname($dn, $ldapname, false);
+	}
+
+	/**
+	 * @brief returns the internal ownCloud name for the given LDAP DN of the user
+	 * @param $dn the dn of the user object
+	 * @param $ldapname optional, the display name of the object
+	 * @returns string with with the name to use in ownCloud
+	 *
+	 * returns the internal ownCloud name for the given LDAP DN of the user
+	 */
+	static public function dn2username($dn, $ldapname = null) {
+		return self::dn2ocname($dn, $ldapname, true);
+	}
+
+	static public function dn2ocname($dn, $ldapname = null, $isUser = true) {
+		$table = self::getMapTable($isUser);
+		if($isUser) {
+			$nameAttribute = self::conf('ldapUserDisplayName');
+		} else {
+			$nameAttribute = self::conf('ldapGroupDisplayName');
+		}
+
+		$query = OCP\DB::prepare('
+			SELECT owncloud_name
+			FROM '.$table.'
+			WHERE ldap_dn = ?
+		');
+
+		$component = $query->execute(array($dn))->fetchOne();
+		if($component) {
+			return $component;
+		}
+
+		if(is_null($ldapname)) {
+			$ldapname = self::readAttribute($dn, $nameAttribute);
+			$ldapname = $ldapname[0];
+		}
+
+		//a new user/group! Then let's try to add it. We're shooting into the blue with the user/group name, assuming that in most cases there will not be a conflict. Otherwise an error will occur and we will continue with our second shot.
+		if(self::mapComponent($dn, $ldapname, $isUser)) {
+			return $ldapname;
+		}
+
+		//doh! There is a conflict. We need to distinguish between users/groups. Adding indexes is an idea, but not much of a help for the user. The DN is ugly, but for now the only reasonable way. But we transform it to a readable format and remove the first part to only give the path where this object is located.
+		$oc_name = self::alternateOwnCloudName($ldapname, $dn);
+		if(self::mapComponent($dn, $oc_name, $isUser)) {
+			return $oc_name;
+		}
+
+		//and this of course should never been thrown :)
+		throw new Exception('LDAP backend: unexpected collision of DN and ownCloud Name.');
+	}
+
+	/**
+	 * @brief gives back the user names as they are used ownClod internally
+	 * @param $ldapGroups an array with the ldap Users result in style of array ( array ('dn' => foo, 'uid' => bar), ... )
+	 * @returns an array with the user names to use in ownCloud
+	 *
+	 * gives back the user names as they are used ownClod internally
+	 */
+	static public function ownCloudUserNames($ldapUsers) {
+		return self::ldap2ownCloudNames($ldapUsers, true);
+	}
+
+	/**
+	 * @brief gives back the group names as they are used ownClod internally
+	 * @param $ldapGroups an array with the ldap Groups result in style of array ( array ('dn' => foo, 'cn' => bar), ... )
+	 * @returns an array with the group names to use in ownCloud
+	 *
+	 * gives back the group names as they are used ownClod internally
+	 */
+	static public function ownCloudGroupNames($ldapGroups) {
+		return self::ldap2ownCloudNames($ldapGroups, false);
+	}
+
+	static private function ldap2ownCloudNames($ldapObjects, $isUsers) {
+		if($isUsers) {
+			$knownObjects = self::mappedUsers();
+			$nameAttribute = self::conf('ldapUserDisplayName');
+		} else {
+			$knownObjects = self::mappedGroups();
+			$nameAttribute = self::conf('ldapGroupDisplayName');
+		}
+		$ownCloudNames = array();
+
+		foreach($ldapObjects as $ldapObject) {
+			$key = self::recursiveArraySearch($knownObjects, $ldapObject['dn']);
+
+			//everything is fine when we know the group
+			if($key) {
+				$ownCloudNames[] = $knownObjects[$key]['owncloud_name'];
+				continue;
+			}
+
+			//a new group! Then let's try to add it. We're shooting into the blue with the group name, assuming that in most cases there will not be a conflict
+			if(self::mapComponent($ldapObject['dn'], $ldapObject[$nameAttribute], $isUsers)) {
+				$ownCloudNames[] = $ldapObject[$nameAttribute];
+				continue;
+			}
+
+			//doh! There is a conflict. We need to distinguish between groups. Adding indexes is an idea, but not much of a help for the user. The DN is ugly, but for now the only reasonable way. But we transform it to a readable format and remove the first part to only give the path where this entry is located.
+			$oc_name = self::alternateOwnCloudName($ldapObject[$nameAttribute], $ldapObject['dn']);
+			if(self::mapComponent($ldapObject['dn'], $oc_name, $isUsers)) {
+				$ownCloudNames[] = $oc_name;
+				continue;
+			}
+
+			//and this of course should never been thrown :)
+			throw new Exception('LDAP backend: unexpected collision of DN and ownCloud Name.');
+		}
+		return $ownCloudNames;
+	}
+
+	/**
+	 * @brief creates a hopefully unique name for owncloud based on the display name and the dn of the LDAP object
+	 * @param $name the display name of the object
+	 * @param $dn the dn of the object
+	 * @returns string with with the name to use in ownCloud
+	 *
+	 * creates a hopefully unique name for owncloud based on the display name and the dn of the LDAP object
+	 */
+	static private function alternateOwnCloudName($name, $dn) {
+		$ufn = ldap_dn2ufn($dn);
+		return $name . ' (' . trim(substr_replace($ufn, '', 0, strpos($ufn, ','))) . ')';
+	}
+
+	/**
+	 * @brief retrieves all known groups from the mappings table
+	 * @returns array with the results
+	 *
+	 * retrieves all known groups from the mappings table
+	 */
+	static private function mappedGroups() {
+		return self::mappedComponents(false);
+	}
+
+	/**
+	 * @brief retrieves all known users from the mappings table
+	 * @returns array with the results
+	 *
+	 * retrieves all known users from the mappings table
+	 */
+	static private function mappedUsers() {
+		return self::mappedComponents(true);
+	}
+
+	static private function mappedComponents($isUsers) {
+		$table = self::getMapTable($isUsers);
+
+		$query = OCP\DB::prepare('
+			SELECT ldap_dn, owncloud_name
+			FROM '. $table
+		);
+
+		return $query->execute()->fetchAll();
+	}
+
+	/**
+	 * @brief inserts a new group into the mappings table
+	 * @param $dn the record in question
+	 * @param $ocname the name to use in ownCloud
+	 * @returns true on success, false otherwise
+	 *
+	 * inserts a new group into the mappings table
+	 */
+	static private function mapGroup($dn, $ocname) {
+		return self::mapComponent($dn, $ocname, false);
+	}
+
+	/**
+	 * @brief inserts a new user into the mappings table
+	 * @param $dn the record in question
+	 * @param $ocname the name to use in ownCloud
+	 * @returns true on success, false otherwise
+	 *
+	 * inserts a new user into the mappings table
+	 */
+	static private function mapUser($dn, $ocname) {
+		return self::mapComponent($dn, $ocname, true);
+	}
+
+	/**
+	 * @brief inserts a new user or group into the mappings table
+	 * @param $dn the record in question
+	 * @param $ocname the name to use in ownCloud
+	 * @param $isUser is it a user or a group?
+	 * @returns true on success, false otherwise
+	 *
+	 * inserts a new user or group into the mappings table
+	 */
+	static private function mapComponent($dn, $ocname, $isUser = true) {
+		$table = self::getMapTable($isUser);
+
+		$insert = OCP\DB::prepare('
+			INSERT IGNORE INTO '.$table.'
+			(ldap_dn, owncloud_name)
+			VALUES (?,?)
+		');
+
+		$res = $insert->execute(array($dn, $ocname));
+
+		return !OCP\DB::isError($res);
+	}
+
+	/**
+	 * @brief reads a given attribute for an LDAP record identified by a DN
+	 * @param $dn the record in question
+	 * @param $attr the attribute that shall be retrieved
+	 * @returns the values in an array on success, false otherwise
+	 *
+	 * Reads an attribute from an LDAP entry
+	 */
+	static public function readAttribute($dn, $attr) {
+		$cr = self::getConnectionResource();
+// echo("<pre>");var_dump($dn);
+		$rr = ldap_read($cr, $dn, 'objectClass=*', array($attr));
+		if(!$rr) {
+			echo('<pre>###RA ');var_dump($dn);var_dump(debug_backtrace());die();
+		}
+		$er = ldap_first_entry($cr, $rr);
+		$result = ldap_get_attributes($cr, $er);
+
+// 		if($dn == 'cn=Coyotes,cn=groups,dc=blizzz-oc,dc=bzoc') die((var_dump($result)));
+		if($result[$attr]['count'] > 0){
+			$values = array();
+			for($i=0;$i<$result[$attr]['count'];$i++) {
+				$values[] = $result[$attr][$i];
+			}
+			return $values;
+		}
+		return false;
+	}
+
+	/**
+	 * @brief executes an LDAP search, optimized for Users
+	 * @param $filter the LDAP filter for the search
+	 * @param $attr optional, when a certain attribute shall be filtered out
+	 * @returns array with the search result
+	 *
+	 * Executes an LDAP search
+	 */
+	static public function searchUsers($filter, $attr = null) {
+		return self::search($filter, self::$ldapBaseUsers, $attr);
+	}
+
+	/**
+	 * @brief executes an LDAP search, optimized for Groups
+	 * @param $filter the LDAP filter for the search
+	 * @param $attr optional, when a certain attribute shall be filtered out
+	 * @returns array with the search result
+	 *
+	 * Executes an LDAP search
+	 */
+	static public function searchGroups($filter, $attr = null) {
+		return self::search($filter, self::$ldapBaseGroups, $attr);
+	}
+
+	/**
+	 * @brief executes an LDAP search
+	 * @param $filter the LDAP filter for the search
+	 * @param $base the LDAP subtree that shall be searched
+	 * @param $attr optional, when a certain attribute shall be filtered out
+	 * @returns array with the search result
+	 *
+	 * Executes an LDAP search
+	 */
+	static private function search($filter, $base, $attr = null) {
+		if(!is_null($attr) && !is_array($attr)) {
+			$attr = array(strtolower($attr));
+		}
+
+		$sr = @ldap_search(self::getConnectionResource(), $base, $filter, $attr);
+		$findings = @ldap_get_entries(self::getConnectionResource(), $sr );
+		// if we're here, probably no connection ressource is returned.
+		// to make ownCloud behave nicely, we simply give back an empty array.
+		if(is_null($findings)) {
+			return array();
+		}
+
+		if(!is_null($attr)) {
+			$selection = array();
+			$multiarray = false;
+			if(count($attr) > 1) {
+				$multiarray = true;
+				$i = 0;
+			}
+			foreach($findings as $item) {
+				if($multiarray) {
+					foreach($attr as $key) {
+						if(isset($item[$key])) {
+							if($key != 'dn'){
+								$selection[$i][$key] = $item[$key][0];
+							} else {
+								$selection[$i][$key] = $item[$key];
+							}
+						}
+
+					}
+					$i++;
+				} else {
+					if(isset($item[$attr[0]])) {
+						$selection[] = $item[$attr[0]];
+					}
+				}
+
+			}
+			return $selection;
+		}
+
+		return $findings;
+	}
+
+	/**
+	 * @brief combines the input filters with AND
+	 * @param $filters array, the filters to connect
+	 * @returns the combined filter
+	 *
+	 * Combines Filter arguments with AND
+	 */
+	static public function combineFilterWithAnd($filters) {
+		return self::combineFilter($filters,'&');
+	}
+
+	/**
+	 * @brief combines the input filters with AND
+	 * @param $filters array, the filters to connect
+	 * @returns the combined filter
+	 *
+	 * Combines Filter arguments with AND
+	 */
+	static public function combineFilterWithOr($filters) {
+		return self::combineFilter($filters,'|');
+	}
+
+	/**
+	 * @brief combines the input filters with given operator
+	 * @param $filters array, the filters to connect
+	 * @param $operator either & or |
+	 * @returns the combined filter
+	 *
+	 * Combines Filter arguments with AND
+	 */
+	static private function combineFilter($filters, $operator) {
+		$combinedFilter = '('.$operator;
+		foreach($filters as $filter) {
+		    if(substr($filter,0,1) != '(') {
+				$filter = '('.$filter.')';
+		    }
+		    $combinedFilter.=$filter;
+		}
+		$combinedFilter.=')';
+		return $combinedFilter;
+	}
+
+	/**
+	 * Returns the LDAP handler
+	 */
+	static private function getConnectionResource() {
+		if(!self::$ldapConnectionRes) {
+			self::init();
+		}
+		if(is_null(self::$ldapConnectionRes)) {
+			OCP\Util::writeLog('ldap', 'Connection could not be established', OCP\Util::INFO);
+		}
+		return self::$ldapConnectionRes;
+	}
+
+	/**
+	 * Caches the general LDAP configuration.
+	 */
+	static private function readConfiguration() {
+		if(!self::$configured) {
+			self::$ldapHost             = OCP\Config::getAppValue('user_ldap', 'ldap_host', '');
+			self::$ldapPort             = OCP\Config::getAppValue('user_ldap', 'ldap_port', OC_USER_BACKEND_LDAP_DEFAULT_PORT);
+			self::$ldapAgentName        = OCP\Config::getAppValue('user_ldap', 'ldap_dn','');
+			self::$ldapAgentPassword    = OCP\Config::getAppValue('user_ldap', 'ldap_password','');
+			self::$ldapBase             = OCP\Config::getAppValue('user_ldap', 'ldap_base', '');
+			self::$ldapBaseUsers        = OCP\Config::getAppValue('user_ldap', 'ldap_base_users',self::$ldapBase);
+			self::$ldapBaseGroups       = OCP\Config::getAppValue('user_ldap', 'ldap_base_groups', self::$ldapBase);
+			self::$ldapTLS              = OCP\Config::getAppValue('user_ldap', 'ldap_tls',0);
+			self::$ldapNoCase           = OCP\Config::getAppValue('user_ldap', 'ldap_nocase', 0);
+			self::$ldapUserDisplayName  = OCP\Config::getAppValue('user_ldap', 'ldap_display_name', OC_USER_BACKEND_LDAP_DEFAULT_DISPLAY_NAME);
+			self::$ldapUserFilter       = OCP\Config::getAppValue('user_ldap', 'ldap_userlist_filter','objectClass=person');
+			self::$ldapGroupDisplayName = OCP\Config::getAppValue('user_ldap', 'ldap_group_display_name', LDAP_GROUP_DISPLAY_NAME_ATTR);
+
+			if(
+				   !empty(self::$ldapHost)
+				&& !empty(self::$ldapPort)
+				&& (
+					   (!empty(self::$ldapAgentName) && !empty(self::$ldapAgentPassword))
+					|| ( empty(self::$ldapAgentName) &&  empty(self::$ldapAgentPassword))
+				)
+				&& !empty(self::$ldapBase)
+				&& !empty(self::$ldapBaseUsers)
+				&& !empty(self::$ldapBaseGroups)
+				&& !empty(self::$ldapUserDisplayName)
+			)
+			{
+				self::$configured = true;
+			}
+		}
+	}
+
+	/**
+	 * Connects and Binds to LDAP
+	 */
+	static private function establishConnection() {
+		if(!self::$configured) {
+			return false;
+		}
+		if(!self::$ldapConnectionRes) {
+			self::$ldapConnectionRes = ldap_connect(self::$ldapHost, self::$ldapPort);
+			if(ldap_set_option(self::$ldapConnectionRes, LDAP_OPT_PROTOCOL_VERSION, 3)) {
+					if(ldap_set_option(self::$ldapConnectionRes, LDAP_OPT_REFERRALS, 0)) {
+						if(self::$ldapTLS) {
+							ldap_start_tls(self::$ldapConnectionRes);
+						}
+					}
+			}
+
+			$ldapLogin = @ldap_bind(self::$ldapConnectionRes, self::$ldapAgentName, self::$ldapAgentPassword );
+			if(!$ldapLogin) {
+				return false;
+			}
+		}
+	}
+
+	/**
+	* taken from http://www.php.net/manual/en/function.array-search.php#97645
+	* TODO: move somewhere, where its better placed since it is not LDAP specific. OC_Helper maybe?
+	*/
+	static public function recursiveArraySearch($haystack, $needle, $index = null) {
+		$aIt = new RecursiveArrayIterator($haystack);
+		$it = new RecursiveIteratorIterator($aIt);
+
+		while($it->valid()) {
+			if (((isset($index) AND ($it->key() == $index)) OR (!isset($index))) AND ($it->current() == $needle)) {
+				return $aIt->key();
+			}
+
+			$it->next();
+		}
+
+		return false;
+	}
+
+ }
\ No newline at end of file
diff --git a/apps/user_ldap/settings.php b/apps/user_ldap/settings.php
old mode 100644
new mode 100755
index ad44fe95f9ecf3ef151387a3b58348c3be22a49b..7512aa3c94262ed768b232b35a948e7dfd3d3ad4
--- a/apps/user_ldap/settings.php
+++ b/apps/user_ldap/settings.php
@@ -20,19 +20,21 @@
  * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
  *
  */
-$params = array('ldap_host', 'ldap_port', 'ldap_dn', 'ldap_password', 'ldap_base', 'ldap_userlist_filter', 'ldap_login_filter', 'ldap_display_name', 'ldap_tls', 'ldap_nocase'. 'ldap_quota_def', 'ldap_quota_attr', 'ldap_email_attr');
+$params = array('ldap_host', 'ldap_port', 'ldap_dn', 'ldap_password', 'ldap_base', 'ldap_base_users', 'ldap_base_groups', 'ldap_userlist_filter', 'ldap_login_filter', 'ldap_display_name', 'ldap_tls', 'ldap_nocase'. 'ldap_quota_def', 'ldap_quota_attr', 'ldap_email_attr');
+
+OCP\Util::addscript('user_ldap', 'settings');
 
 if ($_POST) {
 	foreach($params as $param){
 		if(isset($_POST[$param])){
-			OC_Appconfig::setValue('user_ldap', $param, $_POST[$param]);
+			OCP\Config::setAppValue('user_ldap', $param, $_POST[$param]);
 		}
 		elseif('ldap_tls' == $param) {
 			// unchecked checkboxes are not included in the post paramters
-				OC_Appconfig::setValue('user_ldap', $param, 0);
+				OCP\Config::setAppValue('user_ldap', $param, 0);
 		}
 		elseif('ldap_nocase' == $param) {
-			OC_Appconfig::setValue('user_ldap', $param, 0);
+			OCP\Config::setAppValue('user_ldap', $param, 0);
 		}
 
 	}
@@ -41,14 +43,12 @@ if ($_POST) {
 // fill template
 $tmpl = new OC_Template( 'user_ldap', 'settings');
 foreach($params as $param){
-		$value = OC_Appconfig::getValue('user_ldap', $param,'');
+		$value = OCP\Config::getAppValue('user_ldap', $param,'');
 		$tmpl->assign($param, $value);
 }
 
-// ldap_port has a default value
-$tmpl->assign( 'ldap_port', OC_Appconfig::getValue('user_ldap', 'ldap_port', OC_USER_BACKEND_LDAP_DEFAULT_PORT));
-
-// ldap_display_name has a default value
-$tmpl->assign( 'ldap_display_name', OC_Appconfig::getValue('user_ldap', 'ldap_display_name', OC_USER_BACKEND_LDAP_DEFAULT_DISPLAY_NAME));
+// settings with default values
+$tmpl->assign( 'ldap_port', OCP\Config::getAppValue('user_ldap', 'ldap_port', OC_USER_BACKEND_LDAP_DEFAULT_PORT));
+$tmpl->assign( 'ldap_display_name', OCP\Config::getAppValue('user_ldap', 'ldap_display_name', OC_USER_BACKEND_LDAP_DEFAULT_DISPLAY_NAME));
 
 return $tmpl->fetchPage();
diff --git a/apps/user_ldap/templates/settings.php b/apps/user_ldap/templates/settings.php
index 828c72cba97e4187427a0c5099aa7de21f68d12f..dd3be4df756034870de98b44051e3cdc2dcb0b26 100644
--- a/apps/user_ldap/templates/settings.php
+++ b/apps/user_ldap/templates/settings.php
@@ -1,21 +1,30 @@
 <form id="ldap" action="#" method="post">
-	<fieldset class="personalblock">
-		<legend><strong>LDAP</strong></legend>
-		<p><label for="ldap_host"><?php echo $l->t('Host');?><input type="text" id="ldap_host" name="ldap_host" value="<?php echo $_['ldap_host']; ?>"></label>
-		<label for="ldap_port"><?php echo $l->t('Port');?></label><input type="text" id="ldap_port" name="ldap_port" value="<?php echo $_['ldap_port']; ?>" /></p>
+	<div id="ldapSettings" class="personalblock">
+	<ul>
+		<li><a href="#ldapSettings-1">LDAP Basic</a></li>
+		<li><a href="#ldapSettings-2">Advanced</a></li>
+	</ul>
+	<fieldset id="ldapSettings-1">
+		<p><label for="ldap_host"><?php echo $l->t('Host');?><input type="text" id="ldap_host" name="ldap_host" value="<?php echo $_['ldap_host']; ?>"></label> <label for="ldap_base"><?php echo $l->t('Base');?></label><input type="text" id="ldap_base" name="ldap_base" value="<?php echo $_['ldap_base']; ?>" /></p>
 		<p><label for="ldap_dn"><?php echo $l->t('Name');?></label><input type="text" id="ldap_dn" name="ldap_dn" value="<?php echo $_['ldap_dn']; ?>" />
 		<label for="ldap_password"><?php echo $l->t('Password');?></label><input type="password" id="ldap_password" name="ldap_password" value="<?php echo $_['ldap_password']; ?>" />
 		<small><?php echo $l->t('Leave both empty for anonymous bind for search, then bind with users credentials.');?></small></p>
-		<p><label for="ldap_base"><?php echo $l->t('Base');?></label><input type="text" id="ldap_base" name="ldap_base" value="<?php echo $_['ldap_base']; ?>" /></p>
 		<p><label for="ldap_login_filter"><?php echo $l->t('User Login Filter');?></label><input type="text" id="ldap_login_filter" name="ldap_login_filter" value="<?php echo $_['ldap_login_filter']; ?>" /><small><?php echo $l->t('use %%uid placeholder, e.g. uid=%%uid');?></small></p>
-		<p><label for="ldap_userlist_filter"><?php echo $l->t('User List Filter');?></label><input type="text" id="ldap_userlist_filter" name="ldap_userlist_filter" value="<?php echo $_['ldap_userlist_filter']; ?>" /><small><?php echo $l->t('without any placeholder, e.g. "objectClass=person".');?>	</p>
+		<p><label for="ldap_userlist_filter"><?php echo $l->t('User List Filter');?></label><input type="text" id="ldap_userlist_filter" name="ldap_userlist_filter" value="<?php echo $_['ldap_userlist_filter']; ?>" /><small><?php echo $l->t('without any placeholder, e.g. "objectClass=person".');?></small></p>
+	</fieldset>
+	<fieldset id="ldapSettings-2">
+		<p><label for="ldap_port"><?php echo $l->t('Port');?></label><input type="text" id="ldap_port" name="ldap_port" value="<?php echo $_['ldap_port']; ?>" /></p>
+		<p><label for="ldap_base_users"><?php echo $l->t('Base User Tree');?></label><input type="text" id="ldap_base_users" name="ldap_base_users" value="<?php echo $_['ldap_base_users']; ?>" /></p>
+		<p><label for="ldap_base_groups"><?php echo $l->t('Base Group Tree');?></label><input type="text" id="ldap_base_groups" name="ldap_base_groups" value="<?php echo $_['ldap_base_groups']; ?>" /></p>
+		<p><input type="checkbox" id="ldap_tls" name="ldap_tls" value="1"<?php if ($_['ldap_tls']) echo ' checked'; ?>><label for="ldap_tls"><?php echo $l->t('Use TLS');?></label></p>
+		<p><input type="checkbox" id="ldap_nocase" name="ldap_nocase" value="1"<?php if (isset($_['ldap_nocase']) && ($_['ldap_nocase'])) echo ' checked'; ?>><label for="ldap_nocase"><?php echo $l->t('Case insensitve LDAP server (Windows)');?></label></p>
 		<p><label for="ldap_display_name"><?php echo $l->t('Display Name Field');?></label><input type="text" id="ldap_display_name" name="ldap_display_name" value="<?php echo $_['ldap_display_name']; ?>" />
 		<small><?php echo $l->t('Currently the display name field needs to be the same you matched %%uid against in the filter above, because ownCloud doesn\'t distinguish between user id and user name.');?></small></p>
-		<p><input type="checkbox" id="ldap_tls" name="ldap_tls" value="1"<?php if ($_['ldap_tls']) echo ' checked'; ?>><label for="ldap_tls"><?php echo $l->t('Use TLS');?></label></p>
-		<p><input type="checkbox" id="ldap_nocase" name="ldap_nocase" value="1"<?php if ($_['ldap_nocase']) echo ' checked'; ?>><label for="ldap_nocase"><?php echo $l->t('Case insensitve LDAP server (Windows)');?></label></p>
 		<p><label for="ldap_quota_attr">Quota Attribute</label><input type="text" id="ldap_quota_attr" name="ldap_quota_attr" value="<?php echo $_['ldap_quota_attr']; ?>" />
-                <label for="ldap_quota_def">Quota Default</label><input type="text" id="ldap_quota_def" name="ldap_quota_def" value="<?php echo $_['ldap_quota_def']; ?>" />bytes</p>
-                <p><label for="ldap_email_attr">Email Attribute</label><input type="text" id="ldap_email_attr" name="ldap_email_attr" value="<?php echo $_['ldap_email_attr']; ?>" /></p>
-		<input type="submit" value="Save" />
+		<label for="ldap_quota_def">Quota Default</label><input type="text" id="ldap_quota_def" name="ldap_quota_def" value="<?php if (isset($_['ldap_quota_def'])) echo $_['ldap_quota_def']; ?>" />bytes</p>
+		<p><label for="ldap_email_attr">Email Attribute</label><input type="text" id="ldap_email_attr" name="ldap_email_attr" value="<?php echo $_['ldap_email_attr']; ?>" /></p>
 	</fieldset>
+	<input type="submit" value="Save" />
+	</div>
+
 </form>
diff --git a/apps/user_ldap/tests/group_ldap.php b/apps/user_ldap/tests/group_ldap.php
new file mode 100644
index 0000000000000000000000000000000000000000..2be6b46fb23c05eff40b242240d09b9187d2fbce
--- /dev/null
+++ b/apps/user_ldap/tests/group_ldap.php
@@ -0,0 +1,46 @@
+<?php
+/**
+* ownCloud
+*
+* @author Arthur Schiwon
+* @copyright 2012 Arthur Schiwon blizzz@owncloud.com
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+* License as published by the Free Software Foundation; either
+* version 3 of the License, or any later version.
+*
+* This library 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 AFFERO GENERAL PUBLIC LICENSE for more details.
+*
+* You should have received a copy of the GNU Affero General Public
+* License along with this library.  If not, see <http://www.gnu.org/licenses/>.
+*
+*/
+
+class Test_Group_Ldap extends UnitTestCase {
+	function setUp(){
+		OC_Group::clearBackends();
+	}
+
+	function testSingleBackend(){
+		OC_Group::useBackend(new OC_GROUP_LDAP());
+		$group_ldap = new OC_GROUP_LDAP();
+
+ 		$this->assertIsA(OC_Group::getGroups(),gettype(array()));
+		$this->assertIsA($group_ldap->getGroups(),gettype(array()));
+
+		$this->assertFalse(OC_Group::inGroup('john','dosers'),gettype(false));
+		$this->assertFalse($group_ldap->inGroup('john','dosers'),gettype(false));
+		//TODO: check also for expected true result. This backend won't be able to do any modifications, maybe use a dummy for this.
+
+		$this->assertIsA(OC_Group::getUserGroups('john doe'),gettype(array()));
+		$this->assertIsA($group_ldap->getUserGroups('john doe'),gettype(array()));
+
+		$this->assertIsA(OC_Group::usersInGroup('campers'),gettype(array()));
+		$this->assertIsA($group_ldap->usersInGroup('campers'),gettype(array()));
+	}
+
+}
diff --git a/apps/user_ldap/user_ldap.php b/apps/user_ldap/user_ldap.php
old mode 100644
new mode 100755
index 1e8dc6aaccec6d771b28c78e778873783f6461b2..1a37630aad472da08b89740ad53ceeb10e241701
--- a/apps/user_ldap/user_ldap.php
+++ b/apps/user_ldap/user_ldap.php
@@ -45,19 +45,19 @@ class OC_USER_LDAP extends OC_User_Backend {
 	protected $ldap_dc = false;
 
 	function __construct() {
-		$this->ldap_host = OC_Appconfig::getValue('user_ldap', 'ldap_host','');
-		$this->ldap_port = OC_Appconfig::getValue('user_ldap', 'ldap_port', OC_USER_BACKEND_LDAP_DEFAULT_PORT	);
-		$this->ldap_dn = OC_Appconfig::getValue('user_ldap', 'ldap_dn','');
-		$this->ldap_password = OC_Appconfig::getValue('user_ldap', 'ldap_password','');
-		$this->ldap_base = OC_Appconfig::getValue('user_ldap', 'ldap_base','');
-		$this->ldap_login_filter = OC_Appconfig::getValue('user_ldap', 'ldap_login_filter','');
-		$this->ldap_userlist_filter = OC_Appconfig::getValue('user_ldap', 'ldap_userlist_filter','objectClass=person');
-		$this->ldap_tls = OC_Appconfig::getValue('user_ldap', 'ldap_tls', 0);
-		$this->ldap_nocase = OC_Appconfig::getValue('user_ldap', 'ldap_nocase', 0);
-		$this->ldap_display_name = OC_Appconfig::getValue('user_ldap', 'ldap_display_name', OC_USER_BACKEND_LDAP_DEFAULT_DISPLAY_NAME);
-		$this->ldap_quota_attr = OC_Appconfig::getValue('user_ldap', 'ldap_quota_attr','');
-		$this->ldap_quota_def = OC_Appconfig::getValue('user_ldap', 'ldap_quota_def','');
-		$this->ldap_email_attr = OC_Appconfig::getValue('user_ldap', 'ldap_email_attr','');
+		$this->ldap_host = OCP\Config::getAppValue('user_ldap', 'ldap_host','');
+		$this->ldap_port = OCP\Config::getAppValue('user_ldap', 'ldap_port', OC_USER_BACKEND_LDAP_DEFAULT_PORT	);
+		$this->ldap_dn = OCP\Config::getAppValue('user_ldap', 'ldap_dn','');
+		$this->ldap_password = OCP\Config::getAppValue('user_ldap', 'ldap_password','');
+		$this->ldap_base = OCP\Config::getAppValue('user_ldap', 'ldap_base','');
+		$this->ldap_login_filter = OCP\Config::getAppValue('user_ldap', 'ldap_login_filter','');
+		$this->ldap_userlist_filter = OCP\Config::getAppValue('user_ldap', 'ldap_userlist_filter','objectClass=person');
+		$this->ldap_tls = OCP\Config::getAppValue('user_ldap', 'ldap_tls', 0);
+		$this->ldap_nocase = OCP\Config::getAppValue('user_ldap', 'ldap_nocase', 0);
+		$this->ldap_display_name = OCP\Config::getAppValue('user_ldap', 'ldap_display_name', OC_USER_BACKEND_LDAP_DEFAULT_DISPLAY_NAME);
+		$this->ldap_quota_attr = OCP\Config::getAppValue('user_ldap', 'ldap_quota_attr','');
+		$this->ldap_quota_def = OCP\Config::getAppValue('user_ldap', 'ldap_quota_def','');
+		$this->ldap_email_attr = OCP\Config::getAppValue('user_ldap', 'ldap_email_attr','');
 
 		if( !empty($this->ldap_host)
 			&& !empty($this->ldap_port)
@@ -87,7 +87,7 @@ class OC_USER_LDAP extends OC_User_Backend {
 			$quota = false;
 		}
 		$quota = $quota != -1 ? $quota : $this->ldap_quota_def;
-		OC_Preferences::setValue($uid, 'files', 'quota', OC_Helper::computerFileSize($quota));
+		OCP\Config::setUserValue($uid, 'files', 'quota', OCP\Util::computerFileSize($quota));
 	}
 
 	private function setEmail( $uid ) {
@@ -95,7 +95,7 @@ class OC_USER_LDAP extends OC_User_Backend {
 			return false;
 
 		$email = $this->ldap_dc[$this->ldap_email_attr][0];
-		OC_Preferences::setValue($uid, 'settings', 'email', $email);
+		OCP\Config::setUserValue($uid, 'settings', 'email', $email);
 	}
 
 	//Connect to LDAP and store the resource
diff --git a/apps/user_migrate/admin.php b/apps/user_migrate/admin.php
old mode 100644
new mode 100755
index 0160753af22ed8db7241c1eb5b43061c719f8b94..93f9d59aa4df37da062c025834e2f6e6affc517a
--- a/apps/user_migrate/admin.php
+++ b/apps/user_migrate/admin.php
@@ -20,8 +20,8 @@
  * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
  *
  */
-OC_Util::checkAdminUser();
-OC_Util::checkAppEnabled('user_migrate');
+OCP\User::checkAdminUser();
+OCP\App::checkAppEnabled('user_migrate');
 
 // Import?
 if (isset($_POST['user_import'])) {
@@ -30,14 +30,14 @@ if (isset($_POST['user_import'])) {
 	$importname = "owncloud_import_" . date("y-m-d_H-i-s");
 	
 	// Save data dir for later
-	$datadir = OC_Config::getValue( 'datadirectory' );
+	$datadir = OCP\Config::getSystemValue( 'datadirectory' );
 	
 	// Copy the uploaded file
 	$from = $_FILES['owncloud_import']['tmp_name'];
 	$to = get_temp_dir().'/'.$importname.'.zip';
 	if( !move_uploaded_file( $from, $to ) ){
 		$error = array('error'=>'Failed to move the uploaded file','hint'=>'Try checking the permissions of the '.get_temp_dir().' dir.');
-		OC_Log::write( 'user_migrate', "Failed to copy the uploaded file", OC_Log::ERROR );
+		OCP\Util::writeLog( 'user_migrate', "Failed to copy the uploaded file", OCP\Util::ERROR );
 		$tmpl = new OC_Template('user_migrate', 'admin');
 		$tmpl->assign('error',$error);
     	return $tmpl->fetchPage();
@@ -84,4 +84,4 @@ if (isset($_POST['user_import'])) {
 // fill template
     $tmpl = new OC_Template('user_migrate', 'admin');
     return $tmpl->fetchPage();
-}
\ No newline at end of file
+}
diff --git a/apps/user_migrate/ajax/export.php b/apps/user_migrate/ajax/export.php
old mode 100644
new mode 100755
index 86745d6b1629efe2a8e9075a98370e988052bd70..07c35c7347018a20b405d8e08a715e6c7a6f74dc
--- a/apps/user_migrate/ajax/export.php
+++ b/apps/user_migrate/ajax/export.php
@@ -21,36 +21,36 @@
  *
  */
 // Init owncloud
-require_once('../../../lib/base.php');
+ 
 
 // Check if we are a user
-OC_JSON::checkLoggedIn();
-OC_Util::checkAppEnabled('user_migrate');
+OCP\JSON::checkLoggedIn();
+OCP\App::checkAppEnabled('user_migrate');
 // Which operation
 if( $_GET['operation']=='create' ){
-	$uid = !empty( $_POST['uid'] ) ? $_POST['uid'] :  OC_User::getUser();
-	if( $uid != OC_User::getUser() ){
+	$uid = !empty( $_POST['uid'] ) ? $_POST['uid'] :  OCP\USER::getUser();
+	if( $uid != OCP\USER::getUser() ){
 	    // Needs to be admin to export someone elses account
-		OC_JSON::error();	
+		OCP\JSON::error();	
 		die();
 	}
 	// Create the export zip
 	$response = json_decode( OC_Migrate::export( $uid ) );
 	if( !$response->success ){
 		// Error
-		OC_JSON::error();
+		OCP\JSON::error();
 		die();
 	} else {
 		// Save path in session
 		$_SESSION['ocuserexportpath'] = $response->data;
 	}
-	OC_JSON::success();
+	OCP\JSON::success();
 	die();
 } else if( $_GET['operation']=='download' ){
 	// Download the export
 	$path = isset( $_SESSION['ocuserexportpath'] ) ? $_SESSION['ocuserexportpath'] : false;
 	if( !$path ){
-		OC_JSON::error();	
+		OCP\JSON::error();	
 	}
 	header("Content-Type: application/zip");
 	header("Content-Disposition: attachment; filename=" . basename($path));
diff --git a/apps/user_migrate/appinfo/app.php b/apps/user_migrate/appinfo/app.php
old mode 100644
new mode 100755
index a59b6dd705c3640ea82e36193a230d4e931b54a4..e57bfc2a9d3693c5ed8b5b2310568c80969e4649
--- a/apps/user_migrate/appinfo/app.php
+++ b/apps/user_migrate/appinfo/app.php
@@ -21,15 +21,15 @@
 *
 */
 
-OC_APP::registerPersonal( 'user_migrate', 'settings' );
-OC_APP::registerAdmin( 'user_migrate', 'admin' );
-OC_Util::addScript( 'user_migrate', 'export');
+OCP\App::registerPersonal( 'user_migrate', 'settings' );
+OCP\App::registerAdmin( 'user_migrate', 'admin' );
+OCP\Util::addscript( 'user_migrate', 'export');
 
 // add settings page to navigation
 $entry = array(
 	'id' => "user_migrate_settings",
 	'order'=>1,
-	'href' => OC_Helper::linkTo( "user_migrate", "admin.php" ),
+	'href' => OCP\Util::linkTo( "user_migrate", "admin.php" ),
 	'name' => 'Import'
 );
 ?>
\ No newline at end of file
diff --git a/apps/user_migrate/appinfo/info.xml b/apps/user_migrate/appinfo/info.xml
index 6abcb4af92ce929512181ebc65627a6e285176a8..4c3646f770cccf999ece37590bbe0413f220740b 100644
--- a/apps/user_migrate/appinfo/info.xml
+++ b/apps/user_migrate/appinfo/info.xml
@@ -3,7 +3,6 @@
 	<id>user_migrate</id>
 	<name>User Account Migration</name>
 	<description>Migrate your user accounts</description>
-	<version>0.1</version>
 	<licence>AGPL</licence>
 	<author>Tom Needham</author>
 	<require>2</require>
diff --git a/apps/user_migrate/appinfo/version b/apps/user_migrate/appinfo/version
new file mode 100644
index 0000000000000000000000000000000000000000..ceab6e11ece0bcec917c12e11d350946f085d549
--- /dev/null
+++ b/apps/user_migrate/appinfo/version
@@ -0,0 +1 @@
+0.1
\ No newline at end of file
diff --git a/apps/user_migrate/settings.php b/apps/user_migrate/settings.php
old mode 100644
new mode 100755
index 62f347b3557933540f17eea853a8f723991ad685..2994d10a1eb7320b891c048d6dbffdf05723efbd
--- a/apps/user_migrate/settings.php
+++ b/apps/user_migrate/settings.php
@@ -22,7 +22,7 @@
  * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
  *
  */
-OC_Util::checkAppEnabled('user_migrate');
+OCP\App::checkAppEnabled('user_migrate');
 
 // fill template
 $tmpl = new OC_Template('user_migrate', 'settings');
diff --git a/apps/user_migrate/templates/admin.php b/apps/user_migrate/templates/admin.php
index b01e5c7579a9fc8e2cc478c885a1a20a641233a8..ff51f43ffde9fce8aa6ec481f898e6ae7c95330c 100644
--- a/apps/user_migrate/templates/admin.php
+++ b/apps/user_migrate/templates/admin.php
@@ -6,7 +6,7 @@
 		<?php } ?>
         <legend><strong><?php echo $l->t('Import user account');?></strong></legend>
         </p>
-        <p><input type="file" id="owncloud_import" name="owncloud_import"><label for="owncloud_import"><?php echo $l->t('ownCloud User Zip');?></label>
+        <p><input type="file" id="owncloud_import" name="owncloud_import" style="width:180px;"><label for="owncloud_import"> <?php echo $l->t('ownCloud User Zip');?></label>
         </p>
         <input type="submit" name="user_import" value="<?php echo $l->t('Import'); ?>" />
     </fieldset>
diff --git a/apps/user_migrate/templates/settings.php b/apps/user_migrate/templates/settings.php
old mode 100644
new mode 100755
index 5f4857de5fa4a518605514a2045d0554a4027f1c..8f1fe41df017e43db199b72da7075ead60243b7c
--- a/apps/user_migrate/templates/settings.php
+++ b/apps/user_migrate/templates/settings.php
@@ -2,5 +2,5 @@
 	<legend><strong><?php echo $l->t('Export your user account');?></strong></legend>
 	<p><?php echo $l->t('This will create a compressed file that contains your ownCloud account.');?>
 	</p>
-	<button id="exportbtn">Export<img style="display: none;" class="loading" src="<?php echo OC_Helper::linkTo('core', 'img/loading.gif'); ?>" /></button>
+	<button id="exportbtn">Export<img style="display: none;" class="loading" src="<?php echo OCP\Util::linkTo('core', 'img/loading.gif'); ?>" /></button>
 </fieldset>
diff --git a/apps/user_openid/appinfo/app.php b/apps/user_openid/appinfo/app.php
old mode 100644
new mode 100755
index cbcbe5442210a5b46a612785ee1cd73b3479d020..c683254101fde20a054ed98b8bd66e49746b1571
--- a/apps/user_openid/appinfo/app.php
+++ b/apps/user_openid/appinfo/app.php
@@ -14,10 +14,10 @@ if(strpos($_SERVER["REQUEST_URI"],'?') and !strpos($_SERVER["REQUEST_URI"],'='))
 	}
 }
 
-OC_Util::addHeader('link',array('rel'=>'openid.server', 'href'=>OC_Helper::linkToAbsolute( "user_openid", "user.php" ).'/'.$userName));
-OC_Util::addHeader('link',array('rel'=>'openid.delegate', 'href'=>OC_Helper::linkToAbsolute( "user_openid", "user.php" ).'/'.$userName));
+OCP\Util::addHeader('link',array('rel'=>'openid.server', 'href'=>OCP\Util::linkToAbsolute( "user_openid", "user.php" ).'/'.$userName));
+OCP\Util::addHeader('link',array('rel'=>'openid.delegate', 'href'=>OCP\Util::linkToAbsolute( "user_openid", "user.php" ).'/'.$userName));
 
-OC_APP::registerPersonal('user_openid','settings');
+OCP\App::registerPersonal('user_openid','settings');
 
 require_once 'apps/user_openid/user_openid.php';
 
@@ -26,14 +26,14 @@ OC_User::useBackend('openid');
 
 //check for results from openid requests
 if(isset($_GET['openid_mode']) and $_GET['openid_mode'] == 'id_res'){
-	OC_Log::write('user_openid','openid retured',OC_Log::DEBUG);
+	OCP\Util::writeLog('user_openid','openid retured',OCP\Util::DEBUG);
 	$openid = new SimpleOpenID;
 	$openid->SetIdentity($_GET['openid_identity']);
 	$openid_validation_result = $openid->ValidateWithServer();
 	if ($openid_validation_result == true){         // OK HERE KEY IS VALID
-		OC_Log::write('user_openid','auth sucessfull',OC_Log::DEBUG);
+		OCP\Util::writeLog('user_openid','auth sucessfull',OCP\Util::DEBUG);
 		$identity=$openid->GetIdentity();
-		OC_Log::write('user_openid','auth as '.$identity,OC_Log::DEBUG);
+		OCP\Util::writeLog('user_openid','auth as '.$identity,OCP\Util::DEBUG);
 		$user=OC_USER_OPENID::findUserForIdentity($identity);
 		if($user){
 			$_SESSION['user_id']=$user;
@@ -41,13 +41,13 @@ if(isset($_GET['openid_mode']) and $_GET['openid_mode'] == 'id_res'){
 		}
 	}else if($openid->IsError() == true){            // ON THE WAY, WE GOT SOME ERROR
 		$error = $openid->GetError();
-		OC_Log::write('user_openid','ERROR CODE: '. $error['code'],OC_Log::ERROR);
-		OC_Log::write('user_openid','ERROR DESCRIPTION: '. $error['description'],OC_Log::ERROR);
+		OCP\Util::writeLog('user_openid','ERROR CODE: '. $error['code'],OCP\Util::ERROR);
+		OCP\Util::writeLog('user_openid','ERROR DESCRIPTION: '. $error['description'],OCP\Util::ERROR);
 	}else{                                            // Signature Verification Failed
-		OC_Log::write('user_openid','INVALID AUTHORIZATION',OC_Log::ERROR);
+		OCP\Util::writeLog('user_openid','INVALID AUTHORIZATION',OCP\Util::ERROR);
 	}
 }else if (isset($_GET['openid_mode']) and $_GET['openid_mode'] == 'cancel'){ // User Canceled your Request
-	OC_Log::write('user_openid','USER CANCELED REQUEST',OC_Log::DEBUG);
+	OCP\Util::writeLog('user_openid','USER CANCELED REQUEST',OCP\Util::DEBUG);
 	return false;
 }
 
diff --git a/apps/user_openid/appinfo/info.xml b/apps/user_openid/appinfo/info.xml
index 721db1877e3a661f6e86df6757afcf5cdf4e46c9..6214229c0a18f197cdc0eea73f04df1b8b8675e6 100644
--- a/apps/user_openid/appinfo/info.xml
+++ b/apps/user_openid/appinfo/info.xml
@@ -3,7 +3,6 @@
 	<id>user_openid</id>
 	<name>OpenID user backend</name>
 	<description>Allow login through OpenID</description>
-	<version>0.1</version>
 	<licence>AGPL</licence>
 	<author>Robin Appelman</author>
 	<require>2</require>
diff --git a/apps/user_openid/appinfo/version b/apps/user_openid/appinfo/version
new file mode 100644
index 0000000000000000000000000000000000000000..ceab6e11ece0bcec917c12e11d350946f085d549
--- /dev/null
+++ b/apps/user_openid/appinfo/version
@@ -0,0 +1 @@
+0.1
\ No newline at end of file
diff --git a/apps/user_openid/phpmyid.php b/apps/user_openid/phpmyid.php
old mode 100644
new mode 100755
index ef01e7a046d0089a8212553b3c259c85da59ef92..21d1c0a45459cd9f0eeb0b75e8ab1e6e448ee027
--- a/apps/user_openid/phpmyid.php
+++ b/apps/user_openid/phpmyid.php
@@ -205,7 +205,7 @@ function authorize_mode () {
 
 	$profile['idp_url']=$IDENTITY;
 	if (isset($_SERVER['PHP_AUTH_USER']) && $profile['authorized'] === false && $_SERVER['PHP_AUTH_USER']==$USERNAME) {
-		if (OC_User::checkPassword($USERNAME, $_SERVER['PHP_AUTH_PW'])) {// successful login!
+		if (OCP\User::checkPassword($USERNAME, $_SERVER['PHP_AUTH_PW'])) {// successful login!
 			// return to the refresh url if they get in
 			$_SESSION['openid_auth']=true;
 			$_SESSION['openid_user']=$USERNAME;
@@ -1067,7 +1067,7 @@ function destroy_assoc_handle ( $id ) {
 	session_write_close();
 
 	session_id($id);
-	if (OC_Config::getValue( "forcessl", false )) {
+	if (OCP\Config::getSystemValue( "forcessl", false )) {
 		ini_set("session.cookie_secure", "on");
 	}
 	session_start();
@@ -1195,7 +1195,7 @@ function new_assoc ( $expiration ) {
 		session_write_close();
 	}
 
-	if (OC_Config::getValue( "forcessl", false )) {
+	if (OCP\Config::getSystemValue( "forcessl", false )) {
 		ini_set("session.cookie_secure", "on");
 	}
 	session_start();
@@ -1269,7 +1269,7 @@ function secret ( $handle ) {
 	}
 
 	session_id($handle);
-	if (OC_Config::getValue( "forcessl", false )) {
+	if (OCP\Config::getSystemValue( "forcessl", false )) {
 		ini_set("session.cookie_secure", "on");
 	}
 	session_start();
@@ -1447,7 +1447,7 @@ function user_session () {
 	global $proto, $profile;
 
 	session_name('phpMyID_Server');
-	if (OC_Config::getValue( "forcessl", false )) {
+	if (OCP\Config::getSystemValue( "forcessl", false )) {
 		ini_set("session.cookie_secure", "on");
 	}
 	@session_start();
diff --git a/apps/user_openid/settings.php b/apps/user_openid/settings.php
old mode 100644
new mode 100755
index d85eaebb5ee7e688bc626a623fddbda020325424..cdffab0bc25b95687adc2132819ce786327aaf57
--- a/apps/user_openid/settings.php
+++ b/apps/user_openid/settings.php
@@ -1,10 +1,10 @@
 <?php
 
 $tmpl = new OC_Template( 'user_openid', 'settings');
-$identity=OC_Preferences::getValue(OC_User::getUser(),'user_openid','identity','');
+$identity=OCP\Config::getUserValue(OCP\USER::getUser(),'user_openid','identity','');
 $tmpl->assign('identity',$identity);
 
-OC_Util::addScript('user_openid','settings');
+OCP\Util::addscript('user_openid','settings');
 
 return $tmpl->fetchPage();
 ?>
\ No newline at end of file
diff --git a/apps/user_openid/templates/nomode.php b/apps/user_openid/templates/nomode.php
index f85d28cdc9bd22d0904476827daa5bafc3a77228..3bab4c2edd18b0889dfcbffbd58d1ee05d527e55 100644
--- a/apps/user_openid/templates/nomode.php
+++ b/apps/user_openid/templates/nomode.php
@@ -5,7 +5,7 @@ global $profile;
 ?>
 
 <div id="login">
-	<img src="<?php echo image_path("", "owncloud-logo-medium-white.png"); ?>" alt="ownCloud" />
+	<img src="<?php echo image_path("", "logo.png"); ?>" alt="ownCloud" />
 	<ul>
 		<li class='error'>
 			<div id="setup_form">
diff --git a/apps/user_openid/templates/settings.php b/apps/user_openid/templates/settings.php
old mode 100644
new mode 100755
index 24dfaa1789188a2b49bfdb6585258663057f33ec..731a2c57e98e4bf1f7ef2da81ac9ce76503b5185
--- a/apps/user_openid/templates/settings.php
+++ b/apps/user_openid/templates/settings.php
@@ -1,7 +1,7 @@
 <form id="openidform">
 	<fieldset class="personalblock">
 		<strong>OpenID</strong>
-		<?php echo ((isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') ? 'https' : 'http').'://'.OC_Helper::serverHost().OC::$WEBROOT.'/?'; echo OC_User::getUser(); ?><br /><em><?php echo $l->t('you can authenticate to other sites with this address');?></em><br />
+		<?php echo ((isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') ? 'https' : 'http').'://'.OCP\Util::getServerHost().OC::$WEBROOT.'/?'; echo OCP\USER::getUser(); ?><br /><em><?php echo $l->t('you can authenticate to other sites with this address');?></em><br />
 		<label for="identity"><?php echo $l->t('Authorized OpenID provider');?></label>
 		<input type="text" name="identity" id="identity" value="<?php echo $_['identity']; ?>" placeholder="<?php echo $l->t('Your address at Wordpress, Identi.ca, &hellip;');?>" /><span class="msg"></span>
 	</fieldset>
diff --git a/apps/user_openid/user.php b/apps/user_openid/user.php
old mode 100644
new mode 100755
index 8fec713aa7120c75b65b9fe74a98e8a152945be4..9f751da5edb01927326e2673eb05e62d7e915da7
--- a/apps/user_openid/user.php
+++ b/apps/user_openid/user.php
@@ -37,13 +37,13 @@ if($USERNAME=='' and isset($_SERVER['PHP_AUTH_USER'])){
 $RUNTIME_NOAPPS=true;
 $RUNTIME_NOAPPS=false;
 require_once '../../lib/base.php';
-OC_Util::checkAppEnabled('user_openid');
+OCP\App::checkAppEnabled('user_openid');
 
-if(!OC_User::userExists($USERNAME)){
-	OC_Log::write('user_openid',$USERNAME.' doesn\'t exist',OC_Log::WARN);
+if(!OCP\User::userExists($USERNAME)){
+	OCP\Util::writeLog('user_openid',$USERNAME.' doesn\'t exist',OCP\Util::WARN);
 	$USERNAME='';
 }
-$IDENTITY=OC_Helper::linkToAbsolute( "user_openid", "user.php" ).'/'.$USERNAME;
+$IDENTITY=OCP\Util::linkToAbsolute( "user_openid", "user.php" ).'/'.$USERNAME;
 
 require_once 'phpmyid.php';
 
diff --git a/apps/user_openid/user_openid.php b/apps/user_openid/user_openid.php
old mode 100644
new mode 100755
index df050e908dec6923a1264b08d58ef1eceff8f1fc..8deb42f68c8637acc23bc5612c94a243bb708ffb
--- a/apps/user_openid/user_openid.php
+++ b/apps/user_openid/user_openid.php
@@ -54,7 +54,7 @@ class OC_USER_OPENID extends OC_User_Backend {
 	 * find the user that can be authenticated with an openid identity
 	 */
 	public static function findUserForIdentity($identity){
-		$query=OC_DB::prepare('SELECT userid FROM *PREFIX*preferences WHERE appid=? AND configkey=? AND configvalue=?');
+		$query=OCP\DB::prepare('SELECT userid FROM *PREFIX*preferences WHERE appid=? AND configkey=? AND configvalue=?');
 		$result=$query->execute(array('user_openid','identity',$identity))->fetchAll();
 		if(count($result)>0){
 			return $result[0]['userid'];
diff --git a/apps/user_webfinger/appinfo/app.php b/apps/user_webfinger/appinfo/app.php
old mode 100644
new mode 100755
index 8e8f92c96574184a27d64e209f12e5224eb4352a..f7b927df82a92edda0f939475eaf2510120d1bb7
--- a/apps/user_webfinger/appinfo/app.php
+++ b/apps/user_webfinger/appinfo/app.php
@@ -1,5 +1,5 @@
 <?php
-OC_App::register( array( 
+OCP\App::register( array( 
   'order' => 11,
   'id' => 'user_webfinger',
   'name' => 'Webfinger' ));
diff --git a/apps/user_webfinger/appinfo/info.xml b/apps/user_webfinger/appinfo/info.xml
index d47fb723a3af1aa1aeeec20fc194008d8d6ef7aa..fe1d43718633d1a591a46f2165cc062ac5dfb7fb 100644
--- a/apps/user_webfinger/appinfo/info.xml
+++ b/apps/user_webfinger/appinfo/info.xml
@@ -3,7 +3,6 @@
 	<id>user_webfinger</id>
 	<name>Webfinger</name>
 	<description>Provide WebFinger for all users so they get a user address like user@owncloudinstance which can be used for external applications. Other apps can provide information for webfinger requests, such as remoteStorage compatibility.</description>
-	<version>0.3</version>
 	<licence>AGPL or MIT</licence>
 	<author>Michiel de Jong, Florian Hülsmann</author>
 	<require>2</require>
diff --git a/apps/user_webfinger/appinfo/version b/apps/user_webfinger/appinfo/version
new file mode 100644
index 0000000000000000000000000000000000000000..1d71ef97443918d538e8188167c94d7bbafaf753
--- /dev/null
+++ b/apps/user_webfinger/appinfo/version
@@ -0,0 +1 @@
+0.3
\ No newline at end of file
diff --git a/apps/user_webfinger/webfinger.php b/apps/user_webfinger/webfinger.php
old mode 100644
new mode 100755
index 9ada473ca875c7d35df18caab63da8020f96df95..da35cf29d0e7fb6b5b1113a978a9ac851842510f
--- a/apps/user_webfinger/webfinger.php
+++ b/apps/user_webfinger/webfinger.php
@@ -25,7 +25,7 @@ $SUBURI=substr(realpath($_SERVER["SCRIPT_FILENAME"]),strlen($SERVERROOT));
 $WEBROOT=substr($SUBURI,0,-34);
 */
 
-require_once('../../lib/base.php');
+
 $request = urldecode($_GET['q']);
 if($_GET['q']) {
 	$reqParts = explode('@', $request);
@@ -61,7 +61,7 @@ echo "<";
 <?php
 $apps = OC_Appconfig::getApps();
 foreach($apps as $app) {
-	if(OC_App::isEnabled($app)) {
+	if(OCP\App::isEnabled($app)) {
 		if(is_file(OC::$APPSROOT . '/apps/' . $app . '/appinfo/webfinger.php')) {
 			require($app . '/appinfo/webfinger.php');
 		}
diff --git a/config/config.sample.php b/config/config.sample.php
old mode 100755
new mode 100644
index 199c9248c5154d02d14fe11e60cd297ce38f44f1..8561d0a75807ad43726ef3cdf5c079ba61e14de4
--- a/config/config.sample.php
+++ b/config/config.sample.php
@@ -19,6 +19,15 @@ $CONFIG = array(
 "knowledgebaseurl" => "",
 "appstoreenabled" => true,
 "appstoreurl" => "",
+"mail_smtpmode" => "sendmail",
+"mail_smtphost" => "127.0.0.1",
+"mail_smtpauth" => "false",
+"mail_smtpname" => "",
+"mail_smtppassword" => "",
+"appcodechecker" => "",
+"log_type" => "",
+"logfile" => "",
+"loglevel" => "",
 // "datadirectory" => ""
 );
 ?>
diff --git a/core/ajax/translations.php b/core/ajax/translations.php
index 2e436f8d84eb01fa316e5d50bde5c369bbc04520..a6433b1964afd4a0d6c9090c7007e374a5a583af 100644
--- a/core/ajax/translations.php
+++ b/core/ajax/translations.php
@@ -26,7 +26,7 @@ require_once('../../lib/base.php');
 
 $app = $_POST["app"];
 
-$l = new OC_L10N( $app );
+$l = OC_L10N::get( $app );
 
 OC_JSON::success(array('data' => $l->getTranslations()));
 ?>
diff --git a/core/css/jquery-ui-1.8.16.custom.css b/core/css/jquery-ui-1.8.16.custom.css
old mode 100755
new mode 100644
diff --git a/core/css/multiselect.css b/core/css/multiselect.css
index 1202ea18427163eea77791fdfd0d1d2814d00611..040b0f46ed33d4a788a08677430941389bce5f88 100644
--- a/core/css/multiselect.css
+++ b/core/css/multiselect.css
@@ -1,7 +1,11 @@
+/* Copyright (c) 2011, Jan-Christoph Borchardt, http://jancborchardt.net
+ This file is licensed under the Affero General Public License version 3 or later.
+ See the COPYING-README file. */
+
 ul.multiselectoptions { z-index:49; position:absolute; background-color:#fff; padding-top:.5em; border:1px solid #ddd; border-top:none; -moz-border-radius-bottomleft:.5em; -webkit-border-bottom-left-radius:.5em; border-bottom-left-radius:.5em; -moz-border-radius-bottomright:.5em; -webkit-border-bottom-right-radius:.5em; border-bottom-right-radius:.5em; -moz-box-shadow:0 1px 1px #ddd; -webkit-box-shadow:0 1px 1px #ddd; box-shadow:0 1px 1px #ddd; }
 ul.multiselectoptions>li{ white-space:nowrap; overflow: hidden; }
-div.multiselect { padding-right:.6em; display:inline; position:relative; display:inline-block; vertical-align: bottom; }
+div.multiselect { padding-right:.6em; display:inline; position:relative; display:inline-block; vertical-align: bottom; min-width:100px; max-width:400px; }
 div.multiselect.active { background-color:#fff; border-bottom:none; border-bottom-left-radius:0; border-bottom-right-radius:0; z-index:50; position:relative }
-div.multiselect>span:first-child { margin-right:2em; float:left; }
-div.multiselect>span:last-child { float:right; position:relative }
+div.multiselect>span:first-child { margin-right:2em; float:left; width:90%; overflow:hidden; text-overflow:ellipsis; }
+div.multiselect>span:last-child { position:absolute; right:.8em; }
 ul.multiselectoptions input.new{ margin:0; padding-bottom:0.2em; padding-top:0.2em; border-top-left-radius:0; border-top-right-radius:0; }
diff --git a/core/css/styles.css b/core/css/styles.css
index a8efcfc5a230e222e587bd0f3cc6857e6d5e2092..e3d8403e7502ea26d141beacc31b1a547dd214eb 100644
--- a/core/css/styles.css
+++ b/core/css/styles.css
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, Jan-Christoph Borchardt
+/* Copyright (c) 2011, Jan-Christoph Borchardt, http://jancborchardt.net
  This file is licensed under the Affero General Public License version 3 or later.
  See the COPYING-README file. */
 
@@ -17,7 +17,7 @@ body { background:#fefefe; font:normal .8em/1.6em "Lucida Grande", Arial, Verdan
 
 /* HEADERS */
 #body-user #header, #body-settings #header { position:fixed; top:0; z-index:100; width:100%; height:2.5em; padding:.5em; background:#1d2d44; -moz-box-shadow:0 0 10px rgba(0, 0, 0, .5), inset 0 -2px 10px #222; -webkit-box-shadow:0 0 10px rgba(0, 0, 0, .5), inset 0 -2px 10px #222; box-shadow:0 0 10px rgba(0, 0, 0, .5), inset 0 -2px 10px #222; }
-#body-login #header { margin: -2em auto 0; text-align:center; height:10em;
+#body-login #header { margin: -2em auto 0; text-align:center; height:10em; padding:1em 0 .5em;
  -moz-box-shadow:0 0 1em rgba(0, 0, 0, .5); -webkit-box-shadow:0 0 1em rgba(0, 0, 0, .5); box-shadow:0 0 1em rgba(0, 0, 0, .5);
 background: #1d2d44; /* Old browsers */
 background: -moz-linear-gradient(top, #35537a 0%, #1d2d42 100%); /* FF3.6+ */
@@ -33,12 +33,12 @@ filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#35537a', end
 
 /* INPUTS */
 input[type="text"], input[type="password"] { cursor:text; }
-input, select, button, .button, #quota, div.jp-progress, .pager li a { font-size:1em; width:10em; margin:.3em; padding:.6em .5em .4em; background:#fff; color:#333; border:1px solid #ddd; -moz-box-shadow:0 1px 1px #fff, 0 2px 0 #bbb inset; -webkit-box-shadow:0 1px 1px #fff, 0 1px 0 #bbb inset; box-shadow:0 1px 1px #fff, 0 1px 0 #bbb inset; -moz-border-radius:.5em; -webkit-border-radius:.5em; border-radius:.5em; outline:none; }
+input, textarea, select, button, .button, #quota, div.jp-progress, .pager li a { font-size:1em; width:10em; margin:.3em; padding:.6em .5em .4em; background:#fff; color:#333; border:1px solid #ddd; -moz-box-shadow:0 1px 1px #fff, 0 2px 0 #bbb inset; -webkit-box-shadow:0 1px 1px #fff, 0 1px 0 #bbb inset; box-shadow:0 1px 1px #fff, 0 1px 0 #bbb inset; -moz-border-radius:.5em; -webkit-border-radius:.5em; border-radius:.5em; outline:none; }
 input[type="text"], input[type="password"], input[type="search"] { background:#f8f8f8; color:#555; cursor:text; }
 input[type="text"], input[type="password"], input[type="search"] { -webkit-appearance:textfield; -moz-appearance:textfield; -webkit-box-sizing:content-box; -moz-box-sizing:content-box; box-sizing:content-box; }
 input[type="text"]:hover, input[type="text"]:focus, input[type="text"]:active,
 input[type="password"]:hover, input[type="password"]:focus, input[type="password"]:active,
-.searchbox input[type="search"]:hover, .searchbox input[type="search"]:focus, .searchbox input[type="search"]:active { background-color:#fff; color:#333; opacity:1; }
+.searchbox input[type="search"]:hover, .searchbox input[type="search"]:focus, .searchbox input[type="search"]:active { background-color:#fff; color:#333; -ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=100)"; filter:alpha(opacity=100); opacity:1; }
 
 input[type="submit"], input[type="button"], button, .button, #quota, div.jp-progress, select, .pager li a { width:auto; padding:.4em; border:1px solid #ddd; font-weight:bold; cursor:pointer; background:#f8f8f8; color:#555; text-shadow:#fff 0 1px 0; -moz-box-shadow:0 1px 1px #fff, 0 1px 1px #fff inset; -webkit-box-shadow:0 1px 1px #fff, 0 1px 1px #fff inset; -moz-border-radius:.5em; -webkit-border-radius:.5em; border-radius:.5em; }
 input[type="submit"]:hover, input[type="submit"]:focus, input[type="button"]:hover, select:hover, select:focus, select:active, input[type="button"]:focus, .button:hover { background:#fff; color:#333; }
@@ -49,7 +49,7 @@ input[type="checkbox"] { width:auto; }
 #body-login input[type="text"], #body-login input[type="password"] { width: 13em; }
 #body-login input.login { width: auto; float: right; }
 #remember_login { margin:.8em .2em 0 1em; }
-.searchbox input[type="search"] { position:fixed; font-size:1.2em; top:.4em; right:3em; padding:.2em .5em .2em 1.5em; background:#fff url('../img/actions/search.svg') no-repeat .5em center; border:0; -moz-border-radius:1em; -webkit-border-radius:1em; border-radius:1em; opacity:.3; -webkit-transition:opacity 300ms; -moz-transition:opacity 300ms; -o-transition:opacity 300ms; transition:opacity 300ms; }
+.searchbox input[type="search"] { position:fixed; font-size:1.2em; top:.4em; right:3em; padding:.2em .5em .2em 1.5em; background:#fff url('../img/actions/search.svg') no-repeat .5em center; border:0; -moz-border-radius:1em; -webkit-border-radius:1em; border-radius:1em; -ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=70)"; filter:alpha(opacity=70);opacity:.7; -webkit-transition:opacity 300ms; -moz-transition:opacity 300ms; -o-transition:opacity 300ms; transition:opacity 300ms; }
 input[type="submit"].enabled { background:#66f866; border:1px solid #5e5; -moz-box-shadow:0 1px 1px #f8f8f8, 0 1px 1px #cfc inset; -webkit-box-shadow:0 1px 1px #f8f8f8, 0 1px 1px #cfc inset; box-shadow:0 1px 1px #f8f8f8, 0 1px 1px #cfc inset; }
 input[type="submit"].highlight{ background:#ffc100; border:1px solid #db0; text-shadow:#ffeedd 0 1px 0; -moz-box-shadow:0 1px 1px #f8f8f8, 0 1px 1px #ffeedd inset; -webkit-box-shadow:0 1px 1px #f8f8f8, 0 1px 1px #ffeedd inset; box-shadow:0 1px 1px #f8f8f8, 0 1px 1px #ffeedd inset; }
 
@@ -58,8 +58,10 @@ input[type="submit"].highlight{ background:#ffc100; border:1px solid #db0; text-
 #controls .button { display:inline-block; }
 #content { top: 3.5em; left: 12.5em; position: absolute; }
 #leftcontent, .leftcontent { position:fixed; overflow: auto; top:6.4em; width:20em; background:#f8f8f8; border-right:1px solid #ddd; }
-#leftcontent li, .leftcontent li { background:#f8f8f8; padding:.3em .8em; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; -webkit-transition:background-color 500ms; -moz-transition:background-color 500ms; -o-transition:background-color 500ms; transition:background-color 500ms; }
+#leftcontent li, .leftcontent li { background:#f8f8f8; padding:.5em .8em; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; -webkit-transition:background-color 200ms; -moz-transition:background-color 200ms; -o-transition:background-color 200ms; transition:background-color 200ms; }
 #leftcontent li:hover, #leftcontent li:active, #leftcontent li.active, .leftcontent li:hover, .leftcontent li:active, .leftcontent li.active { background:#eee; }
+#leftcontent li.active, .leftcontent li.active { font-weight:bold; }
+#leftcontent li:hover, .leftcontent li:hover { color:#333; background:#ddd; }
 #rightcontent, .rightcontent { position:fixed; top: 6.4em; left: 32.5em; overflow: auto }
 
 
@@ -95,8 +97,9 @@ label.infield { cursor: text !important; }
 #navigation a.active, #navigation a:hover, #navigation a:focus { background-color:#dbdbdb; border-top:1px solid #d4d4d4; border-bottom:1px solid #ccc; color:#333; }
 #navigation a.active { background-color:#ddd; }
 #navigation #settings { position:absolute; bottom:3.5em; width:100%; }
-#expand { margin:0 0 .2em 1.2em; cursor:pointer; }
-#expand+span { position:relative; bottom:.4em; left:.2em; font-size:1.2em; color:#666; text-shadow:#f8f8f8 0 1px 0; }
+#expand { position:relative; margin-bottom:-.5em; padding:.5em 10.1em .7em 1.2em; cursor:pointer; }
+#expand+span { position:absolute; margin:-1.7em 0 0 2.5em; font-size:1.2em; color:#666; text-shadow:#f8f8f8 0 1px 0; -ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=0)"; filter:alpha(opacity=0); opacity:0; -webkit-transition:opacity 300ms; -moz-transition:opacity 300ms; -o-transition:opacity 300ms; transition:opacity 300ms; }
+#expand:hover+span, #expand+span:hover { -ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=100)"; filter:alpha(opacity=100); opacity:1; cursor:pointer; }
 #logout { position:absolute; right:0; top:0; padding:1.2em 2em .55em 1.2em; }
 
 
@@ -106,17 +109,20 @@ label.infield { cursor: text !important; }
 
 #notification { z-index:101; cursor:pointer; background-color:#fc4; border:0; padding:0 .7em .3em; display:none; position:fixed; left:50%; top:0; -moz-border-radius-bottomleft:1em; -webkit-border-bottom-left-radius:1em; border-bottom-left-radius:1em; -moz-border-radius-bottomright:1em; -webkit-border-bottom-right-radius:1em; border-bottom-right-radius:1em; }
 
-.action, .selectedActions a, #logout { opacity:.5; -webkit-transition:opacity 500ms; -moz-transition:opacity 500ms; -o-transition:opacity 500ms; transition:opacity 500ms; }
+.action, .selectedActions a { -ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=50)"; filter:alpha(opacity=50); opacity:.5; -webkit-transition:opacity 200ms; -moz-transition:opacity 200ms; -o-transition:opacity 200ms; transition:opacity 200ms; }
 .action { width: 16px; height: 16px; }
-.action:hover, .selectedActions a:hover, #logout:hover { opacity:1; }
+#logout { -ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=80)"; filter:alpha(opacity=80); opacity:.8; }
+.action:hover, .selectedActions a:hover, #logout:hover { -ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=100)"; filter:alpha(opacity=100); opacity:1; }
 
-table:not(.nostyle) tr { -webkit-transition:background-color 500ms; -moz-transition:background-color 500ms; -o-transition:background-color 500ms; transition:background-color 500ms; }
+table:not(.nostyle) tr { -webkit-transition:background-color 200ms; -moz-transition:background-color 200ms; -o-transition:background-color 200ms; transition:background-color 200ms; }
 tbody tr:hover, tr:active { background-color:#f8f8f8; }
 
 #body-settings .personalblock, #body-settings .helpblock { padding:.5em 1em; margin:1em; background:#f8f8f8; color:#555; text-shadow:#fff 0 1px 0; -moz-border-radius:.5em; -webkit-border-radius:.5em; border-radius:.5em; }
 #body-settings .personalblock#quota { position:relative; padding:0; }
 #body-settings #controls+.helpblock { position:relative; margin-top: 3em; }
 .personalblock > legend { margin-top:2em; }
+.personalblock > legend, th, dt, label { font-weight: bold; }
+code { font-family: "Lucida Console", "Lucida Sans Typewriter", "DejaVu Sans Mono", monospace; }
 
 #quota div, div.jp-play-bar, div.jp-seek-bar { padding:0; background:#e6e6e6; font-weight:normal; white-space:nowrap; -moz-border-radius-bottomleft:.4em; -webkit-border-bottom-left-radius:.4em; border-bottom-left-radius:.4em; -moz-border-radius-topleft:.4em; -webkit-border-top-left-radius:.4em; border-top-left-radius:.4em; }
 #quotatext {padding: .6em 1em;}
@@ -135,9 +141,9 @@ a.bookmarklet { background-color: #ddd; border:1px solid #ccc; padding: 5px;padd
 
 /* ---- DIALOGS ---- */
 #dirtree {width: 100%;}
-#filelist {height: 270px; overflow:scroll; background-color: white;}
+#filelist {height: 270px; overflow:scroll; background-color: white; width: 100%;}
 .filepicker_element_selected { background-color: lightblue;}
-.filepicker_loader {height: 120px; width: 100%; background-color: #333; opacity: 0.3; visibility: visible; position:absolute; top:0; left:0; text-align:center; padding-top: 150px;}
+.filepicker_loader {height: 120px; width: 100%; background-color: #333; -ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=30)"; filter:alpha(opacity=30); opacity:.3; visibility: visible; position:absolute; top:0; left:0; text-align:center; padding-top: 150px;}
 
 
 /* ---- CATEGORIES ---- */
diff --git a/core/img/actions/history.png b/core/img/actions/history.png
new file mode 100644
index 0000000000000000000000000000000000000000..b1e743651f827e9fa0b34dfdc0c7537f612b36d1
Binary files /dev/null and b/core/img/actions/history.png differ
diff --git a/core/img/actions/history.svg b/core/img/actions/history.svg
new file mode 100644
index 0000000000000000000000000000000000000000..9c2838d565b6a93f399581c3ff3272a5b6747649
--- /dev/null
+++ b/core/img/actions/history.svg
@@ -0,0 +1,240 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:osb="http://www.openswatchbook.org/uri/2009/osb"
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:xlink="http://www.w3.org/1999/xlink"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="17"
+   height="17"
+   id="svg3972"
+   version="1.1"
+   inkscape:version="0.48.1 r9760"
+   sodipodi:docname="backup.svg"
+   inkscape:export-filename="/home/ronny/persoenliches/Programme/JBackpack/jbackpack/src/ch/fhnw/jbackpack/icons/16x16/icon.png"
+   inkscape:export-xdpi="2.8099999"
+   inkscape:export-ydpi="2.8099999">
+  <defs
+     id="defs3974">
+    <linearGradient
+       id="linearGradient3820">
+      <stop
+         style="stop-color:#7399ab;stop-opacity:1;"
+         offset="0"
+         id="stop3822" />
+      <stop
+         style="stop-color:#fffeff;stop-opacity:1;"
+         offset="1"
+         id="stop3824" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient5144">
+      <stop
+         style="stop-color:#ab7392;stop-opacity:1;"
+         offset="0"
+         id="stop5146" />
+      <stop
+         style="stop-color:#ffffff;stop-opacity:0.02909091"
+         offset="1"
+         id="stop5148" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient5130">
+      <stop
+         id="stop5140"
+         offset="0"
+         style="stop-color:#a08f82;stop-opacity:0.74901961;" />
+      <stop
+         id="stop5138"
+         offset="0.5"
+         style="stop-color:#ab7392;stop-opacity:0.49803922;" />
+      <stop
+         style="stop-color:#ab7392;stop-opacity:0;"
+         offset="1"
+         id="stop5134" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient4519"
+       osb:paint="gradient">
+      <stop
+         style="stop-color:#5d879d;stop-opacity:1;"
+         offset="0"
+         id="stop4521" />
+      <stop
+         style="stop-color:#5d879d;stop-opacity:0;"
+         offset="1"
+         id="stop4523" />
+    </linearGradient>
+    <filter
+       id="filter4697"
+       inkscape:label="Drop shadow"
+       width="1.5"
+       height="1.5"
+       x="-0.25"
+       y="-0.25"
+       color-interpolation-filters="sRGB">
+      <feGaussianBlur
+         id="feGaussianBlur4699"
+         in="SourceAlpha"
+         stdDeviation="2"
+         result="blur" />
+      <feColorMatrix
+         id="feColorMatrix4701"
+         result="bluralpha"
+         type="matrix"
+         values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 0.5 0 " />
+      <feOffset
+         id="feOffset4703"
+         in="bluralpha"
+         dx="4"
+         dy="4"
+         result="offsetBlur" />
+      <feMerge
+         id="feMerge4705">
+        <feMergeNode
+           id="feMergeNode4707"
+           in="offsetBlur" />
+        <feMergeNode
+           id="feMergeNode4709"
+           in="SourceGraphic" />
+      </feMerge>
+    </filter>
+    <filter
+       id="filter5086"
+       inkscape:label="Drop shadow"
+       width="1.5"
+       height="1.5"
+       x="-0.25"
+       y="-0.25"
+       color-interpolation-filters="sRGB">
+      <feGaussianBlur
+         id="feGaussianBlur5088"
+         in="SourceAlpha"
+         stdDeviation="5"
+         result="blur" />
+      <feColorMatrix
+         id="feColorMatrix5090"
+         result="bluralpha"
+         type="matrix"
+         values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 0.5 0 " />
+      <feOffset
+         id="feOffset5092"
+         in="bluralpha"
+         dx="10"
+         dy="10"
+         result="offsetBlur" />
+      <feMerge
+         id="feMerge5094">
+        <feMergeNode
+           id="feMergeNode5096"
+           in="offsetBlur" />
+        <feMergeNode
+           id="feMergeNode5098"
+           in="SourceGraphic" />
+      </feMerge>
+    </filter>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient5130"
+       id="linearGradient5136"
+       x1="119.76609"
+       y1="431.36642"
+       x2="631.76611"
+       y2="431.36642"
+       gradientUnits="userSpaceOnUse" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient5144"
+       id="radialGradient5150"
+       cx="294.02567"
+       cy="300.53604"
+       fx="294.02567"
+       fy="300.53604"
+       r="183.84033"
+       gradientTransform="matrix(0.66691196,0.43225768,-0.44145763,0.68110633,230.61036,-24.143353)"
+       gradientUnits="userSpaceOnUse" />
+    <filter
+       inkscape:collect="always"
+       id="filter4381"
+       color-interpolation-filters="sRGB">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="2.5"
+         id="feGaussianBlur4383" />
+    </filter>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3820"
+       id="linearGradient3575"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.06875313,0,0,0.06875313,2.829762,444.82336)"
+       x1="339.43503"
+       y1="370.08636"
+       x2="66.978798"
+       y2="135.09288" />
+  </defs>
+  <sodipodi:namedview
+     id="base"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageopacity="0.0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="45.254834"
+     inkscape:cx="12.081283"
+     inkscape:cy="8.5032287"
+     inkscape:document-units="px"
+     inkscape:current-layer="layer1"
+     showgrid="true"
+     inkscape:window-width="1920"
+     inkscape:window-height="1033"
+     inkscape:window-x="-3"
+     inkscape:window-y="-3"
+     inkscape:window-maximized="1"
+     fit-margin-top="0"
+     fit-margin-left="0"
+     fit-margin-right="0"
+     fit-margin-bottom="0">
+    <inkscape:grid
+       type="xygrid"
+       id="grid4447"
+       empspacing="5"
+       visible="true"
+       enabled="true"
+       snapvisiblegridlinesonly="true" />
+  </sodipodi:namedview>
+  <metadata
+     id="metadata3977">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title></dc:title>
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <g
+     inkscape:label="Ebene 1"
+     inkscape:groupmode="layer"
+     id="layer1"
+     transform="translate(93.42207,-466.65551)">
+    <path
+       style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
+       d="m -83.896989,468.73997 c -3.950245,0 -6.534942,3.44694 -6.364259,6.72133 l -2.160822,0 3.904021,3.91738 4.081269,-3.87222 -2.148938,0 c -0.237051,-1.70092 1.163456,-3.1145 2.688727,-3.0921 1.596496,0.0235 2.800571,1.22922 2.800571,2.73336 0.08961,1.59378 -1.629405,3.4279 -3.965431,2.53172 -8.3e-5,1.22806 0.0027,2.54389 0,3.76397 4.189434,0.82896 7.639781,-2.50953 7.639781,-6.25087 0,-3.56212 -2.9188,-6.45252 -6.474921,-6.45252 z"
+       id="path4438"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="ccccccscccccc"
+       inkscape:export-filename="/home/samtuke/owncloud/git/owncloud/core/img/actions/history.png"
+       inkscape:export-xdpi="89.929733"
+       inkscape:export-ydpi="89.929733" />
+  </g>
+</svg>
diff --git a/core/img/favicon-touch.png b/core/img/favicon-touch.png
index 20af826523cfdb9da47ba1208c81df38ecb3973c..cfaaa4399acd8eba0ef6cc417d77779667adb5cf 100644
Binary files a/core/img/favicon-touch.png and b/core/img/favicon-touch.png differ
diff --git a/core/img/favicon-touch.svg b/core/img/favicon-touch.svg
new file mode 100644
index 0000000000000000000000000000000000000000..6d766d3ced328b30f7a53c9dedeaa4f67030f8b1
--- /dev/null
+++ b/core/img/favicon-touch.svg
@@ -0,0 +1,787 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Generator: Adobe Illustrator 13.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 14948)  -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:xlink="http://www.w3.org/1999/xlink"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   version="1.1"
+   id="Layer_1"
+   x="0px"
+   y="0px"
+   width="128"
+   height="128"
+   viewBox="0 0 128 127.99999"
+   enable-background="new 0 0 595.275 311.111"
+   xml:space="preserve"
+   inkscape:version="0.48.2 r9819"
+   sodipodi:docname="favicon.svg"
+   inkscape:export-filename="/home/user/owncloud/core/img/favicon.png"
+   inkscape:export-xdpi="89.826416"
+   inkscape:export-ydpi="89.826416"><metadata
+   id="metadata327"><rdf:RDF><cc:Work
+       rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
+         rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
+   id="defs325"><linearGradient
+   inkscape:collect="always"
+   xlink:href="#SVGID_1_"
+   id="linearGradient3353"
+   gradientUnits="userSpaceOnUse"
+   x1="288.49411"
+   y1="55.888199"
+   x2="288.49411"
+   y2="339.22189" /><linearGradient
+   inkscape:collect="always"
+   xlink:href="#SVGID_2_"
+   id="linearGradient3355"
+   gradientUnits="userSpaceOnUse"
+   x1="251.2114"
+   y1="55.888199"
+   x2="251.2114"
+   y2="339.22159" /><linearGradient
+   inkscape:collect="always"
+   xlink:href="#SVGID_3_"
+   id="linearGradient3357"
+   gradientUnits="userSpaceOnUse"
+   x1="293.22461"
+   y1="55.888199"
+   x2="293.22461"
+   y2="339.22171" /><linearGradient
+   inkscape:collect="always"
+   xlink:href="#SVGID_4_"
+   id="linearGradient3359"
+   gradientUnits="userSpaceOnUse"
+   x1="375.33401"
+   y1="55.888199"
+   x2="375.33401"
+   y2="339.22159" /><linearGradient
+   inkscape:collect="always"
+   xlink:href="#SVGID_5_"
+   id="linearGradient3361"
+   gradientUnits="userSpaceOnUse"
+   x1="334.49411"
+   y1="55.888199"
+   x2="334.49411"
+   y2="339.22159" /><linearGradient
+   inkscape:collect="always"
+   xlink:href="#SVGID_6_"
+   id="linearGradient3363"
+   gradientUnits="userSpaceOnUse"
+   x1="458.42679"
+   y1="55.8867"
+   x2="458.42679"
+   y2="339.2236" /><linearGradient
+   inkscape:collect="always"
+   xlink:href="#SVGID_7_"
+   id="linearGradient3365"
+   gradientUnits="userSpaceOnUse"
+   x1="413.16309"
+   y1="55.888199"
+   x2="413.16309"
+   y2="339.22131" /><linearGradient
+   inkscape:collect="always"
+   xlink:href="#SVGID_8_"
+   id="linearGradient3367"
+   gradientUnits="userSpaceOnUse"
+   x1="290.76169"
+   y1="55.8867"
+   x2="290.76169"
+   y2="339.2236" /><linearGradient
+   inkscape:collect="always"
+   xlink:href="#SVGID_9_"
+   id="linearGradient3369"
+   gradientUnits="userSpaceOnUse"
+   x1="346.77341"
+   y1="55.888199"
+   x2="346.77341"
+   y2="339.22119" />
+	<linearGradient
+   y2="339.22189"
+   x2="288.49411"
+   y1="55.888199"
+   x1="288.49411"
+   gradientUnits="userSpaceOnUse"
+   id="SVGID_1_">
+		<stop
+   id="stop261"
+   style="stop-color:#BED5E1"
+   offset="0" />
+		<stop
+   id="stop263"
+   style="stop-color:#567B8F"
+   offset="1" />
+	</linearGradient>
+	
+	<linearGradient
+   y2="339.22159"
+   x2="251.2114"
+   y1="55.888199"
+   x1="251.2114"
+   gradientUnits="userSpaceOnUse"
+   id="SVGID_2_">
+		<stop
+   id="stop268"
+   style="stop-color:#BED5E1"
+   offset="0" />
+		<stop
+   id="stop270"
+   style="stop-color:#567B8F"
+   offset="1" />
+	</linearGradient>
+	
+	<linearGradient
+   y2="339.22171"
+   x2="293.22461"
+   y1="55.888199"
+   x1="293.22461"
+   gradientUnits="userSpaceOnUse"
+   id="SVGID_3_">
+		<stop
+   id="stop275"
+   style="stop-color:#BED5E1"
+   offset="0" />
+		<stop
+   id="stop277"
+   style="stop-color:#567B8F"
+   offset="1" />
+	</linearGradient>
+	
+	<linearGradient
+   y2="339.22159"
+   x2="375.33401"
+   y1="55.888199"
+   x1="375.33401"
+   gradientUnits="userSpaceOnUse"
+   id="SVGID_4_">
+		<stop
+   id="stop282"
+   style="stop-color:#BED5E1"
+   offset="0" />
+		<stop
+   id="stop284"
+   style="stop-color:#567B8F"
+   offset="1" />
+	</linearGradient>
+	
+	<linearGradient
+   y2="339.22159"
+   x2="334.49411"
+   y1="55.888199"
+   x1="334.49411"
+   gradientUnits="userSpaceOnUse"
+   id="SVGID_5_">
+		<stop
+   id="stop289"
+   style="stop-color:#BED5E1"
+   offset="0" />
+		<stop
+   id="stop291"
+   style="stop-color:#567B8F"
+   offset="1" />
+	</linearGradient>
+	
+	<linearGradient
+   y2="339.2236"
+   x2="458.42679"
+   y1="55.8867"
+   x1="458.42679"
+   gradientUnits="userSpaceOnUse"
+   id="SVGID_6_">
+		<stop
+   id="stop296"
+   style="stop-color:#BED5E1"
+   offset="0" />
+		<stop
+   id="stop298"
+   style="stop-color:#567B8F"
+   offset="1" />
+	</linearGradient>
+	
+	<linearGradient
+   y2="339.22131"
+   x2="413.16309"
+   y1="55.888199"
+   x1="413.16309"
+   gradientUnits="userSpaceOnUse"
+   id="SVGID_7_">
+		<stop
+   id="stop303"
+   style="stop-color:#BED5E1"
+   offset="0" />
+		<stop
+   id="stop305"
+   style="stop-color:#567B8F"
+   offset="1" />
+	</linearGradient>
+	
+	<linearGradient
+   y2="339.2236"
+   x2="290.76169"
+   y1="55.8867"
+   x1="290.76169"
+   gradientUnits="userSpaceOnUse"
+   id="SVGID_8_">
+		<stop
+   id="stop310"
+   style="stop-color:#BED5E1"
+   offset="0" />
+		<stop
+   id="stop312"
+   style="stop-color:#567B8F"
+   offset="1" />
+	</linearGradient>
+	
+	<linearGradient
+   y2="339.22119"
+   x2="346.77341"
+   y1="55.888199"
+   x1="346.77341"
+   gradientUnits="userSpaceOnUse"
+   id="SVGID_9_">
+		<stop
+   id="stop317"
+   style="stop-color:#BED5E1"
+   offset="0" />
+		<stop
+   id="stop319"
+   style="stop-color:#567B8F"
+   offset="1" />
+	</linearGradient>
+	
+<linearGradient
+   y2="18.967093"
+   x2="-2.4040222"
+   y1="4.4573336"
+   x1="-2.4040222"
+   gradientTransform="translate(13.927091,16.573387)"
+   gradientUnits="userSpaceOnUse"
+   id="linearGradient3475"
+   xlink:href="#linearGradient3587-6-5-26"
+   inkscape:collect="always" /><linearGradient
+   id="linearGradient3587-6-5-26"><stop
+     id="stop3589-9-2-45"
+     style="stop-color:#000000;stop-opacity:1"
+     offset="0" /><stop
+     id="stop3591-7-4-20"
+     style="stop-color:#363636;stop-opacity:1"
+     offset="1" /></linearGradient></defs><sodipodi:namedview
+   pagecolor="#ffffff"
+   bordercolor="#666666"
+   borderopacity="1"
+   objecttolerance="10"
+   gridtolerance="10"
+   guidetolerance="10"
+   inkscape:pageopacity="0"
+   inkscape:pageshadow="2"
+   inkscape:window-width="1280"
+   inkscape:window-height="774"
+   id="namedview323"
+   showgrid="false"
+   inkscape:zoom="2"
+   inkscape:cx="121.64549"
+   inkscape:cy="57.492689"
+   inkscape:window-x="0"
+   inkscape:window-y="26"
+   inkscape:window-maximized="1"
+   inkscape:current-layer="Layer_1"
+   units="px"
+   fit-margin-top="0"
+   fit-margin-left="0"
+   fit-margin-right="0"
+   fit-margin-bottom="0"
+   showguides="true"
+   inkscape:guide-bbox="true" />
+<pattern
+   y="565.223"
+   width="69"
+   height="69"
+   patternUnits="userSpaceOnUse"
+   id="Polka_Dot_Pattern"
+   viewBox="2.125 -70.896 69 69"
+   overflow="visible">
+	<g
+   id="g4">
+		<polygon
+   fill="none"
+   points="71.125,-1.896 2.125,-1.896 2.125,-70.896 71.125,-70.896   "
+   id="polygon6" />
+		<polygon
+   fill="#F6BB60"
+   points="71.125,-1.896 2.125,-1.896 2.125,-70.896 71.125,-70.896   "
+   id="polygon8" />
+		<g
+   id="g10">
+			<path
+   fill="#FFFFFF"
+   d="M61.772-71.653c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128     c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161     c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631     c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45     c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221     c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337     c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207     c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169     c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path12" />
+			<path
+   fill="#FFFFFF"
+   d="M54.105-71.653c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128     c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161     c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631     c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45     c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221     c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337     c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207     c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169     c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path14" />
+			<path
+   fill="#FFFFFF"
+   d="M46.439-71.653c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128     c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161     c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631     c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45     c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221     c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337     c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207     c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169     c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path16" />
+			<path
+   fill="#FFFFFF"
+   d="M38.772-71.653c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128     c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161     c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631     c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45     c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221     c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337     c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207     c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169     c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path18" />
+			<path
+   fill="#FFFFFF"
+   d="M31.105-71.653c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128     c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161     c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631     c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45     c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221     c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337     c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207     c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169     c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path20" />
+			<path
+   fill="#FFFFFF"
+   d="M23.439-71.653c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128     c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161     c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631     c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45     c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221     c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337     c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207     c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169     c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path22" />
+			<path
+   fill="#FFFFFF"
+   d="M15.772-71.653c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128     c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161     c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631     c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45     c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221     c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337     c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207     c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169     c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path24" />
+			<path
+   fill="#FFFFFF"
+   d="M8.105-71.653c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128     c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161     c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631     c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45     c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221     c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337     c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207     c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169     c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path26" />
+			<path
+   fill="#FFFFFF"
+   d="M0.439-71.653c0.018,0.072,0.008,0.127-0.026,0.19C0.361-71.362,0.3-71.4,0.248-71.335     c-0.051,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161     c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631     c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45     c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.07,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221     c0.038-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.051-0.12-0.064-0.187c-0.021-0.114,0.002-0.224,0-0.337     c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207     c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.215,0.124-0.215,0.224c0.002,0.115,0.005,0.051,0.012,0.169     c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path28" />
+		</g>
+		<g
+   id="g30">
+			<path
+   fill="#FFFFFF"
+   d="M69.439-71.653c0.018,0.072,0.008,0.127-0.026,0.19c-0.052,0.101-0.113,0.062-0.165,0.128     c-0.051,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161     c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631     c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45     c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.07,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221     c0.038-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.051-0.12-0.064-0.187c-0.021-0.114,0.002-0.224,0-0.337     c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207     c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.215,0.124-0.215,0.224c0.002,0.115,0.005,0.051,0.012,0.169     c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path32" />
+		</g>
+		<path
+   fill="#FFFFFF"
+   d="M0.495-71.653c0.018,0.072,0.008,0.127-0.026,0.19c-0.052,0.101-0.113,0.062-0.165,0.128    c-0.051,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161    c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631    c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45    c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.07,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221    c0.038-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.051-0.12-0.064-0.187c-0.021-0.114,0.002-0.224,0-0.337    c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207    c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.215,0.124-0.215,0.224C0.5-71.68,0.503-71.744,0.51-71.626    c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path34" />
+		<g
+   id="g36">
+			<g
+   id="g38">
+				<path
+   fill="#FFFFFF"
+   d="M69.439-64.001c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path40" />
+				<path
+   fill="#FFFFFF"
+   d="M61.778-64.001c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path42" />
+				<path
+   fill="#FFFFFF"
+   d="M54.118-64.001c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path44" />
+				<path
+   fill="#FFFFFF"
+   d="M46.458-64.001c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path46" />
+				<path
+   fill="#FFFFFF"
+   d="M38.797-64.001c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path48" />
+				<path
+   fill="#FFFFFF"
+   d="M31.137-64.001c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path50" />
+				<path
+   fill="#FFFFFF"
+   d="M23.477-64.001c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path52" />
+				<path
+   fill="#FFFFFF"
+   d="M15.816-64.001c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path54" />
+				<path
+   fill="#FFFFFF"
+   d="M8.156-64.001c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path56" />
+				<path
+   fill="#FFFFFF"
+   d="M0.495-64.001c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143C2-61.45,2.217-61.397,2.391-61.46c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path58" />
+			</g>
+			<g
+   id="g60">
+				<path
+   fill="#FFFFFF"
+   d="M69.439-56.348c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path62" />
+				<path
+   fill="#FFFFFF"
+   d="M61.778-56.348c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path64" />
+				<path
+   fill="#FFFFFF"
+   d="M54.118-56.348c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path66" />
+				<path
+   fill="#FFFFFF"
+   d="M46.458-56.348c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path68" />
+				<path
+   fill="#FFFFFF"
+   d="M38.797-56.348c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path70" />
+				<path
+   fill="#FFFFFF"
+   d="M31.137-56.348c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path72" />
+				<path
+   fill="#FFFFFF"
+   d="M23.477-56.348c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path74" />
+				<path
+   fill="#FFFFFF"
+   d="M15.816-56.348c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path76" />
+				<path
+   fill="#FFFFFF"
+   d="M8.156-56.348c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path78" />
+				<path
+   fill="#FFFFFF"
+   d="M0.495-56.348c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224C0.5-56.374,0.503-56.438,0.51-56.32      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path80" />
+			</g>
+			<g
+   id="g82">
+				<path
+   fill="#FFFFFF"
+   d="M69.439-48.695c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path84" />
+				<path
+   fill="#FFFFFF"
+   d="M61.778-48.695c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path86" />
+				<path
+   fill="#FFFFFF"
+   d="M54.118-48.695c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path88" />
+				<path
+   fill="#FFFFFF"
+   d="M46.458-48.695c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path90" />
+				<path
+   fill="#FFFFFF"
+   d="M38.797-48.695c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path92" />
+				<path
+   fill="#FFFFFF"
+   d="M31.137-48.695c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path94" />
+				<path
+   fill="#FFFFFF"
+   d="M23.477-48.695c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path96" />
+				<path
+   fill="#FFFFFF"
+   d="M15.816-48.695c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path98" />
+				<path
+   fill="#FFFFFF"
+   d="M8.156-48.695c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path100" />
+				<path
+   fill="#FFFFFF"
+   d="M0.495-48.695c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path102" />
+			</g>
+			<g
+   id="g104">
+				<path
+   fill="#FFFFFF"
+   d="M69.439-41.042c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path106" />
+				<path
+   fill="#FFFFFF"
+   d="M61.778-41.042c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path108" />
+				<path
+   fill="#FFFFFF"
+   d="M54.118-41.042c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path110" />
+				<path
+   fill="#FFFFFF"
+   d="M46.458-41.042c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path112" />
+				<path
+   fill="#FFFFFF"
+   d="M38.797-41.042c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path114" />
+				<path
+   fill="#FFFFFF"
+   d="M31.137-41.042c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path116" />
+				<path
+   fill="#FFFFFF"
+   d="M23.477-41.042c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path118" />
+				<path
+   fill="#FFFFFF"
+   d="M15.816-41.042c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path120" />
+				<path
+   fill="#FFFFFF"
+   d="M8.156-41.042c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      C8.15-41.004,8.149-41.02,8.14-41.04"
+   id="path122" />
+				<path
+   fill="#FFFFFF"
+   d="M0.495-41.042c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path124" />
+			</g>
+			<g
+   id="g126">
+				<path
+   fill="#FFFFFF"
+   d="M69.439-33.39c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path128" />
+				<path
+   fill="#FFFFFF"
+   d="M61.778-33.39c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path130" />
+				<path
+   fill="#FFFFFF"
+   d="M54.118-33.39c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path132" />
+				<path
+   fill="#FFFFFF"
+   d="M46.458-33.39c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path134" />
+				<path
+   fill="#FFFFFF"
+   d="M38.797-33.39c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path136" />
+				<path
+   fill="#FFFFFF"
+   d="M31.137-33.39c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path138" />
+				<path
+   fill="#FFFFFF"
+   d="M23.477-33.39c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path140" />
+				<path
+   fill="#FFFFFF"
+   d="M15.816-33.39c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path142" />
+				<path
+   fill="#FFFFFF"
+   d="M8.156-33.39c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path144" />
+				<path
+   fill="#FFFFFF"
+   d="M0.495-33.39c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224C0.5-33.416,0.503-33.48,0.51-33.362      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path146" />
+			</g>
+			<g
+   id="g148">
+				<path
+   fill="#FFFFFF"
+   d="M69.439-25.736c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path150" />
+				<path
+   fill="#FFFFFF"
+   d="M61.778-25.736c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path152" />
+				<path
+   fill="#FFFFFF"
+   d="M54.118-25.736c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path154" />
+				<path
+   fill="#FFFFFF"
+   d="M46.458-25.736c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path156" />
+				<path
+   fill="#FFFFFF"
+   d="M38.797-25.736c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path158" />
+				<path
+   fill="#FFFFFF"
+   d="M31.137-25.736c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path160" />
+				<path
+   fill="#FFFFFF"
+   d="M23.477-25.736c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path162" />
+				<path
+   fill="#FFFFFF"
+   d="M15.816-25.736c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path164" />
+				<path
+   fill="#FFFFFF"
+   d="M8.156-25.736c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path166" />
+				<path
+   fill="#FFFFFF"
+   d="M0.495-25.736c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path168" />
+			</g>
+			<g
+   id="g170">
+				<path
+   fill="#FFFFFF"
+   d="M69.439-18.084c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path172" />
+				<path
+   fill="#FFFFFF"
+   d="M61.778-18.084c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path174" />
+				<path
+   fill="#FFFFFF"
+   d="M54.118-18.084c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path176" />
+				<path
+   fill="#FFFFFF"
+   d="M46.458-18.084c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path178" />
+				<path
+   fill="#FFFFFF"
+   d="M38.797-18.084c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path180" />
+				<path
+   fill="#FFFFFF"
+   d="M31.137-18.084c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path182" />
+				<path
+   fill="#FFFFFF"
+   d="M23.477-18.084c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path184" />
+				<path
+   fill="#FFFFFF"
+   d="M15.816-18.084c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path186" />
+				<path
+   fill="#FFFFFF"
+   d="M8.156-18.084c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path188" />
+				<path
+   fill="#FFFFFF"
+   d="M0.495-18.084c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224C0.5-18.11,0.503-18.175,0.51-18.057      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path190" />
+			</g>
+			<g
+   id="g192">
+				<path
+   fill="#FFFFFF"
+   d="M69.439-10.431c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362C69-9.692,69.159-9.523,69.154-9.4c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path194" />
+				<path
+   fill="#FFFFFF"
+   d="M61.778-10.431c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path196" />
+				<path
+   fill="#FFFFFF"
+   d="M54.118-10.431c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path198" />
+				<path
+   fill="#FFFFFF"
+   d="M46.458-10.431c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path200" />
+				<path
+   fill="#FFFFFF"
+   d="M38.797-10.431c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path202" />
+				<path
+   fill="#FFFFFF"
+   d="M31.137-10.431c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path204" />
+				<path
+   fill="#FFFFFF"
+   d="M23.477-10.431c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path206" />
+				<path
+   fill="#FFFFFF"
+   d="M15.816-10.431c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053C17.933-7.969,17.839-8.227,18-8.34      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path208" />
+				<path
+   fill="#FFFFFF"
+   d="M8.156-10.431c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      C7.915-10.05,7.866-9.836,7.886-9.75C7.717-9.692,7.876-9.523,7.871-9.4C7.868-9.351,7.83-9.295,7.826-9.239      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      C9.114-7.652,9.321-7.799,9.48-7.837c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path210" />
+				<path
+   fill="#FFFFFF"
+   d="M0.495-10.431c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      C0.254-10.05,0.205-9.836,0.225-9.75C0.056-9.692,0.215-9.523,0.21-9.4c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37C0.33-8.671,0.501-8.456,0.668-8.325c0.19,0.148,0.365,0.572,0.608,0.631      C1.454-7.652,1.66-7.799,1.819-7.837C2-7.88,2.217-7.827,2.391-7.89c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46C3.477-8.933,3.471-8.995,3.5-9.071      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path212" />
+			</g>
+		</g>
+		<g
+   id="g214">
+			<path
+   fill="#FFFFFF"
+   d="M69.439-2.778c0.018,0.072,0.008,0.127-0.026,0.19C69.361-2.487,69.3-2.525,69.248-2.46     c-0.051,0.062-0.099,0.276-0.079,0.362C69-2.04,69.159-1.871,69.154-1.748c-0.002,0.05-0.041,0.105-0.045,0.161     c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631     C70.397,0,70.604-0.146,70.763-0.185c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45     c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.07,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221     c0.038-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.051-0.12-0.064-0.187c-0.021-0.114,0.002-0.224,0-0.337     c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207     c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.215,0.124-0.215,0.224c0.002,0.115,0.005,0.051,0.012,0.169     c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path216" />
+			<path
+   fill="#FFFFFF"
+   d="M61.778-2.778c0.018,0.072,0.007,0.127-0.026,0.19C61.7-2.487,61.64-2.525,61.587-2.46     c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161     c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631     C62.737,0,62.943-0.146,63.103-0.185c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45     c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221     c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337     c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207     c-0.17,0.088-0.139,0.166-0.318,0.224C61.915-3.117,61.78-3.02,61.781-2.92c0.001,0.115,0.005,0.051,0.012,0.169     c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path218" />
+			<path
+   fill="#FFFFFF"
+   d="M54.118-2.778c0.018,0.072,0.007,0.127-0.026,0.19C54.04-2.487,53.98-2.525,53.927-2.46     c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161     c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631     C55.077,0,55.283-0.146,55.442-0.185c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45     c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221     c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337     c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207     c-0.17,0.088-0.139,0.166-0.318,0.224C54.255-3.117,54.12-3.02,54.121-2.92c0.001,0.115,0.005,0.051,0.012,0.169     c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path220" />
+			<path
+   fill="#FFFFFF"
+   d="M46.458-2.778c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128     c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161     c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631     C47.416,0,47.623-0.146,47.782-0.185c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45     c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221     c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337     c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207     c-0.17,0.088-0.139,0.166-0.318,0.224C46.594-3.117,46.459-3.02,46.46-2.92c0.001,0.115,0.005,0.051,0.012,0.169     c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path222" />
+			<path
+   fill="#FFFFFF"
+   d="M38.797-2.778c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128     c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161     c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631     C39.756,0,39.962-0.146,40.122-0.185c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45     c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221     c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337     c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207     c-0.17,0.088-0.139,0.166-0.318,0.224C38.934-3.117,38.799-3.02,38.8-2.92c0.001,0.115,0.005,0.051,0.012,0.169     c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path224" />
+			<path
+   fill="#FFFFFF"
+   d="M31.137-2.778c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128     c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161     c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631     C32.095,0,32.302-0.146,32.461-0.185c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45     c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221     c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337     c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207     c-0.17,0.088-0.139,0.166-0.318,0.224C31.273-3.117,31.139-3.02,31.14-2.92c0.001,0.115,0.005,0.051,0.012,0.169     c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path226" />
+			<path
+   fill="#FFFFFF"
+   d="M23.477-2.778c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128     c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161     c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631     C24.435,0,24.642-0.146,24.801-0.185c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45     c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221     c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337     c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207     c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169     c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path228" />
+			<path
+   fill="#FFFFFF"
+   d="M15.816-2.778c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128     c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161     c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631     C16.774,0,16.981-0.146,17.14-0.185c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45     c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221     c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337     c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207     c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169     C15.81-2.74,15.809-2.756,15.8-2.776"
+   id="path230" />
+			<path
+   fill="#FFFFFF"
+   d="M8.156-2.778c0.018,0.072,0.007,0.127-0.026,0.19C8.077-2.487,8.018-2.525,7.965-2.46     c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35C7.868-1.698,7.83-1.643,7.826-1.587     c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631     C9.114,0,9.321-0.146,9.48-0.185c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45     c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221     c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337     c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789C8.954-3.54,8.847-3.448,8.692-3.367     c-0.17,0.088-0.139,0.166-0.318,0.224C8.292-3.117,8.158-3.02,8.159-2.92C8.16-2.805,8.164-2.869,8.17-2.751     C8.15-2.74,8.149-2.756,8.14-2.776"
+   id="path232" />
+			<path
+   fill="#FFFFFF"
+   d="M0.495-2.778c0.018,0.072,0.008,0.127-0.026,0.19C0.417-2.487,0.356-2.525,0.304-2.46     C0.253-2.397,0.205-2.184,0.225-2.098C0.056-2.04,0.215-1.871,0.21-1.748c-0.002,0.05-0.041,0.105-0.045,0.161     c-0.01,0.119,0.017,0.266,0.068,0.37C0.33-1.019,0.501-0.804,0.668-0.673c0.19,0.148,0.365,0.572,0.608,0.631     C1.454,0,1.66-0.146,1.819-0.185C2-0.228,2.217-0.175,2.391-0.237c0.222-0.079,0.127-0.337,0.288-0.45     c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.07,0.339-0.263,0.376-0.46C3.477-1.28,3.471-1.343,3.5-1.419     c0.038-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.051-0.12-0.064-0.187c-0.021-0.114,0.002-0.224,0-0.337     c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789C1.293-3.54,1.187-3.448,1.031-3.367     c-0.17,0.088-0.139,0.166-0.318,0.224C0.632-3.117,0.498-3.02,0.498-2.92C0.5-2.805,0.503-2.869,0.51-2.751     C0.489-2.74,0.488-2.756,0.479-2.776"
+   id="path234" />
+		</g>
+	</g>
+</pattern>
+
+<rect
+   style="fill:#1d2d44;fill-opacity:1"
+   id="rect7667"
+   width="128"
+   height="128"
+   x="0"
+   y="-1.5000001e-06"
+   rx="20"
+   ry="20" /><path
+   style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;baseline-shift:baseline;color:#000000;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:4;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Sans;-inkscape-font-specification:Sans"
+   d="m 58.33248,29.12399 c -8.931744,0 -16.147768,7.21604 -16.147768,16.14776 0,3.68172 1.225952,7.07024 3.292884,9.78364 4.483908,-5.1898 11.101748,-8.48548 18.490768,-8.48548 3.615048,0 7.043084,0.805 10.13194,2.21636 0.25008,-1.131 0.37996,-2.30724 0.37996,-3.51452 0,-8.93172 -7.216012,-16.14776 -16.147764,-16.14776 z M 37.2454,36.59631 c -4.651408,0 -8.390508,3.77076 -8.390508,8.42216 0,1.506 0.38852,2.92896 1.076512,4.14776 2.80684,-1.58336 6.051864,-2.50132 9.498688,-2.50132 0.33264,0 0.653036,0.012 0.981536,0.032 -0.0372,-0.47152 -0.06328,-0.9438 -0.06328,-1.4248 0,-2.59072 0.562688,-5.05568 1.551452,-7.28232 -1.33128,-0.89272 -2.926288,-1.39312 -4.654356,-1.39312 z m 39.83116,5.7942 c -0.34364,0 -0.674872,0.042 -1.013196,0.0632 0.14636,0.92272 0.25328,1.85444 0.25328,2.81796 0,1.49944 -0.19068,2.94632 -0.538256,4.33772 4.074936,2.25512 7.45902,5.62936 9.68866,9.72032 2.312644,-1.204 4.892476,-1.96952 7.630616,-2.15304 -0.705676,-8.27576 -7.561776,-14.78628 -16.02112,-14.78628 z m -13.108196,6.01584 c -12.498188,0 -22.606872,10.1078 -22.606872,22.60684 0,12.49768 10.108168,22.60688 22.606872,22.60688 12.498716,0 22.60688,-10.1092 22.60688,-22.60688 0,-12.499 -10.10868,-22.60684 -22.60688,-22.60684 z m -24.538272,0.0948 c -9.696224,0 -17.5409,7.84468 -17.5409,17.54092 0,5.70796 2.719624,10.761 6.93404,13.96304 1.776716,-3.42676 5.34516,-5.76252 9.46702,-5.76252 0.498168,0 0.976332,0.0604 1.456464,0.1268 -0.15072,-1.09656 -0.22164,-2.21844 -0.22164,-3.3562 0,-5.43972 1.770672,-10.47008 4.780996,-14.53296 -1.801952,-2.25484 -3.0915,-4.96408 -3.641168,-7.9156 -0.407372,-0.028 -0.820216,-0.0632 -1.234824,-0.0632 z m 54.965732,10.44856 c -2.94422,0 -5.702192,0.75168 -8.137212,2.0264 1.382684,3.06272 2.153036,6.46088 2.153036,10.03692 0,6.69584 -2.692088,12.77572 -7.060688,17.1926 3.209324,3.56304 7.865672,5.7942 13.044864,5.7942 9.696226,0 17.540916,-7.84464 17.540916,-17.54088 0,-9.69624 -7.84469,-17.50924 -17.540916,-17.50924 z m -74.2164,2.31152 C 11.24742,61.26123 4,68.44531 4,77.37731 c 0,8.932 7.24742,16.17944 16.179424,16.17944 3.399648,0 6.5489,-1.0592 9.150408,-2.8496 -1.074996,-1.67044 -1.709768,-3.66752 -1.709768,-5.7942 0,-1.10384 0.16288,-2.16428 0.474928,-3.16624 -4.870276,-3.51968 -8.04222,-9.24728 -8.04222,-15.70448 0,-1.64064 0.2162,-3.22704 0.601592,-4.74936 -0.15996,-0.004 -0.3138,-0.032 -0.47494,-0.032 z m 94.955196,13.86808 c -0.47649,0 -0.93756,0.0544 -1.39314,0.1268 0.0252,0.40276 0.0316,0.79408 0.0316,1.20316 0,5.15012 -2.03206,9.82456 -5.31926,13.29816 1.61719,1.8806 3.99262,3.07124 6.68075,3.07124 4.89645,0 8.86544,-3.93732 8.86544,-8.8338 0,-4.89644 -3.96899,-8.8654 -8.86544,-8.8654 z m -76.844368,0.94984 c -4.8962,0 -8.833776,3.9376 -8.833776,8.8338 0,4.89616 3.937576,8.86544 8.833776,8.86544 3.753,0 6.93856,-2.34184 8.2322,-5.63592 -3.156528,-3.21488 -5.42508,-7.31624 -6.427444,-11.87332 -0.586568,-0.1212 -1.181936,-0.19 -1.804756,-0.19 z"
+   id="circle238"
+   inkscape:export-filename="/home/user/owncloud/core/img/logo.png"
+   inkscape:export-xdpi="90"
+   inkscape:export-ydpi="90"
+   inkscape:connector-curvature="0"
+   sodipodi:nodetypes="sscscsscscscscccscscccsssssssscscsccsscscssscsscscsccccscssccsssccs" />
+
+
+
+
+
+
+
+
+
+
+</svg>
\ No newline at end of file
diff --git a/core/img/favicon.png b/core/img/favicon.png
index a7ee766dfa8931c9a707520176aa02aee76bb7b0..c1b1cb65460c7e61dac7eed23697bf558db2868b 100644
Binary files a/core/img/favicon.png and b/core/img/favicon.png differ
diff --git a/core/img/favicon.svg b/core/img/favicon.svg
new file mode 100644
index 0000000000000000000000000000000000000000..f055c32efb6066c93e32f3bc7cbb3a189a616be4
--- /dev/null
+++ b/core/img/favicon.svg
@@ -0,0 +1,796 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Generator: Adobe Illustrator 13.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 14948)  -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:xlink="http://www.w3.org/1999/xlink"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   version="1.1"
+   id="Layer_1"
+   x="0px"
+   y="0px"
+   width="32"
+   height="32"
+   viewBox="0 0 32 31.999997"
+   enable-background="new 0 0 595.275 311.111"
+   xml:space="preserve"
+   inkscape:version="0.48.2 r9819"
+   sodipodi:docname="logo-iconbluesmall.svg"
+   inkscape:export-filename="/home/user/owncloud/core/img/favicon.png"
+   inkscape:export-xdpi="89.826416"
+   inkscape:export-ydpi="89.826416"><metadata
+   id="metadata327"><rdf:RDF><cc:Work
+       rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
+         rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
+   id="defs325"><linearGradient
+   inkscape:collect="always"
+   xlink:href="#SVGID_1_"
+   id="linearGradient3353"
+   gradientUnits="userSpaceOnUse"
+   x1="288.49411"
+   y1="55.888199"
+   x2="288.49411"
+   y2="339.22189" /><linearGradient
+   inkscape:collect="always"
+   xlink:href="#SVGID_2_"
+   id="linearGradient3355"
+   gradientUnits="userSpaceOnUse"
+   x1="251.2114"
+   y1="55.888199"
+   x2="251.2114"
+   y2="339.22159" /><linearGradient
+   inkscape:collect="always"
+   xlink:href="#SVGID_3_"
+   id="linearGradient3357"
+   gradientUnits="userSpaceOnUse"
+   x1="293.22461"
+   y1="55.888199"
+   x2="293.22461"
+   y2="339.22171" /><linearGradient
+   inkscape:collect="always"
+   xlink:href="#SVGID_4_"
+   id="linearGradient3359"
+   gradientUnits="userSpaceOnUse"
+   x1="375.33401"
+   y1="55.888199"
+   x2="375.33401"
+   y2="339.22159" /><linearGradient
+   inkscape:collect="always"
+   xlink:href="#SVGID_5_"
+   id="linearGradient3361"
+   gradientUnits="userSpaceOnUse"
+   x1="334.49411"
+   y1="55.888199"
+   x2="334.49411"
+   y2="339.22159" /><linearGradient
+   inkscape:collect="always"
+   xlink:href="#SVGID_6_"
+   id="linearGradient3363"
+   gradientUnits="userSpaceOnUse"
+   x1="458.42679"
+   y1="55.8867"
+   x2="458.42679"
+   y2="339.2236" /><linearGradient
+   inkscape:collect="always"
+   xlink:href="#SVGID_7_"
+   id="linearGradient3365"
+   gradientUnits="userSpaceOnUse"
+   x1="413.16309"
+   y1="55.888199"
+   x2="413.16309"
+   y2="339.22131" /><linearGradient
+   inkscape:collect="always"
+   xlink:href="#SVGID_8_"
+   id="linearGradient3367"
+   gradientUnits="userSpaceOnUse"
+   x1="290.76169"
+   y1="55.8867"
+   x2="290.76169"
+   y2="339.2236" /><linearGradient
+   inkscape:collect="always"
+   xlink:href="#SVGID_9_"
+   id="linearGradient3369"
+   gradientUnits="userSpaceOnUse"
+   x1="346.77341"
+   y1="55.888199"
+   x2="346.77341"
+   y2="339.22119" />
+	<linearGradient
+   y2="339.22189"
+   x2="288.49411"
+   y1="55.888199"
+   x1="288.49411"
+   gradientUnits="userSpaceOnUse"
+   id="SVGID_1_">
+		<stop
+   id="stop261"
+   style="stop-color:#BED5E1"
+   offset="0" />
+		<stop
+   id="stop263"
+   style="stop-color:#567B8F"
+   offset="1" />
+	</linearGradient>
+	
+	<linearGradient
+   y2="339.22159"
+   x2="251.2114"
+   y1="55.888199"
+   x1="251.2114"
+   gradientUnits="userSpaceOnUse"
+   id="SVGID_2_">
+		<stop
+   id="stop268"
+   style="stop-color:#BED5E1"
+   offset="0" />
+		<stop
+   id="stop270"
+   style="stop-color:#567B8F"
+   offset="1" />
+	</linearGradient>
+	
+	<linearGradient
+   y2="339.22171"
+   x2="293.22461"
+   y1="55.888199"
+   x1="293.22461"
+   gradientUnits="userSpaceOnUse"
+   id="SVGID_3_">
+		<stop
+   id="stop275"
+   style="stop-color:#BED5E1"
+   offset="0" />
+		<stop
+   id="stop277"
+   style="stop-color:#567B8F"
+   offset="1" />
+	</linearGradient>
+	
+	<linearGradient
+   y2="339.22159"
+   x2="375.33401"
+   y1="55.888199"
+   x1="375.33401"
+   gradientUnits="userSpaceOnUse"
+   id="SVGID_4_">
+		<stop
+   id="stop282"
+   style="stop-color:#BED5E1"
+   offset="0" />
+		<stop
+   id="stop284"
+   style="stop-color:#567B8F"
+   offset="1" />
+	</linearGradient>
+	
+	<linearGradient
+   y2="339.22159"
+   x2="334.49411"
+   y1="55.888199"
+   x1="334.49411"
+   gradientUnits="userSpaceOnUse"
+   id="SVGID_5_">
+		<stop
+   id="stop289"
+   style="stop-color:#BED5E1"
+   offset="0" />
+		<stop
+   id="stop291"
+   style="stop-color:#567B8F"
+   offset="1" />
+	</linearGradient>
+	
+	<linearGradient
+   y2="339.2236"
+   x2="458.42679"
+   y1="55.8867"
+   x1="458.42679"
+   gradientUnits="userSpaceOnUse"
+   id="SVGID_6_">
+		<stop
+   id="stop296"
+   style="stop-color:#BED5E1"
+   offset="0" />
+		<stop
+   id="stop298"
+   style="stop-color:#567B8F"
+   offset="1" />
+	</linearGradient>
+	
+	<linearGradient
+   y2="339.22131"
+   x2="413.16309"
+   y1="55.888199"
+   x1="413.16309"
+   gradientUnits="userSpaceOnUse"
+   id="SVGID_7_">
+		<stop
+   id="stop303"
+   style="stop-color:#BED5E1"
+   offset="0" />
+		<stop
+   id="stop305"
+   style="stop-color:#567B8F"
+   offset="1" />
+	</linearGradient>
+	
+	<linearGradient
+   y2="339.2236"
+   x2="290.76169"
+   y1="55.8867"
+   x1="290.76169"
+   gradientUnits="userSpaceOnUse"
+   id="SVGID_8_">
+		<stop
+   id="stop310"
+   style="stop-color:#BED5E1"
+   offset="0" />
+		<stop
+   id="stop312"
+   style="stop-color:#567B8F"
+   offset="1" />
+	</linearGradient>
+	
+	<linearGradient
+   y2="339.22119"
+   x2="346.77341"
+   y1="55.888199"
+   x1="346.77341"
+   gradientUnits="userSpaceOnUse"
+   id="SVGID_9_">
+		<stop
+   id="stop317"
+   style="stop-color:#BED5E1"
+   offset="0" />
+		<stop
+   id="stop319"
+   style="stop-color:#567B8F"
+   offset="1" />
+	</linearGradient>
+	
+<linearGradient
+   y2="18.967093"
+   x2="-2.4040222"
+   y1="4.4573336"
+   x1="-2.4040222"
+   gradientTransform="translate(13.927091,16.573387)"
+   gradientUnits="userSpaceOnUse"
+   id="linearGradient3475"
+   xlink:href="#linearGradient3587-6-5-26"
+   inkscape:collect="always" /><linearGradient
+   id="linearGradient3587-6-5-26"><stop
+     id="stop3589-9-2-45"
+     style="stop-color:#000000;stop-opacity:1"
+     offset="0" /><stop
+     id="stop3591-7-4-20"
+     style="stop-color:#363636;stop-opacity:1"
+     offset="1" /></linearGradient><filter
+   inkscape:collect="always"
+   id="filter4274"
+   x="-0.075768784"
+   width="1.1515376"
+   y="-0.14014855"
+   height="1.2802971"><feGaussianBlur
+     inkscape:collect="always"
+     stdDeviation="0.94710989"
+     id="feGaussianBlur4276" /></filter></defs><sodipodi:namedview
+   pagecolor="#ffffff"
+   bordercolor="#666666"
+   borderopacity="1"
+   objecttolerance="10"
+   gridtolerance="10"
+   guidetolerance="10"
+   inkscape:pageopacity="0"
+   inkscape:pageshadow="2"
+   inkscape:window-width="1280"
+   inkscape:window-height="774"
+   id="namedview323"
+   showgrid="false"
+   inkscape:zoom="8"
+   inkscape:cx="-8.6923201"
+   inkscape:cy="19.488907"
+   inkscape:window-x="0"
+   inkscape:window-y="26"
+   inkscape:window-maximized="1"
+   inkscape:current-layer="Layer_1"
+   units="px"
+   fit-margin-top="0"
+   fit-margin-left="0"
+   fit-margin-right="0"
+   fit-margin-bottom="0"
+   showguides="true"
+   inkscape:guide-bbox="true" />
+<pattern
+   y="565.223"
+   width="69"
+   height="69"
+   patternUnits="userSpaceOnUse"
+   id="Polka_Dot_Pattern"
+   viewBox="2.125 -70.896 69 69"
+   overflow="visible">
+	<g
+   id="g4">
+		<polygon
+   fill="none"
+   points="71.125,-1.896 2.125,-1.896 2.125,-70.896 71.125,-70.896   "
+   id="polygon6" />
+		<polygon
+   fill="#F6BB60"
+   points="71.125,-1.896 2.125,-1.896 2.125,-70.896 71.125,-70.896   "
+   id="polygon8" />
+		<g
+   id="g10">
+			<path
+   fill="#FFFFFF"
+   d="M61.772-71.653c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128     c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161     c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631     c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45     c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221     c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337     c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207     c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169     c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path12" />
+			<path
+   fill="#FFFFFF"
+   d="M54.105-71.653c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128     c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161     c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631     c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45     c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221     c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337     c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207     c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169     c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path14" />
+			<path
+   fill="#FFFFFF"
+   d="M46.439-71.653c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128     c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161     c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631     c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45     c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221     c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337     c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207     c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169     c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path16" />
+			<path
+   fill="#FFFFFF"
+   d="M38.772-71.653c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128     c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161     c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631     c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45     c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221     c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337     c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207     c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169     c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path18" />
+			<path
+   fill="#FFFFFF"
+   d="M31.105-71.653c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128     c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161     c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631     c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45     c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221     c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337     c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207     c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169     c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path20" />
+			<path
+   fill="#FFFFFF"
+   d="M23.439-71.653c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128     c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161     c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631     c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45     c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221     c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337     c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207     c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169     c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path22" />
+			<path
+   fill="#FFFFFF"
+   d="M15.772-71.653c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128     c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161     c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631     c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45     c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221     c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337     c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207     c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169     c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path24" />
+			<path
+   fill="#FFFFFF"
+   d="M8.105-71.653c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128     c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161     c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631     c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45     c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221     c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337     c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207     c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169     c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path26" />
+			<path
+   fill="#FFFFFF"
+   d="M0.439-71.653c0.018,0.072,0.008,0.127-0.026,0.19C0.361-71.362,0.3-71.4,0.248-71.335     c-0.051,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161     c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631     c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45     c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.07,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221     c0.038-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.051-0.12-0.064-0.187c-0.021-0.114,0.002-0.224,0-0.337     c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207     c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.215,0.124-0.215,0.224c0.002,0.115,0.005,0.051,0.012,0.169     c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path28" />
+		</g>
+		<g
+   id="g30">
+			<path
+   fill="#FFFFFF"
+   d="M69.439-71.653c0.018,0.072,0.008,0.127-0.026,0.19c-0.052,0.101-0.113,0.062-0.165,0.128     c-0.051,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161     c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631     c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45     c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.07,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221     c0.038-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.051-0.12-0.064-0.187c-0.021-0.114,0.002-0.224,0-0.337     c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207     c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.215,0.124-0.215,0.224c0.002,0.115,0.005,0.051,0.012,0.169     c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path32" />
+		</g>
+		<path
+   fill="#FFFFFF"
+   d="M0.495-71.653c0.018,0.072,0.008,0.127-0.026,0.19c-0.052,0.101-0.113,0.062-0.165,0.128    c-0.051,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161    c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631    c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45    c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.07,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221    c0.038-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.051-0.12-0.064-0.187c-0.021-0.114,0.002-0.224,0-0.337    c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207    c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.215,0.124-0.215,0.224C0.5-71.68,0.503-71.744,0.51-71.626    c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path34" />
+		<g
+   id="g36">
+			<g
+   id="g38">
+				<path
+   fill="#FFFFFF"
+   d="M69.439-64.001c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path40" />
+				<path
+   fill="#FFFFFF"
+   d="M61.778-64.001c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path42" />
+				<path
+   fill="#FFFFFF"
+   d="M54.118-64.001c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path44" />
+				<path
+   fill="#FFFFFF"
+   d="M46.458-64.001c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path46" />
+				<path
+   fill="#FFFFFF"
+   d="M38.797-64.001c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path48" />
+				<path
+   fill="#FFFFFF"
+   d="M31.137-64.001c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path50" />
+				<path
+   fill="#FFFFFF"
+   d="M23.477-64.001c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path52" />
+				<path
+   fill="#FFFFFF"
+   d="M15.816-64.001c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path54" />
+				<path
+   fill="#FFFFFF"
+   d="M8.156-64.001c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path56" />
+				<path
+   fill="#FFFFFF"
+   d="M0.495-64.001c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143C2-61.45,2.217-61.397,2.391-61.46c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path58" />
+			</g>
+			<g
+   id="g60">
+				<path
+   fill="#FFFFFF"
+   d="M69.439-56.348c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path62" />
+				<path
+   fill="#FFFFFF"
+   d="M61.778-56.348c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path64" />
+				<path
+   fill="#FFFFFF"
+   d="M54.118-56.348c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path66" />
+				<path
+   fill="#FFFFFF"
+   d="M46.458-56.348c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path68" />
+				<path
+   fill="#FFFFFF"
+   d="M38.797-56.348c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path70" />
+				<path
+   fill="#FFFFFF"
+   d="M31.137-56.348c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path72" />
+				<path
+   fill="#FFFFFF"
+   d="M23.477-56.348c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path74" />
+				<path
+   fill="#FFFFFF"
+   d="M15.816-56.348c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path76" />
+				<path
+   fill="#FFFFFF"
+   d="M8.156-56.348c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path78" />
+				<path
+   fill="#FFFFFF"
+   d="M0.495-56.348c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224C0.5-56.374,0.503-56.438,0.51-56.32      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path80" />
+			</g>
+			<g
+   id="g82">
+				<path
+   fill="#FFFFFF"
+   d="M69.439-48.695c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path84" />
+				<path
+   fill="#FFFFFF"
+   d="M61.778-48.695c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path86" />
+				<path
+   fill="#FFFFFF"
+   d="M54.118-48.695c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path88" />
+				<path
+   fill="#FFFFFF"
+   d="M46.458-48.695c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path90" />
+				<path
+   fill="#FFFFFF"
+   d="M38.797-48.695c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path92" />
+				<path
+   fill="#FFFFFF"
+   d="M31.137-48.695c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path94" />
+				<path
+   fill="#FFFFFF"
+   d="M23.477-48.695c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path96" />
+				<path
+   fill="#FFFFFF"
+   d="M15.816-48.695c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path98" />
+				<path
+   fill="#FFFFFF"
+   d="M8.156-48.695c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path100" />
+				<path
+   fill="#FFFFFF"
+   d="M0.495-48.695c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path102" />
+			</g>
+			<g
+   id="g104">
+				<path
+   fill="#FFFFFF"
+   d="M69.439-41.042c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path106" />
+				<path
+   fill="#FFFFFF"
+   d="M61.778-41.042c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path108" />
+				<path
+   fill="#FFFFFF"
+   d="M54.118-41.042c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path110" />
+				<path
+   fill="#FFFFFF"
+   d="M46.458-41.042c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path112" />
+				<path
+   fill="#FFFFFF"
+   d="M38.797-41.042c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path114" />
+				<path
+   fill="#FFFFFF"
+   d="M31.137-41.042c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path116" />
+				<path
+   fill="#FFFFFF"
+   d="M23.477-41.042c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path118" />
+				<path
+   fill="#FFFFFF"
+   d="M15.816-41.042c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path120" />
+				<path
+   fill="#FFFFFF"
+   d="M8.156-41.042c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      C8.15-41.004,8.149-41.02,8.14-41.04"
+   id="path122" />
+				<path
+   fill="#FFFFFF"
+   d="M0.495-41.042c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path124" />
+			</g>
+			<g
+   id="g126">
+				<path
+   fill="#FFFFFF"
+   d="M69.439-33.39c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path128" />
+				<path
+   fill="#FFFFFF"
+   d="M61.778-33.39c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path130" />
+				<path
+   fill="#FFFFFF"
+   d="M54.118-33.39c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path132" />
+				<path
+   fill="#FFFFFF"
+   d="M46.458-33.39c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path134" />
+				<path
+   fill="#FFFFFF"
+   d="M38.797-33.39c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path136" />
+				<path
+   fill="#FFFFFF"
+   d="M31.137-33.39c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path138" />
+				<path
+   fill="#FFFFFF"
+   d="M23.477-33.39c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path140" />
+				<path
+   fill="#FFFFFF"
+   d="M15.816-33.39c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path142" />
+				<path
+   fill="#FFFFFF"
+   d="M8.156-33.39c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path144" />
+				<path
+   fill="#FFFFFF"
+   d="M0.495-33.39c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224C0.5-33.416,0.503-33.48,0.51-33.362      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path146" />
+			</g>
+			<g
+   id="g148">
+				<path
+   fill="#FFFFFF"
+   d="M69.439-25.736c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path150" />
+				<path
+   fill="#FFFFFF"
+   d="M61.778-25.736c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path152" />
+				<path
+   fill="#FFFFFF"
+   d="M54.118-25.736c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path154" />
+				<path
+   fill="#FFFFFF"
+   d="M46.458-25.736c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path156" />
+				<path
+   fill="#FFFFFF"
+   d="M38.797-25.736c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path158" />
+				<path
+   fill="#FFFFFF"
+   d="M31.137-25.736c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path160" />
+				<path
+   fill="#FFFFFF"
+   d="M23.477-25.736c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path162" />
+				<path
+   fill="#FFFFFF"
+   d="M15.816-25.736c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path164" />
+				<path
+   fill="#FFFFFF"
+   d="M8.156-25.736c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path166" />
+				<path
+   fill="#FFFFFF"
+   d="M0.495-25.736c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path168" />
+			</g>
+			<g
+   id="g170">
+				<path
+   fill="#FFFFFF"
+   d="M69.439-18.084c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path172" />
+				<path
+   fill="#FFFFFF"
+   d="M61.778-18.084c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path174" />
+				<path
+   fill="#FFFFFF"
+   d="M54.118-18.084c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path176" />
+				<path
+   fill="#FFFFFF"
+   d="M46.458-18.084c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path178" />
+				<path
+   fill="#FFFFFF"
+   d="M38.797-18.084c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path180" />
+				<path
+   fill="#FFFFFF"
+   d="M31.137-18.084c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path182" />
+				<path
+   fill="#FFFFFF"
+   d="M23.477-18.084c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path184" />
+				<path
+   fill="#FFFFFF"
+   d="M15.816-18.084c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path186" />
+				<path
+   fill="#FFFFFF"
+   d="M8.156-18.084c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path188" />
+				<path
+   fill="#FFFFFF"
+   d="M0.495-18.084c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224C0.5-18.11,0.503-18.175,0.51-18.057      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path190" />
+			</g>
+			<g
+   id="g192">
+				<path
+   fill="#FFFFFF"
+   d="M69.439-10.431c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362C69-9.692,69.159-9.523,69.154-9.4c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path194" />
+				<path
+   fill="#FFFFFF"
+   d="M61.778-10.431c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path196" />
+				<path
+   fill="#FFFFFF"
+   d="M54.118-10.431c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path198" />
+				<path
+   fill="#FFFFFF"
+   d="M46.458-10.431c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path200" />
+				<path
+   fill="#FFFFFF"
+   d="M38.797-10.431c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path202" />
+				<path
+   fill="#FFFFFF"
+   d="M31.137-10.431c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path204" />
+				<path
+   fill="#FFFFFF"
+   d="M23.477-10.431c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path206" />
+				<path
+   fill="#FFFFFF"
+   d="M15.816-10.431c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053C17.933-7.969,17.839-8.227,18-8.34      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path208" />
+				<path
+   fill="#FFFFFF"
+   d="M8.156-10.431c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      C7.915-10.05,7.866-9.836,7.886-9.75C7.717-9.692,7.876-9.523,7.871-9.4C7.868-9.351,7.83-9.295,7.826-9.239      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      C9.114-7.652,9.321-7.799,9.48-7.837c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path210" />
+				<path
+   fill="#FFFFFF"
+   d="M0.495-10.431c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      C0.254-10.05,0.205-9.836,0.225-9.75C0.056-9.692,0.215-9.523,0.21-9.4c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37C0.33-8.671,0.501-8.456,0.668-8.325c0.19,0.148,0.365,0.572,0.608,0.631      C1.454-7.652,1.66-7.799,1.819-7.837C2-7.88,2.217-7.827,2.391-7.89c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46C3.477-8.933,3.471-8.995,3.5-9.071      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path212" />
+			</g>
+		</g>
+		<g
+   id="g214">
+			<path
+   fill="#FFFFFF"
+   d="M69.439-2.778c0.018,0.072,0.008,0.127-0.026,0.19C69.361-2.487,69.3-2.525,69.248-2.46     c-0.051,0.062-0.099,0.276-0.079,0.362C69-2.04,69.159-1.871,69.154-1.748c-0.002,0.05-0.041,0.105-0.045,0.161     c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631     C70.397,0,70.604-0.146,70.763-0.185c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45     c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.07,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221     c0.038-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.051-0.12-0.064-0.187c-0.021-0.114,0.002-0.224,0-0.337     c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207     c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.215,0.124-0.215,0.224c0.002,0.115,0.005,0.051,0.012,0.169     c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path216" />
+			<path
+   fill="#FFFFFF"
+   d="M61.778-2.778c0.018,0.072,0.007,0.127-0.026,0.19C61.7-2.487,61.64-2.525,61.587-2.46     c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161     c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631     C62.737,0,62.943-0.146,63.103-0.185c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45     c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221     c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337     c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207     c-0.17,0.088-0.139,0.166-0.318,0.224C61.915-3.117,61.78-3.02,61.781-2.92c0.001,0.115,0.005,0.051,0.012,0.169     c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path218" />
+			<path
+   fill="#FFFFFF"
+   d="M54.118-2.778c0.018,0.072,0.007,0.127-0.026,0.19C54.04-2.487,53.98-2.525,53.927-2.46     c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161     c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631     C55.077,0,55.283-0.146,55.442-0.185c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45     c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221     c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337     c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207     c-0.17,0.088-0.139,0.166-0.318,0.224C54.255-3.117,54.12-3.02,54.121-2.92c0.001,0.115,0.005,0.051,0.012,0.169     c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path220" />
+			<path
+   fill="#FFFFFF"
+   d="M46.458-2.778c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128     c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161     c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631     C47.416,0,47.623-0.146,47.782-0.185c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45     c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221     c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337     c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207     c-0.17,0.088-0.139,0.166-0.318,0.224C46.594-3.117,46.459-3.02,46.46-2.92c0.001,0.115,0.005,0.051,0.012,0.169     c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path222" />
+			<path
+   fill="#FFFFFF"
+   d="M38.797-2.778c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128     c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161     c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631     C39.756,0,39.962-0.146,40.122-0.185c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45     c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221     c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337     c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207     c-0.17,0.088-0.139,0.166-0.318,0.224C38.934-3.117,38.799-3.02,38.8-2.92c0.001,0.115,0.005,0.051,0.012,0.169     c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path224" />
+			<path
+   fill="#FFFFFF"
+   d="M31.137-2.778c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128     c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161     c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631     C32.095,0,32.302-0.146,32.461-0.185c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45     c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221     c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337     c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207     c-0.17,0.088-0.139,0.166-0.318,0.224C31.273-3.117,31.139-3.02,31.14-2.92c0.001,0.115,0.005,0.051,0.012,0.169     c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path226" />
+			<path
+   fill="#FFFFFF"
+   d="M23.477-2.778c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128     c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161     c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631     C24.435,0,24.642-0.146,24.801-0.185c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45     c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221     c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337     c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207     c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169     c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path228" />
+			<path
+   fill="#FFFFFF"
+   d="M15.816-2.778c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128     c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161     c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631     C16.774,0,16.981-0.146,17.14-0.185c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45     c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221     c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337     c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207     c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169     C15.81-2.74,15.809-2.756,15.8-2.776"
+   id="path230" />
+			<path
+   fill="#FFFFFF"
+   d="M8.156-2.778c0.018,0.072,0.007,0.127-0.026,0.19C8.077-2.487,8.018-2.525,7.965-2.46     c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35C7.868-1.698,7.83-1.643,7.826-1.587     c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631     C9.114,0,9.321-0.146,9.48-0.185c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45     c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221     c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337     c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789C8.954-3.54,8.847-3.448,8.692-3.367     c-0.17,0.088-0.139,0.166-0.318,0.224C8.292-3.117,8.158-3.02,8.159-2.92C8.16-2.805,8.164-2.869,8.17-2.751     C8.15-2.74,8.149-2.756,8.14-2.776"
+   id="path232" />
+			<path
+   fill="#FFFFFF"
+   d="M0.495-2.778c0.018,0.072,0.008,0.127-0.026,0.19C0.417-2.487,0.356-2.525,0.304-2.46     C0.253-2.397,0.205-2.184,0.225-2.098C0.056-2.04,0.215-1.871,0.21-1.748c-0.002,0.05-0.041,0.105-0.045,0.161     c-0.01,0.119,0.017,0.266,0.068,0.37C0.33-1.019,0.501-0.804,0.668-0.673c0.19,0.148,0.365,0.572,0.608,0.631     C1.454,0,1.66-0.146,1.819-0.185C2-0.228,2.217-0.175,2.391-0.237c0.222-0.079,0.127-0.337,0.288-0.45     c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.07,0.339-0.263,0.376-0.46C3.477-1.28,3.471-1.343,3.5-1.419     c0.038-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.051-0.12-0.064-0.187c-0.021-0.114,0.002-0.224,0-0.337     c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789C1.293-3.54,1.187-3.448,1.031-3.367     c-0.17,0.088-0.139,0.166-0.318,0.224C0.632-3.117,0.498-3.02,0.498-2.92C0.5-2.805,0.503-2.869,0.51-2.751     C0.489-2.74,0.488-2.756,0.479-2.776"
+   id="path234" />
+		</g>
+	</g>
+</pattern>
+
+<rect
+   style="fill:#1d2d44;fill-opacity:1"
+   id="rect7667"
+   width="32"
+   height="32"
+   x="0"
+   y="-5.2587893e-06"
+   rx="5"
+   ry="5" /><path
+   style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;baseline-shift:baseline;color:#000000;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:4;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Sans;-inkscape-font-specification:Sans"
+   d="m 14.58312,7.280992 c -2.232936,0 -4.036942,1.80401 -4.036942,4.03694 0,0.92043 0.306488,1.76756 0.823221,2.44591 1.120977,-1.29745 2.775437,-2.12137 4.622692,-2.12137 0.903762,0 1.760771,0.20125 2.532985,0.55409 0.06252,-0.28275 0.09499,-0.57681 0.09499,-0.87863 0,-2.23293 -1.804003,-4.03694 -4.036941,-4.03694 z m -5.27177,1.86808 c -1.162852,0 -2.097627,0.94269 -2.097627,2.10554 0,0.3765 0.09713,0.73224 0.269128,1.03694 0.70171,-0.39584 1.512966,-0.62533 2.374672,-0.62533 0.08316,0 0.163259,0.003 0.245384,0.008 -0.0093,-0.11788 -0.01582,-0.23595 -0.01582,-0.3562 0,-0.64768 0.140672,-1.26392 0.387863,-1.82058 -0.33282,-0.22318 -0.731572,-0.34828 -1.163589,-0.34828 z m 9.95779,1.44855 c -0.08591,0 -0.168718,0.0105 -0.253299,0.0158 0.03659,0.23068 0.06332,0.46361 0.06332,0.70449 0,0.37486 -0.04767,0.73658 -0.134564,1.08443 1.018734,0.56378 1.864755,1.40734 2.422165,2.43008 0.578161,-0.301 1.223119,-0.49238 1.907654,-0.53826 -0.176419,-2.06894 -1.890444,-3.69657 -4.00528,-3.69657 z m -3.277049,1.50396 c -3.124547,0 -5.651718,2.52695 -5.651718,5.65171 0,3.12442 2.527042,5.65172 5.651718,5.65172 3.124679,0 5.65172,-2.5273 5.65172,-5.65172 0,-3.12475 -2.52717,-5.65171 -5.65172,-5.65171 z m -6.134568,0.0237 c -2.424056,0 -4.385225,1.96117 -4.385225,4.38523 0,1.42699 0.679906,2.69025 1.73351,3.49076 0.444179,-0.85669 1.33629,-1.44063 2.366755,-1.44063 0.124542,0 0.244083,0.0151 0.364116,0.0317 -0.03768,-0.27414 -0.05541,-0.55461 -0.05541,-0.83905 0,-1.35993 0.442668,-2.61752 1.195249,-3.63324 -0.450488,-0.56371 -0.772875,-1.24102 -0.910292,-1.9789 -0.101843,-0.007 -0.205054,-0.0158 -0.308706,-0.0158 z m 13.741433,2.61214 c -0.736055,0 -1.425548,0.18792 -2.034303,0.5066 0.345671,0.76568 0.538259,1.61522 0.538259,2.50923 0,1.67396 -0.673022,3.19393 -1.765172,4.29815 0.802331,0.89076 1.966418,1.44855 3.261216,1.44855 2.424057,0 4.385229,-1.96116 4.385229,-4.38522 0,-2.42406 -1.961172,-4.37731 -4.385229,-4.37731 z m -18.5541,0.57788 C 2.811855,15.315302 1,17.111322 1,19.344322 c 0,2.233 1.811855,4.04486 4.044856,4.04486 0.849912,0 1.637225,-0.2648 2.287602,-0.7124 -0.268749,-0.41761 -0.427442,-0.91688 -0.427442,-1.44855 0,-0.27596 0.04072,-0.54107 0.118732,-0.79156 -1.217569,-0.87992 -2.010555,-2.31182 -2.010555,-3.92612 0,-0.41016 0.05405,-0.80676 0.150398,-1.18734 -0.03999,-10e-4 -0.07845,-0.008 -0.118735,-0.008 z m 23.738799,3.46702 c -0.119122,0 -0.23439,0.0136 -0.348285,0.0317 0.0063,0.10069 0.0079,0.19852 0.0079,0.30079 0,1.28753 -0.508015,2.45614 -1.329815,3.32454 0.404298,0.47015 0.998155,0.76781 1.670188,0.76781 1.224112,0 2.21636,-0.98433 2.21636,-2.20845 0,-1.22411 -0.992248,-2.21635 -2.21636,-2.21635 z m -19.211092,0.23746 c -1.22405,0 -2.208444,0.9844 -2.208444,2.20845 0,1.22404 0.984394,2.21636 2.208444,2.21636 0.93825,0 1.73464,-0.58546 2.05805,-1.40898 -0.789132,-0.80372 -1.35627,-1.82906 -1.606861,-2.96833 -0.146642,-0.0303 -0.295484,-0.0475 -0.451189,-0.0475 z"
+   id="circle238"
+   inkscape:export-filename="/home/user/owncloud/core/img/logo.png"
+   inkscape:export-xdpi="90"
+   inkscape:export-ydpi="90"
+   inkscape:connector-curvature="0"
+   sodipodi:nodetypes="sscscsscscscscccscscccsssssssscscsccsscscssscsscscsccccscssccsssccs" />
+
+
+
+
+
+
+
+
+
+
+</svg>
\ No newline at end of file
diff --git a/core/img/icon-error.png b/core/img/icon-error.png
new file mode 100644
index 0000000000000000000000000000000000000000..ed438a32fd8844543f76e1f10180aaef6f257bbf
Binary files /dev/null and b/core/img/icon-error.png differ
diff --git a/core/img/icon-error.svg b/core/img/icon-error.svg
new file mode 100644
index 0000000000000000000000000000000000000000..6392d819ad8371007b638beabb49643ecf127c82
--- /dev/null
+++ b/core/img/icon-error.svg
@@ -0,0 +1,813 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Generator: Adobe Illustrator 13.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 14948)  -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:xlink="http://www.w3.org/1999/xlink"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   version="1.1"
+   id="Layer_1"
+   x="0px"
+   y="0px"
+   width="32"
+   height="32"
+   viewBox="0 0 32 31.999997"
+   enable-background="new 0 0 595.275 311.111"
+   xml:space="preserve"
+   inkscape:version="0.48.2 r9819"
+   sodipodi:docname="icon-error.svg"
+   inkscape:export-filename="/home/user/owncloud/core/img/icon-error.png"
+   inkscape:export-xdpi="89.826416"
+   inkscape:export-ydpi="89.826416"><metadata
+   id="metadata327"><rdf:RDF><cc:Work
+       rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
+         rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
+   id="defs325"><linearGradient
+   inkscape:collect="always"
+   xlink:href="#SVGID_1_"
+   id="linearGradient3353"
+   gradientUnits="userSpaceOnUse"
+   x1="288.49411"
+   y1="55.888199"
+   x2="288.49411"
+   y2="339.22189" /><linearGradient
+   inkscape:collect="always"
+   xlink:href="#SVGID_2_"
+   id="linearGradient3355"
+   gradientUnits="userSpaceOnUse"
+   x1="251.2114"
+   y1="55.888199"
+   x2="251.2114"
+   y2="339.22159" /><linearGradient
+   inkscape:collect="always"
+   xlink:href="#SVGID_3_"
+   id="linearGradient3357"
+   gradientUnits="userSpaceOnUse"
+   x1="293.22461"
+   y1="55.888199"
+   x2="293.22461"
+   y2="339.22171" /><linearGradient
+   inkscape:collect="always"
+   xlink:href="#SVGID_4_"
+   id="linearGradient3359"
+   gradientUnits="userSpaceOnUse"
+   x1="375.33401"
+   y1="55.888199"
+   x2="375.33401"
+   y2="339.22159" /><linearGradient
+   inkscape:collect="always"
+   xlink:href="#SVGID_5_"
+   id="linearGradient3361"
+   gradientUnits="userSpaceOnUse"
+   x1="334.49411"
+   y1="55.888199"
+   x2="334.49411"
+   y2="339.22159" /><linearGradient
+   inkscape:collect="always"
+   xlink:href="#SVGID_6_"
+   id="linearGradient3363"
+   gradientUnits="userSpaceOnUse"
+   x1="458.42679"
+   y1="55.8867"
+   x2="458.42679"
+   y2="339.2236" /><linearGradient
+   inkscape:collect="always"
+   xlink:href="#SVGID_7_"
+   id="linearGradient3365"
+   gradientUnits="userSpaceOnUse"
+   x1="413.16309"
+   y1="55.888199"
+   x2="413.16309"
+   y2="339.22131" /><linearGradient
+   inkscape:collect="always"
+   xlink:href="#SVGID_8_"
+   id="linearGradient3367"
+   gradientUnits="userSpaceOnUse"
+   x1="290.76169"
+   y1="55.8867"
+   x2="290.76169"
+   y2="339.2236" /><linearGradient
+   inkscape:collect="always"
+   xlink:href="#SVGID_9_"
+   id="linearGradient3369"
+   gradientUnits="userSpaceOnUse"
+   x1="346.77341"
+   y1="55.888199"
+   x2="346.77341"
+   y2="339.22119" />
+	<linearGradient
+   y2="339.22189"
+   x2="288.49411"
+   y1="55.888199"
+   x1="288.49411"
+   gradientUnits="userSpaceOnUse"
+   id="SVGID_1_">
+		<stop
+   id="stop261"
+   style="stop-color:#BED5E1"
+   offset="0" />
+		<stop
+   id="stop263"
+   style="stop-color:#567B8F"
+   offset="1" />
+	</linearGradient>
+	
+	<linearGradient
+   y2="339.22159"
+   x2="251.2114"
+   y1="55.888199"
+   x1="251.2114"
+   gradientUnits="userSpaceOnUse"
+   id="SVGID_2_">
+		<stop
+   id="stop268"
+   style="stop-color:#BED5E1"
+   offset="0" />
+		<stop
+   id="stop270"
+   style="stop-color:#567B8F"
+   offset="1" />
+	</linearGradient>
+	
+	<linearGradient
+   y2="339.22171"
+   x2="293.22461"
+   y1="55.888199"
+   x1="293.22461"
+   gradientUnits="userSpaceOnUse"
+   id="SVGID_3_">
+		<stop
+   id="stop275"
+   style="stop-color:#BED5E1"
+   offset="0" />
+		<stop
+   id="stop277"
+   style="stop-color:#567B8F"
+   offset="1" />
+	</linearGradient>
+	
+	<linearGradient
+   y2="339.22159"
+   x2="375.33401"
+   y1="55.888199"
+   x1="375.33401"
+   gradientUnits="userSpaceOnUse"
+   id="SVGID_4_">
+		<stop
+   id="stop282"
+   style="stop-color:#BED5E1"
+   offset="0" />
+		<stop
+   id="stop284"
+   style="stop-color:#567B8F"
+   offset="1" />
+	</linearGradient>
+	
+	<linearGradient
+   y2="339.22159"
+   x2="334.49411"
+   y1="55.888199"
+   x1="334.49411"
+   gradientUnits="userSpaceOnUse"
+   id="SVGID_5_">
+		<stop
+   id="stop289"
+   style="stop-color:#BED5E1"
+   offset="0" />
+		<stop
+   id="stop291"
+   style="stop-color:#567B8F"
+   offset="1" />
+	</linearGradient>
+	
+	<linearGradient
+   y2="339.2236"
+   x2="458.42679"
+   y1="55.8867"
+   x1="458.42679"
+   gradientUnits="userSpaceOnUse"
+   id="SVGID_6_">
+		<stop
+   id="stop296"
+   style="stop-color:#BED5E1"
+   offset="0" />
+		<stop
+   id="stop298"
+   style="stop-color:#567B8F"
+   offset="1" />
+	</linearGradient>
+	
+	<linearGradient
+   y2="339.22131"
+   x2="413.16309"
+   y1="55.888199"
+   x1="413.16309"
+   gradientUnits="userSpaceOnUse"
+   id="SVGID_7_">
+		<stop
+   id="stop303"
+   style="stop-color:#BED5E1"
+   offset="0" />
+		<stop
+   id="stop305"
+   style="stop-color:#567B8F"
+   offset="1" />
+	</linearGradient>
+	
+	<linearGradient
+   y2="339.2236"
+   x2="290.76169"
+   y1="55.8867"
+   x1="290.76169"
+   gradientUnits="userSpaceOnUse"
+   id="SVGID_8_">
+		<stop
+   id="stop310"
+   style="stop-color:#BED5E1"
+   offset="0" />
+		<stop
+   id="stop312"
+   style="stop-color:#567B8F"
+   offset="1" />
+	</linearGradient>
+	
+	<linearGradient
+   y2="339.22119"
+   x2="346.77341"
+   y1="55.888199"
+   x1="346.77341"
+   gradientUnits="userSpaceOnUse"
+   id="SVGID_9_">
+		<stop
+   id="stop317"
+   style="stop-color:#BED5E1"
+   offset="0" />
+		<stop
+   id="stop319"
+   style="stop-color:#567B8F"
+   offset="1" />
+	</linearGradient>
+	
+<linearGradient
+   y2="18.967093"
+   x2="-2.4040222"
+   y1="4.4573336"
+   x1="-2.4040222"
+   gradientTransform="translate(13.927091,16.573387)"
+   gradientUnits="userSpaceOnUse"
+   id="linearGradient3475"
+   xlink:href="#linearGradient3587-6-5-26"
+   inkscape:collect="always" /><linearGradient
+   id="linearGradient3587-6-5-26"><stop
+     id="stop3589-9-2-45"
+     style="stop-color:#b20000;stop-opacity:1;"
+     offset="0" /><stop
+     id="stop3591-7-4-20"
+     style="stop-color:#b23636;stop-opacity:1;"
+     offset="1" /></linearGradient><linearGradient
+   y2="18.967093"
+   x2="-2.4040222"
+   y1="4.4573336"
+   x1="-2.4040222"
+   gradientTransform="translate(13.927091,16.573387)"
+   gradientUnits="userSpaceOnUse"
+   id="linearGradient7590"
+   xlink:href="#linearGradient3587-6-5-26"
+   inkscape:collect="always" /><linearGradient
+   inkscape:collect="always"
+   xlink:href="#linearGradient3587-6-5-26"
+   id="linearGradient7614"
+   gradientUnits="userSpaceOnUse"
+   gradientTransform="translate(15.071012,45.700897)"
+   x1="-2.4040222"
+   y1="4.4573336"
+   x2="-2.4040222"
+   y2="18.967093" /><linearGradient
+   inkscape:collect="always"
+   xlink:href="#linearGradient3587-6-5-26"
+   id="linearGradient3956"
+   gradientUnits="userSpaceOnUse"
+   gradientTransform="matrix(0.25,0,0,0.25,0,0.500024)"
+   x1="58.866638"
+   y1="24.928007"
+   x2="58.866638"
+   y2="93.882034" /></defs><sodipodi:namedview
+   pagecolor="#ffffff"
+   bordercolor="#666666"
+   borderopacity="1"
+   objecttolerance="10"
+   gridtolerance="10"
+   guidetolerance="10"
+   inkscape:pageopacity="0"
+   inkscape:pageshadow="2"
+   inkscape:window-width="1280"
+   inkscape:window-height="774"
+   id="namedview323"
+   showgrid="true"
+   inkscape:zoom="2.8284271"
+   inkscape:cx="-37.832842"
+   inkscape:cy="0.28559212"
+   inkscape:window-x="0"
+   inkscape:window-y="26"
+   inkscape:window-maximized="1"
+   inkscape:current-layer="Layer_1"
+   units="px"
+   fit-margin-top="0"
+   fit-margin-left="0"
+   fit-margin-right="0"
+   fit-margin-bottom="0"
+   showguides="true"
+   inkscape:guide-bbox="true"><inkscape:grid
+     type="xygrid"
+     id="grid3152"
+     empspacing="2"
+     visible="true"
+     enabled="true"
+     snapvisiblegridlinesonly="true"
+     dotted="false" /></sodipodi:namedview>
+<pattern
+   y="565.223"
+   width="69"
+   height="69"
+   patternUnits="userSpaceOnUse"
+   id="Polka_Dot_Pattern"
+   viewBox="2.125 -70.896 69 69"
+   overflow="visible">
+	<g
+   id="g4">
+		<polygon
+   fill="none"
+   points="71.125,-1.896 2.125,-1.896 2.125,-70.896 71.125,-70.896   "
+   id="polygon6" />
+		<polygon
+   fill="#F6BB60"
+   points="71.125,-1.896 2.125,-1.896 2.125,-70.896 71.125,-70.896   "
+   id="polygon8" />
+		<g
+   id="g10">
+			<path
+   fill="#FFFFFF"
+   d="M61.772-71.653c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128     c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161     c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631     c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45     c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221     c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337     c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207     c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169     c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path12" />
+			<path
+   fill="#FFFFFF"
+   d="M54.105-71.653c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128     c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161     c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631     c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45     c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221     c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337     c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207     c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169     c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path14" />
+			<path
+   fill="#FFFFFF"
+   d="M46.439-71.653c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128     c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161     c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631     c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45     c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221     c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337     c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207     c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169     c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path16" />
+			<path
+   fill="#FFFFFF"
+   d="M38.772-71.653c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128     c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161     c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631     c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45     c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221     c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337     c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207     c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169     c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path18" />
+			<path
+   fill="#FFFFFF"
+   d="M31.105-71.653c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128     c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161     c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631     c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45     c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221     c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337     c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207     c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169     c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path20" />
+			<path
+   fill="#FFFFFF"
+   d="M23.439-71.653c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128     c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161     c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631     c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45     c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221     c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337     c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207     c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169     c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path22" />
+			<path
+   fill="#FFFFFF"
+   d="M15.772-71.653c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128     c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161     c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631     c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45     c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221     c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337     c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207     c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169     c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path24" />
+			<path
+   fill="#FFFFFF"
+   d="M8.105-71.653c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128     c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161     c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631     c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45     c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221     c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337     c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207     c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169     c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path26" />
+			<path
+   fill="#FFFFFF"
+   d="M0.439-71.653c0.018,0.072,0.008,0.127-0.026,0.19C0.361-71.362,0.3-71.4,0.248-71.335     c-0.051,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161     c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631     c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45     c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.07,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221     c0.038-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.051-0.12-0.064-0.187c-0.021-0.114,0.002-0.224,0-0.337     c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207     c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.215,0.124-0.215,0.224c0.002,0.115,0.005,0.051,0.012,0.169     c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path28" />
+		</g>
+		<g
+   id="g30">
+			<path
+   fill="#FFFFFF"
+   d="M69.439-71.653c0.018,0.072,0.008,0.127-0.026,0.19c-0.052,0.101-0.113,0.062-0.165,0.128     c-0.051,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161     c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631     c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45     c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.07,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221     c0.038-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.051-0.12-0.064-0.187c-0.021-0.114,0.002-0.224,0-0.337     c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207     c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.215,0.124-0.215,0.224c0.002,0.115,0.005,0.051,0.012,0.169     c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path32" />
+		</g>
+		<path
+   fill="#FFFFFF"
+   d="M0.495-71.653c0.018,0.072,0.008,0.127-0.026,0.19c-0.052,0.101-0.113,0.062-0.165,0.128    c-0.051,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161    c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631    c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45    c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.07,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221    c0.038-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.051-0.12-0.064-0.187c-0.021-0.114,0.002-0.224,0-0.337    c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207    c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.215,0.124-0.215,0.224C0.5-71.68,0.503-71.744,0.51-71.626    c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path34" />
+		<g
+   id="g36">
+			<g
+   id="g38">
+				<path
+   fill="#FFFFFF"
+   d="M69.439-64.001c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path40" />
+				<path
+   fill="#FFFFFF"
+   d="M61.778-64.001c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path42" />
+				<path
+   fill="#FFFFFF"
+   d="M54.118-64.001c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path44" />
+				<path
+   fill="#FFFFFF"
+   d="M46.458-64.001c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path46" />
+				<path
+   fill="#FFFFFF"
+   d="M38.797-64.001c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path48" />
+				<path
+   fill="#FFFFFF"
+   d="M31.137-64.001c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path50" />
+				<path
+   fill="#FFFFFF"
+   d="M23.477-64.001c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path52" />
+				<path
+   fill="#FFFFFF"
+   d="M15.816-64.001c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path54" />
+				<path
+   fill="#FFFFFF"
+   d="M8.156-64.001c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path56" />
+				<path
+   fill="#FFFFFF"
+   d="M0.495-64.001c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143C2-61.45,2.217-61.397,2.391-61.46c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path58" />
+			</g>
+			<g
+   id="g60">
+				<path
+   fill="#FFFFFF"
+   d="M69.439-56.348c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path62" />
+				<path
+   fill="#FFFFFF"
+   d="M61.778-56.348c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path64" />
+				<path
+   fill="#FFFFFF"
+   d="M54.118-56.348c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path66" />
+				<path
+   fill="#FFFFFF"
+   d="M46.458-56.348c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path68" />
+				<path
+   fill="#FFFFFF"
+   d="M38.797-56.348c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path70" />
+				<path
+   fill="#FFFFFF"
+   d="M31.137-56.348c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path72" />
+				<path
+   fill="#FFFFFF"
+   d="M23.477-56.348c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path74" />
+				<path
+   fill="#FFFFFF"
+   d="M15.816-56.348c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path76" />
+				<path
+   fill="#FFFFFF"
+   d="M8.156-56.348c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path78" />
+				<path
+   fill="#FFFFFF"
+   d="M0.495-56.348c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224C0.5-56.374,0.503-56.438,0.51-56.32      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path80" />
+			</g>
+			<g
+   id="g82">
+				<path
+   fill="#FFFFFF"
+   d="M69.439-48.695c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path84" />
+				<path
+   fill="#FFFFFF"
+   d="M61.778-48.695c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path86" />
+				<path
+   fill="#FFFFFF"
+   d="M54.118-48.695c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path88" />
+				<path
+   fill="#FFFFFF"
+   d="M46.458-48.695c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path90" />
+				<path
+   fill="#FFFFFF"
+   d="M38.797-48.695c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path92" />
+				<path
+   fill="#FFFFFF"
+   d="M31.137-48.695c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path94" />
+				<path
+   fill="#FFFFFF"
+   d="M23.477-48.695c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path96" />
+				<path
+   fill="#FFFFFF"
+   d="M15.816-48.695c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path98" />
+				<path
+   fill="#FFFFFF"
+   d="M8.156-48.695c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path100" />
+				<path
+   fill="#FFFFFF"
+   d="M0.495-48.695c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path102" />
+			</g>
+			<g
+   id="g104">
+				<path
+   fill="#FFFFFF"
+   d="M69.439-41.042c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path106" />
+				<path
+   fill="#FFFFFF"
+   d="M61.778-41.042c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path108" />
+				<path
+   fill="#FFFFFF"
+   d="M54.118-41.042c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path110" />
+				<path
+   fill="#FFFFFF"
+   d="M46.458-41.042c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path112" />
+				<path
+   fill="#FFFFFF"
+   d="M38.797-41.042c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path114" />
+				<path
+   fill="#FFFFFF"
+   d="M31.137-41.042c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path116" />
+				<path
+   fill="#FFFFFF"
+   d="M23.477-41.042c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path118" />
+				<path
+   fill="#FFFFFF"
+   d="M15.816-41.042c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path120" />
+				<path
+   fill="#FFFFFF"
+   d="M8.156-41.042c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      C8.15-41.004,8.149-41.02,8.14-41.04"
+   id="path122" />
+				<path
+   fill="#FFFFFF"
+   d="M0.495-41.042c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path124" />
+			</g>
+			<g
+   id="g126">
+				<path
+   fill="#FFFFFF"
+   d="M69.439-33.39c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path128" />
+				<path
+   fill="#FFFFFF"
+   d="M61.778-33.39c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path130" />
+				<path
+   fill="#FFFFFF"
+   d="M54.118-33.39c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path132" />
+				<path
+   fill="#FFFFFF"
+   d="M46.458-33.39c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path134" />
+				<path
+   fill="#FFFFFF"
+   d="M38.797-33.39c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path136" />
+				<path
+   fill="#FFFFFF"
+   d="M31.137-33.39c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path138" />
+				<path
+   fill="#FFFFFF"
+   d="M23.477-33.39c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path140" />
+				<path
+   fill="#FFFFFF"
+   d="M15.816-33.39c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path142" />
+				<path
+   fill="#FFFFFF"
+   d="M8.156-33.39c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path144" />
+				<path
+   fill="#FFFFFF"
+   d="M0.495-33.39c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224C0.5-33.416,0.503-33.48,0.51-33.362      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path146" />
+			</g>
+			<g
+   id="g148">
+				<path
+   fill="#FFFFFF"
+   d="M69.439-25.736c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path150" />
+				<path
+   fill="#FFFFFF"
+   d="M61.778-25.736c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path152" />
+				<path
+   fill="#FFFFFF"
+   d="M54.118-25.736c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path154" />
+				<path
+   fill="#FFFFFF"
+   d="M46.458-25.736c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path156" />
+				<path
+   fill="#FFFFFF"
+   d="M38.797-25.736c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path158" />
+				<path
+   fill="#FFFFFF"
+   d="M31.137-25.736c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path160" />
+				<path
+   fill="#FFFFFF"
+   d="M23.477-25.736c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path162" />
+				<path
+   fill="#FFFFFF"
+   d="M15.816-25.736c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path164" />
+				<path
+   fill="#FFFFFF"
+   d="M8.156-25.736c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path166" />
+				<path
+   fill="#FFFFFF"
+   d="M0.495-25.736c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path168" />
+			</g>
+			<g
+   id="g170">
+				<path
+   fill="#FFFFFF"
+   d="M69.439-18.084c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path172" />
+				<path
+   fill="#FFFFFF"
+   d="M61.778-18.084c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path174" />
+				<path
+   fill="#FFFFFF"
+   d="M54.118-18.084c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path176" />
+				<path
+   fill="#FFFFFF"
+   d="M46.458-18.084c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path178" />
+				<path
+   fill="#FFFFFF"
+   d="M38.797-18.084c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path180" />
+				<path
+   fill="#FFFFFF"
+   d="M31.137-18.084c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path182" />
+				<path
+   fill="#FFFFFF"
+   d="M23.477-18.084c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path184" />
+				<path
+   fill="#FFFFFF"
+   d="M15.816-18.084c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path186" />
+				<path
+   fill="#FFFFFF"
+   d="M8.156-18.084c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path188" />
+				<path
+   fill="#FFFFFF"
+   d="M0.495-18.084c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224C0.5-18.11,0.503-18.175,0.51-18.057      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path190" />
+			</g>
+			<g
+   id="g192">
+				<path
+   fill="#FFFFFF"
+   d="M69.439-10.431c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362C69-9.692,69.159-9.523,69.154-9.4c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path194" />
+				<path
+   fill="#FFFFFF"
+   d="M61.778-10.431c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path196" />
+				<path
+   fill="#FFFFFF"
+   d="M54.118-10.431c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path198" />
+				<path
+   fill="#FFFFFF"
+   d="M46.458-10.431c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path200" />
+				<path
+   fill="#FFFFFF"
+   d="M38.797-10.431c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path202" />
+				<path
+   fill="#FFFFFF"
+   d="M31.137-10.431c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path204" />
+				<path
+   fill="#FFFFFF"
+   d="M23.477-10.431c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path206" />
+				<path
+   fill="#FFFFFF"
+   d="M15.816-10.431c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053C17.933-7.969,17.839-8.227,18-8.34      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path208" />
+				<path
+   fill="#FFFFFF"
+   d="M8.156-10.431c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      C7.915-10.05,7.866-9.836,7.886-9.75C7.717-9.692,7.876-9.523,7.871-9.4C7.868-9.351,7.83-9.295,7.826-9.239      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      C9.114-7.652,9.321-7.799,9.48-7.837c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path210" />
+				<path
+   fill="#FFFFFF"
+   d="M0.495-10.431c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      C0.254-10.05,0.205-9.836,0.225-9.75C0.056-9.692,0.215-9.523,0.21-9.4c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37C0.33-8.671,0.501-8.456,0.668-8.325c0.19,0.148,0.365,0.572,0.608,0.631      C1.454-7.652,1.66-7.799,1.819-7.837C2-7.88,2.217-7.827,2.391-7.89c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46C3.477-8.933,3.471-8.995,3.5-9.071      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path212" />
+			</g>
+		</g>
+		<g
+   id="g214">
+			<path
+   fill="#FFFFFF"
+   d="M69.439-2.778c0.018,0.072,0.008,0.127-0.026,0.19C69.361-2.487,69.3-2.525,69.248-2.46     c-0.051,0.062-0.099,0.276-0.079,0.362C69-2.04,69.159-1.871,69.154-1.748c-0.002,0.05-0.041,0.105-0.045,0.161     c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631     C70.397,0,70.604-0.146,70.763-0.185c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45     c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.07,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221     c0.038-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.051-0.12-0.064-0.187c-0.021-0.114,0.002-0.224,0-0.337     c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207     c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.215,0.124-0.215,0.224c0.002,0.115,0.005,0.051,0.012,0.169     c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path216" />
+			<path
+   fill="#FFFFFF"
+   d="M61.778-2.778c0.018,0.072,0.007,0.127-0.026,0.19C61.7-2.487,61.64-2.525,61.587-2.46     c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161     c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631     C62.737,0,62.943-0.146,63.103-0.185c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45     c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221     c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337     c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207     c-0.17,0.088-0.139,0.166-0.318,0.224C61.915-3.117,61.78-3.02,61.781-2.92c0.001,0.115,0.005,0.051,0.012,0.169     c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path218" />
+			<path
+   fill="#FFFFFF"
+   d="M54.118-2.778c0.018,0.072,0.007,0.127-0.026,0.19C54.04-2.487,53.98-2.525,53.927-2.46     c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161     c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631     C55.077,0,55.283-0.146,55.442-0.185c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45     c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221     c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337     c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207     c-0.17,0.088-0.139,0.166-0.318,0.224C54.255-3.117,54.12-3.02,54.121-2.92c0.001,0.115,0.005,0.051,0.012,0.169     c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path220" />
+			<path
+   fill="#FFFFFF"
+   d="M46.458-2.778c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128     c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161     c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631     C47.416,0,47.623-0.146,47.782-0.185c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45     c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221     c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337     c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207     c-0.17,0.088-0.139,0.166-0.318,0.224C46.594-3.117,46.459-3.02,46.46-2.92c0.001,0.115,0.005,0.051,0.012,0.169     c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path222" />
+			<path
+   fill="#FFFFFF"
+   d="M38.797-2.778c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128     c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161     c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631     C39.756,0,39.962-0.146,40.122-0.185c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45     c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221     c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337     c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207     c-0.17,0.088-0.139,0.166-0.318,0.224C38.934-3.117,38.799-3.02,38.8-2.92c0.001,0.115,0.005,0.051,0.012,0.169     c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path224" />
+			<path
+   fill="#FFFFFF"
+   d="M31.137-2.778c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128     c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161     c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631     C32.095,0,32.302-0.146,32.461-0.185c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45     c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221     c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337     c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207     c-0.17,0.088-0.139,0.166-0.318,0.224C31.273-3.117,31.139-3.02,31.14-2.92c0.001,0.115,0.005,0.051,0.012,0.169     c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path226" />
+			<path
+   fill="#FFFFFF"
+   d="M23.477-2.778c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128     c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161     c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631     C24.435,0,24.642-0.146,24.801-0.185c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45     c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221     c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337     c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207     c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169     c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path228" />
+			<path
+   fill="#FFFFFF"
+   d="M15.816-2.778c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128     c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161     c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631     C16.774,0,16.981-0.146,17.14-0.185c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45     c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221     c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337     c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207     c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169     C15.81-2.74,15.809-2.756,15.8-2.776"
+   id="path230" />
+			<path
+   fill="#FFFFFF"
+   d="M8.156-2.778c0.018,0.072,0.007,0.127-0.026,0.19C8.077-2.487,8.018-2.525,7.965-2.46     c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35C7.868-1.698,7.83-1.643,7.826-1.587     c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631     C9.114,0,9.321-0.146,9.48-0.185c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45     c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221     c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337     c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789C8.954-3.54,8.847-3.448,8.692-3.367     c-0.17,0.088-0.139,0.166-0.318,0.224C8.292-3.117,8.158-3.02,8.159-2.92C8.16-2.805,8.164-2.869,8.17-2.751     C8.15-2.74,8.149-2.756,8.14-2.776"
+   id="path232" />
+			<path
+   fill="#FFFFFF"
+   d="M0.495-2.778c0.018,0.072,0.008,0.127-0.026,0.19C0.417-2.487,0.356-2.525,0.304-2.46     C0.253-2.397,0.205-2.184,0.225-2.098C0.056-2.04,0.215-1.871,0.21-1.748c-0.002,0.05-0.041,0.105-0.045,0.161     c-0.01,0.119,0.017,0.266,0.068,0.37C0.33-1.019,0.501-0.804,0.668-0.673c0.19,0.148,0.365,0.572,0.608,0.631     C1.454,0,1.66-0.146,1.819-0.185C2-0.228,2.217-0.175,2.391-0.237c0.222-0.079,0.127-0.337,0.288-0.45     c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.07,0.339-0.263,0.376-0.46C3.477-1.28,3.471-1.343,3.5-1.419     c0.038-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.051-0.12-0.064-0.187c-0.021-0.114,0.002-0.224,0-0.337     c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789C1.293-3.54,1.187-3.448,1.031-3.367     c-0.17,0.088-0.139,0.166-0.318,0.224C0.632-3.117,0.498-3.02,0.498-2.92C0.5-2.805,0.503-2.869,0.51-2.751     C0.489-2.74,0.488-2.756,0.479-2.776"
+   id="path234" />
+		</g>
+	</g>
+</pattern>
+
+<path
+   style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;baseline-shift:baseline;opacity:0.2;color:#000000;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:4;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Sans;-inkscape-font-specification:Sans"
+   d="M 14.5 7.6875 C 12.118202 7.6875 10.1875 9.6181999 10.1875 12 C 10.1875 12.98178 10.511318 13.90142 11.0625 14.625 C 12.258208 13.24105 14.029595 12.34375 16 12.34375 C 16.964013 12.34375 17.863805 12.56114 18.6875 12.9375 C 18.75419 12.6359 18.78125 12.32193 18.78125 12 C 18.78125 9.6181999 16.8818 7.6875 14.5 7.6875 z M 8.875 9.6875 C 7.634625 9.6875 6.625 10.69712 6.625 11.9375 C 6.625 12.3391 6.72279 12.70624 6.90625 13.03125 C 7.65474 12.60902 8.5183475 12.375 9.4375 12.375 C 9.526205 12.375 9.63115 12.371 9.71875 12.375 C 9.70882 12.2497 9.6875 12.12826 9.6875 12 C 9.6875 11.30913 9.83008 10.65627 10.09375 10.0625 C 9.7387425 9.8244499 9.3358175 9.6875 8.875 9.6875 z M 19.21875 11.25 C 19.25778 11.49606 19.28125 11.74306 19.28125 12 C 19.28125 12.39985 19.248935 12.78521 19.15625 13.15625 C 20.2429 13.75761 21.12418 14.65908 21.71875 15.75 C 22.335455 15.42894 23.01983 15.23643 23.75 15.1875 C 23.56182 12.98063 21.755825 11.25 19.5 11.25 C 19.40836 11.25 19.30897 11.2444 19.21875 11.25 z M 16 12.84375 C 12.66715 12.84375 9.96875 15.54192 9.96875 18.875 C 9.96875 22.20772 12.667013 24.90625 16 24.90625 C 19.33299 24.90625 22.03125 22.20771 22.03125 18.875 C 22.03125 15.54193 19.332853 12.84375 16 12.84375 z M 9.4375 12.875 C 6.85184 12.875 4.78125 14.94559 4.78125 17.53125 C 4.78125 19.05338 5.501155 20.42736 6.625 21.28125 C 7.09879 20.36744 8.0570875 19.71875 9.15625 19.71875 C 9.289095 19.71875 9.403215 19.7323 9.53125 19.75 C 9.491058 19.45758 9.46875 19.1784 9.46875 18.875 C 9.46875 17.4244 9.947247 16.08344 10.75 15 C 10.26948 14.39871 9.9278275 13.66206 9.78125 12.875 C 9.6726175 12.867 9.5480625 12.875 9.4375 12.875 z M 12.8125 15 L 16 17.40625 L 19.1875 15 L 20 15.8125 L 17.59375 19 L 20 22.1875 L 19.1875 23 L 16 20.59375 L 12.8125 23 L 12 22.1875 L 14.40625 19 L 12 15.8125 L 12.8125 15 z M 24.09375 15.65625 C 23.308625 15.65625 22.586838 15.84758 21.9375 16.1875 C 22.306215 17.00423 22.5 17.92139 22.5 18.875 C 22.5 20.66055 21.78996 22.2909 20.625 23.46875 C 21.48082 24.41888 22.712632 25 24.09375 25 C 26.67941 25 28.78125 22.89816 28.78125 20.3125 C 28.78125 17.726839 26.67941 15.65625 24.09375 15.65625 z M 4.3125 16.28125 C 1.9306325 16.28125 0 18.18063 0 20.5625 C 0 22.94437 1.9306325 24.875 4.3125 24.875 C 5.2190732 24.875 6.056265 24.602439 6.75 24.125 C 6.463335 23.67955 6.3125 23.129619 6.3125 22.5625 C 6.3125 22.268139 6.3542845 21.98594 6.4375 21.71875 C 5.13876 20.78017 4.28125 19.25317 4.28125 17.53125 C 4.28125 17.09375 4.3347293 16.6872 4.4375 16.28125 C 4.394842 16.28025 4.3554647 16.28125 4.3125 16.28125 z M 29.625 19.96875 C 29.497935 19.96875 29.371487 19.9807 29.25 20 C 29.2567 20.1074 29.28125 20.20342 29.28125 20.3125 C 29.28125 21.68587 28.720337 22.9487 27.84375 23.875 C 28.275 24.37649 28.908165 24.6875 29.625 24.6875 C 30.93072 24.6875 32 23.64947 32 22.34375 C 32 21.03803 30.93072 19.96875 29.625 19.96875 z M 9.15625 20.21875 C 7.8505975 20.21875 6.78125 21.25684 6.78125 22.5625 C 6.78125 23.86815 7.8505975 24.9375 9.15625 24.9375 C 10.15705 24.9375 10.99878 24.31592 11.34375 23.4375 C 10.50201 22.5802 9.8922975 21.49648 9.625 20.28125 C 9.4685825 20.24891 9.322335 20.21875 9.15625 20.21875 z "
+   transform="translate(0,-1.5e-6)"
+   id="path7625" /><path
+   style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;baseline-shift:baseline;opacity:0.8;color:#000000;fill:url(#linearGradient3956);fill-opacity:1;stroke:none;stroke-width:4;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Sans;-inkscape-font-specification:Sans"
+   d="m 14.5,6.687498 c -2.381798,0 -4.3125,1.9307 -4.3125,4.312501 0,0.98178 0.323818,1.90142 0.875,2.625 1.195708,-1.38395 2.967095,-2.28125 4.9375,-2.28125 0.964013,0 1.863805,0.21739 2.6875,0.59375 0.06669,-0.3016 0.09375,-0.61557 0.09375,-0.9375 0,-2.381801 -1.89945,-4.312501 -4.28125,-4.312501 z m -5.625,2 c -1.240375,0 -2.25,1.00963 -2.25,2.250001 0,0.4016 0.09779,0.76874 0.28125,1.09375 0.74849,-0.422231 1.6120975,-0.65625 2.53125,-0.65625 0.088705,0 0.19365,-0.004 0.28125,0 -0.00993,-0.1253 -0.03125,-0.246741 -0.03125,-0.375 0,-0.69086 0.14258,-1.343731 0.40625,-1.937501 -0.3550075,-0.238049 -0.7579325,-0.375 -1.21875,-0.375 z m 10.34375,1.562501 c 0.03903,0.24606 0.0625,0.49307 0.0625,0.75 0,0.39985 -0.03232,0.78521 -0.125,1.15625 1.08665,0.60137 1.96793,1.50283 2.5625,2.59375 0.616705,-0.32106 1.30108,-0.51356 2.03125,-0.5625 -0.18818,-2.20687 -1.994175,-3.9375 -4.25,-3.9375 -0.09164,0 -0.19103,-0.0056 -0.28125,0 z M 16,11.843749 c -3.33285,0 -6.03125,2.69817 -6.03125,6.031249 0,3.33272 2.698263,6.03125 6.03125,6.03125 3.33299,0 6.03125,-2.69854 6.03125,-6.03125 0,-3.333069 -2.698397,-6.031249 -6.03125,-6.031249 z m -6.5625,0.03125 c -2.58566,0 -4.65625,2.07058 -4.65625,4.656249 0,1.52212 0.719905,2.89611 1.84375,3.75 0.47379,-0.913811 1.4320875,-1.5625 2.53125,-1.5625 0.132845,0 0.246965,0.01355 0.375,0.03125 -0.040192,-0.29242 -0.0625,-0.5716 -0.0625,-0.875 0,-1.450599 0.478497,-2.791559 1.28125,-3.874999 -0.48052,-0.60129 -0.8221725,-1.33794 -0.96875,-2.125 -0.1086325,-0.008 -0.2331875,0 -0.34375,0 z m 3.375,2.125 L 16,16.406248 19.1875,13.999999 20,14.812499 17.59375,17.999998 20,21.187498 19.1875,21.999998 16,19.593748 12.8125,21.999998 12,21.187498 14.40625,17.999998 12,14.812499 l 0.8125,-0.8125 z m 11.28125,0.65625 c -0.785125,0 -1.506912,0.19133 -2.15625,0.53125 0.368715,0.816729 0.5625,1.733889 0.5625,2.687499 0,1.78555 -0.71004,3.4159 -1.875,4.59375 0.85582,0.950131 2.087632,1.53125 3.46875,1.53125 2.58566,0 4.6875,-2.10184 4.6875,-4.6875 0,-2.58566 -2.10184,-4.656249 -4.6875,-4.656249 z m -19.78125,0.625 C 1.9306325,15.281249 0,17.180628 0,19.562498 c 0,2.38187 1.9306325,4.3125 4.3125,4.3125 0.9065732,0 1.743765,-0.272561 2.4375,-0.75 -0.286665,-0.44545 -0.4375,-0.99538 -0.4375,-1.5625 0,-0.29436 0.041785,-0.57656 0.125,-0.84375 -1.29874,-0.938579 -2.15625,-2.465589 -2.15625,-4.1875 0,-0.43751 0.053479,-0.844049 0.15625,-1.249999 -0.042658,-0.001 -0.082035,0 -0.125,0 z m 25.3125,3.687499 c -0.127065,0 -0.253513,0.01195 -0.375,0.03125 0.0067,0.1074 0.03125,0.203421 0.03125,0.3125 0,1.373371 -0.560913,2.6362 -1.4375,3.5625 0.43125,0.50149 1.064415,0.8125 1.78125,0.8125 1.30572,0 2.375,-1.03803 2.375,-2.34375 0,-1.30572 -1.06928,-2.375 -2.375,-2.375 z m -20.46875,0.25 c -1.3056525,0 -2.375,1.03809 -2.375,2.34375 0,1.30565 1.0693475,2.375 2.375,2.375 1.0008,0 1.84253,-0.621579 2.1875,-1.5 -0.84174,-0.857299 -1.4514525,-1.941019 -1.71875,-3.15625 -0.1564175,-0.03234 -0.302665,-0.0625 -0.46875,-0.0625 z"
+   id="circle238"
+   inkscape:connector-curvature="0" />
+
+
+
+
+
+
+
+
+
+
+</svg>
\ No newline at end of file
diff --git a/core/img/icon-sync.png b/core/img/icon-sync.png
new file mode 100644
index 0000000000000000000000000000000000000000..99a43d4c69ab2a93bd94655c0b74494e0abe537c
Binary files /dev/null and b/core/img/icon-sync.png differ
diff --git a/core/img/icon-sync.svg b/core/img/icon-sync.svg
new file mode 100644
index 0000000000000000000000000000000000000000..f9ebec4a5b560c93e5ac07a0430c492159dc9e3d
--- /dev/null
+++ b/core/img/icon-sync.svg
@@ -0,0 +1,815 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Generator: Adobe Illustrator 13.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 14948)  -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:xlink="http://www.w3.org/1999/xlink"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   version="1.1"
+   id="Layer_1"
+   x="0px"
+   y="0px"
+   width="32"
+   height="32"
+   viewBox="0 0 32 31.999997"
+   enable-background="new 0 0 595.275 311.111"
+   xml:space="preserve"
+   inkscape:version="0.48.2 r9819"
+   sodipodi:docname="icon-sync.svg"
+   inkscape:export-filename="/home/user/owncloud/core/img/icon.png"
+   inkscape:export-xdpi="89.826416"
+   inkscape:export-ydpi="89.826416"><metadata
+   id="metadata327"><rdf:RDF><cc:Work
+       rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
+         rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
+   id="defs325"><linearGradient
+   inkscape:collect="always"
+   xlink:href="#SVGID_1_"
+   id="linearGradient3353"
+   gradientUnits="userSpaceOnUse"
+   x1="288.49411"
+   y1="55.888199"
+   x2="288.49411"
+   y2="339.22189" /><linearGradient
+   inkscape:collect="always"
+   xlink:href="#SVGID_2_"
+   id="linearGradient3355"
+   gradientUnits="userSpaceOnUse"
+   x1="251.2114"
+   y1="55.888199"
+   x2="251.2114"
+   y2="339.22159" /><linearGradient
+   inkscape:collect="always"
+   xlink:href="#SVGID_3_"
+   id="linearGradient3357"
+   gradientUnits="userSpaceOnUse"
+   x1="293.22461"
+   y1="55.888199"
+   x2="293.22461"
+   y2="339.22171" /><linearGradient
+   inkscape:collect="always"
+   xlink:href="#SVGID_4_"
+   id="linearGradient3359"
+   gradientUnits="userSpaceOnUse"
+   x1="375.33401"
+   y1="55.888199"
+   x2="375.33401"
+   y2="339.22159" /><linearGradient
+   inkscape:collect="always"
+   xlink:href="#SVGID_5_"
+   id="linearGradient3361"
+   gradientUnits="userSpaceOnUse"
+   x1="334.49411"
+   y1="55.888199"
+   x2="334.49411"
+   y2="339.22159" /><linearGradient
+   inkscape:collect="always"
+   xlink:href="#SVGID_6_"
+   id="linearGradient3363"
+   gradientUnits="userSpaceOnUse"
+   x1="458.42679"
+   y1="55.8867"
+   x2="458.42679"
+   y2="339.2236" /><linearGradient
+   inkscape:collect="always"
+   xlink:href="#SVGID_7_"
+   id="linearGradient3365"
+   gradientUnits="userSpaceOnUse"
+   x1="413.16309"
+   y1="55.888199"
+   x2="413.16309"
+   y2="339.22131" /><linearGradient
+   inkscape:collect="always"
+   xlink:href="#SVGID_8_"
+   id="linearGradient3367"
+   gradientUnits="userSpaceOnUse"
+   x1="290.76169"
+   y1="55.8867"
+   x2="290.76169"
+   y2="339.2236" /><linearGradient
+   inkscape:collect="always"
+   xlink:href="#SVGID_9_"
+   id="linearGradient3369"
+   gradientUnits="userSpaceOnUse"
+   x1="346.77341"
+   y1="55.888199"
+   x2="346.77341"
+   y2="339.22119" />
+	<linearGradient
+   y2="339.22189"
+   x2="288.49411"
+   y1="55.888199"
+   x1="288.49411"
+   gradientUnits="userSpaceOnUse"
+   id="SVGID_1_">
+		<stop
+   id="stop261"
+   style="stop-color:#BED5E1"
+   offset="0" />
+		<stop
+   id="stop263"
+   style="stop-color:#567B8F"
+   offset="1" />
+	</linearGradient>
+	
+	<linearGradient
+   y2="339.22159"
+   x2="251.2114"
+   y1="55.888199"
+   x1="251.2114"
+   gradientUnits="userSpaceOnUse"
+   id="SVGID_2_">
+		<stop
+   id="stop268"
+   style="stop-color:#BED5E1"
+   offset="0" />
+		<stop
+   id="stop270"
+   style="stop-color:#567B8F"
+   offset="1" />
+	</linearGradient>
+	
+	<linearGradient
+   y2="339.22171"
+   x2="293.22461"
+   y1="55.888199"
+   x1="293.22461"
+   gradientUnits="userSpaceOnUse"
+   id="SVGID_3_">
+		<stop
+   id="stop275"
+   style="stop-color:#BED5E1"
+   offset="0" />
+		<stop
+   id="stop277"
+   style="stop-color:#567B8F"
+   offset="1" />
+	</linearGradient>
+	
+	<linearGradient
+   y2="339.22159"
+   x2="375.33401"
+   y1="55.888199"
+   x1="375.33401"
+   gradientUnits="userSpaceOnUse"
+   id="SVGID_4_">
+		<stop
+   id="stop282"
+   style="stop-color:#BED5E1"
+   offset="0" />
+		<stop
+   id="stop284"
+   style="stop-color:#567B8F"
+   offset="1" />
+	</linearGradient>
+	
+	<linearGradient
+   y2="339.22159"
+   x2="334.49411"
+   y1="55.888199"
+   x1="334.49411"
+   gradientUnits="userSpaceOnUse"
+   id="SVGID_5_">
+		<stop
+   id="stop289"
+   style="stop-color:#BED5E1"
+   offset="0" />
+		<stop
+   id="stop291"
+   style="stop-color:#567B8F"
+   offset="1" />
+	</linearGradient>
+	
+	<linearGradient
+   y2="339.2236"
+   x2="458.42679"
+   y1="55.8867"
+   x1="458.42679"
+   gradientUnits="userSpaceOnUse"
+   id="SVGID_6_">
+		<stop
+   id="stop296"
+   style="stop-color:#BED5E1"
+   offset="0" />
+		<stop
+   id="stop298"
+   style="stop-color:#567B8F"
+   offset="1" />
+	</linearGradient>
+	
+	<linearGradient
+   y2="339.22131"
+   x2="413.16309"
+   y1="55.888199"
+   x1="413.16309"
+   gradientUnits="userSpaceOnUse"
+   id="SVGID_7_">
+		<stop
+   id="stop303"
+   style="stop-color:#BED5E1"
+   offset="0" />
+		<stop
+   id="stop305"
+   style="stop-color:#567B8F"
+   offset="1" />
+	</linearGradient>
+	
+	<linearGradient
+   y2="339.2236"
+   x2="290.76169"
+   y1="55.8867"
+   x1="290.76169"
+   gradientUnits="userSpaceOnUse"
+   id="SVGID_8_">
+		<stop
+   id="stop310"
+   style="stop-color:#BED5E1"
+   offset="0" />
+		<stop
+   id="stop312"
+   style="stop-color:#567B8F"
+   offset="1" />
+	</linearGradient>
+	
+	<linearGradient
+   y2="339.22119"
+   x2="346.77341"
+   y1="55.888199"
+   x1="346.77341"
+   gradientUnits="userSpaceOnUse"
+   id="SVGID_9_">
+		<stop
+   id="stop317"
+   style="stop-color:#BED5E1"
+   offset="0" />
+		<stop
+   id="stop319"
+   style="stop-color:#567B8F"
+   offset="1" />
+	</linearGradient>
+	
+<linearGradient
+   y2="18.967093"
+   x2="-2.4040222"
+   y1="4.4573336"
+   x1="-2.4040222"
+   gradientTransform="translate(13.927091,16.573387)"
+   gradientUnits="userSpaceOnUse"
+   id="linearGradient3475"
+   xlink:href="#linearGradient3587-6-5-26"
+   inkscape:collect="always" /><linearGradient
+   id="linearGradient3587-6-5-26"><stop
+     id="stop3589-9-2-45"
+     style="stop-color:#000000;stop-opacity:1"
+     offset="0" /><stop
+     id="stop3591-7-4-20"
+     style="stop-color:#363636;stop-opacity:1"
+     offset="1" /></linearGradient><linearGradient
+   y2="18.967093"
+   x2="-2.4040222"
+   y1="4.4573336"
+   x1="-2.4040222"
+   gradientTransform="translate(13.927091,16.573387)"
+   gradientUnits="userSpaceOnUse"
+   id="linearGradient7590"
+   xlink:href="#linearGradient3587-6-5-26"
+   inkscape:collect="always" /><linearGradient
+   inkscape:collect="always"
+   xlink:href="#linearGradient3587-6-5-26"
+   id="linearGradient7614"
+   gradientUnits="userSpaceOnUse"
+   gradientTransform="translate(15.071012,45.700897)"
+   x1="-2.4040222"
+   y1="4.4573336"
+   x2="-2.4040222"
+   y2="18.967093" /><linearGradient
+   inkscape:collect="always"
+   xlink:href="#linearGradient3587-6-5-26"
+   id="linearGradient3342"
+   gradientUnits="userSpaceOnUse"
+   gradientTransform="matrix(0.25,0,0,0.25,0,0.500024)"
+   x1="58.866638"
+   y1="24.928007"
+   x2="58.866638"
+   y2="93.882034" /></defs><sodipodi:namedview
+   pagecolor="#ffffff"
+   bordercolor="#666666"
+   borderopacity="1"
+   objecttolerance="10"
+   gridtolerance="10"
+   guidetolerance="10"
+   inkscape:pageopacity="0"
+   inkscape:pageshadow="2"
+   inkscape:window-width="1280"
+   inkscape:window-height="774"
+   id="namedview323"
+   showgrid="true"
+   inkscape:zoom="8"
+   inkscape:cx="9.2669664"
+   inkscape:cy="16.482737"
+   inkscape:window-x="0"
+   inkscape:window-y="26"
+   inkscape:window-maximized="1"
+   inkscape:current-layer="Layer_1"
+   units="px"
+   fit-margin-top="0"
+   fit-margin-left="0"
+   fit-margin-right="0"
+   fit-margin-bottom="0"
+   showguides="true"
+   inkscape:guide-bbox="true"><inkscape:grid
+     type="xygrid"
+     id="grid3152"
+     empspacing="2"
+     visible="true"
+     enabled="true"
+     snapvisiblegridlinesonly="true"
+     dotted="false" /></sodipodi:namedview>
+<pattern
+   y="565.223"
+   width="69"
+   height="69"
+   patternUnits="userSpaceOnUse"
+   id="Polka_Dot_Pattern"
+   viewBox="2.125 -70.896 69 69"
+   overflow="visible">
+	<g
+   id="g4">
+		<polygon
+   fill="none"
+   points="71.125,-1.896 2.125,-1.896 2.125,-70.896 71.125,-70.896   "
+   id="polygon6" />
+		<polygon
+   fill="#F6BB60"
+   points="71.125,-1.896 2.125,-1.896 2.125,-70.896 71.125,-70.896   "
+   id="polygon8" />
+		<g
+   id="g10">
+			<path
+   fill="#FFFFFF"
+   d="M61.772-71.653c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128     c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161     c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631     c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45     c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221     c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337     c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207     c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169     c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path12" />
+			<path
+   fill="#FFFFFF"
+   d="M54.105-71.653c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128     c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161     c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631     c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45     c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221     c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337     c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207     c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169     c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path14" />
+			<path
+   fill="#FFFFFF"
+   d="M46.439-71.653c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128     c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161     c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631     c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45     c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221     c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337     c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207     c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169     c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path16" />
+			<path
+   fill="#FFFFFF"
+   d="M38.772-71.653c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128     c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161     c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631     c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45     c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221     c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337     c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207     c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169     c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path18" />
+			<path
+   fill="#FFFFFF"
+   d="M31.105-71.653c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128     c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161     c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631     c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45     c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221     c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337     c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207     c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169     c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path20" />
+			<path
+   fill="#FFFFFF"
+   d="M23.439-71.653c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128     c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161     c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631     c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45     c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221     c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337     c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207     c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169     c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path22" />
+			<path
+   fill="#FFFFFF"
+   d="M15.772-71.653c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128     c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161     c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631     c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45     c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221     c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337     c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207     c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169     c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path24" />
+			<path
+   fill="#FFFFFF"
+   d="M8.105-71.653c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128     c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161     c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631     c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45     c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221     c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337     c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207     c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169     c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path26" />
+			<path
+   fill="#FFFFFF"
+   d="M0.439-71.653c0.018,0.072,0.008,0.127-0.026,0.19C0.361-71.362,0.3-71.4,0.248-71.335     c-0.051,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161     c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631     c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45     c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.07,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221     c0.038-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.051-0.12-0.064-0.187c-0.021-0.114,0.002-0.224,0-0.337     c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207     c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.215,0.124-0.215,0.224c0.002,0.115,0.005,0.051,0.012,0.169     c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path28" />
+		</g>
+		<g
+   id="g30">
+			<path
+   fill="#FFFFFF"
+   d="M69.439-71.653c0.018,0.072,0.008,0.127-0.026,0.19c-0.052,0.101-0.113,0.062-0.165,0.128     c-0.051,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161     c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631     c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45     c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.07,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221     c0.038-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.051-0.12-0.064-0.187c-0.021-0.114,0.002-0.224,0-0.337     c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207     c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.215,0.124-0.215,0.224c0.002,0.115,0.005,0.051,0.012,0.169     c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path32" />
+		</g>
+		<path
+   fill="#FFFFFF"
+   d="M0.495-71.653c0.018,0.072,0.008,0.127-0.026,0.19c-0.052,0.101-0.113,0.062-0.165,0.128    c-0.051,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161    c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631    c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45    c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.07,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221    c0.038-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.051-0.12-0.064-0.187c-0.021-0.114,0.002-0.224,0-0.337    c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207    c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.215,0.124-0.215,0.224C0.5-71.68,0.503-71.744,0.51-71.626    c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path34" />
+		<g
+   id="g36">
+			<g
+   id="g38">
+				<path
+   fill="#FFFFFF"
+   d="M69.439-64.001c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path40" />
+				<path
+   fill="#FFFFFF"
+   d="M61.778-64.001c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path42" />
+				<path
+   fill="#FFFFFF"
+   d="M54.118-64.001c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path44" />
+				<path
+   fill="#FFFFFF"
+   d="M46.458-64.001c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path46" />
+				<path
+   fill="#FFFFFF"
+   d="M38.797-64.001c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path48" />
+				<path
+   fill="#FFFFFF"
+   d="M31.137-64.001c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path50" />
+				<path
+   fill="#FFFFFF"
+   d="M23.477-64.001c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path52" />
+				<path
+   fill="#FFFFFF"
+   d="M15.816-64.001c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path54" />
+				<path
+   fill="#FFFFFF"
+   d="M8.156-64.001c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path56" />
+				<path
+   fill="#FFFFFF"
+   d="M0.495-64.001c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143C2-61.45,2.217-61.397,2.391-61.46c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path58" />
+			</g>
+			<g
+   id="g60">
+				<path
+   fill="#FFFFFF"
+   d="M69.439-56.348c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path62" />
+				<path
+   fill="#FFFFFF"
+   d="M61.778-56.348c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path64" />
+				<path
+   fill="#FFFFFF"
+   d="M54.118-56.348c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path66" />
+				<path
+   fill="#FFFFFF"
+   d="M46.458-56.348c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path68" />
+				<path
+   fill="#FFFFFF"
+   d="M38.797-56.348c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path70" />
+				<path
+   fill="#FFFFFF"
+   d="M31.137-56.348c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path72" />
+				<path
+   fill="#FFFFFF"
+   d="M23.477-56.348c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path74" />
+				<path
+   fill="#FFFFFF"
+   d="M15.816-56.348c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path76" />
+				<path
+   fill="#FFFFFF"
+   d="M8.156-56.348c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path78" />
+				<path
+   fill="#FFFFFF"
+   d="M0.495-56.348c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224C0.5-56.374,0.503-56.438,0.51-56.32      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path80" />
+			</g>
+			<g
+   id="g82">
+				<path
+   fill="#FFFFFF"
+   d="M69.439-48.695c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path84" />
+				<path
+   fill="#FFFFFF"
+   d="M61.778-48.695c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path86" />
+				<path
+   fill="#FFFFFF"
+   d="M54.118-48.695c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path88" />
+				<path
+   fill="#FFFFFF"
+   d="M46.458-48.695c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path90" />
+				<path
+   fill="#FFFFFF"
+   d="M38.797-48.695c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path92" />
+				<path
+   fill="#FFFFFF"
+   d="M31.137-48.695c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path94" />
+				<path
+   fill="#FFFFFF"
+   d="M23.477-48.695c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path96" />
+				<path
+   fill="#FFFFFF"
+   d="M15.816-48.695c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path98" />
+				<path
+   fill="#FFFFFF"
+   d="M8.156-48.695c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path100" />
+				<path
+   fill="#FFFFFF"
+   d="M0.495-48.695c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path102" />
+			</g>
+			<g
+   id="g104">
+				<path
+   fill="#FFFFFF"
+   d="M69.439-41.042c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path106" />
+				<path
+   fill="#FFFFFF"
+   d="M61.778-41.042c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path108" />
+				<path
+   fill="#FFFFFF"
+   d="M54.118-41.042c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path110" />
+				<path
+   fill="#FFFFFF"
+   d="M46.458-41.042c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path112" />
+				<path
+   fill="#FFFFFF"
+   d="M38.797-41.042c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path114" />
+				<path
+   fill="#FFFFFF"
+   d="M31.137-41.042c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path116" />
+				<path
+   fill="#FFFFFF"
+   d="M23.477-41.042c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path118" />
+				<path
+   fill="#FFFFFF"
+   d="M15.816-41.042c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path120" />
+				<path
+   fill="#FFFFFF"
+   d="M8.156-41.042c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      C8.15-41.004,8.149-41.02,8.14-41.04"
+   id="path122" />
+				<path
+   fill="#FFFFFF"
+   d="M0.495-41.042c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path124" />
+			</g>
+			<g
+   id="g126">
+				<path
+   fill="#FFFFFF"
+   d="M69.439-33.39c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path128" />
+				<path
+   fill="#FFFFFF"
+   d="M61.778-33.39c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path130" />
+				<path
+   fill="#FFFFFF"
+   d="M54.118-33.39c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path132" />
+				<path
+   fill="#FFFFFF"
+   d="M46.458-33.39c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path134" />
+				<path
+   fill="#FFFFFF"
+   d="M38.797-33.39c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path136" />
+				<path
+   fill="#FFFFFF"
+   d="M31.137-33.39c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path138" />
+				<path
+   fill="#FFFFFF"
+   d="M23.477-33.39c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path140" />
+				<path
+   fill="#FFFFFF"
+   d="M15.816-33.39c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path142" />
+				<path
+   fill="#FFFFFF"
+   d="M8.156-33.39c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path144" />
+				<path
+   fill="#FFFFFF"
+   d="M0.495-33.39c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224C0.5-33.416,0.503-33.48,0.51-33.362      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path146" />
+			</g>
+			<g
+   id="g148">
+				<path
+   fill="#FFFFFF"
+   d="M69.439-25.736c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path150" />
+				<path
+   fill="#FFFFFF"
+   d="M61.778-25.736c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path152" />
+				<path
+   fill="#FFFFFF"
+   d="M54.118-25.736c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path154" />
+				<path
+   fill="#FFFFFF"
+   d="M46.458-25.736c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path156" />
+				<path
+   fill="#FFFFFF"
+   d="M38.797-25.736c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path158" />
+				<path
+   fill="#FFFFFF"
+   d="M31.137-25.736c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path160" />
+				<path
+   fill="#FFFFFF"
+   d="M23.477-25.736c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path162" />
+				<path
+   fill="#FFFFFF"
+   d="M15.816-25.736c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path164" />
+				<path
+   fill="#FFFFFF"
+   d="M8.156-25.736c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path166" />
+				<path
+   fill="#FFFFFF"
+   d="M0.495-25.736c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path168" />
+			</g>
+			<g
+   id="g170">
+				<path
+   fill="#FFFFFF"
+   d="M69.439-18.084c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path172" />
+				<path
+   fill="#FFFFFF"
+   d="M61.778-18.084c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path174" />
+				<path
+   fill="#FFFFFF"
+   d="M54.118-18.084c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path176" />
+				<path
+   fill="#FFFFFF"
+   d="M46.458-18.084c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path178" />
+				<path
+   fill="#FFFFFF"
+   d="M38.797-18.084c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path180" />
+				<path
+   fill="#FFFFFF"
+   d="M31.137-18.084c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path182" />
+				<path
+   fill="#FFFFFF"
+   d="M23.477-18.084c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path184" />
+				<path
+   fill="#FFFFFF"
+   d="M15.816-18.084c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path186" />
+				<path
+   fill="#FFFFFF"
+   d="M8.156-18.084c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path188" />
+				<path
+   fill="#FFFFFF"
+   d="M0.495-18.084c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224C0.5-18.11,0.503-18.175,0.51-18.057      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path190" />
+			</g>
+			<g
+   id="g192">
+				<path
+   fill="#FFFFFF"
+   d="M69.439-10.431c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362C69-9.692,69.159-9.523,69.154-9.4c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path194" />
+				<path
+   fill="#FFFFFF"
+   d="M61.778-10.431c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path196" />
+				<path
+   fill="#FFFFFF"
+   d="M54.118-10.431c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path198" />
+				<path
+   fill="#FFFFFF"
+   d="M46.458-10.431c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path200" />
+				<path
+   fill="#FFFFFF"
+   d="M38.797-10.431c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path202" />
+				<path
+   fill="#FFFFFF"
+   d="M31.137-10.431c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path204" />
+				<path
+   fill="#FFFFFF"
+   d="M23.477-10.431c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path206" />
+				<path
+   fill="#FFFFFF"
+   d="M15.816-10.431c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053C17.933-7.969,17.839-8.227,18-8.34      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path208" />
+				<path
+   fill="#FFFFFF"
+   d="M8.156-10.431c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      C7.915-10.05,7.866-9.836,7.886-9.75C7.717-9.692,7.876-9.523,7.871-9.4C7.868-9.351,7.83-9.295,7.826-9.239      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      C9.114-7.652,9.321-7.799,9.48-7.837c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path210" />
+				<path
+   fill="#FFFFFF"
+   d="M0.495-10.431c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      C0.254-10.05,0.205-9.836,0.225-9.75C0.056-9.692,0.215-9.523,0.21-9.4c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37C0.33-8.671,0.501-8.456,0.668-8.325c0.19,0.148,0.365,0.572,0.608,0.631      C1.454-7.652,1.66-7.799,1.819-7.837C2-7.88,2.217-7.827,2.391-7.89c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46C3.477-8.933,3.471-8.995,3.5-9.071      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path212" />
+			</g>
+		</g>
+		<g
+   id="g214">
+			<path
+   fill="#FFFFFF"
+   d="M69.439-2.778c0.018,0.072,0.008,0.127-0.026,0.19C69.361-2.487,69.3-2.525,69.248-2.46     c-0.051,0.062-0.099,0.276-0.079,0.362C69-2.04,69.159-1.871,69.154-1.748c-0.002,0.05-0.041,0.105-0.045,0.161     c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631     C70.397,0,70.604-0.146,70.763-0.185c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45     c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.07,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221     c0.038-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.051-0.12-0.064-0.187c-0.021-0.114,0.002-0.224,0-0.337     c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207     c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.215,0.124-0.215,0.224c0.002,0.115,0.005,0.051,0.012,0.169     c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path216" />
+			<path
+   fill="#FFFFFF"
+   d="M61.778-2.778c0.018,0.072,0.007,0.127-0.026,0.19C61.7-2.487,61.64-2.525,61.587-2.46     c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161     c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631     C62.737,0,62.943-0.146,63.103-0.185c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45     c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221     c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337     c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207     c-0.17,0.088-0.139,0.166-0.318,0.224C61.915-3.117,61.78-3.02,61.781-2.92c0.001,0.115,0.005,0.051,0.012,0.169     c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path218" />
+			<path
+   fill="#FFFFFF"
+   d="M54.118-2.778c0.018,0.072,0.007,0.127-0.026,0.19C54.04-2.487,53.98-2.525,53.927-2.46     c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161     c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631     C55.077,0,55.283-0.146,55.442-0.185c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45     c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221     c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337     c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207     c-0.17,0.088-0.139,0.166-0.318,0.224C54.255-3.117,54.12-3.02,54.121-2.92c0.001,0.115,0.005,0.051,0.012,0.169     c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path220" />
+			<path
+   fill="#FFFFFF"
+   d="M46.458-2.778c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128     c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161     c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631     C47.416,0,47.623-0.146,47.782-0.185c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45     c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221     c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337     c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207     c-0.17,0.088-0.139,0.166-0.318,0.224C46.594-3.117,46.459-3.02,46.46-2.92c0.001,0.115,0.005,0.051,0.012,0.169     c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path222" />
+			<path
+   fill="#FFFFFF"
+   d="M38.797-2.778c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128     c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161     c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631     C39.756,0,39.962-0.146,40.122-0.185c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45     c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221     c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337     c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207     c-0.17,0.088-0.139,0.166-0.318,0.224C38.934-3.117,38.799-3.02,38.8-2.92c0.001,0.115,0.005,0.051,0.012,0.169     c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path224" />
+			<path
+   fill="#FFFFFF"
+   d="M31.137-2.778c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128     c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161     c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631     C32.095,0,32.302-0.146,32.461-0.185c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45     c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221     c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337     c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207     c-0.17,0.088-0.139,0.166-0.318,0.224C31.273-3.117,31.139-3.02,31.14-2.92c0.001,0.115,0.005,0.051,0.012,0.169     c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path226" />
+			<path
+   fill="#FFFFFF"
+   d="M23.477-2.778c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128     c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161     c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631     C24.435,0,24.642-0.146,24.801-0.185c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45     c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221     c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337     c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207     c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169     c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path228" />
+			<path
+   fill="#FFFFFF"
+   d="M15.816-2.778c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128     c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161     c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631     C16.774,0,16.981-0.146,17.14-0.185c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45     c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221     c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337     c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207     c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169     C15.81-2.74,15.809-2.756,15.8-2.776"
+   id="path230" />
+			<path
+   fill="#FFFFFF"
+   d="M8.156-2.778c0.018,0.072,0.007,0.127-0.026,0.19C8.077-2.487,8.018-2.525,7.965-2.46     c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35C7.868-1.698,7.83-1.643,7.826-1.587     c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631     C9.114,0,9.321-0.146,9.48-0.185c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45     c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221     c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337     c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789C8.954-3.54,8.847-3.448,8.692-3.367     c-0.17,0.088-0.139,0.166-0.318,0.224C8.292-3.117,8.158-3.02,8.159-2.92C8.16-2.805,8.164-2.869,8.17-2.751     C8.15-2.74,8.149-2.756,8.14-2.776"
+   id="path232" />
+			<path
+   fill="#FFFFFF"
+   d="M0.495-2.778c0.018,0.072,0.008,0.127-0.026,0.19C0.417-2.487,0.356-2.525,0.304-2.46     C0.253-2.397,0.205-2.184,0.225-2.098C0.056-2.04,0.215-1.871,0.21-1.748c-0.002,0.05-0.041,0.105-0.045,0.161     c-0.01,0.119,0.017,0.266,0.068,0.37C0.33-1.019,0.501-0.804,0.668-0.673c0.19,0.148,0.365,0.572,0.608,0.631     C1.454,0,1.66-0.146,1.819-0.185C2-0.228,2.217-0.175,2.391-0.237c0.222-0.079,0.127-0.337,0.288-0.45     c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.07,0.339-0.263,0.376-0.46C3.477-1.28,3.471-1.343,3.5-1.419     c0.038-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.051-0.12-0.064-0.187c-0.021-0.114,0.002-0.224,0-0.337     c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789C1.293-3.54,1.187-3.448,1.031-3.367     c-0.17,0.088-0.139,0.166-0.318,0.224C0.632-3.117,0.498-3.02,0.498-2.92C0.5-2.805,0.503-2.869,0.51-2.751     C0.489-2.74,0.488-2.756,0.479-2.776"
+   id="path234" />
+		</g>
+	</g>
+</pattern>
+
+<path
+   style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;baseline-shift:baseline;opacity:0.2;color:#000000;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:4;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Sans;-inkscape-font-specification:Sans"
+   d="M 14.5 7.6875 C 12.118202 7.6875 10.1875 9.6181999 10.1875 12 C 10.1875 12.98178 10.511318 13.90142 11.0625 14.625 C 12.258208 13.24105 14.029595 12.34375 16 12.34375 C 16.964013 12.34375 17.863805 12.56114 18.6875 12.9375 C 18.75419 12.6359 18.78125 12.32193 18.78125 12 C 18.78125 9.6181999 16.8818 7.6875 14.5 7.6875 z M 8.875 9.6875 C 7.634625 9.6875 6.625 10.69712 6.625 11.9375 C 6.625 12.3391 6.72279 12.70624 6.90625 13.03125 C 7.65474 12.60902 8.5183475 12.375 9.4375 12.375 C 9.526205 12.375 9.63115 12.371 9.71875 12.375 C 9.70882 12.2497 9.6875 12.12826 9.6875 12 C 9.6875 11.30913 9.83008 10.65627 10.09375 10.0625 C 9.7387425 9.8244499 9.3358175 9.6875 8.875 9.6875 z M 19.21875 11.25 C 19.25778 11.49606 19.28125 11.74306 19.28125 12 C 19.28125 12.39985 19.248935 12.78521 19.15625 13.15625 C 20.2429 13.75761 21.12418 14.65908 21.71875 15.75 C 22.335455 15.42894 23.01983 15.23643 23.75 15.1875 C 23.56182 12.98063 21.755825 11.25 19.5 11.25 C 19.40836 11.25 19.30897 11.2444 19.21875 11.25 z M 16 12.84375 C 12.66715 12.84375 9.96875 15.54192 9.96875 18.875 C 9.96875 22.20772 12.667013 24.90625 16 24.90625 C 19.33299 24.90625 22.03125 22.20771 22.03125 18.875 C 22.03125 15.54193 19.332853 12.84375 16 12.84375 z M 9.4375 12.875 C 6.85184 12.875 4.78125 14.94559 4.78125 17.53125 C 4.78125 19.05338 5.501155 20.42736 6.625 21.28125 C 7.09879 20.36744 8.0570875 19.71875 9.15625 19.71875 C 9.289095 19.71875 9.403215 19.7323 9.53125 19.75 C 9.491058 19.45758 9.46875 19.1784 9.46875 18.875 C 9.46875 17.4244 9.947247 16.08344 10.75 15 C 10.26948 14.39871 9.9278275 13.66206 9.78125 12.875 C 9.6726175 12.867 9.5480625 12.875 9.4375 12.875 z M 16 15 C 16.786501 15 17.505108 15.232582 18.125 15.625 L 18.375 15.3125 L 18.78125 16.28125 L 19.15625 17.25 L 18.125 17.09375 L 17.125 16.9375 L 17.34375 16.65625 C 16.954783 16.434451 16.48047 16.34375 16 16.34375 C 14.525735 16.34375 13.34375 17.525635 13.34375 19 C 13.34375 19.1555 13.34954 19.289339 13.375 19.4375 L 12.0625 19.65625 C 12.02588 19.438476 12 19.228287 12 19 C 12 16.788454 13.788603 15 16 15 z M 24.09375 15.65625 C 23.308625 15.65625 22.586838 15.84758 21.9375 16.1875 C 22.306215 17.00423 22.5 17.92139 22.5 18.875 C 22.5 20.66055 21.78996 22.2909 20.625 23.46875 C 21.48082 24.41888 22.712632 25 24.09375 25 C 26.67941 25 28.78125 22.89816 28.78125 20.3125 C 28.78125 17.726839 26.67941 15.65625 24.09375 15.65625 z M 4.3125 16.28125 C 1.9306325 16.28125 0 18.18063 0 20.5625 C 0 22.94437 1.9306325 24.875 4.3125 24.875 C 5.2190732 24.875 6.056265 24.602439 6.75 24.125 C 6.463335 23.67955 6.3125 23.129619 6.3125 22.5625 C 6.3125 22.268139 6.3542845 21.98594 6.4375 21.71875 C 5.13876 20.78017 4.28125 19.25317 4.28125 17.53125 C 4.28125 17.09375 4.3347293 16.6872 4.4375 16.28125 C 4.394842 16.28025 4.3554647 16.28125 4.3125 16.28125 z M 19.9375 18.34375 C 19.97413 18.561539 20 18.771691 20 19 C 20 21.211306 18.21149 23 16 23 C 15.213467 23 14.494885 22.767434 13.875 22.375 L 13.625 22.6875 L 13.21875 21.71875 L 12.84375 20.75 L 13.875 20.90625 L 14.875 21.0625 L 14.65625 21.34375 C 15.045211 21.565557 15.51951 21.65625 16 21.65625 C 17.474326 21.65625 18.65625 20.474204 18.65625 19 C 18.65625 18.844486 18.65047 18.710671 18.625 18.5625 L 19.9375 18.34375 z M 29.625 19.96875 C 29.497935 19.96875 29.371487 19.9807 29.25 20 C 29.2567 20.1074 29.28125 20.20342 29.28125 20.3125 C 29.28125 21.68587 28.720337 22.9487 27.84375 23.875 C 28.275 24.37649 28.908165 24.6875 29.625 24.6875 C 30.93072 24.6875 32 23.64947 32 22.34375 C 32 21.03803 30.93072 19.96875 29.625 19.96875 z M 9.15625 20.21875 C 7.8505975 20.21875 6.78125 21.25684 6.78125 22.5625 C 6.78125 23.86815 7.8505975 24.9375 9.15625 24.9375 C 10.15705 24.9375 10.99878 24.31592 11.34375 23.4375 C 10.50201 22.5802 9.8922975 21.49648 9.625 20.28125 C 9.4685825 20.24891 9.322335 20.21875 9.15625 20.21875 z "
+   transform="translate(0,-1.5e-6)"
+   id="path7625" /><path
+   style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;baseline-shift:baseline;opacity:0.8;color:#000000;fill:url(#linearGradient3342);fill-opacity:1;stroke:none;stroke-width:4;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Sans;-inkscape-font-specification:Sans"
+   d="m 14.5,6.687498 c -2.381798,0 -4.3125,1.9307 -4.3125,4.312501 0,0.98178 0.323818,1.90142 0.875,2.625 1.195708,-1.38395 2.967095,-2.28125 4.9375,-2.28125 0.964013,0 1.863805,0.21739 2.6875,0.59375 0.06669,-0.3016 0.09375,-0.61557 0.09375,-0.9375 0,-2.381801 -1.89945,-4.312501 -4.28125,-4.312501 z M 8.875,8.687499 c -1.240375,0 -2.25,1.009629 -2.25,2.25 0,0.4016 0.09779,0.76874 0.28125,1.09375 0.74849,-0.422231 1.6120975,-0.65625 2.53125,-0.65625 0.088705,0 0.19365,-0.004 0.28125,0 -0.00993,-0.1253 -0.03125,-0.246741 -0.03125,-0.375 0,-0.69086 0.14258,-1.343731 0.40625,-1.9375 -0.3550075,-0.23805 -0.7579325,-0.375 -1.21875,-0.375 z m 10.34375,1.5625 c 0.03903,0.24606 0.0625,0.49307 0.0625,0.75 0,0.39985 -0.03232,0.78521 -0.125,1.15625 1.08665,0.60137 1.96793,1.50283 2.5625,2.593749 0.616705,-0.32106 1.30108,-0.51356 2.03125,-0.5625 -0.18818,-2.206869 -1.994175,-3.937499 -4.25,-3.937499 -0.09164,0 -0.19103,-0.0056 -0.28125,0 z M 16,11.843749 c -3.33285,0 -6.03125,2.69817 -6.03125,6.031249 0,3.33272 2.698263,6.03125 6.03125,6.03125 3.33299,0 6.03125,-2.69854 6.03125,-6.03125 0,-3.33307 -2.698397,-6.031249 -6.03125,-6.031249 z m -6.5625,0.03125 c -2.58566,0 -4.65625,2.07058 -4.65625,4.656249 0,1.52212 0.719905,2.89611 1.84375,3.75 0.47379,-0.913811 1.4320875,-1.5625 2.53125,-1.5625 0.132845,0 0.246965,0.01355 0.375,0.03125 -0.040192,-0.29242 -0.0625,-0.5716 -0.0625,-0.875 0,-1.4506 0.478497,-2.79156 1.28125,-3.874999 -0.48052,-0.60129 -0.8221725,-1.33794 -0.96875,-2.125 -0.1086325,-0.008 -0.2331875,0 -0.34375,0 z m 6.5625,2.125 c 0.786501,0 1.505108,0.232583 2.125,0.624999 l 0.25,-0.3125 0.40625,0.96875 0.375,0.96875 -1.03125,-0.15625 -1,-0.15625 0.21875,-0.28125 c -0.388967,-0.221799 -0.86328,-0.3125 -1.34375,-0.3125 -1.474265,0 -2.65625,1.181886 -2.65625,2.65625 0,0.1555 0.0058,0.28934 0.03125,0.4375 l -1.3125,0.21875 C 12.02588,18.438475 12,18.228286 12,17.999998 c 0,-2.211546 1.788603,-3.999999 4,-3.999999 z m 8.09375,0.656249 c -0.785125,0 -1.506912,0.19133 -2.15625,0.53125 0.368715,0.81673 0.5625,1.73389 0.5625,2.6875 0,1.78555 -0.71004,3.4159 -1.875,4.59375 0.85582,0.950131 2.087632,1.53125 3.46875,1.53125 2.58566,0 4.6875,-2.10184 4.6875,-4.6875 0,-2.585661 -2.10184,-4.65625 -4.6875,-4.65625 z m -19.78125,0.625 c -2.3818675,0 -4.3125,1.89938 -4.3125,4.28125 0,2.38187 1.9306325,4.3125 4.3125,4.3125 0.9065732,0 1.743765,-0.272561 2.4375,-0.75 -0.286665,-0.44545 -0.4375,-0.99538 -0.4375,-1.5625 0,-0.29436 0.041785,-0.57656 0.125,-0.84375 -1.29874,-0.93858 -2.15625,-2.465589 -2.15625,-4.1875 0,-0.43751 0.053479,-0.84405 0.15625,-1.25 -0.042658,-10e-4 -0.082035,0 -0.125,0 z m 15.625,2.0625 C 19.97413,17.561537 20,17.771689 20,17.999998 c 0,2.211306 -1.78851,4 -4,4 -0.786533,0 -1.505115,-0.232565 -2.125,-0.625 l -0.25,0.3125 -0.40625,-0.96875 -0.375,-0.96875 1.03125,0.15625 1,0.15625 -0.21875,0.28125 c 0.388961,0.221806 0.86326,0.3125 1.34375,0.3125 1.474326,0 2.65625,-1.182046 2.65625,-2.65625 0,-0.155514 -0.0058,-0.289328 -0.03125,-0.4375 l 1.3125,-0.21875 z m 9.6875,1.625 c -0.127065,0 -0.253513,0.01195 -0.375,0.03125 0.0067,0.1074 0.03125,0.203421 0.03125,0.3125 0,1.373371 -0.560913,2.6362 -1.4375,3.5625 0.43125,0.50149 1.064415,0.8125 1.78125,0.8125 1.30572,0 2.375,-1.03803 2.375,-2.34375 0,-1.30572 -1.06928,-2.375 -2.375,-2.375 z m -20.46875,0.25 c -1.3056525,0 -2.375,1.03809 -2.375,2.34375 0,1.30565 1.0693475,2.375 2.375,2.375 1.0008,0 1.84253,-0.62158 2.1875,-1.5 -0.84174,-0.857299 -1.4514525,-1.94102 -1.71875,-3.15625 -0.1564175,-0.03234 -0.302665,-0.0625 -0.46875,-0.0625 z"
+   id="circle238"
+   inkscape:connector-curvature="0" />
+
+
+
+
+
+
+
+
+
+
+<g
+   id="Layer_1-6"
+   transform="matrix(0.5,0,0,0.5,-5,5.9999985)" /></svg>
\ No newline at end of file
diff --git a/core/img/icon.png b/core/img/icon.png
new file mode 100644
index 0000000000000000000000000000000000000000..24a4b1c3e83ba7e9b247f3ff9fec33f4b26c4630
Binary files /dev/null and b/core/img/icon.png differ
diff --git a/core/img/icon.svg b/core/img/icon.svg
new file mode 100644
index 0000000000000000000000000000000000000000..95eac44548961cf67926c504cf57535a3e7784fe
--- /dev/null
+++ b/core/img/icon.svg
@@ -0,0 +1,821 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Generator: Adobe Illustrator 13.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 14948)  -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:xlink="http://www.w3.org/1999/xlink"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   version="1.1"
+   id="Layer_1"
+   x="0px"
+   y="0px"
+   width="32"
+   height="32"
+   viewBox="0 0 32 31.999997"
+   enable-background="new 0 0 595.275 311.111"
+   xml:space="preserve"
+   inkscape:version="0.48.2 r9819"
+   sodipodi:docname="icon.svg"
+   inkscape:export-filename="/home/user/owncloud/core/img/icon.png"
+   inkscape:export-xdpi="89.826416"
+   inkscape:export-ydpi="89.826416"><metadata
+   id="metadata327"><rdf:RDF><cc:Work
+       rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
+         rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
+   id="defs325"><linearGradient
+   inkscape:collect="always"
+   xlink:href="#SVGID_1_"
+   id="linearGradient3353"
+   gradientUnits="userSpaceOnUse"
+   x1="288.49411"
+   y1="55.888199"
+   x2="288.49411"
+   y2="339.22189" /><linearGradient
+   inkscape:collect="always"
+   xlink:href="#SVGID_2_"
+   id="linearGradient3355"
+   gradientUnits="userSpaceOnUse"
+   x1="251.2114"
+   y1="55.888199"
+   x2="251.2114"
+   y2="339.22159" /><linearGradient
+   inkscape:collect="always"
+   xlink:href="#SVGID_3_"
+   id="linearGradient3357"
+   gradientUnits="userSpaceOnUse"
+   x1="293.22461"
+   y1="55.888199"
+   x2="293.22461"
+   y2="339.22171" /><linearGradient
+   inkscape:collect="always"
+   xlink:href="#SVGID_4_"
+   id="linearGradient3359"
+   gradientUnits="userSpaceOnUse"
+   x1="375.33401"
+   y1="55.888199"
+   x2="375.33401"
+   y2="339.22159" /><linearGradient
+   inkscape:collect="always"
+   xlink:href="#SVGID_5_"
+   id="linearGradient3361"
+   gradientUnits="userSpaceOnUse"
+   x1="334.49411"
+   y1="55.888199"
+   x2="334.49411"
+   y2="339.22159" /><linearGradient
+   inkscape:collect="always"
+   xlink:href="#SVGID_6_"
+   id="linearGradient3363"
+   gradientUnits="userSpaceOnUse"
+   x1="458.42679"
+   y1="55.8867"
+   x2="458.42679"
+   y2="339.2236" /><linearGradient
+   inkscape:collect="always"
+   xlink:href="#SVGID_7_"
+   id="linearGradient3365"
+   gradientUnits="userSpaceOnUse"
+   x1="413.16309"
+   y1="55.888199"
+   x2="413.16309"
+   y2="339.22131" /><linearGradient
+   inkscape:collect="always"
+   xlink:href="#SVGID_8_"
+   id="linearGradient3367"
+   gradientUnits="userSpaceOnUse"
+   x1="290.76169"
+   y1="55.8867"
+   x2="290.76169"
+   y2="339.2236" /><linearGradient
+   inkscape:collect="always"
+   xlink:href="#SVGID_9_"
+   id="linearGradient3369"
+   gradientUnits="userSpaceOnUse"
+   x1="346.77341"
+   y1="55.888199"
+   x2="346.77341"
+   y2="339.22119" />
+	<linearGradient
+   y2="339.22189"
+   x2="288.49411"
+   y1="55.888199"
+   x1="288.49411"
+   gradientUnits="userSpaceOnUse"
+   id="SVGID_1_">
+		<stop
+   id="stop261"
+   style="stop-color:#BED5E1"
+   offset="0" />
+		<stop
+   id="stop263"
+   style="stop-color:#567B8F"
+   offset="1" />
+	</linearGradient>
+	
+	<linearGradient
+   y2="339.22159"
+   x2="251.2114"
+   y1="55.888199"
+   x1="251.2114"
+   gradientUnits="userSpaceOnUse"
+   id="SVGID_2_">
+		<stop
+   id="stop268"
+   style="stop-color:#BED5E1"
+   offset="0" />
+		<stop
+   id="stop270"
+   style="stop-color:#567B8F"
+   offset="1" />
+	</linearGradient>
+	
+	<linearGradient
+   y2="339.22171"
+   x2="293.22461"
+   y1="55.888199"
+   x1="293.22461"
+   gradientUnits="userSpaceOnUse"
+   id="SVGID_3_">
+		<stop
+   id="stop275"
+   style="stop-color:#BED5E1"
+   offset="0" />
+		<stop
+   id="stop277"
+   style="stop-color:#567B8F"
+   offset="1" />
+	</linearGradient>
+	
+	<linearGradient
+   y2="339.22159"
+   x2="375.33401"
+   y1="55.888199"
+   x1="375.33401"
+   gradientUnits="userSpaceOnUse"
+   id="SVGID_4_">
+		<stop
+   id="stop282"
+   style="stop-color:#BED5E1"
+   offset="0" />
+		<stop
+   id="stop284"
+   style="stop-color:#567B8F"
+   offset="1" />
+	</linearGradient>
+	
+	<linearGradient
+   y2="339.22159"
+   x2="334.49411"
+   y1="55.888199"
+   x1="334.49411"
+   gradientUnits="userSpaceOnUse"
+   id="SVGID_5_">
+		<stop
+   id="stop289"
+   style="stop-color:#BED5E1"
+   offset="0" />
+		<stop
+   id="stop291"
+   style="stop-color:#567B8F"
+   offset="1" />
+	</linearGradient>
+	
+	<linearGradient
+   y2="339.2236"
+   x2="458.42679"
+   y1="55.8867"
+   x1="458.42679"
+   gradientUnits="userSpaceOnUse"
+   id="SVGID_6_">
+		<stop
+   id="stop296"
+   style="stop-color:#BED5E1"
+   offset="0" />
+		<stop
+   id="stop298"
+   style="stop-color:#567B8F"
+   offset="1" />
+	</linearGradient>
+	
+	<linearGradient
+   y2="339.22131"
+   x2="413.16309"
+   y1="55.888199"
+   x1="413.16309"
+   gradientUnits="userSpaceOnUse"
+   id="SVGID_7_">
+		<stop
+   id="stop303"
+   style="stop-color:#BED5E1"
+   offset="0" />
+		<stop
+   id="stop305"
+   style="stop-color:#567B8F"
+   offset="1" />
+	</linearGradient>
+	
+	<linearGradient
+   y2="339.2236"
+   x2="290.76169"
+   y1="55.8867"
+   x1="290.76169"
+   gradientUnits="userSpaceOnUse"
+   id="SVGID_8_">
+		<stop
+   id="stop310"
+   style="stop-color:#BED5E1"
+   offset="0" />
+		<stop
+   id="stop312"
+   style="stop-color:#567B8F"
+   offset="1" />
+	</linearGradient>
+	
+	<linearGradient
+   y2="339.22119"
+   x2="346.77341"
+   y1="55.888199"
+   x1="346.77341"
+   gradientUnits="userSpaceOnUse"
+   id="SVGID_9_">
+		<stop
+   id="stop317"
+   style="stop-color:#BED5E1"
+   offset="0" />
+		<stop
+   id="stop319"
+   style="stop-color:#567B8F"
+   offset="1" />
+	</linearGradient>
+	
+<linearGradient
+   y2="18.967093"
+   x2="-2.4040222"
+   y1="4.4573336"
+   x1="-2.4040222"
+   gradientTransform="translate(13.927091,16.573387)"
+   gradientUnits="userSpaceOnUse"
+   id="linearGradient3475"
+   xlink:href="#linearGradient3587-6-5-26"
+   inkscape:collect="always" /><linearGradient
+   id="linearGradient3587-6-5-26"><stop
+     id="stop3589-9-2-45"
+     style="stop-color:#000000;stop-opacity:1"
+     offset="0" /><stop
+     id="stop3591-7-4-20"
+     style="stop-color:#363636;stop-opacity:1"
+     offset="1" /></linearGradient><linearGradient
+   y2="18.967093"
+   x2="-2.4040222"
+   y1="4.4573336"
+   x1="-2.4040222"
+   gradientTransform="translate(13.927091,16.573387)"
+   gradientUnits="userSpaceOnUse"
+   id="linearGradient7590"
+   xlink:href="#linearGradient3587-6-5-26"
+   inkscape:collect="always" /><linearGradient
+   inkscape:collect="always"
+   xlink:href="#linearGradient3587-6-5-26"
+   id="linearGradient7614"
+   gradientUnits="userSpaceOnUse"
+   gradientTransform="translate(15.071012,45.700897)"
+   x1="-2.4040222"
+   y1="4.4573336"
+   x2="-2.4040222"
+   y2="18.967093" /><linearGradient
+   inkscape:collect="always"
+   xlink:href="#linearGradient3587-6-5-26"
+   id="linearGradient7623"
+   x1="58.866638"
+   y1="24.928007"
+   x2="58.866638"
+   y2="93.882034"
+   gradientUnits="userSpaceOnUse"
+   gradientTransform="matrix(0.25,0,0,0.25,0,0.500024)" /></defs><sodipodi:namedview
+   pagecolor="#ffffff"
+   bordercolor="#666666"
+   borderopacity="1"
+   objecttolerance="10"
+   gridtolerance="10"
+   guidetolerance="10"
+   inkscape:pageopacity="0"
+   inkscape:pageshadow="2"
+   inkscape:window-width="1280"
+   inkscape:window-height="774"
+   id="namedview323"
+   showgrid="true"
+   inkscape:zoom="8"
+   inkscape:cx="32.984032"
+   inkscape:cy="11.601392"
+   inkscape:window-x="0"
+   inkscape:window-y="26"
+   inkscape:window-maximized="1"
+   inkscape:current-layer="Layer_1"
+   units="px"
+   fit-margin-top="0"
+   fit-margin-left="0"
+   fit-margin-right="0"
+   fit-margin-bottom="0"
+   showguides="true"
+   inkscape:guide-bbox="true"><inkscape:grid
+     type="xygrid"
+     id="grid3152"
+     empspacing="2"
+     visible="true"
+     enabled="true"
+     snapvisiblegridlinesonly="true"
+     dotted="false" /></sodipodi:namedview>
+<pattern
+   y="565.223"
+   width="69"
+   height="69"
+   patternUnits="userSpaceOnUse"
+   id="Polka_Dot_Pattern"
+   viewBox="2.125 -70.896 69 69"
+   overflow="visible">
+	<g
+   id="g4">
+		<polygon
+   fill="none"
+   points="71.125,-1.896 2.125,-1.896 2.125,-70.896 71.125,-70.896   "
+   id="polygon6" />
+		<polygon
+   fill="#F6BB60"
+   points="71.125,-1.896 2.125,-1.896 2.125,-70.896 71.125,-70.896   "
+   id="polygon8" />
+		<g
+   id="g10">
+			<path
+   fill="#FFFFFF"
+   d="M61.772-71.653c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128     c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161     c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631     c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45     c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221     c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337     c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207     c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169     c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path12" />
+			<path
+   fill="#FFFFFF"
+   d="M54.105-71.653c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128     c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161     c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631     c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45     c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221     c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337     c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207     c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169     c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path14" />
+			<path
+   fill="#FFFFFF"
+   d="M46.439-71.653c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128     c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161     c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631     c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45     c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221     c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337     c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207     c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169     c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path16" />
+			<path
+   fill="#FFFFFF"
+   d="M38.772-71.653c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128     c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161     c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631     c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45     c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221     c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337     c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207     c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169     c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path18" />
+			<path
+   fill="#FFFFFF"
+   d="M31.105-71.653c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128     c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161     c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631     c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45     c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221     c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337     c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207     c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169     c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path20" />
+			<path
+   fill="#FFFFFF"
+   d="M23.439-71.653c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128     c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161     c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631     c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45     c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221     c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337     c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207     c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169     c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path22" />
+			<path
+   fill="#FFFFFF"
+   d="M15.772-71.653c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128     c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161     c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631     c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45     c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221     c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337     c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207     c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169     c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path24" />
+			<path
+   fill="#FFFFFF"
+   d="M8.105-71.653c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128     c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161     c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631     c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45     c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221     c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337     c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207     c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169     c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path26" />
+			<path
+   fill="#FFFFFF"
+   d="M0.439-71.653c0.018,0.072,0.008,0.127-0.026,0.19C0.361-71.362,0.3-71.4,0.248-71.335     c-0.051,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161     c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631     c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45     c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.07,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221     c0.038-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.051-0.12-0.064-0.187c-0.021-0.114,0.002-0.224,0-0.337     c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207     c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.215,0.124-0.215,0.224c0.002,0.115,0.005,0.051,0.012,0.169     c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path28" />
+		</g>
+		<g
+   id="g30">
+			<path
+   fill="#FFFFFF"
+   d="M69.439-71.653c0.018,0.072,0.008,0.127-0.026,0.19c-0.052,0.101-0.113,0.062-0.165,0.128     c-0.051,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161     c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631     c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45     c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.07,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221     c0.038-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.051-0.12-0.064-0.187c-0.021-0.114,0.002-0.224,0-0.337     c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207     c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.215,0.124-0.215,0.224c0.002,0.115,0.005,0.051,0.012,0.169     c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path32" />
+		</g>
+		<path
+   fill="#FFFFFF"
+   d="M0.495-71.653c0.018,0.072,0.008,0.127-0.026,0.19c-0.052,0.101-0.113,0.062-0.165,0.128    c-0.051,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161    c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631    c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45    c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.07,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221    c0.038-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.051-0.12-0.064-0.187c-0.021-0.114,0.002-0.224,0-0.337    c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207    c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.215,0.124-0.215,0.224C0.5-71.68,0.503-71.744,0.51-71.626    c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path34" />
+		<g
+   id="g36">
+			<g
+   id="g38">
+				<path
+   fill="#FFFFFF"
+   d="M69.439-64.001c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path40" />
+				<path
+   fill="#FFFFFF"
+   d="M61.778-64.001c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path42" />
+				<path
+   fill="#FFFFFF"
+   d="M54.118-64.001c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path44" />
+				<path
+   fill="#FFFFFF"
+   d="M46.458-64.001c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path46" />
+				<path
+   fill="#FFFFFF"
+   d="M38.797-64.001c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path48" />
+				<path
+   fill="#FFFFFF"
+   d="M31.137-64.001c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path50" />
+				<path
+   fill="#FFFFFF"
+   d="M23.477-64.001c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path52" />
+				<path
+   fill="#FFFFFF"
+   d="M15.816-64.001c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path54" />
+				<path
+   fill="#FFFFFF"
+   d="M8.156-64.001c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path56" />
+				<path
+   fill="#FFFFFF"
+   d="M0.495-64.001c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143C2-61.45,2.217-61.397,2.391-61.46c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path58" />
+			</g>
+			<g
+   id="g60">
+				<path
+   fill="#FFFFFF"
+   d="M69.439-56.348c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path62" />
+				<path
+   fill="#FFFFFF"
+   d="M61.778-56.348c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path64" />
+				<path
+   fill="#FFFFFF"
+   d="M54.118-56.348c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path66" />
+				<path
+   fill="#FFFFFF"
+   d="M46.458-56.348c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path68" />
+				<path
+   fill="#FFFFFF"
+   d="M38.797-56.348c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path70" />
+				<path
+   fill="#FFFFFF"
+   d="M31.137-56.348c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path72" />
+				<path
+   fill="#FFFFFF"
+   d="M23.477-56.348c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path74" />
+				<path
+   fill="#FFFFFF"
+   d="M15.816-56.348c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path76" />
+				<path
+   fill="#FFFFFF"
+   d="M8.156-56.348c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path78" />
+				<path
+   fill="#FFFFFF"
+   d="M0.495-56.348c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224C0.5-56.374,0.503-56.438,0.51-56.32      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path80" />
+			</g>
+			<g
+   id="g82">
+				<path
+   fill="#FFFFFF"
+   d="M69.439-48.695c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path84" />
+				<path
+   fill="#FFFFFF"
+   d="M61.778-48.695c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path86" />
+				<path
+   fill="#FFFFFF"
+   d="M54.118-48.695c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path88" />
+				<path
+   fill="#FFFFFF"
+   d="M46.458-48.695c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path90" />
+				<path
+   fill="#FFFFFF"
+   d="M38.797-48.695c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path92" />
+				<path
+   fill="#FFFFFF"
+   d="M31.137-48.695c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path94" />
+				<path
+   fill="#FFFFFF"
+   d="M23.477-48.695c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path96" />
+				<path
+   fill="#FFFFFF"
+   d="M15.816-48.695c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path98" />
+				<path
+   fill="#FFFFFF"
+   d="M8.156-48.695c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path100" />
+				<path
+   fill="#FFFFFF"
+   d="M0.495-48.695c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path102" />
+			</g>
+			<g
+   id="g104">
+				<path
+   fill="#FFFFFF"
+   d="M69.439-41.042c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path106" />
+				<path
+   fill="#FFFFFF"
+   d="M61.778-41.042c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path108" />
+				<path
+   fill="#FFFFFF"
+   d="M54.118-41.042c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path110" />
+				<path
+   fill="#FFFFFF"
+   d="M46.458-41.042c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path112" />
+				<path
+   fill="#FFFFFF"
+   d="M38.797-41.042c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path114" />
+				<path
+   fill="#FFFFFF"
+   d="M31.137-41.042c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path116" />
+				<path
+   fill="#FFFFFF"
+   d="M23.477-41.042c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path118" />
+				<path
+   fill="#FFFFFF"
+   d="M15.816-41.042c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path120" />
+				<path
+   fill="#FFFFFF"
+   d="M8.156-41.042c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      C8.15-41.004,8.149-41.02,8.14-41.04"
+   id="path122" />
+				<path
+   fill="#FFFFFF"
+   d="M0.495-41.042c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path124" />
+			</g>
+			<g
+   id="g126">
+				<path
+   fill="#FFFFFF"
+   d="M69.439-33.39c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path128" />
+				<path
+   fill="#FFFFFF"
+   d="M61.778-33.39c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path130" />
+				<path
+   fill="#FFFFFF"
+   d="M54.118-33.39c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path132" />
+				<path
+   fill="#FFFFFF"
+   d="M46.458-33.39c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path134" />
+				<path
+   fill="#FFFFFF"
+   d="M38.797-33.39c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path136" />
+				<path
+   fill="#FFFFFF"
+   d="M31.137-33.39c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path138" />
+				<path
+   fill="#FFFFFF"
+   d="M23.477-33.39c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path140" />
+				<path
+   fill="#FFFFFF"
+   d="M15.816-33.39c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path142" />
+				<path
+   fill="#FFFFFF"
+   d="M8.156-33.39c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path144" />
+				<path
+   fill="#FFFFFF"
+   d="M0.495-33.39c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224C0.5-33.416,0.503-33.48,0.51-33.362      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path146" />
+			</g>
+			<g
+   id="g148">
+				<path
+   fill="#FFFFFF"
+   d="M69.439-25.736c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path150" />
+				<path
+   fill="#FFFFFF"
+   d="M61.778-25.736c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path152" />
+				<path
+   fill="#FFFFFF"
+   d="M54.118-25.736c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path154" />
+				<path
+   fill="#FFFFFF"
+   d="M46.458-25.736c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path156" />
+				<path
+   fill="#FFFFFF"
+   d="M38.797-25.736c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path158" />
+				<path
+   fill="#FFFFFF"
+   d="M31.137-25.736c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path160" />
+				<path
+   fill="#FFFFFF"
+   d="M23.477-25.736c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path162" />
+				<path
+   fill="#FFFFFF"
+   d="M15.816-25.736c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path164" />
+				<path
+   fill="#FFFFFF"
+   d="M8.156-25.736c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path166" />
+				<path
+   fill="#FFFFFF"
+   d="M0.495-25.736c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path168" />
+			</g>
+			<g
+   id="g170">
+				<path
+   fill="#FFFFFF"
+   d="M69.439-18.084c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path172" />
+				<path
+   fill="#FFFFFF"
+   d="M61.778-18.084c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path174" />
+				<path
+   fill="#FFFFFF"
+   d="M54.118-18.084c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path176" />
+				<path
+   fill="#FFFFFF"
+   d="M46.458-18.084c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path178" />
+				<path
+   fill="#FFFFFF"
+   d="M38.797-18.084c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path180" />
+				<path
+   fill="#FFFFFF"
+   d="M31.137-18.084c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path182" />
+				<path
+   fill="#FFFFFF"
+   d="M23.477-18.084c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path184" />
+				<path
+   fill="#FFFFFF"
+   d="M15.816-18.084c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path186" />
+				<path
+   fill="#FFFFFF"
+   d="M8.156-18.084c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path188" />
+				<path
+   fill="#FFFFFF"
+   d="M0.495-18.084c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224C0.5-18.11,0.503-18.175,0.51-18.057      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path190" />
+			</g>
+			<g
+   id="g192">
+				<path
+   fill="#FFFFFF"
+   d="M69.439-10.431c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362C69-9.692,69.159-9.523,69.154-9.4c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path194" />
+				<path
+   fill="#FFFFFF"
+   d="M61.778-10.431c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path196" />
+				<path
+   fill="#FFFFFF"
+   d="M54.118-10.431c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path198" />
+				<path
+   fill="#FFFFFF"
+   d="M46.458-10.431c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path200" />
+				<path
+   fill="#FFFFFF"
+   d="M38.797-10.431c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path202" />
+				<path
+   fill="#FFFFFF"
+   d="M31.137-10.431c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path204" />
+				<path
+   fill="#FFFFFF"
+   d="M23.477-10.431c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path206" />
+				<path
+   fill="#FFFFFF"
+   d="M15.816-10.431c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053C17.933-7.969,17.839-8.227,18-8.34      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path208" />
+				<path
+   fill="#FFFFFF"
+   d="M8.156-10.431c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      C7.915-10.05,7.866-9.836,7.886-9.75C7.717-9.692,7.876-9.523,7.871-9.4C7.868-9.351,7.83-9.295,7.826-9.239      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      C9.114-7.652,9.321-7.799,9.48-7.837c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path210" />
+				<path
+   fill="#FFFFFF"
+   d="M0.495-10.431c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      C0.254-10.05,0.205-9.836,0.225-9.75C0.056-9.692,0.215-9.523,0.21-9.4c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37C0.33-8.671,0.501-8.456,0.668-8.325c0.19,0.148,0.365,0.572,0.608,0.631      C1.454-7.652,1.66-7.799,1.819-7.837C2-7.88,2.217-7.827,2.391-7.89c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46C3.477-8.933,3.471-8.995,3.5-9.071      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path212" />
+			</g>
+		</g>
+		<g
+   id="g214">
+			<path
+   fill="#FFFFFF"
+   d="M69.439-2.778c0.018,0.072,0.008,0.127-0.026,0.19C69.361-2.487,69.3-2.525,69.248-2.46     c-0.051,0.062-0.099,0.276-0.079,0.362C69-2.04,69.159-1.871,69.154-1.748c-0.002,0.05-0.041,0.105-0.045,0.161     c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631     C70.397,0,70.604-0.146,70.763-0.185c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45     c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.07,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221     c0.038-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.051-0.12-0.064-0.187c-0.021-0.114,0.002-0.224,0-0.337     c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207     c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.215,0.124-0.215,0.224c0.002,0.115,0.005,0.051,0.012,0.169     c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path216" />
+			<path
+   fill="#FFFFFF"
+   d="M61.778-2.778c0.018,0.072,0.007,0.127-0.026,0.19C61.7-2.487,61.64-2.525,61.587-2.46     c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161     c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631     C62.737,0,62.943-0.146,63.103-0.185c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45     c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221     c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337     c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207     c-0.17,0.088-0.139,0.166-0.318,0.224C61.915-3.117,61.78-3.02,61.781-2.92c0.001,0.115,0.005,0.051,0.012,0.169     c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path218" />
+			<path
+   fill="#FFFFFF"
+   d="M54.118-2.778c0.018,0.072,0.007,0.127-0.026,0.19C54.04-2.487,53.98-2.525,53.927-2.46     c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161     c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631     C55.077,0,55.283-0.146,55.442-0.185c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45     c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221     c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337     c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207     c-0.17,0.088-0.139,0.166-0.318,0.224C54.255-3.117,54.12-3.02,54.121-2.92c0.001,0.115,0.005,0.051,0.012,0.169     c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path220" />
+			<path
+   fill="#FFFFFF"
+   d="M46.458-2.778c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128     c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161     c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631     C47.416,0,47.623-0.146,47.782-0.185c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45     c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221     c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337     c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207     c-0.17,0.088-0.139,0.166-0.318,0.224C46.594-3.117,46.459-3.02,46.46-2.92c0.001,0.115,0.005,0.051,0.012,0.169     c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path222" />
+			<path
+   fill="#FFFFFF"
+   d="M38.797-2.778c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128     c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161     c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631     C39.756,0,39.962-0.146,40.122-0.185c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45     c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221     c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337     c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207     c-0.17,0.088-0.139,0.166-0.318,0.224C38.934-3.117,38.799-3.02,38.8-2.92c0.001,0.115,0.005,0.051,0.012,0.169     c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path224" />
+			<path
+   fill="#FFFFFF"
+   d="M31.137-2.778c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128     c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161     c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631     C32.095,0,32.302-0.146,32.461-0.185c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45     c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221     c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337     c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207     c-0.17,0.088-0.139,0.166-0.318,0.224C31.273-3.117,31.139-3.02,31.14-2.92c0.001,0.115,0.005,0.051,0.012,0.169     c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path226" />
+			<path
+   fill="#FFFFFF"
+   d="M23.477-2.778c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128     c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161     c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631     C24.435,0,24.642-0.146,24.801-0.185c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45     c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221     c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337     c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207     c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169     c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path228" />
+			<path
+   fill="#FFFFFF"
+   d="M15.816-2.778c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128     c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161     c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631     C16.774,0,16.981-0.146,17.14-0.185c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45     c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221     c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337     c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207     c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169     C15.81-2.74,15.809-2.756,15.8-2.776"
+   id="path230" />
+			<path
+   fill="#FFFFFF"
+   d="M8.156-2.778c0.018,0.072,0.007,0.127-0.026,0.19C8.077-2.487,8.018-2.525,7.965-2.46     c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35C7.868-1.698,7.83-1.643,7.826-1.587     c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631     C9.114,0,9.321-0.146,9.48-0.185c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45     c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221     c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337     c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789C8.954-3.54,8.847-3.448,8.692-3.367     c-0.17,0.088-0.139,0.166-0.318,0.224C8.292-3.117,8.158-3.02,8.159-2.92C8.16-2.805,8.164-2.869,8.17-2.751     C8.15-2.74,8.149-2.756,8.14-2.776"
+   id="path232" />
+			<path
+   fill="#FFFFFF"
+   d="M0.495-2.778c0.018,0.072,0.008,0.127-0.026,0.19C0.417-2.487,0.356-2.525,0.304-2.46     C0.253-2.397,0.205-2.184,0.225-2.098C0.056-2.04,0.215-1.871,0.21-1.748c-0.002,0.05-0.041,0.105-0.045,0.161     c-0.01,0.119,0.017,0.266,0.068,0.37C0.33-1.019,0.501-0.804,0.668-0.673c0.19,0.148,0.365,0.572,0.608,0.631     C1.454,0,1.66-0.146,1.819-0.185C2-0.228,2.217-0.175,2.391-0.237c0.222-0.079,0.127-0.337,0.288-0.45     c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.07,0.339-0.263,0.376-0.46C3.477-1.28,3.471-1.343,3.5-1.419     c0.038-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.051-0.12-0.064-0.187c-0.021-0.114,0.002-0.224,0-0.337     c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789C1.293-3.54,1.187-3.448,1.031-3.367     c-0.17,0.088-0.139,0.166-0.318,0.224C0.632-3.117,0.498-3.02,0.498-2.92C0.5-2.805,0.503-2.869,0.51-2.751     C0.489-2.74,0.488-2.756,0.479-2.776"
+   id="path234" />
+		</g>
+	</g>
+</pattern>
+
+<path
+   sodipodi:nodetypes="sscscsscscscscccscscccsssssssscscsccsscscssscsscscsccccscssccsssccs"
+   inkscape:connector-curvature="0"
+   inkscape:export-ydpi="90"
+   inkscape:export-xdpi="90"
+   inkscape:export-filename="/home/user/owncloud/core/img/logo.png"
+   id="path7625"
+   d="m 14.488658,7.6997589 c -2.381798,0 -4.30607,1.92427 -4.30607,4.3060701 0,0.98178 0.32692,1.88539 0.878102,2.60897 1.195708,-1.38395 2.960465,-2.2628 4.93087,-2.2628 0.964013,0 1.878155,0.21467 2.70185,0.59103 0.06669,-0.3016 0.101318,-0.61527 0.101318,-0.9372 0,-2.3818001 -1.92427,-4.3060701 -4.30607,-4.3060701 z m -5.6232205,1.99261 c -1.240375,0 -2.2374675,1.0055301 -2.2374675,2.2459101 0,0.4016 0.10361,0.78106 0.28707,1.10607 0.74849,-0.42223 1.61383,-0.66702 2.5329825,-0.66702 0.088705,0 0.1741425,0.004 0.2617425,0.008 -0.00993,-0.1253 -0.016875,-0.25124 -0.016875,-0.3795 0,-0.69087 0.15005,-1.34819 0.41372,-1.94196 C 9.7516025,9.8258189 9.3262675,9.6923689 8.86545,9.6923689 z M 19.487078,11.237489 c -0.09164,0 -0.179965,0.0113 -0.270185,0.0169 0.03903,0.24606 0.06755,0.49451 0.06755,0.75145 0,0.39985 -0.05085,0.78569 -0.143535,1.15673 1.08665,0.60136 1.989072,1.50116 2.583642,2.59208 0.616705,-0.32106 1.30466,-0.52521 2.03483,-0.57414 -0.18818,-2.20687 -2.016472,-3.94301 -4.272297,-3.94301 z m -3.495518,1.60422 c -3.33285,0 -6.0284975,2.69542 -6.0284975,6.0285 0,3.33272 2.6955105,6.0285 6.0284975,6.0285 3.33299,0 6.0285,-2.69579 6.0285,-6.0285 0,-3.33307 -2.695647,-6.0285 -6.0285,-6.0285 z m -6.5435375,0.0253 c -2.58566,0 -4.6775725,2.09191 -4.6775725,4.67757 0,1.52213 0.7252325,2.8696 1.8490775,3.72349 0.47379,-0.91381 1.425375,-1.53668 2.5245375,-1.53668 0.132845,0 0.260355,0.0161 0.38839,0.0338 -0.040192,-0.29242 -0.0591,-0.59159 -0.0591,-0.89499 0,-1.4506 0.47218,-2.79202 1.274933,-3.87546 -0.48052,-0.60129 -0.8244005,-1.32376 -0.970978,-2.11082 -0.1086325,-0.008 -0.218725,-0.0169 -0.3292875,-0.0169 z m 14.6575255,2.78628 c -0.785125,0 -1.520585,0.20045 -2.169923,0.54037 0.368715,0.81673 0.574143,1.72291 0.574143,2.67652 0,1.78555 -0.71789,3.406849 -1.88285,4.584699 0.85582,0.95013 2.097512,1.54512 3.47863,1.54512 2.58566,0 4.677575,-2.091919 4.677575,-4.677579 0,-2.585661 -2.091915,-4.66913 -4.677575,-4.66913 z M 4.3145118,16.269679 C 1.9326443,16.269679 0,18.185439 0,20.567309 c 0,2.38187 1.9326443,4.31451 4.3145118,4.31451 0.9065732,0 1.7463732,-0.282451 2.4401082,-0.75989 -0.286665,-0.44545 -0.4559375,-0.978001 -0.4559375,-1.54512 0,-0.294361 0.043432,-0.57714 0.1266475,-0.84433 -1.29874,-0.93858 -2.1445912,-2.46595 -2.1445912,-4.18787 0,-0.4375 0.057653,-0.86054 0.1604237,-1.26649 -0.042658,-0.001 -0.083686,-0.008 -0.1266507,-0.008 z m 25.3213812,3.69816 c -0.127065,0 -0.250018,0.0145 -0.371505,0.0338 0.0067,0.1074 0.0084,0.21176 0.0084,0.32084 0,1.37337 -0.541883,2.61988 -1.41847,3.54618 0.43125,0.50149 1.064697,0.819 1.781532,0.819 1.30572,0 2.364118,-1.04996 2.364118,-2.35568 0,-1.30572 -1.058398,-2.36411 -2.364118,-2.36411 z m -20.491828,0.25329 c -1.3056525,0 -2.3556725,1.05002 -2.3556725,2.35568 0,1.30565 1.05002,2.36411 2.3556725,2.36411 1.0008,0 1.850283,-0.62448 2.195253,-1.5029 -0.84174,-0.8573 -1.446688,-1.951 -1.7139855,-3.16623 C 9.468915,20.239449 9.31015,20.221129 9.144065,20.221129 z"
+   style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;baseline-shift:baseline;opacity:0.2;color:#000000;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:4;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Sans;-inkscape-font-specification:Sans" /><path
+   style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;baseline-shift:baseline;opacity:0.8;color:#000000;fill:url(#linearGradient7623);fill-opacity:1;stroke:none;stroke-width:4;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Sans;-inkscape-font-specification:Sans"
+   d="m 14.488658,6.699758 c -2.381798,0 -4.30607,1.92427 -4.30607,4.306071 0,0.98178 0.32692,1.88539 0.878102,2.60897 1.195708,-1.38395 2.960465,-2.2628 4.93087,-2.2628 0.964013,0 1.878155,0.21467 2.70185,0.59103 0.06669,-0.3016 0.101318,-0.61527 0.101318,-0.9372 0,-2.381801 -1.92427,-4.306071 -4.30607,-4.306071 z m -5.6232205,1.99261 c -1.240375,0 -2.2374675,1.00554 -2.2374675,2.245911 0,0.4016 0.10361,0.78106 0.28707,1.10607 0.74849,-0.42223 1.61383,-0.66702 2.5329825,-0.66702 0.088705,0 0.1741425,0.004 0.2617425,0.008 -0.00993,-0.1253 -0.016875,-0.25124 -0.016875,-0.3795 0,-0.69086 0.15005,-1.348191 0.41372,-1.941961 -0.3550075,-0.23805 -0.7803425,-0.3715 -1.24116,-0.3715 z m 10.6216405,1.545121 c -0.09164,0 -0.179965,0.0113 -0.270185,0.0169 0.03903,0.24606 0.06755,0.49452 0.06755,0.75145 0,0.39985 -0.05085,0.78569 -0.143535,1.15673 1.08665,0.60137 1.989072,1.50116 2.583642,2.59208 0.616705,-0.32106 1.30466,-0.5252 2.03483,-0.57414 -0.18818,-2.20687 -2.016472,-3.94301 -4.272297,-3.94301 z m -3.495518,1.60422 c -3.33285,0 -6.0284975,2.69542 -6.0284975,6.0285 0,3.33272 2.6955105,6.0285 6.0284975,6.0285 3.33299,0 6.0285,-2.69579 6.0285,-6.0285 0,-3.33307 -2.695647,-6.0285 -6.0285,-6.0285 z m -6.5435375,0.0253 c -2.58566,0 -4.6775725,2.09191 -4.6775725,4.67758 0,1.52212 0.7252325,2.86959 1.8490775,3.72348 0.47379,-0.913811 1.425375,-1.53668 2.5245375,-1.53668 0.132845,0 0.260355,0.0161 0.38839,0.0338 -0.040192,-0.29242 -0.0591,-0.59159 -0.0591,-0.89499 0,-1.4506 0.47218,-2.792019 1.274933,-3.875459 -0.48052,-0.60129 -0.8244005,-1.32376 -0.970978,-2.11082 -0.1086325,-0.008 -0.218725,-0.0169 -0.3292875,-0.0169 z m 14.6575255,2.78628 c -0.785125,0 -1.520585,0.20045 -2.169923,0.54037 0.368715,0.81673 0.574143,1.72291 0.574143,2.67652 0,1.78555 -0.71789,3.406849 -1.88285,4.584699 0.85582,0.95013 2.097512,1.54512 3.47863,1.54512 2.58566,0 4.677575,-2.091919 4.677575,-4.677579 0,-2.585661 -2.091915,-4.66913 -4.677575,-4.66913 z M 4.3145118,15.269679 C 1.9326443,15.269679 0,17.185439 0,19.567309 c 0,2.38187 1.9326443,4.31451 4.3145118,4.31451 0.9065732,0 1.7463732,-0.282451 2.4401082,-0.75989 -0.286665,-0.44545 -0.4559375,-0.978001 -0.4559375,-1.54512 0,-0.294361 0.043432,-0.57714 0.1266475,-0.84433 -1.29874,-0.93858 -2.1445912,-2.46595 -2.1445912,-4.18786 0,-0.43751 0.057653,-0.86055 0.1604237,-1.2665 -0.042658,-10e-4 -0.083686,-0.008 -0.1266507,-0.008 z m 25.3213812,3.69816 c -0.127065,0 -0.250018,0.0145 -0.371505,0.0338 0.0067,0.1074 0.0084,0.21176 0.0084,0.32084 0,1.37337 -0.541883,2.61988 -1.41847,3.54618 0.43125,0.50149 1.064697,0.819 1.781532,0.819 1.30572,0 2.364118,-1.04996 2.364118,-2.35568 0,-1.30572 -1.058398,-2.36411 -2.364118,-2.36411 z m -20.491828,0.25329 c -1.3056525,0 -2.3556725,1.05002 -2.3556725,2.35568 0,1.30565 1.05002,2.36411 2.3556725,2.36411 1.0008,0 1.850283,-0.62448 2.195253,-1.5029 -0.84174,-0.8573 -1.446688,-1.951 -1.7139855,-3.16623 C 9.468915,19.239449 9.31015,19.221129 9.144065,19.221129 z"
+   id="circle238"
+   inkscape:export-filename="/home/user/owncloud/core/img/logo.png"
+   inkscape:export-xdpi="90"
+   inkscape:export-ydpi="90"
+   inkscape:connector-curvature="0"
+   sodipodi:nodetypes="sscscsscscscscccscscccsssssssscscsccsscscssscsscscsccccscssccsssccs" />
+
+
+
+
+
+
+
+
+
+
+</svg>
\ No newline at end of file
diff --git a/core/img/logo-inverted.png b/core/img/logo-inverted.png
new file mode 100644
index 0000000000000000000000000000000000000000..d9fd119dc1883d2c7d384ede0fed4ceb58f1898d
Binary files /dev/null and b/core/img/logo-inverted.png differ
diff --git a/core/img/logo-inverted.svg b/core/img/logo-inverted.svg
index 427531bc7a9dc2843d673304dfa2e6f0ff4c7eac..9ac167cc41f0a19ec81ad892773433ebf33a220b 100644
--- a/core/img/logo-inverted.svg
+++ b/core/img/logo-inverted.svg
@@ -14,94 +14,97 @@
    id="Layer_1"
    x="0px"
    y="0px"
-   width="595.275px"
-   height="311.111px"
-   viewBox="0 0 595.275 311.111"
+   width="250.00002"
+   height="118.22803"
+   viewBox="0 0 250.00001 118.22802"
    enable-background="new 0 0 595.275 311.111"
    xml:space="preserve"
-   inkscape:version="0.48.1 r9760"
-   sodipodi:docname="logo inverted.svg"><metadata
+   inkscape:version="0.48.2 r9819"
+   sodipodi:docname="logo.svg"
+   inkscape:export-filename="/home/user/owncloud/core/img/logo-sticker.png"
+   inkscape:export-xdpi="300.00223"
+   inkscape:export-ydpi="300.00223"><metadata
    id="metadata327"><rdf:RDF><cc:Work
        rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
-         rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title /></cc:Work></rdf:RDF></metadata><defs
+         rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
    id="defs325"><linearGradient
    inkscape:collect="always"
    xlink:href="#SVGID_1_"
    id="linearGradient3353"
    gradientUnits="userSpaceOnUse"
-   x1="288.4941"
-   y1="55.8882"
-   x2="288.4941"
-   y2="339.2219" /><linearGradient
+   x1="288.49411"
+   y1="55.888199"
+   x2="288.49411"
+   y2="339.22189" /><linearGradient
    inkscape:collect="always"
    xlink:href="#SVGID_2_"
    id="linearGradient3355"
    gradientUnits="userSpaceOnUse"
    x1="251.2114"
-   y1="55.8882"
+   y1="55.888199"
    x2="251.2114"
-   y2="339.2216" /><linearGradient
+   y2="339.22159" /><linearGradient
    inkscape:collect="always"
    xlink:href="#SVGID_3_"
    id="linearGradient3357"
    gradientUnits="userSpaceOnUse"
-   x1="293.2246"
-   y1="55.8882"
-   x2="293.2246"
-   y2="339.2217" /><linearGradient
+   x1="293.22461"
+   y1="55.888199"
+   x2="293.22461"
+   y2="339.22171" /><linearGradient
    inkscape:collect="always"
    xlink:href="#SVGID_4_"
    id="linearGradient3359"
    gradientUnits="userSpaceOnUse"
-   x1="375.334"
-   y1="55.8882"
-   x2="375.334"
-   y2="339.2216" /><linearGradient
+   x1="375.33401"
+   y1="55.888199"
+   x2="375.33401"
+   y2="339.22159" /><linearGradient
    inkscape:collect="always"
    xlink:href="#SVGID_5_"
    id="linearGradient3361"
    gradientUnits="userSpaceOnUse"
-   x1="334.4941"
-   y1="55.8882"
-   x2="334.4941"
-   y2="339.2216" /><linearGradient
+   x1="334.49411"
+   y1="55.888199"
+   x2="334.49411"
+   y2="339.22159" /><linearGradient
    inkscape:collect="always"
    xlink:href="#SVGID_6_"
    id="linearGradient3363"
    gradientUnits="userSpaceOnUse"
-   x1="458.4268"
+   x1="458.42679"
    y1="55.8867"
-   x2="458.4268"
+   x2="458.42679"
    y2="339.2236" /><linearGradient
    inkscape:collect="always"
    xlink:href="#SVGID_7_"
    id="linearGradient3365"
    gradientUnits="userSpaceOnUse"
-   x1="413.1631"
-   y1="55.8882"
-   x2="413.1631"
-   y2="339.2213" /><linearGradient
+   x1="413.16309"
+   y1="55.888199"
+   x2="413.16309"
+   y2="339.22131" /><linearGradient
    inkscape:collect="always"
    xlink:href="#SVGID_8_"
    id="linearGradient3367"
    gradientUnits="userSpaceOnUse"
-   x1="290.7617"
+   x1="290.76169"
    y1="55.8867"
-   x2="290.7617"
+   x2="290.76169"
    y2="339.2236" /><linearGradient
    inkscape:collect="always"
    xlink:href="#SVGID_9_"
    id="linearGradient3369"
    gradientUnits="userSpaceOnUse"
-   x1="346.7734"
-   y1="55.8882"
-   x2="346.7734"
-   y2="339.2212" />
+   x1="346.77341"
+   y1="55.888199"
+   x2="346.77341"
+   y2="339.22119" />
 	<linearGradient
-   y2="339.2219"
-   x2="288.4941"
-   y1="55.8882"
-   x1="288.4941"
+   y2="339.22189"
+   x2="288.49411"
+   y1="55.888199"
+   x1="288.49411"
    gradientUnits="userSpaceOnUse"
    id="SVGID_1_">
 		<stop
@@ -115,9 +118,9 @@
 	</linearGradient>
 	
 	<linearGradient
-   y2="339.2216"
+   y2="339.22159"
    x2="251.2114"
-   y1="55.8882"
+   y1="55.888199"
    x1="251.2114"
    gradientUnits="userSpaceOnUse"
    id="SVGID_2_">
@@ -132,10 +135,10 @@
 	</linearGradient>
 	
 	<linearGradient
-   y2="339.2217"
-   x2="293.2246"
-   y1="55.8882"
-   x1="293.2246"
+   y2="339.22171"
+   x2="293.22461"
+   y1="55.888199"
+   x1="293.22461"
    gradientUnits="userSpaceOnUse"
    id="SVGID_3_">
 		<stop
@@ -149,10 +152,10 @@
 	</linearGradient>
 	
 	<linearGradient
-   y2="339.2216"
-   x2="375.334"
-   y1="55.8882"
-   x1="375.334"
+   y2="339.22159"
+   x2="375.33401"
+   y1="55.888199"
+   x1="375.33401"
    gradientUnits="userSpaceOnUse"
    id="SVGID_4_">
 		<stop
@@ -166,10 +169,10 @@
 	</linearGradient>
 	
 	<linearGradient
-   y2="339.2216"
-   x2="334.4941"
-   y1="55.8882"
-   x1="334.4941"
+   y2="339.22159"
+   x2="334.49411"
+   y1="55.888199"
+   x1="334.49411"
    gradientUnits="userSpaceOnUse"
    id="SVGID_5_">
 		<stop
@@ -184,9 +187,9 @@
 	
 	<linearGradient
    y2="339.2236"
-   x2="458.4268"
+   x2="458.42679"
    y1="55.8867"
-   x1="458.4268"
+   x1="458.42679"
    gradientUnits="userSpaceOnUse"
    id="SVGID_6_">
 		<stop
@@ -200,10 +203,10 @@
 	</linearGradient>
 	
 	<linearGradient
-   y2="339.2213"
-   x2="413.1631"
-   y1="55.8882"
-   x1="413.1631"
+   y2="339.22131"
+   x2="413.16309"
+   y1="55.888199"
+   x1="413.16309"
    gradientUnits="userSpaceOnUse"
    id="SVGID_7_">
 		<stop
@@ -218,9 +221,9 @@
 	
 	<linearGradient
    y2="339.2236"
-   x2="290.7617"
+   x2="290.76169"
    y1="55.8867"
-   x1="290.7617"
+   x1="290.76169"
    gradientUnits="userSpaceOnUse"
    id="SVGID_8_">
 		<stop
@@ -234,10 +237,10 @@
 	</linearGradient>
 	
 	<linearGradient
-   y2="339.2212"
-   x2="346.7734"
-   y1="55.8882"
-   x1="346.7734"
+   y2="339.22119"
+   x2="346.77341"
+   y1="55.888199"
+   x1="346.77341"
    gradientUnits="userSpaceOnUse"
    id="SVGID_9_">
 		<stop
@@ -260,16 +263,23 @@
    inkscape:pageopacity="0"
    inkscape:pageshadow="2"
    inkscape:window-width="1280"
-   inkscape:window-height="776"
+   inkscape:window-height="774"
    id="namedview323"
    showgrid="false"
-   inkscape:zoom="0.85170716"
-   inkscape:cx="222.31049"
-   inkscape:cy="155.5555"
+   inkscape:zoom="1"
+   inkscape:cx="-43.42615"
+   inkscape:cy="55.236805"
    inkscape:window-x="0"
-   inkscape:window-y="24"
+   inkscape:window-y="26"
    inkscape:window-maximized="1"
-   inkscape:current-layer="Layer_1" />
+   inkscape:current-layer="Layer_1"
+   units="mm"
+   fit-margin-top="0"
+   fit-margin-left="0"
+   fit-margin-right="0"
+   fit-margin-bottom="0"
+   showguides="true"
+   inkscape:guide-bbox="true" />
 <pattern
    y="565.223"
    width="69"
@@ -731,161 +741,22 @@
 	</g>
 </pattern>
 
-<rect
-   y="7.5683593e-06"
-   x="-1.9447623e-05"
-   width="595.27502"
-   height="311.11099"
-   id="rect236"
-   style="fill:#ffffff;fill-opacity:1" /><circle
-   fill="none"
-   stroke="#E76E34"
-   stroke-width="4"
-   cx="97.312"
-   cy="225.171"
-   r="21.999"
-   id="circle238"
-   style="stroke:#1d2d42;stroke-opacity:1" />
-<circle
-   fill="none"
-   stroke="#567B8F"
-   stroke-width="4"
-   cx="364.825"
-   cy="225.171"
-   r="22.001"
-   id="circle240"
-   style="stroke:#1d2d42;stroke-opacity:1" />
-<path
-   fill="none"
-   stroke="#E76E34"
-   stroke-width="4"
-   d="M135.313,202.966v30.074c0,7.801,6.324,14.123,14.123,14.123  c7.803,0,14.125-6.322,14.125-14.123c0-0.004,0-30.074,0-30.074"
-   id="path242"
-   style="stroke:#1d2d42;stroke-opacity:1" />
-<path
-   fill="none"
-   stroke="#E76E34"
-   stroke-width="4"
-   d="M163.561,202.966v30.074c0,7.801,6.324,14.123,14.125,14.123  s14.125-6.322,14.125-14.123c0-0.004,0-30.074,0-30.074"
-   id="path244"
-   style="stroke:#1d2d42;stroke-opacity:1" />
-<path
-   fill="none"
-   stroke="#567B8F"
-   stroke-width="4"
-   d="M319.578,162.962v70.078c0,7.801,6.322,14.123,14.123,14.123"
-   id="path246"
-   style="stroke:#1d2d42;stroke-opacity:1" />
-<path
-   fill="none"
-   stroke="#E76E34"
-   stroke-width="4"
-   d="M208.317,247.169v-22.201c0-12.15,9.85-22,22-22  c12.152,0,22.002,9.85,22.002,22c0,0.006,0,22.201,0,22.201"
-   id="path248"
-   style="stroke:#1d2d42;stroke-opacity:1" />
-<path
-   fill="none"
-   stroke="#567B8F"
-   stroke-width="4"
-   d="M401.322,202.966v22.205c0,12.148,9.85,21.998,22,21.998  s22.002-9.85,22.002-21.998c0-0.008,0-22.205,0-22.205"
-   id="path250"
-   style="stroke:#1d2d42;stroke-opacity:1" />
-<path
-   fill="none"
-   stroke="#567B8F"
-   stroke-width="4"
-   d="M303.146,176.839c-19.421,0-35.167,15.744-35.167,35.166  s15.746,35.164,35.167,35.164"
-   id="path252"
-   style="stroke:#1d2d42;stroke-opacity:1" />
-<polyline
-   fill="none"
-   stroke="#567B8F"
-   stroke-width="4"
-   points="504.596,162.962 504.596,203.134 504.596,202.155 "
-   id="polyline254"
-   style="stroke:#1d2d42;stroke-opacity:1" />
 <path
-   fill="none"
-   stroke="#567B8F"
-   stroke-width="4"
-   d="M490.236,247.157c-4.275,0-7.844,0-7.848,0c-12.15,0-22-9.85-22-21.998  c0-12.15,9.85-22,22-22l22.207-0.025c0,0,0.137,22.342,0,29.895C504.457,240.581,496.627,247.157,490.236,247.157z"
-   id="path256"
-   style="stroke:#1d2d42;stroke-opacity:1" />
-<circle
-   sodipodi:ry="20.332001"
-   sodipodi:rx="20.332001"
-   sodipodi:cy="78.911003"
-   sodipodi:cx="288.49399"
-   style="fill:#1d2d44;stroke:#ffffff;stroke-width:4;fill-opacity:1;stroke-opacity:1"
-   id="circle265"
-   r="20.332001"
-   cy="78.911003"
-   cx="288.49399" /><circle
-   sodipodi:ry="37.242001"
-   sodipodi:rx="37.242001"
-   sodipodi:cy="149.577"
-   sodipodi:cx="251.211"
-   style="fill:#1d2d44;stroke:#ffffff;stroke-width:4;fill-opacity:1;stroke-opacity:1"
-   id="circle272"
-   r="37.242001"
-   cy="149.577"
-   cx="251.211" /><circle
-   sodipodi:ry="40.261002"
-   sodipodi:rx="40.261002"
-   sodipodi:cy="124.796"
-   sodipodi:cx="293.22501"
-   style="fill:#1d2d44;stroke:#ffffff;stroke-width:4;fill-opacity:1;stroke-opacity:1"
-   id="circle279"
-   r="40.261002"
-   cy="124.796"
-   cx="293.22501" /><circle
-   sodipodi:ry="37.242001"
-   sodipodi:rx="37.242001"
-   sodipodi:cy="108.472"
-   sodipodi:cx="375.33401"
-   style="fill:#1d2d44;stroke:#ffffff;stroke-width:4;fill-opacity:1;stroke-opacity:1"
-   id="circle286"
-   r="37.242001"
-   cy="108.472"
-   cx="375.33401" /><circle
-   sodipodi:ry="37.241001"
-   sodipodi:rx="37.241001"
-   sodipodi:cy="79.503998"
-   sodipodi:cx="334.49301"
-   style="fill:#1d2d44;stroke:#ffffff;stroke-width:4;fill-opacity:1;stroke-opacity:1"
-   id="circle293"
-   r="37.241001"
-   cy="79.503998"
-   cx="334.49301" /><circle
-   sodipodi:ry="21.299999"
-   sodipodi:rx="21.299999"
-   sodipodi:cy="163.95799"
-   sodipodi:cx="458.427"
-   style="fill:#1d2d44;stroke:#ffffff;stroke-width:4;fill-opacity:1;stroke-opacity:1"
-   id="circle300"
-   r="21.299999"
-   cy="163.95799"
-   cx="458.427" /><circle
-   sodipodi:ry="40.261002"
-   sodipodi:rx="40.261002"
-   sodipodi:cy="147.563"
-   sodipodi:cx="413.16299"
-   style="fill:#1d2d44;stroke:#ffffff;stroke-width:4;fill-opacity:1;stroke-opacity:1"
-   id="circle307"
-   r="40.261002"
-   cy="147.563"
-   cx="413.16299" /><circle
-   sodipodi:ry="21.299"
-   sodipodi:rx="21.299"
-   sodipodi:cy="166.011"
-   sodipodi:cx="290.76199"
-   style="fill:#1d2d44;stroke:#ffffff;stroke-width:4;fill-opacity:1;stroke-opacity:1"
-   id="circle314"
-   r="21.299"
-   cy="166.011"
-   cx="290.76199" /><path
-   inkscape:connector-curvature="0"
-   style="fill:#1d2d44;stroke:#ffffff;stroke-width:4;fill-opacity:1;stroke-opacity:1"
-   id="path321"
-   d="m 398.107,135.669 c 0,28.348 -22.984,51.328 -51.334,51.328 -28.35,0 -51.333,-22.98 -51.333,-51.328 0,-28.351 22.984,-51.333 51.333,-51.333 28.349,0 51.334,22.982 51.334,51.333 z" />
+   style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;baseline-shift:baseline;color:#000000;fill:#1d2d44;fill-opacity:1;stroke:none;stroke-width:4;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Sans;-inkscape-font-specification:Sans"
+   d="m 150.66402,-4.207031e-7 c -11.24079,0 -20.32231,9.0815110207031 -20.32231,20.3223094207031 0,4.63349 1.54288,8.898031 4.14416,12.312928 5.64309,-6.531492 13.97179,-10.679174 23.27103,-10.679174 4.54961,0 8.86387,1.013111 12.75126,2.789337 0.31474,-1.423374 0.47817,-2.903724 0.47817,-4.423091 C 170.98633,9.0815106 161.90482,-4.207031e-7 150.66402,-4.207031e-7 z M 124.12548,9.4040486 c -5.8539,0 -10.55964,4.7455764 -10.55964,10.5994794 0,1.89532 0.48899,3.686187 1.35482,5.220044 3.53247,-1.99271 7.6164,-3.147966 11.9543,-3.147966 0.41864,0 0.82186,0.01699 1.23528,0.03985 -0.0468,-0.593428 -0.0797,-1.187821 -0.0797,-1.793145 0,-3.260488 0.70816,-6.362694 1.95253,-9.164963 -1.67544,-1.123499 -3.68279,-1.7532974 -5.8576,-1.7532974 z m 50.12836,7.2921224 c -0.43247,0 -0.84934,0.05309 -1.27513,0.0797 0.18418,1.16127 0.31878,2.33386 0.31878,3.546442 0,1.887099 -0.24,3.708046 -0.67741,5.45913 5.1284,2.83813 9.38734,7.08467 12.19339,12.233233 2.91052,-1.515226 6.15729,-2.47869 9.60329,-2.709641 -0.8881,-10.415209 -9.51665,-18.60886 -20.16292,-18.60886 z m -16.49694,7.571057 c -15.72924,0 -28.45123,12.720931 -28.45123,28.451232 0,15.728607 12.72134,28.451231 28.45123,28.451231 15.7299,0 28.45124,-12.72265 28.45124,-28.451231 0,-15.730273 -12.72199,-28.451232 -28.45124,-28.451232 z m -30.88194,0.119543 c -12.20291,0 -22.0756,9.87269 -22.0756,22.075606 0,7.183598 3.4227,13.542949 8.72664,17.57282 2.23603,-4.312671 6.727,-7.252275 11.91445,-7.252275 0.62695,0 1.22873,0.07599 1.83299,0.159391 -0.18969,-1.380056 -0.27893,-2.791988 -0.27893,-4.223853 0,-6.846031 2.22844,-13.176829 6.01699,-18.290078 -2.26779,-2.837739 -3.89072,-6.247406 -4.58248,-9.961916 -0.51269,-0.03551 -1.03226,-0.0797 -1.55406,-0.0797 z M 196.05051,37.5365 c -3.70536,0 -7.17634,0.945989 -10.24085,2.550251 1.74013,3.854499 2.70964,8.131195 2.70964,12.631709 0,8.42684 -3.38806,16.078501 -8.88603,21.637282 4.039,4.484129 9.89911,7.292119 16.41724,7.292119 12.20291,0 22.07561,-9.872692 22.07561,-22.075602 0,-12.202916 -9.8727,-22.035759 -22.07561,-22.035759 z m -93.40293,2.90888 c -11.24112,0 -20.36215,9.041344 -20.36215,20.282461 0,11.241122 9.12103,20.36216 20.36215,20.36216 4.27853,0 8.24193,-1.33304 11.51598,-3.58629 -1.3529,-2.102251 -2.15177,-4.615612 -2.15177,-7.292126 0,-1.389185 0.20497,-2.723795 0.59771,-3.984766 -6.12935,-4.429596 -10.12131,-11.637922 -10.12131,-19.764442 0,-2.064771 0.27209,-4.061306 0.75711,-5.97715 -0.20132,-0.0058 -0.39495,-0.03985 -0.59772,-0.03985 z m 119.50315,17.453277 c -0.59968,0 -1.17994,0.06831 -1.7533,0.15939 0.0316,0.506877 0.0398,0.999386 0.0398,1.514212 0,6.481551 -2.55739,12.364405 -6.69441,16.736019 2.03527,2.366783 5.02479,3.865223 8.40786,3.865223 6.16229,0 11.15735,-4.955213 11.15735,-11.117498 0,-6.162288 -4.99506,-11.157346 -11.15735,-11.157346 z m -96.71028,1.19543 c -6.16197,0 -11.1175,4.955527 -11.1175,11.117498 0,6.161966 4.95553,11.157346 11.1175,11.157346 4.72323,0 8.73232,-2.94722 10.36039,-7.092884 -3.97255,-4.045998 -6.82757,-9.207657 -8.08907,-14.942874 -0.73821,-0.152657 -1.48749,-0.239086 -2.27132,-0.239086 z m 122.21279,9.364201 0,22.035763 -11.67537,0 c -7.63217,0 -13.82714,6.23473 -13.82714,13.866979 0,7.63109 6.19497,13.82714 13.82714,13.82714 l 3.38705,0 1.15558,0 c 2.239,0 4.47478,-1.08741 6.25609,-2.74949 1.78131,-1.66207 3.14086,-3.96444 3.18781,-6.53501 0.0801,-4.41219 0,-17.254039 0,-17.254039 l 0,-0.55787 0,-22.633473 -2.31116,0 z m -106.7519,9.961913 0,30.483469 c 0,5.12322 4.20109,9.2845 9.32436,9.2845 l 0,-2.31116 c -3.87663,0 -7.01319,-3.09673 -7.01319,-6.97334 l 0,-29.048949 c -0.80461,-0.4325 -1.55141,-0.93449 -2.31117,-1.43452 z m -23.11164,2.82919 c -4.09351,3.90587 -6.65456,9.40526 -6.65456,15.50074 0,11.827049 9.61175,21.438039 21.43804,21.438039 l 0,-2.31116 c -10.57945,0 -19.12688,-8.54692 -19.12688,-19.126879 0,-5.69048 2.48389,-10.80462 6.41548,-14.30531 -0.73485,-0.33851 -1.4155,-0.73502 -2.07208,-1.19543 z m -27.21596,9.16496 c -7.63218,0 -13.82714,6.19489 -13.82714,13.827139 l 0,12.7911 2.31117,0 0,-12.7911 c 0,-6.385199 5.13086,-11.555819 11.51597,-11.555819 6.38636,0 11.55582,5.17062 11.55582,11.555819 l 0,12.7911 2.31117,0 0,-12.7911 c 0,-7.632249 -6.23376,-13.827139 -13.86699,-13.827139 z m 77.5834,0.0797 c -7.6326,0 -13.82713,6.23438 -13.82713,13.866979 0,7.63262 6.19453,13.86699 13.82713,13.86699 7.63262,0 13.86699,-6.23437 13.86699,-13.86699 0,-7.632599 -6.23437,-13.866979 -13.86699,-13.866979 z m -154.290153,0.0398 c -7.6319743,0 -13.86698728410752,6.19517 -13.86698728410752,13.827139 0,7.63198 6.23501298410752,13.82714 13.86698728410752,13.82714 7.631973,0 13.82714,-6.19516 13.82714,-13.82714 0,-7.631969 -6.195167,-13.827139 -13.82714,-13.827139 z m 20.760634,1.03604 0,17.333739 c 0,5.12342 4.162235,9.2845 9.284505,9.2845 3.491222,0 6.571552,-1.93031 8.168772,-4.78172 1.585655,2.85141 4.638381,4.78172 8.128923,4.78172 5.123264,0 9.324349,-4.16108 9.324349,-9.2845 l 0,-17.333739 -2.31116,0 0,17.333739 c 0,3.8764 -3.136557,6.97334 -7.013189,6.97334 -3.876637,0 -6.973341,-3.09694 -6.973341,-6.97334 l 0,-17.333739 -2.311165,0 0,17.333739 c 0,3.87661 -3.135236,6.97334 -7.013189,6.97334 -3.875319,0 -6.973341,-3.09694 -6.973341,-6.97334 l 0,-17.333739 -2.311164,0 z m 153.453359,0 0,12.791099 c 0,7.63109 6.19496,13.82714 13.82714,13.82714 7.63218,0 13.86698,-6.19592 13.86698,-13.82714 l 0,-12.791099 -2.31116,0 0,12.791099 c 0,6.38369 -5.17071,11.51598 -11.55582,11.51598 -6.3851,0 -11.51598,-5.13216 -11.51598,-11.51598 l 0,-12.791099 -2.31116,0 z m -19.92384,1.23528 c 6.38563,0 11.55583,5.17021 11.55583,11.555819 0,6.38563 -5.1702,11.55583 -11.55583,11.55583 -6.38561,0 -11.51597,-5.1702 -11.51597,-11.55583 0,-6.385609 5.13036,-11.555819 11.51597,-11.555819 z m 67.82073,0 11.67537,0 c 0.009,1.52706 0.0728,12.045619 0,16.058609 -0.0326,1.78576 -1.01212,3.57763 -2.43071,4.90126 -1.41859,1.32363 -3.25441,2.11193 -4.70203,2.11193 l -4.54263,0 c -6.3851,0 -11.51598,-5.13216 -11.51598,-11.51598 0,-6.385199 5.13088,-11.555819 11.51598,-11.555819 z m -222.110883,0.0399 c 6.384977,0 11.515975,5.131 11.515975,11.515969 0,6.38499 -5.130998,11.51598 -11.515975,11.51598 -6.3849773,0 -11.5558223,-5.13099 -11.5558223,-11.51598 0,-6.384969 5.170845,-11.515969 11.5558223,-11.515969 z"
+   id="circle238"
+   inkscape:export-filename="/home/user/owncloud/core/img/logo.png"
+   inkscape:export-xdpi="90"
+   inkscape:export-ydpi="90"
+   inkscape:connector-curvature="0" />
+
+
+
+
+
+
+
+
+
+
 </svg>
\ No newline at end of file
diff --git a/core/img/logo-sticker.jpg b/core/img/logo-sticker.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..ad2bf63ca37aa064d4f7c05c6e293bcafcb5e702
Binary files /dev/null and b/core/img/logo-sticker.jpg differ
diff --git a/core/img/logo-sticker.svg b/core/img/logo-sticker.svg
new file mode 100644
index 0000000000000000000000000000000000000000..e48f7a78c7d91cc0cd5c25c2ed082be598af4ee3
--- /dev/null
+++ b/core/img/logo-sticker.svg
@@ -0,0 +1,764 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Generator: Adobe Illustrator 13.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 14948)  -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:xlink="http://www.w3.org/1999/xlink"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   version="1.1"
+   id="Layer_1"
+   x="0px"
+   y="0px"
+   width="269.29132"
+   height="191.33858"
+   viewBox="0 0 269.29131 191.33857"
+   enable-background="new 0 0 595.275 311.111"
+   xml:space="preserve"
+   inkscape:version="0.48.2 r9819"
+   sodipodi:docname="logo.svg"
+   inkscape:export-filename="/home/user/owncloud/core/img/logo-sticker.png"
+   inkscape:export-xdpi="300.00223"
+   inkscape:export-ydpi="300.00223"><metadata
+   id="metadata327"><rdf:RDF><cc:Work
+       rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
+         rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
+   id="defs325"><linearGradient
+   inkscape:collect="always"
+   xlink:href="#SVGID_1_"
+   id="linearGradient3353"
+   gradientUnits="userSpaceOnUse"
+   x1="288.49411"
+   y1="55.888199"
+   x2="288.49411"
+   y2="339.22189" /><linearGradient
+   inkscape:collect="always"
+   xlink:href="#SVGID_2_"
+   id="linearGradient3355"
+   gradientUnits="userSpaceOnUse"
+   x1="251.2114"
+   y1="55.888199"
+   x2="251.2114"
+   y2="339.22159" /><linearGradient
+   inkscape:collect="always"
+   xlink:href="#SVGID_3_"
+   id="linearGradient3357"
+   gradientUnits="userSpaceOnUse"
+   x1="293.22461"
+   y1="55.888199"
+   x2="293.22461"
+   y2="339.22171" /><linearGradient
+   inkscape:collect="always"
+   xlink:href="#SVGID_4_"
+   id="linearGradient3359"
+   gradientUnits="userSpaceOnUse"
+   x1="375.33401"
+   y1="55.888199"
+   x2="375.33401"
+   y2="339.22159" /><linearGradient
+   inkscape:collect="always"
+   xlink:href="#SVGID_5_"
+   id="linearGradient3361"
+   gradientUnits="userSpaceOnUse"
+   x1="334.49411"
+   y1="55.888199"
+   x2="334.49411"
+   y2="339.22159" /><linearGradient
+   inkscape:collect="always"
+   xlink:href="#SVGID_6_"
+   id="linearGradient3363"
+   gradientUnits="userSpaceOnUse"
+   x1="458.42679"
+   y1="55.8867"
+   x2="458.42679"
+   y2="339.2236" /><linearGradient
+   inkscape:collect="always"
+   xlink:href="#SVGID_7_"
+   id="linearGradient3365"
+   gradientUnits="userSpaceOnUse"
+   x1="413.16309"
+   y1="55.888199"
+   x2="413.16309"
+   y2="339.22131" /><linearGradient
+   inkscape:collect="always"
+   xlink:href="#SVGID_8_"
+   id="linearGradient3367"
+   gradientUnits="userSpaceOnUse"
+   x1="290.76169"
+   y1="55.8867"
+   x2="290.76169"
+   y2="339.2236" /><linearGradient
+   inkscape:collect="always"
+   xlink:href="#SVGID_9_"
+   id="linearGradient3369"
+   gradientUnits="userSpaceOnUse"
+   x1="346.77341"
+   y1="55.888199"
+   x2="346.77341"
+   y2="339.22119" />
+	<linearGradient
+   y2="339.22189"
+   x2="288.49411"
+   y1="55.888199"
+   x1="288.49411"
+   gradientUnits="userSpaceOnUse"
+   id="SVGID_1_">
+		<stop
+   id="stop261"
+   style="stop-color:#BED5E1"
+   offset="0" />
+		<stop
+   id="stop263"
+   style="stop-color:#567B8F"
+   offset="1" />
+	</linearGradient>
+	
+	<linearGradient
+   y2="339.22159"
+   x2="251.2114"
+   y1="55.888199"
+   x1="251.2114"
+   gradientUnits="userSpaceOnUse"
+   id="SVGID_2_">
+		<stop
+   id="stop268"
+   style="stop-color:#BED5E1"
+   offset="0" />
+		<stop
+   id="stop270"
+   style="stop-color:#567B8F"
+   offset="1" />
+	</linearGradient>
+	
+	<linearGradient
+   y2="339.22171"
+   x2="293.22461"
+   y1="55.888199"
+   x1="293.22461"
+   gradientUnits="userSpaceOnUse"
+   id="SVGID_3_">
+		<stop
+   id="stop275"
+   style="stop-color:#BED5E1"
+   offset="0" />
+		<stop
+   id="stop277"
+   style="stop-color:#567B8F"
+   offset="1" />
+	</linearGradient>
+	
+	<linearGradient
+   y2="339.22159"
+   x2="375.33401"
+   y1="55.888199"
+   x1="375.33401"
+   gradientUnits="userSpaceOnUse"
+   id="SVGID_4_">
+		<stop
+   id="stop282"
+   style="stop-color:#BED5E1"
+   offset="0" />
+		<stop
+   id="stop284"
+   style="stop-color:#567B8F"
+   offset="1" />
+	</linearGradient>
+	
+	<linearGradient
+   y2="339.22159"
+   x2="334.49411"
+   y1="55.888199"
+   x1="334.49411"
+   gradientUnits="userSpaceOnUse"
+   id="SVGID_5_">
+		<stop
+   id="stop289"
+   style="stop-color:#BED5E1"
+   offset="0" />
+		<stop
+   id="stop291"
+   style="stop-color:#567B8F"
+   offset="1" />
+	</linearGradient>
+	
+	<linearGradient
+   y2="339.2236"
+   x2="458.42679"
+   y1="55.8867"
+   x1="458.42679"
+   gradientUnits="userSpaceOnUse"
+   id="SVGID_6_">
+		<stop
+   id="stop296"
+   style="stop-color:#BED5E1"
+   offset="0" />
+		<stop
+   id="stop298"
+   style="stop-color:#567B8F"
+   offset="1" />
+	</linearGradient>
+	
+	<linearGradient
+   y2="339.22131"
+   x2="413.16309"
+   y1="55.888199"
+   x1="413.16309"
+   gradientUnits="userSpaceOnUse"
+   id="SVGID_7_">
+		<stop
+   id="stop303"
+   style="stop-color:#BED5E1"
+   offset="0" />
+		<stop
+   id="stop305"
+   style="stop-color:#567B8F"
+   offset="1" />
+	</linearGradient>
+	
+	<linearGradient
+   y2="339.2236"
+   x2="290.76169"
+   y1="55.8867"
+   x1="290.76169"
+   gradientUnits="userSpaceOnUse"
+   id="SVGID_8_">
+		<stop
+   id="stop310"
+   style="stop-color:#BED5E1"
+   offset="0" />
+		<stop
+   id="stop312"
+   style="stop-color:#567B8F"
+   offset="1" />
+	</linearGradient>
+	
+	<linearGradient
+   y2="339.22119"
+   x2="346.77341"
+   y1="55.888199"
+   x1="346.77341"
+   gradientUnits="userSpaceOnUse"
+   id="SVGID_9_">
+		<stop
+   id="stop317"
+   style="stop-color:#BED5E1"
+   offset="0" />
+		<stop
+   id="stop319"
+   style="stop-color:#567B8F"
+   offset="1" />
+	</linearGradient>
+	
+</defs><sodipodi:namedview
+   pagecolor="#ffffff"
+   bordercolor="#666666"
+   borderopacity="1"
+   objecttolerance="10"
+   gridtolerance="10"
+   guidetolerance="10"
+   inkscape:pageopacity="0"
+   inkscape:pageshadow="2"
+   inkscape:window-width="1280"
+   inkscape:window-height="774"
+   id="namedview323"
+   showgrid="false"
+   inkscape:zoom="2"
+   inkscape:cx="156.13378"
+   inkscape:cy="107.57751"
+   inkscape:window-x="0"
+   inkscape:window-y="26"
+   inkscape:window-maximized="1"
+   inkscape:current-layer="Layer_1"
+   units="mm"
+   fit-margin-top="0"
+   fit-margin-left="0"
+   fit-margin-right="0"
+   fit-margin-bottom="0"
+   showguides="true"
+   inkscape:guide-bbox="true" />
+<pattern
+   y="565.223"
+   width="69"
+   height="69"
+   patternUnits="userSpaceOnUse"
+   id="Polka_Dot_Pattern"
+   viewBox="2.125 -70.896 69 69"
+   overflow="visible">
+	<g
+   id="g4">
+		<polygon
+   fill="none"
+   points="71.125,-1.896 2.125,-1.896 2.125,-70.896 71.125,-70.896   "
+   id="polygon6" />
+		<polygon
+   fill="#F6BB60"
+   points="71.125,-1.896 2.125,-1.896 2.125,-70.896 71.125,-70.896   "
+   id="polygon8" />
+		<g
+   id="g10">
+			<path
+   fill="#FFFFFF"
+   d="M61.772-71.653c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128     c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161     c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631     c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45     c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221     c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337     c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207     c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169     c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path12" />
+			<path
+   fill="#FFFFFF"
+   d="M54.105-71.653c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128     c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161     c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631     c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45     c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221     c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337     c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207     c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169     c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path14" />
+			<path
+   fill="#FFFFFF"
+   d="M46.439-71.653c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128     c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161     c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631     c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45     c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221     c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337     c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207     c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169     c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path16" />
+			<path
+   fill="#FFFFFF"
+   d="M38.772-71.653c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128     c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161     c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631     c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45     c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221     c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337     c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207     c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169     c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path18" />
+			<path
+   fill="#FFFFFF"
+   d="M31.105-71.653c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128     c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161     c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631     c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45     c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221     c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337     c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207     c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169     c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path20" />
+			<path
+   fill="#FFFFFF"
+   d="M23.439-71.653c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128     c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161     c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631     c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45     c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221     c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337     c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207     c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169     c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path22" />
+			<path
+   fill="#FFFFFF"
+   d="M15.772-71.653c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128     c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161     c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631     c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45     c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221     c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337     c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207     c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169     c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path24" />
+			<path
+   fill="#FFFFFF"
+   d="M8.105-71.653c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128     c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161     c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631     c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45     c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221     c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337     c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207     c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169     c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path26" />
+			<path
+   fill="#FFFFFF"
+   d="M0.439-71.653c0.018,0.072,0.008,0.127-0.026,0.19C0.361-71.362,0.3-71.4,0.248-71.335     c-0.051,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161     c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631     c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45     c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.07,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221     c0.038-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.051-0.12-0.064-0.187c-0.021-0.114,0.002-0.224,0-0.337     c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207     c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.215,0.124-0.215,0.224c0.002,0.115,0.005,0.051,0.012,0.169     c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path28" />
+		</g>
+		<g
+   id="g30">
+			<path
+   fill="#FFFFFF"
+   d="M69.439-71.653c0.018,0.072,0.008,0.127-0.026,0.19c-0.052,0.101-0.113,0.062-0.165,0.128     c-0.051,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161     c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631     c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45     c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.07,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221     c0.038-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.051-0.12-0.064-0.187c-0.021-0.114,0.002-0.224,0-0.337     c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207     c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.215,0.124-0.215,0.224c0.002,0.115,0.005,0.051,0.012,0.169     c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path32" />
+		</g>
+		<path
+   fill="#FFFFFF"
+   d="M0.495-71.653c0.018,0.072,0.008,0.127-0.026,0.19c-0.052,0.101-0.113,0.062-0.165,0.128    c-0.051,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161    c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631    c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45    c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.07,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221    c0.038-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.051-0.12-0.064-0.187c-0.021-0.114,0.002-0.224,0-0.337    c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207    c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.215,0.124-0.215,0.224C0.5-71.68,0.503-71.744,0.51-71.626    c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path34" />
+		<g
+   id="g36">
+			<g
+   id="g38">
+				<path
+   fill="#FFFFFF"
+   d="M69.439-64.001c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path40" />
+				<path
+   fill="#FFFFFF"
+   d="M61.778-64.001c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path42" />
+				<path
+   fill="#FFFFFF"
+   d="M54.118-64.001c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path44" />
+				<path
+   fill="#FFFFFF"
+   d="M46.458-64.001c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path46" />
+				<path
+   fill="#FFFFFF"
+   d="M38.797-64.001c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path48" />
+				<path
+   fill="#FFFFFF"
+   d="M31.137-64.001c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path50" />
+				<path
+   fill="#FFFFFF"
+   d="M23.477-64.001c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path52" />
+				<path
+   fill="#FFFFFF"
+   d="M15.816-64.001c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path54" />
+				<path
+   fill="#FFFFFF"
+   d="M8.156-64.001c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path56" />
+				<path
+   fill="#FFFFFF"
+   d="M0.495-64.001c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143C2-61.45,2.217-61.397,2.391-61.46c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path58" />
+			</g>
+			<g
+   id="g60">
+				<path
+   fill="#FFFFFF"
+   d="M69.439-56.348c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path62" />
+				<path
+   fill="#FFFFFF"
+   d="M61.778-56.348c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path64" />
+				<path
+   fill="#FFFFFF"
+   d="M54.118-56.348c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path66" />
+				<path
+   fill="#FFFFFF"
+   d="M46.458-56.348c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path68" />
+				<path
+   fill="#FFFFFF"
+   d="M38.797-56.348c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path70" />
+				<path
+   fill="#FFFFFF"
+   d="M31.137-56.348c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path72" />
+				<path
+   fill="#FFFFFF"
+   d="M23.477-56.348c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path74" />
+				<path
+   fill="#FFFFFF"
+   d="M15.816-56.348c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path76" />
+				<path
+   fill="#FFFFFF"
+   d="M8.156-56.348c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path78" />
+				<path
+   fill="#FFFFFF"
+   d="M0.495-56.348c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224C0.5-56.374,0.503-56.438,0.51-56.32      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path80" />
+			</g>
+			<g
+   id="g82">
+				<path
+   fill="#FFFFFF"
+   d="M69.439-48.695c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path84" />
+				<path
+   fill="#FFFFFF"
+   d="M61.778-48.695c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path86" />
+				<path
+   fill="#FFFFFF"
+   d="M54.118-48.695c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path88" />
+				<path
+   fill="#FFFFFF"
+   d="M46.458-48.695c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path90" />
+				<path
+   fill="#FFFFFF"
+   d="M38.797-48.695c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path92" />
+				<path
+   fill="#FFFFFF"
+   d="M31.137-48.695c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path94" />
+				<path
+   fill="#FFFFFF"
+   d="M23.477-48.695c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path96" />
+				<path
+   fill="#FFFFFF"
+   d="M15.816-48.695c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path98" />
+				<path
+   fill="#FFFFFF"
+   d="M8.156-48.695c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path100" />
+				<path
+   fill="#FFFFFF"
+   d="M0.495-48.695c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path102" />
+			</g>
+			<g
+   id="g104">
+				<path
+   fill="#FFFFFF"
+   d="M69.439-41.042c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path106" />
+				<path
+   fill="#FFFFFF"
+   d="M61.778-41.042c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path108" />
+				<path
+   fill="#FFFFFF"
+   d="M54.118-41.042c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path110" />
+				<path
+   fill="#FFFFFF"
+   d="M46.458-41.042c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path112" />
+				<path
+   fill="#FFFFFF"
+   d="M38.797-41.042c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path114" />
+				<path
+   fill="#FFFFFF"
+   d="M31.137-41.042c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path116" />
+				<path
+   fill="#FFFFFF"
+   d="M23.477-41.042c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path118" />
+				<path
+   fill="#FFFFFF"
+   d="M15.816-41.042c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path120" />
+				<path
+   fill="#FFFFFF"
+   d="M8.156-41.042c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      C8.15-41.004,8.149-41.02,8.14-41.04"
+   id="path122" />
+				<path
+   fill="#FFFFFF"
+   d="M0.495-41.042c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path124" />
+			</g>
+			<g
+   id="g126">
+				<path
+   fill="#FFFFFF"
+   d="M69.439-33.39c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path128" />
+				<path
+   fill="#FFFFFF"
+   d="M61.778-33.39c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path130" />
+				<path
+   fill="#FFFFFF"
+   d="M54.118-33.39c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path132" />
+				<path
+   fill="#FFFFFF"
+   d="M46.458-33.39c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path134" />
+				<path
+   fill="#FFFFFF"
+   d="M38.797-33.39c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path136" />
+				<path
+   fill="#FFFFFF"
+   d="M31.137-33.39c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path138" />
+				<path
+   fill="#FFFFFF"
+   d="M23.477-33.39c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path140" />
+				<path
+   fill="#FFFFFF"
+   d="M15.816-33.39c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path142" />
+				<path
+   fill="#FFFFFF"
+   d="M8.156-33.39c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path144" />
+				<path
+   fill="#FFFFFF"
+   d="M0.495-33.39c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224C0.5-33.416,0.503-33.48,0.51-33.362      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path146" />
+			</g>
+			<g
+   id="g148">
+				<path
+   fill="#FFFFFF"
+   d="M69.439-25.736c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path150" />
+				<path
+   fill="#FFFFFF"
+   d="M61.778-25.736c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path152" />
+				<path
+   fill="#FFFFFF"
+   d="M54.118-25.736c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path154" />
+				<path
+   fill="#FFFFFF"
+   d="M46.458-25.736c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path156" />
+				<path
+   fill="#FFFFFF"
+   d="M38.797-25.736c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path158" />
+				<path
+   fill="#FFFFFF"
+   d="M31.137-25.736c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path160" />
+				<path
+   fill="#FFFFFF"
+   d="M23.477-25.736c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path162" />
+				<path
+   fill="#FFFFFF"
+   d="M15.816-25.736c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path164" />
+				<path
+   fill="#FFFFFF"
+   d="M8.156-25.736c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path166" />
+				<path
+   fill="#FFFFFF"
+   d="M0.495-25.736c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path168" />
+			</g>
+			<g
+   id="g170">
+				<path
+   fill="#FFFFFF"
+   d="M69.439-18.084c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path172" />
+				<path
+   fill="#FFFFFF"
+   d="M61.778-18.084c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path174" />
+				<path
+   fill="#FFFFFF"
+   d="M54.118-18.084c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path176" />
+				<path
+   fill="#FFFFFF"
+   d="M46.458-18.084c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path178" />
+				<path
+   fill="#FFFFFF"
+   d="M38.797-18.084c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path180" />
+				<path
+   fill="#FFFFFF"
+   d="M31.137-18.084c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path182" />
+				<path
+   fill="#FFFFFF"
+   d="M23.477-18.084c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path184" />
+				<path
+   fill="#FFFFFF"
+   d="M15.816-18.084c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path186" />
+				<path
+   fill="#FFFFFF"
+   d="M8.156-18.084c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path188" />
+				<path
+   fill="#FFFFFF"
+   d="M0.495-18.084c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224C0.5-18.11,0.503-18.175,0.51-18.057      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path190" />
+			</g>
+			<g
+   id="g192">
+				<path
+   fill="#FFFFFF"
+   d="M69.439-10.431c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362C69-9.692,69.159-9.523,69.154-9.4c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path194" />
+				<path
+   fill="#FFFFFF"
+   d="M61.778-10.431c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path196" />
+				<path
+   fill="#FFFFFF"
+   d="M54.118-10.431c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path198" />
+				<path
+   fill="#FFFFFF"
+   d="M46.458-10.431c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path200" />
+				<path
+   fill="#FFFFFF"
+   d="M38.797-10.431c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path202" />
+				<path
+   fill="#FFFFFF"
+   d="M31.137-10.431c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path204" />
+				<path
+   fill="#FFFFFF"
+   d="M23.477-10.431c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path206" />
+				<path
+   fill="#FFFFFF"
+   d="M15.816-10.431c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053C17.933-7.969,17.839-8.227,18-8.34      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path208" />
+				<path
+   fill="#FFFFFF"
+   d="M8.156-10.431c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      C7.915-10.05,7.866-9.836,7.886-9.75C7.717-9.692,7.876-9.523,7.871-9.4C7.868-9.351,7.83-9.295,7.826-9.239      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      C9.114-7.652,9.321-7.799,9.48-7.837c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path210" />
+				<path
+   fill="#FFFFFF"
+   d="M0.495-10.431c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      C0.254-10.05,0.205-9.836,0.225-9.75C0.056-9.692,0.215-9.523,0.21-9.4c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37C0.33-8.671,0.501-8.456,0.668-8.325c0.19,0.148,0.365,0.572,0.608,0.631      C1.454-7.652,1.66-7.799,1.819-7.837C2-7.88,2.217-7.827,2.391-7.89c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46C3.477-8.933,3.471-8.995,3.5-9.071      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path212" />
+			</g>
+		</g>
+		<g
+   id="g214">
+			<path
+   fill="#FFFFFF"
+   d="M69.439-2.778c0.018,0.072,0.008,0.127-0.026,0.19C69.361-2.487,69.3-2.525,69.248-2.46     c-0.051,0.062-0.099,0.276-0.079,0.362C69-2.04,69.159-1.871,69.154-1.748c-0.002,0.05-0.041,0.105-0.045,0.161     c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631     C70.397,0,70.604-0.146,70.763-0.185c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45     c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.07,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221     c0.038-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.051-0.12-0.064-0.187c-0.021-0.114,0.002-0.224,0-0.337     c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207     c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.215,0.124-0.215,0.224c0.002,0.115,0.005,0.051,0.012,0.169     c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path216" />
+			<path
+   fill="#FFFFFF"
+   d="M61.778-2.778c0.018,0.072,0.007,0.127-0.026,0.19C61.7-2.487,61.64-2.525,61.587-2.46     c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161     c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631     C62.737,0,62.943-0.146,63.103-0.185c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45     c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221     c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337     c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207     c-0.17,0.088-0.139,0.166-0.318,0.224C61.915-3.117,61.78-3.02,61.781-2.92c0.001,0.115,0.005,0.051,0.012,0.169     c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path218" />
+			<path
+   fill="#FFFFFF"
+   d="M54.118-2.778c0.018,0.072,0.007,0.127-0.026,0.19C54.04-2.487,53.98-2.525,53.927-2.46     c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161     c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631     C55.077,0,55.283-0.146,55.442-0.185c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45     c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221     c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337     c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207     c-0.17,0.088-0.139,0.166-0.318,0.224C54.255-3.117,54.12-3.02,54.121-2.92c0.001,0.115,0.005,0.051,0.012,0.169     c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path220" />
+			<path
+   fill="#FFFFFF"
+   d="M46.458-2.778c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128     c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161     c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631     C47.416,0,47.623-0.146,47.782-0.185c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45     c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221     c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337     c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207     c-0.17,0.088-0.139,0.166-0.318,0.224C46.594-3.117,46.459-3.02,46.46-2.92c0.001,0.115,0.005,0.051,0.012,0.169     c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path222" />
+			<path
+   fill="#FFFFFF"
+   d="M38.797-2.778c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128     c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161     c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631     C39.756,0,39.962-0.146,40.122-0.185c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45     c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221     c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337     c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207     c-0.17,0.088-0.139,0.166-0.318,0.224C38.934-3.117,38.799-3.02,38.8-2.92c0.001,0.115,0.005,0.051,0.012,0.169     c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path224" />
+			<path
+   fill="#FFFFFF"
+   d="M31.137-2.778c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128     c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161     c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631     C32.095,0,32.302-0.146,32.461-0.185c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45     c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221     c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337     c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207     c-0.17,0.088-0.139,0.166-0.318,0.224C31.273-3.117,31.139-3.02,31.14-2.92c0.001,0.115,0.005,0.051,0.012,0.169     c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path226" />
+			<path
+   fill="#FFFFFF"
+   d="M23.477-2.778c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128     c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161     c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631     C24.435,0,24.642-0.146,24.801-0.185c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45     c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221     c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337     c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207     c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169     c-0.021,0.011-0.021-0.005-0.03-0.025"
+   id="path228" />
+			<path
+   fill="#FFFFFF"
+   d="M15.816-2.778c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128     c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161     c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631     C16.774,0,16.981-0.146,17.14-0.185c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45     c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221     c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337     c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207     c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169     C15.81-2.74,15.809-2.756,15.8-2.776"
+   id="path230" />
+			<path
+   fill="#FFFFFF"
+   d="M8.156-2.778c0.018,0.072,0.007,0.127-0.026,0.19C8.077-2.487,8.018-2.525,7.965-2.46     c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35C7.868-1.698,7.83-1.643,7.826-1.587     c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631     C9.114,0,9.321-0.146,9.48-0.185c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45     c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221     c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337     c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789C8.954-3.54,8.847-3.448,8.692-3.367     c-0.17,0.088-0.139,0.166-0.318,0.224C8.292-3.117,8.158-3.02,8.159-2.92C8.16-2.805,8.164-2.869,8.17-2.751     C8.15-2.74,8.149-2.756,8.14-2.776"
+   id="path232" />
+			<path
+   fill="#FFFFFF"
+   d="M0.495-2.778c0.018,0.072,0.008,0.127-0.026,0.19C0.417-2.487,0.356-2.525,0.304-2.46     C0.253-2.397,0.205-2.184,0.225-2.098C0.056-2.04,0.215-1.871,0.21-1.748c-0.002,0.05-0.041,0.105-0.045,0.161     c-0.01,0.119,0.017,0.266,0.068,0.37C0.33-1.019,0.501-0.804,0.668-0.673c0.19,0.148,0.365,0.572,0.608,0.631     C1.454,0,1.66-0.146,1.819-0.185C2-0.228,2.217-0.175,2.391-0.237c0.222-0.079,0.127-0.337,0.288-0.45     c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.07,0.339-0.263,0.376-0.46C3.477-1.28,3.471-1.343,3.5-1.419     c0.038-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.051-0.12-0.064-0.187c-0.021-0.114,0.002-0.224,0-0.337     c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789C1.293-3.54,1.187-3.448,1.031-3.367     c-0.17,0.088-0.139,0.166-0.318,0.224C0.632-3.117,0.498-3.02,0.498-2.92C0.5-2.805,0.503-2.869,0.51-2.751     C0.489-2.74,0.488-2.756,0.479-2.776"
+   id="path234" />
+		</g>
+	</g>
+</pattern>
+<rect
+   width="269.29132"
+   height="191.33858"
+   id="rect236"
+   style="fill:#1d2d44;fill-opacity:1"
+   x="-2.2128221e-05"
+   y="0" />
+<path
+   style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;baseline-shift:baseline;color:#000000;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:4;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Sans;-inkscape-font-specification:Sans"
+   d="M 151.3125 48.21875 C 142.49706 48.21875 135.375 55.340804 135.375 64.15625 C 135.375 67.790003 136.58498 71.134412 138.625 73.8125 C 143.05052 68.690264 149.58219 65.4375 156.875 65.4375 C 160.44297 65.4375 163.82637 66.232019 166.875 67.625 C 167.12183 66.508738 167.25 65.347793 167.25 64.15625 C 167.25 55.340804 160.12795 48.21875 151.3125 48.21875 z M 130.5 55.59375 C 125.90916 55.59375 122.21875 59.315405 122.21875 63.90625 C 122.21875 65.39263 122.60223 66.797093 123.28125 68 C 126.05154 66.437244 129.25431 65.53125 132.65625 65.53125 C 132.98456 65.53125 133.30078 65.544578 133.625 65.5625 C 133.58831 65.097112 133.5625 64.630967 133.5625 64.15625 C 133.5625 61.599256 134.11787 59.166392 135.09375 56.96875 C 133.77981 56.087661 132.20557 55.59375 130.5 55.59375 z M 169.8125 61.3125 C 169.47334 61.3125 169.14642 61.354138 168.8125 61.375 C 168.95694 62.285711 169.0625 63.205299 169.0625 64.15625 C 169.0625 65.636182 168.87428 67.064236 168.53125 68.4375 C 172.55313 70.663266 175.89314 73.993558 178.09375 78.03125 C 180.37629 76.842954 182.92252 76.08737 185.625 75.90625 C 184.92852 67.738261 178.1617 61.3125 169.8125 61.3125 z M 156.875 67.25 C 144.53955 67.25 134.5625 77.226221 134.5625 89.5625 C 134.5625 101.89745 144.53904 111.875 156.875 111.875 C 169.21096 111.875 179.1875 101.89743 179.1875 89.5625 C 179.1875 77.226243 169.21045 67.25 156.875 67.25 z M 132.65625 67.34375 C 123.08628 67.34375 115.34375 75.086276 115.34375 84.65625 C 115.34375 90.289891 118.02796 95.277127 122.1875 98.4375 C 123.94108 95.055345 127.46306 92.75 131.53125 92.75 C 132.02293 92.75 132.49487 92.809591 132.96875 92.875 C 132.81999 91.79271 132.75 90.685421 132.75 89.5625 C 132.75 84.193591 134.49763 79.228747 137.46875 75.21875 C 135.69026 72.993291 134.4175 70.319305 133.875 67.40625 C 133.47293 67.378399 133.06546 67.34375 132.65625 67.34375 z M 186.90625 77.65625 C 184.00037 77.65625 181.2783 78.398129 178.875 79.65625 C 180.23967 82.67909 181 86.033032 181 89.5625 C 181 96.171137 178.34296 102.17185 174.03125 106.53125 C 177.19878 110.04787 181.79449 112.25 186.90625 112.25 C 196.47622 112.25 204.21875 104.50747 204.21875 94.9375 C 204.21875 85.367526 196.47622 77.65625 186.90625 77.65625 z M 113.65625 79.9375 C 104.84055 79.9375 97.6875 87.028054 97.6875 95.84375 C 97.6875 104.65945 104.84055 111.8125 113.65625 111.8125 C 117.01163 111.8125 120.11987 110.76708 122.6875 109 C 121.62651 107.35134 121 105.38027 121 103.28125 C 121 102.1918 121.16075 101.14515 121.46875 100.15625 C 116.66189 96.682399 113.53125 91.029365 113.53125 84.65625 C 113.53125 83.036981 113.74463 81.471225 114.125 79.96875 C 113.96712 79.964167 113.81527 79.9375 113.65625 79.9375 z M 207.375 93.625 C 206.90471 93.625 206.44965 93.678572 206 93.75 C 206.02476 94.147511 206.03125 94.533755 206.03125 94.9375 C 206.03125 100.02057 204.02565 104.63412 200.78125 108.0625 C 202.37738 109.91862 204.72187 111.09375 207.375 111.09375 C 212.20769 111.09375 216.125 107.20769 216.125 102.375 C 216.125 97.542308 212.20769 93.625 207.375 93.625 z M 131.53125 94.5625 C 126.69881 94.5625 122.8125 98.448806 122.8125 103.28125 C 122.8125 108.11369 126.69881 112.03125 131.53125 112.03125 C 135.23538 112.03125 138.37946 109.71993 139.65625 106.46875 C 136.54083 103.29573 134.30182 99.247768 133.3125 94.75 C 132.73357 94.630281 132.14596 94.5625 131.53125 94.5625 z M 227.375 101.90625 L 227.375 119.1875 L 218.21875 119.1875 C 212.23332 119.1875 207.375 124.07701 207.375 130.0625 C 207.375 136.04708 212.23332 140.90625 218.21875 140.90625 L 220.875 140.90625 L 221.78125 140.90625 C 223.53715 140.90625 225.29053 140.05346 226.6875 138.75 C 228.08447 137.44654 229.15068 135.64094 229.1875 133.625 C 229.2503 130.1648 229.1875 120.09375 229.1875 120.09375 L 229.1875 119.65625 L 229.1875 101.90625 L 227.375 101.90625 z M 143.65625 109.71875 L 143.65625 133.625 C 143.65625 137.64282 146.9509 140.90625 150.96875 140.90625 L 150.96875 139.09375 C 147.92856 139.09375 145.46875 136.66518 145.46875 133.625 L 145.46875 110.84375 C 144.83775 110.50457 144.25208 110.11089 143.65625 109.71875 z M 125.53125 111.9375 C 122.32097 115.00063 120.3125 119.31345 120.3125 124.09375 C 120.3125 133.36896 127.85039 140.90625 137.125 140.90625 L 137.125 139.09375 C 128.82821 139.09375 122.125 132.39094 122.125 124.09375 C 122.125 119.63107 124.07296 115.62037 127.15625 112.875 C 126.57996 112.60953 126.04617 112.29857 125.53125 111.9375 z M 104.1875 119.125 C 98.202067 119.125 93.34375 123.98326 93.34375 129.96875 L 93.34375 140 L 95.15625 140 L 95.15625 129.96875 C 95.15625 124.96124 99.180065 120.90625 104.1875 120.90625 C 109.19592 120.90625 113.25 124.96124 113.25 129.96875 L 113.25 140 L 115.0625 140 L 115.0625 129.96875 C 115.0625 123.98326 110.17376 119.125 104.1875 119.125 z M 165.03125 119.1875 C 159.04548 119.1875 154.1875 124.07673 154.1875 130.0625 C 154.1875 136.04828 159.04548 140.9375 165.03125 140.9375 C 171.01703 140.9375 175.90625 136.04828 175.90625 130.0625 C 175.90625 124.07673 171.01703 119.1875 165.03125 119.1875 z M 44.03125 119.21875 C 38.045976 119.21875 33.15625 124.07723 33.15625 130.0625 C 33.15625 136.04778 38.045976 140.90625 44.03125 140.90625 C 50.016523 140.90625 54.875 136.04778 54.875 130.0625 C 54.875 124.07723 50.016523 119.21875 44.03125 119.21875 z M 60.3125 120.03125 L 60.3125 133.625 C 60.3125 137.64298 63.576678 140.90625 67.59375 140.90625 C 70.331694 140.90625 72.747402 139.39243 74 137.15625 C 75.243529 139.39243 77.637589 140.90625 80.375 140.90625 C 84.392851 140.90625 87.6875 137.64298 87.6875 133.625 L 87.6875 120.03125 L 85.875 120.03125 L 85.875 133.625 C 85.875 136.66502 83.415197 139.09375 80.375 139.09375 C 77.334799 139.09375 74.90625 136.66502 74.90625 133.625 L 74.90625 120.03125 L 73.09375 120.03125 L 73.09375 133.625 C 73.09375 136.66518 70.634983 139.09375 67.59375 139.09375 C 64.554582 139.09375 62.125 136.66502 62.125 133.625 L 62.125 120.03125 L 60.3125 120.03125 z M 180.65625 120.03125 L 180.65625 130.0625 C 180.65625 136.04708 185.51457 140.90625 191.5 140.90625 C 197.48544 140.90625 202.375 136.04718 202.375 130.0625 L 202.375 120.03125 L 200.5625 120.03125 L 200.5625 130.0625 C 200.5625 135.06882 196.50744 139.09375 191.5 139.09375 C 186.49257 139.09375 182.46875 135.06892 182.46875 130.0625 L 182.46875 120.03125 L 180.65625 120.03125 z M 165.03125 121 C 170.03909 121 174.09375 125.05467 174.09375 130.0625 C 174.09375 135.07034 170.03909 139.125 165.03125 139.125 C 160.02342 139.125 156 135.07034 156 130.0625 C 156 125.05467 160.02342 121 165.03125 121 z M 218.21875 121 L 227.375 121 C 227.382 122.19758 227.4321 130.44662 227.375 133.59375 C 227.3494 134.99421 226.58126 136.39946 225.46875 137.4375 C 224.35624 138.47554 222.91652 139.09375 221.78125 139.09375 L 218.21875 139.09375 C 213.21132 139.09375 209.1875 135.06892 209.1875 130.0625 C 209.1875 125.05499 213.21132 121 218.21875 121 z M 44.03125 121.03125 C 49.038583 121.03125 53.0625 125.05517 53.0625 130.0625 C 53.0625 135.06984 49.038583 139.09375 44.03125 139.09375 C 39.023917 139.09375 34.96875 135.06984 34.96875 130.0625 C 34.96875 125.05517 39.023917 121.03125 44.03125 121.03125 z "
+   id="circle238" />
+
+
+
+
+
+
+
+
+
+
+</svg>
\ No newline at end of file
diff --git a/core/img/logo-wide.png b/core/img/logo-wide.png
index b2c16a0f60a6991eb6a98109d017b48e3b3a3a3b..ea10828db5e9ce5e002f0e5f0bd07f96456960ea 100644
Binary files a/core/img/logo-wide.png and b/core/img/logo-wide.png differ
diff --git a/core/img/logo-wide.svg b/core/img/logo-wide.svg
index 73b37cc7aaaeadf755a5424e48ea48d26508c7a4..37fc0007479055e1324f465ee53f01cd6fd31a16 100644
--- a/core/img/logo-wide.svg
+++ b/core/img/logo-wide.svg
@@ -14,16 +14,16 @@
    id="Layer_1"
    x="0px"
    y="0px"
-   width="140"
+   width="147.33263"
    height="32"
-   viewBox="0 0 139.99999 32"
+   viewBox="0 0 147.33262 32"
    enable-background="new 0 0 595.275 311.111"
    xml:space="preserve"
-   inkscape:version="0.48.1 r9760"
+   inkscape:version="0.48.2 r9819"
    sodipodi:docname="logo-wide.svg"><metadata
    id="metadata327"><rdf:RDF><cc:Work
        rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
-         rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title /></cc:Work></rdf:RDF></metadata><defs
+         rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
    id="defs325"><linearGradient
    inkscape:collect="always"
    xlink:href="#SVGID_1_"
@@ -260,18 +260,22 @@
    inkscape:pageopacity="0"
    inkscape:pageshadow="2"
    inkscape:window-width="1280"
-   inkscape:window-height="776"
+   inkscape:window-height="774"
    id="namedview323"
    showgrid="false"
-   inkscape:zoom="3.4068286"
-   inkscape:cx="79.998916"
-   inkscape:cy="32.107419"
+   inkscape:zoom="4.8179832"
+   inkscape:cx="73.94445"
+   inkscape:cy="21.619195"
    inkscape:window-x="0"
-   inkscape:window-y="24"
+   inkscape:window-y="26"
    inkscape:window-maximized="1"
    inkscape:current-layer="Layer_1"
    showguides="true"
-   inkscape:guide-bbox="true" />
+   inkscape:guide-bbox="true"
+   fit-margin-top="0"
+   fit-margin-left="0"
+   fit-margin-right="0"
+   fit-margin-bottom="0" />
 <pattern
    y="565.223"
    width="69"
@@ -745,131 +749,43 @@
 
 
 <g
-   style="display:inline"
-   id="g3154"
-   transform="matrix(0.21384268,0,0,0.21384268,31.655324,-22.278409)"><circle
-     style="fill:none;stroke:#ffffff;stroke-width:4;stroke-opacity:1"
-     id="circle238"
-     r="21.999001"
-     cy="225.17101"
-     cx="97.311996"
-     sodipodi:cx="97.311996"
-     sodipodi:cy="225.17101"
-     sodipodi:rx="21.999001"
-     sodipodi:ry="21.999001"
-     d="m 119.311,225.17101 c 0,12.14971 -9.84929,21.999 -21.999004,21.999 -12.149712,0 -21.999,-9.84929 -21.999,-21.999 0,-12.14972 9.849288,-21.99901 21.999,-21.99901 12.149714,0 21.999004,9.84929 21.999004,21.99901 z" /><circle
-     style="fill:none;stroke:#ffffff;stroke-width:4;stroke-opacity:1"
-     id="circle240"
-     r="22.000999"
-     cy="225.17101"
-     cx="364.82501"
-     sodipodi:cx="364.82501"
-     sodipodi:cy="225.17101"
-     sodipodi:rx="22.000999"
-     sodipodi:ry="22.000999"
-     d="m 386.82601,225.17101 c 0,12.15081 -9.85018,22.00099 -22.001,22.00099 -12.15081,0 -22.001,-9.85018 -22.001,-22.00099 0,-12.15082 9.85019,-22.001 22.001,-22.001 12.15082,0 22.001,9.85018 22.001,22.001 z" /><path
-     style="fill:none;stroke:#ffffff;stroke-width:4;stroke-opacity:1"
-     id="path242"
-     d="m 135.313,202.966 v 30.074 c 0,7.801 6.324,14.123 14.123,14.123 7.803,0 14.125,-6.322 14.125,-14.123 0,-0.004 0,-30.074 0,-30.074"
-     inkscape:connector-curvature="0" /><path
-     style="fill:none;stroke:#ffffff;stroke-width:4;stroke-opacity:1"
-     id="path244"
-     d="m 163.561,202.966 v 30.074 c 0,7.801 6.324,14.123 14.125,14.123 7.801,0 14.125,-6.322 14.125,-14.123 0,-0.004 0,-30.074 0,-30.074"
-     inkscape:connector-curvature="0" /><path
-     style="fill:none;stroke:#ffffff;stroke-width:4;stroke-opacity:1"
-     id="path246"
-     d="m 319.578,162.962 v 70.078 c 0,7.801 6.322,14.123 14.123,14.123"
-     inkscape:connector-curvature="0" /><path
-     style="fill:none;stroke:#ffffff;stroke-width:4;stroke-opacity:1"
-     id="path248"
-     d="m 208.317,247.169 v -22.201 c 0,-12.15 9.85,-22 22,-22 12.152,0 22.002,9.85 22.002,22 0,0.006 0,22.201 0,22.201"
-     inkscape:connector-curvature="0" /><path
-     style="fill:none;stroke:#ffffff;stroke-width:4;stroke-opacity:1"
-     id="path250"
-     d="m 401.322,202.966 v 22.205 c 0,12.148 9.85,21.998 22,21.998 12.15,0 22.002,-9.85 22.002,-21.998 0,-0.008 0,-22.205 0,-22.205"
-     inkscape:connector-curvature="0" /><path
-     style="fill:none;stroke:#ffffff;stroke-width:4;stroke-opacity:1"
-     id="path252"
-     d="m 303.146,176.839 c -19.421,0 -35.167,15.744 -35.167,35.166 0,19.422 15.746,35.164 35.167,35.164"
-     inkscape:connector-curvature="0" /><polyline
-     style="fill:none;stroke:#ffffff;stroke-width:4;stroke-opacity:1"
-     id="polyline254"
-     points="504.596,162.962 504.596,203.134 504.596,202.155 " /><path
-     style="fill:none;stroke:#ffffff;stroke-width:4;stroke-opacity:1"
-     id="path256"
-     d="m 490.236,247.157 c -4.275,0 -7.844,0 -7.848,0 -12.15,0 -22,-9.85 -22,-21.998 0,-12.15 9.85,-22 22,-22 l 22.207,-0.025 c 0,0 0.137,22.342 0,29.895 -0.138,7.552 -7.968,14.128 -14.359,14.128 z"
-     inkscape:connector-curvature="0" /></g><circle
-   sodipodi:ry="20.332001"
-   sodipodi:rx="20.332001"
-   sodipodi:cy="78.911003"
-   sodipodi:cx="288.49399"
-   style="fill:#ffffff;fill-opacity:1;stroke:#1d2d44;stroke-width:4;stroke-opacity:1;display:inline"
-   id="circle265"
-   r="20.332001"
-   cy="78.911003"
-   cx="288.49399"
-   transform="matrix(0.21384268,0,0,0.21384268,-45.328041,-8.5924791)" /><circle
-   sodipodi:ry="37.242001"
-   sodipodi:rx="37.242001"
-   sodipodi:cy="149.577"
-   sodipodi:cx="251.211"
-   style="fill:#ffffff;fill-opacity:1;stroke:#1d2d44;stroke-width:4;stroke-opacity:1;display:inline"
-   id="circle272"
-   r="37.242001"
-   cy="149.577"
-   cx="251.211"
-   transform="matrix(0.21384268,0,0,0.21384268,-45.328041,-8.5924791)" /><circle
-   sodipodi:ry="40.261002"
-   sodipodi:rx="40.261002"
-   sodipodi:cy="124.796"
-   sodipodi:cx="293.22501"
-   style="fill:#ffffff;fill-opacity:1;stroke:#1d2d44;stroke-width:4;stroke-opacity:1;display:inline"
-   id="circle279"
-   r="40.261002"
-   cy="124.796"
-   cx="293.22501"
-   transform="matrix(0.21384268,0,0,0.21384268,-45.328041,-8.5924791)" /><circle
-   sodipodi:ry="37.242001"
-   sodipodi:rx="37.242001"
-   sodipodi:cy="108.472"
-   sodipodi:cx="375.33401"
-   style="fill:#ffffff;fill-opacity:1;stroke:#1d2d44;stroke-width:4;stroke-opacity:1;display:inline"
-   id="circle286"
-   r="37.242001"
-   cy="108.472"
-   cx="375.33401"
-   transform="matrix(0.21384268,0,0,0.21384268,-45.328041,-8.5924791)" /><circle
-   sodipodi:ry="37.241001"
-   sodipodi:rx="37.241001"
-   sodipodi:cy="79.503998"
-   sodipodi:cx="334.49301"
-   style="fill:#ffffff;fill-opacity:1;stroke:#1d2d44;stroke-width:4;stroke-opacity:1;display:inline"
-   id="circle293"
-   r="37.241001"
-   cy="79.503998"
-   cx="334.49301"
-   transform="matrix(0.21384268,0,0,0.21384268,-45.328041,-8.5924791)" /><circle
-   sodipodi:ry="40.261002"
-   sodipodi:rx="40.261002"
-   sodipodi:cy="147.563"
-   sodipodi:cx="413.16299"
-   style="fill:#ffffff;fill-opacity:1;stroke:#1d2d44;stroke-width:4;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline"
-   id="circle307"
-   r="40.261002"
-   cy="147.563"
-   cx="413.16299"
-   transform="matrix(0.21384268,0,0,0.21384268,-45.328041,-8.5924791)" /><circle
-   sodipodi:ry="21.299"
-   sodipodi:rx="21.299"
-   sodipodi:cy="166.011"
-   sodipodi:cx="290.76199"
-   style="fill:#ffffff;fill-opacity:1;stroke:#1d2d44;stroke-width:4;stroke-opacity:1;display:inline"
-   id="circle314"
-   r="21.299"
-   cy="166.011"
-   cx="290.76199"
-   transform="matrix(0.21384268,0,0,0.21384268,-45.328041,-8.5924791)" /><path
-   inkscape:connector-curvature="0"
-   style="fill:#ffffff;fill-opacity:1;stroke:#1d2d44;stroke-width:0.8553707;stroke-opacity:1;display:inline"
-   id="path321"
-   d="m 39.804227,20.419344 c 0,6.062012 -4.91496,10.976117 -10.9774,10.976117 -6.06244,0 -10.977185,-4.914105 -10.977185,-10.976117 0,-6.062654 4.914959,-10.9771861 10.977185,-10.9771861 6.062226,0 10.9774,4.9145321 10.9774,10.9771861 z" /></svg>
\ No newline at end of file
+   id="g4811"
+   transform="matrix(0.49975595,0,0,0.49975595,82.761244,31.693374)"><path
+     inkscape:connector-curvature="0"
+     id="path4576"
+     d="m 43.646673,-38.417697 0,31.7187492 c 0,4.01782 3.29464,7.28125004 7.3125,7.28125004 l 0,-1.81250004 c -3.04019,0 -5.5,-2.42857 -5.5,-5.46875 l 0,-31.7187492 -1.8125,0 z m 83.718747,0 0,17.281249 -9.15625,0 c -5.98544,0 -10.84375,4.88951 -10.84375,10.875 0,5.9845802 4.85831,10.84375024 10.84375,10.84375024 l 2.65625,0 0.90625,0 c 1.75589,0 3.50927,-0.85279 4.90625,-2.15625004 1.39697,-1.30346 2.46318,-3.10906 2.5,-5.125 0.0628,-3.4602002 0,-13.5312502 0,-13.5312502 l 0,-0.4375 0,-17.749999 -1.8125,0 z m -90.249997,5.375 c -9.27468,0 -16.8125,7.537289 -16.8125,16.812499 0,9.2752102 7.53789,16.81250024 16.8125,16.81250024 l 0,-1.81250004 c -8.29679,0 -15,-6.70281 -15,-15.0000002 0,-8.29719 6.70326,-15 15,-15 l 0,-1.812499 z M 4.1779234,-21.198948 c -5.98544,0 -10.84375,4.85826 -10.84375,10.84375 l 0,10.03125024 1.8125,0 0,-10.03125024 c 0,-5.00751 4.02380001,-9.0625 9.03125,-9.0625 5.00842,0 9.0624996,4.05499 9.0624996,9.0625 l 0,10.03125024 1.8125,0 0,-10.03125024 c 0,-5.98549 -4.88875,-10.84375 -10.8749996,-10.84375 z m 60.8437496,0.0625 c -5.98578,0 -10.84375,4.88923 -10.84375,10.875 0,5.9857802 4.85797,10.87500024 10.84375,10.87500024 5.98577,0 10.875,-4.88922004 10.875,-10.87500024 0,-5.98577 -4.88923,-10.875 -10.875,-10.875 z m -121,0.0312 c -0.605,0 -1.20257,0.0608 -1.78125,0.15625 0.13317,0.58261 0.26534,1.17968 0.34375,1.78125 0.4646,-0.0728 0.95217,-0.125 1.4375,-0.125 5.00732,0 9.03125,4.02392 9.03125,9.03125 0,5.0073402 -4.02393,9.0312502 -9.03125,9.0312502 -2.45581,0 -4.71206,-0.95417 -6.34375,-2.53125 -0.39944,0.43386 -0.81248,0.85451 -1.25,1.25 1.96253,1.90787004 4.64884,3.09375004 7.59375,3.09375004 5.98526,0 10.84375,-4.85847004 10.84375,-10.84375024 0,-5.98527 -4.85849,-10.84375 -10.84375,-10.84375 z m 16.28125,0.8125 0,13.5937502 c 0,4.01798 3.26418,7.28125004 7.28125,7.28125004 2.73793,0 5.15364,-1.51382 6.40625,-3.75000004 1.24352,2.23618004 3.63758,3.75000004 6.375,3.75000004 4.01785,0 7.3125,-3.26327004 7.3125,-7.28125004 l 0,-13.5937502 -1.8125,0 0,13.5937502 c 0,3.04002 -2.45981,5.46875 -5.5,5.46875 -3.04021,0 -5.46875,-2.42873 -5.46875,-5.46875 l 0,-13.5937502 -1.8125,0 0,13.5937502 c 0,3.04018 -2.45878,5.46875 -5.5,5.46875 -3.03918,0 -5.46875,-2.42873 -5.46875,-5.46875 l 0,-13.5937502 -1.8125,0 z m 120.34375,0 0,10.03125 c 0,5.9845802 4.85831,10.84375024 10.84375,10.84375024 5.98543,0 10.874997,-4.85907004 10.874997,-10.84375024 l 0,-10.03125 -1.8125,0 0,10.03125 c 0,5.0063202 -4.055067,9.0312502 -9.062497,9.0312502 -5.00743,0 -9.03125,-4.02483 -9.03125,-9.0312502 l 0,-10.03125 -1.8125,0 z m -15.625,0.96875 c 5.00783,0 9.0625,4.05467 9.0625,9.0625 0,5.0078402 -4.05467,9.0625002 -9.0625,9.0625002 -5.00784,0 -9.03125,-4.05466 -9.03125,-9.0625002 0,-5.00783 4.02341,-9.0625 9.03125,-9.0625 z m 53.187497,0 9.15625,0 c 0.007,1.19758 0.0571,9.4466202 0,12.5937502 -0.0256,1.40046 -0.79375,2.80571 -1.90625,3.84375 -1.11251,1.03804 -2.55224,1.65625 -3.6875,1.65625 l -3.5625,0 c -5.00743,0 -9.03125,-4.02483 -9.03125,-9.0312502 0,-5.00751 4.02382,-9.0625 9.03125,-9.0625 z"
+     style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;baseline-shift:baseline;color:#000000;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:4;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Sans;-inkscape-font-specification:Sans" /><g
+     transform="translate(-263.29083,-71.636453)"
+     id="g4665"><path
+       id="path4645"
+       d="m 130.5,15.593752 c -4.59084,0 -8.28125,3.721655 -8.28125,8.3125 0,1.48638 0.38348,2.890843 1.0625,4.09375 2.77029,-1.562756 5.97306,-2.46875 9.375,-2.46875 0.32831,0 0.64453,0.01333 0.96875,0.03125 -0.0367,-0.465388 -0.0625,-0.931533 -0.0625,-1.40625 0,-2.556994 0.55537,-4.989858 1.53125,-7.1875 -1.31394,-0.881089 -2.88818,-1.375 -4.59375,-1.375 z"
+       style="fill:#ffffff;fill-opacity:1;stroke:none"
+       inkscape:connector-curvature="0" /><path
+       id="path4647"
+       d="m 113.65625,39.937502 c -8.8157,0 -15.968749,7.090554 -15.968749,15.90625 0,8.8157 7.153049,15.96875 15.968749,15.96875 3.35538,0 6.46362,-1.04542 9.03125,-2.8125 -1.06099,-1.64866 -1.6875,-3.61973 -1.6875,-5.71875 0,-1.08945 0.16075,-2.1361 0.46875,-3.125 -4.80686,-3.473851 -7.9375,-9.126885 -7.9375,-15.5 0,-1.619269 0.21338,-3.185025 0.59375,-4.6875 -0.15788,-0.0046 -0.30973,-0.03125 -0.46875,-0.03125 z"
+       style="fill:#ffffff;fill-opacity:1;stroke:none"
+       inkscape:connector-curvature="0" /><path
+       id="path4649"
+       d="m 132.65625,27.343752 c -9.56997,0 -17.3125,7.742526 -17.3125,17.3125 0,5.633641 2.68421,10.620877 6.84375,13.78125 1.75358,-3.382155 5.27556,-5.6875 9.34375,-5.6875 0.49168,0 0.96362,0.05959 1.4375,0.125 -0.14876,-1.08229 -0.21875,-2.189579 -0.21875,-3.3125 0,-5.368909 1.74763,-10.333753 4.71875,-14.34375 -1.77849,-2.225459 -3.05125,-4.899445 -3.59375,-7.8125 -0.40207,-0.02785 -0.80954,-0.0625 -1.21875,-0.0625 z"
+       style="fill:#ffffff;fill-opacity:1;stroke:none"
+       inkscape:connector-curvature="0" /><path
+       id="path4651"
+       d="m 169.8125,21.312502 c -0.33916,0 -0.66608,0.04164 -1,0.0625 0.14444,0.910711 0.25,1.830299 0.25,2.78125 0,1.479932 -0.18822,2.907986 -0.53125,4.28125 4.02188,2.225766 7.36189,5.556058 9.5625,9.59375 2.28254,-1.188296 4.82877,-1.94388 7.53125,-2.125 -0.69648,-8.167989 -7.4633,-14.59375 -15.8125,-14.59375 z"
+       style="fill:#ffffff;fill-opacity:1;stroke:none"
+       inkscape:connector-curvature="0" /><path
+       id="path4653"
+       d="m 151.3125,8.2187518 c -8.81544,0 -15.9375,7.1220542 -15.9375,15.9375002 0,3.633753 1.20998,6.978162 3.25,9.65625 4.42552,-5.122236 10.95719,-8.375 18.25,-8.375 3.56797,0 6.95137,0.794519 10,2.1875 0.24683,-1.116262 0.375,-2.277207 0.375,-3.46875 0,-8.815446 -7.12205,-15.9375002 -15.9375,-15.9375002 z"
+       style="fill:#ffffff;fill-opacity:1;stroke:none"
+       inkscape:connector-curvature="0" /><path
+       id="path4657"
+       d="m 186.90625,37.656252 c -2.90588,0 -5.62795,0.741879 -8.03125,2 1.36467,3.02284 2.125,6.376782 2.125,9.90625 0,6.608637 -2.65704,12.60935 -6.96875,16.96875 3.16753,3.51662 7.76324,5.71875 12.875,5.71875 9.56997,0 17.3125,-7.74253 17.3125,-17.3125 0,-9.569974 -7.74253,-17.28125 -17.3125,-17.28125 z"
+       style="fill:#ffffff;fill-opacity:1;stroke:none"
+       inkscape:connector-curvature="0" /><path
+       id="path4659"
+       d="m 131.53125,54.562502 c -4.83244,0 -8.71875,3.886306 -8.71875,8.71875 0,4.83244 3.88631,8.75 8.71875,8.75 3.70413,0 6.84821,-2.31132 8.125,-5.5625 -3.11542,-3.17302 -5.35443,-7.220982 -6.34375,-11.71875 -0.57893,-0.119719 -1.16654,-0.1875 -1.78125,-0.1875 z"
+       style="fill:#ffffff;fill-opacity:1;stroke:none"
+       inkscape:connector-curvature="0" /><path
+       id="path4661"
+       d="m 156.875,27.250002 c -12.33545,0 -22.3125,9.976221 -22.3125,22.3125 0,12.33495 9.97654,22.3125 22.3125,22.3125 12.33596,0 22.3125,-9.97757 22.3125,-22.3125 0,-12.336257 -9.97705,-22.3125 -22.3125,-22.3125 z"
+       style="fill:#ffffff;fill-opacity:1;stroke:none"
+       inkscape:connector-curvature="0" /></g></g></svg>
\ No newline at end of file
diff --git a/core/img/logo.png b/core/img/logo.png
new file mode 100644
index 0000000000000000000000000000000000000000..8177c4cdba196fe6fc2521dd46f8bd06a257beb3
Binary files /dev/null and b/core/img/logo.png differ
diff --git a/core/img/logo.svg b/core/img/logo.svg
index c1df6cb7153df39f0a777d1ae2d7870e67e8b1b5..bd928cccfa28ed2db23d536fee53f87d818341ca 100644
--- a/core/img/logo.svg
+++ b/core/img/logo.svg
@@ -14,94 +14,97 @@
    id="Layer_1"
    x="0px"
    y="0px"
-   width="595.275px"
-   height="311.111px"
-   viewBox="0 0 595.275 311.111"
+   width="250.00002"
+   height="118.22803"
+   viewBox="0 0 250.00001 118.22802"
    enable-background="new 0 0 595.275 311.111"
    xml:space="preserve"
-   inkscape:version="0.48.1 r9760"
-   sodipodi:docname="owncloud-logo.svg"><metadata
+   inkscape:version="0.48.2 r9819"
+   sodipodi:docname="logo-inverted.svg"
+   inkscape:export-filename="/home/user/owncloud/core/img/logo-sticker.png"
+   inkscape:export-xdpi="300.00223"
+   inkscape:export-ydpi="300.00223"><metadata
    id="metadata327"><rdf:RDF><cc:Work
        rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
-         rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></cc:Work></rdf:RDF></metadata><defs
+         rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
    id="defs325"><linearGradient
    inkscape:collect="always"
    xlink:href="#SVGID_1_"
    id="linearGradient3353"
    gradientUnits="userSpaceOnUse"
-   x1="288.4941"
-   y1="55.8882"
-   x2="288.4941"
-   y2="339.2219" /><linearGradient
+   x1="288.49411"
+   y1="55.888199"
+   x2="288.49411"
+   y2="339.22189" /><linearGradient
    inkscape:collect="always"
    xlink:href="#SVGID_2_"
    id="linearGradient3355"
    gradientUnits="userSpaceOnUse"
    x1="251.2114"
-   y1="55.8882"
+   y1="55.888199"
    x2="251.2114"
-   y2="339.2216" /><linearGradient
+   y2="339.22159" /><linearGradient
    inkscape:collect="always"
    xlink:href="#SVGID_3_"
    id="linearGradient3357"
    gradientUnits="userSpaceOnUse"
-   x1="293.2246"
-   y1="55.8882"
-   x2="293.2246"
-   y2="339.2217" /><linearGradient
+   x1="293.22461"
+   y1="55.888199"
+   x2="293.22461"
+   y2="339.22171" /><linearGradient
    inkscape:collect="always"
    xlink:href="#SVGID_4_"
    id="linearGradient3359"
    gradientUnits="userSpaceOnUse"
-   x1="375.334"
-   y1="55.8882"
-   x2="375.334"
-   y2="339.2216" /><linearGradient
+   x1="375.33401"
+   y1="55.888199"
+   x2="375.33401"
+   y2="339.22159" /><linearGradient
    inkscape:collect="always"
    xlink:href="#SVGID_5_"
    id="linearGradient3361"
    gradientUnits="userSpaceOnUse"
-   x1="334.4941"
-   y1="55.8882"
-   x2="334.4941"
-   y2="339.2216" /><linearGradient
+   x1="334.49411"
+   y1="55.888199"
+   x2="334.49411"
+   y2="339.22159" /><linearGradient
    inkscape:collect="always"
    xlink:href="#SVGID_6_"
    id="linearGradient3363"
    gradientUnits="userSpaceOnUse"
-   x1="458.4268"
+   x1="458.42679"
    y1="55.8867"
-   x2="458.4268"
+   x2="458.42679"
    y2="339.2236" /><linearGradient
    inkscape:collect="always"
    xlink:href="#SVGID_7_"
    id="linearGradient3365"
    gradientUnits="userSpaceOnUse"
-   x1="413.1631"
-   y1="55.8882"
-   x2="413.1631"
-   y2="339.2213" /><linearGradient
+   x1="413.16309"
+   y1="55.888199"
+   x2="413.16309"
+   y2="339.22131" /><linearGradient
    inkscape:collect="always"
    xlink:href="#SVGID_8_"
    id="linearGradient3367"
    gradientUnits="userSpaceOnUse"
-   x1="290.7617"
+   x1="290.76169"
    y1="55.8867"
-   x2="290.7617"
+   x2="290.76169"
    y2="339.2236" /><linearGradient
    inkscape:collect="always"
    xlink:href="#SVGID_9_"
    id="linearGradient3369"
    gradientUnits="userSpaceOnUse"
-   x1="346.7734"
-   y1="55.8882"
-   x2="346.7734"
-   y2="339.2212" />
+   x1="346.77341"
+   y1="55.888199"
+   x2="346.77341"
+   y2="339.22119" />
 	<linearGradient
-   y2="339.2219"
-   x2="288.4941"
-   y1="55.8882"
-   x1="288.4941"
+   y2="339.22189"
+   x2="288.49411"
+   y1="55.888199"
+   x1="288.49411"
    gradientUnits="userSpaceOnUse"
    id="SVGID_1_">
 		<stop
@@ -115,9 +118,9 @@
 	</linearGradient>
 	
 	<linearGradient
-   y2="339.2216"
+   y2="339.22159"
    x2="251.2114"
-   y1="55.8882"
+   y1="55.888199"
    x1="251.2114"
    gradientUnits="userSpaceOnUse"
    id="SVGID_2_">
@@ -132,10 +135,10 @@
 	</linearGradient>
 	
 	<linearGradient
-   y2="339.2217"
-   x2="293.2246"
-   y1="55.8882"
-   x1="293.2246"
+   y2="339.22171"
+   x2="293.22461"
+   y1="55.888199"
+   x1="293.22461"
    gradientUnits="userSpaceOnUse"
    id="SVGID_3_">
 		<stop
@@ -149,10 +152,10 @@
 	</linearGradient>
 	
 	<linearGradient
-   y2="339.2216"
-   x2="375.334"
-   y1="55.8882"
-   x1="375.334"
+   y2="339.22159"
+   x2="375.33401"
+   y1="55.888199"
+   x1="375.33401"
    gradientUnits="userSpaceOnUse"
    id="SVGID_4_">
 		<stop
@@ -166,10 +169,10 @@
 	</linearGradient>
 	
 	<linearGradient
-   y2="339.2216"
-   x2="334.4941"
-   y1="55.8882"
-   x1="334.4941"
+   y2="339.22159"
+   x2="334.49411"
+   y1="55.888199"
+   x1="334.49411"
    gradientUnits="userSpaceOnUse"
    id="SVGID_5_">
 		<stop
@@ -184,9 +187,9 @@
 	
 	<linearGradient
    y2="339.2236"
-   x2="458.4268"
+   x2="458.42679"
    y1="55.8867"
-   x1="458.4268"
+   x1="458.42679"
    gradientUnits="userSpaceOnUse"
    id="SVGID_6_">
 		<stop
@@ -200,10 +203,10 @@
 	</linearGradient>
 	
 	<linearGradient
-   y2="339.2213"
-   x2="413.1631"
-   y1="55.8882"
-   x1="413.1631"
+   y2="339.22131"
+   x2="413.16309"
+   y1="55.888199"
+   x1="413.16309"
    gradientUnits="userSpaceOnUse"
    id="SVGID_7_">
 		<stop
@@ -218,9 +221,9 @@
 	
 	<linearGradient
    y2="339.2236"
-   x2="290.7617"
+   x2="290.76169"
    y1="55.8867"
-   x1="290.7617"
+   x1="290.76169"
    gradientUnits="userSpaceOnUse"
    id="SVGID_8_">
 		<stop
@@ -234,10 +237,10 @@
 	</linearGradient>
 	
 	<linearGradient
-   y2="339.2212"
-   x2="346.7734"
-   y1="55.8882"
-   x1="346.7734"
+   y2="339.22119"
+   x2="346.77341"
+   y1="55.888199"
+   x1="346.77341"
    gradientUnits="userSpaceOnUse"
    id="SVGID_9_">
 		<stop
@@ -260,16 +263,23 @@
    inkscape:pageopacity="0"
    inkscape:pageshadow="2"
    inkscape:window-width="1280"
-   inkscape:window-height="776"
+   inkscape:window-height="774"
    id="namedview323"
    showgrid="false"
-   inkscape:zoom="0.85170716"
-   inkscape:cx="438.93424"
-   inkscape:cy="155.5555"
+   inkscape:zoom="1"
+   inkscape:cx="33.895785"
+   inkscape:cy="55.236805"
    inkscape:window-x="0"
-   inkscape:window-y="24"
+   inkscape:window-y="26"
    inkscape:window-maximized="1"
-   inkscape:current-layer="Layer_1" />
+   inkscape:current-layer="Layer_1"
+   units="mm"
+   fit-margin-top="0"
+   fit-margin-left="0"
+   fit-margin-right="0"
+   fit-margin-bottom="0"
+   showguides="true"
+   inkscape:guide-bbox="true" />
 <pattern
    y="565.223"
    width="69"
@@ -730,161 +740,20 @@
 		</g>
 	</g>
 </pattern>
-<rect
-   fill="#FFFFFF"
-   width="595.275"
-   height="311.111"
-   id="rect236"
-   style="fill:#1d2d44;fill-opacity:1" />
-<circle
-   fill="none"
-   stroke="#E76E34"
-   stroke-width="4"
-   cx="97.312"
-   cy="225.171"
-   r="21.999"
-   id="circle238"
-   style="stroke:#ffffff;stroke-opacity:1" />
-<circle
-   fill="none"
-   stroke="#567B8F"
-   stroke-width="4"
-   cx="364.825"
-   cy="225.171"
-   r="22.001"
-   id="circle240"
-   style="stroke:#ffffff;stroke-opacity:1" />
-<path
-   fill="none"
-   stroke="#E76E34"
-   stroke-width="4"
-   d="M135.313,202.966v30.074c0,7.801,6.324,14.123,14.123,14.123  c7.803,0,14.125-6.322,14.125-14.123c0-0.004,0-30.074,0-30.074"
-   id="path242"
-   style="stroke:#ffffff;stroke-opacity:1" />
-<path
-   fill="none"
-   stroke="#E76E34"
-   stroke-width="4"
-   d="M163.561,202.966v30.074c0,7.801,6.324,14.123,14.125,14.123  s14.125-6.322,14.125-14.123c0-0.004,0-30.074,0-30.074"
-   id="path244"
-   style="stroke:#ffffff;stroke-opacity:1" />
-<path
-   fill="none"
-   stroke="#567B8F"
-   stroke-width="4"
-   d="M319.578,162.962v70.078c0,7.801,6.322,14.123,14.123,14.123"
-   id="path246"
-   style="stroke:#ffffff;stroke-opacity:1" />
-<path
-   fill="none"
-   stroke="#E76E34"
-   stroke-width="4"
-   d="M208.317,247.169v-22.201c0-12.15,9.85-22,22-22  c12.152,0,22.002,9.85,22.002,22c0,0.006,0,22.201,0,22.201"
-   id="path248"
-   style="stroke:#ffffff;stroke-opacity:1" />
-<path
-   fill="none"
-   stroke="#567B8F"
-   stroke-width="4"
-   d="M401.322,202.966v22.205c0,12.148,9.85,21.998,22,21.998  s22.002-9.85,22.002-21.998c0-0.008,0-22.205,0-22.205"
-   id="path250"
-   style="stroke:#ffffff;stroke-opacity:1" />
-<path
-   fill="none"
-   stroke="#567B8F"
-   stroke-width="4"
-   d="M303.146,176.839c-19.421,0-35.167,15.744-35.167,35.166  s15.746,35.164,35.167,35.164"
-   id="path252"
-   style="stroke:#ffffff;stroke-opacity:1" />
-<polyline
-   fill="none"
-   stroke="#567B8F"
-   stroke-width="4"
-   points="504.596,162.962 504.596,203.134 504.596,202.155 "
-   id="polyline254"
-   style="stroke:#ffffff;stroke-opacity:1" />
+
 <path
-   fill="none"
-   stroke="#567B8F"
-   stroke-width="4"
-   d="M490.236,247.157c-4.275,0-7.844,0-7.848,0c-12.15,0-22-9.85-22-21.998  c0-12.15,9.85-22,22-22l22.207-0.025c0,0,0.137,22.342,0,29.895C504.457,240.581,496.627,247.157,490.236,247.157z"
-   id="path256"
-   style="stroke:#ffffff;stroke-opacity:1" />
-<circle
-   sodipodi:ry="20.332001"
-   sodipodi:rx="20.332001"
-   sodipodi:cy="78.911003"
-   sodipodi:cx="288.49399"
-   style="fill:#ffffff;stroke:#1d2d44;stroke-width:4;fill-opacity:1;stroke-opacity:1"
-   id="circle265"
-   r="20.332001"
-   cy="78.911003"
-   cx="288.49399" /><circle
-   sodipodi:ry="37.242001"
-   sodipodi:rx="37.242001"
-   sodipodi:cy="149.577"
-   sodipodi:cx="251.211"
-   style="fill:#ffffff;stroke:#1d2d44;stroke-width:4;fill-opacity:1;stroke-opacity:1"
-   id="circle272"
-   r="37.242001"
-   cy="149.577"
-   cx="251.211" /><circle
-   sodipodi:ry="40.261002"
-   sodipodi:rx="40.261002"
-   sodipodi:cy="124.796"
-   sodipodi:cx="293.22501"
-   style="fill:#ffffff;stroke:#1d2d44;stroke-width:4;fill-opacity:1;stroke-opacity:1"
-   id="circle279"
-   r="40.261002"
-   cy="124.796"
-   cx="293.22501" /><circle
-   sodipodi:ry="37.242001"
-   sodipodi:rx="37.242001"
-   sodipodi:cy="108.472"
-   sodipodi:cx="375.33401"
-   style="fill:#ffffff;stroke:#1d2d44;stroke-width:4;fill-opacity:1;stroke-opacity:1"
-   id="circle286"
-   r="37.242001"
-   cy="108.472"
-   cx="375.33401" /><circle
-   sodipodi:ry="37.241001"
-   sodipodi:rx="37.241001"
-   sodipodi:cy="79.503998"
-   sodipodi:cx="334.49301"
-   style="fill:#ffffff;stroke:#1d2d44;stroke-width:4;fill-opacity:1;stroke-opacity:1"
-   id="circle293"
-   r="37.241001"
-   cy="79.503998"
-   cx="334.49301" /><circle
-   sodipodi:ry="21.299999"
-   sodipodi:rx="21.299999"
-   sodipodi:cy="163.95799"
-   sodipodi:cx="458.427"
-   style="fill:#ffffff;stroke:#1d2d44;stroke-width:4;fill-opacity:1;stroke-opacity:1"
-   id="circle300"
-   r="21.299999"
-   cy="163.95799"
-   cx="458.427" /><circle
-   sodipodi:ry="40.261002"
-   sodipodi:rx="40.261002"
-   sodipodi:cy="147.563"
-   sodipodi:cx="413.16299"
-   style="fill:#ffffff;stroke:#1d2d44;stroke-width:4;fill-opacity:1;stroke-opacity:1"
-   id="circle307"
-   r="40.261002"
-   cy="147.563"
-   cx="413.16299" /><circle
-   sodipodi:ry="21.299"
-   sodipodi:rx="21.299"
-   sodipodi:cy="166.011"
-   sodipodi:cx="290.76199"
-   style="fill:#ffffff;stroke:#1d2d44;stroke-width:4;fill-opacity:1;stroke-opacity:1"
-   id="circle314"
-   r="21.299"
-   cy="166.011"
-   cx="290.76199" /><path
-   inkscape:connector-curvature="0"
-   style="fill:#ffffff;stroke:#1d2d44;stroke-width:4;fill-opacity:1;stroke-opacity:1"
-   id="path321"
-   d="m 398.107,135.669 c 0,28.348 -22.984,51.328 -51.334,51.328 -28.35,0 -51.333,-22.98 -51.333,-51.328 0,-28.351 22.984,-51.333 51.333,-51.333 28.349,0 51.334,22.982 51.334,51.333 z" />
+   style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;baseline-shift:baseline;color:#000000;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:4;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Sans;-inkscape-font-specification:Sans"
+   d="m 150.66402,0 c -11.24079,0 -20.32231,9.081511 -20.32231,20.322309 0,4.63349 1.54288,8.898031 4.14416,12.312928 5.64309,-6.531492 13.97179,-10.679174 23.27103,-10.679174 4.54961,0 8.86387,1.013111 12.75126,2.789337 0.31474,-1.423374 0.47817,-2.903724 0.47817,-4.423091 C 170.98633,9.081511 161.90482,0 150.66402,0 z m -26.53854,9.404049 c -5.8539,0 -10.55964,4.745576 -10.55964,10.599479 0,1.89532 0.48899,3.686187 1.35482,5.220044 3.53247,-1.99271 7.6164,-3.147966 11.9543,-3.147966 0.41864,0 0.82186,0.01699 1.23528,0.03985 -0.0468,-0.593428 -0.0797,-1.187821 -0.0797,-1.793145 0,-3.260488 0.70816,-6.362694 1.95253,-9.164963 -1.67544,-1.123499 -3.68279,-1.753297 -5.8576,-1.753297 z m 50.12836,7.292122 c -0.43247,0 -0.84934,0.05309 -1.27513,0.0797 0.18418,1.16127 0.31878,2.33386 0.31878,3.546442 0,1.887099 -0.24,3.708046 -0.67741,5.45913 5.1284,2.83813 9.38734,7.08467 12.19339,12.233233 2.91052,-1.515226 6.15729,-2.47869 9.60329,-2.709641 -0.8881,-10.415209 -9.51665,-18.60886 -20.16292,-18.60886 z m -16.49694,7.571057 c -15.72924,0 -28.45123,12.720931 -28.45123,28.451232 0,15.728607 12.72134,28.451231 28.45123,28.451231 15.7299,0 28.45124,-12.72265 28.45124,-28.451231 0,-15.730273 -12.72199,-28.451232 -28.45124,-28.451232 z m -30.88194,0.119543 c -12.20291,0 -22.0756,9.87269 -22.0756,22.075606 0,7.183598 3.4227,13.542949 8.72664,17.57282 2.23603,-4.312671 6.727,-7.252275 11.91445,-7.252275 0.62695,0 1.22873,0.07599 1.83299,0.159391 -0.18969,-1.380056 -0.27893,-2.791988 -0.27893,-4.223853 0,-6.846031 2.22844,-13.176829 6.01699,-18.290078 -2.26779,-2.837739 -3.89072,-6.247406 -4.58248,-9.961916 -0.51269,-0.03551 -1.03226,-0.0797 -1.55406,-0.0797 z M 196.05051,37.5365 c -3.70536,0 -7.17634,0.945989 -10.24085,2.550251 1.74013,3.854499 2.70964,8.131195 2.70964,12.631709 0,8.42684 -3.38806,16.078501 -8.88603,21.637282 4.039,4.484129 9.89911,7.292119 16.41724,7.292119 12.20291,0 22.07561,-9.872692 22.07561,-22.075602 0,-12.202916 -9.8727,-22.035759 -22.07561,-22.035759 z m -93.40293,2.90888 c -11.24112,0 -20.36215,9.041344 -20.36215,20.282461 0,11.241122 9.12103,20.36216 20.36215,20.36216 4.27853,0 8.24193,-1.33304 11.51598,-3.58629 -1.3529,-2.102251 -2.15177,-4.615612 -2.15177,-7.292126 0,-1.389185 0.20497,-2.723795 0.59771,-3.984766 -6.12935,-4.429596 -10.12131,-11.637922 -10.12131,-19.764442 0,-2.064771 0.27209,-4.061306 0.75711,-5.97715 -0.20132,-0.0058 -0.39495,-0.03985 -0.59772,-0.03985 z m 119.50315,17.453277 c -0.59968,0 -1.17994,0.06831 -1.7533,0.15939 0.0316,0.506877 0.0398,0.999386 0.0398,1.514212 0,6.481551 -2.55739,12.364405 -6.69441,16.736019 2.03527,2.366783 5.02479,3.865223 8.40786,3.865223 6.16229,0 11.15735,-4.955213 11.15735,-11.117498 0,-6.162288 -4.99506,-11.157346 -11.15735,-11.157346 z m -96.71028,1.19543 c -6.16197,0 -11.1175,4.955527 -11.1175,11.117498 0,6.161966 4.95553,11.157346 11.1175,11.157346 4.72323,0 8.73232,-2.94722 10.36039,-7.092884 -3.97255,-4.045998 -6.82757,-9.207657 -8.08907,-14.942874 -0.73821,-0.152657 -1.48749,-0.239086 -2.27132,-0.239086 z m 122.21279,9.364201 0,22.035763 -11.67537,0 c -7.63217,0 -13.82714,6.23473 -13.82714,13.866979 0,7.63109 6.19497,13.82714 13.82714,13.82714 l 3.38705,0 1.15558,0 c 2.239,0 4.47478,-1.08741 6.25609,-2.74949 1.78131,-1.66207 3.14086,-3.96444 3.18781,-6.53501 0.0801,-4.41219 0,-17.254039 0,-17.254039 l 0,-0.55787 0,-22.633473 -2.31116,0 z m -106.7519,9.961913 0,30.483469 c 0,5.12322 4.20109,9.2845 9.32436,9.2845 l 0,-2.31116 c -3.87663,0 -7.01319,-3.09673 -7.01319,-6.97334 l 0,-29.048949 c -0.80461,-0.4325 -1.55141,-0.93449 -2.31117,-1.43452 z m -23.11164,2.82919 c -4.09351,3.90587 -6.65456,9.40526 -6.65456,15.50074 0,11.827049 9.61175,21.438039 21.43804,21.438039 l 0,-2.31116 c -10.57945,0 -19.12688,-8.54692 -19.12688,-19.126879 0,-5.69048 2.48389,-10.80462 6.41548,-14.30531 -0.73485,-0.33851 -1.4155,-0.73502 -2.07208,-1.19543 z m -27.21596,9.16496 c -7.63218,0 -13.82714,6.19489 -13.82714,13.827139 l 0,12.7911 2.31117,0 0,-12.7911 c 0,-6.385199 5.13086,-11.555819 11.51597,-11.555819 6.38636,0 11.55582,5.17062 11.55582,11.555819 l 0,12.7911 2.31117,0 0,-12.7911 c 0,-7.632249 -6.23376,-13.827139 -13.86699,-13.827139 z m 77.5834,0.0797 c -7.6326,0 -13.82713,6.23438 -13.82713,13.866979 0,7.63262 6.19453,13.86699 13.82713,13.86699 7.63262,0 13.86699,-6.23437 13.86699,-13.86699 0,-7.632599 -6.23437,-13.866979 -13.86699,-13.866979 z m -154.290153,0.0398 c -7.6319743,0 -13.86698728410754,6.19517 -13.86698728410754,13.827139 0,7.63198 6.23501298410754,13.82714 13.86698728410754,13.82714 7.631973,0 13.82714,-6.19516 13.82714,-13.82714 0,-7.631969 -6.195167,-13.827139 -13.82714,-13.827139 z m 20.760634,1.03604 0,17.333739 c 0,5.12342 4.162235,9.2845 9.284505,9.2845 3.491222,0 6.571552,-1.93031 8.168772,-4.78172 1.585655,2.85141 4.638381,4.78172 8.128923,4.78172 5.123264,0 9.324349,-4.16108 9.324349,-9.2845 l 0,-17.333739 -2.31116,0 0,17.333739 c 0,3.8764 -3.136557,6.97334 -7.013189,6.97334 -3.876637,0 -6.973341,-3.09694 -6.973341,-6.97334 l 0,-17.333739 -2.311165,0 0,17.333739 c 0,3.87661 -3.135236,6.97334 -7.013189,6.97334 -3.875319,0 -6.973341,-3.09694 -6.973341,-6.97334 l 0,-17.333739 -2.311164,0 z m 153.453359,0 0,12.791099 c 0,7.63109 6.19496,13.82714 13.82714,13.82714 7.63218,0 13.86698,-6.19592 13.86698,-13.82714 l 0,-12.791099 -2.31116,0 0,12.791099 c 0,6.38369 -5.17071,11.51598 -11.55582,11.51598 -6.3851,0 -11.51598,-5.13216 -11.51598,-11.51598 l 0,-12.791099 -2.31116,0 z m -19.92384,1.23528 c 6.38563,0 11.55583,5.17021 11.55583,11.555819 0,6.38563 -5.1702,11.55583 -11.55583,11.55583 -6.38561,0 -11.51597,-5.1702 -11.51597,-11.55583 0,-6.385609 5.13036,-11.555819 11.51597,-11.555819 z m 67.82073,0 11.67537,0 c 0.009,1.52706 0.0728,12.045619 0,16.058609 -0.0326,1.78576 -1.01212,3.57763 -2.43071,4.90126 -1.41859,1.32363 -3.25441,2.11193 -4.70203,2.11193 l -4.54263,0 c -6.3851,0 -11.51598,-5.13216 -11.51598,-11.51598 0,-6.385199 5.13088,-11.555819 11.51598,-11.555819 z m -222.110883,0.0399 c 6.384977,0 11.515975,5.131 11.515975,11.515969 0,6.38499 -5.130998,11.51598 -11.515975,11.51598 -6.3849773,0 -11.5558223,-5.13099 -11.5558223,-11.51598 0,-6.384969 5.170845,-11.515969 11.5558223,-11.515969 z"
+   id="circle238"
+   inkscape:connector-curvature="0" />
+
+
+
+
+
+
+
+
+
+
 </svg>
\ No newline at end of file
diff --git a/core/img/owncloud-logo-medium-white.png b/core/img/owncloud-logo-medium-white.png
deleted file mode 100644
index d4d06fdd62d6a1cfe82170b3009fd8a9f36e0a1e..0000000000000000000000000000000000000000
Binary files a/core/img/owncloud-logo-medium-white.png and /dev/null differ
diff --git a/core/js/jquery-ui-1.8.16.custom.min.js b/core/js/jquery-ui-1.8.16.custom.min.js
old mode 100755
new mode 100644
diff --git a/core/js/jquery.infieldlabel.js b/core/js/jquery.infieldlabel.js
old mode 100755
new mode 100644
diff --git a/core/js/jquery.infieldlabel.min.js b/core/js/jquery.infieldlabel.min.js
old mode 100755
new mode 100644
diff --git a/core/js/js.js b/core/js/js.js
index 7e8ca6164c63eb3eae0e13b4d6a7955dd902f7c9..f697f2b8537416dcc9ec875b78f2d31e54112f45 100644
--- a/core/js/js.js
+++ b/core/js/js.js
@@ -31,8 +31,9 @@ t.cache={};
 
 OC={
 	webroot:oc_webroot,
+	appswebroot:oc_appswebroot,
 	currentUser:(typeof oc_current_user!=='undefined')?oc_current_user:false,
-	coreApps:['files','admin','log','search','settings','core','3rdparty'],
+	coreApps:['admin','log','search','settings','core','3rdparty'],
 	/**
 	 * get an absolute url to a file in an appen
 	 * @param app the id of the app the file belongs to
@@ -51,16 +52,34 @@ OC={
 	 */
 	filePath:function(app,type,file){
 		var isCore=OC.coreApps.indexOf(app)!=-1;
-		app+='/';
-		var link=OC.webroot+'/';
-		if(!isCore){
+		var link=OC.webroot;
+		if((file.substring(file.length-3) == 'php' || file.substring(file.length-3) == 'css') && !isCore){
+			link+='/?app=' + app + '&getfile=';
+			if(type){
+				link+=encodeURI(type + '/');
+			}
+			link+= file;
+		}else if(file.substring(file.length-3) != 'php' && !isCore){
+			link=OC.appswebroot;
+			link+='/';
 			link+='apps/';
+			link+=app+'/';
+			if(type){
+				link+=type+'/';
+			}
+			link+=file;
+		}else{
+			link+='/';
+			app+='/';
+			if(!isCore){
+				link+='apps/';
+			}
+			link+=app;
+			if(type){
+				link+=type+'/';
+			}
+			link+=file;	
 		}
-		link+=app;
-		if(type){
-			link+=type+'/';
-		}
-		link+=file;
 		return link;
 	},
 	/**
@@ -69,10 +88,10 @@ OC={
 	 * @param file the name of the image file
 	 * @return string
 	 * 
-	 * if no extention is given for the image, it will automatically decide between .png and .svg based on what the browser supports
+	 * if no extension is given for the image, it will automatically decide between .png and .svg based on what the browser supports
 	 */ 
 	imagePath:function(app,file){
-		if(file.indexOf('.')==-1){//if no extention is given, use png or svg depending on browser support
+		if(file.indexOf('.')==-1){//if no extension is given, use png or svg depending on browser support
 			file+=(SVGSupport())?'.svg':'.png';
 		}
 		return OC.filePath(app,'img',file);
@@ -152,6 +171,7 @@ if(typeof localStorage !='undefined'){
 			return localStorage.setItem(OC.localStorage.namespace+name,JSON.stringify(item));
 		},
 		getItem:function(name){
+			if(localStorage.getItem(OC.localStorage.namespace+name)==null){return null;}
 			return JSON.parse(localStorage.getItem(OC.localStorage.namespace+name));
 		}
 	};
@@ -297,7 +317,10 @@ function object(o) {
  * Fills height of window. (more precise than height: 100%;)
  */
 function fillHeight(selector) {
-	var height = parseFloat($(window).height())-parseFloat(selector.css('top'));
+	if (selector.length == 0) {
+		return;
+	}
+	var height = parseFloat($(window).height())-selector.offset().top;
 	selector.css('height', height + 'px');
 	if(selector.outerHeight() > selector.height())
 		selector.css('height', height-(selector.outerHeight()-selector.height()) + 'px');
@@ -307,8 +330,11 @@ function fillHeight(selector) {
  * Fills height and width of window. (more precise than height: 100%; or width: 100%;)
  */
 function fillWindow(selector) {
+	if (selector.length == 0) {
+		return;
+	}
 	fillHeight(selector);
-	var width = parseFloat($(window).width())-parseFloat(selector.css('left'));
+	var width = parseFloat($(window).width())-selector.offset().left;
 	selector.css('width', width + 'px');
 	if(selector.outerWidth() > selector.width())
 		selector.css('width', width-(selector.outerWidth()-selector.width()) + 'px');
@@ -400,9 +426,6 @@ $(document).ready(function(){
 	$('#settings #expanddiv').click(function(event){
 		event.stopPropagation();
 	});
-	$('#settings #expand').hover(function(){
-		$('#settings #expand+span').fadeToggle();
-	});
 	$(window).click(function(){//hide the settings menu when clicking oustide it
 		if($('body').attr("id")=="body-user"){
 			$('#settings #expanddiv').slideUp();
@@ -415,7 +438,7 @@ $(document).ready(function(){
 	$('.password .action').tipsy({gravity:'se', fade:true, live:true});
 	$('.file_upload_button_wrapper').tipsy({gravity:'w', fade:true});
 	$('.selectedActions a').tipsy({gravity:'s', fade:true, live:true});
-	$('a.delete').tipsy({gravity: 'se', fade:true, live:true});
+	$('a.delete').tipsy({gravity: 'e', fade:true, live:true});
 	$('a.action').tipsy({gravity:'s', fade:true, live:true});
 	$('#headerSize').tipsy({gravity:'s', fade:true, live:true});
 	$('td.filesize').tipsy({gravity:'s', fade:true, live:true});
diff --git a/core/js/oc-dialogs.js b/core/js/oc-dialogs.js
index a3aa1e8c149cb4313623491c7926633131a40590..f6870e62710040493daeebca937be9fc71c3ddd9 100644
--- a/core/js/oc-dialogs.js
+++ b/core/js/oc-dialogs.js
@@ -107,7 +107,7 @@ OCdialogs = {
     $(c_id + ' #dirtree').focus(function() { var t = $(this); t.data('oldval',  t.val())})
                          .change({dcid: c_id}, OC.dialogs.handleTreeListSelect);
     $(c_id).ready(function(){
-      $.getJSON(OC.webroot+'/files/ajax/rawlist.php', {mimetype: mimetype_filter} ,function(r){OC.dialogs.fillFilePicker(r, c_id, callback)});
+      $.getJSON(OC.filePath('files', 'ajax', 'rawlist.php'), {mimetype: mimetype_filter} ,function(r){OC.dialogs.fillFilePicker(r, c_id, callback)});
     }).data('multiselect', multiselect).data('mimetype',mimetype_filter);
     // build buttons
     var b = [
@@ -131,7 +131,7 @@ OCdialogs = {
       },
       {text: t('dialogs', 'Cancel'), click: function(){$(c_id).dialog('close'); }}
       ];
-    $(c_id).dialog({width: 4*$(document).width()/9, height: 400, modal: modal, buttons: b});
+      $(c_id).dialog({width: ((4*$('body').width())/9), height: 400, modal: modal, buttons: b});
     OCdialogs.dialogs_counter++;
   },
   // guts, dont use, dont touch
@@ -222,7 +222,7 @@ OCdialogs = {
     $(this).children().each(function(i, element) { if (skip_first) {skip_first = false; return; }path += '/'+$(element).text(); });
     $(event.data.dcid).data('path', path);
     $(event.data.dcid + ' .filepicker_loader').css('visibility', 'visible');
-    $.getJSON(OC.webroot+'/files/ajax/rawlist.php', {dir: path, mimetype: $(event.data.dcid).data('mimetype')}, function(r){OC.dialogs.fillFilePicker(r, event.data.dcid)});
+    $.getJSON(OC.filePath('files', 'ajax', 'rawlist.php'), {dir: path, mimetype: $(event.data.dcid).data('mimetype')}, function(r){OC.dialogs.fillFilePicker(r, event.data.dcid)});
   },
   // this function is in early development state, please dont use it unlsess you know what you are doing
   handlePickerClick:function(element, name, dcid) {
@@ -240,6 +240,6 @@ OCdialogs = {
     var newval = parseInt($(dcid + ' #dirtree option:last').val())+1;
     $(dcid + ' #dirtree').append('<option selected="selected" value="'+newval+'">'+name+'</option>');
     $(dcid + ' .filepicker_loader').css('visibility', 'visible');
-    $.getJSON(OC.webroot+'/files/ajax/rawlist.php', {dir: p, mimetype: $(dcid).data('mimetype')}, function(r){OC.dialogs.fillFilePicker(r, dcid)});
+    $.getJSON(OC.filePath('files', 'ajax', 'rawlist.php'), {dir: p, mimetype: $(dcid).data('mimetype')}, function(r){OC.dialogs.fillFilePicker(r, dcid)});
   }
 };
diff --git a/core/lostpassword/index.php b/core/lostpassword/index.php
index a9b7d10804feb3670a631c75c37183417fa9978e..2b87a1eb1115fb9654b7999ddb8bb8ee95729467 100644
--- a/core/lostpassword/index.php
+++ b/core/lostpassword/index.php
@@ -9,25 +9,35 @@
 $RUNTIME_NOAPPS = TRUE; //no apps
 require_once('../../lib/base.php');
 
+
 // Someone lost their password:
 if (isset($_POST['user'])) {
 	if (OC_User::userExists($_POST['user'])) {
 		$token = sha1($_POST['user'].md5(uniqid(rand(), true)));
 		OC_Preferences::setValue($_POST['user'], 'owncloud', 'lostpassword', $token);
 		$email = OC_Preferences::getValue($_POST['user'], 'settings', 'email', '');
-		if (!empty($email)) {
+		if (!empty($email) and isset($_POST['sectoken']) and isset($_SESSION['sectoken']) and ($_POST['sectoken']==$_SESSION['sectoken']) ) {
 			$link = OC_Helper::linkToAbsolute('core/lostpassword', 'resetpassword.php').'?user='.$_POST['user'].'&token='.$token;
 			$tmpl = new OC_Template('core/lostpassword', 'email');
 			$tmpl->assign('link', $link);
 			$msg = $tmpl->fetchPage();
-			$l = new OC_L10N('core');
+			$l = OC_L10N::get('core');
 			$from = 'lostpassword-noreply@' . $_SERVER['HTTP_HOST'];
-			mail($email, $l->t('Owncloud password reset'), $msg, 'From:' . $from);
+			$r=mail($email, $l->t('Owncloud password reset'), $msg, 'From:' . $from);
+			OC_MAIL::send($email,$_POST['user'],$l->t('ownCloud password reset'),$msg,$from,'ownCloud');
+			echo('sent');
+
 		}
-		OC_Template::printGuestPage('core/lostpassword', 'lostpassword', array('error' => false, 'requested' => true));
+		$sectoken=rand(1000000,9999999);
+		$_SESSION['sectoken']=$sectoken;
+		OC_Template::printGuestPage('core/lostpassword', 'lostpassword', array('error' => false, 'requested' => true, 'sectoken' => $sectoken));
 	} else {
-		OC_Template::printGuestPage('core/lostpassword', 'lostpassword', array('error' => true, 'requested' => false));
+		$sectoken=rand(1000000,9999999);
+		$_SESSION['sectoken']=$sectoken;
+		OC_Template::printGuestPage('core/lostpassword', 'lostpassword', array('error' => true, 'requested' => false, 'sectoken' => $sectoken));
 	}
 } else {
-	OC_Template::printGuestPage('core/lostpassword', 'lostpassword', array('error' => false, 'requested' => false));
+	$sectoken=rand(1000000,9999999);
+	$_SESSION['sectoken']=$sectoken;
+	OC_Template::printGuestPage('core/lostpassword', 'lostpassword', array('error' => false, 'requested' => false, 'sectoken' => $sectoken));
 }
diff --git a/core/lostpassword/templates/lostpassword.php b/core/lostpassword/templates/lostpassword.php
index 4b871963b8055fbc6159ba0b8dcb595acd51da42..754eabdad678b200ceb89e47ceae8993b1dac3e1 100644
--- a/core/lostpassword/templates/lostpassword.php
+++ b/core/lostpassword/templates/lostpassword.php
@@ -10,6 +10,7 @@
 			<p class="infield">
 				<label for="user" class="infield"><?php echo $l->t( 'Username' ); ?></label>
 				<input type="text" name="user" id="user" value="" autocomplete="off" required autofocus />
+				<input type="hidden" name="sectoken" id="sectoken" value="<?php echo($_['sectoken']); ?>"  />
 			</p>
 			<input type="submit" id="submit" value="<?php echo $l->t('Request reset'); ?>" />
 		<?php endif; ?>
diff --git a/core/strings.php b/core/strings.php
index 9b4290db4769785a39f884d10b9d81d5f8e5a2eb..8c3f64ef14f63d045a48f9a26ad68ee076663787 100644
--- a/core/strings.php
+++ b/core/strings.php
@@ -1,7 +1,7 @@
 <?php
 
 //some strings that are used in /lib but wont be translatable unless they are in /core too
-$l=new OC_L10N('core');
+$l=OC_L10N::get('core');
 $l->t("Personal");
 $l->t("Users");
 $l->t("Apps");
diff --git a/core/templates/404.php b/core/templates/404.php
index 13a81010343449ec60658b55083529e582b35eb5..cd4f2b40bb2e0e21a5397a25f691fe4d420d28e0 100644
--- a/core/templates/404.php
+++ b/core/templates/404.php
@@ -10,6 +10,6 @@ if(!isset($_)){//also provide standalone error page
 <ul>
 	<li class='error'>
 		<?php echo $l->t( 'Cloud not found' ); ?><br/>
-		<p class='hint'><?php if(isset($_['file'])) echo $_['file']?></p>
+		<p class='hint'><?php if(isset($_['file'])) echo htmlentities($_['file'])?></p>
 	</li>
 </ul>
diff --git a/core/templates/layout.guest.php b/core/templates/layout.guest.php
index e1f8928fc9b7557cfd9213700d7bd22c4ef4df92..86f46d9c7eb55a345a012a3c73c9fc32eb9fe8ad 100644
--- a/core/templates/layout.guest.php
+++ b/core/templates/layout.guest.php
@@ -9,6 +9,8 @@
 		<?php endforeach; ?>
 		<script type="text/javascript">
 			var oc_webroot = '<?php echo OC::$WEBROOT; ?>';
+			var oc_appswebroot = '<?php echo OC::$APPSWEBROOT; ?>';
+			var oc_appswebroot = '<?php echo OC::$APPSWEBROOT; ?>';
 		</script>
 		<?php foreach($_['jsfiles'] as $jsfile): ?>
 			<script type="text/javascript" src="<?php echo $jsfile; ?>"></script>
@@ -28,7 +30,7 @@
 	<body id="body-login">
 		<div id="login">
 			<header><div id="header">
-				<img src="<?php echo image_path('', 'owncloud-logo-medium-white.png'); ?>" alt="ownCloud" />
+				<img src="<?php echo image_path('', 'logo.png'); ?>" alt="ownCloud" />
 			</div></header>
 			<?php echo $_['content']; ?>
 		</div>
diff --git a/core/templates/layout.user.php b/core/templates/layout.user.php
index 85cf08997924666cb5e0ca015fcb6e27fdecd671..674b1853037467761bc62403aa4e526270f7ab0d 100644
--- a/core/templates/layout.user.php
+++ b/core/templates/layout.user.php
@@ -1,7 +1,7 @@
 <!DOCTYPE html>
 <html>
 	<head>
-		<title><?php echo isset($_['application']) && !empty($_['application'])?$_['application'].' | ':'' ?>ownCloud</title>
+		<title><?php echo isset($_['application']) && !empty($_['application'])?$_['application'].' | ':'' ?>ownCloud <?php echo OC_User::getUser()?' ('.OC_User::getUser().') ':'' ?></title>
 		<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
 		<link rel="shortcut icon" href="<?php echo image_path('', 'favicon.png'); ?>" /><link rel="apple-touch-icon-precomposed" href="<?php echo image_path('', 'favicon-touch.png'); ?>" />
 		<?php foreach($_['cssfiles'] as $cssfile): ?>
@@ -9,6 +9,7 @@
 		<?php endforeach; ?>
 		<script type="text/javascript">
 			var oc_webroot = '<?php echo OC::$WEBROOT; ?>';
+			var oc_appswebroot = '<?php echo OC::$APPSWEBROOT; ?>';
 			var oc_current_user = '<?php echo OC_User::getUser() ?>';
 		</script>
 		<?php foreach($_['jsfiles'] as $jsfile): ?>
@@ -44,7 +45,7 @@
 
 			<ul id="settings" class="svg">
 				<img id="expand" class="svg" alt="<?php echo $l->t('Settings');?>" src="<?php echo image_path('', 'actions/settings.svg'); ?>" />
-				<span style="display:none;"><?php echo $l->t('Settings');?></span>
+				<span><?php echo $l->t('Settings');?></span>
 				<div id="expanddiv" <?php if($_['bodyid'] == 'body-user') echo 'style="display:none;"'; ?>>
 				<?php foreach($_['settingsnavigation'] as $entry):?>
 					<li><a style="background-image:url(<?php echo $entry['icon']; ?>)" href="<?php echo $entry['href']; ?>" title="" <?php if( $entry["active"] ): ?> class="active"<?php endif; ?>><?php echo $entry['name'] ?></a></li>
diff --git a/core/templates/login.php b/core/templates/login.php
index 4ba92221a7d43a01a9fe48920d5aaa1a9b0e7189..4035dfe8a5af4204e8c5280d66c2e2680938c065 100644
--- a/core/templates/login.php
+++ b/core/templates/login.php
@@ -12,6 +12,7 @@
 		<p class="infield">
 			<label for="password" class="infield"><?php echo $l->t( 'Password' ); ?></label>
 			<input type="password" name="password" id="password" value="" required <?php echo !empty($_POST['user'])?'autofocus':''; ?> />
+			<input type="hidden" name="sectoken" id="sectoken" value="<?php echo($_['sectoken']); ?>"  />
 		</p>
 		<input type="checkbox" name="remember_login" value="1" id="remember_login" /><label for="remember_login"><?php echo $l->t('remember'); ?></label>
 		<input type="submit" id="submit" class="login" value="<?php echo $l->t( 'Log in' ); ?>" />
diff --git a/dav.php b/dav.php
deleted file mode 100644
index 78e2711aec84495b36a8837ac0d44a66f43cdb3c..0000000000000000000000000000000000000000
--- a/dav.php
+++ /dev/null
@@ -1,77 +0,0 @@
-<?php
-
-/**
-* ownCloud
-*
-* @author Jakob Sack
-* @copyright 2012 Jakob Sack owncloud@jakobsack.de
-*
-* This library is free software; you can redistribute it and/or
-* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
-* License as published by the Free Software Foundation; either
-* version 3 of the License, or any later version.
-*
-* This library 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 AFFERO GENERAL PUBLIC LICENSE for more details.
-*
-* You should have received a copy of the GNU Affero General Public
-* License along with this library.  If not, see <http://www.gnu.org/licenses/>.
-*
-*/
-
-require_once('lib/base.php');
-
-// Backends we always need (auth, principal and files)
-$backends = array(
-	'auth' => new OC_Connector_Sabre_Auth(),
-	'principal' => new OC_Connector_Sabre_Principal()
-);
-
-// Root nodes
-$nodes = array(
-	new Sabre_CalDAV_Principal_Collection($backends['principal'])
-);
-
-// Plugins
-$plugins = array(
-	new Sabre_DAV_Auth_Plugin($backends['auth'],'ownCloud'),
-	new Sabre_DAVACL_Plugin(),
-	new Sabre_DAV_Browser_Plugin(false) // Show something in the Browser, but no upload
-);
-
-// Load the plugins etc we need for usual file sharing
-$backends['lock'] = new OC_Connector_Sabre_Locks();
-$plugins[] = new Sabre_DAV_Locks_Plugin($backends['lock']);
-// Add a RESTful user directory
-// /files/$username/
-if( OC_User::isLoggedIn()){
-	$currentuser = OC_User::getUser();
-	$files = new Sabre_DAV_SimpleCollection('files');
-	foreach( OC_User::getUsers() as $username ){
-		if( $username == $currentuser ){
-			$public = new OC_Connector_Sabre_Directory('.');
-			$files->addChild( new Sabre_DAV_SimpleCollection( $username, $public->getChildren()));
-		}
-		else{
-			$files->addChild(new Sabre_DAV_SimpleCollection( $username ));
-		}
-	}
-	$nodes[] = $files;
-}
-
-// Get the other plugins and nodes
-OC_Hook::emit( 'OC_DAV', 'initialize', array( 'backends' => &$backends, 'nodes' => &$nodes, 'plugins' => &$plugins ));
-
-// Fire up server
-$server = new Sabre_DAV_Server($nodes);
-$server->setBaseUri(OC::$WEBROOT.'/dav.php');
-
-// Load additional plugins
-foreach( $plugins as &$plugin ){
-	$server->addPlugin( $plugin );
-} unset( $plugin ); // Always do this after foreach with references!
-
-// And off we go!
-$server->exec();
diff --git a/db_structure.xml b/db_structure.xml
index 2df218d359c83277dd178f905d158ccde24f15ad..d29dcb46f8c94afe77f9953c5f31d87c62d92f74 100644
--- a/db_structure.xml
+++ b/db_structure.xml
@@ -131,7 +131,7 @@
 	   <default>
 	   </default>
 	   <notnull>true</notnull>
-	   <length>32</length>
+	   <length>96</length>
    </field>
 
    <field>
diff --git a/files/ajax/move.php b/files/ajax/move.php
deleted file mode 100644
index 9af3f80208f5e0b8d31e8f00279a39efcc222ede..0000000000000000000000000000000000000000
--- a/files/ajax/move.php
+++ /dev/null
@@ -1,20 +0,0 @@
-<?php
-
-// Init owncloud
-require_once('../../lib/base.php');
-
-OC_JSON::checkLoggedIn();
-
-// Get data
-$dir = stripslashes($_GET["dir"]);
-$file = stripslashes($_GET["file"]);
-$target = stripslashes($_GET["target"]);
-
-
-if(OC_Files::move($dir,$file,$target,$file)){
-	OC_JSON::success(array("data" => array( "dir" => $dir, "files" => $file )));
-}else{
-	OC_JSON::error(array("data" => array( "message" => "Could not move $file" )));
-}
-
-?>
diff --git a/files/ajax/rename.php b/files/ajax/rename.php
deleted file mode 100644
index a51b36635b376694166ab1914c8ab6004b24f2e3..0000000000000000000000000000000000000000
--- a/files/ajax/rename.php
+++ /dev/null
@@ -1,21 +0,0 @@
-<?php
-
-// Init owncloud
-require_once('../../lib/base.php');
-
-OC_JSON::checkLoggedIn();
-
-// Get data
-$dir = stripslashes($_GET["dir"]);
-$file = stripslashes($_GET["file"]);
-$newname = stripslashes($_GET["newname"]);
-
-// Delete
-if( OC_Files::move( $dir, $file, $dir, $newname )) {
-	OC_JSON::success(array("data" => array( "dir" => $dir, "file" => $file, "newname" => $newname )));
-}
-else{
-	OC_JSON::error(array("data" => array( "message" => "Unable to rename file" )));
-}
-
-?>
diff --git a/files/appinfo/app.php b/files/appinfo/app.php
deleted file mode 100644
index 0bf73d9a07e24474525d04cd066cf395a0c5ec8a..0000000000000000000000000000000000000000
--- a/files/appinfo/app.php
+++ /dev/null
@@ -1,10 +0,0 @@
-<?php
-
-
-$l=new OC_L10N('files');
-
-OC_App::register( array( "order" => 2, "id" => "files", "name" => "Files" ));
-
-OC_App::addNavigationEntry( array( "id" => "files_index", "order" => 1, "href" => OC_Helper::linkTo( "files", "index.php" ), "icon" => OC_Helper::imagePath( "core", "places/home.svg" ), "name" => $l->t("Files") ));
-
-OC_Search::registerProvider('OC_Search_Provider_File');
diff --git a/files/webdav.php b/files/webdav.php
index 25e33024470d40881ef685643f444bb2880a8dda..3ed687041ca7785cbac8654854252ac1765ca807 100644
--- a/files/webdav.php
+++ b/files/webdav.php
@@ -25,11 +25,12 @@
 
 // Do not load FS ...
 $RUNTIME_NOSETUPFS = true;
+require_once('../lib/base.php');
 
 // only need filesystem apps
 $RUNTIME_APPTYPES=array('filesystem','authentication');
 
-require_once('../lib/base.php');
+ 
 
 // Backends
 $authBackend = new OC_Connector_Sabre_Auth();
diff --git a/index.php b/index.php
index b4cac1879c6797f177e00dc6cad769f90f73b268..b9872a906d73ee8b285de40080c5b1b632f4980c 100644
--- a/index.php
+++ b/index.php
@@ -44,28 +44,30 @@ if($not_installed) {
 
 // Handle WebDAV
 if($_SERVER['REQUEST_METHOD']=='PROPFIND'){
-	header('location: '.OC_Helper::linkToAbsolute('files','webdav.php'));
+	header('location: '.OC_Helper::linkToAbsolute('remote','webdav.php'));
 	exit();
 }
 
 // Someone is logged in :
 elseif(OC_User::isLoggedIn()) {
+	OC_App::loadApps();
 	if(isset($_GET["logout"]) and ($_GET["logout"])) {
-		OC_App::loadApps();
 		OC_User::logout();
 		header("Location: ".OC::$WEBROOT.'/');
 		exit();
+	}else{
+		if(is_null(OC::$REQUESTEDFILE)){
+			OC::loadapp();
+		}else{
+			OC::loadfile();
+		}
+		
 	}
-	else {
-		OC_Util::redirectToDefaultPage();
-	}
-}
 
 // For all others cases, we display the guest page :
-else {
+} else {
 	OC_App::loadApps();
 	$error = false;
-
 	// remember was checked after last login
 	if(isset($_COOKIE["oc_remember_login"]) && isset($_COOKIE["oc_token"]) && isset($_COOKIE["oc_username"]) && $_COOKIE["oc_remember_login"]) {
 		if(defined("DEBUG") && DEBUG) {
@@ -80,10 +82,9 @@ else {
 		else {
 			OC_User::unsetMagicInCookie();
 		}
-	}
 
 	// Someone wants to log in :
-	elseif(isset($_POST["user"]) && isset($_POST['password'])) {
+	} elseif(isset($_POST["user"]) and isset($_POST['password']) and isset($_SESSION['sectoken']) and isset($_POST['sectoken']) and ($_SESSION['sectoken']==$_POST['sectoken']) ) {
 		if(OC_User::login($_POST["user"], $_POST["password"])) {
 			if(!empty($_POST["remember_login"])){
 				if(defined("DEBUG") && DEBUG) {
@@ -100,9 +101,9 @@ else {
 		} else {
 			$error = true;
 		}
-	}
+	
 	// The user is already authenticated using Apaches AuthType Basic... very usable in combination with LDAP
-	elseif(isset($_SERVER["PHP_AUTH_USER"]) && isset($_SERVER["PHP_AUTH_PW"])){
+	} elseif(isset($_SERVER["PHP_AUTH_USER"]) && isset($_SERVER["PHP_AUTH_PW"])){
 		if (OC_User::login($_SERVER["PHP_AUTH_USER"],$_SERVER["PHP_AUTH_PW"]))	{
 			//OC_Log::write('core',"Logged in with HTTP Authentication",OC_Log::DEBUG);
 			OC_User::unsetMagicInCookie();
@@ -111,5 +112,9 @@ else {
 			$error = true;
 		}
 	}
-	OC_Template::printGuestPage('', 'login', array('error' => $error, 'redirect' => isset($_REQUEST['redirect_url'])?$_REQUEST['redirect_url']:'' ));
+	if(is_null(OC::$REQUESTEDFILE)){
+		$sectoken=rand(1000000,9999999);
+		$_SESSION['sectoken']=$sectoken;
+		OC_Template::printGuestPage('', 'login', array('error' => $error, 'sectoken' => $sectoken, 'redirect' => isset($_REQUEST['redirect_url'])?$_REQUEST['redirect_url']:'' ));
+	}
 }
diff --git a/lib/app.php b/lib/app.php
old mode 100755
new mode 100644
index 1c81fbd42425457335dbed33339dc4aed623d190..c8d3826bca50f9c7590dc35b036dc13258dbdd49
--- a/lib/app.php
+++ b/lib/app.php
@@ -35,6 +35,7 @@ class OC_App{
 	static private $adminForms = array();
 	static private $personalForms = array();
 	static private $appInfo = array();
+	static private $appTypes = array();
 
 	/**
 	 * @brief loads all apps
@@ -54,7 +55,7 @@ class OC_App{
 		}
 
 		// Our very own core apps are hardcoded
-		foreach( array('files', 'settings') as $app ){
+		foreach( array( 'settings') as $app ){
 			if(is_null($types)){
 				require( $app.'/appinfo/app.php' );
 			}
@@ -63,7 +64,7 @@ class OC_App{
 		// The rest comes here
 		$apps = self::getEnabledApps();
 		foreach( $apps as $app ){
-			if(is_null($types) or self::isType($app,$types)){
+			if((is_null($types) or self::isType($app,$types))){
 				if(is_file(OC::$APPSROOT.'/apps/'.$app.'/appinfo/app.php')){
 					require( $app.'/appinfo/app.php' );
 				}
@@ -85,11 +86,7 @@ class OC_App{
 		if(is_string($types)){
 			$types=array($types);
 		}
-		$appData=self::getAppInfo($app);
-		if(!isset($appData['types'])){
-			return false;
-		}
-		$appTypes=$appData['types'];
+		$appTypes=self::getAppTypes($app);
 		foreach($types as $type){
 			if(array_search($type,$appTypes)!==false){
 				return true;
@@ -98,15 +95,43 @@ class OC_App{
 		return false;
 	}
 
+	/**
+	 * get the types of an app
+	 * @param string $app
+	 * @return array
+	 */
+	private static function getAppTypes($app){
+		//load the cache
+		if(count(self::$appTypes)==0){
+			self::$appTypes=OC_Appconfig::getValues(false,'types');
+		}
+
+		//get it from info.xml if we haven't cached it
+		if(!isset(self::$appTypes[$app])){
+			$appData=self::getAppInfo($app);
+			if(isset($appData['types'])){
+				self::$appTypes[$app]=$appData['types'];
+			}else{
+				self::$appTypes[$app]=array();
+			}
+
+			OC_Appconfig::setValue($app,'types',implode(',',self::$appTypes[$app]));
+		}
+
+		return explode(',',self::$appTypes[$app]);
+	}
+
 	/**
 	 * get all enabled apps
 	 */
 	public static function getEnabledApps(){
-		$apps=array();
+		$apps=array('files');
 		$query = OC_DB::prepare( 'SELECT appid FROM *PREFIX*appconfig WHERE configkey = \'enabled\' AND configvalue=\'yes\'' );
 		$result=$query->execute();
 		while($row=$result->fetchRow()){
-			$apps[]=$row['appid'];
+			if(array_search($row['appid'],$apps)===false){
+				$apps[]=$row['appid'];
+			}
 		}
 		return $apps;
 	}
@@ -139,13 +164,18 @@ class OC_App{
 			if(!is_numeric($app)){
 				OC_Installer::installShippedApp($app);
 			}else{
-                                $download=OC_OCSClient::getApplicationDownload($app,1);
-				if(isset($download['downloadlink']) and $download['downloadlink']<>'') {
+				$download=OC_OCSClient::getApplicationDownload($app,1);
+				if(isset($download['downloadlink']) and $download['downloadlink']!='') {
 					$app=OC_Installer::installApp(array('source'=>'http','href'=>$download['downloadlink']));
 				}
 			}
 		}
-		OC_Appconfig::setValue( $app, 'enabled', 'yes' );
+		if($app!==false){
+			OC_Appconfig::setValue( $app, 'enabled', 'yes' );
+			return true;
+		}else{
+			return false;
+		}
 	}
 
 	/**
@@ -249,7 +279,7 @@ class OC_App{
 	 * entries are sorted by the key 'order' ascending.
 	 */
 	public static function getSettingsNavigation(){
-		$l=new OC_L10N('core');
+		$l=OC_L10N::get('core');
 
 		$settings = array();
 		// by default, settings only contain the help menu
@@ -275,8 +305,6 @@ class OC_App{
 				$settings[] = array( "id" => "core_users", "order" => 2, "href" => OC_Helper::linkTo( "settings", "users.php" ), "name" => $l->t("Users"), "icon" => OC_Helper::imagePath( "settings", "users.svg" ));
 				// admin apps menu
 				$settings[] = array( "id" => "core_apps", "order" => 3, "href" => OC_Helper::linkTo( "settings", "apps.php" ).'?installed', "name" => $l->t("Apps"), "icon" => OC_Helper::imagePath( "settings", "apps.svg" ));
-				// admin log menu
-				$settings[] = array( "id" => "core_log", "order" => 4, "href" => OC_Helper::linkTo( "settings", "log.php" ), "name" => $l->t("Log"), "icon" => OC_Helper::imagePath( "settings", "log.svg" ));
 
 				$settings[]=array( "id" => "admin", "order" => 1000, "href" => OC_Helper::linkTo( "settings", "admin.php" ), "name" => $l->t("Admin"), "icon" => OC_Helper::imagePath( "settings", "admin.svg" ));
 			}
@@ -303,6 +331,20 @@ class OC_App{
 		return $list;
 	}
 
+	/**
+	 * get the last version of the app, either from appinfo/version or from appinfo/info.xml
+	 */
+	public static function getAppVersion($appid){
+		$file=OC::$APPSROOT.'/apps/'.$appid.'/appinfo/version';
+		$version=@file_get_contents($file);
+		if($version){
+			return $version;
+		}else{
+			$appData=self::getAppInfo($appid);
+			return $appData['version'];
+		}
+	}
+
 	/**
 	 * @brief Read app metadata from the info.xml file
 	 * @param string $appid id of the app or the path of the info.xml file
@@ -381,7 +423,6 @@ class OC_App{
 				$source=self::$settingsForms;
 				break;
 			case 'admin':
-				$forms[] = include 'files/admin.php';   //hardcode own apps
 				$source=self::$adminForms;
 				break;
 			case 'personal':
@@ -436,12 +477,11 @@ class OC_App{
 		// The rest comes here
 		$versions = self::getAppVersions();
 		foreach( $versions as $app=>$installedVersion ){
-			$appInfo=OC_App::getAppInfo($app);
-			if (isset($appInfo['version'])) {
-				$currentVersion=$appInfo['version'];
+			$currentVersion=OC_App::getAppVersion($app);
+			if ($currentVersion) {
 				if (version_compare($currentVersion, $installedVersion, '>')) {
 					OC_App::updateApp($app);
-					OC_Appconfig::setValue($app,'installed_version',$appInfo['version']);
+          OC_Appconfig::setValue($app,'installed_version',OC_App::getAppVersion($app));
 				}
 			}
 		}
@@ -480,6 +520,10 @@ class OC_App{
 	public static function getStorage($appid){
 		if(OC_App::isEnabled($appid)){//sanity check
 			if(OC_User::isLoggedIn()){
+				$view = new OC_FilesystemView('/'.OC_User::getUser());
+				if(!$view->file_exists($appid)) {
+					$view->mkdir($appid);
+				}
 				return new OC_FilesystemView('/'.OC_User::getUser().'/'.$appid);
 			}else{
 				OC_Log::write('core','Can\'t get app storage, app, user not logged in',OC_Log::ERROR);
diff --git a/lib/appconfig.php b/lib/appconfig.php
index 2b5cef59adc426025fd1504d1fece4c26816015c..5aaaadd9c4a2dd435053ac755aa511f25fefa358 100644
--- a/lib/appconfig.php
+++ b/lib/appconfig.php
@@ -163,4 +163,38 @@ class OC_Appconfig{
 
 		return true;
 	}
+	
+	/**
+	 * get multiply values, either the app or key can be used as wildcard by setting it to false
+	 * @param app
+	 * @param key
+	 * @return array
+	 */
+	public static function getValues($app,$key){
+		if($app!==false and $key!==false){
+			return false;
+		}
+		$where='WHERE';
+		$fields='configvalue';
+		$params=array();
+		if($app!==false){
+			$where.=' appid = ?';
+			$fields.=', configkey';
+			$params[]=$app;
+			$key='configkey';
+		}else{
+			$fields.=', appid';
+			$where.=' configkey = ?';
+			$params[]=$key;
+			$key='appid';
+		}
+		$queryString='SELECT '.$fields.' FROM *PREFIX*appconfig '.$where;
+		$query=OC_DB::prepare($queryString);
+		$result=$query->execute($params);
+		$values=array();
+		while($row=$result->fetchRow()){
+			$values[$row[$key]]=$row['configvalue'];
+		}
+		return $values;
+	}
 }
diff --git a/apps/files_archive/lib/archive.php b/lib/archive.php
similarity index 100%
rename from apps/files_archive/lib/archive.php
rename to lib/archive.php
diff --git a/apps/files_archive/lib/tar.php b/lib/archive/tar.php
old mode 100644
new mode 100755
similarity index 95%
rename from apps/files_archive/lib/tar.php
rename to lib/archive/tar.php
index a5d54004788f7fe0b6f8a64213ca3795f53b4fc4..07f0ba5bd8a44fb921ee9bb56f9b3e77c5a3e3af
--- a/apps/files_archive/lib/tar.php
+++ b/lib/archive/tar.php
@@ -6,6 +6,8 @@
  * See the COPYING-README file.
  */
 
+require_once '3rdparty/Archive/Tar.php';
+
 class OC_Archive_TAR extends OC_Archive{
 	const PLAIN=0;
 	const GZIP=1;
@@ -30,8 +32,8 @@ class OC_Archive_TAR extends OC_Archive{
 	 */
 	static public function getTarType($file){
 		if(strpos($file,'.')){
-			$extention=substr($file,strrpos($file,'.'));
-			switch($extention){
+			$extension=substr($file,strrpos($file,'.'));
+			switch($extension){
 				case 'gz':
 				case 'tgz':
 					return self::GZIP;
@@ -93,7 +95,7 @@ class OC_Archive_TAR extends OC_Archive{
 	 */
 	function rename($source,$dest){
 		//no proper way to delete, rename entire archive, rename file and remake archive
-		$tmp=OC_Helper::tmpFolder();
+		$tmp=OCP\Files::tmpFolder();
 		$this->tar->extract($tmp);
 		rename($tmp.$source,$tmp.$dest);
 		$this->tar=null;
@@ -177,7 +179,7 @@ class OC_Archive_TAR extends OC_Archive{
 	 * @return bool
 	 */
 	function extractFile($path,$dest){
-		$tmp=OC_Helper::tmpFolder();
+		$tmp=OCP\Files::tmpFolder();
 		if(!$this->fileExists($path)){
 			return false;
 		}
@@ -185,7 +187,7 @@ class OC_Archive_TAR extends OC_Archive{
 		if($success){
 			rename($tmp.$path,$dest);
 		}
-		OC_Helper::rmdirr($tmp);
+		OCP\Files::rmdirr($tmp);
 		return $success;
 	}
 	/**
@@ -216,9 +218,9 @@ class OC_Archive_TAR extends OC_Archive{
 			return false;
 		}
 		//no proper way to delete, extract entire archive, delete file and remake archive
-		$tmp=OC_Helper::tmpFolder();
+		$tmp=OCP\Files::tmpFolder();
 		$this->tar->extract($tmp);
-		OC_Helper::rmdirr($tmp.$path);
+		OCP\Files::rmdirr($tmp.$path);
 		$this->tar=null;
 		unlink($this->path);
 		$this->reopen();
@@ -237,7 +239,7 @@ class OC_Archive_TAR extends OC_Archive{
 		}else{
 			$ext='';
 		}
-		$tmpFile=OC_Helper::tmpFile($ext);
+		$tmpFile=OCP\Files::tmpFile($ext);
 		if($this->fileExists($path)){
 			$this->extractFile($path,$tmpFile);
 		}elseif($mode=='r' or $mode=='rb'){
diff --git a/apps/files_archive/lib/zip.php b/lib/archive/zip.php
old mode 100644
new mode 100755
similarity index 97%
rename from apps/files_archive/lib/zip.php
rename to lib/archive/zip.php
index 5a5bc766875ddde02b3d02abac2f2fd825dc274b..22ab48937ebadaa9fb87e13e1a516d0c019aa4bb
--- a/apps/files_archive/lib/zip.php
+++ b/lib/archive/zip.php
@@ -19,7 +19,7 @@ class OC_Archive_ZIP extends OC_Archive{
 		$this->zip=new ZipArchive();
 		if($this->zip->open($source,ZipArchive::CREATE)){
 		}else{
-			OC_LOG::write('files_archive','Error while opening archive '.$source,OC_Log::WARN);
+			OCP\Util::writeLog('files_archive','Error while opening archive '.$source,OCP\Util::WARN);
 		}
 	}
 	/**
@@ -169,7 +169,7 @@ class OC_Archive_ZIP extends OC_Archive{
 			}else{
 				$ext='';
 			}
-			$tmpFile=OC_Helper::tmpFile($ext);
+			$tmpFile=OCP\Files::tmpFile($ext);
 			OC_CloseStreamWrapper::$callBacks[$tmpFile]=array($this,'writeBack');
 			if($this->fileExists($path)){
 				$this->extractFile($path,$tmpFile);
diff --git a/lib/base.php b/lib/base.php
index f3dacdc0f76ae7769891d5447eab1519ae9d9cbd..40df2b0c56cb3765249dc2002b90755a6fc44051 100644
--- a/lib/base.php
+++ b/lib/base.php
@@ -62,15 +62,22 @@ class OC{
 	 * the root path of the 3rdparty folder for http requests (e.g. owncloud/3rdparty)
 	 */
 	public static $THIRDPARTYWEBROOT = '';
-        /**
-         * The installation path of the apps folder on the server (e.g. /srv/http/owncloud)
-         */
-        public static $APPSROOT = '';
-        /**
-         * the root path of the apps folder for http requests (e.g. owncloud)
-         */
-        public static $APPSWEBROOT = '';
-
+	/**
+	 * The installation path of the apps folder on the server (e.g. /srv/http/owncloud)
+	 */
+	public static $APPSROOT = '';
+	/**
+	 * the root path of the apps folder for http requests (e.g. owncloud)
+	 */
+	public static $APPSWEBROOT = '';
+	/*
+	 * requested app
+	 */
+	public static $REQUESTEDAPP = '';
+	/*
+	 * requested file of app
+	 */
+	public static $REQUESTEDFILE = '';
 	/**
 	 * SPL autoload
 	 */
@@ -81,6 +88,9 @@ class OC{
 		elseif(strpos($className,'OC_')===0){
 			require_once strtolower(str_replace('_','/',substr($className,3)) . '.php');
 		}
+		elseif(strpos($className,'OCP\\')===0){
+			require_once 'public/'.strtolower(str_replace('\\','/',substr($className,3)) . '.php');
+		}
 		elseif(strpos($className,'Sabre_')===0) {
 			require_once str_replace('_','/',$className) . '.php';
 		}
@@ -161,12 +171,15 @@ class OC{
 		}
 
 		// search the apps folder
-		if(file_exists(OC::$SERVERROOT.'/apps')){
+		if(OC_Config::getValue('appsroot', '')<>''){
+			OC::$APPSROOT=OC_Config::getValue('appsroot', '');
+			OC::$APPSWEBROOT=OC_Config::getValue('appsurl', '');
+		}elseif(file_exists(OC::$SERVERROOT.'/apps')){
 			OC::$APPSROOT=OC::$SERVERROOT;
 			OC::$APPSWEBROOT=OC::$WEBROOT;
 		}elseif(file_exists(OC::$SERVERROOT.'/../apps')){
-			OC::$APPSWEBROOT=rtrim(dirname(OC::$WEBROOT), '/');
 			OC::$APPSROOT=rtrim(dirname(OC::$SERVERROOT), '/');
+			OC::$APPSWEBROOT=rtrim(dirname(OC::$WEBROOT), '/');
 		}else{
 			echo("apps directory not found! Please put the ownCloud apps folder in the ownCloud folder or the folder above. You can also configure the location in the config.php file.");
 			exit;
@@ -261,6 +274,34 @@ class OC{
 		ini_set('session.cookie_httponly','1;');
 		session_start();
 	}
+	
+	public static function loadapp(){
+		if(file_exists(OC::$APPSROOT . '/apps/' . OC::$REQUESTEDAPP . '/index.php')){
+			require_once(OC::$APPSROOT . '/apps/' . OC::$REQUESTEDAPP . '/index.php');
+		}else{
+			trigger_error('The requested App was not found.', E_USER_ERROR);//load default app instead?
+		}
+	}
+	
+	public static function loadfile(){
+		if(file_exists(OC::$APPSROOT . '/apps/' . OC::$REQUESTEDAPP . '/' . OC::$REQUESTEDFILE)){
+			if(substr(OC::$REQUESTEDFILE, -3) == 'css'){
+				$appswebroot = (string) OC::$APPSWEBROOT;
+				$webroot = (string) OC::$WEBROOT;
+				$cssfile = file_get_contents(OC::$APPSROOT . '/apps/' . OC::$REQUESTEDAPP . '/' . OC::$REQUESTEDFILE);
+				$cssfile = str_replace('%appswebroot%', $appswebroot, $cssfile);
+				$cssfile = str_replace('%webroot%', $webroot, $cssfile);
+				header('Content-Type: text/css');
+				echo $cssfile;
+				exit;
+			}elseif(substr(OC::$REQUESTEDFILE, -3) == 'php'){
+				require_once(OC::$APPSROOT . '/apps/' . OC::$REQUESTEDAPP . '/' . OC::$REQUESTEDFILE);
+			}	
+		}else{
+			header('HTTP/1.0 404 Not Found');
+			exit;
+		}
+	}
 
 	public static function init(){
 		// register autoloader
@@ -322,6 +363,16 @@ class OC{
 		self::checkInstalled();
 		self::checkSSL();
 
+                // CSRF protection
+                if(isset($_SERVER['HTTP_REFERER'])) $referer=$_SERVER['HTTP_REFERER']; else $referer='';
+                if(isset($_SERVER['HTTPS']) and $_SERVER['HTTPS']<>'') $protocol='https://'; else $protocol='http://';
+                $server=$protocol.$_SERVER['SERVER_NAME'];
+                if(($_SERVER['REQUEST_METHOD']=='POST') and (substr($referer,0,strlen($server))<>$server)) {
+                        $url = $protocol.$_SERVER['SERVER_NAME'].OC::$WEBROOT.'/index.php';
+                        header("Location: $url");
+                        exit();
+                } 
+
 		self::initSession();
 		self::initTemplateEngine();
 		self::checkUpgrade();
@@ -371,6 +422,35 @@ class OC{
 
 		//make sure temporary files are cleaned up
 		register_shutdown_function(array('OC_Helper','cleanTmp'));
+		
+		//parse the given parameters
+		self::$REQUESTEDAPP = (isset($_GET['app'])?strip_tags($_GET['app']):'files');
+		if(substr_count(self::$REQUESTEDAPP, '?') != 0){
+			$app = substr(self::$REQUESTEDAPP, 0, strpos(self::$REQUESTEDAPP, '?'));
+			$param = substr(self::$REQUESTEDAPP, strpos(self::$REQUESTEDAPP, '?') + 1);
+			parse_str($param, $get);
+			$_GET = array_merge($_GET, $get);
+			self::$REQUESTEDAPP = $app;
+			$_GET['app'] = $app;
+		}
+		self::$REQUESTEDFILE = (isset($_GET['getfile'])?$_GET['getfile']:null);
+		if(substr_count(self::$REQUESTEDFILE, '?') != 0){
+			$file = substr(self::$REQUESTEDFILE, 0, strpos(self::$REQUESTEDFILE, '?'));
+			$param = substr(self::$REQUESTEDFILE, strpos(self::$REQUESTEDFILE, '?') + 1);
+			parse_str($param, $get);
+			$_GET = array_merge($_GET, $get);
+			self::$REQUESTEDFILE = $file;
+			$_GET['getfile'] = $file;
+		}
+		if(!is_null(self::$REQUESTEDFILE)){
+			$subdir = OC::$APPSROOT . '/' . self::$REQUESTEDAPP . '/' . self::$REQUESTEDFILE;
+			$parent = OC::$APPSROOT . '/' . self::$REQUESTEDAPP;
+			if(!OC_Helper::issubdirectory($subdir, $parent)){
+				self::$REQUESTEDFILE = null;
+				header('HTTP/1.0 404 Not Found');
+				exit;
+			}
+		}
 	}
 }
 
diff --git a/lib/connect.php b/lib/connect.php
deleted file mode 100644
index 22e48750a622ba0211f0bfb63c2207cf88b92722..0000000000000000000000000000000000000000
--- a/lib/connect.php
+++ /dev/null
@@ -1,40 +0,0 @@
-<?php
-
-/**
-* ownCloud
-*
-* @author Frank Karlitschek
-* @copyright 2010 Frank Karlitschek karlitschek@kde.org
-*
-* This library is free software; you can redistribute it and/or
-* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
-* License as published by the Free Software Foundation; either
-* version 3 of the License, or any later version.
-*
-* This library 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 AFFERO GENERAL PUBLIC LICENSE for more details.
-*
-* You should have received a copy of the GNU Affero General Public
-* License along with this library.  If not, see <http://www.gnu.org/licenses/>.
-*
-*/
-
-/**
- * Class for connecting multiply ownCloud installations
- *
- */
-class OC_Connect{
-	static private $clouds=array();
-
-	static function connect($path,$user,$password){
-		$cloud=new OC_REMOTE_CLOUD($path,$user,$password);
-		if($cloud->connected){
-			self::$clouds[$path]=$cloud;
-			return $cloud;
-		}else{
-			return false;
-		}
-	}
-}
diff --git a/lib/connector/sabre/directory.php b/lib/connector/sabre/directory.php
index cc37bf22d5dae2e15257e893b8b0a348ebcfda80..912c8cd439a10b3a6b2b5f934c08ce875ba1a11a 100644
--- a/lib/connector/sabre/directory.php
+++ b/lib/connector/sabre/directory.php
@@ -50,7 +50,7 @@ class OC_Connector_Sabre_Directory extends OC_Connector_Sabre_Node implements Sa
 
 		$path = $this->path . '/' . $name;
 
-		if (!OC_Filesystem::file_exists($path)) throw new Sabre_DAV_Exception_FileNotFound('File with name ' . $path . ' could not be located');
+		if (!OC_Filesystem::file_exists($path)) throw new Sabre_DAV_Exception_NotFound('File with name ' . $path . ' could not be located');
 
 		if (OC_Filesystem::is_dir($path)) {
 
diff --git a/lib/connector/sabre/principal.php b/lib/connector/sabre/principal.php
index 28a36438e8767d5c4d1fb4dd9fdcb5ec441a6b4c..d1456f7c64215a780c96f24d5d6ace63bcff47d3 100644
--- a/lib/connector/sabre/principal.php
+++ b/lib/connector/sabre/principal.php
@@ -46,7 +46,7 @@ class OC_Connector_Sabre_Principal implements Sabre_DAVACL_IPrincipalBackend {
 	 * @return array
 	 */
 	public function getPrincipalByPath($path) {
-		list($prefix,$name) = Sabre_DAV_URLUtil::splitPath($path);
+		list($prefix,$name) = explode('/', $path);
 
 		if ($prefix == 'principals' && OC_User::userExists($name)) {
 			return array(
@@ -115,4 +115,6 @@ class OC_Connector_Sabre_Principal implements Sabre_DAVACL_IPrincipalBackend {
 	public function setGroupMemberSet($principal, array $members) {
 		throw new Sabre_DAV_Exception('Setting members of the group is not supported yet');
 	}
+	function updatePrincipal($path, $mutations){return 0;}
+	function searchPrincipals($prefixPath, array $searchProperties){return 0;}
 }
diff --git a/lib/db.php b/lib/db.php
index 9364b9e0015a91cd8671df775578db58ebfb4f12..2f74cc6dd95c66222f949f90869cfde38aaa5bba 100644
--- a/lib/db.php
+++ b/lib/db.php
@@ -36,7 +36,25 @@ class OC_DB {
 	static private $affected=0;
 	static private $result=false;
 	static private $inTransaction=false;
+	static private $prefix=null;
+	static private $type=null;
 
+	/**
+	 * check which backend we should use
+	 * @return BACKEND_MDB2 or BACKEND_PDO
+	 */
+	private static function getDBBackend(){
+		$backend=self::BACKEND_MDB2;
+		if(class_exists('PDO') && OC_Config::getValue('installed', false)){//check if we can use PDO, else use MDB2 (instalation always needs to be done my mdb2)
+			$type = OC_Config::getValue( "dbtype", "sqlite" );
+			if($type=='sqlite3') $type='sqlite';
+			$drivers=PDO::getAvailableDrivers();
+			if(array_search($type,$drivers)!==false){
+				$backend=self::BACKEND_PDO;
+			}
+		}
+	}
+	
 	/**
 	 * @brief connects to the database
 	 * @returns true if connection can be established or nothing (die())
@@ -48,15 +66,7 @@ class OC_DB {
 			return;
 		}
 		if(is_null($backend)){
-			$backend=self::BACKEND_MDB2;
-			if(class_exists('PDO') && OC_Config::getValue('installed', false)){//check if we can use PDO, else use MDB2 (instalation always needs to be done my mdb2)
-				$type = OC_Config::getValue( "dbtype", "sqlite" );
-				if($type=='sqlite3') $type='sqlite';
-				$drivers=PDO::getAvailableDrivers();
-				if(array_search($type,$drivers)!==false){
-					$backend=self::BACKEND_PDO;
-				}
-			}
+			$backend=self::getDBBackend();
 		}
 		if($backend==self::BACKEND_PDO){
 			self::connectPDO();
@@ -423,8 +433,14 @@ class OC_DB {
 	private static function processQuery( $query ){
 		self::connect();
 		// We need Database type and table prefix
-		$type = OC_Config::getValue( "dbtype", "sqlite" );
-		$prefix = OC_Config::getValue( "dbtableprefix", "oc_" );
+		if(is_null(self::$type)){
+			self::$type=OC_Config::getValue( "dbtype", "sqlite" );
+		}
+		$type = self::$type;
+		if(is_null(self::$prefix)){
+			self::$prefix=OC_Config::getValue( "dbtableprefix", "oc_" );
+		}
+		$prefix = self::$prefix;
 		
 		// differences in escaping of table names ('`' for mysql) and getting the current timestamp
 		if( $type == 'sqlite' || $type == 'sqlite3' ){
@@ -485,7 +501,7 @@ class OC_DB {
 	}
 	
 	/**
-	 * @breif replaces the owncloud tables with a new set
+	 * @brief replaces the owncloud tables with a new set
 	 * @param $file string path to the MDB2 xml db export file
 	 */
 	 public static function replaceDB( $file ){
diff --git a/lib/filecache.php b/lib/filecache.php
index cdd91dcbfa4e3a5405fd68065d3def68547b48f4..091a7939e1a909df802100c2a1b041819f6dfa3e 100644
--- a/lib/filecache.php
+++ b/lib/filecache.php
@@ -64,7 +64,7 @@ class OC_FileCache{
 		if(is_array($result)){
 			return $result;
 		}else{
-			OC_Log::write('get(): file not found in cache ('.$path.')','core',OC_Log::DEBUG);
+			OC_Log::write('files','get(): file not found in cache ('.$path.')',OC_Log::DEBUG);
 			return false;
 		}
 	}
@@ -110,8 +110,13 @@ class OC_FileCache{
 			$data['versioned']=false;
 		}
 		$mimePart=dirname($data['mimetype']);
+		$data['size']=(int)$data['size'];
+		$data['ctime']=(int)$data['mtime'];
+		$data['writable']=(int)$data['writable'];
+		$data['encrypted']=(int)$data['encrypted'];
+		$data['versioned']=(int)$data['versioned'];
 		$user=OC_User::getUser();
-		$query=OC_DB::prepare('INSERT INTO *PREFIX*fscache(parent, name, path, path_hash, size, mtime, ctime, mimetype, mimepart,user,writable,encrypted,versioned) VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?)');
+		$query=OC_DB::prepare('INSERT INTO *PREFIX*fscache(parent, name, path, path_hash, size, mtime, ctime, mimetype, mimepart,`user`,writable,encrypted,versioned) VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?)');
 		$result=$query->execute(array($parent,basename($path),$path,md5($path),$data['size'],$data['mtime'],$data['ctime'],$data['mimetype'],$mimePart,$user,$data['writable'],$data['encrypted'],$data['versioned']));
 		if(OC_DB::isError($result)){
 			OC_Log::write('files','error while writing file('.$path.') to cache',OC_Log::ERROR);
@@ -208,9 +213,9 @@ class OC_FileCache{
 		}
 		$rootLen=strlen($root);
 		if(!$returnData){
-			$query=OC_DB::prepare('SELECT path FROM *PREFIX*fscache WHERE name LIKE ? AND user=?');
+			$query=OC_DB::prepare('SELECT path FROM *PREFIX*fscache WHERE name LIKE ? AND `user`=?');
 		}else{
-			$query=OC_DB::prepare('SELECT * FROM *PREFIX*fscache WHERE name LIKE ? AND user=?');
+			$query=OC_DB::prepare('SELECT * FROM *PREFIX*fscache WHERE name LIKE ? AND `user`=?');
 		}
 		$result=$query->execute(array("%$search%",OC_User::getUser()));
 		$names=array();
@@ -257,7 +262,7 @@ class OC_FileCache{
 		if(is_array($result)){
 			return $result;
 		}else{
-			OC_Log::write('getFolderContent(): file not found in cache ('.$path.')','core',OC_Log::DEBUG);
+			OC_Log::write('files','getFolderContent(): file not found in cache ('.$path.')',OC_Log::DEBUG);
 			return false;
 		}
 	}
@@ -281,6 +286,7 @@ class OC_FileCache{
 
 	/**
 	 * get the file id as used in the cache
+	 * unlike the public getId, full paths are used here (/usename/files/foo instead of /foo)
 	 * @param string $path
 	 * @return int
 	 */
@@ -299,10 +305,48 @@ class OC_FileCache{
 		if(is_array($result)){
 			return $result['id'];
 		}else{
-			OC_Log::write('getFileId(): file not found in cache ('.$path.')','core',OC_Log::DEBUG);
+			OC_Log::write('files','getFileId(): file not found in cache ('.$path.')',OC_Log::DEBUG);
 			return -1;
 		}
 	}
+	
+	/**
+	 * get the file id as used in the cache
+	 * @param string path
+	 * @param string root (optional)
+	 * @return int
+	 */
+	public static function getId($path,$root=''){
+		if(!$root){
+			$root=OC_Filesystem::getRoot();
+		}
+		if($root=='/'){
+			$root='';
+		}
+		$path=$root.$path;
+		return self::getFileId($path);
+	}
+	
+	/**
+	 * get the file path from the id, relative to the home folder of the user
+	 * @param int id
+	 * @param string user (optional)
+	 * @return string
+	 */
+	public static function getPath($id,$user=''){
+		if(!$user){
+			$user=OC_User::getUser();
+		}
+		$query=OC_DB::prepare('SELECT path FROM *PREFIX*fscache WHERE id=? AND `user`=?');
+		$result=$query->execute(array($id,$user));
+		$row=$result->fetchRow();
+		$path=$row['path'];
+		$root='/'.$user.'/files';
+		if(substr($path,0,strlen($root))!=$root){
+			return false;
+		}
+		return substr($path,strlen($root));
+	}
 
 	/**
 	 * get the file id of the parent folder, taking into account '/' has no parent
@@ -375,8 +419,12 @@ class OC_FileCache{
 			}
 			return $result;
 		}else{
-			OC_Log::write('get(): file not found in cache ('.$path.')','core',OC_Log::DEBUG);
-			return false;
+			OC_Log::write('files','getChached(): file not found in cache ('.$path.')',OC_Log::DEBUG);
+			if(isset(self::$savedData[$path])){
+				return self::$savedData[$path];
+			}else{
+				return array();
+			}
 		}
 	}
 	
@@ -441,7 +489,7 @@ class OC_FileCache{
 		}else{
 			return;
 		}
-		$size=OC_Filesystem::filesize($oldPath);
+		$size=OC_Filesystem::filesize($newPath);
 		self::increaseSize(dirname($fullOldPath),-$oldSize);
 		self::increaseSize(dirname($fullNewPath),$oldSize);
 		self::move($oldPath,$newPath);
@@ -498,6 +546,7 @@ class OC_FileCache{
 				}
 			}
 		}
+		self::cleanFolder($path,$root);
 		self::increaseSize($view->getRoot().$path,$totalSize);
 	}
 
@@ -514,6 +563,7 @@ class OC_FileCache{
 			$view=new OC_FilesystemView(($root=='/')?'':$root);
 		}
 		if(!$view->is_readable($path)) return; //cant read, nothing we can do
+		clearstatcache();
 		$stat=$view->stat($path);
 		$mimetype=$view->getMimeType($path);
 		$writable=$view->is_writable($path);
@@ -549,10 +599,10 @@ class OC_FileCache{
 		$root .= '%';
 		$user=OC_User::getUser();
 		if(!$part2){
-			$query=OC_DB::prepare('SELECT path FROM *PREFIX*fscache WHERE mimepart=? AND user=? AND path LIKE ?');
+			$query=OC_DB::prepare('SELECT path FROM *PREFIX*fscache WHERE mimepart=? AND `user`=? AND path LIKE ?');
 			$result=$query->execute(array($part1,$user, $root));
 		}else{
-			$query=OC_DB::prepare('SELECT path FROM *PREFIX*fscache WHERE mimetype=? AND user=? AND path LIKE ? ');
+			$query=OC_DB::prepare('SELECT path FROM *PREFIX*fscache WHERE mimetype=? AND `user`=? AND path LIKE ? ');
 			$result=$query->execute(array($part1.'/'.$part2,$user, $root));
 		}
 		$names=array();
@@ -620,7 +670,26 @@ class OC_FileCache{
 				}
 			}
 		}
+		
+		self::cleanFolder($path,$root);
+		
+		//update the folder last, so we can calculate the size correctly
+		if(!$root){//filesystem hooks are only valid for the default root
+			OC_Hook::emit('OC_Filesystem','post_write',array('path'=>$path));
+		}else{
+			self::fileSystemWatcherWrite(array('path'=>$path),$root);
+		}
+	}
 
+	/**
+	 * delete non existing files from the cache
+	 */
+	private static function cleanFolder($path,$root=''){
+		if(!$root){
+			$view=OC_Filesystem::getView();
+		}else{
+			$view=new OC_FilesystemView(($root=='/')?'':$root);
+		}
 		//check for removed files, not using getFolderContent to prevent loops
 		$parent=self::getFileId($view->getRoot().$path);
 		$query=OC_DB::prepare('SELECT name FROM *PREFIX*fscache WHERE parent=?');
@@ -635,12 +704,6 @@ class OC_FileCache{
 				}
 			}
 		}
-		//update the folder last, so we can calculate the size correctly
-		if(!$root){//filesystem hooks are only valid for the default root
-			OC_Hook::emit('OC_Filesystem','post_write',array('path'=>$path));
-		}else{
-			self::fileSystemWatcherWrite(array('path'=>$path),$root);
-		}
 	}
 
 	/**
diff --git a/lib/files.php b/lib/files.php
index 01558a68588c01c5239f21fe36ab0004bc92a066..107605fc34e4c45787c7e1296695fbe99734c621 100644
--- a/lib/files.php
+++ b/lib/files.php
@@ -104,22 +104,29 @@ class OC_Files {
 				header('Content-Type: application/zip');
 				header('Content-Length: ' . filesize($filename));
 			}else{
-				header('Content-Type: ' . OC_Filesystem::getMimeType($filename));
-				header('Content-Length: ' . OC_Filesystem::filesize($filename));
+				$fileData=OC_FileCache::get($filename);
+				header('Content-Type: ' . $fileData['mimetype']);
+				header('Content-Length: ' . $fileData['size']);
 			}
 		}elseif($zip or !OC_Filesystem::file_exists($filename)){
 			header("HTTP/1.0 404 Not Found");
 			$tmpl = new OC_Template( '', '404', 'guest' );
 			$tmpl->assign('file',$filename);
 			$tmpl->printPage();
-// 			die('404 Not Found');
 		}else{
 			header("HTTP/1.0 403 Forbidden");
 			die('403 Forbidden');
 		}
 		@ob_end_clean();
 		if($zip){
-			readfile($filename);
+			$handle=fopen($filename,'r');
+			if ($handle) {
+				$chunkSize = 8*1024;// 1 MB chunks
+				while (!feof($handle)) {
+					echo fread($handle, $chunkSize);
+					flush();
+				}
+			}
 			unlink($filename);
 		}else{
 			OC_Filesystem::readfile($filename);
@@ -225,7 +232,7 @@ class OC_Files {
 	*/
 	static function validateZipDownload($dir, $files) {
 		if(!OC_Config::getValue('allowZipDownload', true)) {
-			$l = new OC_L10N('files');
+			$l = OC_L10N::get('files');
 			header("HTTP/1.0 409 Conflict");
 			$tmpl = new OC_Template( '', 'error', 'user' );
 			$errors = array(
@@ -250,7 +257,7 @@ class OC_Files {
 				$totalsize += OC_Filesystem::filesize($dir.'/'.$files);
 			}
 			if($totalsize > $zipLimit) {
-				$l = new OC_L10N('files');
+				$l = OC_L10N::get('files');
 				header("HTTP/1.0 409 Conflict");
 				$tmpl = new OC_Template( '', 'error', 'user' );
 				$errors = array(
diff --git a/lib/filestorage/common.php b/lib/filestorage/common.php
index f632474df01d62f9cae1812d96369f83eab65fab..f0bfc064cb581ae9ed07dcbf64babf7f925eaff8 100644
--- a/lib/filestorage/common.php
+++ b/lib/filestorage/common.php
@@ -100,11 +100,11 @@ abstract class OC_Filestorage_Common extends OC_Filestorage {
 		}
 		$head=fread($source,8192);//8kb should suffice to determine a mimetype
 		if($pos=strrpos($path,'.')){
-			$extention=substr($path,$pos);
+			$extension=substr($path,$pos);
 		}else{
-			$extention='';
+			$extension='';
 		}
-		$tmpFile=OC_Helper::tmpFile($extention);
+		$tmpFile=OC_Helper::tmpFile($extension);
 		file_put_contents($tmpFile,$head);
 		$mime=OC_Helper::getMimeType($tmpFile);
 		unlink($tmpFile);
@@ -129,11 +129,11 @@ abstract class OC_Filestorage_Common extends OC_Filestorage {
 			return false;
 		}
 		if($pos=strrpos($path,'.')){
-			$extention=substr($path,$pos);
+			$extension=substr($path,$pos);
 		}else{
-			$extention='';
+			$extension='';
 		}
-		$tmpFile=OC_Helper::tmpFile($extention);
+		$tmpFile=OC_Helper::tmpFile($extension);
 		$target=fopen($tmpFile,'w');
 		$count=OC_Helper::streamCopy($source,$target);
 		return $tmpFile;
diff --git a/lib/filesystem.php b/lib/filesystem.php
index dc678fba74c3d45a14c55b06e08e5250b6303306..cac7e8648ef127e08a5faeaf7d5e2e966c4290a3 100644
--- a/lib/filesystem.php
+++ b/lib/filesystem.php
@@ -196,9 +196,57 @@ class OC_Filesystem{
 			return false;
 		}
 		self::$defaultInstance=new OC_FilesystemView($root);
+
+		//load custom mount config
+		if(is_file(OC::$SERVERROOT.'/config/mount.php')){
+			$mountConfig=include(OC::$SERVERROOT.'/config/mount.php');
+			if(isset($mountConfig['global'])){
+				foreach($mountConfig['global'] as $mountPoint=>$options){
+					self::mount($options['class'],$options['options'],$mountPoint);
+				}
+			}
+
+			if(isset($mountConfig['group'])){
+				foreach($mountConfig['group'] as $group=>$mounts){
+					if(OC_Group::inGroup(OC_User::getUser(),$group)){
+						foreach($mounts as $mountPoint=>$options){
+							$mountPoint=self::setUserVars($mountPoint);
+							foreach($options as &$option){
+								$option=self::setUserVars($option);
+							}
+							self::mount($options['class'],$options['options'],$mountPoint);
+						}
+					}
+				}
+			}
+
+			if(isset($mountConfig['user'])){
+				foreach($mountConfig['user'] as $user=>$mounts){
+					if($user==='all' or strtolower($user)===strtolower(OC_User::getUser())){
+						foreach($mounts as $mountPoint=>$options){
+							$mountPoint=self::setUserVars($mountPoint);
+							foreach($options as &$option){
+								$option=self::setUserVars($option);
+							}
+							self::mount($options['class'],$options['options'],$mountPoint);
+						}
+					}
+				}
+			}
+		}
+		
 		self::$loaded=true;
 	}
 
+	/**
+	 * fill in the correct values for $user, and $password placeholders
+	 * @param string intput
+	 * @return string
+	 */
+	private static function setUserVars($input){
+		return str_replace('$user',OC_User::getUser(),$input);
+	}
+
 	/**
 	 * get the default filesystem view
 	 * @return OC_FilesystemView
@@ -227,6 +275,7 @@ class OC_Filesystem{
 		if(class_exists($class)){
 			return new $class($arguments);
 		}else{
+			OC_Log::write('core','storage backend '.$class.' not found',OC_Log::ERROR);
 			return false;
 		}
 	}
diff --git a/lib/filesystemview.php b/lib/filesystemview.php
index 95873bd87cfabd61f519611d7ade6716dadf8497..ac5a0a3bff50bc81d6039dd614033a4fae05b8bd 100644
--- a/lib/filesystemview.php
+++ b/lib/filesystemview.php
@@ -136,15 +136,16 @@ class OC_FilesystemView {
 		return $this->basicOperation('filesize',$path);
 	}
 	public function readfile($path){
+		@ob_end_clean();
 		$handle=$this->fopen($path,'r');
 		if ($handle) {
-			$chunkSize = 1024*1024;// 1 MB chunks
+			$chunkSize = 8*1024;// 1 MB chunks
 			while (!feof($handle)) {
 				echo fread($handle, $chunkSize);
-				@ob_flush();
 				flush();
 			}
-			return $this->filesize($path);
+			$size=$this->filesize($path);
+			return $size;
 		}
 		return false;
 	}
@@ -174,11 +175,23 @@ class OC_FilesystemView {
 	}
 	public function file_put_contents($path,$data){
 		if(is_resource($data)){//not having to deal with streams in file_put_contents makes life easier
+			$exists=$this->file_exists($path);
+			$run=true;
+			if(!$exists){
+				OC_Hook::emit( OC_Filesystem::CLASSNAME, OC_Filesystem::signal_create, array( OC_Filesystem::signal_param_path => $path, OC_Filesystem::signal_param_run => &$run));
+			}
+			OC_Hook::emit( OC_Filesystem::CLASSNAME, OC_Filesystem::signal_write, array( OC_Filesystem::signal_param_path => $path, OC_Filesystem::signal_param_run => &$run));
+			if(!$run){
+				return false;
+			}
 			$target=$this->fopen($path,'w');
 			if($target){
 				$count=OC_Helper::streamCopy($data,$target);
 				fclose($target);
 				fclose($data);
+				if(!$exists){
+					OC_Hook::emit( OC_Filesystem::CLASSNAME, OC_Filesystem::signal_post_create, array( OC_Filesystem::signal_param_path => $path));
+				}
 				OC_Hook::emit( OC_Filesystem::CLASSNAME, OC_Filesystem::signal_post_write, array( OC_Filesystem::signal_param_path => $path));
 				return $count>0;
 			}else{
diff --git a/lib/group.php b/lib/group.php
index 4ae9302f78b1b97ae4b3a6a2a64f47488d403feb..9b2959d1f73c77cfa3dba3e8a0b4f88679d220ae 100644
--- a/lib/group.php
+++ b/lib/group.php
@@ -255,7 +255,12 @@ class OC_Group {
 	 * @return bool
 	 */
 	public static function groupExists($gid){
-		return in_array( $gid, self::getGroups());
+		foreach(self::$_usedBackends as $backend){
+			if ($backend->groupExists($gid)){
+				return true;
+			}
+		}
+		return false;
 	}
 	
 	/**
diff --git a/lib/group/backend.php b/lib/group/backend.php
index b3fc06ac9a87a700eba81c1d6eee2cd07670f39d..af6c53c803577cdcb5145d2d6c2922ddbb8efdea 100644
--- a/lib/group/backend.php
+++ b/lib/group/backend.php
@@ -82,4 +82,16 @@ abstract class OC_Group_Backend {
 	public function implementsActions($actions){
 		return (bool)($this->getSupportedActions() & $actions);
 	}
+
+	/**
+	 * check if a group exists
+	 * @param string $gid
+	 * @return bool
+	 */
+	public function groupExists($gid){
+		if(!$this->implementsActions(OC_GROUP_BACKEND_GET_GROUPS)){
+			return false;
+		}
+		return in_array($gid, $this->getGroups());
+	}
 }
diff --git a/lib/helper.php b/lib/helper.php
old mode 100755
new mode 100644
index 2026286352a8cddf8d1a4dd2a335439be540cb9d..82d1017debdd944592c003eb1925b8e336d95c38
--- a/lib/helper.php
+++ b/lib/helper.php
@@ -41,7 +41,15 @@ class OC_Helper {
 			$app .= '/';
 			// Check if the app is in the app folder
 			if( file_exists( OC::$APPSROOT . '/apps/'. $app.$file )){
-				$urlLinkTo =  OC::$APPSWEBROOT . '/apps/' . $app . $file;
+				if(substr($file, -3) == 'php' || substr($file, -3) == 'css'){	
+					if(substr($app, -1, 1) == '/'){
+						$app = substr($app, 0, strlen($app) - 1);
+					}
+					$urlLinkTo =  OC::$WEBROOT . '/?app=' . $app;
+					$urlLinkTo .= ($file!='index.php')?'&getfile=' . urlencode($file):'';
+				}else{
+					$urlLinkTo =  OC::$APPSWEBROOT . '/apps/' . $app . $file;
+				}
 			}
 			else{
 				$urlLinkTo =  OC::$WEBROOT . '/' . $app . $file;
@@ -310,9 +318,9 @@ class OC_Helper {
 		$mimeType='application/octet-stream';
 		if ($mimeType=='application/octet-stream') {
 			self::$mimetypes = include('mimetypes.fixlist.php');
-			$extention=strtolower(strrchr(basename($path), "."));
-			$extention=substr($extention,1);//remove leading .
-			$mimeType=(isset(self::$mimetypes[$extention]))?self::$mimetypes[$extention]:'application/octet-stream';
+			$extension=strtolower(strrchr(basename($path), "."));
+			$extension=substr($extension,1);//remove leading .
+			$mimeType=(isset(self::$mimetypes[$extension]))?self::$mimetypes[$extension]:'application/octet-stream';
 
 		}
 		if (@is_dir($path)) {
@@ -346,13 +354,33 @@ class OC_Helper {
 			if(!self::$mimetypes || self::$mimetypes != include('mimetypes.list.php')){
 				self::$mimetypes=include('mimetypes.list.php');
 			}
-			$extention=strtolower(strrchr(basename($path), "."));
-			$extention=substr($extention,1);//remove leading .
-			$mimeType=(isset(self::$mimetypes[$extention]))?self::$mimetypes[$extention]:'application/octet-stream';
+			$extension=strtolower(strrchr(basename($path), "."));
+			$extension=substr($extension,1);//remove leading .
+			$mimeType=(isset(self::$mimetypes[$extension]))?self::$mimetypes[$extension]:'application/octet-stream';
 		}
 		return $mimeType;
 	}
 
+	/**
+	 * get the mimetype form a data string
+	 * @param string data
+	 * @return string
+	 */
+	static function getStringMimeType($data){
+		if(function_exists('finfo_open') and function_exists('finfo_file')){
+			$finfo=finfo_open(FILEINFO_MIME);
+			return finfo_buffer($finfo, $data);
+		}else{
+			$tmpFile=OC_Helper::tmpFile();
+			$fh=fopen($tmpFile,'wb');
+			fwrite($fh,$data,8024);
+			fclose($fh);
+			$mime=self::getMimeType($tmpFile);
+			unset($tmpFile);
+			return $mime;
+		}
+	}
+
 	/**
 	 * @brief Checks $_REQUEST contains a var for the $s key. If so, returns the html-escaped value of this var; otherwise returns the default value provided by $d.
 	 * @param $s name of the var to escape, if set.
@@ -492,4 +520,70 @@ class OC_Helper {
 			}
 		}
 	}
+
+    /**
+     * Adds a suffix to the name in case the file exists
+     *
+     * @param $path
+     * @param $filename
+     * @return string
+     */
+    public static function buildNotExistingFileName($path, $filename){
+	    if($path==='/'){
+		    $path='';
+	    }
+        if ($pos = strrpos($filename, '.')) {
+            $name = substr($filename, 0, $pos);
+            $ext = substr($filename, $pos);
+        } else {
+            $name = $filename;
+        }
+
+        $newpath = $path . '/' . $filename;
+        $newname = $filename;
+        $counter = 2;
+        while (OC_Filesystem::file_exists($newpath)) {
+            $newname = $name . ' (' . $counter . ')' . $ext;
+            $newpath = $path . '/' . $newname;
+            $counter++;
+        }
+
+        return $newpath;
+    }
+	
+	/*
+	 * checks if $sub is a subdirectory of $parent
+	 * 
+	 * @param $sub 
+	 * @param $parent
+	 * @return bool
+	 */
+	public static function issubdirectory($sub, $parent){
+		if($sub == null || $sub == '' || $parent == null || $parent == ''){
+			return false;
+		}
+		$realpath_sub = realpath($sub);
+		$realpath_parent = realpath($parent);
+		if(($realpath_sub == false && substr_count($realpath_sub, './') != 0) || ($realpath_parent == false && substr_count($realpath_parent, './') != 0)){ //it checks for  both ./ and ../
+			return false;
+		}
+		if($realpath_sub && $realpath_sub != '' && $realpath_parent && $realpath_parent != ''){
+			if(substr($realpath_sub, 0, strlen($realpath_parent)) == $realpath_parent){
+				return true;
+			}
+		}else{
+			if(substr($sub, 0, strlen($parent)) == $parent){
+				return true;
+			}
+		}
+		/*
+		echo 'SUB: ' . $sub . "\n";
+		echo 'PAR: ' . $parent . "\n";
+		echo 'REALSUB: ' . $realpath_sub . "\n";
+		echo 'REALPAR: ' . $realpath_parent . "\n";
+		echo substr($realpath_sub, 0, strlen($realpath_parent));
+		exit;
+		*/
+		return false;
+	}
 }
diff --git a/lib/installer.php b/lib/installer.php
index 38e17130e3c5ff55b96e9b50cca33457e652b5ab..b75c009c8f04ed2f6370d94f39bfd4091aecd489 100644
--- a/lib/installer.php
+++ b/lib/installer.php
@@ -47,6 +47,7 @@ class OC_Installer{
 	 * This function works as follows
 	 *   -# fetching the file
 	 *   -# unzipping it
+	 *   -# check the code
 	 *   -# installing the database at appinfo/database.xml
 	 *   -# including appinfo/install.php
 	 *   -# setting the installed version
@@ -91,6 +92,7 @@ class OC_Installer{
 		
 		//extract the archive in a temporary folder
 		$extractDir=OC_Helper::tmpFolder();
+		OC_Helper::rmdirr($extractDir);
 		mkdir($extractDir);
 		if($archive=OC_Archive::open($path)){
 			$archive->extract($extractDir);
@@ -102,7 +104,7 @@ class OC_Installer{
 			}
 			return false;
 		}
-		
+	
 		//load the info.xml file of the app
 		if(!is_file($extractDir.'/appinfo/info.xml')){
 			//try to find it in a subdir
@@ -125,6 +127,12 @@ class OC_Installer{
 		}
 		$info=OC_App::getAppInfo($extractDir.'/appinfo/info.xml',true);
 		$basedir=OC::$APPSROOT.'/apps/'.$info['id'];
+
+                // check the code for not allowed calls
+                if(!OC_Installer::checkCode($info['id'],$extractDir)){
+			OC_Helper::rmdirr($extractDir);
+                        return false;
+		}
 		
 		//check if an app with the same id is already installed
 		if(self::isInstalled( $info['id'] )){
@@ -151,8 +159,8 @@ class OC_Installer{
 		}
 		
 		//copy the app to the correct place
-		if(!mkdir($basedir)){
-			OC_Log::write('core','Can\'t create app folder ('.$basedir.')',OC_Log::ERROR);
+		if(@!mkdir($basedir)){
+			OC_Log::write('core','Can\'t create app folder. Please fix permissions. ('.$basedir.')',OC_Log::ERROR);
 			OC_Helper::rmdirr($extractDir);
 			if($data['source']=='http'){
 				unlink($path);
@@ -175,7 +183,7 @@ class OC_Installer{
 		}
 		
 		//set the installed version
-		OC_Appconfig::setValue($info['id'],'installed_version',$info['version']);
+		OC_Appconfig::setValue($info['id'],'installed_version',OC_App::getAppVersion($info['id']));
 		OC_Appconfig::setValue($info['id'],'enabled','no');
 		return $info['id'];
 	}
@@ -255,11 +263,8 @@ class OC_Installer{
 
 	/**
 	 * @brief Installs shipped apps
-	 * @param $enabled
 	 *
-	 * This function installs all apps found in the 'apps' directory;
-	 * If $enabled is true, apps are installed as enabled.
-	 * If $enabled is false, apps are installed as disabled.
+	 * This function installs all apps found in the 'apps' directory that should be enabled by default;
 	 */
 	public static function installShippedApps(){
 		$dir = opendir( OC::$APPSROOT."/apps" );
@@ -267,12 +272,11 @@ class OC_Installer{
 			if( substr( $filename, 0, 1 ) != '.' and is_dir(OC::$APPSROOT."/apps/$filename") ){
 				if( file_exists( OC::$APPSROOT."/apps/$filename/appinfo/app.php" )){
 					if(!OC_Installer::isInstalled($filename)){
-						$info = OC_Installer::installShippedApp($filename);
+						$info=OC_App::getAppInfo($filename);
 						$enabled = isset($info['default_enable']);
 						if( $enabled ){
+							OC_Installer::installShippedApp($filename);
 							OC_Appconfig::setValue($filename,'enabled','yes');
-						}else{
-							OC_Appconfig::setValue($filename,'enabled','no');
 						}
 					}
 				}
@@ -297,7 +301,52 @@ class OC_Installer{
 			include(OC::$APPSROOT."/apps/$app/appinfo/install.php");
 		}
 		$info=OC_App::getAppInfo($app);
-		OC_Appconfig::setValue($app,'installed_version',$info['version']);
+		OC_Appconfig::setValue($app,'installed_version',OC_App::getAppVersion($app));
 		return $info;
 	}
+
+
+        /**
+         * check the code of an app with some static code checks
+         * @param string $folder the folder of the app to check
+         * @returns true for app is o.k. and false for app is not o.k.
+         */
+        public static function checkCode($appname,$folder){
+
+		$blacklist=array(
+			'fopen(',
+			'eval('
+			// more evil pattern will go here later
+			// will will also check if an app is using private api once the public api is in place
+
+		);
+
+		// is the code checker enabled?
+		if(OC_Config::getValue('appcodechecker', false)){   
+
+			// check if grep is installed
+			$grep = exec('which grep');
+			if($grep=='') {
+				OC_Log::write('core','grep not installed. So checking the code of the app "'.$appname.'" was not possible',OC_Log::ERROR);
+				return true;
+			}
+
+			// iterate the bad patterns
+			foreach($blacklist as $bl) {
+				$cmd = 'grep -ri '.escapeshellarg($bl).' '.$folder.'';
+				$result = exec($cmd);
+				// bad pattern found
+				if($result<>'') {
+					OC_Log::write('core','App "'.$appname.'" is using a not allowed call "'.$bl.'". Installation refused.',OC_Log::ERROR);
+					return false;
+				}
+			}
+			return true;
+			
+		}else{
+          		return true;
+		}
+        }
+
+
 }
diff --git a/lib/json.php b/lib/json.php
index cedf79fd7c3fe5951dd5201ba69bb66c86052886..0d208ce12a223af5d61fde3a0cd45a9607266626 100644
--- a/lib/json.php
+++ b/lib/json.php
@@ -24,7 +24,7 @@ class OC_JSON{
 	*/
 	public static function checkAppEnabled($app){
 		if( !OC_App::isEnabled($app)){
-			$l = new OC_L10N('core');
+			$l = OC_L10N::get('core');
 			self::error(array( 'data' => array( 'message' => $l->t('Application is not enabled') )));
 			exit();
 		}
@@ -35,7 +35,7 @@ class OC_JSON{
 	*/
 	public static function checkLoggedIn(){
 		if( !OC_User::isLoggedIn()){
-			$l = new OC_L10N('core');
+			$l = OC_L10N::get('core');
 			self::error(array( 'data' => array( 'message' => $l->t('Authentication error') )));
 			exit();
 		}
@@ -47,7 +47,7 @@ class OC_JSON{
 	public static function checkAdminUser(){
 		self::checkLoggedIn();
 		if( !OC_Group::inGroup( OC_User::getUser(), 'admin' )){
-			$l = new OC_L10N('core');
+			$l = OC_L10N::get('core');
 			self::error(array( 'data' => array( 'message' => $l->t('Authentication error') )));
 			exit();
 		}
diff --git a/lib/l10n.php b/lib/l10n.php
index 636326f9864a84a4b3b718c09cf3ec4bb684eeb1..c0ecdbd1b705dd061d3c454e8327b62600649a83 100644
--- a/lib/l10n.php
+++ b/lib/l10n.php
@@ -24,6 +24,11 @@
  * This class is for i18n and l10n
  */
 class OC_L10N{
+	/**
+	 * cached instances
+	 */
+	protected static $instances=array();
+	
 	/**
 	 * cache
 	 */
@@ -46,6 +51,21 @@ class OC_L10N{
 		'date' => 'd.m.Y',
 		'datetime' => 'd.m.Y H:i:s',
 		'time' => 'H:i:s');
+		
+	/**
+	 * get an L10N instance
+	 * @return OC_L10N
+	 */
+	public static function get($app,$lang=null){
+		if(is_null($lang)){
+			if(!isset(self::$instances[$app])){
+				self::$instances[$app]=new OC_L10N($app);
+			}
+			return self::$instances[$app];
+		}else{
+			return new OC_L10N($app,$lang);
+		}
+	}
 	
 	/**
 	 * @brief The constructor
@@ -261,17 +281,14 @@ class OC_L10N{
 	public static function findAvailableLanguages($app=null){
 		$available=array('en');//english is always available
 		$dir = self::findI18nDir($app);
-		if(file_exists($dir)){
-			$dh = opendir($dir);
-			while(($file = readdir($dh)) !== false){
-				if(substr($file, -4, 4) == '.php' and (strlen($file) == 6 || strlen($file) == 9)){
+		if(is_dir($dir)){
+			$files=scandir($dir);
+			foreach($files as $file){
+				if(substr($file, -4, 4) == '.php'){
 					$i = substr($file, 0, -4);
-					if($i != ''){
-						$available[] = $i;
-					}
+					$available[] = $i;
 				}
 			}
-			closedir($dh);
 		}
 		return $available;
 	}
diff --git a/lib/log/owncloud.php b/lib/log/owncloud.php
index 0ed30510134407756cd2a57ac21ec77802927583..0b7a231d3045aa76de1432c8446be0dba25d9cdb 100644
--- a/lib/log/owncloud.php
+++ b/lib/log/owncloud.php
@@ -44,7 +44,7 @@ class OC_Log_Owncloud {
 	 * @param int level
 	 */
 	public static function write($app, $message, $level) {
-		$minLevel=OC_Config::getValue( "loglevel", 2 );
+		$minLevel=min(OC_Config::getValue( "loglevel", OC_Log::WARN ),OC_Log::ERROR);
 		if($level>=$minLevel){
 			$entry=array('app'=>$app, 'message'=>$message, 'level'=>$level,'time'=>time());
 			$fh=fopen(self::$logFile, 'a');
@@ -61,6 +61,7 @@ class OC_Log_Owncloud {
 	 */
 	public static function getEntries($limit=50, $offset=0){
 		self::init();
+		$minLevel=OC_Config::getValue( "loglevel", OC_Log::WARN );
 		$entries=array();
 		if(!file_exists(self::$logFile)) {
 			return array();
@@ -71,8 +72,13 @@ class OC_Log_Owncloud {
 		}
 		$end=max(count($contents)-$offset-1, 0);
 		$start=max($end-$limit,0);
-		for($i=$end;$i>$start;$i--) {
-			$entries[]=json_decode($contents[$i]);
+		$i=$end;
+		while($i>$start){
+			$entry=json_decode($contents[$i]);
+			if($entry->level>=$minLevel){
+				$entries[]=$entry;
+			}
+			$i--;
 		}
 		return $entries;
 	}
diff --git a/lib/mail.php b/lib/mail.php
new file mode 100644
index 0000000000000000000000000000000000000000..0045f8de6da1903fe603b84d5f28870d8a63da61
--- /dev/null
+++ b/lib/mail.php
@@ -0,0 +1,116 @@
+<?php
+/**
+ * Copyright (c) 2012 Frank Karlitschek <frank@owncloud.org>
+ * This file is licensed under the Affero General Public License version 3 or
+ * later.
+ * See the COPYING-README file.
+ */
+
+/**
+ * OC_Mail
+ *
+ * A class to handle mail sending.
+ */
+
+require_once('class.phpmailer.php');
+
+class OC_Mail {
+
+	/**
+	 * send an email 
+	 *
+	 * @param string $toaddress
+	 * @param string $toname
+	 * @param string $subject
+	 * @param string $mailtext
+	 * @param string $fromaddress
+	 * @param string $fromname
+	 * @param bool $html
+	 */
+	public static function send($toaddress,$toname,$subject,$mailtext,$fromaddress,$fromname,$html=0,$altbody='',$ccaddress='',$ccname='',$bcc='') {
+
+		$SMTPMODE = OC_Config::getValue( 'mail_smtpmode', 'sendmail' );
+		$SMTPHOST = OC_Config::getValue( 'mail_smtphost', '127.0.0.1' );
+		$SMTPAUTH = OC_Config::getValue( 'mail_smtpauth', 'false' ); 
+		$SMTPUSERNAME = OC_Config::getValue( 'mail_smtpname', '' ); 
+		$SMTPPASSWORD = OC_Config::getValue( 'mail_smtppassword', '' );  
+
+
+		$mailo = new PHPMailer();
+		if($SMTPMODE=='sendmail') {
+			$mailo->IsSendmail();
+		}elseif($SMTPMODE=='smtp'){
+			$mailo->IsSMTP();
+		}elseif($SMTPMODE=='qmail'){
+			$mailo->IsQmail();
+		}else{
+			$mailo->IsMail();
+		}
+
+
+		$mailo->Host = $SMTPHOST;
+		$mailo->SMTPAuth = $SMTPAUTH;
+		$mailo->Username = $SMTPUSERNAME;
+		$mailo->Password = $SMTPPASSWORD;
+
+		$mailo->From =$fromaddress;
+		$mailo->FromName = $fromname;;
+		$a=explode(' ',$toaddress);
+		foreach($a as $ad) {
+			$mailo->AddAddress($ad,$toname);
+		}
+
+		if($ccaddress<>'') $mailo->AddCC($ccaddress,$ccname);
+		if($bcc<>'') $mailo->AddBCC($bcc);
+
+		$mailo->AddReplyTo($fromaddress, $fromname);
+
+		$mailo->WordWrap = 50;
+		if($html==1) $mailo->IsHTML(true); else $mailo->IsHTML(false);
+
+		$mailo->Subject = $subject;
+		if($altbody=='') {
+			$mailo->Body    = $mailtext.OC_MAIL::getfooter();
+			$mailo->AltBody = '';
+		}else{
+			$mailo->Body    = $mailtext;
+			$mailo->AltBody = $altbody;
+		}
+		$mailo->CharSet = 'UTF-8';
+
+		$mailo->Send();
+		unset($mailo);
+
+		OC_Log::write('Mail from '.$fromname.' ('.$fromaddress.')'.' to: '.$toname.'('.$toaddress.')'.' subject: '.$subject,'mail',OC_Log::DEBUG);
+
+	}
+
+
+
+	/**
+	 * sending a mail based on a template
+	 *
+	 * @param texttemplate $texttemplate
+	 * @param htmltemplate $htmltemplate
+	 * @param data $data
+	 * @param To $toaddress
+	 * @param ToName $toname
+	 * @param Subject $subject
+	 * @param From $fromaddress
+	 * @param FromName $fromname
+	 * @param ccaddress $ccaddress
+	 * @param ccname $ccname
+	 * @param bcc $bcc
+	 */
+	public static function getfooter() {
+
+		$txt="\n--\n";
+		$txt.="ownCloud\n";
+		$txt.="Your Cloud, Your Data, Your Way!\n";
+		return($txt);
+
+	}
+
+
+
+}
diff --git a/lib/migrate.php b/lib/migrate.php
index dff3abe9e9336a34bd2f9397df62f5aeb5670430..f46d860e806500d1f81faf622023d8991083fbda 100644
--- a/lib/migrate.php
+++ b/lib/migrate.php
@@ -25,8 +25,8 @@
  * provides an interface to migrate users and whole ownclouds
  */
 class OC_Migrate{
-	
-	
+
+
 	// Array of OC_Migration_Provider objects
 	static private $providers=array();
 	// User id of the user to import/export
@@ -47,7 +47,7 @@ class OC_Migrate{
 	static private $zippath=false;
 	// Holds the OC_Migration_Content object
 	static private $content=false;
-	
+
 	/**
 	 * register a new migration provider
 	 * @param OC_Migrate_Provider $provider
@@ -55,28 +55,28 @@ class OC_Migrate{
 	public static function registerProvider($provider){
 		self::$providers[]=$provider;
 	}
-	
-	/** 
-	* @breif finds and loads the providers
+
+	/**
+	* @brief finds and loads the providers
 	*/
 	static private function findProviders(){
 		// Find the providers
 		$apps = OC_App::getAllApps();
-		
+
 		foreach($apps as $app){
 			$path = OC::$SERVERROOT . '/apps/' . $app . '/appinfo/migrate.php';
 			if( file_exists( $path ) ){
-				include( $path );	
-			}	
-		}	
+				include( $path );
+			}
+		}
 	}
-	
+
 	/**
-	 * @breif exports a user, or owncloud instance
+	 * @brief exports a user, or owncloud instance
 	 * @param optional $uid string user id of user to export if export type is user, defaults to current
 	 * @param ootional $type string type of export, defualts to user
 	 * @param otional $path string path to zip output folder
-	 * @return false on error, path to zip on success 
+	 * @return false on error, path to zip on success
 	 */
 	 public static function export( $uid=null, $type='user', $path=null ){
 		$datadir = OC_Config::getValue( 'datadirectory' );
@@ -84,47 +84,48 @@ class OC_Migrate{
 	 	$types = array( 'user', 'instance', 'system', 'userfiles' );
 	 	if( !in_array( $type, $types ) ){
 	 		OC_Log::write( 'migration', 'Invalid export type', OC_Log::ERROR );
-	 		return json_encode( array( array( 'success' => false ) ) );	
+	 		return json_encode( array( array( 'success' => false ) ) );
 	 	}
 	 	self::$exporttype = $type;
 	 	// Userid?
 	 	if( self::$exporttype == 'user' ){
 	 		// Check user exists
-	 		if( !is_null($uid) ){	
-		 		if( !OC_User_Database::userExists( $uid ) ){
+	 		if( !is_null($uid) ){
+                                $db = new OC_User_Database;
+		 		if( !$db->userExists( $uid ) ){
 					OC_Log::write('migration', 'User: '.$uid.' is not in the database and so cannot be exported.', OC_Log::ERROR);
-					return json_encode( array( 'success' => false ) );	
+					return json_encode( array( 'success' => false ) );
 				}
 				self::$uid = $uid;
 	 		} else {
-	 			self::$uid = OC_User::getUser();	
-	 		}	
+	 			self::$uid = OC_User::getUser();
+	 		}
 	 	}
 	 	// Calculate zipname
 	 	if( self::$exporttype == 'user' ){
-	 		$zipname = 'oc_export_' . self::$uid . '_' . date("y-m-d_H-i-s") . '.zip';		
+	 		$zipname = 'oc_export_' . self::$uid . '_' . date("y-m-d_H-i-s") . '.zip';
 	 	} else {
 	 		$zipname = 'oc_export_' . self::$exporttype . '_' . date("y-m-d_H-i-s") . '.zip';
 	 	}
 	 	// Calculate path
 	 	if( self::$exporttype == 'user' ){
-	 		self::$zippath = $datadir . '/' . self::$uid . '/' . $zipname;	
+	 		self::$zippath = $datadir . '/' . self::$uid . '/' . $zipname;
 	 	} else {
 	 		if( !is_null( $path ) ){
 	 			// Validate custom path
 	 			if( !file_exists( $path ) || !is_writeable( $path ) ){
 	 				OC_Log::write( 'migration', 'Path supplied is invalid.', OC_Log::ERROR );
-	 				return json_encode( array( 'success' => false ) );	
+	 				return json_encode( array( 'success' => false ) );
 	 			}
-	 			self::$zippath = $path . $zipname;	
+	 			self::$zippath = $path . $zipname;
 	 		} else {
 	 			// Default path
-	 			self::$zippath = get_temp_dir() . '/' . $zipname;	
+	 			self::$zippath = get_temp_dir() . '/' . $zipname;
 	 		}
 	 	}
 	 	// Create the zip object
 	 	if( !self::createZip() ){
-	 		return json_encode( array( 'success' => false ) );	
+	 		return json_encode( array( 'success' => false ) );
 	 	}
 	 	// Do the export
 	 	self::findProviders();
@@ -134,20 +135,20 @@ class OC_Migrate{
 	 			// Connect to the db
 	 			self::$dbpath = $datadir . '/' . self::$uid . '/migration.db';
 	 			if( !self::connectDB() ){
-	 				return json_encode( array( 'success' => false ) );	
+	 				return json_encode( array( 'success' => false ) );
 	 			}
 	 			self::$content = new OC_Migration_Content( self::$zip, self::$MDB2 );
 	 			// Export the app info
-			    $exportdata = self::exportAppData();			    
+			    $exportdata = self::exportAppData();
 				// Add the data dir to the zip
 				self::$content->addDir( $datadir . '/' . self::$uid, true, '/' );
-	 		break;	
+	 		break;
 	 		case 'instance':
 	 			self::$content = new OC_Migration_Content( self::$zip );
 				// Creates a zip that is compatable with the import function
 				$dbfile = tempnam( "/tmp", "owncloud_export_data_" );
 				OC_DB::getDbStructure( $dbfile, 'MDB2_SCHEMA_DUMP_ALL');
-				
+
 				// Now add in *dbname* and *dbprefix*
 				$dbexport = file_get_contents( $dbfile );
 				$dbnamestring = "<database>\n\n <name>" . OC_Config::getValue( "dbname", "owncloud" );
@@ -158,14 +159,14 @@ class OC_Migrate{
 				self::$content->addFromString( $dbexport, "dbexport.xml" );
 				// Add user data
 				foreach(OC_User::getUsers() as $user){
-					self::$content->addDir( $datadir . '/' . $user . '/', true, "/userdata/" );	
+					self::$content->addDir( $datadir . '/' . $user . '/', true, "/userdata/" );
 				}
 			break;
 			case 'userfiles':
 				self::$content = new OC_Migration_Content( self::$zip );
 				// Creates a zip with all of the users files
 				foreach(OC_User::getUsers() as $user){
-					self::$content->addDir( $datadir . '/' . $user . '/', true, "/" );	
+					self::$content->addDir( $datadir . '/' . $user . '/', true, "/" );
 				}
 			break;
 			case 'system':
@@ -178,70 +179,70 @@ class OC_Migrate{
 			break;
 	 	}
 	 	if( !$info = self::getExportInfo( $exportdata ) ){
-	 		return json_encode( array( 'success' => false ) );	
+	 		return json_encode( array( 'success' => false ) );
 	 	}
 	 	// Add the export info json to the export zip
 	 	self::$content->addFromString( $info, 'export_info.json' );
 	 	if( !self::$content->finish() ){
-	 		return json_encode( array( 'success' => false ) );	
+	 		return json_encode( array( 'success' => false ) );
 	 	}
-	 	return json_encode( array( 'success' => true, 'data' => self::$zippath ) );	
+	 	return json_encode( array( 'success' => true, 'data' => self::$zippath ) );
 	 }
-	 
+
 	/**
-	* @breif imports a user, or owncloud instance
+	* @brief imports a user, or owncloud instance
 	* @param $path string path to zip
 	* @param optional $type type of import (user or instance)
-	* @param optional $uid userid of new user 
+	* @param optional $uid userid of new user
 	*/
 	public static function import( $path, $type='user', $uid=null ){
 		OC_Util::checkAdminUser();
 		$datadir = OC_Config::getValue( 'datadirectory' );
 		// Extract the zip
 		if( !$extractpath = self::extractZip( $path ) ){
-			return json_encode( array( 'success' => false ) );	
+			return json_encode( array( 'success' => false ) );
 		}
 		// Get export_info.json
 		$scan = scandir( $extractpath );
 		// Check for export_info.json
 		if( !in_array( 'export_info.json', $scan ) ){
 			OC_Log::write( 'migration', 'Invalid import file, export_info.json note found', OC_Log::ERROR );
-			return json_encode( array( 'success' => false ) );	
+			return json_encode( array( 'success' => false ) );
 		}
 		$json = json_decode( file_get_contents( $extractpath . 'export_info.json' ) );
 		if( $json->exporttype != $type ){
 			OC_Log::write( 'migration', 'Invalid import file', OC_Log::ERROR );
-			return json_encode( array( 'success' => false ) );	
+			return json_encode( array( 'success' => false ) );
 		}
 		self::$exporttype = $type;
- 
+
 		// Have we got a user if type is user
 		if( self::$exporttype == 'user' ){
 			if( !$uid ){
 				self::$uid = $json->exporteduser;
-			} else {	
+			} else {
 				self::$uid = $uid;
 			}
 		}
-		
+
 		// Handle export types
 		switch( self::$exporttype ){
 			case 'user':
 				// Check user availability
 				if( OC_User::userExists( self::$uid ) ){
 					OC_Log::write( 'migration', 'User already exists', OC_Log::ERROR );
-					return json_encode( array( 'success' => false ) );	
+					return json_encode( array( 'success' => false ) );
 				}
 				$run = true;
 				OC_Hook::emit( "OC_User", "pre_createUser", array( "run" => &$run, "uid" => self::$uid, "password" => $json->hash ));
 				if( !$run ){
 					// Something stopped the user creation
 					OC_Log::write( 'migration', 'User creation failed', OC_Log::ERROR );
-					return json_encode( array( 'success' => false ) );	
+					return json_encode( array( 'success' => false ) );
 				}
 				// Create the user
 				if( !self::createUser( self::$uid, $json->hash ) ){
-					return json_encode( array( 'success' => false ) );	
+					return json_encode( array( 'success' => false ) );
 				}
 				// Emit the post_createUser hook (password is already hashed, will cause problems
 				OC_Hook::emit( "OC_User", "post_createUser", array( "uid" => self::$uid, "password" => $json->hash ));
@@ -249,19 +250,19 @@ class OC_Migrate{
 				$path = $datadir . '/' . self::$uid;
 				if( !mkdir( $path, 0755, true ) ){
 					OC_Log::write( 'migration', 'Failed to create users data dir: '.$path, OC_Log::ERROR );
-					return json_encode( array( 'success' => false ) );	
+					return json_encode( array( 'success' => false ) );
 				}
 				// Copy data
 				if( !self::copy_r( $extractpath . $json->exporteduser, $datadir . '/' . self::$uid ) ){
-					return json_encode( array( 'success' => false ) );	
+					return json_encode( array( 'success' => false ) );
 				}
-				// Import user app data 
+				// Import user app data
 				if( !$appsimported = self::importAppData( $extractpath . $json->exporteduser . '/migration.db', $json, self::$uid ) ){
-					return json_encode( array( 'success' => false ) );	
+					return json_encode( array( 'success' => false ) );
 				}
 				// All done!
 				if( !self::unlink_r( $extractpath ) ){
-					OC_Log::write( 'migration', 'Failed to delete the extracted zip', OC_Log::ERROR );	
+					OC_Log::write( 'migration', 'Failed to delete the extracted zip', OC_Log::ERROR );
 				}
 				return json_encode( array( 'success' => true, 'data' => $appsimported ) );
 			break;
@@ -270,59 +271,59 @@ class OC_Migrate{
 					 * EXPERIMENTAL
 					// Check for new data dir and dbexport before doing anything
 					// TODO
-					
+
 					// Delete current data folder.
 					OC_Log::write( 'migration', "Deleting current data dir", OC_Log::INFO );
 					if( !self::unlink_r( $datadir, false ) ){
 						OC_Log::write( 'migration', 'Failed to delete the current data dir', OC_Log::ERROR );
-						return json_encode( array( 'success' => false ) );	
+						return json_encode( array( 'success' => false ) );
 					}
-				
+
 					// Copy over data
 					if( !self::copy_r( $extractpath . 'userdata', $datadir ) ){
 						OC_Log::write( 'migration', 'Failed to copy over data directory', OC_Log::ERROR );
-						return json_encode( array( 'success' => false ) );	
+						return json_encode( array( 'success' => false ) );
 					}
-					
+
 					// Import the db
 					if( !OC_DB::replaceDB( $extractpath . 'dbexport.xml' ) ){
-						return json_encode( array( 'success' => false ) );	
+						return json_encode( array( 'success' => false ) );
 					}
 					// Done
-					return json_encode( 'success' => true ); 
+					return json_encode( 'success' => true );
 					*/
-			break;	
+			break;
 		}
-		
+
 	}
-	
+
 	/**
-	* @breif recursively deletes a directory
+	* @brief recursively deletes a directory
 	* @param $dir string path of dir to delete
 	* $param optional $deleteRootToo bool delete the root directory
 	* @return bool
 	*/
-	private static function unlink_r( $dir, $deleteRootToo=true ){ 
-		if( !$dh = @opendir( $dir ) ){ 
-			return false; 
-		} 
+	private static function unlink_r( $dir, $deleteRootToo=true ){
+		if( !$dh = @opendir( $dir ) ){
+			return false;
+		}
 		while (false !== ($obj = readdir($dh))){
-			if($obj == '.' || $obj == '..') { 
-				continue; 
-			} 
-			if (!@unlink($dir . '/' . $obj)){ 
-				self::unlink_r($dir.'/'.$obj, true); 
-			} 
-		} 
-		closedir($dh); 
-		if ( $deleteRootToo ) { 
-			@rmdir($dir); 
-		} 
-		return true; 
-	} 
-	
+			if($obj == '.' || $obj == '..') {
+				continue;
+			}
+			if (!@unlink($dir . '/' . $obj)){
+				self::unlink_r($dir.'/'.$obj, true);
+			}
+		}
+		closedir($dh);
+		if ( $deleteRootToo ) {
+			@rmdir($dir);
+		}
+		return true;
+	}
+
 	/**
-	* @breif copies recursively
+	* @brief copies recursively
 	* @param $path string path to source folder
 	* @param $dest string path to destination
 	* @return bool
@@ -349,12 +350,12 @@ class OC_Migrate{
 			return copy( $path, $dest );
 		} else {
 			return false;
-		}	
+		}
 	}
-	 
+
 	/**
-	* @breif tries to extract the import zip
-	* @param $path string path to the zip 
+	* @brief tries to extract the import zip
+	* @param $path string path to the zip
 	* @return string path to extract location (with a trailing slash) or false on failure
 	*/
 	static private function extractZip( $path ){
@@ -362,20 +363,20 @@ class OC_Migrate{
 		// Validate path
 	 	if( !file_exists( $path ) ){
 	 		OC_Log::write( 'migration', 'Zip not found', OC_Log::ERROR );
-	 		return false;	
+	 		return false;
 	 	}
 		if ( self::$zip->open( $path ) != TRUE ) {
 			OC_Log::write( 'migration', "Failed to open zip file", OC_Log::ERROR );
 			return false;
 		}
-		$to = get_temp_dir() . '/oc_import_' . self::$exporttype . '_' . date("y-m-d_H-i-s") . '/';		
+		$to = get_temp_dir() . '/oc_import_' . self::$exporttype . '_' . date("y-m-d_H-i-s") . '/';
 		if( !self::$zip->extractTo( $to ) ){
-			return false;	
+			return false;
 		}
-		self::$zip->close();	
+		self::$zip->close();
 		return $to;
 	}
-	 
+
 	/**
 	 * @brief connects to a MDB2 database scheme
 	 * @returns bool
@@ -393,16 +394,16 @@ class OC_Migrate{
 
 		return true;
 	}
-	
+
 	/**
-	 * @breif creates a migration.db in the users data dir with their app data in
+	 * @brief creates a migration.db in the users data dir with their app data in
 	 * @return bool whether operation was successfull
 	 */
 	private static function exportAppData( ){
-				
+
 		$success = true;
 		$return = array();
-				
+
 		// Foreach provider
 		foreach( self::$providers as $provider ){
 			$success = true;
@@ -413,37 +414,37 @@ class OC_Migrate{
 				if( is_array( $tables ) ){
 					// Save the table names
 					foreach($tables as $table){
-						$return['apps'][$provider->getID()]['tables'][] = $table;	
-					}	
+						$return['apps'][$provider->getID()]['tables'][] = $table;
+					}
 				} else {
 					// It failed to create the tables
 					$success = false;
-				}	
+				}
 			}
-			
+
 			// Run the export function?
 			if( $success ){
 				// Set the provider properties
 				$provider->setData( self::$uid, self::$content );
-				$return['apps'][$provider->getID()]['success'] = $provider->export();	
+				$return['apps'][$provider->getID()]['success'] = $provider->export();
 			} else {
-				$return['apps'][$provider->getID()]['success'] = false;	
-				$return['apps'][$provider->getID()]['message'] = 'failed to create the app tables';	
+				$return['apps'][$provider->getID()]['success'] = false;
+				$return['apps'][$provider->getID()]['message'] = 'failed to create the app tables';
 			}
-			
+
 			// Now add some app info the the return array
 			$appinfo = OC_App::getAppInfo( $provider->getID() );
-			$return['apps'][$provider->getID()]['version'] = $appinfo['version'];
-			
+			$return['apps'][$provider->getID()]['version'] = OC_App::getAppVersion($provider->getID());
+
 		}
-		
+
 		return $return;
-		
+
 	}
-	
-	
+
+
 	/**
-	 * @breif generates json containing export info, and merges any data supplied
+	 * @brief generates json containing export info, and merges any data supplied
 	 * @param optional $array array of data to include in the returned json
 	 * @return bool
 	 */
@@ -464,11 +465,11 @@ class OC_Migrate{
 				OC_Log::write( 'migration', 'Failed to get the users password hash', OC_log::ERROR);
 				return false;
 			}
-			$info['hash'] = $hash; 
-			$info['exporteduser'] = self::$uid; 	
+			$info['hash'] = $hash;
+			$info['exporteduser'] = self::$uid;
 		}
 		if( !is_array( $array ) ){
-			OC_Log::write( 'migration', 'Supplied $array was not an array in getExportInfo()', OC_Log::ERROR );	
+			OC_Log::write( 'migration', 'Supplied $array was not an array in getExportInfo()', OC_Log::ERROR );
 		}
 		// Merge in other data
 		$info = array_merge( $info, (array)$array );
@@ -476,9 +477,9 @@ class OC_Migrate{
 		$json = json_encode( $info );
 		return $json;
 	}
-	
+
 	/**
-	 * @breif connects to migration.db, or creates if not found
+	 * @brief connects to migration.db, or creates if not found
 	 * @param $db optional path to migration.db, defaults to user data dir
 	 * @return bool whether the operation was successful
 	 */
@@ -487,19 +488,19 @@ class OC_Migrate{
 		self::$dbpath = !is_null( $path ) ? $path : self::$dbpath;
 		if( !self::$dbpath ){
 			OC_Log::write( 'migration', 'connectDB() was called without dbpath being set', OC_Log::ERROR );
-			return false;	
+			return false;
 		}
 		// Already connected
 		if(!self::$MDB2){
 			require_once('MDB2.php');
-			
+
 			$datadir = OC_Config::getValue( "datadirectory", OC::$SERVERROOT."/data" );
-						
+
 			// DB type
 			if( class_exists( 'SQLite3' ) ){
 				$dbtype = 'sqlite3';
 			} else if( is_callable( 'sqlite_open' ) ){
-				$dbtype = 'sqlite';	
+				$dbtype = 'sqlite';
 			} else {
 				OC_Log::write( 'migration', 'SQLite not found', OC_Log::ERROR );
 				return false;
@@ -533,53 +534,53 @@ class OC_Migrate{
 			self::$MDB2->setFetchMode(MDB2_FETCHMODE_ASSOC);
 		}
 		return true;
-		
+
 	}
-	
+
 	/**
-	 * @breif creates the tables in migration.db from an apps database.xml
+	 * @brief creates the tables in migration.db from an apps database.xml
 	 * @param $appid string id of the app
 	 * @return bool whether the operation was successful
 	 */
 	static private function createAppTables( $appid ){
-			
+
 		if( !self::connectScheme() ){
-			return false;	
+			return false;
 		}
-		
-		// There is a database.xml file			
+
+		// There is a database.xml file
 		$content = file_get_contents( OC::$SERVERROOT . '/apps/' . $appid . '/appinfo/database.xml' );
-		
+
 		$file2 = 'static://db_scheme';
 		// TODO get the relative path to migration.db from the data dir
 		// For now just cheat
 		$path = pathinfo( self::$dbpath );
 		$content = str_replace( '*dbname*', self::$uid.'/migration', $content );
 		$content = str_replace( '*dbprefix*', '', $content );
-		
+
 		$xml = new SimpleXMLElement($content);
 		foreach($xml->table as $table){
-			$tables[] = (string)$table->name;	
-		}	
-		
+			$tables[] = (string)$table->name;
+		}
+
 		file_put_contents( $file2, $content );
-		
+
 		// Try to create tables
 		$definition = self::$schema->parseDatabaseDefinitionFile( $file2 );
 
 		unlink( $file2 );
-		
+
 		// Die in case something went wrong
 		if( $definition instanceof MDB2_Schema_Error ){
 			OC_Log::write( 'migration', 'Failed to parse database.xml for: '.$appid, OC_Log::FATAL );
 			OC_Log::write( 'migration', $definition->getMessage().': '.$definition->getUserInfo(), OC_Log::FATAL );
 			return false;
 		}
-		
+
 		$definition['overwrite'] = true;
-		
+
 		$ret = self::$schema->createDatabase( $definition );
-		
+
 		// Die in case something went wrong
 		if( $ret instanceof MDB2_Error ){
 			OC_Log::write( 'migration', 'Failed to create tables for: '.$appid, OC_Log::FATAL );
@@ -591,7 +592,7 @@ class OC_Migrate{
 	}
 
 	/**
-	* @breif tries to create the zip
+	* @brief tries to create the zip
 	* @param $path string path to zip destination
 	* @return bool
 	*/
@@ -600,18 +601,18 @@ class OC_Migrate{
 		// Check if properties are set
 		if( !self::$zippath ){
 			OC_Log::write('migration', 'createZip() called but $zip and/or $zippath have not been set', OC_Log::ERROR);
-			return false;	
+			return false;
 		}
 		if ( self::$zip->open( self::$zippath, ZIPARCHIVE::CREATE | ZIPARCHIVE::OVERWRITE ) !== TRUE ) {
 			OC_Log::write('migration', 'Failed to create the zip with error: '.self::$zip->getStatusString(), OC_Log::ERROR);
 			return false;
 	    } else {
-	    	return true;	
-	    }	
+	    	return true;
+	    }
 	}
-	
+
 	/**
-	* @breif returns an array of apps that support migration
+	* @brief returns an array of apps that support migration
 	* @return array
 	*/
 	static public function getApps(){
@@ -620,13 +621,13 @@ class OC_Migrate{
 			$path = OC::$SERVERROOT . '/apps/' . $app . '/lib/migrate.php';
 			if( file_exists( $path ) ){
 				$supportsmigration[] = $app;
-			}	
+			}
 		}
-		return $supportsmigration;	
+		return $supportsmigration;
 	}
-	
+
 	/**
-	* @breif imports a new user
+	* @brief imports a new user
 	* @param $db string path to migration.db
 	* @param $info object of migration info
 	* @param $uid optional uid to use
@@ -639,76 +640,76 @@ class OC_Migrate{
 			if(!self::connectDB( $db )){
 				OC_Log::write('migration','Failed to connect to migration.db',OC_Log::ERROR);
 				return false;
-			}	
+			}
 		} else {
-			OC_Log::write('migration','Migration.db not found at: '.$db, OC_Log::FATAL );	
+			OC_Log::write('migration','Migration.db not found at: '.$db, OC_Log::FATAL );
 			return false;
 		}
-		
+
 		// Find providers
 		self::findProviders();
 
 		// Generate importinfo array
-		$importinfo = array( 
+		$importinfo = array(
 							'olduid' => $info->exporteduser,
 							'newuid' => self::$uid
 							);
-							
+
 		foreach( self::$providers as $provider){
 			// Is the app in the export?
 			$id = $provider->getID();
 			if( isset( $info->apps->$id ) ){
 				// Is the app installed
 				if( !OC_App::isEnabled( $id ) ){
-					OC_Log::write( 'migration', 'App: ' . $id . ' is not installed, can\'t import data.', OC_Log::INFO );	
-					$appsstatus[$id] = 'notsupported';	
+					OC_Log::write( 'migration', 'App: ' . $id . ' is not installed, can\'t import data.', OC_Log::INFO );
+					$appsstatus[$id] = 'notsupported';
 				} else {
 					// Did it succeed on export?
 					if( $info->apps->$id->success ){
 						// Give the provider the content object
 						if( !self::connectDB( $db ) ){
-							return false;	
+							return false;
 						}
 						$content = new OC_Migration_Content( self::$zip, self::$MDB2 );
 						$provider->setData( self::$uid, $content, $info );
 						// Then do the import
 						if( !$appsstatus[$id] = $provider->import( $info->apps->$id, $importinfo ) ){
 							// Failed to import app
-							OC_Log::write( 'migration', 'Failed to import app data for user: ' . self::$uid . ' for app: ' . $id, OC_Log::ERROR );	
+							OC_Log::write( 'migration', 'Failed to import app data for user: ' . self::$uid . ' for app: ' . $id, OC_Log::ERROR );
 						}
 					} else {
 						// Add to failed list
-						$appsstatus[$id] = false;	
+						$appsstatus[$id] = false;
 					}
-				}	
-			}		
+				}
+			}
 		}
-		
+
 		return $appsstatus;
-	
+
 	}
-	
+
 	/*
-	* @breif creates a new user in the database
+	* @brief creates a new user in the database
 	* @param $uid string user_id of the user to be created
 	* @param $hash string hash of the user to be created
 	* @return bool result of user creation
 	*/
 	public static function createUser( $uid, $hash ){
-		
+
 		// Check if userid exists
 		if(OC_User::userExists( $uid )){
 			return false;
 		}
-		
+
 		// Create the user
 		$query = OC_DB::prepare( "INSERT INTO `*PREFIX*users` ( `uid`, `password` ) VALUES( ?, ? )" );
 		$result = $query->execute( array( $uid, $hash));
 		if( !$result ){
-			OC_Log::write('migration', 'Failed to create the new user "'.$uid."");	
+			OC_Log::write('migration', 'Failed to create the new user "'.$uid."");
 		}
 		return $result ? true : false;
-		
+
 	}
 
 }
diff --git a/lib/migration/content.php b/lib/migration/content.php
index d304051f3e6cf16a1f4ae9c29923f2bc00cb30cd..7ef88f36e43d2ad70c719df9a2a8e2b4c2a4b4aa 100644
--- a/lib/migration/content.php
+++ b/lib/migration/content.php
@@ -33,7 +33,7 @@ class OC_Migration_Content{
 	private $tmpfiles=false;
 	
 	/**
-	* @breif sets up the 
+	* @brief sets up the
 	* @param $zip ZipArchive object
 	* @param optional $db a MDB2 database object (required for exporttype user)
 	* @return bool
@@ -51,7 +51,7 @@ class OC_Migration_Content{
 		
 	}
 	
-	// @breif prepares the db
+	// @brief prepares the db
 	// @param $query the sql query to prepare
 	public function prepare( $query ){
 		
@@ -74,7 +74,7 @@ class OC_Migration_Content{
 	}
 	
 	/**
-	* @breif processes the db query
+	* @brief processes the db query
 	* @param $query the query to process
 	* @return string of processed query
 	*/
@@ -130,7 +130,7 @@ class OC_Migration_Content{
 	}
 	
 	/**
-	* @breif saves a sql data set into migration.db
+	* @brief saves a sql data set into migration.db
 	* @param $data a sql data set returned from self::prepare()->query()
 	* @param $options array of copyRows options
 	* @return void
@@ -175,7 +175,7 @@ class OC_Migration_Content{
 	}
 	
 	/**
-	* @breif adds a directory to the zip object
+	* @brief adds a directory to the zip object
 	* @param $dir string path of the directory to add
 	* @param $recursive bool 
 	* @param $internaldir string path of folder to add dir to in zip
@@ -209,7 +209,7 @@ class OC_Migration_Content{
 	}
 	
 	/**
-	* @breif adds a file to the zip from a given string
+	* @brief adds a file to the zip from a given string
 	* @param $data string of data to add
 	* @param $path the relative path inside of the zip to save the file to
 	* @return bool
@@ -228,7 +228,7 @@ class OC_Migration_Content{
 	}
 	
 	/**
-	* @breif closes the zip, removes temp files
+	* @brief closes the zip, removes temp files
 	* @return bool
 	*/
 	public function finish(){
@@ -241,7 +241,7 @@ class OC_Migration_Content{
 	}	
 	
 		/**
-	* @breif cleans up after the zip
+	* @brief cleans up after the zip
 	*/
 	private function cleanup(){
 		// Delete tmp files
@@ -249,4 +249,4 @@ class OC_Migration_Content{
 			unlink( $i );	
 		}	
 	}
-}
\ No newline at end of file
+}
diff --git a/lib/migration/provider.php b/lib/migration/provider.php
index feae29f1354bb1d3cef9b62819ac49d50d594ade..91336f3019d178063d1399e22290e594f60c3252 100644
--- a/lib/migration/provider.php
+++ b/lib/migration/provider.php
@@ -17,19 +17,19 @@ abstract class OC_Migration_Provider{
 	}
 	
 	/**
-	 * @breif exports data for apps
+	 * @brief exports data for apps
 	 * @return array appdata to be exported
 	 */
 	abstract function export( );
 	
 	/**
-	 * @breif imports data for the app
+	 * @brief imports data for the app
 	 * @return void
 	 */
 	abstract function import( );
 	
 	/**
-	* @breif sets the OC_Migration_Content object to $this->content
+	* @brief sets the OC_Migration_Content object to $this->content
 	* @param $content a OC_Migration_Content object
 	*/
 	public function setData( $uid, $content, $info=null ){
@@ -43,7 +43,7 @@ abstract class OC_Migration_Provider{
 	}
 	 	
 	/**
-	* @breif returns the appid of the provider
+	* @brief returns the appid of the provider
 	* @return string
 	*/
 	public function getID(){
diff --git a/lib/mimetypes.list.php b/lib/mimetypes.list.php
index e0570e84ea5c8c8e758ecc0339b2d7e4d029635e..ccf47999b1cfa1dbbe26c68c814b97405259c6b3 100644
--- a/lib/mimetypes.list.php
+++ b/lib/mimetypes.list.php
@@ -21,7 +21,7 @@
 */
 
 /**
- * list of mimetypes by extention
+ * list of mimetypes by extension
  */
 
 return array(
diff --git a/lib/ocsclient.php b/lib/ocsclient.php
old mode 100755
new mode 100644
index d830a4f3e7e0623f0882ec32ac2165fa5feb5608..aef51f38fb7f33e129f397d0634aff029f57e759
--- a/lib/ocsclient.php
+++ b/lib/ocsclient.php
@@ -162,6 +162,7 @@ class OC_OCSClient{
 		$app['preview3']=$tmp->smallpreviewpic3;
 		$app['changed']=strtotime($tmp->changed);
 		$app['description']=$tmp->description;
+		$app['detailpage']=$tmp->detailpage;
 
 		return $app;
 	}
@@ -199,7 +200,7 @@ class OC_OCSClient{
 	 *
 	 * This function returns a list of all the knowledgebase entries from the OCS server
 	 */
-	public static function getKnownledgebaseEntries($page,$pagesize){	
+	public static function getKnownledgebaseEntries($page,$pagesize,$search=''){	
 		if(OC_Config::getValue('knowledgebaseenabled', true)==false){
 			$kbe=array();
 			$kbe['totalitems']=0;
@@ -208,7 +209,8 @@ class OC_OCSClient{
 
 		$p= (int) $page;
 		$s= (int) $pagesize;
-		$url=OC_OCSClient::getKBURL().'/knowledgebase/data?type=150&page='.$p.'&pagesize='.$s;
+		if($search<>'') $searchcmd='&search='.urlencode($search); else $searchcmd='';
+		$url=OC_OCSClient::getKBURL().'/knowledgebase/data?type=150&page='.$p.'&pagesize='.$s.$searchcmd;
 
 		$kbe=array();
 		$xml=@file_get_contents($url);
diff --git a/lib/public/app.php b/lib/public/app.php
new file mode 100644
index 0000000000000000000000000000000000000000..80d0fd22b6ba932665c873b1c0172e7327f721e7
--- /dev/null
+++ b/lib/public/app.php
@@ -0,0 +1,169 @@
+<?php
+/**
+* ownCloud
+*
+* @author Frank Karlitschek
+* @copyright 2010 Frank Karlitschek karlitschek@kde.org
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+* License as published by the Free Software Foundation; either
+* version 3 of the License, or any later version.
+*
+* This library 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 AFFERO GENERAL PUBLIC LICENSE for more details.
+*
+* You should have received a copy of the GNU Affero General Public
+* License along with this library.  If not, see <http://www.gnu.org/licenses/>.
+*
+*/
+
+/**
+ * Public interface of ownCloud for apps to use.
+ * App Class.
+ *
+ */
+
+// use OCP namespace for all classes that are considered public. 
+// This means that they should be used by apps instead of the internal ownCloud classes
+namespace OCP;
+
+class App {
+
+
+	/**
+	 * @brief get the user id of the user currently logged in.
+	 * @return string uid or false
+	 */
+	public static function getUser(){
+		return \OC_USER::getUser();
+	}
+
+
+        /**
+         * @brief makes owncloud aware of this app
+         * @param $data array with all information
+         * @returns true/false
+         *
+         * This function registers the application. $data is an associative array.
+         * The following keys are required:
+         *   - id: id of the application, has to be unique ('addressbook')
+         *   - name: Human readable name ('Addressbook')
+         *   - version: array with Version (major, minor, bugfix) ( array(1, 0, 2))
+         *
+         * The following keys are optional:
+         *   - order: integer, that influences the position of your application in
+         *     a list of applications. Lower values come first.
+         *
+         */
+        public static function register( $data ){
+		return \OC_App::register( $data );
+        }
+
+
+	/**
+	 * register an admin form to be shown
+	 */
+	public static function registerAdmin($app,$page){
+		return \OC_App::registerAdmin($app,$page);
+	}
+
+
+        /**
+         * @brief adds an entry to the navigation
+         * @param $data array containing the data
+         * @returns true/false
+         *
+         * This function adds a new entry to the navigation visible to users. $data
+         * is an associative array.
+         * The following keys are required:
+         *   - id: unique id for this entry ('addressbook_index')
+         *   - href: link to the page
+         *   - name: Human readable name ('Addressbook')
+         *
+         * The following keys are optional:
+         *   - icon: path to the icon of the app
+         *   - order: integer, that influences the position of your application in
+         *     the navigation. Lower values come first.
+         */
+        public static function addNavigationEntry( $data ){
+		return \OC_App::addNavigationEntry($data);
+	}
+
+
+        /**
+         * @brief Read app metadata from the info.xml file
+         * @param string $appid id of the app or the path of the info.xml file
+         * @param boolean path (optional)
+         * @returns array
+        */
+        public static function getAppInfo($appid,$path=false){
+		return \OC_App::getAppInfo($appid,$path);
+	}
+
+
+        /**
+         * register a personal form to be shown
+         */
+        public static function registerPersonal($app,$page){
+		return \OC_App::registerPersonal($app,$page);
+	}
+
+
+        /**
+         * @brief marks a navigation entry as active
+         * @param $id id of the entry
+         * @returns true/false
+         *
+         * This function sets a navigation entry as active and removes the 'active'
+         * property from all other entries. The templates can use this for
+         * highlighting the current position of the user.
+         */
+        public static function setActiveNavigationEntry($id){
+		return \OC_App::setActiveNavigationEntry($id);
+	}
+
+
+        /**
+         * @brief checks whether or not an app is enabled
+         * @param $app app
+         * @returns true/false
+         *
+         * This function checks whether or not an app is enabled.
+         */
+        public static function isEnabled( $app ){
+		return \OC_App::isEnabled( $app );
+	}
+
+
+        /**
+        * Check if the app is enabled, redirects to home if not
+        */
+        public static function checkAppEnabled($app){
+                return \OC_Util::checkAppEnabled( $app );
+        }
+
+
+        /**
+         * get the last version of the app, either from appinfo/version or from appinfo/info.xml
+         */
+        public static function getAppVersion($appid){
+		return \OC_App::getAppVersion( $appid );
+	}
+
+
+        /**
+         * @param string appid
+         * @return OC_FilesystemView
+         */
+        public static function getStorage($appid){
+		return \OC_App::getStorage( $appid );
+	}
+
+
+}
+
+
+?>
diff --git a/lib/public/config.php b/lib/public/config.php
new file mode 100644
index 0000000000000000000000000000000000000000..5681f20e3b33d744c8ce98f1df762b9fcdd2ecd6
--- /dev/null
+++ b/lib/public/config.php
@@ -0,0 +1,133 @@
+<?php
+/**
+* ownCloud
+*
+* @author Frank Karlitschek
+* @copyright 2010 Frank Karlitschek karlitschek@kde.org
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+* License as published by the Free Software Foundation; either
+* version 3 of the License, or any later version.
+*
+* This library 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 AFFERO GENERAL PUBLIC LICENSE for more details.
+*
+* You should have received a copy of the GNU Affero General Public
+* License along with this library.  If not, see <http://www.gnu.org/licenses/>.
+*
+*/
+
+/**
+ * Public interface of ownCloud for apps to use.
+ * Config Class
+ *
+ */
+
+// use OCP namespace for all classes that are considered public. 
+// This means that they should be used by apps instead of the internal ownCloud classes
+namespace OCP;
+
+class Config {
+
+
+
+
+	/**
+	 * @brief Gets a value from config.php
+	 * @param $key key
+	 * @param $default = null default value
+	 * @returns the value or $default
+	 *
+	 * This function gets the value from config.php. If it does not exist,
+	 * $default will be returned.
+	 */
+	public static function getSystemValue( $key, $default = null ){
+		return(\OC_Config::getValue( $key, $default ));
+	}
+
+
+	/**
+	 * @brief Sets a value
+	 * @param $key key
+	 * @param $value value
+	 * @returns true/false
+	 *
+	 * This function sets the value and writes the config.php. If the file can
+	 * not be written, false will be returned.
+	 */
+	public static function setSystemValue( $key, $value ){
+		return(\OC_Config::setValue( $key, $value ));
+	}
+
+
+        /**
+         * @brief Gets the config value
+         * @param $app app
+         * @param $key key
+         * @param $default = null, default value if the key does not exist
+         * @returns the value or $default
+         *
+         * This function gets a value from the appconfig table. If the key does
+         * not exist the default value will be returnes
+         */
+        public static function getAppValue( $app, $key, $default = null ){
+		return(\OC_Appconfig::getValue( $app, $key, $default ));
+	}
+
+
+        /**
+         * @brief sets a value in the appconfig
+         * @param $app app
+         * @param $key key
+         * @param $value value
+         * @returns true/false
+         *
+         * Sets a value. If the key did not exist before it will be created.
+         */
+        public static function setAppValue( $app, $key, $value ){
+		return(\OC_Appconfig::setValue( $app, $key, $value ));
+	}
+
+
+        /**
+         * @brief Gets the preference
+         * @param $user user
+         * @param $app app
+         * @param $key key
+         * @param $default = null, default value if the key does not exist
+         * @returns the value or $default
+         *
+         * This function gets a value from the prefernces table. If the key does
+         * not exist the default value will be returnes
+         */
+        public static function getUserValue( $user, $app, $key, $default = null ){
+		return(\OC_Preferences::getValue( $user, $app, $key, $default ));
+	}
+
+
+        /**
+         * @brief sets a value in the preferences
+         * @param $user user
+         * @param $app app
+         * @param $key key
+         * @param $value value
+         * @returns true/false
+         *
+         * Adds a value to the preferences. If the key did not exist before, it
+         * will be added automagically.
+         */
+        public static function setUserValue( $user, $app, $key, $value ){
+		return(\OC_Preferences::setValue(  $user, $app, $key, $value ));
+	}
+
+
+
+
+
+
+}
+
+?>
diff --git a/lib/public/db.php b/lib/public/db.php
new file mode 100644
index 0000000000000000000000000000000000000000..b534756a5a07f14cf7aae25a2f45c5397cdec318
--- /dev/null
+++ b/lib/public/db.php
@@ -0,0 +1,92 @@
+<?php
+/**
+* ownCloud
+*
+* @author Frank Karlitschek
+* @copyright 2010 Frank Karlitschek karlitschek@kde.org
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+* License as published by the Free Software Foundation; either
+* version 3 of the License, or any later version.
+*
+* This library 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 AFFERO GENERAL PUBLIC LICENSE for more details.
+*
+* You should have received a copy of the GNU Affero General Public
+* License along with this library.  If not, see <http://www.gnu.org/licenses/>.
+*
+*/
+
+/**
+ * Public interface of ownCloud for apps to use.
+ * DB Class
+ *
+ */
+
+// use OCP namespace for all classes that are considered public. 
+// This means that they should be used by apps instead of the internal ownCloud classes
+namespace OCP;
+
+class DB {
+
+
+	/**
+	 * @brief Prepare a SQL query
+	 * @param $query Query string
+	 * @returns prepared SQL query
+	 *
+	 * SQL query via MDB2 prepare(), needs to be execute()'d!
+	 */
+	static public function prepare( $query ){
+		return(\OC_DB::prepare($query));
+	}
+
+	/**
+	 * @brief gets last value of autoincrement
+	 * @param $table string The optional table name (will replace *PREFIX*) and add sequence suffix
+	 * @returns id
+	 *
+	 * MDB2 lastInsertID()
+	 *
+	 * Call this method right after the insert command or other functions may
+	 * cause trouble!
+	 */
+	public static function insertid($table=null){
+		return(\OC_DB::insertid($table));
+	}
+
+
+
+	/**
+	 * Start a transaction
+	 */
+	public static function beginTransaction(){
+		return(\OC_DB::beginTransaction());
+	}
+
+
+	/**
+	 * Commit the database changes done during a transaction that is in progress
+	 */
+	public static function commit(){
+		return(\OC_DB::commit());
+	}
+
+
+	/**
+	 * check if a result is an error, works with MDB2 and PDOException
+	 * @param mixed $result
+	 * @return bool
+	 */
+	public static function isError($result){
+		return(\OC_DB::isError($result));
+	}
+
+
+
+}
+
+?>
diff --git a/lib/public/files.php b/lib/public/files.php
new file mode 100644
index 0000000000000000000000000000000000000000..f2153f33b900c1c159877e276fa6bd520a0ed77c
--- /dev/null
+++ b/lib/public/files.php
@@ -0,0 +1,114 @@
+<?php
+/**
+* ownCloud
+*
+* @author Frank Karlitschek
+* @copyright 2010 Frank Karlitschek karlitschek@kde.org
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+* License as published by the Free Software Foundation; either
+* version 3 of the License, or any later version.
+*
+* This library 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 AFFERO GENERAL PUBLIC LICENSE for more details.
+*
+* You should have received a copy of the GNU Affero General Public
+* License along with this library.  If not, see <http://www.gnu.org/licenses/>.
+*
+*/
+
+/**
+ * Public interface of ownCloud for apps to use.
+ * Files Class
+ *
+ */
+
+// use OCP namespace for all classes that are considered public. 
+// This means that they should be used by apps instead of the internal ownCloud classes
+namespace OCP;
+
+class Files {
+
+
+	/**
+	 * @brief Recusive deletion of folders
+	 * @param string $dir path to the folder
+	 *
+	 */
+	static function rmdirr($dir) {
+		\OC_Helper::rmdirr( $dir );
+	}
+
+
+	/**
+	 * get the mimetype form a local file
+	 * @param string path
+	 * @return string
+	 * does NOT work for ownClouds filesystem, use OC_FileSystem::getMimeType instead
+	 */
+	static function getMimeType($path){
+		return(\OC_Helper::getMimeType( $path ));
+	}
+
+	/**
+	 * copy the contents of one stream to another
+	 * @param resource source
+	 * @param resource target
+	 * @return int the number of bytes copied
+	 */
+	public static function streamCopy($source,$target){
+		return(\OC_Helper::streamCopy($source,$target));
+	}
+
+
+	/**
+	 * create a temporary file with an unique filename
+	 * @param string postfix
+	 * @return string
+	 *
+	 * temporary files are automatically cleaned up after the script is finished
+	 */
+	public static function tmpFile($postfix=''){
+		return(\OC_Helper::tmpFile($postfix));
+	}
+
+	/**
+	 * create a temporary folder with an unique filename
+	 * @return string
+	 *
+	 * temporary files are automatically cleaned up after the script is finished
+	 */
+	public static function tmpFolder(){
+		return(\OC_Helper::tmpFolder());
+	}
+
+	/**
+	 * Adds a suffix to the name in case the file exists
+	 *
+	 * @param $path
+	 * @param $filename
+	 * @return string
+	 */
+	public static function buildNotExistingFileName($path, $filename){
+		return(\OC_Helper::buildNotExistingFileName($path, $filename));
+	}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+}
+
+?>
diff --git a/lib/public/json.php b/lib/public/json.php
new file mode 100644
index 0000000000000000000000000000000000000000..36d3bed807fc62f14b11ed01d73560c2ea6deb3a
--- /dev/null
+++ b/lib/public/json.php
@@ -0,0 +1,94 @@
+<?php
+/**
+* ownCloud
+*
+* @author Frank Karlitschek
+* @copyright 2010 Frank Karlitschek karlitschek@kde.org
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+* License as published by the Free Software Foundation; either
+* version 3 of the License, or any later version.
+*
+* This library 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 AFFERO GENERAL PUBLIC LICENSE for more details.
+*
+* You should have received a copy of the GNU Affero General Public
+* License along with this library.  If not, see <http://www.gnu.org/licenses/>.
+*
+*/
+
+/**
+ * Public interface of ownCloud for apps to use.
+ * JSON Class
+ *
+ */
+
+// use OCP namespace for all classes that are considered public. 
+// This means that they should be used by apps instead of the internal ownCloud classes
+namespace OCP;
+
+class JSON {
+
+
+
+	/**
+	* Encode and print $data in JSON format
+	*/
+	public static function encodedPrint($data,$setContentType=true){
+		return(\OC_JSON::encodedPrint($data,$setContentType));
+	}
+
+	/**
+	* Check if the user is logged in, send json error msg if not
+	*/
+	public static function checkLoggedIn(){
+		return(\OC_JSON::checkLoggedIn());
+	}
+
+
+
+	/**
+	* Send json success msg
+	*/
+	public static function success($data = array()){
+		return(\OC_JSON::success($data));
+	}
+
+
+	/**
+	* Send json error msg
+	*/
+	public static function error($data = array()){
+		return(\OC_JSON::error($data));
+	}
+
+
+	/**
+	 * set Content-Type header to jsonrequest
+	 */
+	public static function setContentTypeHeader($type='application/json'){
+		return(\OC_JSON::setContentTypeHeader($type));
+	}
+
+
+	/**
+	* Check if the app is enabled, send json error msg if not
+	*/
+	public static function checkAppEnabled($app){
+		return(\OC_JSON::checkAppEnabled($app));
+	}
+
+
+	/**
+	* Check if the user is a admin, send json error msg if not
+	*/
+	public static function checkAdminUser(){
+		return(\OC_JSON::checkAdminUser());
+	}
+
+}
+
+?>
diff --git a/lib/public/response.php b/lib/public/response.php
new file mode 100644
index 0000000000000000000000000000000000000000..2efa74ef840739bd2aa64c132c50f1758fc92ca9
--- /dev/null
+++ b/lib/public/response.php
@@ -0,0 +1,106 @@
+<?php
+/**
+* ownCloud
+*
+* @author Frank Karlitschek
+* @copyright 2010 Frank Karlitschek karlitschek@kde.org
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+* License as published by the Free Software Foundation; either
+* version 3 of the License, or any later version.
+*
+* This library 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 AFFERO GENERAL PUBLIC LICENSE for more details.
+*
+* You should have received a copy of the GNU Affero General Public
+* License along with this library.  If not, see <http://www.gnu.org/licenses/>.
+*
+*/
+
+/**
+ * Public interface of ownCloud for apps to use.
+ * Response Class.
+ *
+ */
+
+// use OCP namespace for all classes that are considered public. 
+// This means that they should be used by apps instead of the internal ownCloud classes
+namespace OCP;
+
+class Response {
+
+
+	/**
+	* @brief Enable response caching by sending correct HTTP headers
+	* @param $cache_time time to cache the response
+	*  >0		cache time in seconds
+	*  0 and <0	enable default browser caching
+	*  null		cache indefinitly
+	*/
+	static public function enableCaching($cache_time = null) {
+		return(\OC_Response::enableCaching($cache_time));
+	}
+
+
+	/**
+	* Checks and set Last-Modified header, when the request matches sends a
+	* 'not modified' response
+	* @param $lastModified time when the reponse was last modified
+	*/
+	static public function setLastModifiedHeader($lastModified) {
+		return(\OC_Response::setLastModifiedHeader($lastModified));
+	}
+
+
+	/**
+	* @brief disable browser caching
+	* @see enableCaching with cache_time = 0
+	*/
+	static public function disableCaching() {
+		return(\OC_Response::disableCaching());
+	}
+
+
+	/**
+	* Checks and set ETag header, when the request matches sends a
+	* 'not modified' response
+	* @param $etag token to use for modification check
+	*/
+	static public function setETagHeader($etag) {
+		return(\OC_Response::setETagHeader($etag));
+	}
+
+
+	/**
+	* @brief Send file as response, checking and setting caching headers
+	* @param $filepath of file to send
+	*/
+	static public function sendFile($filepath) {
+		return(\OC_Response::sendFile($filepath));
+	}
+
+	/**
+	* @brief Set reponse expire time
+	* @param $expires date-time when the response expires
+	*  string for DateInterval from now
+	*  DateTime object when to expire response
+	*/
+	static public function setExpiresHeader($expires) {
+		return(\OC_Response::setExpiresHeader($expires));
+	}
+
+	/**
+	* @brief Send redirect response
+	* @param $location to redirect to
+	*/
+	static public function redirect($location) {
+		return(\OC_Response::redirect($location));
+	}
+
+
+}
+
+?>
diff --git a/lib/public/user.php b/lib/public/user.php
new file mode 100644
index 0000000000000000000000000000000000000000..b39235bb96507829cd256b01b0091282be769c6a
--- /dev/null
+++ b/lib/public/user.php
@@ -0,0 +1,106 @@
+<?php
+/**
+* ownCloud
+*
+* @author Frank Karlitschek
+* @copyright 2010 Frank Karlitschek karlitschek@kde.org
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+* License as published by the Free Software Foundation; either
+* version 3 of the License, or any later version.
+*
+* This library 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 AFFERO GENERAL PUBLIC LICENSE for more details.
+*
+* You should have received a copy of the GNU Affero General Public
+* License along with this library.  If not, see <http://www.gnu.org/licenses/>.
+*
+*/
+
+/**
+ * Public interface of ownCloud for apps to use.
+ * User Class.
+ *
+ */
+
+// use OCP namespace for all classes that are considered public. 
+// This means that they should be used by apps instead of the internal ownCloud classes
+namespace OCP;
+
+class User {
+
+
+	/**
+	 * @brief get the user id of the user currently logged in.
+	 * @return string uid or false
+	 */
+	public static function getUser(){
+		return \OC_USER::getUser();
+	}
+
+
+
+	/**
+	 * @brief Check if the user is logged in
+	 * @returns true/false
+	 *
+	 * Checks if the user is logged in
+	 */
+	public static function isLoggedIn(){
+		return \OC_USER::isLoggedIn();
+	}
+
+	/**
+	 * @brief check if a user exists
+	 * @param string $uid the username
+	 * @return boolean
+	 */
+	public static function userExists($uid){
+		return \OC_USER::userExists($uid);
+	}
+
+	/**
+	 * @brief Loggs the user out including all the session data
+	 * @returns true
+	 *
+	 * Logout, destroys session
+	 */
+	public static function logout(){
+		return \OC_USER::logout();
+	}
+
+	/**
+	 * @brief Check if the password is correct
+	 * @param $uid The username
+	 * @param $password The password
+	 * @returns true/false
+	 *
+	 * Check if the password is correct without logging in the user
+	 */
+	public static function checkPassword( $uid, $password ){
+		return \OC_USER::checkPassword($uid, $password);
+	}
+
+        /**
+        * Check if the user is a admin, redirects to home if not
+        */
+        public static function checkAdminUser(){
+                \OC_Util::checkAdminUser();
+        }
+
+        /**
+        * Check if the user is logged in, redirects to home if not. With
+        * redirect URL parameter to the request URI.
+        */
+        public static function checkLoggedIn(){
+                \OC_Util::checkLoggedIn();
+        }
+
+
+}
+
+
+?>
diff --git a/lib/public/util.php b/lib/public/util.php
new file mode 100644
index 0000000000000000000000000000000000000000..a65b9aa262723fa41baa6518ad4b691313643426
--- /dev/null
+++ b/lib/public/util.php
@@ -0,0 +1,200 @@
+<?php
+/**
+* ownCloud
+*
+* @author Frank Karlitschek
+* @copyright 2010 Frank Karlitschek karlitschek@kde.org
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+* License as published by the Free Software Foundation; either
+* version 3 of the License, or any later version.
+*
+* This library 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 AFFERO GENERAL PUBLIC LICENSE for more details.
+*
+* You should have received a copy of the GNU Affero General Public
+* License along with this library.  If not, see <http://www.gnu.org/licenses/>.
+*
+*/
+
+/**
+ * Public interface of ownCloud for apps to use.
+ * Utility Class.
+ *
+ */
+
+// use OCP namespace for all classes that are considered public. 
+// This means that they should be used by apps instead of the internal ownCloud classes
+namespace OCP;
+
+class Util {
+
+	// consts for Logging
+	const DEBUG=0;
+	const INFO=1;
+	const WARN=2;
+	const ERROR=3;
+	const FATAL=4;
+
+	/**
+	 * get the current installed version of ownCloud
+	 * @return array
+	 */
+	public static function getVersion(){
+		return(\OC_Util::getVersion());
+	}
+
+
+	/**
+	 * send an email 
+	 *
+	 * @param string $toaddress
+	 * @param string $toname
+	 * @param string $subject
+	 * @param string $mailtext
+	 * @param string $fromaddress
+	 * @param string $fromname
+	 * @param bool $html
+	 */
+	public static function sendMail($toaddress,$toname,$subject,$mailtext,$fromaddress,$fromname,$html=0,$altbody='',$ccaddress='',$ccname='',$bcc='') {
+		// call the internal mail class
+		\OC_MAIL::send($toaddress,$toname,$subject,$mailtext,$fromaddress,$fromname,$html=0,$altbody='',$ccaddress='',$ccname='',$bcc='');
+	}
+
+        /**
+	 * write a message in the log
+         *
+	 * @param string $app
+	 * @param string $message
+	 * @param int level
+         */
+        public static function writeLog($app, $message, $level) {
+                // call the internal log class
+                \OC_LOG::write($app, $message, $level);
+        }
+
+
+	/**
+	 * add a css file
+	 *
+	 * @param url  $url
+	 */
+	public static function addStyle( $application, $file = null ){
+		\OC_Util::addStyle($application, $file);
+        }
+
+	/**
+	 * add a javascript file
+	 *
+	 * @param appid  $application
+	 * @param filename  $file
+	 */
+	public static function addScript( $application, $file = null ){
+		\OC_Util::addScript($application, $file);
+        }
+
+	/**
+	 * @brief Add a custom element to the header
+	 * @param string tag tag name of the element
+	 * @param array $attributes array of attributes for the element
+	 * @param string $text the text content for the element
+	 */
+	public static function addHeader( $tag, $attributes, $text=''){
+		\OC_Util::addHeader($tag, $attribute, $text);
+	}
+
+	/**
+	 * formats a timestamp in the "right" way
+	 *
+	 * @param int timestamp $timestamp
+	 * @param bool dateOnly option to ommit time from the result
+	 */
+	public static function formatDate( $timestamp,$dateOnly=false){
+		return(\OC_Util::formatDate($timestamp,$dateOnly));
+	}
+
+
+
+	/**
+	 * @brief Creates an absolute url
+	 * @param $app app
+	 * @param $file file
+	 * @returns the url
+	 *
+	 * Returns a absolute url to the given app and file.
+	 */
+	public static function linkToAbsolute( $app, $file ) {
+		return(\OC_Helper::linkToAbsolute( $app, $file ));
+	}
+
+
+        /**
+         * @brief Creates an url
+         * @param $app app
+         * @param $file file
+         * @returns the url
+         *
+         * Returns a url to the given app and file.
+         */
+        public static function linkTo( $app, $file ){
+		return(\OC_Helper::linkTo( $app, $file ));
+	}
+
+	/**
+	 * @brief Returns the server host
+	 * @returns the server host
+	 *
+	 * Returns the server host, even if the website uses one or more
+	 * reverse proxies
+	 */
+	public static function getServerHost() {
+		return(\OC_Helper::severHost());
+	}
+
+	/**
+	 * @brief Creates path to an image
+	 * @param $app app
+	 * @param $image image name
+	 * @returns the url
+	 *
+	 * Returns the path to the image.
+	 */
+        public static function imagePath( $app, $image ){
+		return(\OC_Helper::imagePath( $app, $image ));
+	}
+
+
+	/**
+	 * @brief Make a human file size
+	 * @param $bytes file size in bytes
+	 * @returns a human readable file size
+	 *
+	 * Makes 2048 to 2 kB.
+	 */
+	public static function humanFileSize( $bytes ){
+		return(\OC_Helper::humanFileSize( $bytes ));
+	}
+
+	/**
+	 * @brief Make a computer file size
+	 * @param $str file size in a fancy format
+	 * @returns a file size in bytes
+	 *
+	 * Makes 2kB to 2048.
+	 *
+	 * Inspired by: http://www.php.net/manual/en/function.filesize.php#92418
+	 */
+	public static function computerFileSize( $str ){
+		return(\OC_Helper::computerFileSize( $str ));
+	}
+
+
+
+
+
+}
+
+?>
diff --git a/lib/setup.php b/lib/setup.php
index 3e46a3dcc9a863e8cebd8f76ce23823b71f8d69c..3dca3c509189999a1f8bc540000c6462f810539b 100644
--- a/lib/setup.php
+++ b/lib/setup.php
@@ -296,15 +296,21 @@ class OC_Setup {
 	 * create .htaccess files for apache hosts
 	 */
 	private static function createHtaccess() {
+		$content = "ErrorDocument 403 ".OC::$WEBROOT."/core/templates/403.php\n";//custom 403 error page
 		$content = "ErrorDocument 404 ".OC::$WEBROOT."/core/templates/404.php\n";//custom 404 error page
 		$content.= "<IfModule mod_php5.c>\n";
 		$content.= "php_value upload_max_filesize 512M\n";//upload limit
 		$content.= "php_value post_max_size 512M\n";
-		$content.= "SetEnv htaccessWorking true\n";
+		$content.= "php_value memory_limit 512M\n";
+		$content.= "<IfModule env_module>\n";
+		$content.= "  SetEnv htaccessWorking true\n";
+		$content.= "</IfModule>\n";
 		$content.= "</IfModule>\n";
 		$content.= "<IfModule mod_rewrite.c>\n";
 		$content.= "RewriteEngine on\n";
 		$content.= "RewriteRule .* - [env=HTTP_AUTHORIZATION:%{HTTP:Authorization},last]\n";
+		$content.= "RewriteRule ^.well-known/carddav /apps/contacts/carddav.php [R]\n";
+		$content.= "RewriteRule ^.well-known/caldav /apps/calendar/caldav.php [R]\n";
 		$content.= "</IfModule>\n";
 		$content.= "Options -Indexes\n";
 		@file_put_contents(OC::$SERVERROOT.'/.htaccess', $content); //supress errors in case we don't have permissions for it
diff --git a/lib/template.php b/lib/template.php
index 5bcf52b93213e95e4ba18f76034ff41305217f2d..57e9c15f5e689a6c79ae0a6ed53f71e38ab6259a 100644
--- a/lib/template.php
+++ b/lib/template.php
@@ -76,7 +76,7 @@ function simple_file_size($bytes) {
 }
 
 function relative_modified_date($timestamp) {
-    $l=new OC_L10N('template');
+    $l=OC_L10N::get('template');
 	$timediff = time() - $timestamp;
 	$diffminutes = round($timediff/60);
 	$diffhours = round($diffminutes/60);
@@ -155,13 +155,13 @@ class OC_Template{
 		$this->renderas = $renderas;
 		$this->application = $app;
 		$this->vars = array();
-		$this->l10n = new OC_L10N($app);
+		$this->l10n = OC_L10N::get($app);
 
 		$this->findTemplate($name);
 	}
 
 	/**
-	 * @brief Returns the formfactor extention for current formfactor
+	 * @brief Returns the formfactor extension for current formfactor
 	 */
 	protected function getFormFactorExtension()
 	{
@@ -323,7 +323,16 @@ class OC_Template{
 	 */
         public function appendIfExist($type, $root, $web, $file) {
                 if (is_file($root.'/'.$file)) {
-                        $this->append( $type, $web.'/'.$file);
+                		$pathes = explode('/', $file);
+                		if($type == 'cssfiles' && $root == OC::$APPSROOT && $pathes[0] == 'apps'){
+                				$app = $pathes[1];
+                				unset($pathes[0]);
+                				unset($pathes[1]);
+                				$path = implode('/', $pathes);
+                				$this->append( $type, OC_Helper::linkTo($app, $path));
+                		}else{
+                				$this->append( $type, $web.'/'.$file);
+                		}
                         return true;
                 }
                 return false;
diff --git a/lib/updater.php b/lib/updater.php
index 196822ac35d42084979e8c5e08741fff7be7a0a8..deb0f05945e88beb3503a228d9a1b59f04c797fb 100644
--- a/lib/updater.php
+++ b/lib/updater.php
@@ -59,9 +59,9 @@ class OC_Updater{
 	public static function ShowUpdatingHint(){
 		$data=OC_Updater::check();
 		if(isset($data['version']) and $data['version']<>'') {
-			$txt='<span style="color:#AA0000; font-weight:bold;">'.$data['versionstring'].' is available. Please click <a href="'.$data['web'].'">here</a> for more information</span>';
+			$txt='<span style="color:#AA0000; font-weight:bold;">'.$data['versionstring'].' is available. Get <a href="'.$data['web'].'">more information</a></span>';
 		}else{
-			$txt='Your ownCloud is up to date';
+			$txt='up to date';
 		}
 		return($txt);
 	}
diff --git a/lib/user.php b/lib/user.php
index 8c27ec30cc200fa7884ab30f9bb4d5dd4d13982e..8b887559df3d5e0ea9786196362740a7133f86f2 100644
--- a/lib/user.php
+++ b/lib/user.php
@@ -215,7 +215,7 @@ class OC_User {
 	}
 
 	/**
-	 * @brief Kick the user
+	 * @brief Logs the current user out and kills all the session data
 	 * @returns true
 	 *
 	 * Logout, destroys session
@@ -244,7 +244,7 @@ class OC_User {
 	}
 
 	/**
-	 * @brief get the user idea of the user currently logged in.
+	 * @brief get the user id of the user currently logged in.
 	 * @return string uid or false
 	 */
 	public static function getUser(){
@@ -279,15 +279,16 @@ class OC_User {
 		OC_Hook::emit( "OC_User", "pre_setPassword", array( "run" => &$run, "uid" => $uid, "password" => $password ));
 
 		if( $run ){
+			$success = false;
 			foreach(self::$_usedBackends as $backend){
 				if($backend->implementsActions(OC_USER_BACKEND_SET_PASSWORD)){
 					if($backend->userExists($uid)){
-						$backend->setPassword($uid,$password);
+						$success |= $backend->setPassword($uid,$password);
 					}
 				}
 			}
 			OC_Hook::emit( "OC_User", "post_setPassword", array( "uid" => $uid, "password" => $password ));
-			return true;
+			return $success;
 		}
 		else{
 			return false;
diff --git a/lib/user/database.php b/lib/user/database.php
index 3eade276dd9e05a97d2e0a8d73e2c4a0652759e4..c1bac1bb0b5f22599ff3e4a61ce12c661b9650a1 100644
--- a/lib/user/database.php
+++ b/lib/user/database.php
@@ -172,7 +172,7 @@ class OC_User_Database extends OC_User_Backend {
 	 * @return boolean
 	 */
 	public function userExists($uid){
-		$query = OC_DB::prepare( "SELECT * FROM `*PREFIX*users` WHERE uid = ?" );
+		$query = OC_DB::prepare( "SELECT * FROM `*PREFIX*users` WHERE uid LIKE ?" );
 		$result = $query->execute( array( $uid ));
 		
 		return $result->numRows() > 0;
diff --git a/lib/util.php b/lib/util.php
index 34f535d2d5cd8eb36bf572ee084403d60560be9b..d22d8710867379649633a7f4f3a1969a0ca46848 100644
--- a/lib/util.php
+++ b/lib/util.php
@@ -20,12 +20,20 @@ class OC_Util {
 		$CONFIG_DATADIRECTORY_ROOT = OC_Config::getValue( "datadirectory", OC::$SERVERROOT."/data" );
 		$CONFIG_BACKUPDIRECTORY = OC_Config::getValue( "backupdirectory", OC::$SERVERROOT."/backup" );
 
-		// Create root dir
+		// Check if config folder is writable.
+		if(!is_writable(OC::$SERVERROOT."/config/")) {
+			$tmpl = new OC_Template( '', 'error', 'guest' );
+			$tmpl->assign('errors',array(1=>array('error'=>"Can't write into config directory 'config'",'hint'=>"You can usually fix this by giving the webserver user write access to the config directory in owncloud")));
+			$tmpl->printPage();
+			exit;
+		}
+		
+		// Create root dir.
 		if(!is_dir($CONFIG_DATADIRECTORY_ROOT)){
 			$success=@mkdir($CONFIG_DATADIRECTORY_ROOT);
-                        if(!$success) {
+            if(!$success) {
 				$tmpl = new OC_Template( '', 'error', 'guest' );
-				$tmpl->assign('errors',array(1=>array('error'=>"Can't create data directory (".$CONFIG_DATADIRECTORY_ROOT.")",'hint'=>"You can usually fix this by giving the webserver write access to the ownCloud directory '".OC::$SERVERROOT."' ")));
+				$tmpl->assign('errors',array(1=>array('error'=>"Can't create data directory (".$CONFIG_DATADIRECTORY_ROOT.")",'hint'=>"You can usually fix this by giving the webserver write access to the ownCloud directory '".OC::$SERVERROOT."' (in a terminal, use the command 'chown -R www-data:www-data /path/to/your/owncloud/install/data' ")));
 				$tmpl->printPage();
 				exit;
   			}
@@ -88,7 +96,8 @@ class OC_Util {
 	/**
 	 * add a javascript file
 	 *
-	 * @param url  $url
+	 * @param appid  $application
+	 * @param filename  $file
 	 */
 	public static function addScript( $application, $file = null ){
 		if( is_null( $file )){
@@ -105,7 +114,8 @@ class OC_Util {
 	/**
 	 * add a css file
 	 *
-	 * @param url  $url
+	 * @param appid  $application
+	 * @param filename  $file
 	 */
 	public static function addStyle( $application, $file = null ){
 		if( is_null( $file )){
@@ -129,23 +139,23 @@ class OC_Util {
 		self::$headers[]=array('tag'=>$tag,'attributes'=>$attributes,'text'=>$text);
 	}
 
-       /**
-         * formats a timestamp in the "right" way
-         *
-         * @param int timestamp $timestamp
-         * @param bool dateOnly option to ommit time from the result
-         */
-        public static function formatDate( $timestamp,$dateOnly=false){
-			if(isset($_SESSION['timezone'])){//adjust to clients timezone if we know it
-				$systemTimeZone = intval(date('O'));
-				$systemTimeZone=(round($systemTimeZone/100,0)*60)+($systemTimeZone%100);
-				$clientTimeZone=$_SESSION['timezone']*60;
-				$offset=$clientTimeZone-$systemTimeZone;
-				$timestamp=$timestamp+$offset*60;
-			}
-			$timeformat=$dateOnly?'F j, Y':'F j, Y, H:i';
-			return date($timeformat,$timestamp);
-        }
+   /**
+     * formats a timestamp in the "right" way
+     *
+     * @param int timestamp $timestamp
+     * @param bool dateOnly option to ommit time from the result
+     */
+    public static function formatDate( $timestamp,$dateOnly=false){
+		if(isset($_SESSION['timezone'])){//adjust to clients timezone if we know it
+			$systemTimeZone = intval(date('O'));
+			$systemTimeZone=(round($systemTimeZone/100,0)*60)+($systemTimeZone%100);
+			$clientTimeZone=$_SESSION['timezone']*60;
+			$offset=$clientTimeZone-$systemTimeZone;
+			$timestamp=$timestamp+$offset*60;
+		}
+		$timeformat=$dateOnly?'F j, Y':'F j, Y, H:i';
+		return date($timeformat,$timestamp);
+    }
 
 	/**
 	 * Shows a pagenavi widget where you can jump to different pages.
@@ -237,6 +247,15 @@ class OC_Util {
 		if(!function_exists('ctype_digit')){
 			$errors[]=array('error'=>'PHP module ctype is not installed.<br/>','hint'=>'Please ask your server administrator to install the module.');
 		}
+		if(!function_exists('json_encode')){
+			$errors[]=array('error'=>'PHP module JSON is not installed.<br/>','hint'=>'Please ask your server administrator to install the module.');
+		}
+		if(!function_exists('imagepng')){
+			$errors[]=array('error'=>'PHP module GD is not installed.<br/>','hint'=>'Please ask your server administrator to install the module.');
+		}
+		if(floatval(phpversion())<5.3){
+			$errors[]=array('error'=>'PHP 5.3 is required.<br/>','hint'=>'Please ask your server administrator to update PHP to version 5.3 or higher. PHP 5.2 is no longer supported by ownCloud and the PHP community.');
+		}
 
 		return $errors;
 	}
@@ -247,6 +266,9 @@ class OC_Util {
 		} else {
 			$parameters["username"] = '';
 		}
+		$sectoken=rand(1000000,9999999);
+		$_SESSION['sectoken']=$sectoken;
+		$parameters["sectoken"] = $sectoken;
 		OC_Template::printGuestPage("", "login", $parameters);
 	}
 
@@ -292,7 +314,7 @@ class OC_Util {
 		if(isset($_REQUEST['redirect_url'])) {
 			header( 'Location: '.$_REQUEST['redirect_url']);
 		} else {
-			header( 'Location: '.OC::$WEBROOT.'/'.OC_Appconfig::getValue('core', 'defaultpage', 'files/index.php'));
+			header( 'Location: '.OC::$WEBROOT.'/'.OC_Appconfig::getValue('core', 'defaultpage', '?app=files'));
 		}
 		exit();
 	}
diff --git a/lib/vobject.php b/lib/vobject.php
index e3479fc6d3687a3a9c8f09416e37b8c2d06d737b..ec80e1d605ae2d163c06b2a78fb1068351378db8 100644
--- a/lib/vobject.php
+++ b/lib/vobject.php
@@ -41,7 +41,7 @@ class OC_VObject{
 	 */
 	public static function parse($data){
 		try {
-			Sabre_VObject_Reader::$elementMap['LAST-MODIFIED'] = 'Sabre_VObject_Element_DateTime';
+			Sabre_VObject_Property::$classMap['LAST-MODIFIED'] = 'Sabre_VObject_Property_DateTime';
 			$vobject = Sabre_VObject_Reader::read($data);
 			if ($vobject instanceof Sabre_VObject_Component){
 				$vobject = new OC_VObject($vobject);
@@ -150,12 +150,12 @@ class OC_VObject{
 	 * @param int $dateType
 	 * @return void
 	 */
-	public function setDateTime($name, $datetime, $dateType=Sabre_VObject_Element_DateTime::LOCALTZ){
+	public function setDateTime($name, $datetime, $dateType=Sabre_VObject_Property_DateTime::LOCALTZ){
 		if ($datetime == 'now'){
 			$datetime = new DateTime();
 		}
 		if ($datetime instanceof DateTime){
-			$datetime_element = new Sabre_VObject_Element_DateTime($name);
+			$datetime_element = new Sabre_VObject_Property_DateTime($name);
 			$datetime_element->setDateTime($datetime, $dateType);
 			$this->vobject->__set($name, $datetime_element);
 		}else{
diff --git a/remote/.gitignore b/remote/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..c96a04f008ee21e260b28f7701595ed59e2839e3
--- /dev/null
+++ b/remote/.gitignore
@@ -0,0 +1,2 @@
+*
+!.gitignore
\ No newline at end of file
diff --git a/search/css/results.css b/search/css/results.css
index 440e68ee48f74e02bdb5c62c73a9a5275dabd30f..40d5563e89e61491b9e8afb779bbb26608998dc3 100644
--- a/search/css/results.css
+++ b/search/css/results.css
@@ -1,3 +1,7 @@
+/* Copyright (c) 2011, Jan-Christoph Borchardt, http://jancborchardt.net
+ This file is licensed under the Affero General Public License version 3 or later.
+ See the COPYING-README file. */
+
 #searchresults { list-style:none; position:fixed; top:3.5em; right:0; z-index:75; background-color:#fff; overflow:hidden; text-overflow:ellipsis; max-height:80%; width:26.5em; padding-bottom:1em; -moz-box-shadow:0 0 10px #000; -webkit-box-shadow:0 0 10px #000; box-shadow:0 0 10px #000; -moz-border-radius-bottomleft:1em; -webkit-border-bottom-left-radius:1em; border-bottom-left-radius:1em; }
 #searchresults li.resultHeader { font-size:1.2em; font-weight:bold; border-bottom:solid 1px #CCC; padding:.2em; background-color:#eee; }
 #searchresults li.result { margin-left:2em; }
diff --git a/settings/admin.php b/settings/admin.php
index 9ee79002b5e772fdf04e0afa0ae0d50c86266315..a997bad4e3c8553987a73f0ec87ea4194d057dc5 100644
--- a/settings/admin.php
+++ b/settings/admin.php
@@ -10,11 +10,20 @@ OC_Util::checkAdminUser();
 
 OC_Util::addStyle( "settings", "settings" );
 OC_Util::addScript( "settings", "admin" );
+OC_Util::addScript( "settings", "log" );
 OC_App::setActiveNavigationEntry( "admin" );
 
 $tmpl = new OC_Template( 'settings', 'admin', 'user');
 $forms=OC_App::getForms('admin');
+
+$entries=OC_Log_Owncloud::getEntries(3);
+function compareEntries($a,$b){
+	return $b->time - $a->time;
+}
+usort($entries, 'compareEntries');
+
 $tmpl->assign('loglevel',OC_Config::getValue( "loglevel", 2 ));
+$tmpl->assign('entries',$entries);
 $tmpl->assign('forms',array());
 foreach($forms as $form){
 	$tmpl->append('forms',$form);
diff --git a/settings/ajax/disableapp.php b/settings/ajax/disableapp.php
index 06dd3c2ac6bfd5dc9fddc8959a10b8fd41c234b1..53e9be379e19eae172eff3b15215a60425060c66 100644
--- a/settings/ajax/disableapp.php
+++ b/settings/ajax/disableapp.php
@@ -6,4 +6,4 @@ OC_JSON::setContentTypeHeader();
 
 OC_App::disable($_POST['appid']);
 
-?>
+OC_JSON::success();
diff --git a/settings/ajax/enableapp.php b/settings/ajax/enableapp.php
index 639df2aecc0fad9505acdcdc12d1691d998b863a..cb116ebe4e84bf1a3e88431d684f12ec03ad8d55 100644
--- a/settings/ajax/enableapp.php
+++ b/settings/ajax/enableapp.php
@@ -5,6 +5,8 @@ require_once('../../lib/base.php');
 OC_JSON::checkAdminUser();
 OC_JSON::setContentTypeHeader();
 
-OC_App::enable($_POST['appid']);
-
-?>
+if(OC_App::enable($_POST['appid'])){
+	OC_JSON::success();
+}else{
+	OC_JSON::error();
+}
diff --git a/settings/ajax/lostpassword.php b/settings/ajax/lostpassword.php
index a2dfc0332065fd924076725e995f52bc0c194c9b..5874dec9647d67323123d941dc5bbfe9002d71d3 100644
--- a/settings/ajax/lostpassword.php
+++ b/settings/ajax/lostpassword.php
@@ -5,7 +5,7 @@ require_once('../../lib/base.php');
 
 OC_JSON::checkLoggedIn();
 
-$l=new OC_L10N('core');
+$l=OC_L10N::get('core');
 
 // Get data
 if( isset( $_POST['email'] ) ){
diff --git a/settings/ajax/openid.php b/settings/ajax/openid.php
index c4b119b448dd1bdf9d9100d5e815ad97723b4cbc..58d071255c205c0c10224e23b836399460bf654b 100644
--- a/settings/ajax/openid.php
+++ b/settings/ajax/openid.php
@@ -3,7 +3,7 @@
 // Init owncloud
 require_once('../../lib/base.php');
 
-$l=new OC_L10N('settings');
+$l=OC_L10N::get('settings');
 
 OC_JSON::checkLoggedIn();
 OC_JSON::checkAppEnabled('user_openid');
diff --git a/settings/ajax/setlanguage.php b/settings/ajax/setlanguage.php
index dc1128de2e53ce975b40df15495030bff1c219ef..e3b00c3bc8073b980949fc8dafb925755bd54d34 100644
--- a/settings/ajax/setlanguage.php
+++ b/settings/ajax/setlanguage.php
@@ -3,15 +3,21 @@
 // Init owncloud
 require_once('../../lib/base.php');
 
-$l=new OC_L10N('settings');
+$l=OC_L10N::get('settings');
 
 OC_JSON::checkLoggedIn();
 
+
 // Get data
 if( isset( $_POST['lang'] ) ){
+	$languageCodes=OC_L10N::findAvailableLanguages();
 	$lang=$_POST['lang'];
-	OC_Preferences::setValue( OC_User::getUser(), 'core', 'lang', $lang );
-	OC_JSON::success(array("data" => array( "message" => $l->t("Language changed") )));
+	if(array_search($lang,$languageCodes) or $lang=='en'){
+		OC_Preferences::setValue( OC_User::getUser(), 'core', 'lang', $lang );
+		OC_JSON::success(array("data" => array( "message" => $l->t("Language changed") )));
+	}else{
+		OC_JSON::error(array("data" => array( "message" => $l->t("Invalid request") )));
+	}
 }else{
 	OC_JSON::error(array("data" => array( "message" => $l->t("Invalid request") )));
 }
diff --git a/settings/apps.php b/settings/apps.php
index 0889b0c45ed720a9b3953f48169f54ec35d21fe0..eef01641f321d58bdefdbfd4dbc426433bba8745 100644
--- a/settings/apps.php
+++ b/settings/apps.php
@@ -32,13 +32,16 @@ OC_App::setActiveNavigationEntry( "core_apps" );
 $registeredApps=OC_App::getAllApps();
 $apps=array();
 
-$blacklist=array('files_imageviewer','files_textviewer');//we dont want to show configuration for these
+$blacklist=array('files','files_imageviewer','files_textviewer');//we dont want to show configuration for these
 
 foreach($registeredApps as $app){
 	if(array_search($app,$blacklist)===false){
 		$info=OC_App::getAppInfo($app);
 		$active=(OC_Appconfig::getValue($app,'enabled','no')=='yes')?true:false;
 		$info['active']=$active;
+		$info['internal']=true;
+		$info['internallabel']='Internal App';
+		$info['preview']='trans.png';
 		$apps[]=$info;
 	}
 }
@@ -64,6 +67,7 @@ usort($apps, 'app_sort');
 		}
 
 		if(!$local) {
+ 			if($app['preview']=='') $pre='trans.png'; else $pre=$app['preview'];
 	 		$apps[]=array(
  				'name'=>$app['name'],
  				'id'=>$app['id'],
@@ -71,6 +75,9 @@ usort($apps, 'app_sort');
  				'description'=>$app['description'],
  				'author'=>$app['personid'],
  				'license'=>$app['license'],
+ 				'preview'=>$pre,
+ 				'internal'=>false,
+ 				'internallabel'=>'3rd Party App',
  			);
 		}
  	}
diff --git a/settings/css/settings.css b/settings/css/settings.css
index 42576953d042c382888f00914af93118a25588d7..36d9b8d26f9e77afcbab15cdfae19bdbfd3a41a2 100644
--- a/settings/css/settings.css
+++ b/settings/css/settings.css
@@ -1,3 +1,7 @@
+/* Copyright (c) 2011, Jan-Christoph Borchardt, http://jancborchardt.net
+ This file is licensed under the Affero General Public License version 3 or later.
+ See the COPYING-README file. */
+
 select#languageinput, select#timezone { width:15em; }
 input#openid, input#webdav { width:20em; }
 
@@ -40,7 +44,8 @@ select.quota.active { background: #fff; }
 /* APPS */
 li { color:#888; }
 li.active { color:#000; }
+small.externalapp { color:#FFF; background-color:#BBB; font-weight:bold; font-size:6pt; padding:4px; border-radius: 4px;}
 span.version { margin-left:3em; color:#ddd; }
 
 /* LOF */
-#log { white-space:normal; }
\ No newline at end of file
+#log { white-space:normal; }
diff --git a/settings/img/log.svg b/settings/img/log.svg
old mode 100755
new mode 100644
diff --git a/settings/js/admin.js b/settings/js/admin.js
index a3585f7e1c24113e1da93977f5172d6066702b0d..4f295ab6f5d3fbf4e2e054f1d3ca7ed2d9c4b09b 100644
--- a/settings/js/admin.js
+++ b/settings/js/admin.js
@@ -1,5 +1,7 @@
 $(document).ready(function(){
 	$('#loglevel').change(function(){
-		$.post(OC.filePath('settings','ajax','setloglevel.php'), { level: $(this).val() } );
+		$.post(OC.filePath('settings','ajax','setloglevel.php'), { level: $(this).val() },function(){
+			OC.Log.reload();
+		} );
 	})
 });
\ No newline at end of file
diff --git a/settings/js/apps.js b/settings/js/apps.js
index e2f882c6fec7f1760861812888dacb207bbea2e7..df5300911aa388ffc404165644d0fe196f44f6c4 100644
--- a/settings/js/apps.js
+++ b/settings/js/apps.js
@@ -13,8 +13,11 @@ $(document).ready(function(){
 		var app=$(this).data('app');
 		$('#rightcontent p').show();
 		$('#rightcontent span.name').text(app.name);
+		$('#rightcontent small.externalapp').text(app.internallabel);
 		$('#rightcontent span.version').text(app.version);
 		$('#rightcontent p.description').text(app.description);
+		$('#rightcontent img.preview').attr('src',app.preview);
+		$('#rightcontent small.externalapp').attr('style','visibility:visible');
 		$('#rightcontent span.author').text(app.author);
 		$('#rightcontent span.licence').text(app.licence);
 		
@@ -28,10 +31,18 @@ $(document).ready(function(){
 		var active=$(this).data('active');
 		if(app){
 			if(active){
-				$.post(OC.filePath('settings','ajax','disableapp.php'),{appid:app});
+				$.post(OC.filePath('settings','ajax','disableapp.php'),{appid:app},function(result){
+					if(!result || result.status!='success'){
+						OC.dialogs.alert('Error','Error while disabling app');
+					}
+				},'json');
 				$('#leftcontent li[data-id="'+app+'"]').removeClass('active');
 			}else{
-				$.post(OC.filePath('settings','ajax','enableapp.php'),{appid:app});
+				$.post(OC.filePath('settings','ajax','enableapp.php'),{appid:app},function(result){
+					if(!result || result.status!='success'){
+						OC.dialogs.alert('Error','Error while enabling app');
+					}
+				},'json');
 				$('#leftcontent li[data-id="'+app+'"]').addClass('active');
 			}
 			active=!active;
diff --git a/settings/js/log.js b/settings/js/log.js
index ae83f0a6283ab2ee569075ec4c44a2c0ce4367cf..6063c7d9a9fe8cb41834e832a1f8416b31c6f3ae 100644
--- a/settings/js/log.js
+++ b/settings/js/log.js
@@ -5,15 +5,26 @@
  */
 
 OC.Log={
+	reload:function(count){
+		if(!count){
+			count=OC.Log.loaded;
+		}
+		OC.Log.loaded=0;
+		$('#log tbody').empty();
+		OC.Log.getMore(count);
+	},
 	levels:['Debug','Info','Warning','Error','Fatal'],
-	loaded:50,//are initially loaded
-	getMore:function(){
-		$.get(OC.filePath('settings','ajax','getlog.php'),{offset:OC.Log.loaded},function(result){
+	loaded:3,//are initially loaded
+	getMore:function(count){
+		if(!count){
+			count=10;
+		}
+		$.get(OC.filePath('settings','ajax','getlog.php'),{offset:OC.Log.loaded,count:count},function(result){
 			if(result.status=='success'){
 				OC.Log.addEntries(result.data);
+				$('html, body').animate({scrollTop: $(document).height()}, 800);
 			}
 		});
-		OC.Log.loaded+=50;
 	},
 	addEntries:function(entries){
 		for(var i=0;i<entries.length;i++){
@@ -36,6 +47,7 @@ OC.Log={
 			row.append(timeTd);
 			$('#log').append(row);
 		}
+		OC.Log.loaded += entries.length;
 	}
 }
 
diff --git a/settings/js/personal.js b/settings/js/personal.js
index 8108da433c80baefdfbe2a7f3fb9a480ac053ab0..77d103c53b676033b0bd5cf18b92444b9b738d19 100644
--- a/settings/js/personal.js
+++ b/settings/js/personal.js
@@ -33,7 +33,11 @@ $(document).ready(function(){
 	});
 
 	$('#lostpassword #email').blur(function(event){
+		if ($(this).val() == this.defaultValue){
+			return;
+		}
 		event.preventDefault();
+		this.defaultValue = $(this).val();
 		OC.msg.startSaving('#lostpassword .msg');
 		var post = $( "#lostpassword" ).serialize();
 		$.post( 'ajax/lostpassword.php', post, function(data){
diff --git a/settings/personal.php b/settings/personal.php
old mode 100755
new mode 100644
index 07030109de7a5e2388a70d2e56c217a4bc2bdf49..41499657ac781fd65c23ce1402174e7125f5ef1c
--- a/settings/personal.php
+++ b/settings/personal.php
@@ -35,7 +35,7 @@ array_unshift($languageCodes,$lang);
 $languageNames=include 'languageCodes.php';
 $languages=array();
 foreach($languageCodes as $lang){
-	$l=new OC_L10N('settings',$lang);
+	$l=OC_L10N::get('settings',$lang);
 	if(substr($l->t('__language_name__'),0,1)!='_'){//first check if the language name is in the translation file
 		$languages[]=array('code'=>$lang,'name'=>$l->t('__language_name__'));
 	}elseif(isset($languageNames[$lang])){
diff --git a/settings/templates/admin.php b/settings/templates/admin.php
index e3fd60fefce44e32d305c13010857a1bfcb556df..38c6042c82ae68fa5022b0c6d75d3a4a452a7241 100644
--- a/settings/templates/admin.php
+++ b/settings/templates/admin.php
@@ -10,8 +10,8 @@ $levels=array('Debug','Info','Warning','Error','Fatal');
 	echo $form;
 };?>
 <fieldset class="personalblock">
-	<legend><strong><?php echo $l->t('Log level');?></strong></legend>
-	<select name='loglevel' id='loglevel'>
+	<legend><strong><?php echo $l->t('Log');?></strong></legend>
+	Log level: <select name='loglevel' id='loglevel'>
 		<option value='<?php echo $_['loglevel']?>'><?php echo $levels[$_['loglevel']]?></option>
 		<?php for($i=0;$i<5;$i++):
 			if($i!=$_['loglevel']):?>
@@ -19,4 +19,23 @@ $levels=array('Debug','Info','Warning','Error','Fatal');
 			<?php endif;
 		endfor;?>
 	</select>
+	<table id='log'>
+	<?php foreach($_['entries'] as $entry):?>
+		<tr>
+			<td>
+				<?php echo $levels[$entry->level];?>
+			</td>
+			<td>
+				<?php echo $entry->app;?>
+			</td>
+			<td>
+				<?php echo $entry->message;?>
+			</td>
+			<td>
+				<?php echo OC_Util::formatDate($entry->time);?>
+			</td>
+		</tr>
+	<?php endforeach;?>
+</table>
+<input id='moreLog' type='button' value='<?php echo $l->t('More');?>...'></input>
 </fieldset>
diff --git a/settings/templates/apps.php b/settings/templates/apps.php
index 1e49b4c89288425000c7df4970a75247f30ca1ac..d25ca1bc7fb881f291288643a46b7df9a194f52a 100644
--- a/settings/templates/apps.php
+++ b/settings/templates/apps.php
@@ -5,7 +5,7 @@
  */?>
 
 <div id="controls">
-	<a class="button" target="_blank" href="http://owncloud.org/dev/writing-apps/"><?php echo $l->t('Add your application');?></a>
+	<a class="button" target="_blank" href="http://owncloud.org/dev/writing-apps/"><?php echo $l->t('Add your App');?></a>
 </div>
 <ul id="leftcontent">
 	<?php foreach($_['apps'] as $app):?>
@@ -14,12 +14,14 @@
 		<span class="hidden">
 			<?php OC_JSON::encodedPrint($app,false) ?>
 		</span>
+		<?php  if(!$app['internal']) echo '<small class="externalapp">3rd party</small>' ?>
 	</li>
 	<?php endforeach;?>
 </ul>
 <div id="rightcontent">
-	<h3><strong><span class="name"><?php echo $l->t('Select an App');?></span></strong><span class="version"></span></h3>
+	<h3><strong><span class="name"><?php echo $l->t('Select an App');?></span></strong><span class="version"></span><small class="externalapp" style="visibility:hidden;"></small></h3>
 	<p class="description"></p>
+	<img src="" class="preview" />
 	<p class="hidden"><span class="licence"></span><?php echo $l->t('-licensed');?> <?php echo $l->t('by');?> <span class="author"></span></p>
 	<input class="enable hidden" type="submit" />
 </div>
diff --git a/settings/templates/help.php b/settings/templates/help.php
index 754bf8b6376d84357acd7e4691368cb76bbe4222..f9eb8615972ea4d4c28bf8b20d7665945fd80900 100644
--- a/settings/templates/help.php
+++ b/settings/templates/help.php
@@ -5,6 +5,8 @@
  */?>
 
 <div id="controls">
+	<a class="button newquestion" href="http://owncloud.org/support" target="_blank"><?php echo $l->t( 'Documentation' ); ?></a>
+	<a class="button newquestion" href="http://owncloud.org/support/big-files" target="_blank"><?php echo $l->t( 'Managing Big Files' ); ?></a>
 	<a class="button newquestion" href="http://apps.owncloud.com/knowledgebase/editquestion.php?action=new" target="_blank"><?php echo $l->t( 'Ask a question' ); ?></a>
 	<?php
 		$url=OC_Helper::linkTo( "settings", "help.php" ).'?page=';
diff --git a/settings/templates/log.php b/settings/templates/log.php
deleted file mode 100644
index da5defc320e8c3c6b1f439fcba38742bc5ed32c1..0000000000000000000000000000000000000000
--- a/settings/templates/log.php
+++ /dev/null
@@ -1,30 +0,0 @@
-<?php /**
- * Copyright (c) 2011, Robin Appelman <icewind1991@gmail.com>
- * This file is licensed under the Affero General Public License version 3 or later.
- * See the COPYING-README file.
- */
-$levels=array('Debug','Info','Warning','Error','Fatal');
-?>
-
-<div id="controls">
-	
-</div>
-<table id='log'>
-	<?php foreach($_['entries'] as $entry):?>
-		<tr>
-			<td>
-				<?php echo $levels[$entry->level];?>
-			</td>
-			<td>
-				<?php echo $entry->app;?>
-			</td>
-			<td>
-				<?php echo $entry->message;?>
-			</td>
-			<td>
-				<?php echo $l->l('datetime',$entry->time);?>
-			</td>
-		</tr>
-	<?php endforeach;?>
-</table>
-<input id='moreLog' type='button' value='<?php echo $l->t('More');?>...'></input>
diff --git a/settings/templates/personal.php b/settings/templates/personal.php
index d40da7eb773fca58d2bc870619f91a7856f73296..d460b33202e3467f407bd789ce127f67c64e9ae6 100644
--- a/settings/templates/personal.php
+++ b/settings/templates/personal.php
@@ -8,6 +8,12 @@
 	<p id="quotatext"><?php echo $l->t('You use');?> <strong><?php echo $_['usage'];?></strong> <?php echo $l->t('of the available');?> <strong><?php echo $_['total_space'];?></strong></p>
 </div></div>
 
+<div class="personalblock">
+	<?php echo $l->t('Desktop and Mobile Syncing Clients');?>
+	<a class="button" href="http://owncloud.org/sync-clients/" target="_blank"><?php echo $l->t('Download');?></a>
+</div>
+
+
 <form id="passwordform">
 	<fieldset class="personalblock">
 		<div id="passwordchanged"><?php echo $l->t('Your password got changed');?></div>
@@ -41,7 +47,7 @@
 
 <p class="personalblock">
 	<strong>WebDAV</strong>
-	<?php echo OC_Helper::linkToAbsolute('files', 'webdav.php'); ?><br />
+	<code><?php echo OC_Helper::linkToAbsolute('files', 'webdav.php'); ?></code><br />
 	<em><?php echo $l->t('use this address to connect to your ownCloud in your file manager');?></em>
 </p>
 
@@ -50,10 +56,8 @@
 };?>
 
 <p class="personalblock">
-	<strong>ownCloud</strong> <?php echo(OC_Util::getVersionString()); ?> <?php echo(OC_Util::getEditionString()); ?><br />
-	developed by the <a href="http://ownCloud.org/credits" target="_blank">ownCloud community</a><br />
-	<?php echo(OC_Updater::ShowUpdatingHint());     ?><br />
-	<a href="http://gitorious.org/owncloud" target="_blank">source code</a> licensed freely under <a href="http://www.gnu.org/licenses/agpl-3.0.html" target="_blank">AGPL</a>
+	<strong>ownCloud</strong> <?php echo(OC_Util::getVersionString()); ?> <?php echo(OC_Util::getEditionString()); ?> (<?php echo(OC_Updater::ShowUpdatingHint()); ?>)<br />
+	Developed by the <a href="http://ownCloud.org/contact" target="_blank">ownCloud community</a>, the <a href="http://gitorious.org/owncloud" target="_blank">source code</a> is freely licensed under the <a href="http://www.gnu.org/licenses/agpl-3.0.html" target="_blank"><abbr title="Affero General Public License">AGPL</abbr></a>.
 </p>
 
 
diff --git a/settings/trans.png b/settings/trans.png
new file mode 100644
index 0000000000000000000000000000000000000000..e6920168bf2dbb9405040360e42095922b9e124a
Binary files /dev/null and b/settings/trans.png differ
diff --git a/tests/index.php b/tests/index.php
index a6f678b3bc2ca416d6efa8e19abc8c907221975f..6dec1b050fb35518dc2577bb685f9819ef54c6c1 100644
--- a/tests/index.php
+++ b/tests/index.php
@@ -30,7 +30,7 @@ require_once 'simpletest/default_reporter.php';
 loadTests(dirname(__FILE__));
 
 //load app test cases
-$apps=OC_Appconfig::getApps();
+$apps=OC_App::getEnabledApps();
 foreach($apps as $app){
 	if(is_dir(OC::$SERVERROOT.'/apps/'.$app.'/tests')){
 		loadTests(OC::$SERVERROOT.'/apps/'.$app.'/tests');
diff --git a/apps/files_archive/tests/archive.php b/tests/lib/archive.php
old mode 100644
new mode 100755
similarity index 97%
rename from apps/files_archive/tests/archive.php
rename to tests/lib/archive.php
index 9e99466a521c334dfb5890bbb0739852a017a4fd..1779127c932bb909bd4e794931105da824c4cdd2
--- a/apps/files_archive/tests/archive.php
+++ b/tests/lib/archive.php
@@ -55,7 +55,7 @@ abstract class Test_Archive extends UnitTestCase {
 		$textFile=$dir.'/lorem.txt';
 		$this->assertEqual(file_get_contents($textFile),$this->instance->getFile('lorem.txt'));
 		
-		$tmpFile=OC_Helper::tmpFile('.txt');
+		$tmpFile=OCP\Files::tmpFile('.txt');
 		$this->instance->extractFile('lorem.txt',$tmpFile);
 		$this->assertEqual(file_get_contents($textFile),file_get_contents($tmpFile));
 	}
@@ -89,7 +89,7 @@ abstract class Test_Archive extends UnitTestCase {
 		$this->instance=$this->getNew();
 		$fh=$this->instance->getStream('lorem.txt','w');
 		$source=fopen($dir.'/lorem.txt','r');
-		OC_Helper::streamCopy($source,$fh);
+		OCP\Files::streamCopy($source,$fh);
 		fclose($source);
 		fclose($fh);
 		$this->assertTrue($this->instance->fileExists('lorem.txt'));
@@ -109,13 +109,13 @@ abstract class Test_Archive extends UnitTestCase {
 	public function testExtract(){
 		$dir=OC::$SERVERROOT.'/apps/files_archive/tests/data';
 		$this->instance=$this->getExisting();
-		$tmpDir=OC_Helper::tmpFolder();
+		$tmpDir=OCP\Files::tmpFolder();
 		$this->instance->extract($tmpDir);
 		$this->assertEqual(true,file_exists($tmpDir.'lorem.txt'));
 		$this->assertEqual(true,file_exists($tmpDir.'dir/lorem.txt'));
 		$this->assertEqual(true,file_exists($tmpDir.'logo-wide.png'));
 		$this->assertEqual(file_get_contents($dir.'/lorem.txt'),file_get_contents($tmpDir.'lorem.txt'));
-		OC_Helper::rmdirr($tmpDir);
+		OCP\Files::rmdirr($tmpDir);
 	}
 	public function testMoveRemove(){
 		$dir=OC::$SERVERROOT.'/apps/files_archive/tests/data';
diff --git a/tests/lib/archive/tar.php b/tests/lib/archive/tar.php
new file mode 100755
index 0000000000000000000000000000000000000000..c138a51a6518829b38a934757c8107ada73f089b
--- /dev/null
+++ b/tests/lib/archive/tar.php
@@ -0,0 +1,24 @@
+<?php
+/**
+ * Copyright (c) 2012 Robin Appelman <icewind@owncloud.com>
+ * This file is licensed under the Affero General Public License version 3 or
+ * later.
+ * See the COPYING-README file.
+ */
+
+require_once('archive.php');
+
+if(is_dir(OC::$SERVERROOT.'/apps/files_archive/tests/data')){
+	class Test_Archive_TAR extends Test_Archive{
+		protected function getExisting(){
+			$dir=OC::$SERVERROOT.'/apps/files_archive/tests/data';
+			return new OC_Archive_TAR($dir.'/data.tar.gz');
+		}
+
+		protected function getNew(){
+			return new OC_Archive_TAR(OCP\Files::tmpFile('.tar.gz'));
+		}
+	}
+}else{
+	abstract class Test_Archive_TAR extends Test_Archive{}
+}
diff --git a/tests/lib/archive/zip.php b/tests/lib/archive/zip.php
new file mode 100755
index 0000000000000000000000000000000000000000..615c9e3c7e23cb8ce184f6c3085eff0bc0093334
--- /dev/null
+++ b/tests/lib/archive/zip.php
@@ -0,0 +1,24 @@
+<?php
+/**
+ * Copyright (c) 2012 Robin Appelman <icewind@owncloud.com>
+ * This file is licensed under the Affero General Public License version 3 or
+ * later.
+ * See the COPYING-README file.
+ */
+
+require_once('archive.php');
+
+if(is_dir(OC::$SERVERROOT.'/apps/files_archive/tests/data')){
+	class Test_Archive_ZIP extends Test_Archive{
+		protected function getExisting(){
+			$dir=OC::$SERVERROOT.'/apps/files_archive/tests/data';
+			return new OC_Archive_ZIP($dir.'/data.zip');
+		}
+
+		protected function getNew(){
+			return new OC_Archive_ZIP(OCP\Files::tmpFile('.zip'));
+		}
+	}
+}else{
+	abstract class Test_Archive_ZIP extends Test_Archive{}
+}
diff --git a/tests/lib/filestorage.php b/tests/lib/filestorage.php
index 4858234a2d863d247f6f3b0b65661abd64f464b2..b58e28cefde7654dedf83fac9d48419c414708b3 100644
--- a/tests/lib/filestorage.php
+++ b/tests/lib/filestorage.php
@@ -68,6 +68,15 @@ abstract class Test_FileStorage extends UnitTestCase {
 		$this->assertFalse($this->instance->file_exists('/folder'));
 		
 		$this->assertFalse($this->instance->rmdir('/folder'));//cant remove non existing folders
+
+		$dh=$this->instance->opendir('/');
+		$content=array();
+		while($file=readdir($dh)){
+			if($file!='.' and $file!='..'){
+				$content[]=$file;
+			}
+		}
+		$this->assertEqual(array(),$content);
 	}
 
 	/**